Release branch of Ruby 2.1

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_2_1@44340 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
naruse 2013-12-22 07:00:55 +00:00
commit e39b6aaac2
1668 changed files with 163123 additions and 86060 deletions

View file

@ -10,12 +10,9 @@
prelude.rb prelude.rb
# the lib/ directory (which has its own .document file) # the lib/ directory (which has its own .document file)
lib lib
# and some of the ext/ directory (which has its own .document file) # and some of the ext/ directory (which has its own .document file)
ext ext
# rdoc files # rdoc files

462
.gdbinit
View file

@ -1,80 +1,34 @@
define rp define hook-run
set $color_type = 0
set $color_highlite = 0
set $color_end = 0
end
define ruby_gdb_init
if !$color_type
set $color_type = "\033[31m"
end
if !$color_highlite
set $color_highlite = "\033[36m"
end
if !$color_end
set $color_end = "\033[m"
end
if ruby_dummy_gdb_enums.special_consts if ruby_dummy_gdb_enums.special_consts
end end
end
# set prompt \033[36m(gdb)\033[m\040
define rp
ruby_gdb_init
if (VALUE)($arg0) & RUBY_FIXNUM_FLAG if (VALUE)($arg0) & RUBY_FIXNUM_FLAG
printf "FIXNUM: %ld\n", (long)($arg0) >> 1 printf "FIXNUM: %ld\n", (long)($arg0) >> 1
else else
if ((VALUE)($arg0) & ~(~(VALUE)0<<RUBY_SPECIAL_SHIFT)) == RUBY_SYMBOL_FLAG if ((VALUE)($arg0) & ~(~(VALUE)0<<RUBY_SPECIAL_SHIFT)) == RUBY_SYMBOL_FLAG
set $id = (($arg0) >> RUBY_SPECIAL_SHIFT) set $id = (($arg0) >> RUBY_SPECIAL_SHIFT)
if $id == '!' || $id == '+' || $id == '-' || $id == '*' || $id == '/' || $id == '%' || $id == '<' || $id == '>' || $id == '`' printf "%sSYMBOL%s: ", $color_type, $color_end
printf "SYMBOL(:%c)\n", $id rp_id $id
else
if $id == idDot2
echo SYMBOL(:..)\n
else
if $id == idDot3
echo SYMBOL(:...)\n
else
if $id == idUPlus
echo SYMBOL(:+@)\n
else
if $id == idUMinus
echo SYMBOL(:-@)\n
else
if $id == idPow
echo SYMBOL(:**)\n
else
if $id == idCmp
echo SYMBOL(:<=>)\n
else
if $id == idLTLT
echo SYMBOL(:<<)\n
else
if $id == idLE
echo SYMBOL(:<=)\n
else
if $id == idGE
echo SYMBOL(:>=)\n
else
if $id == idEq
echo SYMBOL(:==)\n
else
if $id == idEqq
echo SYMBOL(:===)\n
else
if $id == idNeq
echo SYMBOL(:!=)\n
else
if $id == idEqTilde
echo SYMBOL(:=~)\n
else
if $id == idNeqTilde
echo SYMBOL(:!~)\n
else
if $id == idAREF
echo SYMBOL(:[])\n
else
if $id == idASET
echo SYMBOL(:[]=)\n
else
printf "SYMBOL(%ld)\n", $id
end
end
end
end
end
end
end
end
end
end
end
end
end
end
end
end
end
else else
if ($arg0) == RUBY_Qfalse if ($arg0) == RUBY_Qfalse
echo false\n echo false\n
@ -90,80 +44,51 @@ define rp
else else
if (VALUE)($arg0) & RUBY_IMMEDIATE_MASK if (VALUE)($arg0) & RUBY_IMMEDIATE_MASK
if ((VALUE)($arg0) & RUBY_FLONUM_MASK) == RUBY_FLONUM_FLAG if ((VALUE)($arg0) & RUBY_FLONUM_MASK) == RUBY_FLONUM_FLAG
printf "FLONUM: %g\n", (double)rb_float_value($arg0) printf "%sFLONUM%s: %g\n", $color_type, $color_end, (double)rb_float_value($arg0)
else else
echo immediate\n echo immediate\n
end end
else else
set $flags = ((struct RBasic*)($arg0))->flags set $flags = ((struct RBasic*)($arg0))->flags
if ($flags & RUBY_FL_PROMOTED)
printf "[PROMOTED] "
end
if ($flags & RUBY_T_MASK) == RUBY_T_NONE if ($flags & RUBY_T_MASK) == RUBY_T_NONE
printf "T_NONE: " printf "%sT_NONE%s: ", $color_type, $color_end
print (struct RBasic *)($arg0) print (struct RBasic *)($arg0)
else else
if ($flags & RUBY_T_MASK) == RUBY_T_NIL if ($flags & RUBY_T_MASK) == RUBY_T_NIL
printf "T_NIL: " printf "%sT_NIL%s: ", $color_type, $color_end
print (struct RBasic *)($arg0) print (struct RBasic *)($arg0)
else else
if ($flags & RUBY_T_MASK) == RUBY_T_OBJECT if ($flags & RUBY_T_MASK) == RUBY_T_OBJECT
printf "T_OBJECT: " printf "%sT_OBJECT%s: ", $color_type, $color_end
print (struct RObject *)($arg0) print (struct RObject *)($arg0)
else else
if ($flags & RUBY_T_MASK) == RUBY_T_CLASS if ($flags & RUBY_T_MASK) == RUBY_T_CLASS
printf "T_CLASS%s: ", ($flags & RUBY_FL_SINGLETON) ? "*" : "" printf "%sT_CLASS%s%s: ", $color_type, ($flags & RUBY_FL_SINGLETON) ? "*" : "", $color_end
rp_class $arg0 rp_class $arg0
else else
if ($flags & RUBY_T_MASK) == RUBY_T_ICLASS if ($flags & RUBY_T_MASK) == RUBY_T_ICLASS
printf "T_ICLASS: " printf "%sT_ICLASS%s: ", $color_type, $color_end
rp_class $arg0 rp_class $arg0
else else
if ($flags & RUBY_T_MASK) == RUBY_T_MODULE if ($flags & RUBY_T_MASK) == RUBY_T_MODULE
printf "T_MODULE: " printf "%sT_MODULE%s: ", $color_type, $color_end
rp_class $arg0 rp_class $arg0
else else
if ($flags & RUBY_T_MASK) == RUBY_T_FLOAT if ($flags & RUBY_T_MASK) == RUBY_T_FLOAT
printf "T_FLOAT: %.16g ", (((struct RFloat*)($arg0))->float_value) printf "%sT_FLOAT%s: %.16g ", $color_type, $color_end, (((struct RFloat*)($arg0))->float_value)
print (struct RFloat *)($arg0) print (struct RFloat *)($arg0)
else else
if ($flags & RUBY_T_MASK) == RUBY_T_STRING if ($flags & RUBY_T_MASK) == RUBY_T_STRING
printf "T_STRING: " printf "%sT_STRING%s: ", $color_type, $color_end
set print address off rp_string $arg0 $flags
output (char *)(($flags & RUBY_FL_USER1) ? \
((struct RString*)($arg0))->as.heap.ptr : \
((struct RString*)($arg0))->as.ary)
set print address on
printf " bytesize:%ld ", ($flags & RUBY_FL_USER1) ? \
((struct RString*)($arg0))->as.heap.len : \
(($flags & (RUBY_FL_USER2|RUBY_FL_USER3|RUBY_FL_USER4|RUBY_FL_USER5|RUBY_FL_USER6)) >> RUBY_FL_USHIFT+2)
if !($flags & RUBY_FL_USER1)
printf "(embed) "
else
if ($flags & RUBY_FL_USER2)
printf "(shared) "
end
if ($flags & RUBY_FL_USER3)
printf "(assoc) "
end
end
printf "encoding:%d ", ($flags & RUBY_ENCODING_MASK) >> RUBY_ENCODING_SHIFT
if ($flags & RUBY_ENC_CODERANGE_MASK) == 0
printf "coderange:unknown "
else
if ($flags & RUBY_ENC_CODERANGE_MASK) == RUBY_ENC_CODERANGE_7BIT
printf "coderange:7bit "
else
if ($flags & RUBY_ENC_CODERANGE_MASK) == RUBY_ENC_CODERANGE_VALID
printf "coderange:valid "
else
printf "coderange:broken "
end
end
end
print (struct RString *)($arg0)
else else
if ($flags & RUBY_T_MASK) == RUBY_T_REGEXP if ($flags & RUBY_T_MASK) == RUBY_T_REGEXP
set $regsrc = ((struct RRegexp*)($arg0))->src set $regsrc = ((struct RRegexp*)($arg0))->src
set $rsflags = ((struct RBasic*)$regsrc)->flags set $rsflags = ((struct RBasic*)$regsrc)->flags
printf "T_REGEXP: " printf "%sT_REGEXP%s: ", $color_type, $color_end
set print address off set print address off
output (char *)(($rsflags & RUBY_FL_USER1) ? \ output (char *)(($rsflags & RUBY_FL_USER1) ? \
((struct RString*)$regsrc)->as.heap.ptr : \ ((struct RString*)$regsrc)->as.heap.ptr : \
@ -187,7 +112,7 @@ define rp
if ($flags & RUBY_T_MASK) == RUBY_T_ARRAY if ($flags & RUBY_T_MASK) == RUBY_T_ARRAY
if ($flags & RUBY_FL_USER1) if ($flags & RUBY_FL_USER1)
set $len = (($flags & (RUBY_FL_USER3|RUBY_FL_USER4)) >> (RUBY_FL_USHIFT+3)) set $len = (($flags & (RUBY_FL_USER3|RUBY_FL_USER4)) >> (RUBY_FL_USHIFT+3))
printf "T_ARRAY: len=%ld ", $len printf "%sT_ARRAY%s: len=%ld ", $color_type, $color_end, $len
printf "(embed) " printf "(embed) "
if ($len == 0) if ($len == 0)
printf "{(empty)} " printf "{(empty)} "
@ -197,7 +122,7 @@ define rp
end end
else else
set $len = ((struct RArray*)($arg0))->as.heap.len set $len = ((struct RArray*)($arg0))->as.heap.len
printf "T_ARRAY: len=%ld ", $len printf "%sT_ARRAY%s: len=%ld ", $color_type, $color_end, $len
if ($flags & RUBY_FL_USER2) if ($flags & RUBY_FL_USER2)
printf "(shared) shared=" printf "(shared) shared="
output/x ((struct RArray*)($arg0))->as.heap.aux.shared output/x ((struct RArray*)($arg0))->as.heap.aux.shared
@ -215,18 +140,18 @@ define rp
print (struct RArray *)($arg0) print (struct RArray *)($arg0)
else else
if ($flags & RUBY_T_MASK) == RUBY_T_FIXNUM if ($flags & RUBY_T_MASK) == RUBY_T_FIXNUM
printf "T_FIXNUM: " printf "%sT_FIXNUM%s: ", $color_type, $color_end
print (struct RBasic *)($arg0) print (struct RBasic *)($arg0)
else else
if ($flags & RUBY_T_MASK) == RUBY_T_HASH if ($flags & RUBY_T_MASK) == RUBY_T_HASH
printf "T_HASH: ", printf "%sT_HASH%s: ", $color_type, $color_end,
if ((struct RHash *)($arg0))->ntbl if ((struct RHash *)($arg0))->ntbl
printf "len=%ld ", ((struct RHash *)($arg0))->ntbl->num_entries printf "len=%ld ", ((struct RHash *)($arg0))->ntbl->num_entries
end end
print (struct RHash *)($arg0) print (struct RHash *)($arg0)
else else
if ($flags & RUBY_T_MASK) == RUBY_T_STRUCT if ($flags & RUBY_T_MASK) == RUBY_T_STRUCT
printf "T_STRUCT: len=%ld ", \ printf "%sT_STRUCT%s: len=%ld ", $color_type, $color_end, \
(($flags & (RUBY_FL_USER1|RUBY_FL_USER2)) ? \ (($flags & (RUBY_FL_USER1|RUBY_FL_USER2)) ? \
($flags & (RUBY_FL_USER1|RUBY_FL_USER2)) >> (RUBY_FL_USHIFT+1) : \ ($flags & (RUBY_FL_USER1|RUBY_FL_USER2)) >> (RUBY_FL_USHIFT+1) : \
((struct RStruct *)($arg0))->as.heap.len) ((struct RStruct *)($arg0))->as.heap.len)
@ -236,7 +161,7 @@ define rp
((struct RStruct *)($arg0))->as.heap.ptr) ((struct RStruct *)($arg0))->as.heap.ptr)
else else
if ($flags & RUBY_T_MASK) == RUBY_T_BIGNUM if ($flags & RUBY_T_MASK) == RUBY_T_BIGNUM
printf "T_BIGNUM: sign=%d len=%ld ", \ printf "%sT_BIGNUM%s: sign=%d len=%ld ", $color_type, $color_end, \
(($flags & RUBY_FL_USER1) != 0), \ (($flags & RUBY_FL_USER1) != 0), \
(($flags & RUBY_FL_USER2) ? \ (($flags & RUBY_FL_USER2) ? \
($flags & (RUBY_FL_USER5|RUBY_FL_USER4|RUBY_FL_USER3)) >> (RUBY_FL_USHIFT+3) : \ ($flags & (RUBY_FL_USER5|RUBY_FL_USER4|RUBY_FL_USER3)) >> (RUBY_FL_USHIFT+3) : \
@ -250,59 +175,59 @@ define rp
((struct RBignum*)($arg0))->as.heap.digits) ((struct RBignum*)($arg0))->as.heap.digits)
else else
if ($flags & RUBY_T_MASK) == RUBY_T_RATIONAL if ($flags & RUBY_T_MASK) == RUBY_T_RATIONAL
printf "T_RATIONAL: " printf "%sT_RATIONAL%s: ", $color_type, $color_end
print (struct RRational *)($arg0) print (struct RRational *)($arg0)
else else
if ($flags & RUBY_T_MASK) == RUBY_T_COMPLEX if ($flags & RUBY_T_MASK) == RUBY_T_COMPLEX
printf "T_COMPLEX: " printf "%sT_COMPLEX%s: ", $color_type, $color_end
print (struct RComplex *)($arg0) print (struct RComplex *)($arg0)
else else
if ($flags & RUBY_T_MASK) == RUBY_T_FILE if ($flags & RUBY_T_MASK) == RUBY_T_FILE
printf "T_FILE: " printf "%sT_FILE%s: ", $color_type, $color_end
print (struct RFile *)($arg0) print (struct RFile *)($arg0)
output *((struct RFile *)($arg0))->fptr output *((struct RFile *)($arg0))->fptr
printf "\n" printf "\n"
else else
if ($flags & RUBY_T_MASK) == RUBY_T_TRUE if ($flags & RUBY_T_MASK) == RUBY_T_TRUE
printf "T_TRUE: " printf "%sT_TRUE%s: ", $color_type, $color_end
print (struct RBasic *)($arg0) print (struct RBasic *)($arg0)
else else
if ($flags & RUBY_T_MASK) == RUBY_T_FALSE if ($flags & RUBY_T_MASK) == RUBY_T_FALSE
printf "T_FALSE: " printf "%sT_FALSE%s: ", $color_type, $color_end
print (struct RBasic *)($arg0) print (struct RBasic *)($arg0)
else else
if ($flags & RUBY_T_MASK) == RUBY_T_DATA if ($flags & RUBY_T_MASK) == RUBY_T_DATA
if ((struct RTypedData *)($arg0))->typed_flag == 1 if ((struct RTypedData *)($arg0))->typed_flag == 1
printf "T_DATA(%s): ", ((struct RTypedData *)($arg0))->type->wrap_struct_name printf "%sT_DATA%s(%s): ", $color_type, $color_end, ((struct RTypedData *)($arg0))->type->wrap_struct_name
print (struct RTypedData *)($arg0) print (struct RTypedData *)($arg0)
else else
printf "T_DATA: " printf "%sT_DATA%s: ", $color_type, $color_end
print (struct RData *)($arg0) print (struct RData *)($arg0)
end end
else else
if ($flags & RUBY_T_MASK) == RUBY_T_MATCH if ($flags & RUBY_T_MASK) == RUBY_T_MATCH
printf "T_MATCH: " printf "%sT_MATCH%s: ", $color_type, $color_end
print (struct RMatch *)($arg0) print (struct RMatch *)($arg0)
else else
if ($flags & RUBY_T_MASK) == RUBY_T_SYMBOL if ($flags & RUBY_T_MASK) == RUBY_T_SYMBOL
printf "T_SYMBOL: " printf "%sT_SYMBOL%s: ", $color_type, $color_end
print (struct RBasic *)($arg0) print (struct RBasic *)($arg0)
else else
if ($flags & RUBY_T_MASK) == RUBY_T_UNDEF if ($flags & RUBY_T_MASK) == RUBY_T_UNDEF
printf "T_UNDEF: " printf "%sT_UNDEF%s: ", $color_type, $color_end
print (struct RBasic *)($arg0) print (struct RBasic *)($arg0)
else else
if ($flags & RUBY_T_MASK) == RUBY_T_NODE if ($flags & RUBY_T_MASK) == RUBY_T_NODE
printf "T_NODE(" printf "%sT_NODE%s(", $color_type, $color_end
output (enum node_type)(($flags&RUBY_NODE_TYPEMASK)>>RUBY_NODE_TYPESHIFT) output (enum node_type)(($flags&RUBY_NODE_TYPEMASK)>>RUBY_NODE_TYPESHIFT)
printf "): " printf "): "
print *(NODE *)($arg0) print *(NODE *)($arg0)
else else
if ($flags & RUBY_T_MASK) == RUBY_T_ZOMBIE if ($flags & RUBY_T_MASK) == RUBY_T_ZOMBIE
printf "T_ZOMBIE: " printf "%sT_ZOMBIE%s: ", $color_type, $color_end
print (struct RData *)($arg0) print (struct RData *)($arg0)
else else
printf "unknown: " printf "%sunknown%s: ", $color_type, $color_end
print (struct RBasic *)($arg0) print (struct RBasic *)($arg0)
end end
end end
@ -341,12 +266,165 @@ document rp
Print a Ruby's VALUE. Print a Ruby's VALUE.
end end
define rp_id
set $id = (ID)$arg0
if $id == '!' || $id == '+' || $id == '-' || $id == '*' || $id == '/' || $id == '%' || $id == '<' || $id == '>' || $id == '`'
printf "(:%c)\n", $id
else
if $id == idDot2
printf "(:..)\n"
else
if $id == idDot3
printf "(:...)\n"
else
if $id == idUPlus
printf "(:+@)\n"
else
if $id == idUMinus
printf "(:-@)\n"
else
if $id == idPow
printf "(:**)\n"
else
if $id == idCmp
printf "(:<=>)\n"
else
if $id == idLTLT
printf "(:<<)\n"
else
if $id == idLE
printf "(:<=)\n"
else
if $id == idGE
printf "(:>=)\n"
else
if $id == idEq
printf "(:==)\n"
else
if $id == idEqq
printf "(:===)\n"
else
if $id == idNeq
printf "(:!=)\n"
else
if $id == idEqTilde
printf "(:=~)\n"
else
if $id == idNeqTilde
printf "(:!~)\n"
else
if $id == idAREF
printf "(:[])\n"
else
if $id == idASET
printf "(:[]=)\n"
else
if $id <= tLAST_OP_ID
printf "O"
else
set $id_type = $id & RUBY_ID_SCOPE_MASK
if $id_type == RUBY_ID_LOCAL
printf "l"
else
if $id_type == RUBY_ID_INSTANCE
printf "i"
else
if $id_type == RUBY_ID_GLOBAL
printf "G"
else
if $id_type == RUBY_ID_ATTRSET
printf "a"
else
if $id_type == RUBY_ID_CONST
printf "C"
else
if $id_type == RUBY_ID_CLASS
printf "c"
else
printf "j"
end
end
end
end
end
end
end
printf "(%ld): ", $id
rb_numtable_entry global_symbols.id_str $id
if $rb_numtable_rec
rp_string $rb_numtable_rec
else
echo undef\n
end
end
end
end
end
end
end
end
end
end
end
end
end
end
end
end
end
end
end
document rp_id
Print an ID.
end
define rp_string
set $flags = ((struct RBasic*)($arg0))->flags
set print address off
output (char *)(($flags & RUBY_FL_USER1) ? \
((struct RString*)($arg0))->as.heap.ptr : \
((struct RString*)($arg0))->as.ary)
set print address on
printf " bytesize:%ld ", ($flags & RUBY_FL_USER1) ? \
((struct RString*)($arg0))->as.heap.len : \
(($flags & (RUBY_FL_USER2|RUBY_FL_USER3|RUBY_FL_USER4|RUBY_FL_USER5|RUBY_FL_USER6)) >> RUBY_FL_USHIFT+2)
if !($flags & RUBY_FL_USER1)
printf "(embed) "
else
if ($flags & RUBY_FL_USER2)
printf "(shared) "
end
if ($flags & RUBY_FL_USER3)
printf "(assoc) "
end
end
printf "encoding:%d ", ($flags & RUBY_ENCODING_MASK) >> RUBY_ENCODING_SHIFT
if ($flags & RUBY_ENC_CODERANGE_MASK) == 0
printf "coderange:unknown "
else
if ($flags & RUBY_ENC_CODERANGE_MASK) == RUBY_ENC_CODERANGE_7BIT
printf "coderange:7bit "
else
if ($flags & RUBY_ENC_CODERANGE_MASK) == RUBY_ENC_CODERANGE_VALID
printf "coderange:valid "
else
printf "coderange:broken "
end
end
end
print (struct RString *)($arg0)
end
document rp_string
Print the content of a String.
end
define rp_class define rp_class
printf "(struct RClass *) %p", (void*)$arg0 printf "(struct RClass *) %p", (void*)$arg0
if ((struct RClass *)($arg0))->ptr.origin != $arg0 if ((struct RClass *)($arg0))->ptr.origin != $arg0
printf " -> %p", ((struct RClass *)($arg0))->ptr.origin printf " -> %p", ((struct RClass *)($arg0))->ptr.origin
end end
printf "\n" printf "\n"
rb_classname $arg0
print *(struct RClass *)($arg0) print *(struct RClass *)($arg0)
print *((struct RClass *)($arg0))->ptr print *((struct RClass *)($arg0))->ptr
end end
@ -378,257 +456,257 @@ end
# Print members of ruby node. # Print members of ruby node.
define nd_head define nd_head
printf "u1.node: " printf "%su1.node%s: ", $color_highlite, $color_end
rp ($arg0).u1.node rp ($arg0).u1.node
end end
define nd_alen define nd_alen
printf "u2.argc: " printf "%su2.argc%s: ", $color_highlite, $color_end
p ($arg0).u2.argc p ($arg0).u2.argc
end end
define nd_next define nd_next
printf "u3.node: " printf "%su3.node%s: ", $color_highlite, $color_end
rp ($arg0).u3.node rp ($arg0).u3.node
end end
define nd_cond define nd_cond
printf "u1.node: " printf "%su1.node%s: ", $color_highlite, $color_end
rp ($arg0).u1.node rp ($arg0).u1.node
end end
define nd_body define nd_body
printf "u2.node: " printf "%su2.node%s: ", $color_highlite, $color_end
rp ($arg0).u2.node rp ($arg0).u2.node
end end
define nd_else define nd_else
printf "u3.node: " printf "%su3.node%s: ", $color_highlite, $color_end
rp ($arg0).u3.node rp ($arg0).u3.node
end end
define nd_orig define nd_orig
printf "u3.value: " printf "%su3.value%s: ", $color_highlite, $color_end
rp ($arg0).u3.value rp ($arg0).u3.value
end end
define nd_resq define nd_resq
printf "u2.node: " printf "%su2.node%s: ", $color_highlite, $color_end
rp ($arg0).u2.node rp ($arg0).u2.node
end end
define nd_ensr define nd_ensr
printf "u3.node: " printf "%su3.node%s: ", $color_highlite, $color_end
rp ($arg0).u3.node rp ($arg0).u3.node
end end
define nd_1st define nd_1st
printf "u1.node: " printf "%su1.node%s: ", $color_highlite, $color_end
rp ($arg0).u1.node rp ($arg0).u1.node
end end
define nd_2nd define nd_2nd
printf "u2.node: " printf "%su2.node%s: ", $color_highlite, $color_end
rp ($arg0).u2.node rp ($arg0).u2.node
end end
define nd_stts define nd_stts
printf "u1.node: " printf "%su1.node%s: ", $color_highlite, $color_end
rp ($arg0).u1.node rp ($arg0).u1.node
end end
define nd_entry define nd_entry
printf "u3.entry: " printf "%su3.entry%s: ", $color_highlite, $color_end
p ($arg0).u3.entry p ($arg0).u3.entry
end end
define nd_vid define nd_vid
printf "u1.id: " printf "%su1.id%s: ", $color_highlite, $color_end
p ($arg0).u1.id p ($arg0).u1.id
end end
define nd_cflag define nd_cflag
printf "u2.id: " printf "%su2.id%s: ", $color_highlite, $color_end
p ($arg0).u2.id p ($arg0).u2.id
end end
define nd_cval define nd_cval
printf "u3.value: " printf "%su3.value%s: ", $color_highlite, $color_end
rp ($arg0).u3.value rp ($arg0).u3.value
end end
define nd_cnt define nd_cnt
printf "u3.cnt: " printf "%su3.cnt%s: ", $color_highlite, $color_end
p ($arg0).u3.cnt p ($arg0).u3.cnt
end end
define nd_tbl define nd_tbl
printf "u1.tbl: " printf "%su1.tbl%s: ", $color_highlite, $color_end
p ($arg0).u1.tbl p ($arg0).u1.tbl
end end
define nd_var define nd_var
printf "u1.node: " printf "%su1.node%s: ", $color_highlite, $color_end
rp ($arg0).u1.node rp ($arg0).u1.node
end end
define nd_ibdy define nd_ibdy
printf "u2.node: " printf "%su2.node%s: ", $color_highlite, $color_end
rp ($arg0).u2.node rp ($arg0).u2.node
end end
define nd_iter define nd_iter
printf "u3.node: " printf "%su3.node%s: ", $color_highlite, $color_end
rp ($arg0).u3.node rp ($arg0).u3.node
end end
define nd_value define nd_value
printf "u2.node: " printf "%su2.node%s: ", $color_highlite, $color_end
rp ($arg0).u2.node rp ($arg0).u2.node
end end
define nd_aid define nd_aid
printf "u3.id: " printf "%su3.id%s: ", $color_highlite, $color_end
p ($arg0).u3.id p ($arg0).u3.id
end end
define nd_lit define nd_lit
printf "u1.value: " printf "%su1.value%s: ", $color_highlite, $color_end
rp ($arg0).u1.value rp ($arg0).u1.value
end end
define nd_frml define nd_frml
printf "u1.node: " printf "%su1.node%s: ", $color_highlite, $color_end
rp ($arg0).u1.node rp ($arg0).u1.node
end end
define nd_rest define nd_rest
printf "u2.argc: " printf "%su2.argc%s: ", $color_highlite, $color_end
p ($arg0).u2.argc p ($arg0).u2.argc
end end
define nd_opt define nd_opt
printf "u1.node: " printf "%su1.node%s: ", $color_highlite, $color_end
rp ($arg0).u1.node rp ($arg0).u1.node
end end
define nd_recv define nd_recv
printf "u1.node: " printf "%su1.node%s: ", $color_highlite, $color_end
rp ($arg0).u1.node rp ($arg0).u1.node
end end
define nd_mid define nd_mid
printf "u2.id: " printf "%su2.id%s: ", $color_highlite, $color_end
p ($arg0).u2.id p ($arg0).u2.id
end end
define nd_args define nd_args
printf "u3.node: " printf "%su3.node%s: ", $color_highlite, $color_end
rp ($arg0).u3.node rp ($arg0).u3.node
end end
define nd_noex define nd_noex
printf "u1.id: " printf "%su1.id%s: ", $color_highlite, $color_end
p ($arg0).u1.id p ($arg0).u1.id
end end
define nd_defn define nd_defn
printf "u3.node: " printf "%su3.node%s: ", $color_highlite, $color_end
rp ($arg0).u3.node rp ($arg0).u3.node
end end
define nd_old define nd_old
printf "u1.id: " printf "%su1.id%s: ", $color_highlite, $color_end
p ($arg0).u1.id p ($arg0).u1.id
end end
define nd_new define nd_new
printf "u2.id: " printf "%su2.id%s: ", $color_highlite, $color_end
p ($arg0).u2.id p ($arg0).u2.id
end end
define nd_cfnc define nd_cfnc
printf "u1.cfunc: " printf "%su1.cfunc%s: ", $color_highlite, $color_end
p ($arg0).u1.cfunc p ($arg0).u1.cfunc
end end
define nd_argc define nd_argc
printf "u2.argc: " printf "%su2.argc%s: ", $color_highlite, $color_end
p ($arg0).u2.argc p ($arg0).u2.argc
end end
define nd_cname define nd_cname
printf "u1.id: " printf "%su1.id%s: ", $color_highlite, $color_end
p ($arg0).u1.id p ($arg0).u1.id
end end
define nd_super define nd_super
printf "u3.node: " printf "%su3.node%s: ", $color_highlite, $color_end
rp ($arg0).u3.node rp ($arg0).u3.node
end end
define nd_modl define nd_modl
printf "u1.id: " printf "%su1.id%s: ", $color_highlite, $color_end
p ($arg0).u1.id p ($arg0).u1.id
end end
define nd_clss define nd_clss
printf "u1.value: " printf "%su1.value%s: ", $color_highlite, $color_end
rp ($arg0).u1.value rp ($arg0).u1.value
end end
define nd_beg define nd_beg
printf "u1.node: " printf "%su1.node%s: ", $color_highlite, $color_end
rp ($arg0).u1.node rp ($arg0).u1.node
end end
define nd_end define nd_end
printf "u2.node: " printf "%su2.node%s: ", $color_highlite, $color_end
rp ($arg0).u2.node rp ($arg0).u2.node
end end
define nd_state define nd_state
printf "u3.state: " printf "%su3.state%s: ", $color_highlite, $color_end
p ($arg0).u3.state p ($arg0).u3.state
end end
define nd_rval define nd_rval
printf "u2.value: " printf "%su2.value%s: ", $color_highlite, $color_end
rp ($arg0).u2.value rp ($arg0).u2.value
end end
define nd_nth define nd_nth
printf "u2.argc: " printf "%su2.argc%s: ", $color_highlite, $color_end
p ($arg0).u2.argc p ($arg0).u2.argc
end end
define nd_tag define nd_tag
printf "u1.id: " printf "%su1.id%s: ", $color_highlite, $color_end
p ($arg0).u1.id p ($arg0).u1.id
end end
define nd_tval define nd_tval
printf "u2.value: " printf "%su2.value%s: ", $color_highlite, $color_end
rp ($arg0).u2.value rp ($arg0).u2.value
end end
@ -667,12 +745,9 @@ define rb_numtable_entry
end end
define rb_id2name define rb_id2name
rb_numtable_entry global_symbols.id_str (ID)$arg0 ruby_gdb_init
if $rb_numtable_rec printf "%sID%s: ", $color_type, $color_end
rp $rb_numtable_rec rp_id $arg0
else
echo undef\n
end
end end
document rb_id2name document rb_id2name
Print the name of id Print the name of id
@ -683,7 +758,7 @@ define rb_method_entry
set $rb_method_entry_id = (ID)$arg1 set $rb_method_entry_id = (ID)$arg1
set $rb_method_entry_me = (rb_method_entry_t *)0 set $rb_method_entry_me = (rb_method_entry_t *)0
while !$rb_method_entry_me && $rb_method_entry_klass while !$rb_method_entry_me && $rb_method_entry_klass
rb_numtable_entry $rb_method_entry_klass->m_tbl $rb_method_entry_id rb_numtable_entry $rb_method_entry_klass->m_tbl_wrapper->tbl $rb_method_entry_id
set $rb_method_entry_me = (rb_method_entry_t *)$rb_numtable_rec set $rb_method_entry_me = (rb_method_entry_t *)$rb_numtable_rec
if !$rb_method_entry_me if !$rb_method_entry_me
set $rb_method_entry_klass = (struct RClass *)$rb_method_entry_klass->ptr->super set $rb_method_entry_klass = (struct RClass *)$rb_method_entry_klass->ptr->super
@ -701,15 +776,20 @@ document rb_method_entry
end end
define rb_classname define rb_classname
call classname($arg0) # up to 128bit int
rb_p $ set $rb_classname_permanent = "0123456789ABCDEF"
print *(struct RClass*)($arg0) set $rb_classname = classname($arg0, $rb_classname_permanent)
if $rb_classname != RUBY_Qnil
rp $rb_classname
else
echo anonymous class/module\n
end
end end
define rb_ancestors define rb_ancestors
set $rb_ancestors_module = $arg0 set $rb_ancestors_module = $arg0
while $rb_ancestors_module while $rb_ancestors_module
rp $rb_ancestors_module rp_class $rb_ancestors_module
set $rb_ancestors_module = ((struct RClass *)($rb_ancestors_module))->ptr.super set $rb_ancestors_module = ((struct RClass *)($rb_ancestors_module))->ptr.super
end end
end end
@ -722,7 +802,7 @@ define rb_backtrace
end end
define iseq define iseq
if dummy_gdb_enums.special_consts if ruby_dummy_gdb_enums.special_consts
end end
if ($arg0)->type == ISEQ_ELEMENT_NONE if ($arg0)->type == ISEQ_ELEMENT_NONE
echo [none]\n echo [none]\n

10
.gitignore vendored
View file

@ -23,6 +23,7 @@
.ppack .ppack
.svn .svn
Makefile Makefile
Makefile.old
extconf.h extconf.h
y.output y.output
y.tab.c y.tab.c
@ -36,6 +37,7 @@ y.tab.c
/ChangeLog.pre1_1 /ChangeLog.pre1_1
/Doxyfile /Doxyfile
/GNUmakefile /GNUmakefile
/GNUmakefile.old
/README.atheos /README.atheos
/README.fat-patch /README.fat-patch
/README.v6 /README.v6
@ -82,6 +84,7 @@ y.tab.c
/rubicon /rubicon
/ruby /ruby
/ruby-man.rd.gz /ruby-man.rd.gz
/sizes.c
/test.rb /test.rb
/tmp /tmp
/transdb.h /transdb.h
@ -103,6 +106,9 @@ y.tab.c
/ext/dl/callback/callback-*.c /ext/dl/callback/callback-*.c
/ext/dl/callback/callback.c /ext/dl/callback/callback.c
# /ext/rbconfig/
/ext/rbconfig/sizeof/sizes.c
# /ext/ripper/ # /ext/ripper/
/ext/ripper/eventids1.c /ext/ripper/eventids1.c
/ext/ripper/eventids2table.c /ext/ripper/eventids2table.c
@ -122,6 +128,10 @@ y.tab.c
/spec/mspec /spec/mspec
/spec/rubyspec /spec/rubyspec
# /tool/
/tool/config.guess
/tool/config.sub
# /win32/ # /win32/
/win32/*.ico /win32/*.ico
/win32/.time /win32/.time

View file

@ -38,11 +38,19 @@ install: "sudo apt-get -qq build-dep ruby1.9.1 2>/dev/null"
# like test-all, test-rubyspec. This is because they take too much time, # like test-all, test-rubyspec. This is because they take too much time,
# enough for Travis to shut down the VM as being stalled. # enough for Travis to shut down the VM as being stalled.
before_script: before_script:
- "make -f common.mk BASERUBY=ruby srcdir=. update-config_files"
- "autoconf" - "autoconf"
- "./configure --with-gcc=$CC" - "mkdir config_1st config_2nd"
- "./configure -C --with-gcc=$CC"
- "cp -pr config.status .ext/include config_1st"
- "make reconfig"
- "cp -pr config.status .ext/include config_2nd"
- "diff -ru config_1st config_2nd"
- "make -sj encs" - "make -sj encs"
- "make -sj exts" - "make -sj exts"
script: "make test OPTS=-v" script:
- "make test OPTS=-v"
# - "make test-all TESTS='-v'"
# Branch matrix. Not all branches are Travis-ready so we limit branches here. # Branch matrix. Not all branches are Travis-ready so we limit branches here.
branches: branches:
@ -61,6 +69,13 @@ notifications:
template: template:
- "%{message} by @%{author}: See %{build_url}" - "%{message} by @%{author}: See %{build_url}"
# Update ruby-head installed on Travis CI so other projects can test against it.
webhooks:
urls:
- "https://rubies.travis-ci.org/rebuild/ruby-head"
on_success: always
on_failure: never
# Local Variables: # Local Variables:
# mode: YAML # mode: YAML
# coding: utf-8-unix # coding: utf-8-unix

2
BSDL
View file

@ -1,4 +1,4 @@
Copyright (C) 1993-2010 Yukihiro Matsumoto. All rights reserved. Copyright (C) 1993-2013 Yukihiro Matsumoto. All rights reserved.
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions modification, are permitted provided that the following conditions

39484
ChangeLog

File diff suppressed because it is too large Load diff

View file

@ -40,6 +40,7 @@ datadir = @datadir@
arch = @arch@ arch = @arch@
sitearch = @sitearch@ sitearch = @sitearch@
sitedir = @sitedir@ sitedir = @sitedir@
archlibdir = @archlibdir@
ruby_version = @ruby_version@ ruby_version = @ruby_version@
TESTUI = console TESTUI = console
@ -52,6 +53,7 @@ arch_hdrdir = $(EXTOUT)/include/$(arch)
VPATH = $(arch_hdrdir)/ruby:$(hdrdir)/ruby:$(srcdir):$(srcdir)/enc:$(srcdir)/missing VPATH = $(arch_hdrdir)/ruby:$(hdrdir)/ruby:$(srcdir):$(srcdir)/enc:$(srcdir)/missing
empty = empty =
CC_VERSION = @CC_VERSION@
OUTFLAG = @OUTFLAG@$(empty) OUTFLAG = @OUTFLAG@$(empty)
COUTFLAG = @COUTFLAG@$(empty) COUTFLAG = @COUTFLAG@$(empty)
ARCH_FLAG = @ARCH_FLAG@ ARCH_FLAG = @ARCH_FLAG@
@ -60,6 +62,7 @@ cflags = @cflags@
optflags = @optflags@ optflags = @optflags@
debugflags = @debugflags@ debugflags = @debugflags@
warnflags = @warnflags@ @strict_warnflags@ warnflags = @warnflags@ @strict_warnflags@
cppflags = @cppflags@
INCFLAGS = -I. -I$(arch_hdrdir) -I$(hdrdir) -I$(srcdir) INCFLAGS = -I. -I$(arch_hdrdir) -I$(hdrdir) -I$(srcdir)
XCFLAGS = @XCFLAGS@ XCFLAGS = @XCFLAGS@
CPPFLAGS = @CPPFLAGS@ $(INCFLAGS) CPPFLAGS = @CPPFLAGS@ $(INCFLAGS)
@ -93,8 +96,11 @@ PROGRAM=$(RUBY_INSTALL_NAME)$(EXEEXT)
RUBY = $(RUBY_INSTALL_NAME) RUBY = $(RUBY_INSTALL_NAME)
MINIRUBY = @MINIRUBY@\ MINIRUBY = @MINIRUBY@\
$(MINIRUBYOPT) $(MINIRUBYOPT)
RUNRUBY_COMMAND = @RUNRUBY@ $(RUNRUBYOPT) # RUNRUBY_COMMAND:: runruby.rb or baseruby. do not append options directly
RUNRUBY = $(RUNRUBY_COMMAND) -- $(RUN_OPTS) RUNRUBY_COMMAND = @RUNRUBY_COMMAND@
# RUNRUBY:: run ruby with RUN_OPTS which is passed to ruby
RUNRUBY = @RUNRUBY@ $(RUN_OPTS)
# RUNRUBY_DEBUGGER:: debugging option for runruby.rb
RUNRUBY_DEBUGGER = --debugger='gdb -x run.gdb --quiet --args' RUNRUBY_DEBUGGER = --debugger='gdb -x run.gdb --quiet --args'
XRUBY = @XRUBY@ XRUBY = @XRUBY@
BTESTRUBY = @BTESTRUBY@\ BTESTRUBY = @BTESTRUBY@\
@ -107,7 +113,7 @@ XRUBY_LIBDIR = @XRUBY_LIBDIR@
XRUBY_RUBYLIBDIR = @XRUBY_RUBYLIBDIR@ XRUBY_RUBYLIBDIR = @XRUBY_RUBYLIBDIR@
XRUBY_RUBYHDRDIR = @XRUBY_RUBYHDRDIR@ XRUBY_RUBYHDRDIR = @XRUBY_RUBYHDRDIR@
DEFAULT_PRELUDES = $(@USE_RUBYGEMS@_GEM_PRELUDE) DEFAULT_PRELUDES = $(GEM_PRELUDE)
#### End of system configuration section. #### #### End of system configuration section. ####
@ -178,6 +184,8 @@ OS_DEST_FILE = $@
MESSAGE_BEGIN = @for line in MESSAGE_BEGIN = @for line in
MESSAGE_END = ; do echo "$$line"; done MESSAGE_END = ; do echo "$$line"; done
ECHO_BEGIN = @sep=''; for word in
ECHO_END = ; do echo @ECHO_N@ "$$sep'$$word'@ECHO_C@"; sep=' '; done; echo
configure_args = @configure_args@ configure_args = @configure_args@
#### End of variables #### End of variables
@ -194,12 +202,12 @@ all:
miniruby$(EXEEXT): miniruby$(EXEEXT):
@-if test -f $@; then $(MV) -f $@ $@.old; $(RM) $@.old; fi @-if test -f $@; then $(MV) -f $@ $@.old; $(RM) $@.old; fi
$(ECHO) linking $@ $(ECHO) linking $@
$(Q) $(PURIFY) $(CC) $(LDFLAGS) $(XLDFLAGS) $(MAINLIBS) $(NORMALMAINOBJ) $(MINIOBJS) $(COMMONOBJS) $(DMYEXT) $(DTRACE_OBJ) $(LIBS) $(OUTFLAG)$@ $(Q) $(PURIFY) $(CC) $(LDFLAGS) $(XLDFLAGS) $(NORMALMAINOBJ) $(MINIOBJS) $(COMMONOBJS) $(DMYEXT) $(DTRACE_OBJ) $(MAINLIBS) $(LIBS) $(OUTFLAG)$@
$(PROGRAM): $(PROGRAM):
@$(RM) $@ @$(RM) $@
$(ECHO) linking $@ $(ECHO) linking $@
$(Q) $(PURIFY) $(CC) $(LDFLAGS) $(XLDFLAGS) $(MAINLIBS) $(MAINOBJ) $(EXTOBJS) $(LIBRUBYARG) $(LIBS) $(EXTLIBS) $(OUTFLAG)$@ $(Q) $(PURIFY) $(CC) $(LDFLAGS) $(XLDFLAGS) $(MAINOBJ) $(EXTOBJS) $(LIBRUBYARG) $(MAINLIBS) $(LIBS) $(EXTLIBS) $(OUTFLAG)$@
$(Q) $(POSTLINK) $(Q) $(POSTLINK)
# We must `rm' the library each time this rule is invoked because "updating" a # We must `rm' the library each time this rule is invoked because "updating" a
@ -211,7 +219,7 @@ $(LIBRUBY_A):
$(Q) $(AR) $(ARFLAGS) $@ $(LIBRUBY_A_OBJS) $(DMYEXT) $(Q) $(AR) $(ARFLAGS) $@ $(LIBRUBY_A_OBJS) $(DMYEXT)
@-$(RANLIB) $@ 2> /dev/null || true @-$(RANLIB) $@ 2> /dev/null || true
$(ECHO) verifying static-library $@ $(ECHO) verifying static-library $@
@$(PURIFY) $(CC) $(XLDFLAGS) $(MAINOBJ) $(LIBRUBY_A) $(MAINLIBS) $(EXTLIBS) $(LIBS) $(OUTFLAG)conftest$(EXEEXT) $(LDFLAGS) @$(PURIFY) $(CC) $(LDFLAGS) $(XLDFLAGS) $(MAINOBJ) $(LIBRUBY_A) $(MAINLIBS) $(EXTLIBS) $(LIBS) $(OUTFLAG)conftest$(EXEEXT)
@$(RM) conftest$(EXEEXT) conftest.c @$(RM) conftest$(EXEEXT) conftest.c
$(LIBRUBY_SO): $(LIBRUBY_SO):
@ -220,7 +228,7 @@ $(LIBRUBY_SO):
$(Q) $(LDSHARED) $(DLDFLAGS) $(OBJS) $(DLDOBJS) $(DTRACE_OBJ) $(SOLIBS) $(EXTSOLIBS) $(OUTFLAG)$@ $(Q) $(LDSHARED) $(DLDFLAGS) $(OBJS) $(DLDOBJS) $(DTRACE_OBJ) $(SOLIBS) $(EXTSOLIBS) $(OUTFLAG)$@
-$(Q) $(OBJCOPY) -w -L '$(SYMBOL_PREFIX)Init_*' -L '$(SYMBOL_PREFIX)*_threadptr_*' $@ -$(Q) $(OBJCOPY) -w -L '$(SYMBOL_PREFIX)Init_*' -L '$(SYMBOL_PREFIX)*_threadptr_*' $@
$(Q) $(POSTLINK) $(Q) $(POSTLINK)
@-$(MINIRUBY) -e 'ARGV.each{|link| File.delete link if File.exist? link; \ @-$(MINIRUBY) -e 'ARGV.each{|link| File.delete link rescue nil; \
File.symlink "$(LIBRUBY_SO)", link}' \ File.symlink "$(LIBRUBY_SO)", link}' \
$(LIBRUBY_ALIASES) || true $(LIBRUBY_ALIASES) || true
$(arch)-fake.rb: config.status $(srcdir)/template/fake.rb.in $(arch)-fake.rb: config.status $(srcdir)/template/fake.rb.in
@ -251,14 +259,16 @@ install-cross: $(arch)-fake.rb $(RBCONFIG) rbconfig.rb $(arch_hdrdir)/ruby/confi
Makefile: $(srcdir)/Makefile.in $(srcdir)/enc/Makefile.in Makefile: $(srcdir)/Makefile.in $(srcdir)/enc/Makefile.in
$(MKFILES): config.status $(MKFILES): config.status
MAKE=$(MAKE) $(SHELL) ./config.status @[ -f $@ ] && mv $@ $@.old
@{ \ MAKE=$(MAKE) $(SHELL) ./config.status $@
@cmp $@ $@.old > /dev/null 2>&1 && echo $@ unchanged && exit 0; \
{ \
echo "all:; -@rm -f conftest.mk"; \ echo "all:; -@rm -f conftest.mk"; \
echo "conftest.mk: .force; @echo AUTO_REMAKE"; \ echo "conftest.mk: .force; @echo AUTO_REMAKE"; \
echo ".force:"; \ echo ".force:"; \
} > conftest.mk || exit 1; \ } > conftest.mk || exit 1; \
$(MAKE) -f conftest.mk | grep '^AUTO_REMAKE$$' >/dev/null 2>&1 || \ $(MAKE) -f conftest.mk | grep '^AUTO_REMAKE$$' >/dev/null 2>&1 || \
{ echo "Makefile updated, restart."; exit 1; } { echo "$@ updated, restart."; exit 1; }
uncommon.mk: $(srcdir)/common.mk uncommon.mk: $(srcdir)/common.mk
sed 's/{\$$([^(){}]*)[^{}]*}//g' $< > $@ sed 's/{\$$([^(){}]*)[^{}]*}//g' $< > $@
@ -425,6 +435,11 @@ enc/encinit.$(OBJEXT): enc/encinit.c $(SETUP)
up:: up::
@$(CHDIR) "$(srcdir)" && LC_TIME=C exec $(VCSUP) @$(CHDIR) "$(srcdir)" && LC_TIME=C exec $(VCSUP)
up::
-$(Q)$(MAKE) $(MFLAGS) after-update
after-update:: update-config_files
update-mspec: update-mspec:
@$(CHDIR) $(srcdir); \ @$(CHDIR) $(srcdir); \
if [ -d spec/mspec ]; then \ if [ -d spec/mspec ]; then \
@ -458,3 +473,8 @@ $(INSNS): $(srcdir)/insns.def vm_opts.h \
$(srcdir)/tool/instruction.rb $(srcdir)/tool/insns2vm.rb $(srcdir)/tool/instruction.rb $(srcdir)/tool/insns2vm.rb
$(ECHO) generating $@ $(ECHO) generating $@
$(Q) $(BASERUBY) -Ku $(srcdir)/tool/insns2vm.rb $(INSNS2VMOPT) $@ $(Q) $(BASERUBY) -Ku $(srcdir)/tool/insns2vm.rb $(INSNS2VMOPT) $@
loadpath: verconf.h
@$(CPP) $(XCFLAGS) $(CPPFLAGS) $(srcdir)/loadpath.c | \
sed -e '1,/^const char ruby_initial_load_paths/d;/;/,$$d' \
-e '/^ /!d;s/ *"\\0"$$//;s/" *"//g'

759
NEWS
View file

@ -1,6 +1,6 @@
# -*- rdoc -*- # -*- rdoc -*-
= NEWS for Ruby 2.0.0 = NEWS for Ruby 2.1.0
This document is a list of user visible feature changes made between This document is a list of user visible feature changes made between
releases except for bug fixes. releases except for bug fixes.
@ -9,446 +9,365 @@ Note that each entry is kept so brief that no reason behind or
reference information is supplied with. For a full list of changes reference information is supplied with. For a full list of changes
with all sufficient information, see the ChangeLog file. with all sufficient information, see the ChangeLog file.
== Changes since the 1.9.3 release == Changes since the 2.0.0 release
=== C API updates
* NUM2SHORT() and NUM2USHORT() added. They are similar to NUM2INT, but short.
* rb_newobj_of() and NEWOBJ_OF() added. They create a new object of a given class.
=== Library updates (outstanding ones only)
* builtin classes
* Array
* added method:
* added Array#bsearch for binary search.
* incompatible changes:
* random parameter of Array#shuffle! and Array#sample now
will be called with one argument, maximum value.
* when given Range arguments, Array#values_at now returns nil for each
value that is out-of-range.
* Enumerable
* added method:
* added Enumerable#lazy method for lazy enumeration.
* Enumerator
* added method:
* added Enumerator#size for lazy size evaluation.
* extended method:
* Enumerator.new accept an argument for lazy size evaluation.
* ENV
* aliased method:
* ENV.to_h is a new alias for ENV.to_hash
* Fiber
* incompatible changes:
* Fiber#resume cannot resume a fiber which invokes "Fiber#transfer".
* File
* extended method:
* File.fnmatch? now expands braces in the pattern if
File::FNM_EXTGLOB option is given.
* GC
* improvements:
* introduced the bitmap marking which suppresses to copy a memory page
with Copy-on-Write.
* introduced the non-recursive marking which avoids unexpected stack overflow.
* GC::Profiler
* added method:
* added GC::Profiler.raw_data which returns raw profile data for GC.
* Hash
* added method:
* added Hash#to_h as explicit conversion method, like Array#to_a.
* extended method:
* Hash#default_proc= can be passed nil to clear the default proc.
* IO
* deprecated methods:
* IO#lines, #bytes, #chars and #codepoints are deprecated.
* Kernel
* added method:
* added Kernel#Hash conversion method like Array() or Float().
* added Kernel#__dir__ which returns a current dirname.
* added Kernel#caller_locations which returns an array of
frame information objects.
* extended method:
* Kernel#warn accepts multiple args in like puts.
* Kernel#caller accepts second optional argument `n' which specify
required caller size.
* Kernel#to_enum and enum_for accept a block for lazy size evaluation.
* incompatible changes:
* system() and exec() closes non-standard file descriptors
(The default of :close_others option is changed to true by default.)
* respond_to? against a protected method now returns false unless
the second argument is true.
* __callee__ has returned to the original behavior, and now
returns the called name but not the original name in an
aliased method.
* Kernel#inspect does not call #to_s anymore
(it used to call redefined #to_s).
* LoadError
* added method:
* added LoadError#path method to return the file name that could not be
loaded.
* Module
* added method:
* added Module#prepend which is similar to Module#include,
however a method in the prepended module overrides the
corresponding method in the prepending module.
* added Module#refine, which extends a class or module locally.
[experimental]
* extended method:
* Module#define_method accepts a UnboundMethod from a Module.
* Module#const_get accepts a qualified constant string, e.g.
Object.const_get("Foo::Bar::Baz")
* Mutex
* added method:
* added Mutex#owned? which returns the mutex is held by current
thread or not. [experimental]
* incompatible changes:
* Mutex#lock, Mutex#unlock, Mutex#try_lock, Mutex#synchronize
and Mutex#sleep are no longer allowed to be used from trap handler
and raise a ThreadError in such case.
* Mutex#sleep may spurious wakeup. Check after wakeup.
* NilClass
* added method:
* added nil.to_h which returns {}
* Process
* added method:
* added getsid for getting session id (unix only).
* Range
* added method:
* added Range#size for lazy size evaluation.
* added Range#bsearch for binary search.
* RubyVM (MRI specific)
* added Environment variables to specify stack usage:
* RUBY_THREAD_VM_STACK_SIZE: vm stack size used at thread creation.
default: 128KB (32bit CPU) or 256KB (64bit CPU).
* RUBY_THREAD_MACHINE_STACK_SIZE: machine stack size used at thread
creation. default: 512KB or 1024KB.
* RUBY_FIBER_VM_STACK_SIZE: vm stack size used at fiber creation.
default: 64KB or 128KB.
* RUBY_FIBER_MACHINE_STACK_SIZE: machine stack size used at fiber
creation. default: 256KB or 256KB.
These variables are checked only at launched time.
* added constant DEFAULT_PARAMS to get above default parameters.
* Signal
* added method:
* added Signal.signame which returns signal name
* incompatible changes:
* Signal.trap raises ArgumentError when :SEGV, :BUS, :ILL, :FPE, :VTALRM
are specified.
* String
* added method:
* added String#b returning a copied string whose encoding is ASCII-8BIT.
* change return value:
* String#lines now returns an array instead of an enumerator.
* String#chars now returns an array instead of an enumerator.
* String#codepoints now returns an array instead of an enumerator.
* String#bytes now returns an array instead of an enumerator.
* Struct
* added method:
* added Struct#to_h returning values with keys corresponding to the
instance variable names.
* Thread
* added method:
* added Thread#thread_variable_get for getting thread local variables
(these are different than Fiber local variables).
* added Thread#thread_variable_set for setting thread local variables.
* added Thread#thread_variables for getting a list of the thread local
variable keys.
* added Thread#thread_variable? for testing to see if a particular thread
variable has been set.
* added Thread#backtrace_locations which returns similar information of
Kernel#caller_locations.
* incompatible changes:
* Thread#join and Thread#value now raises a ThreadError if target thread
is the current or main thread.
* Time
* change return value:
* Time#to_s returned encoding defaults to US-ASCII but automatically
transcodes to Encoding.default_internal if it is set.
* TracePoint
* new class. This class is replacement of set_trace_func.
Easy to use and efficient implementation.
* toplevel
* added method:
* added main.define_method which defines a global function.
* added main.using, which imports refinements into the current file or
eval string. [experimental]
* cgi
* Add HTML5 tag maker.
* CGI#header has been renamed to CGI#http_header and
aliased to CGI#header.
* When HTML5 tagmaker called, overwrite CGI#header,
CGI#header function is to create a <header> element.
* iconv
* Iconv has been removed. Use String#encode instead.
* io/wait
* new features:
* added IO#wait_writable method.
* added IO#wait_readable method as alias of IO#wait.
* net/http
* new features:
* Proxies are now automatically detected from the http_proxy environment
variable. See Net::HTTP::new for details.
* gzip and deflate compression are now requested for all requests by
default. See Net::HTTP for details.
* SSL sessions are now reused across connections for a single instance.
This speeds up connection by using a previously negotiated session.
* Requests may be created from a URI which sets the request_uri and host
header of the request (but does not change the host connected to).
* Responses contain the URI requested which allows easier implementation of
redirect following.
* new methods:
* Net::HTTP#local_host
* Net::HTTP#local_host=
* Net::HTTP#local_port
* Net::HTTP#local_port=
* extended method:
* Net::HTTP#connect uses local_host and local_port if specified.
* net/imap
* new methods:
* Net::IMAP.default_port
* Net::IMAP.default_imap_port
* Net::IMAP.default_tls_port
* Net::IMAP.default_ssl_port
* Net::IMAP.default_imaps_port
* objspace
* new method:
* ObjectSpace.reachable_objects_from(obj)
* openssl
* Consistently raise an error when trying to encode nil values. All instances
of OpenSSL::ASN1::Primitive now raise TypeError when calling to_der on an
instance whose value is nil. All instances of OpenSSL::ASN1::Constructive
raise NoMethodError in the same case. Constructing such values is still
permitted.
* TLS 1.1 & 1.2 support by setting OpenSSL::SSL::SSLContext#ssl_version to
:TLSv1_2, :TLSv1_2_server, :TLSv1_2_client or :TLSv1_1, :TLSv1_1_server
:TLSv1_1_client. The version being effectively used can be queried
with OpenSSL::SSL#ssl_version. Furthermore, it is also possible to
blacklist the new TLS versions with OpenSSL::SSL:OP_NO_TLSv1_1 and
OpenSSL::SSL::OP_NO_TLSv1_2.
* Added OpenSSL::SSL::SSLContext#renegotiation_cb. A user-defined callback
may be set which gets called whenever a new handshake is negotiated. This
also allows to programmatically decline (client) renegotiation attempts.
* Support for "0/n" splitting of records as BEAST mitigation via
OpenSSL::SSL::OP_DONT_INSERT_EMPTY_FRAGMENTS.
* The default options for OpenSSL::SSL::SSLContext have changed to
OpenSSL::SSL::OP_ALL & ~OpenSSL::SSL::OP_DONT_INSERT_EMPTY_FRAGMENTS
instead of OpenSSL::SSL::OP_ALL only. This enables the countermeasure for
the BEAST attack by default.
* OpenSSL requires passwords for decrypting PEM-encoded files to be at least
four characters long. This led to awkward situations where an export with
a password with fewer than four characters was possible, but accessing the
file afterwards failed. OpenSSL::PKey::RSA, OpenSSL::PKey::DSA and
OpenSSL::PKey::EC therefore now enforce the same check when exporting a
private key to PEM with a password - it has to be at least four characters
long.
* SSL/TLS support for the Next Protocol Negotiation extension. Supported
with OpenSSL 1.0.1 and higher.
* OpenSSL::OPENSSL_FIPS allows client applications to detect whether OpenSSL
is FIPS-enabled. OpenSSL.fips_mode= allows turning on and off FIPS mode
manually in order to adapt to situations where FIPS mode would be an
explicit requirement.
* Authenticated Encryption with Associated Data (AEAD) is supported via
Cipher#auth_data= and Cipher#auth_tag/Cipher#auth_tag=.
Currently (OpenSSL 1.0.1c), only GCM mode is supported.
* ostruct
* new methods:
* OpenStruct#[], []=
* OpenStruct#each_pair
* OpenStruct#eql?
* OpenStruct#hash
* OpenStruct#to_h converts the struct to a hash.
* extended method:
* OpenStruct.new also accepts an OpenStruct / Struct.
* pathname
* extended method:
* Pathname#find returns an enumerator if no block is given.
* rake
* rake has been updated to version 0.9.5.
This version is backwards-compatible with previous rake versions and
contains many bug fixes.
See
http://rake.rubyforge.org/doc/release_notes/rake-0_9_5_rdoc.html for a list
of changes in rake 0.9.3, 0.9.4 and 0.9.5.
* rdoc
* rdoc has been updated to version 4.0
This version is largely backwards-compatible with previous rdoc versions.
The most notable change is an update to the ri data format (ri data must
be regenerated for gems shared across rdoc versions). Further API changes
are internal and won't affect most users.
See https://github.com/rdoc/rdoc/blob/master/History.rdoc for a list of
changes in rdoc 4.0.
* resolv
* new methods:
* Resolv::DNS#timeouts=
* Resolv::DNS::Config#timeouts=
* rexml
* REXML::Document#write supports Hash arguments.
* REXML::Document#write supports new :encoding option. It changes
XML document encoding. Without :encoding option, encoding in
XML declaration is used for XML document encoding.
* RubyGems
* Updated to 2.0.0.preview2
RubyGems 2.0.0 features the following improvements:
* Improved support for default gems shipping with ruby 2.0.0+
* A gem can have arbitrary metadata through Gem::Specification#metadata
* `gem search` now defaults to --remote and is anchored like gem list.
* Added --document to replace --rdoc and --ri. Use --no-document to
disable documentation, --document=rdoc to only generate rdoc.
* Only ri-format documentation is generated by default.
* `gem server` uses RDoc::Servlet from RDoc 4.0 to generate HTML
documentation.
For an expanded list of updates and bug fixes see:
https://github.com/rubygems/rubygems/blob/master/History.txt
* shellwords
* Shellwords#shellescape() now stringifies the given object using to_s.
* Shellwords#shelljoin() accepts non-string objects in the given
array, each of which is stringified using to_s.
* stringio
* deprecated methods:
* StringIO#lines, #bytes, #chars and #codepoints are deprecated.
* syslog
* Added Syslog::Logger which provides a Logger API atop Syslog.
* Syslog::Priority, Syslog::Level, Syslog::Option and Syslog::Macros
are introduced for easy detection of available constants on a
running system.
* tmpdir
* incompatible changes:
* Dir.mktmpdir uses FileUtils.remove_entry instead of
FileUtils.remove_entry_secure. This means that applications should not
change the permission of the created temporary directory to make
accessible from other users.
* yaml
* Syck has been removed. YAML now completely depends on libyaml being
installed.
* zlib
* Added streaming support for Zlib::Inflate and Zlib::Deflate. This allows
processing of a stream without the use of large amounts of memory.
* Added support for the new deflate strategies Zlib::RLE and Zlib::FIXED.
* Zlib streams are now processed without the GVL. This allows gzip, zlib and
deflate streams to be processed in parallel.
* deprecated methods:
* Zlib::GzipReader#lines and #bytes are deprecated.
=== Language changes === Language changes
* Added %i and %I for symbol list creation (similar to %w and %W). * Now the default values of keyword arguments can be omitted. Those
"required keyword arguments" need giving explicitly at the call time.
* Default source encoding is changed to UTF-8. (was US-ASCII) * Added suffixes for integer and float literals: 'r', 'i', and 'ri'.
* "42r" and "3.14r" are evaluated as Rational(42, 1) and 3.14.rationalize,
respectively. But exponential form with 'r' suffix like "6.022e+23r" is
not accepted because it is misleading.
* "42i" and "3.14i" are evaluated as Complex(0, 42) and Complex(0, 3.14),
respectively.
* "42ri" and "3.14ri" are evaluated as Complex(0, 42r) and Complex(0, 3.14r),
respectively.
=== Compatibility issues (excluding feature bug fixes) * def-expr now returns the symbol of its name instead of nil.
* Array#values_at === Core classes updates (outstanding ones only)
See above. * Array
* New methods
* Array#to_h converts an array of key-value pairs into a Hash.
* String#lines * Binding
* String#chars * New methods
* String#codepoints * Binding#local_variable_get(symbol)
* String#bytes * Binding#local_variable_set(symbol, obj)
* Binding#local_variable_defined?(symbol)
These methods no longer return an Enumerator, although passing a * Enumerable
block is still supported for backwards compatibility. * New methods
* Enumerable#to_h converts a list of key-value pairs into a Hash.
Code like str.lines.with_index(1) { |line, lineno| ... } no longer * Exception
works because str.lines returns an array. Replace lines with * New methods
each_line in such cases. * Exception#cause provides the previous exception which has been caught
at where raising the new exception.
* IO#lines * GC
* IO#chars * improvements:
* IO#codepoints * introduced the generational GC a.k.a RGenGC.
* IO#bytes * added environment variables:
* ARGF#lines * RUBY_GC_HEAP_INIT_SLOTS
* ARGF#chars * RUBY_GC_HEAP_FREE_SLOTS
* ARGF#codepoints * RUBY_GC_HEAP_GROWTH_FACTOR
* ARGF#bytes * RUBY_GC_HEAP_GROWTH_MAX_SLOTS
* StringIO#lines * RUBY_GC_MALLOC_LIMIT_MAX
* StringIO#chars * RUBY_GC_MALLOC_LIMIT_GROWTH_FACTOR
* StringIO#codepoints * RUBY_GC_OLDMALLOC_LIMIT
* StringIO#bytes * RUBY_GC_OLDMALLOC_LIMIT_MAX
* Zlib::GzipReader#lines * RUBY_GC_OLDMALLOC_LIMIT_GROWTH_FACTOR
* Zlib::GzipReader#bytes * obsoleted environment variables:
* RUBY_FREE_MIN (Use RUBY_GC_HEAP_FREE_SLOTS instead)
* RUBY_HEAP_MIN_SLOTS (Use RUBY_GC_HEAP_INIT_SLOTS instead)
These methods are deprecated in favor of each_line, each_byte, * Integer
each_char and each_codepoint. * New methods
* Fixnum#bit_length
* Bignum#bit_length
* Bignum performance improvement
* Use GMP if available.
GMP is used only for several operations:
multiplication, division, radix conversion, GCD
* Signal.trap * IO
* extended methods:
* IO#seek supports SEEK_DATA and SEEK_HOLE as whence.
* IO#seek accepts symbols (:CUR, :END, :SET, :DATA, :HOLE) for 2nd argument.
* IO#read_nonblock accepts optional `exception: false` to return symbols
* IO#write_nonblock accepts optional `exception: false` to return symbols
See above. * Kernel
* New methods:
* Kernel#singleton_method
* Merge Onigmo. * Module
https://github.com/k-takata/Onigmo * New methods:
* Module#using, which activates refinements of the specified module only
in the current class or module definition.
* Module#singleton_class? returns true if the receiver is a singleton class
or false if it is an ordinary class or module.
* extended methods:
* Module#refine is no longer experimental.
* Module#include and Module#prepend are now public methods.
* The :close_others option is true by default for system() and exec(). * Mutex
Also, the close-on-exec flag is set by default for all new file descriptors. * misc
This means file descriptors doesn't inherit to spawned process unless * Mutex#owned? is no longer experimental.
explicitly requested such as system(..., fd=>fd).
* Kernel#respond_to? against a protected method now returns false * Numeric
unless the second argument is true. * extended methods:
* Numeric#step allows the limit argument to be omitted, in which
case an infinite sequence of numbers is generated. Keyword
arguments `to` and `by` are introduced for ease of use.
* Dir.mktmpdir in lib/tmpdir.rb * Process
* New methods:
* alternative methods to $0/$0=:
* Process.argv0() returns the original value of $0.
* Process.setproctitle() sets the process title without affecting $0.
* Process.clock_gettime
* Process.clock_getres
See above. * String
* New methods:
* String#scrub and String#scrub! verify and fix invalid byte sequence.
If you want to use this function with older Ruby,
consider to use string-scrub.gem.
* OpenStruct new methods can conflict with custom attributes named * Symbol
"each_pair", "eql?", "hash" or "to_h". * All symbols are now frozen.
* Thread#join, Thread#value * pack/unpack (Array/String)
* Q! and q! directives for long long type if platform has the type.
See above. * toplevel
* extended methods:
* main.using is no longer experimental. The method activates refinements
in the ancestors of the argument module to support refinement
inheritance by Module#include.
* Mutex#lock, Mutex#unlock, Mutex#try_lock, Mutex#synchronize and Mutex#sleep === Core classes compatibility issues (excluding feature bug fixes)
See above. * Hash
* incompatible changes:
* Hash#reject will return plain Hash object in the future versions, that
is the original object's subclass, instance variables, default value,
and taintedness will be no longer copied, so now warnings are emitted
when called with such Hash.
* IO
* incompatible changes:
* open ignore internal encoding if external encoding is ASCII-8BIT.
* Kernel#eval, Kernel#instance_eval, and Module#module_eval.
* Copies the scope information of the original environment, which means
that private, protected, public, and module_function without arguments
do not affect the environment outside the eval string.
For example, `class Foo; eval "private"; def foo; end; end' doesn't make
Foo#foo private.
* Kernel#untrusted?, untrust, and trust
* These methods are deprecated and their behavior is same as tainted?,
taint, and untaint, respectively. If $VERBOSE is true, they show warnings.
* Module#ancestors
* The ancestors of a singleton class now include singleton classes,
in particular itself.
* Module#define_method and Object#define_singleton_method
* Now they return the symbols of the defined methods, not the methods/procs
themselves.
* Numeric#quo
* Raises TypeError instead of ArgumentError if the receiver doesn't have
to_r method.
* Proc
* Returning from lambda proc now always exits from the Proc, not from the
method where the lambda is created. Returning from non-lambda proc exits
from the method, same as the former behavior.
String
* If invalid: :replace is specified for String#encode, replace
invalid byte sequence even if the destination encoding equals to
the source encoding.
=== Stdlib updates (outstanding ones only)
* CGI::Util
* All class methods modulized.
* Digest
* extended methods:
* Digest::Class.file takes optional arguments for its constructor
* Matrix
* Added Vector#cross_product.
* Net::SMTP
* Added Net::SMTP#rset to implement the RSET command
* objspace
* new method:
* ObjectSpace.trace_object_allocations
* ObjectSpace.trace_object_allocations_start
* ObjectSpace.trace_object_allocations_stop
* ObjectSpace.trace_object_allocations_clear
* ObjectSpace.allocation_sourcefile
* ObjectSpace.allocation_sourceline
* ObjectSpace.allocation_class_path
* ObjectSpace.allocation_method_id
* ObjectSpace.allocation_generation
* ObjectSpace.reachable_objects_from_root
* ObjectSpace.dump
* ObjectSpace.dump_all
* OpenSSL::BN
* extended methods:
* OpenSSL::BN.new allows Fixnum/Bignum argument.
* open-uri
* Support multiple fields with same field name (like Set-Cookie).
* Pathname
* New methods:
* Pathname#write
* Pathname#binwrite
* rake
* Updated to 10.1.0. Major changes include removal of the class namespace,
Rake::DSL to hold the rake DSL methods and removal of support for legacy
rake features.
For a complete list of changes since rake 0.9.6 see:
http://rake.rubyforge.org/doc/release_notes/rake-10_1_0_rdoc.html
http://rake.rubyforge.org/doc/release_notes/rake-10_0_3_rdoc.html
* RbConfig
* New constants:
* RbConfig::SIZEOF is added to provide the size of C types.
* RDoc
* Updated to 4.1.0. Major enhancements include a modified default template
* and accessibility enhancements.
For a list of minor enhancements and bug fixes see:
https://github.com/rdoc/rdoc/blob/v4.1.0.preview.1/History.rdoc
* Resolv
* New methods:
* Resolv::DNS.fetch_resource
* One-shot multicast DNS support
* Support LOC resources
* REXML::Parsers::SAX2Parser
* Fixes wrong number of arguments of entitydecl event. Document of the event
says "an array of the entity declaration" but implementation passes two
or more arguments. It is an implementation bug but it breaks backword
compatibility.
* REXML::Parsers::StreamParser
* Supports "entity" event.
* REXML::Text
* REXML::Text#<< supports method chain like 'text << "XXX" << "YYY"'.
* REXML::Text#<< supports not "raw" mode.
* Rinda::RingServer, Rinda::RingFinger
* Rinda now supports multicast sockets. See Rinda::RingServer and
Rinda::RingFinger for details.
* RubyGems
* Updated to 2.2.0. Notable new features include:
* Gemfile or gem.deps.rb support including Gem.file.lock (experimental)
* Improved, iterative resolver (compared to RubyGems 2.1 and earlier)
* Support for a sharing a GEM_HOME across ruby platforms and versions
For a complete list of enhancements and bug fixes see:
https://github.com/rubygems/rubygems/tree/master/History.txt
* Set
* New methods:
* Set#intersect?
* Set#disjoint?
* Socket
* New methods:
* Socket.getifaddrs
* StringScanner
* extended methods:
* StringScanner#[] supports named captures.
* Syslog::Logger
* Added facility.
* Tempfile
* New methods:
* Tempfile.create
* Timeout
* The exception to terminate the given block can no longer be rescued
inside the block, by default, unless the exception class is given
explicitly.
* TSort
* New methods:
* TSort.tsort
* TSort.tsort_each
* TSort.strongly_connected_components
* TSort.each_strongly_connected_component
* TSort.each_strongly_connected_component_from
* WEBrick
* The body of a response may now be a StringIO or other IO-like that responds
to #readpartial and #read.
* XMLRPC::Client
* New methods:
* XMLRPC::Client#http. It returns Net::HTTP for the client. Normally,
it is not needed. It is useful when you want to change minor HTTP client
options. You can change major HTTP client options by XMLRPC::Client
methods. You should use XMLRPC::Client methods for changing major
HTTP client options instead of XMLRPC::Client#http.
=== Stdlib compatibility issues (excluding feature bug fixes)
* Set
* incompatible changes:
* Set#to_set now returns self instead of generating a copy.
* URI
* incompatible changes:
* URI.decode_www_form follows current WHATWG URL Standard.
It gets encoding argument to specify the character encoding.
It now allows loose percent encoded strings, but denies ;-separator.
* URI.encode_www_form follows current WHATWG URL Standard.
It gets encoding argument to convert before percent encode.
UTF-16 strings aren't converted to UTF-8 before percent encode by default.
* curses
* Removed.
curses is now available as a gem.
See https://rubygems.org/gems/curses for details.
=== Built-in global variables compatibility issues
* $SAFE
* $SAFE=4 is obsolete. If $SAFE is set to 4 or larger, an ArgumentError
is raised.
=== C API updates
* rb_gc_set_params() is deprecated. This is only used in Ruby internal.
* rb_gc_count() added. This returns the number of times GC occurred.
* rb_gc_stat() added. This allows access to specific GC.stat() values from C
without any allocation overhead.
* rb_gc_latest_gc_info() added. This allows access to GC.latest_gc_info().
* rb_postponed_job_register() added. Takes a function callback which is invoked
when the VM is in a consistent state, i.e. to perform work from a C signal
handler.
* rb_profile_frames() added. Provides low-cost access to the current ruby stack
for callstack profiling.
* rb_tracepoint_new() supports new internal events accessible only from C:
* RUBY_INTERNAL_EVENT_NEWOBJ
* RUBY_INTERNAL_EVENT_FREEOBJ
* RUBY_INTERNAL_EVENT_GC_START
* RUBY_INTERNAL_EVENT_GC_END_MARK
* RUBY_INTERNAL_EVENT_GC_END_SWEEP
* Note that you *can not* specify "internal events" with normal events
(such as RUBY_EVENT_CALL, RUBY_EVENT_RETURN) simultaneously.

25
README
View file

@ -23,6 +23,11 @@ Perl). It is simple, straight-forward, and extensible.
== How to get Ruby == How to get Ruby
For a complete list of ways to install Ruby, including using third party
tools like rvm, see:
http://www.ruby-lang.org/en/downloads/
The Ruby distribution files can be found in the following FTP site: The Ruby distribution files can be found in the following FTP site:
ftp://ftp.ruby-lang.org/pub/ruby/ ftp://ftp.ruby-lang.org/pub/ruby/
@ -32,7 +37,7 @@ following command:
$ svn co http://svn.ruby-lang.org/repos/ruby/trunk/ ruby $ svn co http://svn.ruby-lang.org/repos/ruby/trunk/ ruby
Or if you are using git then use following command: Or if you are using git then use the following command:
$ git clone git://github.com/ruby/ruby.git $ git clone git://github.com/ruby/ruby.git
@ -41,7 +46,7 @@ command and see the list of branches:
$ svn ls http://svn.ruby-lang.org/repos/ruby/branches/ $ svn ls http://svn.ruby-lang.org/repos/ruby/branches/
Or if you are using git then use following command: Or if you are using git then use the following command:
$ git ls-remote git://github.com/ruby/ruby.git $ git ls-remote git://github.com/ruby/ruby.git
@ -132,21 +137,29 @@ This is what you need to do to compile and install Ruby:
If you fail to compile ruby, please send the detailed error report with If you fail to compile ruby, please send the detailed error report with
the error log and machine/OS type, to help others. the error log and machine/OS type, to help others.
Some extension libraries may not get compiled because of lack of
necessary external libraries and/or headers, then you will need to run
'<tt>make distclean-ext</tt>' to remove old configuration after
installing them in such case.
== Copying == Copying
See the file +COPYING+. See the file +COPYING+.
== Feedback
Questions about the Ruby language can be asked on the Ruby-Talk mailing list
(http://www.ruby-lang.org/en/community/mailing-lists) or on websites like
(http://stackoverflow.com).
Bug reports should be filed at http://bugs.ruby-lang.org
== The Author == The Author
Feel free to send comments and bug reports to the author. Here is the Ruby was originally designed and developed by Yukihiro Matsumoto (Matz) in 1995.
author's latest mail address:
<mailto:matz@ruby-lang.org> <mailto:matz@ruby-lang.org>
-------------------------------------------------------
created at: Thu Aug 3 11:57:36 JST 1995
-- --
Local variables: Local variables:
mode: rdoc mode: rdoc

View file

@ -125,12 +125,15 @@ Other data types have corresponding C structures, e.g. struct RArray
for T_ARRAY etc. The VALUE of the type which has the corresponding for T_ARRAY etc. The VALUE of the type which has the corresponding
structure can be cast to retrieve the pointer to the struct. The structure can be cast to retrieve the pointer to the struct. The
casting macro will be of the form RXXXX for each data type; for casting macro will be of the form RXXXX for each data type; for
instance, RARRAY(obj). See "ruby.h". instance, RARRAY(obj). See "ruby.h". However, we do not recommend
to access RXXXX data directly because these data structure is complex.
Use corresponding rb_xxx() functions to access internal struct.
For example, to access an entry of array, use rb_ary_entry(ary, offset)
and rb_ary_store(ary, offset, obj).
There are some accessing macros for structure members, for example There are some accessing macros for structure members, for example
`RSTRING_LEN(str)' to get the size of the Ruby String object. The `RSTRING_LEN(str)' to get the size of the Ruby String object. The
allocated region can be accessed by `RSTRING_PTR(str)'. For arrays, allocated region can be accessed by `RSTRING_PTR(str)'.
use `RARRAY_LEN(ary)' and `RARRAY_PTR(ary)' respectively.
Notice: Do not change the value of the structure directly, unless you Notice: Do not change the value of the structure directly, unless you
are responsible for the result. This ends up being the cause of are responsible for the result. This ends up being the cause of
@ -196,6 +199,10 @@ rb_vsprintf(const char *format, va_list ap) ::
Creates a new Ruby string with printf(3) format. Creates a new Ruby string with printf(3) format.
Note: In the format string, %i is used for Object#to_s (or Object#inspect if
'+' flag is set) output (and related argument must be a VALUE). For integers
in format strings, use %d.
rb_str_cat(VALUE str, const char *ptr, long len) :: rb_str_cat(VALUE str, const char *ptr, long len) ::
Appends len bytes of data from ptr to the Ruby string. Appends len bytes of data from ptr to the Ruby string.
@ -214,6 +221,7 @@ rb_str_vcatf(VALUE str, const char* format, va_list ap) ::
rb_str_cat2(str, rb_vsprintf(format, ap)), respectively. rb_str_cat2(str, rb_vsprintf(format, ap)), respectively.
rb_enc_str_new(const char *ptr, long len, rb_encoding *enc) :: rb_enc_str_new(const char *ptr, long len, rb_encoding *enc) ::
rb_enc_str_new_cstr(const char *ptr, rb_encoding *enc) ::
Creates a new Ruby string with the specified encoding. Creates a new Ruby string with the specified encoding.
@ -246,15 +254,18 @@ rb_ary_new() ::
Creates an array with no elements. Creates an array with no elements.
rb_ary_new2(long len) :: rb_ary_new2(long len) ::
rb_ary_new_capa(long len) ::
Creates an array with no elements, allocating internal buffer Creates an array with no elements, allocating internal buffer
for len elements. for len elements.
rb_ary_new3(long n, ...) :: rb_ary_new3(long n, ...) ::
rb_ary_new_from_args(long n, ...) ::
Creates an n-element array from the arguments. Creates an n-element array from the arguments.
rb_ary_new4(long n, VALUE *elts) :: rb_ary_new4(long n, VALUE *elts) ::
rb_ary_new_from_values(long n, VALUE *elts) ::
Creates an n-element array from a C array. Creates an n-element array from a C array.
@ -268,12 +279,16 @@ types are given.
rb_ary_aref(argc, VALUE *argv, VALUE ary) :: rb_ary_aref(argc, VALUE *argv, VALUE ary) ::
Equivaelent to Array#[]. Equivalent to Array#[].
rb_ary_entry(VALUE ary, long offset) :: rb_ary_entry(VALUE ary, long offset) ::
ary[offset] ary[offset]
rb_ary_store(VALUE ary, long offset, VALUE obj) ::
ary[offset] = obj
rb_ary_subseq(VALUE ary, long beg, long len) :: rb_ary_subseq(VALUE ary, long beg, long len) ::
ary[beg, len] ary[beg, len]
@ -756,7 +771,7 @@ various conditions.
check_sizeof(type[, headers[, opts]]): check size of type check_sizeof(type[, headers[, opts]]): check size of type
check_signedness(type[, headers[, opts]]): check signedness of type check_signedness(type[, headers[, opts]]): check signedness of type
convertible_int(type[, headers[, opts]]): find convertible integer type convertible_int(type[, headers[, opts]]): find convertible integer type
find_executable(bin[, path]): find excutable file path find_executable(bin[, path]): find executable file path
create_header(header): generate configured header create_header(header): generate configured header
create_makefile(target[, target_prefix]): generate Makefile create_makefile(target[, target_prefix]): generate Makefile
@ -849,7 +864,7 @@ lex.c :: automatically generated from keywords
eval_safe.c eval_safe.c
insns.def : definition of VM instructions insns.def : definition of VM instructions
iseq.c : implementation of VM::ISeq iseq.c : implementation of VM::ISeq
thread.c : thread management and context swiching thread.c : thread management and context switching
thread_win32.c : thread implementation thread_win32.c : thread implementation
thread_pthread.c : ditto thread_pthread.c : ditto
vm.c vm.c
@ -878,7 +893,7 @@ lex.c :: automatically generated from keywords
== Utility Functions == Utility Functions
debug.c :: debug symbols for C debuggger debug.c :: debug symbols for C debugger
dln.c :: dynamic loading dln.c :: dynamic loading
st.c :: general purpose hash table st.c :: general purpose hash table
strftime.c :: formatting times strftime.c :: formatting times
@ -1053,6 +1068,10 @@ NUM2SSIZET(value), SSIZET2NUM(ssize) ::
Numeric <-> ssize_t Numeric <-> ssize_t
rb_integer_pack(value, words, numwords, wordsize, nails, flags), rb_integer_unpack(words, numwords, wordsize, nails, flags) ::
Numeric <-> Arbitrary size integer buffer
NUM2DBL(value) :: NUM2DBL(value) ::
Numeric -> double Numeric -> double
@ -1235,10 +1254,18 @@ rb_scan_args(int argc, VALUE *argv, const char *fmt, ...) ::
VALUE rb_funcall(VALUE recv, ID mid, int narg, ...) :: VALUE rb_funcall(VALUE recv, ID mid, int narg, ...) ::
Invokes a method. To retrieve mid from a method name, use rb_intern(). Invokes a method. To retrieve mid from a method name, use rb_intern().
Able to call even private/protected methods.
VALUE rb_funcall2(VALUE recv, ID mid, int argc, VALUE *argv) :: VALUE rb_funcall2(VALUE recv, ID mid, int argc, VALUE *argv) ::
VALUE rb_funcallv(VALUE recv, ID mid, int argc, VALUE *argv) ::
Invokes a method, passing arguments by an array of values. Invokes a method, passing arguments as an array of values.
Able to call even private/protected methods.
VALUE rb_funcallv_public(VALUE recv, ID mid, int argc, VALUE *argv) ::
Invokes a method, passing arguments as an array of values.
Able to call only public methods.
VALUE rb_eval_string(const char *str) :: VALUE rb_eval_string(const char *str) ::
@ -1308,12 +1335,12 @@ VALUE rb_ensure(VALUE (*func1)(), VALUE arg1, VALUE (*func2)(), VALUE arg2) ::
Calls the function func1 with arg1 as the argument, then calls func2 Calls the function func1 with arg1 as the argument, then calls func2
with arg2 if execution terminated. The return value from with arg2 if execution terminated. The return value from
rb_ensure() is that of func1 when no exception occured. rb_ensure() is that of func1 when no exception occurred.
VALUE rb_protect(VALUE (*func) (VALUE), VALUE arg, int *state) :: VALUE rb_protect(VALUE (*func) (VALUE), VALUE arg, int *state) ::
Calls the function func with arg as the argument. If no exception Calls the function func with arg as the argument. If no exception
occured during func, it returns the result of func and *state is zero. occurred during func, it returns the result of func and *state is zero.
Otherwise, it returns Qnil and sets *state to nonzero. If state is Otherwise, it returns Qnil and sets *state to nonzero. If state is
NULL, it is not set in both cases. NULL, it is not set in both cases.
You have to clear the error info with rb_set_errinfo(Qnil) when You have to clear the error info with rb_set_errinfo(Qnil) when
@ -1366,6 +1393,10 @@ void rb_bug(const char *fmt, ...) ::
called under the situation caused by the bug in the interpreter. No called under the situation caused by the bug in the interpreter. No
exception handling nor ensure execution will be done. exception handling nor ensure execution will be done.
Note: In the format string, %i is used for Object#to_s (or Object#inspect if
'+' flag is set) output (and related argument must be a VALUE). For integers
in format strings, use %d.
== Initialize and Start the Interpreter == Initialize and Start the Interpreter
The embedding API functions are below (not needed for extension libraries): The embedding API functions are below (not needed for extension libraries):
@ -1457,6 +1488,10 @@ RB_EVENT_HOOKS_HAVE_CALLBACK_DATA ::
Means that rb_add_event_hook() takes the third argument `data', to be Means that rb_add_event_hook() takes the third argument `data', to be
passed to the given event hook function. passed to the given event hook function.
= Appendix C. Functions available for use in extconf.rb
See documentation for {mkmf}[rdoc-ref:MakeMakefile].
/* /*
* Local variables: * Local variables:
* fill-column: 70 * fill-column: 70

View file

@ -140,13 +140,15 @@ var は lvalue である必要があります.
あるのは文字列と配列くらいだと思います. あるのは文字列と配列くらいだと思います.
ruby.hでは構造体へキャストするマクロも「RXXXXX()」(全部大文 ruby.hでは構造体へキャストするマクロも「RXXXXX()」(全部大文
字にしたもの)という名前で提供されています(例: RSTRING()) 字にしたもの)という名前で提供されています(例: RSTRING()).た
だし、構造体への直接のアクセスはできるだけ避け,対応する
rb_xxxx() といった関数を使うようにして下さい.例えば,配列の
要素へアクセスする場合はrb_ary_entry(ary, offset)
rb_ary_store(ary, offset, obj) を利用するようにして下さい.
構造体からデータを取り出すマクロが提供されています.文字列 構造体からデータを取り出すマクロが提供されています.文字列
strの長さを得るためには「RSTRING_LEN(str)」とし文字列strを strの長さを得るためには「RSTRING_LEN(str)」とし文字列strを
char*として得るためには「RSTRING_PTR(str)」とします.配列の char*として得るためには「RSTRING_PTR(str)」とします.
場合にはそれぞれ「RARRAY_LEN(ary)」「RARRAY_PTR(ary)」と
なります.
Rubyの構造体を直接アクセスする時に気をつけなければならないこ Rubyの構造体を直接アクセスする時に気をつけなければならないこ
とは,配列や文字列の構造体の中身は参照するだけで,直接変更し とは,配列や文字列の構造体の中身は参照するだけで,直接変更し
@ -193,7 +195,7 @@ INT2NUM()は整数がFIXNUMの範囲に収まらない場合Bignumに変換
Rubyが用意している関数を用いてください Rubyが用意している関数を用いてください
ここではもっとも使われるであろう文字列と配列の生成/操作を行 ここではもっとも使われるであろう文字列と配列の生成/操作を行
関数をあげます(全部ではないです) 関数をあげます(全部ではないです)
=== 文字列に対する関数 === 文字列に対する関数
@ -224,6 +226,9 @@ rb_vsprintf(const char *format, va_list ap)
Cの文字列formatと続く引数をprintf(3)のフォーマットにしたがって Cの文字列formatと続く引数をprintf(3)のフォーマットにしたがって
整形しRubyの文字列を生成する 整形しRubyの文字列を生成する
注意: %iはObject#to_s('+'フラグが指定されているときはObject#inspect)を
使ったVALUEの出力に使用されているため整数には%dを使用すること
rb_str_cat(VALUE str, const char *ptr, long len) rb_str_cat(VALUE str, const char *ptr, long len)
Rubyの文字列strにlenバイトの文字列ptrを追加する Rubyの文字列strにlenバイトの文字列ptrを追加する
@ -242,6 +247,7 @@ rb_str_vcatf(VALUE str, const char* format, va_list ap)
rb_str_cat2(str, rb_vsprintf(format, ap)) と同等である. rb_str_cat2(str, rb_vsprintf(format, ap)) と同等である.
rb_enc_str_new(const char *ptr, long len, rb_encoding *enc) rb_enc_str_new(const char *ptr, long len, rb_encoding *enc)
rb_enc_str_new_cstr(const char *ptr, rb_encoding *enc)
指定されたエンコーディングでRubyの文字列を生成する. 指定されたエンコーディングでRubyの文字列を生成する.
@ -274,15 +280,18 @@ rb_ary_new()
要素が0の配列を生成する 要素が0の配列を生成する
rb_ary_new2(long len) rb_ary_new2(long len)
rb_ary_new_capa(long len)
要素が0の配列を生成するlen要素分の領域をあらかじめ割り 要素が0の配列を生成するlen要素分の領域をあらかじめ割り
当てておく. 当てておく.
rb_ary_new3(long n, ...) rb_ary_new3(long n, ...)
rb_ary_new_from_args(long n, ...)
引数で指定したn要素を含む配列を生成する 引数で指定したn要素を含む配列を生成する
rb_ary_new4(long n, VALUE *elts) rb_ary_new4(long n, VALUE *elts)
rb_ary_new_from_values(long n, VALUE *elts)
配列で与えたn要素の配列を生成する 配列で与えたn要素の配列を生成する
@ -303,6 +312,10 @@ rb_ary_entry(VALUE ary, long offset)
ary[offset] ary[offset]
rb_ary_store(VALUE ary, long offset, VALUE obj) ::
ary[offset] = obj
rb_ary_subseq(VALUE ary, long beg, long len) rb_ary_subseq(VALUE ary, long beg, long len)
ary[beg, len] ary[beg, len]
@ -521,6 +534,7 @@ Cから文字列を経由せずにRubyのメソッドを呼び出すためには
します.その他に引数の指定の仕方が違う以下の関数もあります. します.その他に引数の指定の仕方が違う以下の関数もあります.
VALUE rb_funcall2(VALUE recv, ID mid, int argc, VALUE *argv) VALUE rb_funcall2(VALUE recv, ID mid, int argc, VALUE *argv)
VALUE rb_funcallv(VALUE recv, ID mid, int argc, VALUE *argv)
VALUE rb_apply(VALUE recv, ID mid, VALUE args) VALUE rb_apply(VALUE recv, ID mid, VALUE args)
applyには引数としてRubyの配列を与えます applyには引数としてRubyの配列を与えます
@ -628,10 +642,9 @@ Dataオブジェクトを生成して構造体をRubyオブジェクトにカプ
このマクロの戻り値は生成されたDataオブジェクトです このマクロの戻り値は生成されたDataオブジェクトです
klassはこのDataオブジェクトのクラスですptrはカプセル化する klassはこのDataオブジェクトのクラスですmarkはこの構造体が
Cの構造体へのポインタですmarkはこの構造体がRubyのオブジェ Rubyのオブジェクトへの参照がある時に使う関数ですそのような
クトへの参照がある時に使う関数です.そのような参照を含まない 参照を含まない時には0を指定します
時には0を指定します
# そのような参照は勧められません. # そのような参照は勧められません.
@ -649,7 +662,10 @@ Cの構造体の割当とDataオブジェクトの生成を同時に行うマク
Data_Make_Struct(klass, type, mark, free, sval) Data_Make_Struct(klass, type, mark, free, sval)
このマクロの戻り値は生成されたDataオブジェクトです このマクロの戻り値は生成されたDataオブジェクトですこのマク
ロは以下の式のように働きます:
(sval = ALLOC(type), Data_Wrap_Struct(klass, mark, free, sval))
klass, mark, freeはData_Wrap_Structと同じ働きをしますtype klass, mark, freeはData_Wrap_Structと同じ働きをしますtype
は割り当てるC構造体の型です割り当てられた構造体は変数sval は割り当てるC構造体の型です割り当てられた構造体は変数sval
@ -1099,6 +1115,7 @@ Data_Get_Struct(data, type, sval) ::
NUM2OFFT(value), OFFT2NUM(off) NUM2OFFT(value), OFFT2NUM(off)
NUM2SIZET(value), SIZET2NUM(size) NUM2SIZET(value), SIZET2NUM(size)
NUM2SSIZET(value), SSIZET2NUM(ssize) NUM2SSIZET(value), SSIZET2NUM(ssize)
rb_integer_pack(value, words, numwords, wordsize, nails, flags), rb_integer_unpack(words, numwords, wordsize, nails, flags)
NUM2DBL(value) NUM2DBL(value)
rb_float_new(f) rb_float_new(f)
StringValue(value) StringValue(value)
@ -1250,10 +1267,18 @@ VALUE rb_funcall(VALUE recv, ID mid, int narg, ...) ::
メソッド呼び出し文字列からmidを得るためにはrb_intern()を メソッド呼び出し文字列からmidを得るためにはrb_intern()を
使う. 使う.
private/protectedなメソッドでも呼び出せる
VALUE rb_funcall2(VALUE recv, ID mid, int argc, VALUE *argv) :: VALUE rb_funcall2(VALUE recv, ID mid, int argc, VALUE *argv) ::
VALUE rb_funcallv(VALUE recv, ID mid, int argc, VALUE *argv) ::
メソッド呼び出し引数をargc, argv形式で渡す メソッド呼び出し引数をargc, argv形式で渡す
private/protectedなメソッドでも呼び出せる
VALUE rb_funcallv_public(VALUE recv, ID mid, int argc, VALUE *argv) ::
メソッド呼び出し.
publicなメソッドしか呼べない
VALUE rb_eval_string(const char *str) VALUE rb_eval_string(const char *str)
@ -1379,6 +1404,9 @@ void rb_bug(const char *fmt, ...) ::
状況の時呼ぶ.インタープリタはコアダンプし直ちに終了する. 状況の時呼ぶ.インタープリタはコアダンプし直ちに終了する.
例外処理は一切行なわれない. 例外処理は一切行なわれない.
注意: %iはObject#to_s('+'フラグが指定されているときはObject#inspect)を
使ったVALUEの出力に使用されているため整数には%dを使用すること
== Rubyの初期化・実行 == Rubyの初期化・実行
Rubyをアプリケーションに埋め込む場合には以下のインタフェース Rubyをアプリケーションに埋め込む場合には以下のインタフェース
@ -1487,53 +1515,62 @@ have_macro(macro, headers) ::
have_library(lib, func) :: have_library(lib, func) ::
関数funcを定義しているライブラリlibの存在をチェックする 関数funcを定義しているライブラリlibの存在をチェックする
ライブラリが存在する時trueを返す チェックに成功すると,-llibを$libsに追加しtrueを返す
find_library(lib, func, path...) :: find_library(lib, func, path...) ::
関数funcを定義しているライブラリlibの存在を -Lpath を追加 関数funcを定義しているライブラリlibの存在を -Lpath を追加
しながらチェックするライブラリが見付かった時trueを返す しながらチェックする.チェックに成功すると,-llibを$libsに
追加しtrueを返す
have_func(func, header) :: have_func(func, header) ::
ヘッダファイルheaderをインクルードして関数funcの存在をチェ ヘッダファイルheaderをインクルードして関数funcの存在をチェ
ックするfuncが標準ではリンクされないライブラリ内のもので ックするfuncが標準ではリンクされないライブラリ内のもので
ある時には先にhave_libraryでそのライブラリをチェックしてお ある時には先にhave_libraryでそのライブラリをチェックしてお
く事関数が存在する時trueを返す く事.チェックに成功すると,プリプロセッサマクロ
`HAVE_{FUNC}` を定義しtrueを返す
have_var(var, header) :: have_var(var, header) ::
ヘッダファイルheaderをインクルードして変数varの存在をチェッ ヘッダファイルheaderをインクルードして変数varの存在をチェッ
クするvarが標準ではリンクされないライブラリ内のものであ クするvarが標準ではリンクされないライブラリ内のものであ
る時には先にhave_libraryでそのライブラリをチェックしておく る時には先にhave_libraryでそのライブラリをチェックしておく
変数が存在する時trueを返す 事.チェックに成功すると,プリプロセッサマクロ
`HAVE_{VAR}` を定義しtrueを返す
have_header(header) :: have_header(header) ::
ヘッダファイルの存在をチェックする.ヘッダファイルが存在す ヘッダファイルの存在をチェックする.チェックに成功すると,
る時trueを返す プリプロセッサマクロ `HAVE_{HEADER_H}` を定義しtrueを返す
(スラッシュやドットはアンダースコアに置換される)
find_header(header, path...) :: find_header(header, path...) ::
ヘッダファイルheaderの存在を -Ipath を追加しながらチェック ヘッダファイルheaderの存在を -Ipath を追加しながらチェック
するヘッダファイルが見付かった時trueを返す する.チェックに成功すると,プリプロセッサマクロ
`HAVE_{HEADER_H}` を定義しtrueを返す
(スラッシュやドットはアンダースコアに置換される)
have_struct_member(type, member[, header[, opt]]) :: have_struct_member(type, member[, header[, opt]]) ::
ヘッダファイルheaderをインクルードして型typeにメンバmember ヘッダファイルheaderをインクルードして型typeが定義され
が存在するかをチェックするtypeが定義されていてmemberを なおかつメンバmemberが存在するかをチェックするチェックに
持つする時trueを返す 成功すると,プリプロセッサマクロ `HAVE_{TYPE}_{MEMBER}` を
定義しtrueを返す
have_type(type, header, opt) :: have_type(type, header, opt) ::
ヘッダファイルheaderをインクルードして型typeが存在するかを ヘッダファイルheaderをインクルードして型typeが存在するかを
チェックするtypeが定義されている時trueを返す チェックする.チェックに成功すると,プリプロセッサマクロ
`HAVE_TYPE_{TYPE}` を定義しtrueを返す
check_sizeof(type, header) :: check_sizeof(type, header) ::
ヘッダファイルheaderをインクルードして型typeのchar単位サイ ヘッダファイルheaderをインクルードして型typeのchar単位サイ
ズを調べるtypeが定義されている時そのサイズを返す定義さ ズを調べる.チェックに成功すると,プリプロセッサマクロ
れていないときはnilを返す `SIZEOF_{TYPE}` を定義し,そのサイズを返す.定義されていな
いときはnilを返す
create_makefile(target[, target_prefix]) :: create_makefile(target[, target_prefix]) ::
@ -1574,11 +1611,21 @@ dir_config(target[, default_include, default_lib]) ::
と等価である.追加された include ディレクトリと lib ディレ と等価である.追加された include ディレクトリと lib ディレ
クトリの配列を返す. ([include_dir, lib_dir]) クトリの配列を返す. ([include_dir, lib_dir])
pkg_config(pkg) :: pkg_config(pkg, option=nil) ::
pkg-configコマンドからパッケージpkgの情報を得る pkg-configコマンドからパッケージpkgの情報を [cflags, ldflags, libs]
pkg-configの実際のコマンド名は--with-pkg-configコマンド の配列として得る.$CFLAGS, $LDFLAGS, $libs にはそれぞれの値が
ラインオプションで指定可能. 追加される.
pkg-configの実際のコマンドは以下の順で試される
1. コマンドラインで--with-{pkg}-config={command}オプションが
指定された場合: {command} {option}
2. {pkg}-config {option}
3. pkg-config {option} {pkg}
optionが指定された場合は、上記の配列の代わりにそのオプションを
指定して得られた出力をstripしたものを返す
/* /*
* Local variables: * Local variables:

View file

@ -183,7 +183,7 @@ UNIXであれば +configure+ がほとんどの差異を吸収してくれるは
== 著者 == 著者
コメント,バグレポートその他は mailto:matz@ruby-lang.jp まで. コメント,バグレポートその他は mailto:matz@ruby-lang.org まで.
------------------------------------------------------- -------------------------------------------------------
created at: Thu Aug 3 11:57:36 JST 1995 created at: Thu Aug 3 11:57:36 JST 1995
-- --

View file

@ -9,6 +9,7 @@
**********************************************************************/ **********************************************************************/
#include "ruby/config.h" #include "ruby/config.h"
#include "ruby/missing.h"
#include "addr2line.h" #include "addr2line.h"
#include <stdio.h> #include <stdio.h>
@ -16,11 +17,6 @@
#ifdef USE_ELF #ifdef USE_ELF
#ifdef __OpenBSD__
#include <elf_abi.h>
#else
#include <elf.h>
#endif
#include <fcntl.h> #include <fcntl.h>
#include <limits.h> #include <limits.h>
#include <stdio.h> #include <stdio.h>
@ -32,6 +28,12 @@
#include <sys/stat.h> #include <sys/stat.h>
#include <unistd.h> #include <unistd.h>
#ifdef __OpenBSD__
#include <elf_abi.h>
#else
#include <elf.h>
#endif
/* Make alloca work the best possible way. */ /* Make alloca work the best possible way. */
#ifdef __GNUC__ #ifdef __GNUC__
# ifndef atarist # ifndef atarist
@ -90,6 +92,8 @@ void *alloca();
#define PATH_MAX 4096 #define PATH_MAX 4096
#endif #endif
int kprintf(const char *fmt, ...);
typedef struct { typedef struct {
const char *dirname; const char *dirname;
const char *filename; const char *filename;
@ -153,7 +157,7 @@ get_nth_dirname(unsigned long dir, char *p)
while (*p) p++; while (*p) p++;
p++; p++;
if (!*p) { if (!*p) {
fprintf(stderr, "Unexpected directory number %lu in %s\n", kprintf("Unexpected directory number %lu in %s\n",
dir, binary_filename); dir, binary_filename);
return ""; return "";
} }
@ -173,7 +177,7 @@ fill_filename(int file, char *include_directories, char *filenames,
filename = p; filename = p;
if (!*p) { if (!*p) {
/* Need to output binary file name? */ /* Need to output binary file name? */
fprintf(stderr, "Unexpected file number %d in %s\n", kprintf("Unexpected file number %d in %s\n",
file, binary_filename); file, binary_filename);
return; return;
} }
@ -375,7 +379,7 @@ parse_debug_line_cu(int num_traces, void **traces,
p += sizeof(unsigned long); p += sizeof(unsigned long);
break; break;
case DW_LNE_define_file: case DW_LNE_define_file:
fprintf(stderr, "Unsupported operation in %s\n", kprintf("Unsupported operation in %s\n",
binary_filename); binary_filename);
break; break;
case DW_LNE_set_discriminator: case DW_LNE_set_discriminator:
@ -383,7 +387,7 @@ parse_debug_line_cu(int num_traces, void **traces,
uleb128(&p); uleb128(&p);
break; break;
default: default:
fprintf(stderr, "Unknown extended opcode: %d in %s\n", kprintf("Unknown extended opcode: %d in %s\n",
op, binary_filename); op, binary_filename);
} }
break; break;
@ -411,7 +415,7 @@ parse_debug_line(int num_traces, void **traces,
parse_debug_line_cu(num_traces, traces, &debug_line, lines); parse_debug_line_cu(num_traces, traces, &debug_line, lines);
} }
if (debug_line != debug_line_end) { if (debug_line != debug_line_end) {
fprintf(stderr, "Unexpected size of .debug_line in %s\n", kprintf("Unexpected size of .debug_line in %s\n",
binary_filename); binary_filename);
} }
} }
@ -473,13 +477,13 @@ fill_lines(int num_traces, void **traces, char **syms, int check_debuglink,
if (filesize < 0) { if (filesize < 0) {
int e = errno; int e = errno;
close(fd); close(fd);
fprintf(stderr, "lseek: %s\n", strerror(e)); kprintf("lseek: %s\n", strerror(e));
return; return;
} }
#if SIZEOF_OFF_T > SIZEOF_SIZE_T #if SIZEOF_OFF_T > SIZEOF_SIZE_T
if (filesize > (off_t)SIZE_MAX) { if (filesize > (off_t)SIZE_MAX) {
close(fd); close(fd);
fprintf(stderr, "Too large file %s\n", binary_filename); kprintf("Too large file %s\n", binary_filename);
return; return;
} }
#endif #endif
@ -489,7 +493,7 @@ fill_lines(int num_traces, void **traces, char **syms, int check_debuglink,
if (file == MAP_FAILED) { if (file == MAP_FAILED) {
int e = errno; int e = errno;
close(fd); close(fd);
fprintf(stderr, "mmap: %s\n", strerror(e)); kprintf("mmap: %s\n", strerror(e));
return; return;
} }
@ -614,23 +618,22 @@ rb_dump_backtrace_with_lines(int num_traces, void **trace, char **syms)
fill_lines(num_traces, trace, syms, 1, &lines[i], lines); fill_lines(num_traces, trace, syms, 1, &lines[i], lines);
} }
/* fprintf may not be async-signal safe */
for (i = 0; i < num_traces; i++) { for (i = 0; i < num_traces; i++) {
line_info_t *line = &lines[i]; line_info_t *line = &lines[i];
if (line->line > 0) { if (line->line > 0) {
fprintf(stderr, "%s ", syms[i]);
if (line->filename) { if (line->filename) {
if (line->dirname && line->dirname[0]) { if (line->dirname && line->dirname[0]) {
fprintf(stderr, "%s/", line->dirname); kprintf("%s %s/%s:%d\n", syms[i], line->dirname, line->filename, line->line);
}
else {
kprintf("%s %s:%d\n", syms[i], line->filename, line->line);
} }
fprintf(stderr, "%s", line->filename);
} else { } else {
fprintf(stderr, "???"); kprintf("%s ???:%d\n", syms[i], line->line);
} }
fprintf(stderr, ":%d\n", line->line);
} else { } else {
fprintf(stderr, "%s\n", syms[i]); kprintf("%s\n", syms[i]);
} }
} }
@ -644,6 +647,436 @@ rb_dump_backtrace_with_lines(int num_traces, void **trace, char **syms)
free(lines); free(lines);
} }
/* From FreeBSD's lib/libstand/printf.c */
/*-
* Copyright (c) 1986, 1988, 1991, 1993
* The Regents of the University of California. All rights reserved.
* (c) UNIX System Laboratories, Inc.
* All or some portions of this file are derived from material licensed
* to the University of California by American Telephone and Telegraph
* Co. or Unix System Laboratories, Inc. and are reproduced herein with
* the permission of UNIX System Laboratories, Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)subr_prf.c 8.3 (Berkeley) 1/21/94
*/
#include <stdarg.h>
#define MAXNBUF (sizeof(intmax_t) * CHAR_BIT + 1)
extern int rb_toupper(int c);
#define toupper(c) rb_toupper(c)
#define hex2ascii(hex) (hex2ascii_data[hex])
char const hex2ascii_data[] = "0123456789abcdefghijklmnopqrstuvwxyz";
static inline int imax(int a, int b) { return (a > b ? a : b); }
static int kvprintf(char const *fmt, void (*func)(int), void *arg, int radix, va_list ap);
static void putce(int c)
{
char s[1];
ssize_t ret;
s[0] = (char)c;
ret = write(2, s, 1);
(void)ret;
}
int
kprintf(const char *fmt, ...)
{
va_list ap;
int retval;
va_start(ap, fmt);
retval = kvprintf(fmt, putce, NULL, 10, ap);
va_end(ap);
return retval;
}
/*
* Put a NUL-terminated ASCII number (base <= 36) in a buffer in reverse
* order; return an optional length and a pointer to the last character
* written in the buffer (i.e., the first character of the string).
* The buffer pointed to by `nbuf' must have length >= MAXNBUF.
*/
static char *
ksprintn(char *nbuf, uintmax_t num, int base, int *lenp, int upper)
{
char *p, c;
p = nbuf;
*p = '\0';
do {
c = hex2ascii(num % base);
*++p = upper ? toupper(c) : c;
} while (num /= base);
if (lenp)
*lenp = (int)(p - nbuf);
return (p);
}
/*
* Scaled down version of printf(3).
*
* Two additional formats:
*
* The format %b is supported to decode error registers.
* Its usage is:
*
* printf("reg=%b\n", regval, "<base><arg>*");
*
* where <base> is the output base expressed as a control character, e.g.
* \10 gives octal; \20 gives hex. Each arg is a sequence of characters,
* the first of which gives the bit number to be inspected (origin 1), and
* the next characters (up to a control character, i.e. a character <= 32),
* give the name of the register. Thus:
*
* kvprintf("reg=%b\n", 3, "\10\2BITTWO\1BITONE\n");
*
* would produce output:
*
* reg=3<BITTWO,BITONE>
*
* XXX: %D -- Hexdump, takes pointer and separator string:
* ("%6D", ptr, ":") -> XX:XX:XX:XX:XX:XX
* ("%*D", len, ptr, " " -> XX XX XX XX ...
*/
static int
kvprintf(char const *fmt, void (*func)(int), void *arg, int radix, va_list ap)
{
#define PCHAR(c) {int cc=(c); if (func) (*func)(cc); else *d++ = cc; retval++; }
char nbuf[MAXNBUF];
char *d;
const char *p, *percent, *q;
unsigned char *up;
int ch, n;
uintmax_t num;
int base, lflag, qflag, tmp, width, ladjust, sharpflag, neg, sign, dot;
int cflag, hflag, jflag, tflag, zflag;
int dwidth, upper;
char padc;
int stop = 0, retval = 0;
num = 0;
if (!func)
d = (char *) arg;
else
d = NULL;
if (fmt == NULL)
fmt = "(fmt null)\n";
if (radix < 2 || radix > 36)
radix = 10;
for (;;) {
padc = ' ';
width = 0;
while ((ch = (unsigned char)*fmt++) != '%' || stop) {
if (ch == '\0')
return (retval);
PCHAR(ch);
}
percent = fmt - 1;
qflag = 0; lflag = 0; ladjust = 0; sharpflag = 0; neg = 0;
sign = 0; dot = 0; dwidth = 0; upper = 0;
cflag = 0; hflag = 0; jflag = 0; tflag = 0; zflag = 0;
reswitch: switch (ch = (unsigned char)*fmt++) {
case '.':
dot = 1;
goto reswitch;
case '#':
sharpflag = 1;
goto reswitch;
case '+':
sign = 1;
goto reswitch;
case '-':
ladjust = 1;
goto reswitch;
case '%':
PCHAR(ch);
break;
case '*':
if (!dot) {
width = va_arg(ap, int);
if (width < 0) {
ladjust = !ladjust;
width = -width;
}
} else {
dwidth = va_arg(ap, int);
}
goto reswitch;
case '0':
if (!dot) {
padc = '0';
goto reswitch;
}
case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
for (n = 0;; ++fmt) {
n = n * 10 + ch - '0';
ch = *fmt;
if (ch < '0' || ch > '9')
break;
}
if (dot)
dwidth = n;
else
width = n;
goto reswitch;
case 'b':
num = (unsigned int)va_arg(ap, int);
p = va_arg(ap, char *);
for (q = ksprintn(nbuf, num, *p++, NULL, 0); *q;)
PCHAR(*q--);
if (num == 0)
break;
for (tmp = 0; *p;) {
n = *p++;
if (num & (1 << (n - 1))) {
PCHAR(tmp ? ',' : '<');
for (; (n = *p) > ' '; ++p)
PCHAR(n);
tmp = 1;
} else
for (; *p > ' '; ++p)
continue;
}
if (tmp)
PCHAR('>');
break;
case 'c':
PCHAR(va_arg(ap, int));
break;
case 'D':
up = va_arg(ap, unsigned char *);
p = va_arg(ap, char *);
if (!width)
width = 16;
while(width--) {
PCHAR(hex2ascii(*up >> 4));
PCHAR(hex2ascii(*up & 0x0f));
up++;
if (width)
for (q=p;*q;q++)
PCHAR(*q);
}
break;
case 'd':
case 'i':
base = 10;
sign = 1;
goto handle_sign;
case 'h':
if (hflag) {
hflag = 0;
cflag = 1;
} else
hflag = 1;
goto reswitch;
case 'j':
jflag = 1;
goto reswitch;
case 'l':
if (lflag) {
lflag = 0;
qflag = 1;
} else
lflag = 1;
goto reswitch;
case 'n':
if (jflag)
*(va_arg(ap, intmax_t *)) = retval;
else if (qflag)
*(va_arg(ap, int64_t *)) = retval;
else if (lflag)
*(va_arg(ap, long *)) = retval;
else if (zflag)
*(va_arg(ap, size_t *)) = retval;
else if (hflag)
*(va_arg(ap, short *)) = retval;
else if (cflag)
*(va_arg(ap, char *)) = retval;
else
*(va_arg(ap, int *)) = retval;
break;
case 'o':
base = 8;
goto handle_nosign;
case 'p':
base = 16;
sharpflag = (width == 0);
sign = 0;
num = (uintptr_t)va_arg(ap, void *);
goto number;
case 'q':
qflag = 1;
goto reswitch;
case 'r':
base = radix;
if (sign)
goto handle_sign;
goto handle_nosign;
case 's':
p = va_arg(ap, char *);
if (p == NULL)
p = "(null)";
if (!dot)
n = (int)strlen (p);
else
for (n = 0; n < dwidth && p[n]; n++)
continue;
width -= n;
if (!ladjust && width > 0)
while (width--)
PCHAR(padc);
while (n--)
PCHAR(*p++);
if (ladjust && width > 0)
while (width--)
PCHAR(padc);
break;
case 't':
tflag = 1;
goto reswitch;
case 'u':
base = 10;
goto handle_nosign;
case 'X':
upper = 1;
case 'x':
base = 16;
goto handle_nosign;
case 'y':
base = 16;
sign = 1;
goto handle_sign;
case 'z':
zflag = 1;
goto reswitch;
handle_nosign:
sign = 0;
if (jflag)
num = va_arg(ap, uintmax_t);
else if (qflag)
num = va_arg(ap, uint64_t);
else if (tflag)
num = va_arg(ap, ptrdiff_t);
else if (lflag)
num = va_arg(ap, unsigned long);
else if (zflag)
num = va_arg(ap, size_t);
else if (hflag)
num = (unsigned short)va_arg(ap, int);
else if (cflag)
num = (unsigned char)va_arg(ap, int);
else
num = va_arg(ap, unsigned int);
goto number;
handle_sign:
if (jflag)
num = va_arg(ap, intmax_t);
else if (qflag)
num = va_arg(ap, int64_t);
else if (tflag)
num = va_arg(ap, ptrdiff_t);
else if (lflag)
num = va_arg(ap, long);
else if (zflag)
num = va_arg(ap, ssize_t);
else if (hflag)
num = (short)va_arg(ap, int);
else if (cflag)
num = (char)va_arg(ap, int);
else
num = va_arg(ap, int);
number:
if (sign && (intmax_t)num < 0) {
neg = 1;
num = -(intmax_t)num;
}
p = ksprintn(nbuf, num, base, &n, upper);
tmp = 0;
if (sharpflag && num != 0) {
if (base == 8)
tmp++;
else if (base == 16)
tmp += 2;
}
if (neg)
tmp++;
if (!ladjust && padc == '0')
dwidth = width - tmp;
width -= tmp + imax(dwidth, n);
dwidth -= n;
if (!ladjust)
while (width-- > 0)
PCHAR(' ');
if (neg)
PCHAR('-');
if (sharpflag && num != 0) {
if (base == 8) {
PCHAR('0');
} else if (base == 16) {
PCHAR('0');
PCHAR('x');
}
}
while (dwidth-- > 0)
PCHAR('0');
while (*p)
PCHAR(*p--);
if (ladjust)
while (width-- > 0)
PCHAR(' ');
break;
default:
while (percent < fmt)
PCHAR(*percent++);
/*
* Since we ignore an formatting argument it is no
* longer safe to obey the remaining formatting
* arguments as the arguments will no longer match
* the format specs.
*/
stop = 1;
break;
}
}
#undef PCHAR
}
#else /* defined(USE_ELF) */ #else /* defined(USE_ELF) */
#error not supported #error not supported
#endif #endif

1137
array.c

File diff suppressed because it is too large Load diff

View file

@ -1,617 +0,0 @@
# -*- makefile -*-
SHELL = $(COMSPEC)
MKFILES = Makefile
!ifndef MFLAGS
MFLAGS=-
!endif
#### Start of system configuration section. ####
!ifndef OS
OS = bccwin32
!endif
!if !defined(RT)
!error RT not defined. Retry from configure pass.
!endif
arch = $(ARCH)-$(OS)
## variables may be overridden by $(compile_dir)/Makefile
!ifndef srcdir
srcdir = ..
!endif
!ifndef RUBY_INSTALL_NAME
RUBY_INSTALL_NAME = ruby
!endif
!ifndef RUBYW_INSTALL_NAME
RUBYW_INSTALL_NAME = $(RUBY_INSTALL_NAME:ruby=rubyw)
!elif "$(RUBYW_INSTALL_NAME)" == "$(RUBY_INSTALL_NAME)"
RUBYW_INSTALL_NAME = $(RUBY_INSTALL_NAME:ruby=rubyw)
!endif
!if "$(RUBYW_INSTALL_NAME)" == "$(RUBY_INSTALL_NAME)"
RUBYW_INSTALL_NAME = $(RUBY_INSTALL_NAME)w
!endif
!ifndef RUBY_SO_NAME
RUBY_SO_NAME = $(RT)-$(RUBY_INSTALL_NAME)$(MAJOR)$(MINOR)$(TEENY)
!endif
!ifndef icondirs
!ifdef ICONDIRS
icondirs=$(ICONDIRS)
!endif
!endif
!ifdef icondirs
icondirs=$(icondirs:\=/)
iconinc=-I$(icondirs: = -I)
!endif
###############
.SUFFIXES: .y
!ifndef CC
CC = bcc32
!endif
!ifndef CPP
CPP = cpp32
!endif
!ifndef RC
RC = brcc32
!endif
!ifndef YACC
YACC = bison
!endif
!ifndef AR
AR = tlib
!endif
!ifndef BASERUBY
BASERUBY = ruby
!endif
PURIFY =
AUTOCONF = autoconf
IFCHANGE = $(srcdir:/=\)\win32\ifchange.bat
RM = $(srcdir:/=\)\win32\rm.bat
CP = copy > nul
MV = move > nul
!if !defined(PROCESSOR_ARCHITECTURE)
PROCESSOR_ARCHITECTURE = x86
!endif
MACHINE = $(PROCESSOR_ARCHITECTURE)
!if "$(PROCESSOR_ARCHITECTURE)" == "x86"
!ifndef PROCESSOR_LEVEL
PROCESSOR_LEVEL = 5
!endif
!if 6 < $(PROCESSOR_LEVEL)
PROCESSOR_LEVEL = 6
!endif
PROCESSOR_FLAG = -$(PROCESSOR_LEVEL)
CPU = i$(PROCESSOR_LEVEL)86
ARCH = i386
!else
CPU = $(PROCESSOR_ARCHITECTURE)
ARCH = $(PROCESSOR_ARCHITECTURE)
!endif
!ifndef DEBUGFLAGS
DEBUGFLAGS =
!endif
!ifndef OPTFLAGS
OPTFLAGS = -O
!endif
!ifndef prefix
prefix = /usr
!endif
!ifndef exec_prefix
exec_prefix = $(prefix)
!endif
!ifndef libdir
libdir = $(exec_prefix)/lib
!endif
!if !defined(datadir)
datadir = $(prefix)/share
!endif
!ifndef EXTOUT
EXTOUT = .ext
!endif
!ifndef TESTUI
TESTUI = console
!endif
!ifndef TESTS
TESTS =
!endif
!ifndef RDOCTARGET
RDOCTARGET = install-doc
!endif
OUTFLAG = -o
COUTFLAG = -o
!ifndef CFLAGS
CFLAGS = -q -tWR -tWC $(DEBUGFLAGS) $(OPTFLAGS) $(PROCESSOR_FLAG) -w- -wsus -wcpt -wdup -wext -wrng -wrpt -wzdi
!endif
!ifndef DEFS
DEFS =
!endif
!ifndef CPPFLAGS
CPPFLAGS =
!endif
CPPFLAGS = $(DEFS) $(CPPFLAGS)
!ifndef CXXFLAGS
CXXFLAGS = $(CFLAGS)
!endif
!ifndef LDFLAGS
LDFLAGS = -S:$(STACK)
!endif
!ifndef RFLAGS
RFLAGS = $(iconinc)
!endif
!ifndef EXTLIBS
EXTLIBS =
!endif
!ifndef MEMLIB
MEMLIB =
!endif
LIBS = $(MEMLIB) cw32i.lib import32.lib ws2_32.lib $(EXTLIBS)
MISSING = acosh.obj cbrt.obj crypt.obj erf.obj lgamma_r.obj strlcat.obj strlcpy.obj tgamma.obj win32.obj
!ifndef STACK
STACK = 0x2000000
!endif
XCFLAGS = -DRUBY_EXPORT -I. -I$(arch_hdrdir) -I$(hdrdir) -I$(srcdir) -I$(srcdir)/missing
ARFLAGS = /a /p32
LD = ilink32 -q -Gn
LDSHARED = $(LD)
XLDFLAGS = -Tpe c0x32.obj
WLDFLAGS = -aa -Tpe c0w32.obj
DLDFLAGS = -Tpd c0d32.obj
LIBRUBY_LDSHARED = $(LDSHARED)
LIBRUBY_DLDFLAGS = -Gi $(DLDFLAGS) $(EXTLDFLAGS)
LDOBJECTS = $(MAINOBJ)
SOLIBS =
EXEEXT = .exe
PROGRAM=$(RUBY_INSTALL_NAME)$(EXEEXT)
WPROGRAM=$(RUBYW_INSTALL_NAME)$(EXEEXT)
RUBYDEF = $(RUBY_SO_NAME).def
MINIRUBY = .\miniruby$(EXEEXT) -I$(srcdir)/lib $(MINIRUBYOPT)
RUNRUBY = .\$(PROGRAM) -i"$(EXTOUT)/$(arch)" "$(srcdir)/runruby.rb" --extout="$(EXTOUT)" --
ORGLIBPATH = $(LIB)
#### End of system configuration section. ####
LIBRUBY_A = $(RUBY_SO_NAME)-static.lib
LIBRUBY_SO = $(RUBY_SO_NAME).dll
LIBRUBY = $(RUBY_SO_NAME).lib
LIBRUBYARG = $(LIBRUBY)
THREAD_MODEL = win32
PREP = miniruby$(EXEEXT)
OBJEXT = obj
ASMEXT = asm
INSTALLED_LIST= .installed.list
MKMAIN_CMD = mkmain.bat
SRC_FILE = $(<:\=/)
WINMAINOBJ = winmain.$(OBJEXT)
ARCHMINIOBJS = dmydln.$(OBJEXT)
arch_hdrdir = $(EXTOUT)/include/$(arch)
hdrdir = $(srcdir)/include
VPATH = $(arch_hdrdir)/ruby;$(hdrdir)/ruby;$(srcdir);$(srcdir)/enc;$(srcdir)/missing;$(srcdir)/win32
.path.c = .;$(srcdir);$(srcdir)/enc;$(srcdir)/win32;$(srcdir)/missing
.path.ci = $(srcdir)
.path.inc = .;$(srcdir)
.path.def = .;$(srcdir)
.path.h = .;$(arch_hdrdir)/ruby;$(hdrdir)/ruby;$(srcdir);$(srcdir)/win32;$(srcdir)/missing
.path.y = $(srcdir)
.path. = $(srcdir)
.c.obj:
$(CC) $(CFLAGS) $(XCFLAGS) -I. $(CPPFLAGS) $(COUTFLAG)$@ -c $(<:/=\)
.c.asm:
$(CC) $(CFLAGS) $(XCFLAGS) -I. $(CPPFLAGS) $(COUTFLAG)$@ -S $(<:\=/)
.rc.res:
$(RC) $(RFLAGS) -I. -I$(<D). $(iconinc) -I$(srcdir)/win32 $(RFLAGS) -fo$@ $(<:/=\)
all: $(srcdir)/bcc32/Makefile.sub $(srcdir)/common.mk
ruby: $(PROGRAM)
rubyw: $(WPROGRAM)
!include $(srcdir)/common.mk
$(MKFILES): $(srcdir)/bcc32/Makefile.sub $(srcdir)/bcc32/configure.bat $(srcdir)/bcc32/setup.mak
$(COMSPEC) /C $(srcdir:/=\)\bcc32\configure.bat $(configure_args)
@echo $(MKFILES) should be updated, re-run $(MAKE).
@$(MAKE) > nul -q -f &&|
PHONY: nul
@exit
|
PHONY: nul
RUBY_CONFIG_H = $(arch_hdrdir)/ruby/config.h
CONFIG_H = ./.config.h.time
config: config.status
config.status: $(CONFIG_H)
guard = INCLUDE_RUBY_CONFIG_H
$(CONFIG_H): $(MKFILES) $(srcdir)/bcc32/Makefile.sub
@if not exist $(arch_hdrdir:/=\) md $(arch_hdrdir:/=\)
@if not exist $(arch_hdrdir:/=\)\ruby md $(arch_hdrdir:/=\)\ruby
@$(IFCHANGE) $(RUBY_CONFIG_H:/=\) &&|
\#ifndef $(guard)
\#define $(guard) 1
\#define NO_BIG_INLINE 1
\#define HAVE_SYS_TYPES_H 1
\#define HAVE_SYS_STAT_H 1
\#define HAVE_STDLIB_H 1
\#define HAVE_STRING_H 1
\#define HAVE_MEMORY_H 1
\#define HAVE_LONG_LONG 1
\#define HAVE_OFF_T 1
\#define SIZEOF_INT 4
\#define SIZEOF_SHORT 2
\#define SIZEOF_LONG 4
\#define SIZEOF_LONG_LONG 0
\#define SIZEOF___INT64 8
\#define SIZEOF_OFF_T 8
\#define SIZEOF_VOIDP 4
\#define SIZEOF_FLOAT 4
\#define SIZEOF_DOUBLE 8
\#define SIZEOF_TIME_T 4
\#define SIZEOF_RLIM_T 0
\#define SIZEOF_SIZE_T 4
\#define SIZEOF_PTRDIFF_T 4
\#define HAVE_PROTOTYPES 1
\#define TOKEN_PASTE(x,y) x\#\#y
\#define HAVE_STDARG_PROTOTYPES 1
\#define NORETURN(x) x
\#define RUBY_EXTERN extern __declspec(dllimport)
\#define HAVE_DECL_SYS_NERR 1
\#define HAVE_LIMITS_H 1
\#define HAVE_FCNTL_H 1
\#define HAVE_UTIME_H 1
\#define HAVE_FLOAT_H 1
\#define rb_uid_t uid_t
\#define rb_gid_t gid_t
\#define rb_pid_t int
\#define HAVE_STRUCT_STAT_ST_RDEV 1
\#define HAVE_ST_RDEV 1
!if $(BORLANDC) < 0x0580
\#define int8_t signed char
\#define uint8_t unsigned char
\#define int16_t short
\#define uint16_t unsigned short
\#define int32_t int
\#define uint32_t unsigned int
\#define int64_t __int64
\#define uint64_t unsigned __int64
\#define ssize_t int
!endif
\#define HAVE_INT8_T 1
\#define HAVE_UINT8_T 1
\#define SIZEOF_INT8_T 1
\#define HAVE_INT16_T 1
\#define HAVE_UINT16_T 1
\#define SIZEOF_INT32_T 2
\#define HAVE_INT32_T 1
\#define HAVE_UINT32_T 1
\#define SIZEOF_INT32_T 4
\#define HAVE_INT64_T 1
\#define HAVE_UINT64_T 1
\#define SIZEOF_INT64_T 8
\#define HAVE_INTPTR_T 1
\#define HAVE_UINTPTR_T 1
\#define HAVE_SSIZE_T 1
\#define GETGROUPS_T int
\#define RETSIGTYPE void
\#define HAVE_ALLOCA 1
\#define HAVE_DUP2 1
\#define HAVE_MEMMOVE 1
\#define HAVE_MKDIR 1
\#define HAVE_STRCASECMP 1
\#define HAVE_STRNCASECMP 1
\#define HAVE_STRERROR 1
\#define HAVE_STRFTIME 1
\#define HAVE_STRCHR 1
\#define HAVE_STRSTR 1
\#define HAVE_STRTOD 1
\#define HAVE_STRTOL 1
\#define HAVE_STRTOUL 1
\#define HAVE_SNPRINTF 1
\#define HAVE_VSNPRINTF 1
\#define HAVE_ISNAN 1
\#define HAVE_FINITE 1
\#define HAVE_HYPOT 1
\#define HAVE_FMOD 1
\#define HAVE_WAITPID 1
\#define HAVE_FSYNC 1
\#define HAVE_GETCWD 1
\#define HAVE_TRUNCATE 1
\#define HAVE_FTRUNCATE 1
\#define HAVE_FSEEKO 1
\#define HAVE_FTELLO 1
\#define HAVE_TIMES 1
\#define HAVE_FCNTL 1
\#define HAVE_LINK 1
\#define HAVE_TELLDIR 1
\#define HAVE_SEEKDIR 1
\#define HAVE_COSH 1
\#define HAVE_SINH 1
\#define HAVE_TANH 1
\#define RSHIFT(x,y) ((x)>>(int)y)
\#define FILE_COUNT level
\#define FILE_READPTR curp
\#define RUBY_SETJMP(env) setjmp(env)
\#define RUBY_LONGJMP(env,val) longjmp(env,val)
\#define RUBY_JMP_BUF jmp_buf
\#define inline __inline
\#define NEED_IO_SEEK_BETWEEN_RW 1
\#define STACK_GROW_DIRECTION -1
\#define DEFAULT_KCODE KCODE_NONE
\#define LOAD_RELATIVE 1
\#define DLEXT ".so"
\#define RUBY_LIB_PREFIX "/lib/ruby"
\#define RUBY_PLATFORM "$(ARCH)-$(OS)"
\#endif /* $(guard) */
|
@exit > $(@:/=\)
config.status: $(MKFILES) $(srcdir)/bcc32/Makefile.sub $(srcdir)/common.mk
@echo Creating $@
@type > $@ &&|
# Generated automatically by Makefile.sub.
s,@SHELL@,$$(COMSPEC),;t t
s,@BUILD_FILE_SEPARATOR@,\,;t t
s,@PATH_SEPARATOR@,;,;t t
s,@CFLAGS@,$(CFLAGS),;t t
s,@DEFS@,$(DEFS),;t t
s,@CPPFLAGS@,$(CPPFLAGS),;t t
s,@CXXFLAGS@,$(CXXFLAGS),;t t
s,@FFLAGS@,$(FFLAGS),;t t
s,@LDFLAGS@,,;t t
s,@LIBS@,$(LIBS),;t t
s,@exec_prefix@,$${prefix},;t t
s,@prefix@,$(prefix),;t t
s,@program_transform_name@,s,,,,;t t
s,@bindir@,$${exec_prefix}/bin,;t t
s,@sbindir@,$${exec_prefix}/sbin,;t t
s,@libexecdir@,$${exec_prefix}/libexec,;t t
s,@datadir@,$${prefix}/share,;t t
s,@sysconfdir@,$${prefix}/etc,;t t
s,@sharedstatedir@,/etc,;t t
s,@localstatedir@,/var,;t t
s,@libdir@,$${exec_prefix}/lib,;t t
s,@includedir@,$${prefix}/include,;t t
s,@oldincludedir@,/usr/include,;t t
s,@infodir@,$${prefix}/info,;t t
s,@mandir@,$${prefix}/man,;t t
s,@ridir@,$${prefix}/share/ri,;t t
s,@build@,$(CPU)-pc-$(OS),;t t
s,@build_alias@,$(CPU)-$(OS),;t t
s,@build_cpu@,$(CPU),;t t
s,@build_vendor@,pc,;t t
s,@build_os@,$(OS),;t t
s,@host@,$(CPU)-pc-$(OS),;t t
s,@host_alias@,$(CPU)-$(OS),;t t
s,@host_cpu@,$(CPU),;t t
s,@host_vendor@,pc,;t t
s,@host_os@,$(OS),;t t
s,@target@,$(ARCH)-pc-$(OS),;t t
s,@target_alias@,$(ARCH)-$(OS),;t t
s,@target_cpu@,$(ARCH),;t t
s,@target_vendor@,pc,;t t
s,@target_os@,$(OS),;t t
s,@CC@,$(CC),;t t
s,@CPP@,cpp32,;t t
s,@CXX@,$$(CC),;t t
s,@LD@,$(LD),;t t
s,@YACC@,$(YACC),;t t
s,@RANLIB@,,;t t
s,@AR@,$(AR),;t t
s,@ARFLAGS@,$(ARFLAGS) ,;t t
s,@LN_S@,$(LN_S),;t t
s,@SET_MAKE@,MFLAGS = -$$(MAKEFLAGS),;t t
s,@RM@,$$(top_srcdir:/=\)\win32\rm.bat,;t t
s,@CP@,copy > nul,;t t
s,@LIBOBJS@, $(MISSING),;t t
s,@ALLOCA@,$(ALLOCA),;t t
s,@DEFAULT_KCODE@,$(DEFAULT_KCODE),;t t
s,@EXEEXT@,.exe,;t t
s,@OBJEXT@,obj,;t t
s,@XCFLAGS@,$(XCFLAGS),;t t
s,@XLDFLAGS@,$(XLDFLAGS),;t t
s,@DLDFLAGS@,$(DLDFLAGS),;t t
s,@ARCH_FLAG@,$(ARCH_FLAG),;t t
s,@STATIC@,$(STATIC),;t t
s,@CCDLFLAGS@,,;t t
s,@LDSHARED@,$(LDSHARED),;t t
s,@DLEXT@,so,;t t
s,@LIBEXT@,lib,;t t
s,@STRIP@,$(STRIP),;t t
s,@EXTSTATIC@,$(EXTSTATIC),;t t
s,@setup@,Setup,;t t
s,@MINIRUBY@,$(MINIRUBY),;t t
s,@PREP@,miniruby$(EXEEXT),;t t
s,@RUNRUBY@,$(RUNRUBY),;t t
s,@EXTOUT@,$(EXTOUT),;t t
s,@ARCHFILE@,,;t t
s,@RDOCTARGET@,,;t t
s,@LIBRUBY_LDSHARED@,$$(LDSHARED),;t t
s,@LIBRUBY_DLDFLAGS@,-Gi $$(DLDFLAGS),;t t
s,@RUBY_INSTALL_NAME@,$(RUBY_INSTALL_NAME),;t t
s,@rubyw_install_name@,$(RUBYW_INSTALL_NAME),;t t
s,@RUBYW_INSTALL_NAME@,$(RUBYW_INSTALL_NAME),;t t
s,@RUBY_SO_NAME@,$(RUBY_SO_NAME),;t t
s,@LIBRUBY_A@,$$(RUBY_SO_NAME)-static.lib,;t t
s,@LIBRUBY_SO@,$$(RUBY_SO_NAME).dll,;t t
s,@LIBRUBY_ALIASES@,$(LIBRUBY_ALIASES),;t t
s,@LIBRUBY@,$$(RUBY_SO_NAME).lib,;t t
s,@LIBRUBYARG@,$$(LIBRUBYARG_SHARED),;t t
s,@LIBRUBYARG_STATIC@,$$(LIBRUBY_A),;t t
s,@LIBRUBYARG_SHARED@,$$(LIBRUBY),;t t
s,@SOLIBS@,$(SOLIBS),;t t
s,@DLDLIBS@,$(DLDLIBS),;t t
s,@ENABLE_SHARED@,yes,;t t
s,@OUTFLAG@,$(OUTFLAG),;t t
s,@COUTFLAG@,$(COUTFLAG),;t t
s,@CPPOUTFILE@,,;t t
s,@LIBPATHFLAG@, -L"%s",;t t
s,@RPATHFLAG@,,;t t
s,@LIBARG@,%s.lib,;t t
s,@LINK_SO@,$$(LDSHARED) $$(DLDFLAGS) $$(LIBPATH) $$(OBJS:/=\), $$(@:/=\), nul, $$(LIBS) $$(LOCAL_LIBS), $$(DEFFILE:/=\), $$(RESFILE:/=\),;t t
s,@COMPILE_C@,$$(CC) $$(INCFLAGS) $$(CFLAGS) $$(CPPFLAGS) $(COUTFLAG)$$(@) -c $$(<:/=\),;t t
s,@COMPILE_CXX@,$$(CXX) $$(INCFLAGS) $$(CXXFLAGS) $$(CPPFLAGS) -P $(COUTFLAG)$$(@) -c $$(<:/=\),;t t
s,@COMPILE_RULES@,{$$(srcdir)}.%s{}.%s: {$$(topdir)}.%s{}.%s: {$$(hdrdir)}.%s{}.%s: .%s.%s:,;t t
s,@RULE_SUBST@,{.;$$(VPATH)}%s,;t t
s,@COMMON_LIBS@,m advapi32 avicap32 avifil32 cap comctl32 comdlg32 dlcapi gdi32 glu32 imagehlp imm32 inetmib1 kernel32 loadperf lsapi32 lz32 mapi32 mgmtapi mpr msacm32 msvfw32 nddeapi netapi32 ole32 oleaut32 oledlg olepro32 opengl32 pdh pkpd32 rasapi32 rasdlg rassapi rpcrt4 setupapi shell32 shfolder snmpapi sporder tapi32 url user32 vdmdbg version win32spl winmm wintrust wsock32,;t t
s,@COMMON_MACROS@,WIN32_LEAN_AND_MEAN WIN32,;t t
s,@COMMON_HEADERS@,winsock2.h windows.h,;t t
s,@cleanlibs@,$$*.tds,;t t
s,@cleanobjs@,$$*-$$(arch).def $$*.il? $$*.lib,;t t
s,@TRY_LINK@,$$(CC) -oconftest $$(INCFLAGS) -I$$(hdrdir) $$(CPPFLAGS) $$(CFLAGS) $$(LIBPATH) $$(LDFLAGS) $$(src) $$(LOCAL_LIBS) $$(LIBS),;t t
s,@EXPORT_PREFIX@,_,;t t
s,@arch@,$(ARCH)-$(OS),;t t
s,@sitearch@,$(ARCH)-$(OS),;t t
s,@sitedir@,$${prefix}/lib/ruby/site_ruby,;t t
s,@vendordir@,$${prefix}/lib/ruby/vendor_ruby,;t t
s,@rubyhdrdir@,$$(includedir)/ruby-$$(MAJOR).$$(MINOR).$$(TEENY),;t t
s,@sitehdrdir@,$$(rubyhdrdir)/site_ruby,;t t
s,@vendorhdrdir@,$$(rubyhdrdir)/vendor_ruby,;t t
s,@configure_args@,--enable-shared $(configure_args),;t t
s,@configure_input@,$$configure_input,;t t
s,@srcdir@,$(srcdir),;t t
s,@top_srcdir@,$(srcdir),;t t
|
miniruby$(EXEEXT):
@echo $(LIBS)
$(LD) $(LDFLAGS) $(XLDFLAGS) $(MAINOBJ) $(MINIOBJS) $(COMMONOBJS:/=\) $(DMYEXT),$@,nul,$(LIBS)
$(PROGRAM): $(MAINOBJ) $(LIBRUBY_SO) $(RUBY_INSTALL_NAME).res
$(LD) $(LDFLAGS) $(XLDFLAGS) $(MAINOBJ),$@,nul,$(LIBRUBYARG) $(LIBS),,$(RUBY_INSTALL_NAME).res
$(WPROGRAM): $(MAINOBJ) $(WINMAINOBJ) $(LIBRUBY_SO) $(RUBYW_INSTALL_NAME).res
$(LD) $(LDFLAGS) $(WLDFLAGS) $(MAINOBJ) $(WINMAINOBJ),$@,nul,$(LIBRUBYARG) $(LIBS),,$(RUBYW_INSTALL_NAME).res
$(LIBRUBY_A): $(OBJS) $(DMYEXT)
@-if exist $@ del $@
$(AR) $(ARFLAGS) "$@" $(OBJS) $(DMYEXT)
# $(LIBRUBY): $(LIBRUBY_SO)
# implib $@ $(LIBRUBY_SO)
$(LIBRUBY_SO): $(LIBRUBY_A) $(DLDOBJS) $(RUBYDEF) $(RUBY_SO_NAME).res
@echo $(DLDOBJS)
@$(PRE_LIBRUBY_UPDATE)
$(LIBRUBY_LDSHARED) $(LIBRUBY_DLDFLAGS) $(DLDOBJS:/=\),$(LIBRUBY_SO),nul,$(LIBRUBY_A) $(LIBS),$(RUBYDEF),$(RUBY_SO_NAME).res
$(LIBRUBY): $(LIBRUBY_SO)
$(RUBYDEF): $(LIBRUBY_A) $(PREP)
$(MINIRUBY) $(srcdir)/bcc32/mkexports.rb -output=$@ -base=$(RUBY_SO_NAME) $(LIBRUBY_A)
$(RUBY_INSTALL_NAME).rc $(RUBYW_INSTALL_NAME).rc $(RUBY_SO_NAME).rc: rbconfig.rb $(srcdir)/revision.h $(srcdir)/win32/resource.rb
@$(MINIRUBY) $(srcdir)/win32/resource.rb \
-ruby_name=$(RUBY_INSTALL_NAME) \
-rubyw_name=$(RUBYW_INSTALL_NAME) \
-so_name=$(RUBY_SO_NAME) \
. $(icondirs) $(srcdir)/win32
lex.c: {$(srcdir)}lex.c.blt
copy "$(?:/=\)" $@
post-install-bin::
@$(NULLCMD)
post-install-lib::
@$(NULLCMD)
post-install-ext-comm::
@$(NULLCMD)
post-install-ext-arch::
@$(NULLCMD)
post-install-man::
@$(NULLCMD)
post-install-doc::
@$(NULLCMD)
clean-local::
@$(RM) $(WINMAINOBJ) ext\extinit.c ext\extinit.$(OBJEXT) *.tds *.il? $(RUBY_SO_NAME).lib
@$(RM) $(RUBY_INSTALL_NAME).res $(RUBYW_INSTALL_NAME).res $(RUBY_SO_NAME).res
@$(RM) *.map *.pdb *.ilk *.exp $(RUBYDEF) ext\ripper\y.output
distclean-local::
@$(RM) ext\config.cache $(RBCONFIG:/=\)
@$(RM) $(RUBY_INSTALL_NAME).rc $(RUBYW_INSTALL_NAME).rc $(RUBY_SO_NAME).rc
clean-ext distclean-ext realclean-ext::
@for /R ext %I in (.) do @if exist %I\Makefile ( \
echo $(@:-ext=)ing %~nI & \
cd %I & \
$(MAKE) $(MFLAGS) $(@:-ext=) & \
cd %CD% \
)
ext/extinit.obj: ext/extinit.c $(SETUP)
$(CC) $(CFLAGS) $(XCFLAGS) $(CPPFLAGS) $(COUTFLAG)$@ -c ext/extinit.c
main.$(OBJEXT): win32.h
ascii.$(OBJEXT): win32.h
array.$(OBJEXT): win32.h
bignum.$(OBJEXT): win32.h
class.$(OBJEXT): win32.h
compar.$(OBJEXT): win32.h
dir.$(OBJEXT): dir.h win32.h
dln.$(OBJEXT): win32.h
enum.$(OBJEXT): win32.h
error.$(OBJEXT): win32.h
euc_jp.$(OBJEXT): win32.h
eval.$(OBJEXT): win32.h
file.$(OBJEXT): win32.h
gc.$(OBJEXT): win32.h
hash.$(OBJEXT): win32.h
inits.$(OBJEXT): win32.h
io.$(OBJEXT): win32.h
marshal.$(OBJEXT): win32.h
math.$(OBJEXT): win32.h
numeric.$(OBJEXT): win32.h
object.$(OBJEXT): win32.h
pack.$(OBJEXT): win32.h
parse.$(OBJEXT): win32.h
process.$(OBJEXT): win32.h
prec.$(OBJEXT): win32.h
random.$(OBJEXT): win32.h
range.$(OBJEXT): win32.h
re.$(OBJEXT): win32.h
regcomp.$(OBJEXT): win32.h
regenc.$(OBJEXT): win32.h
regerror.$(OBJEXT): win32.h
regexec.$(OBJEXT): win32.h
reggnu.$(OBJEXT): win32.h
regparse.$(OBJEXT): win32.h
ruby.$(OBJEXT): win32.h
signal.$(OBJEXT): win32.h
sjis.$(OBJEXT): win32.h
sprintf.$(OBJEXT): win32.h
st.$(OBJEXT): win32.h
string.$(OBJEXT): win32.h
struct.$(OBJEXT): win32.h
time.$(OBJEXT): win32.h
utf_8.$(OBJEXT): win32.h
util.$(OBJEXT): win32.h
variable.$(OBJEXT): win32.h
version.$(OBJEXT): win32.h

View file

@ -1,130 +0,0 @@
=begin
= How to build ruby using Borland C++
== Requirement
(1) Borland C++ 5.0 or later.
(2) Please set environment variable (({PATH}))
to run required commands properly from the command line.
Note: building ruby requires following commands.
* make
* bcc32
* tlib
* ilink32
(3) If you want to build from CVS source, following commands are required.
* bison ((<URL:http://gnuwin32.sourceforge.net/packages/bison.htm>))
* sed ((<URL:http://gnuwin32.sourceforge.net/packages/sed.htm>))
(4) We strongly recommend to build ruby on C++Builder, to link following files.
* usebormm.lib
* memmgr.lib
RTL's internal memory manager cannot handle large memory block properly,
so we should use borlndmm.dll instead.
10000.times { "" << "." * 529671; GC.start } # crash
== How to compile and install
(1) Execute bcc32\configure.bat on your build directory.
ex. c:\src\ruby> bcc32\configure.bat
You can specify the target platform as an argument.
For example, run `((%configure i686-bccwin32%))'
You can also specify the install directory.
For example, run `((%configure --prefix=<install_directory>%))'
Default of the install directory is /usr .
The default ((|<PLATFORM>|)) is `(({i386-bccwin32}))'.
(2) Change ((|RUBY_INSTALL_NAME|)) and ((|RUBY_SO_NAME|)) in (({Makefile}))
if you want to change the name of the executable files.
And add ((|RUBYW_INSTALL_NAME|)) to change the name of the
executable without console window if also you want.
(3) Run `((%make%))'
(4) Run `((%make test%))'
(5) Run `((%make install%))'
(6) Requires dynamic RTL (cc3250.dll on C++Builder5) and borlndmm.dll (If built with
usebormm.lib) to use installed binary. These files are ordinary in bcc32's bin
directory.
== Icons
Any icon files(*.ico) in the build directory, directories specified with
((|icondirs|)) make variable and (({win32})) directory under the ruby
source directory will be included in DLL or executable files, according
to their base names.
$(RUBY_INSTALL_NAME).ico or ruby.ico --> $(RUBY_INSTALL_NAME).exe
$(RUBYW_INSTALL_NAME).ico or rubyw.ico --> $(RUBYW_INSTALL_NAME).exe
the others --> $(RUBY_SO_NAME).dll
Although no icons are distributed with the ruby source or in the official
site, you can use anything you like. For example, followings are written
in Japanese, but you can download at least.
* ((<URL:http://member.nifty.ne.jp/ueivu/rubyico.html>)) or
((<zipped icons|URL:http://member.nifty.ne.jp/ueivu/Ruby_ico.zip>))
* ((<URL:http://homepage1.nifty.com/a_nakata/ruby/>)) or
((<icon itself|URL:http://homepage1.nifty.com/a_nakata/ruby/RubyIcon.ico>))
== Build examples
* Build on the ruby source directory.
ex.)
ruby source directory: C:\ruby
build directory: C:\ruby
install directory: C:\usr\local
C:
cd \ruby
bcc32\configure --prefix=/usr/local
make
make test
make install
* Build on the relative directory from the ruby source directory and CPU type
i386.
ex.)
ruby source directory: C:\ruby
build directory: C:\ruby\bccwin32
install directory: C:\usr\local
CPU i386
C:
cd \ruby
mkdir bccwin32
cd bccwin32
..\bcc32\configure --prefix=/usr/local
make
make test
make install
* Build on the different drive.
ex.)
ruby source directory: C:\src\ruby
build directory: D:\build\ruby
install directory: C:\usr\local
D:
cd D:\build\ruby
C:\src\ruby\bcc32\configure --prefix=C:/usr/local
make
make test
make install
== Bugs
You can ((*NOT*)) use a path name contains any white space characters as
the ruby source directory, this restriction comes from the behavior of
(({!INCLUDE})) directives of (({MAKE})).
((- you may call it a bug. -))
=end

View file

@ -1,163 +0,0 @@
@echo off
::: Don't set environment variable in batch file other than autoexec.bat
::: to avoid "Out of environment space" problem on Windows 95/98.
::: set TMPMAKE=~tmp~.mak
echo> ~tmp~.mak ####
echo>> ~tmp~.mak conf = %0
echo>> ~tmp~.mak $(conf:\=/): nul
echo>> ~tmp~.mak @del ~setup~.mak
echo>> ~tmp~.mak @-$(MAKE) -l$(MAKEFLAGS) -f $(@D)setup.mak \
if exist pathlist.tmp del pathlist.tmp
if exist confargs.mk del confargs.mk
:loop
if "%1" == "" goto :end
if "%1" == "--prefix" goto :prefix
if "%1" == "prefix" goto :prefix
if "%1" == "--srcdir" goto :srcdir
if "%1" == "srcdir" goto :srcdir
if "%1" == "--target" goto :target
if "%1" == "target" goto :target
if "%1" == "--with-static-linked-ext" goto :extstatic
if "%1" == "--program-suffix" goto :suffix
if "%1" == "RUBY_SUFFIX" goto :suffix
if "%1" == "--program-name" goto :installname
if "%1" == "--install-name" goto :installname
if "%1" == "RUBY_INSTALL_NAME" goto :installname
if "%1" == "--so-name" goto :soname
if "%1" == "RUBY_SO_NAME" goto :soname
if "%1" == "--enable-install-doc" goto :enable-rdoc
if "%1" == "--disable-install-doc" goto :disable-rdoc
if "%1" == "--extout" goto :extout
if "%1" == "EXTOUT" goto :extout
if "%1" == "--with-baseruby" goto :baseruby
if "%1" == "BASERUBY" goto :baseruby
if "%1" == "--path" goto :path
if "%1" == "-h" goto :help
if "%1" == "--help" goto :help
echo>>confargs.tmp %1 \
shift
goto :loop
:srcdir
echo>> ~tmp~.mak -Dsrcdir=%2 \
echo>>confargs.tmp --srcdir=%2 \
shift
shift
goto :loop
:prefix
echo>> ~tmp~.mak -Dprefix=%2 \
echo>>confargs.tmp %1=%2 \
shift
shift
goto :loop
:suffix
echo>>confargs.mk !ifndef RUBY_SUFFIX
echo>>confargs.mk RUBY_SUFFIX = %2
echo>>confargs.mk !endif
echo>>confargs.tmp %1=%2 \
shift
shift
goto :loop
:installname
echo>>confargs.mk !ifndef RUBY_INSTALL_NAME
echo>>confargs.mk RUBY_INSTALL_NAME = %2
echo>>confargs.mk !endif
echo>>confargs.tmp %1=%2 \
shift
shift
goto :loop
:soname
echo>>confargs.mk !ifndef RUBY_SO_NAME
echo>>confargs.mk RUBY_SO_NAME = %2
echo>>confargs.mk !endif
echo>>confargs.tmp %1=%2 \
shift
shift
goto :loop
:target
echo>> ~tmp~.mak %2 \
echo>>confargs.tmp --target=%2 \
shift
shift
goto :loop
:extstatic
echo>>confargs.mk !ifndef EXTSTATIC
echo>>confargs.mk EXTSTATIC = static
echo>>confargs.mk !endif
echo>>confargs.tmp %1 \
shift
goto :loop
:enable-rdoc
echo>>confargs.mk !ifndef RDOCTARGET
echo>>confargs.mk RDOCTARGET = install-doc
echo>>confargs.mk !endif
echo>>confargs.tmp %1 \
shift
goto :loop
:disable-rdoc
echo>>confargs.mk !ifndef RDOCTARGET
echo>>confargs.mk RDOCTARGET = install-nodoc
echo>>confargs.mk !endif
echo>>confargs.tmp %1 \
shift
goto :loop
:extout
echo>>confargs.mk !ifndef EXTOUT
echo>>confargs.mk EXTOUT = %2
echo>>confargs.mk !endif
echo>>confargs.tmp %1=%2 \
shift
shift
goto :loop
:baseruby
echo>>confargs.mk !ifndef BASERUBY
echo>>confargs.mk BASERUBY = %2
echo>>confargs.mk !endif
echo>>confargs.tmp %1=%2 \
shift
shift
goto :loop
:path
echo>>pathlist.tmp %2;\
echo>>confargs.tmp %1=%2 \
shift
shift
goto :loop
:help
echo Configuration:
echo --help display this help
echo --srcdir=DIR find the sources in DIR [configure dir or `..']
echo Installation directories:
echo --prefix=PREFIX install files in PREFIX (ignored currently)
echo System types:
echo --target=TARGET configure for TARGET [i386-bccwin32]
echo Optional Package:
echo --with-baseruby=RUBY use RUBY as baseruby [ruby]
echo --with-static-linked-ext link external modules statically
echo --enable-install-doc install rdoc indexes during install
del *.tmp
del ~tmp~.mak
goto :exit
:end
echo>> ~tmp~.mak -Dbcc32dir=$(@D)
if not exist confargs.tmp goto :noconfargs
echo>>confargs.mk configure_args = \
type>>confargs.mk confargs.tmp
echo.>>confargs.mk
echo>>confargs.mk ####
:noconfargs
if not exist pathlist.tmp goto :nopathlist
echo>>confargs.mk pathlist = \
type>>confargs.mk pathlist.tmp
echo.>>confargs.mk
echo>>confargs.mk ####
echo>>confargs.mk PATH = $(pathlist:;=/bin;)$(PATH)
echo>>confargs.mk INCLUDE = $(pathlist:;=/include;)
echo>>confargs.mk LIB = $(pathlist:;=/lib;)
:nopathlist
if exist confargs.mk copy confargs.mk ~setup~.mak > nul
type>>~setup~.mak ~tmp~.mak
del *.tmp > nul
del ~tmp~.mak > nul
make -s -f ~setup~.mak
:exit

View file

@ -1,26 +0,0 @@
#!./miniruby -s
$:.unshift(File.expand_path("../..", __FILE__))
require 'win32/mkexports'
class Exports::Bcc < Exports
def forwarding(internal, export)
internal[/\A_?/]+export
end
def each_line(objs, &block)
objs.each do |obj|
opt = /\.(?:so|dll)\z/i =~ obj ? "-ee" : "-oiPUBDEF -oiPUBD32"
IO.foreach("|tdump -q #{opt} #{obj.tr('/', '\\')} < nul", &block)
end
end
def each_export(objs)
objdump(objs) do |l|
next unless /(?:PUBDEF|PUBD32|EXPORT)/ =~ l
yield $1 if /'(.*?)'/ =~ l
end
yield "_strcasecmp", "_stricmp"
yield "_strncasecmp", "_strnicmp"
end
end

View file

@ -1,179 +0,0 @@
# -*- makefile -*-
!if "$(srcdir)" != ""
bcc32dir = $(srcdir)/bcc32
!elseif "$(bcc32dir)" == "bcc32/"
srcdir = .
!elseif "$(bcc32dir:/bcc32/=)/bcc32/" == "$(bcc32dir)"
srcdir = $(bcc32dir:/bcc32/=)
!else
srcdir = $(bcc32dir)/..
!endif
!ifndef prefix
prefix = /usr
!endif
OS = bccwin32
RT = $(OS)
BANG = !
APPEND = echo.>>$(MAKEFILE)
!ifdef MAKEFILE
MAKE = $(MAKE) -f $(MAKEFILE)
!else
MAKEFILE = Makefile
!endif
all: Makefile
Makefile: -prologue- -generic- -epilogue-
i386-$(OS): -prologue- -i386- -epilogue-
i486-$(OS): -prologue- -i486- -epilogue-
i586-$(OS): -prologue- -i586- -epilogue-
i686-$(OS): -prologue- -i686- -epilogue-
alpha-$(OS): -prologue- -alpha- -epilogue-
-prologue-: -basic-vars- -version- -system-vars-
-basic-vars-: nul
@echo Creating $(MAKEFILE)
@type > $(MAKEFILE) &&|
\#\#\# Makefile for ruby $(OS) \#\#\#
$(BANG)ifndef srcdir
srcdir = $(srcdir:\=/)
$(BANG)endif
$(BANG)ifndef prefix
prefix = $(prefix:\=/)
$(BANG)endif
$(BANG)if !defined(BASERUBY)
!if defined(BASERUBY)
BASERUBY = $(BASERUBY)
!endif
|
!if !defined(BASERUBY)
@for %I in (ruby.exe) do @echo BASERUBY = "%~$$PATH:I" >> $(MAKEFILE)
!endif
@type >> $(MAKEFILE) &&|
$(BANG)endif
|
!if exist(confargs.mk)
@type confargs.mk >> $(MAKEFILE)
@del confargs.mk
!endif
-system-vars-: -runtime- -bormm-
-bormm-: nul
@-ilink32 -q -Gn -x usebormm.lib > nul
@-if exist usebormm.tds $(APPEND) MEMLIB = usebormm.lib
@if exist usebormm.* del usebormm.*
-osname-: nul
@echo OS = >>$(MAKEFILE)
-runtime-: nul
type > conftest.c &&|
\#include <stdio.h>
int main(){printf("");return 0;}
|
bcc32 conftest.c cw32i.lib > nul
tdump conftest.exe < nul > conftest.i
grep "^Imports from CC" conftest.i > conftest.c
cpp32 -P- -DFile=\# -DImports=RTNAME -Dfrom== conftest.c > nul
$(MAKE) > nul -DBANG=$(BANG) -f &&|
-runtime-: nul
$(BANG)include conftest.i
RT = $$(RTNAME:.DLL=)
OS = $$(RT:CC32=)
-runtime-:
del conftest.*
$(BANG)if "$$(OS)" == "50"
echo OS = bccwin32 >> $(MAKEFILE)
$(BANG)else
echo OS = bccwin32_$$(OS) >> $(MAKEFILE)
$(BANG)endif
|
@echo RT = $$(OS) >> $(MAKEFILE)
-version-: nul
@cpp32 -I$(srcdir) -P- -o$(MAKEFILE) > nul &&|
\#define RUBY_REVISION 0
\#include "version.h"
MAJOR = RUBY_API_VERSION_MAJOR
MINOR = RUBY_API_VERSION_MINOR
TEENY = RUBY_API_VERSION_TEENY
BORLANDC = __BORLANDC__
|
@$(MAKE) > nul -DBANG=$(BANG) -f &&,
-version-: nul
$(BANG)include $(MAKEFILE)
$(BANG)include $(MAKEFILE).i
-version-:
@del $(MAKEFILE).i
@type >> $(MAKEFILE) &&|
MAJOR = $$(MAJOR)
MINOR = $$(MINOR)
TEENY = $$(TEENY)
BORLANDC = $$(BORLANDC)
|
,
-generic-: nul
!if defined(PROCESSOR_ARCHITECTURE) || defined(PROCESSOR_LEVEL)
@type >> $(MAKEFILE) &&|
!if defined(PROCESSOR_ARCHITECTURE)
$(BANG)ifndef PROCESSOR_ARCHITECTURE
PROCESSOR_ARCHITECTURE = $(PROCESSOR_ARCHITECTURE)
$(BANG)endif
!endif
!if defined(PROCESSOR_LEVEL)
$(BANG)ifndef PROCESSOR_LEVEL
PROCESSOR_LEVEL = $(PROCESSOR_LEVEL)
$(BANG)endif
!endif
|
!endif
-alpha-: nul
@$(APPEND) !ifndef PROCESSOR_ARCHITECTURE
@$(APPEND) PROCESSOR_ARCHITECTURE = alpha
@$(APPEND) !endif
-ix86-: nul
@$(APPEND) !ifndef PROCESSOR_ARCHITECTURE
@$(APPEND) PROCESSOR_ARCHITECTURE = x86
@$(APPEND) !endif
-i386-: -ix86-
@$(APPEND) !ifndef PROCESSOR_LEVEL
@$(APPEND) PROCESSOR_LEVEL = 3
@$(APPEND) !endif
-i486-: -ix86-
@$(APPEND) !ifndef PROCESSOR_LEVEL
@$(APPEND) PROCESSOR_LEVEL = 4
@$(APPEND) !endif
-i586-: -ix86-
@$(APPEND) !ifndef PROCESSOR_LEVEL
@$(APPEND) PROCESSOR_LEVEL = 5
@$(APPEND) !endif
-i686-: -ix86-
@$(APPEND) !ifndef PROCESSOR_LEVEL
@$(APPEND) PROCESSOR_LEVEL = 6
@$(APPEND) !endif
-epilogue-: -encs-
-encs-: nul
@$(MAKE) -f $(srcdir)/win32/enc-setup.mak srcdir="$(srcdir)" MAKEFILE=$(MAKEFILE)
-epilogue-: nul
@type >> $(MAKEFILE) &&|
\# RUBY_INSTALL_NAME = ruby
\# RUBY_SO_NAME = $$(RT)-$$(RUBY_INSTALL_NAME)$$(MAJOR)$$(MINOR)
\# CFLAGS = -q $$(DEBUGFLAGS) $$(OPTFLAGS) $$(PROCESSOR_FLAG) -w- -wsus -wcpt -wdup -wext -wrng -wrpt -wzdi
\# CPPFLAGS = -I. -I$$(srcdir) -I$$(srcdir)/missing -DLIBRUBY_SO=\"$$(LIBRUBY_SO)\"
\# STACK = 0x2000000
\# LDFLAGS = -S:$$(STACK)
\# RFLAGS = $$(iconinc)
\# EXTLIBS = cw32.lib import32.lib user32.lib kernel32.lib
$(BANG)include $$(srcdir)/bcc32/Makefile.sub
|
@echo type "`$(MAKE)'" to make ruby for $(OS).

292
benchmark/bm_app_aobench.rb Normal file
View file

@ -0,0 +1,292 @@
# AO rebder benchmark
# Original program (C) Syoyo Fujita in Javascript (and other languages)
# http://lucille.atso-net.jp/blog/?p=642
# http://lucille.atso-net.jp/blog/?p=711
# Ruby(yarv2llvm) version by Hideki Miura
#
IMAGE_WIDTH = 256
IMAGE_HEIGHT = 256
NSUBSAMPLES = 2
NAO_SAMPLES = 8
class Vec
def initialize(x, y, z)
@x = x
@y = y
@z = z
end
attr_accessor :x, :y, :z
def vadd(b)
Vec.new(@x + b.x, @y + b.y, @z + b.z)
end
def vsub(b)
Vec.new(@x - b.x, @y - b.y, @z - b.z)
end
def vcross(b)
Vec.new(@y * b.z - @z * b.y,
@z * b.x - @x * b.z,
@x * b.y - @y * b.x)
end
def vdot(b)
@x * b.x + @y * b.y + @z * b.z
end
def vlength
Math.sqrt(@x * @x + @y * @y + @z * @z)
end
def vnormalize
len = vlength
v = Vec.new(@x, @y, @z)
if len > 1.0e-17 then
v.x = v.x / len
v.y = v.y / len
v.z = v.z / len
end
v
end
end
class Sphere
def initialize(center, radius)
@center = center
@radius = radius
end
attr_reader :center, :radius
def intersect(ray, isect)
rs = ray.org.vsub(@center)
b = rs.vdot(ray.dir)
c = rs.vdot(rs) - (@radius * @radius)
d = b * b - c
if d > 0.0 then
t = - b - Math.sqrt(d)
if t > 0.0 and t < isect.t then
isect.t = t
isect.hit = true
isect.pl = Vec.new(ray.org.x + ray.dir.x * t,
ray.org.y + ray.dir.y * t,
ray.org.z + ray.dir.z * t)
n = isect.pl.vsub(@center)
isect.n = n.vnormalize
else
0.0
end
end
nil
end
end
class Plane
def initialize(p, n)
@p = p
@n = n
end
def intersect(ray, isect)
d = -@p.vdot(@n)
v = ray.dir.vdot(@n)
v0 = v
if v < 0.0 then
v0 = -v
end
if v0 < 1.0e-17 then
return
end
t = -(ray.org.vdot(@n) + d) / v
if t > 0.0 and t < isect.t then
isect.hit = true
isect.t = t
isect.n = @n
isect.pl = Vec.new(ray.org.x + t * ray.dir.x,
ray.org.y + t * ray.dir.y,
ray.org.z + t * ray.dir.z)
end
nil
end
end
class Ray
def initialize(org, dir)
@org = org
@dir = dir
end
attr_accessor :org, :dir
end
class Isect
def initialize
@t = 10000000.0
@hit = false
@pl = Vec.new(0.0, 0.0, 0.0)
@n = Vec.new(0.0, 0.0, 0.0)
end
attr_accessor :t, :hit, :pl, :n
end
def clamp(f)
i = f * 255.5
if i > 255.0 then
i = 255.0
end
if i < 0.0 then
i = 0.0
end
i.to_i
end
def otherBasis(basis, n)
basis[2] = Vec.new(n.x, n.y, n.z)
basis[1] = Vec.new(0.0, 0.0, 0.0)
if n.x < 0.6 and n.x > -0.6 then
basis[1].x = 1.0
elsif n.y < 0.6 and n.y > -0.6 then
basis[1].y = 1.0
elsif n.z < 0.6 and n.z > -0.6 then
basis[1].z = 1.0
else
basis[1].x = 1.0
end
basis[0] = basis[1].vcross(basis[2])
basis[0] = basis[0].vnormalize
basis[1] = basis[2].vcross(basis[0])
basis[1] = basis[1].vnormalize
end
class Scene
def initialize
@spheres = Array.new
@spheres[0] = Sphere.new(Vec.new(-2.0, 0.0, -3.5), 0.5)
@spheres[1] = Sphere.new(Vec.new(-0.5, 0.0, -3.0), 0.5)
@spheres[2] = Sphere.new(Vec.new(1.0, 0.0, -2.2), 0.5)
@plane = Plane.new(Vec.new(0.0, -0.5, 0.0), Vec.new(0.0, 1.0, 0.0))
end
def ambient_occlusion(isect)
basis = Array.new
otherBasis(basis, isect.n)
ntheta = NAO_SAMPLES
nphi = NAO_SAMPLES
eps = 0.0001
occlusion = 0.0
p0 = Vec.new(isect.pl.x + eps * isect.n.x,
isect.pl.y + eps * isect.n.y,
isect.pl.z + eps * isect.n.z)
nphi.times do |j|
ntheta.times do |i|
r = rand
phi = 2.0 * 3.14159265 * rand
x = Math.cos(phi) * Math.sqrt(1.0 - r)
y = Math.sin(phi) * Math.sqrt(1.0 - r)
z = Math.sqrt(r)
rx = x * basis[0].x + y * basis[1].x + z * basis[2].x
ry = x * basis[0].y + y * basis[1].y + z * basis[2].y
rz = x * basis[0].z + y * basis[1].z + z * basis[2].z
raydir = Vec.new(rx, ry, rz)
ray = Ray.new(p0, raydir)
occisect = Isect.new
@spheres[0].intersect(ray, occisect)
@spheres[1].intersect(ray, occisect)
@spheres[2].intersect(ray, occisect)
@plane.intersect(ray, occisect)
if occisect.hit then
occlusion = occlusion + 1.0
else
0.0
end
end
end
occlusion = (ntheta.to_f * nphi.to_f - occlusion) / (ntheta.to_f * nphi.to_f)
Vec.new(occlusion, occlusion, occlusion)
end
def render(w, h, nsubsamples)
cnt = 0
nsf = nsubsamples.to_f
h.times do |y|
w.times do |x|
rad = Vec.new(0.0, 0.0, 0.0)
# Subsmpling
nsubsamples.times do |v|
nsubsamples.times do |u|
cnt = cnt + 1
wf = w.to_f
hf = h.to_f
xf = x.to_f
yf = y.to_f
uf = u.to_f
vf = v.to_f
px = (xf + (uf / nsf) - (wf / 2.0)) / (wf / 2.0)
py = -(yf + (vf / nsf) - (hf / 2.0)) / (hf / 2.0)
eye = Vec.new(px, py, -1.0).vnormalize
ray = Ray.new(Vec.new(0.0, 0.0, 0.0), eye)
isect = Isect.new
@spheres[0].intersect(ray, isect)
@spheres[1].intersect(ray, isect)
@spheres[2].intersect(ray, isect)
@plane.intersect(ray, isect)
if isect.hit then
col = ambient_occlusion(isect)
rad.x = rad.x + col.x
rad.y = rad.y + col.y
rad.z = rad.z + col.z
end
end
end
r = rad.x / (nsf * nsf)
g = rad.y / (nsf * nsf)
b = rad.z / (nsf * nsf)
printf("%c", clamp(r))
printf("%c", clamp(g))
printf("%c", clamp(b))
end
nil
end
nil
end
end
alias printf_orig printf
def printf *args
end
# File.open("ao.ppm", "w") do |fp|
printf("P6\n")
printf("%d %d\n", IMAGE_WIDTH, IMAGE_HEIGHT)
printf("255\n", IMAGE_WIDTH, IMAGE_HEIGHT)
Scene.new.render(IMAGE_WIDTH, IMAGE_HEIGHT, NSUBSAMPLES)
# end
undef printf
alias printf printf_orig

View file

@ -0,0 +1,9 @@
h = {}
10000.times do |i|
h[i] = nil
end
1000.times do
h.flatten
end

View file

@ -0,0 +1,9 @@
h = {}
10000.times do |i|
h[i] = nil
end
5000.times do
h.keys
end

View file

@ -0,0 +1,10 @@
h = {}
10000.times do |i|
h[i] = nil
end
50000.times do
k, v = h.shift
h[k] = v
end

View file

@ -0,0 +1,9 @@
h = {}
10000.times do |i|
h[i] = nil
end
5000.times do
h.values
end

View file

@ -4,7 +4,9 @@
# contributed by Jesse Millikan # contributed by Jesse Millikan
# disable output # disable output
def STDOUT.write_ *args alias puts_orig puts
def puts str
# disable puts
end end
def item_check(tree) def item_check(tree)
@ -25,7 +27,7 @@ def bottom_up_tree(item, depth)
end end
end end
max_depth = 12 # 16 # ARGV[0].to_i max_depth = 16 # ARGV[0].to_i
min_depth = 4 min_depth = 4
max_depth = min_depth + 2 if min_depth + 2 > max_depth max_depth = min_depth + 2 if min_depth + 2 > max_depth
@ -55,3 +57,6 @@ min_depth.step(max_depth + 1, 2) do |depth|
end end
puts "long lived tree of depth #{max_depth}\t check: #{item_check(long_lived_tree)}" puts "long lived tree of depth #{max_depth}\t check: #{item_check(long_lived_tree)}"
undef puts
alias puts puts_orig

View file

@ -0,0 +1,10 @@
i = 0
while i<30_000_000 # while loop 1
a = '' # short-lived String
b = ''
c = ''
d = ''
e = ''
f = ''
i+=1
end

View file

@ -0,0 +1,27 @@
def nested_hash h, n
if n == 0
''
else
10.times{
h[Object.new] = nested_hash(h, n-1)
}
end
end
long_lived = Hash.new
nested_hash long_lived, 6
GC.start
GC.start
i = 0
while i<30_000_000 # while loop 1
a = '' # short-lived String
b = ''
c = ''
d = ''
e = ''
f = ''
i+=1
end

View file

@ -0,0 +1,13 @@
long_lived = Array.new(1_000_000){|i| "#{i}"}
GC.start
GC.start
i = 0
while i<30_000_000 # while loop 1
a = '' # short-lived String
b = ''
c = ''
d = ''
e = ''
f = ''
i+=1
end

View file

@ -0,0 +1,15 @@
# make many symbols
50_000.times{|i| sym = "sym#{i}".to_sym}
GC.start
GC.start
i = 0
while i<30_000_000 # while loop 1
a = '' # short-lived String
b = ''
c = ''
d = ''
e = ''
f = ''
i+=1
end

View file

@ -0,0 +1,10 @@
long_lived = []
GC.start
GC.start
i = 0
short_lived = ''
while i<30_000_000 # while loop 1
long_lived[0] = short_lived # write barrier
i+=1
end

View file

@ -0,0 +1,13 @@
class C
attr_accessor :foo
end
long_lived = C.new
GC.start
GC.start
i = 0
short_lived = ''
while i<30_000_000 # while loop 1
long_lived.foo = short_lived # write barrier
i+=1
end

View file

@ -0,0 +1,18 @@
require 'thread'
n = 1_000_000
q = Queue.new
consumer = Thread.new{
while q.pop
# consuming
end
}
producer = Thread.new{
n.times{
q.push true
}
q.push nil
}
consumer.join

1
benchmark/gc/aobench.rb Normal file
View file

@ -0,0 +1 @@
require_relative '../bm_app_aobench.rb'

View file

@ -0,0 +1 @@
require_relative '../bm_so_binary_trees.rb'

56
benchmark/gc/gcbench.rb Normal file
View file

@ -0,0 +1,56 @@
require 'benchmark'
require 'pp'
require 'optparse'
$list = true
$gcprof = true
opt = OptionParser.new
opt.on('-q'){$list = false}
opt.on('-d'){$gcprof = false}
opt.parse!(ARGV)
script = File.join(File.dirname(__FILE__), ARGV.shift)
script += '.rb' unless FileTest.exist?(script)
raise "#{script} not found" unless FileTest.exist?(script)
puts "Script: #{script}"
if $gcprof
GC::Profiler.enable
end
tms = Benchmark.measure{|x|
load script
}
gc_time = 0
if $gcprof
gc_time = GC::Profiler.total_time
GC::Profiler.report if $list and RUBY_VERSION >= '2.0.0' # before 1.9.3, report() may run infinite loop
GC::Profiler.disable
end
pp GC.stat
puts "#{RUBY_DESCRIPTION} #{GC::OPTS.inspect}" if defined?(GC::OPTS)
desc = "#{RUBY_VERSION}#{RUBY_PATCHLEVEL >= 0 ? "p#{RUBY_PATCHLEVEL}" : "dev"}"
name = File.basename(script, '.rb')
puts
puts script
puts Benchmark::CAPTION
puts tms
puts "GC total time (sec): #{gc_time}"
# show High-Water Mark on Linux
if File.exist?('/proc/self/status') && /VmHWM:\s*(\d+.+)/ =~ File.read('/proc/self/status')
puts
puts "VmHWM: #{$1.chomp}"
end
puts
puts "Summary of #{name} on #{desc}\t#{tms.real}\t#{gc_time}\t#{GC.count}"
puts " (real time in sec, GC time in sec, GC count)"

11
benchmark/gc/hash1.rb Normal file
View file

@ -0,0 +1,11 @@
value = 0.01
h = {}
n = 50_000
1.upto(n){|i|
h["%020d" % i] = "v-#{i}"
}
(n * 1_000).times{
''
}

7
benchmark/gc/hash2.rb Normal file
View file

@ -0,0 +1,7 @@
value = 0.01
h = {}
n = 4*(10**6)
1.upto(n){|i|
h["%020d" % i] = value * i
}

1
benchmark/gc/null.rb Normal file
View file

@ -0,0 +1 @@
# null

View file

@ -0,0 +1 @@
require_relative '../bm_app_pentomino.rb'

13
benchmark/gc/rdoc.rb Normal file
View file

@ -0,0 +1,13 @@
require 'rdoc/rdoc'
require 'tmpdir'
srcdir = File.expand_path('../..', __dir__)
Dir.mktmpdir('rdocbench-'){|d|
dir = File.join(d, 'rdocbench')
args = %W(--root #{srcdir} --page-dir #{srcdir}/doc --encoding=UTF-8 --no-force-update --all --ri --debug --quiet #{srcdir})
args << '--op' << dir
r = RDoc::RDoc.new
r.document args
}

366
benchmark/gc/redblack.rb Normal file
View file

@ -0,0 +1,366 @@
# This benchmark is imported from https://github.com/jruby/rubybench/blob/master/time/bench_red_black.rb
# License is License is Apache-2
require 'benchmark'
# Algorithm based on "Introduction to Algorithms" by Cormen and others
class RedBlackTree
class Node
attr_accessor :color
attr_accessor :key
attr_accessor :left
attr_accessor :right
attr_accessor :parent
RED = :red
BLACK = :black
COLORS = [RED, BLACK].freeze
def initialize(key, color = RED)
raise ArgumentError, "Bad value for color parameter" unless COLORS.include?(color)
@color = color
@key = key
@left = @right = @parent = NilNode.instance
end
def black?
return color == BLACK
end
def red?
return color == RED
end
end
class NilNode < Node
class << self
private :new
# it's not thread safe
def instance
@instance ||= begin
def instance
return @instance
end
new
end
end
end
def initialize
self.color = BLACK
self.key = 0
self.left = nil
self.right = nil
self.parent = nil
end
def nil?
return true
end
end
include Enumerable
attr_accessor :root
attr_accessor :size
def initialize
self.root = NilNode.instance
self.size = 0
end
def add(key)
insert(Node.new(key))
end
def insert(x)
insert_helper(x)
x.color = Node::RED
while x != root && x.parent.color == Node::RED
if x.parent == x.parent.parent.left
y = x.parent.parent.right
if !y.nil? && y.color == Node::RED
x.parent.color = Node::BLACK
y.color = Node::BLACK
x.parent.parent.color = Node::RED
x = x.parent.parent
else
if x == x.parent.right
x = x.parent
left_rotate(x)
end
x.parent.color = Node::BLACK
x.parent.parent.color = Node::RED
right_rotate(x.parent.parent)
end
else
y = x.parent.parent.left
if !y.nil? && y.color == Node::RED
x.parent.color = Node::BLACK
y.color = Node::BLACK
x.parent.parent.color = Node::RED
x = x.parent.parent
else
if x == x.parent.left
x = x.parent
right_rotate(x)
end
x.parent.color = Node::BLACK
x.parent.parent.color = Node::RED
left_rotate(x.parent.parent)
end
end
end
root.color = Node::BLACK
end
alias << insert
def delete(z)
y = (z.left.nil? || z.right.nil?) ? z : successor(z)
x = y.left.nil? ? y.right : y.left
x.parent = y.parent
if y.parent.nil?
self.root = x
else
if y == y.parent.left
y.parent.left = x
else
y.parent.right = x
end
end
z.key = y.key if y != z
if y.color == Node::BLACK
delete_fixup(x)
end
self.size -= 1
return y
end
def minimum(x = root)
while !x.left.nil?
x = x.left
end
return x
end
def maximum(x = root)
while !x.right.nil?
x = x.right
end
return x
end
def successor(x)
if !x.right.nil?
return minimum(x.right)
end
y = x.parent
while !y.nil? && x == y.right
x = y
y = y.parent
end
return y
end
def predecessor(x)
if !x.left.nil?
return maximum(x.left)
end
y = x.parent
while !y.nil? && x == y.left
x = y
y = y.parent
end
return y
end
def inorder_walk(x = root)
x = self.minimum
while !x.nil?
yield x.key
x = successor(x)
end
end
alias each inorder_walk
def reverse_inorder_walk(x = root)
x = self.maximum
while !x.nil?
yield x.key
x = predecessor(x)
end
end
alias reverse_each reverse_inorder_walk
def search(key, x = root)
while !x.nil? && x.key != key
key < x.key ? x = x.left : x = x.right
end
return x
end
def empty?
return self.root.nil?
end
def black_height(x = root)
height = 0
while !x.nil?
x = x.left
height +=1 if x.nil? || x.black?
end
return height
end
private
def left_rotate(x)
raise "x.right is nil!" if x.right.nil?
y = x.right
x.right = y.left
y.left.parent = x if !y.left.nil?
y.parent = x.parent
if x.parent.nil?
self.root = y
else
if x == x.parent.left
x.parent.left = y
else
x.parent.right = y
end
end
y.left = x
x.parent = y
end
def right_rotate(x)
raise "x.left is nil!" if x.left.nil?
y = x.left
x.left = y.right
y.right.parent = x if !y.right.nil?
y.parent = x.parent
if x.parent.nil?
self.root = y
else
if x == x.parent.left
x.parent.left = y
else
x.parent.right = y
end
end
y.right = x
x.parent = y
end
def insert_helper(z)
y = NilNode.instance
x = root
while !x.nil?
y = x
z.key < x.key ? x = x.left : x = x.right
end
z.parent = y
if y.nil?
self.root = z
else
z.key < y.key ? y.left = z : y.right = z
end
self.size += 1
end
def delete_fixup(x)
while x != root && x.color == Node::BLACK
if x == x.parent.left
w = x.parent.right
if w.color == Node::RED
w.color = Node::BLACK
x.parent.color = Node::RED
left_rotate(x.parent)
w = x.parent.right
end
if w.left.color == Node::BLACK && w.right.color == Node::BLACK
w.color = Node::RED
x = x.parent
else
if w.right.color == Node::BLACK
w.left.color = Node::BLACK
w.color = Node::RED
right_rotate(w)
w = x.parent.right
end
w.color = x.parent.color
x.parent.color = Node::BLACK
w.right.color = Node::BLACK
left_rotate(x.parent)
x = root
end
else
w = x.parent.left
if w.color == Node::RED
w.color = Node::BLACK
x.parent.color = Node::RED
right_rotate(x.parent)
w = x.parent.left
end
if w.right.color == Node::BLACK && w.left.color == Node::BLACK
w.color = Node::RED
x = x.parent
else
if w.left.color == Node::BLACK
w.right.color = Node::BLACK
w.color = Node::RED
left_rotate(w)
w = x.parent.left
end
w.color = x.parent.color
x.parent.color = Node::BLACK
w.left.color = Node::BLACK
right_rotate(x.parent)
x = root
end
end
end
x.color = Node::BLACK
end
end
def rbt_bm
n = 100_000
a1 = []; n.times { a1 << rand(999_999) }
a2 = []; n.times { a2 << rand(999_999) }
start = Time.now
tree = RedBlackTree.new
n.times {|i| tree.add(i) }
n.times { tree.delete(tree.root) }
tree = RedBlackTree.new
a1.each {|e| tree.add(e) }
a2.each {|e| tree.search(e) }
tree.inorder_walk {|key| key + 1 }
tree.reverse_inorder_walk {|key| key + 1 }
n.times { tree.minimum }
n.times { tree.maximum }
return Time.now - start
end
N = (ARGV[0] || 10).to_i
N.times do
# puts rbt_bm.to_f
rbt_bm.to_f
# puts "GC.count = #{GC.count}" if GC.respond_to?(:count)
end

29
benchmark/gc/ring.rb Normal file
View file

@ -0,0 +1,29 @@
# create many old objects
max = 30_000_000
class Ring
attr_reader :next_ring
def initialize n = nil
@next_ring = n
end
def size
s = 1
ring = self
while ring.next_ring
s += 1
ring = ring.next_ring
end
s
end
end
ring = Ring.new
max.times{
ring = Ring.new(ring)
}
# p ring.size

7175
bignum.c

File diff suppressed because it is too large Load diff

View file

@ -72,7 +72,7 @@ class ERB
require ARGV.req_arg require ARGV.req_arg
when '-S' # security level when '-S' # security level
arg = ARGV.req_arg arg = ARGV.req_arg
raise "invalid safe_level #{arg.dump}" unless arg =~ /^[0-4]$/ raise "invalid safe_level #{arg.dump}" unless arg =~ /^[0-3]$/
safe_level = arg.to_i safe_level = arg.to_i
when '-T' # trim mode when '-T' # trim mode
arg = ARGV.req_arg arg = ARGV.req_arg
@ -105,7 +105,7 @@ class ERB
-v enable verbose mode -v enable verbose mode
-d set $DEBUG to true -d set $DEBUG to true
-r library load a library -r library load a library
-S safe_level set $SAFE (0..4) -S safe_level set $SAFE (0..3)
-E ex[:in] set default external/internal encodings -E ex[:in] set default external/internal encodings
-U set default encoding to UTF-8. -U set default encoding to UTF-8.
-T trim_mode specify trim_mode (0..2, -) -T trim_mode specify trim_mode (0..2, -)

11
bin/irb
View file

@ -8,13 +8,4 @@
require "irb" require "irb"
if __FILE__ == $0 IRB.start(__FILE__)
IRB.start(__FILE__)
else
# check -e option
if /^-e$/ =~ $0
IRB.start(__FILE__)
else
IRB.setup(__FILE__)
end
end

View file

@ -28,10 +28,6 @@ begin
rescue LoadError rescue LoadError
end end
module Rake
REDUCE_COMPAT = true if ARGV.include?("--reduce-compat")
end
require 'rake' require 'rake'
Rake.application.run Rake.application.run

View file

@ -62,6 +62,7 @@ def main
@verbose = false @verbose = false
$stress = false $stress = false
@color = nil @color = nil
@tty = nil
@quiet = false @quiet = false
dir = nil dir = nil
quiet = false quiet = false
@ -87,6 +88,10 @@ def main
warn "unknown --color argument: #$3" if $3 warn "unknown --color argument: #$3" if $3
@color = $1 ? nil : !$2 @color = $1 ? nil : !$2
true true
when /\A--tty(=(?:yes|(no)|(.*)))?\z/
warn "unknown --tty argument: #$3" if $3
@tty = !$1 || !$2
true
when /\A(-q|--q(uiet))\z/ when /\A(-q|--q(uiet))\z/
quiet = true quiet = true
@quiet = true @quiet = true
@ -123,7 +128,7 @@ End
@progress = %w[- \\ | /] @progress = %w[- \\ | /]
@progress_bs = "\b" * @progress[0].size @progress_bs = "\b" * @progress[0].size
@tty = $stderr.tty? @tty = $stderr.tty? if @tty.nil?
case @color case @color
when nil when nil
@color = @tty && /dumb/ !~ ENV["TERM"] @color = @tty && /dumb/ !~ ENV["TERM"]
@ -178,20 +183,20 @@ def exec_test(pathes)
$stderr.print "#{@progress_bs}#{@failed}FAIL #{@error-error}/#{@count-count}#{@reset}" $stderr.print "#{@progress_bs}#{@failed}FAIL #{@error-error}/#{@count-count}#{@reset}"
end end
end end
$stderr.puts unless @quiet $stderr.puts unless @quiet and @tty
end end
if @error == 0 if @error == 0
if @count == 0 if @count == 0
$stderr.puts "No tests, no problem" $stderr.puts "No tests, no problem"
else else
$stderr.puts "PASS all #{@count} tests" $stderr.puts "#{@passed}PASS#{@reset} all #{@count} tests"
end end
exit true exit true
else else
@errbuf.each do |msg| @errbuf.each do |msg|
$stderr.puts msg $stderr.puts msg
end end
$stderr.puts "FAIL #{@error}/#{@count} tests failed" $stderr.puts "#{@failed}FAIL#{@reset} #{@error}/#{@count} tests failed"
exit false exit false
end end
end end
@ -316,7 +321,7 @@ def assert_normal_exit(testsrc, *rest)
$stderr.reopen(old_stderr) $stderr.reopen(old_stderr)
old_stderr.close old_stderr.close
end end
if status.signaled? if status && status.signaled?
signo = status.termsig signo = status.termsig
signame = Signal.list.invert[signo] signame = Signal.list.invert[signo]
unless ignore_signals and ignore_signals.include?(signame) unless ignore_signals and ignore_signals.include?(signame)
@ -402,7 +407,7 @@ def get_result_string(src, opt = '')
begin begin
`#{@ruby} -W0 #{opt} #{filename}` `#{@ruby} -W0 #{opt} #{filename}`
ensure ensure
raise Interrupt if $?.signaled? && $?.termsig == Signal.list["INT"] raise Interrupt if $? and $?.signaled? && $?.termsig == Signal.list["INT"]
raise CoreDumpError, "core dumped" if $? and $?.coredump? raise CoreDumpError, "core dumped" if $? and $?.coredump?
end end
else else

View file

@ -43,46 +43,6 @@ assert_equal 'ok', %q{
ZZZ.ok ZZZ.ok
} }
assert_equal 'ok', %q{
open("zzz.rb", "w") {|f| f.puts "class ZZZ; def self.ok;:ok;end;end"}
autoload :ZZZ, "./zzz.rb"
proc{$SAFE=4; ZZZ.ok}.call
}
assert_equal 'ok', %q{
open("zzz.rb", "w") {|f| f.puts "class ZZZ; def self.ok;:ok;end;end"}
autoload :ZZZ, "./zzz.rb"
require "./zzz.rb"
proc{$SAFE=4; ZZZ.ok}.call
}
assert_equal 'ok', %q{
open("zzz.rb", "w") {|f| f.puts "class ZZZ; def hoge;:ok;end;end"}
autoload :ZZZ, File.join(Dir.pwd, 'zzz.rb')
module M; end
Thread.new{M.instance_eval('$SAFE=4; ZZZ.new.hoge')}.value
}
assert_equal 'ok', %q{
open("zzz.rb", "w") {|f| f.puts "class ZZZ; def hoge;:ok;end;end"}
autoload :ZZZ, File.join(Dir.pwd, 'zzz.rb')
module M; end
Thread.new{$SAFE=4; M.instance_eval('ZZZ.new.hoge')}.value
}
assert_equal 'ok', %q{
open("zzz.rb", "w") {|f| f.puts "class ZZZ; def hoge;:ok;end;end"}
autoload :ZZZ, File.join(Dir.pwd, 'zzz.rb')
Thread.new{$SAFE=4; eval('ZZZ.new.hoge')}.value
}
assert_equal 'ok', %q{
open("zzz.rb", "w") {|f| f.puts "class ZZZ; def hoge;:ok;end;end"}
autoload :ZZZ, File.join(Dir.pwd, 'zzz.rb')
module M; end
Thread.new{eval('$SAFE=4; ZZZ.new.hoge')}.value
}
assert_equal 'okok', %q{ assert_equal 'okok', %q{
open("zzz.rb", "w") {|f| f.puts "class ZZZ; def self.ok;:ok;end;end"} open("zzz.rb", "w") {|f| f.puts "class ZZZ; def self.ok;:ok;end;end"}
autoload :ZZZ, "./zzz.rb" autoload :ZZZ, "./zzz.rb"

View file

@ -11,6 +11,16 @@ assert_equal 'C', %q( class C; end
C.new.class.name ) C.new.class.name )
assert_equal 'Class', %q( class C; end assert_equal 'Class', %q( class C; end
C.new.class.class ) C.new.class.class )
assert_equal 'true', %q( Object.__send__(:remove_const, :TrueClass)
GC.start
true.inspect)
assert_equal 'false', %q( Object.__send__(:remove_const, :FalseClass)
GC.start
false.inspect)
assert_equal 'nil', %q( Object.__send__(:remove_const, :NilClass)
GC.start
nil.inspect)
# inherited class # inherited class
assert_equal 'true', %q( class A; end assert_equal 'true', %q( class A; end

View file

@ -224,3 +224,8 @@ assert_equal 'ok', %q{ # long hash literal (optimized)
eval "a = {#{(1..10_000).map{|n| "#{n} => #{n}"}.join(', ')}}" eval "a = {#{(1..10_000).map{|n| "#{n} => #{n}"}.join(', ')}}"
:ok :ok
} }
assert_equal 'ok', %q{
[print(:ok), exit] # void literal with side-effect
:dummy
}

View file

@ -0,0 +1,54 @@
# numbers with suffix
assert_equal '0/1', '0r'
assert_equal 'Rational', '0r.class'
assert_equal '1/1', '1r'
assert_equal 'Rational', '1r.class'
assert_equal '-1/1', '-1r'
assert_equal 'Rational', '(-1r).class'
assert_equal '1/1', '0x1r'
assert_equal 'Rational', '0x1r.class'
assert_equal '1/1', '0b1r'
assert_equal 'Rational', '0b1r.class'
assert_equal '1/1', '0d1r'
assert_equal 'Rational', '0d1r.class'
assert_equal '1/1', '0o1r'
assert_equal 'Rational', '0o1r.class'
assert_equal '1/1', '01r'
assert_equal 'Rational', '01r.class'
assert_equal '6/5', '1.2r'
assert_equal 'Rational', '1.2r.class'
assert_equal '-6/5', '-1.2r'
assert_equal 'Rational', '(-1.2r).class'
assert_equal '0+0i', '0i'
assert_equal 'Complex', '0i.class'
assert_equal '0+1i', '1i'
assert_equal 'Complex', '1i.class'
assert_equal '0+1i', '0x1i'
assert_equal 'Complex', '0x1i.class'
assert_equal '0+1i', '0b1i'
assert_equal 'Complex', '0b1i.class'
assert_equal '0+1i', '0d1i'
assert_equal 'Complex', '0d1i.class'
assert_equal '0+1i', '0o1i'
assert_equal 'Complex', '0o1i.class'
assert_equal '0+1i', '01i'
assert_equal 'Complex', '01i.class'
assert_equal '0+1.2i', '1.2i'
assert_equal 'Complex', '1.2i.class'
assert_equal '0+1/1i', '1ri'
assert_equal 'Complex', '1ri.class'
assert_equal '0+6/5i', '1.2ri'
assert_equal 'Complex', '1.2ri.class'
assert_equal '0+10.0i', '1e1i'
assert_equal 'Complex', '1e1i.class'
assert_equal '1', '1if true'
assert_equal '1', '1rescue nil'
assert_equal '10000000000000000001/10000000000000000000',
'1.0000000000000000001r'
assert_equal 'syntax error, unexpected tIDENTIFIER, expecting end-of-input',
%q{begin eval('1ir', nil, '', 0); rescue SyntaxError => e; e.message[/\A:(?:\d+:)? (.*)/, 1] end}
assert_equal 'syntax error, unexpected tIDENTIFIER, expecting end-of-input',
%q{begin eval('1.2ir', nil, '', 0); rescue SyntaxError => e; e.message[/\A:(?:\d+:)? (.*)/, 1] end}
assert_equal 'syntax error, unexpected tIDENTIFIER, expecting end-of-input',
%q{begin eval('1e1r', nil, '', 0); rescue SyntaxError => e; e.message[/\A:(?:\d+:)? (.*)/, 1] end}

View file

@ -886,50 +886,6 @@ class C0; def m *args; [:C0_m, args]; end; end
class C1 < C0; def m a, o=:o; super; end; end class C1 < C0; def m a, o=:o; super; end; end
; C1.new.m 1, 2} ; C1.new.m 1, 2}
assert_equal %q{[:ok, :ok, :ok, :ok, :ok, :ok, :ng, :ng]}, %q{
$ans = []
class Foo
def m
end
end
c1 = c2 = nil
lambda{
$SAFE = 4
c1 = Class.new{
def m
end
}
c2 = Class.new(Foo){
alias mm m
}
}.call
def test
begin
yield
rescue SecurityError
$ans << :ok
else
$ans << :ng
end
end
o1 = c1.new
o2 = c2.new
test{o1.m}
test{o2.mm}
test{o1.send :m}
test{o2.send :mm}
test{o1.public_send :m}
test{o2.public_send :mm}
test{o1.method(:m).call}
test{o2.method(:mm).call}
$ans
}
assert_equal 'ok', %q{ assert_equal 'ok', %q{
class C class C
def x=(n) def x=(n)

View file

@ -10,7 +10,8 @@ assert_equal %q{ok}, %q{
:ok :ok
}.value }.value
} }
assert_equal %q{20100}, %q{ assert_equal %q{ok}, %q{
begin
v = 0 v = 0
(1..200).map{|i| (1..200).map{|i|
Thread.new{ Thread.new{
@ -19,7 +20,10 @@ assert_equal %q{20100}, %q{
}.each{|t| }.each{|t|
v += t.value v += t.value
} }
v v == 20100 ? :ok : v
rescue ThreadError => e
:ok if /can't create Thread/ =~ e.message
end
} }
assert_equal %q{5000}, %q{ assert_equal %q{5000}, %q{
5000.times{|e| 5000.times{|e|
@ -41,13 +45,17 @@ assert_equal %q{5000}, %q{
} }
} }
} }
assert_equal %q{5000}, %q{ assert_equal %q{ok}, %q{
5000.times{ begin
:ok if 5000 == 5000.times{
t = Thread.new{} t = Thread.new{}
while t.alive? while t.alive?
Thread.pass Thread.pass
end end
} }
rescue NoMemoryError
:ok
end
} }
assert_equal %q{100}, %q{ assert_equal %q{100}, %q{
100.times{ 100.times{

502
class.c
View file

@ -31,8 +31,113 @@
#include "internal.h" #include "internal.h"
#include <ctype.h> #include <ctype.h>
extern st_table *rb_class_tbl; int rb_vm_add_root_module(ID id, VALUE module);
static ID id_attached;
#define id_attached id__attached__
void
rb_class_subclass_add(VALUE super, VALUE klass)
{
rb_subclass_entry_t *entry, *head;
if (super && super != Qundef) {
entry = malloc(sizeof(*entry));
entry->klass = klass;
entry->next = NULL;
head = RCLASS_EXT(super)->subclasses;
if (head) {
entry->next = head;
RCLASS_EXT(head->klass)->parent_subclasses = &entry->next;
}
RCLASS_EXT(super)->subclasses = entry;
RCLASS_EXT(klass)->parent_subclasses = &RCLASS_EXT(super)->subclasses;
}
}
static void
rb_module_add_to_subclasses_list(VALUE module, VALUE iclass)
{
rb_subclass_entry_t *entry, *head;
entry = malloc(sizeof(*entry));
entry->klass = iclass;
entry->next = NULL;
head = RCLASS_EXT(module)->subclasses;
if (head) {
entry->next = head;
RCLASS_EXT(head->klass)->module_subclasses = &entry->next;
}
RCLASS_EXT(module)->subclasses = entry;
RCLASS_EXT(iclass)->module_subclasses = &RCLASS_EXT(module)->subclasses;
}
void
rb_class_remove_from_super_subclasses(VALUE klass)
{
rb_subclass_entry_t *entry;
if (RCLASS_EXT(klass)->parent_subclasses) {
entry = *RCLASS_EXT(klass)->parent_subclasses;
*RCLASS_EXT(klass)->parent_subclasses = entry->next;
if (entry->next) {
RCLASS_EXT(entry->next->klass)->parent_subclasses = RCLASS_EXT(klass)->parent_subclasses;
}
free(entry);
}
RCLASS_EXT(klass)->parent_subclasses = NULL;
}
void
rb_class_remove_from_module_subclasses(VALUE klass)
{
rb_subclass_entry_t *entry;
if (RCLASS_EXT(klass)->module_subclasses) {
entry = *RCLASS_EXT(klass)->module_subclasses;
*RCLASS_EXT(klass)->module_subclasses = entry->next;
if (entry->next) {
RCLASS_EXT(entry->next->klass)->module_subclasses = RCLASS_EXT(klass)->module_subclasses;
}
free(entry);
}
RCLASS_EXT(klass)->module_subclasses = NULL;
}
void
rb_class_foreach_subclass(VALUE klass, void(*f)(VALUE))
{
rb_subclass_entry_t *cur = RCLASS_EXT(klass)->subclasses;
/* do not be tempted to simplify this loop into a for loop, the order of
operations is important here if `f` modifies the linked list */
while (cur) {
VALUE curklass = cur->klass;
cur = cur->next;
f(curklass);
}
}
void
rb_class_detach_subclasses(VALUE klass)
{
rb_class_foreach_subclass(klass, rb_class_remove_from_super_subclasses);
}
void
rb_class_detach_module_subclasses(VALUE klass)
{
rb_class_foreach_subclass(klass, rb_class_remove_from_module_subclasses);
}
/** /**
* Allocates a struct RClass for a new class. * Allocates a struct RClass for a new class.
@ -49,14 +154,20 @@ static ID id_attached;
static VALUE static VALUE
class_alloc(VALUE flags, VALUE klass) class_alloc(VALUE flags, VALUE klass)
{ {
NEWOBJ_OF(obj, struct RClass, klass, flags); NEWOBJ_OF(obj, struct RClass, klass, (flags & T_MASK) | (RGENGC_WB_PROTECTED_CLASS ? FL_WB_PROTECTED : 0));
obj->ptr = ALLOC(rb_classext_t); obj->ptr = ALLOC(rb_classext_t);
RCLASS_IV_TBL(obj) = 0; RCLASS_IV_TBL(obj) = 0;
RCLASS_CONST_TBL(obj) = 0; RCLASS_CONST_TBL(obj) = 0;
RCLASS_M_TBL(obj) = 0; RCLASS_M_TBL_WRAPPER(obj) = 0;
RCLASS_SUPER(obj) = 0; RCLASS_SET_SUPER((VALUE)obj, 0);
RCLASS_ORIGIN(obj) = (VALUE)obj; RCLASS_ORIGIN(obj) = (VALUE)obj;
RCLASS_IV_INDEX_TBL(obj) = 0; RCLASS_IV_INDEX_TBL(obj) = 0;
RCLASS_EXT(obj)->subclasses = NULL;
RCLASS_EXT(obj)->parent_subclasses = NULL;
RCLASS_EXT(obj)->module_subclasses = NULL;
RCLASS_SERIAL(obj) = rb_next_class_serial();
RCLASS_REFINED_CLASS(obj) = Qnil; RCLASS_REFINED_CLASS(obj) = Qnil;
RCLASS_EXT(obj)->allocator = 0; RCLASS_EXT(obj)->allocator = 0;
return (VALUE)obj; return (VALUE)obj;
@ -77,8 +188,8 @@ rb_class_boot(VALUE super)
{ {
VALUE klass = class_alloc(T_CLASS, rb_cClass); VALUE klass = class_alloc(T_CLASS, rb_cClass);
RCLASS_SUPER(klass) = super; RCLASS_SET_SUPER(klass, super);
RCLASS_M_TBL(klass) = st_init_numtable(); RCLASS_M_TBL_INIT(klass);
OBJ_INFECT(klass, super); OBJ_INFECT(klass, super);
return (VALUE)klass; return (VALUE)klass;
@ -121,21 +232,23 @@ rb_class_new(VALUE super)
return rb_class_boot(super); return rb_class_boot(super);
} }
static NODE* static void
rewrite_cref_stack(NODE *node, VALUE old_klass, VALUE new_klass) rewrite_cref_stack(NODE *node, VALUE old_klass, VALUE new_klass, NODE **new_cref_ptr)
{ {
NODE *new_node; NODE *new_node;
if (!node) { while (node) {
return NULL; if (node->nd_clss == old_klass) {
} new_node = NEW_CREF(new_klass);
if (node->nd_clss == old_klass) { RB_OBJ_WRITE(new_node, &new_node->nd_next, node->nd_next);
new_node = NEW_CREF(new_klass); *new_cref_ptr = new_node;
new_node->nd_next = node->nd_next; return;
} else { }
new_node = NEW_CREF(node->nd_clss); new_node = NEW_CREF(node->nd_clss);
new_node->nd_next = rewrite_cref_stack(node->nd_next, old_klass, new_klass); node = node->nd_next;
*new_cref_ptr = new_node;
new_cref_ptr = &new_node->nd_next;
} }
return new_node; *new_cref_ptr = NULL;
} }
static void static void
@ -144,9 +257,11 @@ clone_method(VALUE klass, ID mid, const rb_method_entry_t *me)
VALUE newiseqval; VALUE newiseqval;
if (me->def && me->def->type == VM_METHOD_TYPE_ISEQ) { if (me->def && me->def->type == VM_METHOD_TYPE_ISEQ) {
rb_iseq_t *iseq; rb_iseq_t *iseq;
NODE *new_cref;
newiseqval = rb_iseq_clone(me->def->body.iseq->self, klass); newiseqval = rb_iseq_clone(me->def->body.iseq->self, klass);
GetISeqPtr(newiseqval, iseq); GetISeqPtr(newiseqval, iseq);
iseq->cref_stack = rewrite_cref_stack(me->def->body.iseq->cref_stack, me->klass, klass); rewrite_cref_stack(me->def->body.iseq->cref_stack, me->klass, klass, &new_cref);
RB_OBJ_WRITE(iseq->self, &iseq->cref_stack, new_cref);
rb_add_method(klass, mid, VM_METHOD_TYPE_ISEQ, iseq, me->flag); rb_add_method(klass, mid, VM_METHOD_TYPE_ISEQ, iseq, me->flag);
RB_GC_GUARD(newiseqval); RB_GC_GUARD(newiseqval);
} }
@ -162,19 +277,27 @@ clone_method_i(st_data_t key, st_data_t value, st_data_t data)
return ST_CONTINUE; return ST_CONTINUE;
} }
struct clone_const_arg {
VALUE klass;
st_table *tbl;
};
static int static int
clone_const(ID key, const rb_const_entry_t *ce, st_table *tbl) clone_const(ID key, const rb_const_entry_t *ce, struct clone_const_arg *arg)
{ {
rb_const_entry_t *nce = ALLOC(rb_const_entry_t); rb_const_entry_t *nce = ALLOC(rb_const_entry_t);
*nce = *ce; MEMCPY(nce, ce, rb_const_entry_t, 1);
st_insert(tbl, key, (st_data_t)nce); RB_OBJ_WRITTEN(arg->klass, Qundef, ce->value);
RB_OBJ_WRITTEN(arg->klass, Qundef, ce->file);
st_insert(arg->tbl, key, (st_data_t)nce);
return ST_CONTINUE; return ST_CONTINUE;
} }
static int static int
clone_const_i(st_data_t key, st_data_t value, st_data_t data) clone_const_i(st_data_t key, st_data_t value, st_data_t data)
{ {
return clone_const((ID)key, (const rb_const_entry_t *)value, (st_table *)data); return clone_const((ID)key, (const rb_const_entry_t *)value, (struct clone_const_arg *)data);
} }
static void static void
@ -200,10 +323,10 @@ rb_mod_init_copy(VALUE clone, VALUE orig)
} }
rb_obj_init_copy(clone, orig); rb_obj_init_copy(clone, orig);
if (!FL_TEST(CLASS_OF(clone), FL_SINGLETON)) { if (!FL_TEST(CLASS_OF(clone), FL_SINGLETON)) {
RBASIC(clone)->klass = rb_singleton_class_clone(orig); RBASIC_SET_CLASS(clone, rb_singleton_class_clone(orig));
rb_singleton_class_attached(RBASIC(clone)->klass, (VALUE)clone); rb_singleton_class_attached(RBASIC(clone)->klass, (VALUE)clone);
} }
RCLASS_SUPER(clone) = RCLASS_SUPER(orig); RCLASS_SET_SUPER(clone, RCLASS_SUPER(orig));
RCLASS_EXT(clone)->allocator = RCLASS_EXT(orig)->allocator; RCLASS_EXT(clone)->allocator = RCLASS_EXT(orig)->allocator;
if (RCLASS_IV_TBL(orig)) { if (RCLASS_IV_TBL(orig)) {
st_data_t id; st_data_t id;
@ -211,7 +334,7 @@ rb_mod_init_copy(VALUE clone, VALUE orig)
if (RCLASS_IV_TBL(clone)) { if (RCLASS_IV_TBL(clone)) {
st_free_table(RCLASS_IV_TBL(clone)); st_free_table(RCLASS_IV_TBL(clone));
} }
RCLASS_IV_TBL(clone) = st_copy(RCLASS_IV_TBL(orig)); RCLASS_IV_TBL(clone) = rb_st_copy(clone, RCLASS_IV_TBL(orig));
CONST_ID(id, "__tmp_classpath__"); CONST_ID(id, "__tmp_classpath__");
st_delete(RCLASS_IV_TBL(clone), &id, 0); st_delete(RCLASS_IV_TBL(clone), &id, 0);
CONST_ID(id, "__classpath__"); CONST_ID(id, "__classpath__");
@ -220,17 +343,20 @@ rb_mod_init_copy(VALUE clone, VALUE orig)
st_delete(RCLASS_IV_TBL(clone), &id, 0); st_delete(RCLASS_IV_TBL(clone), &id, 0);
} }
if (RCLASS_CONST_TBL(orig)) { if (RCLASS_CONST_TBL(orig)) {
struct clone_const_arg arg;
if (RCLASS_CONST_TBL(clone)) { if (RCLASS_CONST_TBL(clone)) {
rb_free_const_table(RCLASS_CONST_TBL(clone)); rb_free_const_table(RCLASS_CONST_TBL(clone));
} }
RCLASS_CONST_TBL(clone) = st_init_numtable(); RCLASS_CONST_TBL(clone) = st_init_numtable();
st_foreach(RCLASS_CONST_TBL(orig), clone_const_i, (st_data_t)RCLASS_CONST_TBL(clone)); arg.klass = clone;
arg.tbl = RCLASS_CONST_TBL(clone);
st_foreach(RCLASS_CONST_TBL(orig), clone_const_i, (st_data_t)&arg);
} }
if (RCLASS_M_TBL(orig)) { if (RCLASS_M_TBL(orig)) {
if (RCLASS_M_TBL(clone)) { if (RCLASS_M_TBL_WRAPPER(clone)) {
rb_free_m_table(RCLASS_M_TBL(clone)); rb_free_m_tbl_wrapper(RCLASS_M_TBL_WRAPPER(clone));
} }
RCLASS_M_TBL(clone) = st_init_numtable(); RCLASS_M_TBL_INIT(clone);
st_foreach(RCLASS_M_TBL(orig), clone_method_i, (st_data_t)clone); st_foreach(RCLASS_M_TBL(orig), clone_method_i, (st_data_t)clone);
} }
@ -255,28 +381,32 @@ rb_singleton_class_clone_and_attach(VALUE obj, VALUE attach)
VALUE clone = class_alloc(RBASIC(klass)->flags, 0); VALUE clone = class_alloc(RBASIC(klass)->flags, 0);
if (BUILTIN_TYPE(obj) == T_CLASS) { if (BUILTIN_TYPE(obj) == T_CLASS) {
RBASIC(clone)->klass = clone; RBASIC_SET_CLASS(clone, clone);
} }
else { else {
RBASIC(clone)->klass = rb_singleton_class_clone(klass); RBASIC_SET_CLASS(clone, rb_singleton_class_clone(klass));
} }
RCLASS_SUPER(clone) = RCLASS_SUPER(klass); RCLASS_SET_SUPER(clone, RCLASS_SUPER(klass));
RCLASS_EXT(clone)->allocator = RCLASS_EXT(klass)->allocator; RCLASS_EXT(clone)->allocator = RCLASS_EXT(klass)->allocator;
if (RCLASS_IV_TBL(klass)) { if (RCLASS_IV_TBL(klass)) {
RCLASS_IV_TBL(clone) = st_copy(RCLASS_IV_TBL(klass)); RCLASS_IV_TBL(clone) = rb_st_copy(clone, RCLASS_IV_TBL(klass));
} }
if (RCLASS_CONST_TBL(klass)) { if (RCLASS_CONST_TBL(klass)) {
struct clone_const_arg arg;
RCLASS_CONST_TBL(clone) = st_init_numtable(); RCLASS_CONST_TBL(clone) = st_init_numtable();
st_foreach(RCLASS_CONST_TBL(klass), clone_const_i, (st_data_t)RCLASS_CONST_TBL(clone)); arg.klass = clone;
arg.tbl = RCLASS_CONST_TBL(clone);
st_foreach(RCLASS_CONST_TBL(klass), clone_const_i, (st_data_t)&arg);
} }
if (attach != Qundef) { if (attach != Qundef) {
rb_singleton_class_attached(clone, attach); rb_singleton_class_attached(clone, attach);
} }
RCLASS_M_TBL(clone) = st_init_numtable(); RCLASS_M_TBL_INIT(clone);
st_foreach(RCLASS_M_TBL(klass), clone_method_i, (st_data_t)clone); st_foreach(RCLASS_M_TBL(klass), clone_method_i, (st_data_t)clone);
rb_singleton_class_attached(RBASIC(clone)->klass, clone); rb_singleton_class_attached(RBASIC(clone)->klass, clone);
FL_SET(clone, FL_SINGLETON); FL_SET(clone, FL_SINGLETON);
return clone; return clone;
} }
} }
@ -292,13 +422,14 @@ rb_singleton_class_attached(VALUE klass, VALUE obj)
if (!RCLASS_IV_TBL(klass)) { if (!RCLASS_IV_TBL(klass)) {
RCLASS_IV_TBL(klass) = st_init_numtable(); RCLASS_IV_TBL(klass) = st_init_numtable();
} }
st_insert(RCLASS_IV_TBL(klass), id_attached, obj); rb_st_insert_id_and_value(klass, RCLASS_IV_TBL(klass), id_attached, obj);
} }
} }
#define METACLASS_OF(k) RBASIC(k)->klass #define METACLASS_OF(k) RBASIC(k)->klass
#define SET_METACLASS_OF(k, cls) RBASIC_SET_CLASS(k, cls)
/*! /*!
* whether k is a meta^(n)-class of Class class * whether k is a meta^(n)-class of Class class
@ -307,6 +438,14 @@ rb_singleton_class_attached(VALUE klass, VALUE obj)
*/ */
#define META_CLASS_OF_CLASS_CLASS_P(k) (METACLASS_OF(k) == (k)) #define META_CLASS_OF_CLASS_CLASS_P(k) (METACLASS_OF(k) == (k))
/*!
* whether k has a metaclass
* @retval 1 if \a k has a metaclass
* @retval 0 otherwise
*/
#define HAVE_METACLASS_P(k) \
(FL_TEST(METACLASS_OF(k), FL_SINGLETON) && \
rb_ivar_get(METACLASS_OF(k), id_attached) == (k))
/*! /*!
* ensures \a klass belongs to its own eigenclass. * ensures \a klass belongs to its own eigenclass.
@ -316,7 +455,7 @@ rb_singleton_class_attached(VALUE klass, VALUE obj)
* @note this macro creates a new eigenclass if necessary. * @note this macro creates a new eigenclass if necessary.
*/ */
#define ENSURE_EIGENCLASS(klass) \ #define ENSURE_EIGENCLASS(klass) \
(rb_ivar_get(METACLASS_OF(klass), id_attached) == (klass) ? METACLASS_OF(klass) : make_metaclass(klass)) (HAVE_METACLASS_P(klass) ? METACLASS_OF(klass) : make_metaclass(klass))
/*! /*!
@ -338,17 +477,18 @@ make_metaclass(VALUE klass)
rb_singleton_class_attached(metaclass, klass); rb_singleton_class_attached(metaclass, klass);
if (META_CLASS_OF_CLASS_CLASS_P(klass)) { if (META_CLASS_OF_CLASS_CLASS_P(klass)) {
METACLASS_OF(klass) = METACLASS_OF(metaclass) = metaclass; SET_METACLASS_OF(klass, metaclass);
SET_METACLASS_OF(metaclass, metaclass);
} }
else { else {
VALUE tmp = METACLASS_OF(klass); /* for a meta^(n)-class klass, tmp is meta^(n)-class of Class class */ VALUE tmp = METACLASS_OF(klass); /* for a meta^(n)-class klass, tmp is meta^(n)-class of Class class */
METACLASS_OF(klass) = metaclass; SET_METACLASS_OF(klass, metaclass);
METACLASS_OF(metaclass) = ENSURE_EIGENCLASS(tmp); SET_METACLASS_OF(metaclass, ENSURE_EIGENCLASS(tmp));
} }
super = RCLASS_SUPER(klass); super = RCLASS_SUPER(klass);
while (RB_TYPE_P(super, T_ICLASS)) super = RCLASS_SUPER(super); while (RB_TYPE_P(super, T_ICLASS)) super = RCLASS_SUPER(super);
RCLASS_SUPER(metaclass) = super ? ENSURE_EIGENCLASS(super) : rb_cClass; RCLASS_SET_SUPER(metaclass, super ? ENSURE_EIGENCLASS(super) : rb_cClass);
OBJ_INFECT(metaclass, RCLASS_SUPER(metaclass)); OBJ_INFECT(metaclass, RCLASS_SUPER(metaclass));
@ -368,10 +508,10 @@ make_singleton_class(VALUE obj)
VALUE klass = rb_class_boot(orig_class); VALUE klass = rb_class_boot(orig_class);
FL_SET(klass, FL_SINGLETON); FL_SET(klass, FL_SINGLETON);
RBASIC(obj)->klass = klass; RBASIC_SET_CLASS(obj, klass);
rb_singleton_class_attached(klass, obj); rb_singleton_class_attached(klass, obj);
METACLASS_OF(klass) = METACLASS_OF(rb_class_real(orig_class)); SET_METACLASS_OF(klass, METACLASS_OF(rb_class_real(orig_class)));
return klass; return klass;
} }
@ -379,12 +519,10 @@ make_singleton_class(VALUE obj)
static VALUE static VALUE
boot_defclass(const char *name, VALUE super) boot_defclass(const char *name, VALUE super)
{ {
extern st_table *rb_class_tbl;
VALUE obj = rb_class_boot(super); VALUE obj = rb_class_boot(super);
ID id = rb_intern(name); ID id = rb_intern(name);
rb_name_class(obj, id); rb_name_class(obj, id);
st_add_direct(rb_class_tbl, id, obj);
rb_const_set((rb_cObject ? rb_cObject : obj), id, obj); rb_const_set((rb_cObject ? rb_cObject : obj), id, obj);
return obj; return obj;
} }
@ -392,19 +530,16 @@ boot_defclass(const char *name, VALUE super)
void void
Init_class_hierarchy(void) Init_class_hierarchy(void)
{ {
id_attached = rb_intern("__attached__");
rb_cBasicObject = boot_defclass("BasicObject", 0); rb_cBasicObject = boot_defclass("BasicObject", 0);
rb_cObject = boot_defclass("Object", rb_cBasicObject); rb_cObject = boot_defclass("Object", rb_cBasicObject);
rb_cModule = boot_defclass("Module", rb_cObject); rb_cModule = boot_defclass("Module", rb_cObject);
rb_cClass = boot_defclass("Class", rb_cModule); rb_cClass = boot_defclass("Class", rb_cModule);
rb_const_set(rb_cObject, rb_intern("BasicObject"), rb_cBasicObject); rb_const_set(rb_cObject, rb_intern("BasicObject"), rb_cBasicObject);
RBASIC(rb_cClass)->klass RBASIC_SET_CLASS(rb_cClass, rb_cClass);
= RBASIC(rb_cModule)->klass RBASIC_SET_CLASS(rb_cModule, rb_cClass);
= RBASIC(rb_cObject)->klass RBASIC_SET_CLASS(rb_cObject, rb_cClass);
= RBASIC(rb_cBasicObject)->klass RBASIC_SET_CLASS(rb_cBasicObject, rb_cClass);
= rb_cClass;
} }
@ -508,7 +643,7 @@ rb_define_class(const char *name, VALUE super)
rb_warn("no super class for `%s', Object assumed", name); rb_warn("no super class for `%s', Object assumed", name);
} }
klass = rb_define_class_id(id, super); klass = rb_define_class_id(id, super);
st_add_direct(rb_class_tbl, id, klass); rb_vm_add_root_module(id, klass);
rb_name_class(klass, id); rb_name_class(klass, id);
rb_const_set(rb_cObject, id, klass); rb_const_set(rb_cObject, id, klass);
rb_class_inherited(super, klass); rb_class_inherited(super, klass);
@ -588,9 +723,7 @@ VALUE
rb_module_new(void) rb_module_new(void)
{ {
VALUE mdl = class_alloc(T_MODULE, rb_cModule); VALUE mdl = class_alloc(T_MODULE, rb_cModule);
RCLASS_M_TBL_INIT(mdl);
RCLASS_M_TBL(mdl) = st_init_numtable();
return (VALUE)mdl; return (VALUE)mdl;
} }
@ -619,7 +752,7 @@ rb_define_module(const char *name)
rb_raise(rb_eTypeError, "%s is not a module", rb_obj_classname(module)); rb_raise(rb_eTypeError, "%s is not a module", rb_obj_classname(module));
} }
module = rb_define_module_id(id); module = rb_define_module_id(id);
st_add_direct(rb_class_tbl, id, module); rb_vm_add_root_module(id, module);
rb_const_set(rb_cObject, id, module); rb_const_set(rb_cObject, id, module);
return module; return module;
@ -667,13 +800,16 @@ rb_include_class_new(VALUE module, VALUE super)
} }
RCLASS_IV_TBL(klass) = RCLASS_IV_TBL(module); RCLASS_IV_TBL(klass) = RCLASS_IV_TBL(module);
RCLASS_CONST_TBL(klass) = RCLASS_CONST_TBL(module); RCLASS_CONST_TBL(klass) = RCLASS_CONST_TBL(module);
RCLASS_M_TBL(klass) = RCLASS_M_TBL(RCLASS_ORIGIN(module));
RCLASS_SUPER(klass) = super; RCLASS_M_TBL_WRAPPER(OBJ_WB_UNPROTECT(klass)) =
RCLASS_M_TBL_WRAPPER(OBJ_WB_UNPROTECT(RCLASS_ORIGIN(module)));
RCLASS_SET_SUPER(klass, super);
if (RB_TYPE_P(module, T_ICLASS)) { if (RB_TYPE_P(module, T_ICLASS)) {
RBASIC(klass)->klass = RBASIC(module)->klass; RBASIC_SET_CLASS(klass, RBASIC(module)->klass);
} }
else { else {
RBASIC(klass)->klass = module; RBASIC_SET_CLASS(klass, module);
} }
OBJ_INFECT(klass, module); OBJ_INFECT(klass, module);
OBJ_INFECT(klass, super); OBJ_INFECT(klass, super);
@ -681,7 +817,7 @@ rb_include_class_new(VALUE module, VALUE super)
return (VALUE)klass; return (VALUE)klass;
} }
static int include_modules_at(VALUE klass, VALUE c, VALUE module); static int include_modules_at(const VALUE klass, VALUE c, VALUE module);
void void
rb_include_module(VALUE klass, VALUE module) rb_include_module(VALUE klass, VALUE module)
@ -689,9 +825,6 @@ rb_include_module(VALUE klass, VALUE module)
int changed = 0; int changed = 0;
rb_frozen_class_p(klass); rb_frozen_class_p(klass);
if (!OBJ_UNTRUSTED(klass)) {
rb_secure(4);
}
if (!RB_TYPE_P(module, T_MODULE)) { if (!RB_TYPE_P(module, T_MODULE)) {
Check_Type(module, T_MODULE); Check_Type(module, T_MODULE);
@ -702,7 +835,6 @@ rb_include_module(VALUE klass, VALUE module)
changed = include_modules_at(klass, RCLASS_ORIGIN(klass), module); changed = include_modules_at(klass, RCLASS_ORIGIN(klass), module);
if (changed < 0) if (changed < 0)
rb_raise(rb_eArgError, "cyclic include detected"); rb_raise(rb_eArgError, "cyclic include detected");
if (changed) rb_clear_cache();
} }
static int static int
@ -713,23 +845,24 @@ add_refined_method_entry_i(st_data_t key, st_data_t value, st_data_t data)
} }
static int static int
include_modules_at(VALUE klass, VALUE c, VALUE module) include_modules_at(const VALUE klass, VALUE c, VALUE module)
{ {
VALUE p; VALUE p, iclass;
int changed = 0; int method_changed = 0, constant_changed = 0;
const st_table *const klass_m_tbl = RCLASS_M_TBL(RCLASS_ORIGIN(klass));
while (module) { while (module) {
int superclass_seen = FALSE; int superclass_seen = FALSE;
if (RCLASS_ORIGIN(module) != module) if (RCLASS_ORIGIN(module) != module)
goto skip; goto skip;
if (RCLASS_M_TBL(klass) && RCLASS_M_TBL(klass) == RCLASS_M_TBL(module)) if (klass_m_tbl && klass_m_tbl == RCLASS_M_TBL(module))
return -1; return -1;
/* ignore if the module included already in superclasses */ /* ignore if the module included already in superclasses */
for (p = RCLASS_SUPER(klass); p; p = RCLASS_SUPER(p)) { for (p = RCLASS_SUPER(klass); p; p = RCLASS_SUPER(p)) {
switch (BUILTIN_TYPE(p)) { switch (BUILTIN_TYPE(p)) {
case T_ICLASS: case T_ICLASS:
if (RCLASS_M_TBL(p) == RCLASS_M_TBL(module)) { if (RCLASS_M_TBL_WRAPPER(p) == RCLASS_M_TBL_WRAPPER(module)) {
if (!superclass_seen) { if (!superclass_seen) {
c = p; /* move insertion point */ c = p; /* move insertion point */
} }
@ -741,7 +874,15 @@ include_modules_at(VALUE klass, VALUE c, VALUE module)
break; break;
} }
} }
c = RCLASS_SUPER(c) = rb_include_class_new(module, RCLASS_SUPER(c)); iclass = rb_include_class_new(module, RCLASS_SUPER(c));
c = RCLASS_SET_SUPER(c, iclass);
if (BUILTIN_TYPE(module) == T_ICLASS) {
rb_module_add_to_subclasses_list(RBASIC(module)->klass, iclass);
} else {
rb_module_add_to_subclasses_list(module, iclass);
}
if (FL_TEST(klass, RMODULE_IS_REFINEMENT)) { if (FL_TEST(klass, RMODULE_IS_REFINEMENT)) {
VALUE refined_class = VALUE refined_class =
rb_refinement_module_get_refined_class(klass); rb_refinement_module_get_refined_class(klass);
@ -751,12 +892,17 @@ include_modules_at(VALUE klass, VALUE c, VALUE module)
FL_SET(c, RMODULE_INCLUDED_INTO_REFINEMENT); FL_SET(c, RMODULE_INCLUDED_INTO_REFINEMENT);
} }
if (RMODULE_M_TBL(module) && RMODULE_M_TBL(module)->num_entries) if (RMODULE_M_TBL(module) && RMODULE_M_TBL(module)->num_entries)
changed = 1; method_changed = 1;
if (RMODULE_CONST_TBL(module) && RMODULE_CONST_TBL(module)->num_entries)
constant_changed = 1;
skip: skip:
module = RCLASS_SUPER(module); module = RCLASS_SUPER(module);
} }
return changed; if (method_changed) rb_clear_method_cache_by_class(klass);
if (constant_changed) rb_clear_constant_cache();
return method_changed;
} }
static int static int
@ -789,13 +935,11 @@ move_refined_method(st_data_t key, st_data_t value, st_data_t data)
void void
rb_prepend_module(VALUE klass, VALUE module) rb_prepend_module(VALUE klass, VALUE module)
{ {
void rb_vm_check_redefinition_by_prepend(VALUE klass);
VALUE origin; VALUE origin;
int changed = 0; int changed = 0;
rb_frozen_class_p(klass); rb_frozen_class_p(klass);
if (!OBJ_UNTRUSTED(klass)) {
rb_secure(4);
}
Check_Type(module, T_MODULE); Check_Type(module, T_MODULE);
@ -804,18 +948,21 @@ rb_prepend_module(VALUE klass, VALUE module)
origin = RCLASS_ORIGIN(klass); origin = RCLASS_ORIGIN(klass);
if (origin == klass) { if (origin == klass) {
origin = class_alloc(T_ICLASS, klass); origin = class_alloc(T_ICLASS, klass);
RCLASS_SUPER(origin) = RCLASS_SUPER(klass); OBJ_WB_UNPROTECT(origin); /* TODO: conservertive shading. Need more survery. */
RCLASS_SUPER(klass) = origin; RCLASS_SET_SUPER(origin, RCLASS_SUPER(klass));
RCLASS_SET_SUPER(klass, origin);
RCLASS_ORIGIN(klass) = origin; RCLASS_ORIGIN(klass) = origin;
RCLASS_M_TBL(origin) = RCLASS_M_TBL(klass); RCLASS_M_TBL_WRAPPER(origin) = RCLASS_M_TBL_WRAPPER(klass);
RCLASS_M_TBL(klass) = st_init_numtable(); RCLASS_M_TBL_INIT(klass);
st_foreach(RCLASS_M_TBL(origin), move_refined_method, st_foreach(RCLASS_M_TBL(origin), move_refined_method,
(st_data_t) RCLASS_M_TBL(klass)); (st_data_t) RCLASS_M_TBL(klass));
} }
changed = include_modules_at(klass, klass, module); changed = include_modules_at(klass, klass, module);
if (changed < 0) if (changed < 0)
rb_raise(rb_eArgError, "cyclic prepend detected"); rb_raise(rb_eArgError, "cyclic prepend detected");
if (changed) rb_clear_cache(); if (changed) {
rb_vm_check_redefinition_by_prepend(klass);
}
} }
/* /*
@ -840,10 +987,13 @@ rb_mod_included_modules(VALUE mod)
{ {
VALUE ary = rb_ary_new(); VALUE ary = rb_ary_new();
VALUE p; VALUE p;
VALUE origin = RCLASS_ORIGIN(mod);
for (p = RCLASS_SUPER(mod); p; p = RCLASS_SUPER(p)) { for (p = RCLASS_SUPER(mod); p; p = RCLASS_SUPER(p)) {
if (BUILTIN_TYPE(p) == T_ICLASS) { if (p != origin && BUILTIN_TYPE(p) == T_ICLASS) {
rb_ary_push(ary, RBASIC(p)->klass); VALUE m = RBASIC(p)->klass;
if (RB_TYPE_P(m, T_MODULE))
rb_ary_push(ary, m);
} }
} }
return ary; return ary;
@ -904,8 +1054,6 @@ rb_mod_ancestors(VALUE mod)
VALUE p, ary = rb_ary_new(); VALUE p, ary = rb_ary_new();
for (p = mod; p; p = RCLASS_SUPER(p)) { for (p = mod; p; p = RCLASS_SUPER(p)) {
if (FL_TEST(p, FL_SINGLETON))
continue;
if (BUILTIN_TYPE(p) == T_ICLASS) { if (BUILTIN_TYPE(p) == T_ICLASS) {
rb_ary_push(ary, RBASIC(p)->klass); rb_ary_push(ary, RBASIC(p)->klass);
} }
@ -971,6 +1119,10 @@ method_entry_i(st_data_t key, st_data_t value, st_data_t data)
st_table *list = (st_table *)data; st_table *list = (st_table *)data;
long type; long type;
if (me && me->def->type == VM_METHOD_TYPE_REFINED) {
me = rb_resolve_refined_method(Qnil, me, NULL);
if (!me) return ST_CONTINUE;
}
if (!st_lookup(list, key, 0)) { if (!st_lookup(list, key, 0)) {
if (UNDEFINED_METHOD_ENTRY_P(me)) { if (UNDEFINED_METHOD_ENTRY_P(me)) {
type = -1; /* none */ type = -1; /* none */
@ -1106,13 +1258,14 @@ rb_class_public_instance_methods(int argc, VALUE *argv, VALUE mod)
/* /*
* call-seq: * call-seq:
* obj.methods(all=true) -> array * obj.methods(regular=true) -> array
* *
* Returns a list of the names of public and protected methods of * Returns a list of the names of public and protected methods of
* <i>obj</i>. This will include all the methods accessible in * <i>obj</i>. This will include all the methods accessible in
* <i>obj</i>'s ancestors. * <i>obj</i>'s ancestors.
* If the <i>all</i> parameter is set to <code>false</code>, only those methods * If the <i>regular</i> parameter is set to <code>false</code>,
* in the receiver will be listed. * Returns an array of obj's public and protected singleton methods,
* the array will not include methods in modules included in <i>obj</i>.
* *
* class Klass * class Klass
* def klass_method() * def klass_method()
@ -1123,6 +1276,14 @@ rb_class_public_instance_methods(int argc, VALUE *argv, VALUE mod)
* # :==~, :!, :eql? * # :==~, :!, :eql?
* # :hash, :<=>, :class, :singleton_class] * # :hash, :<=>, :class, :singleton_class]
* k.methods.length #=> 57 * k.methods.length #=> 57
*
* k.methods(false) #=> []
* def k.singleton_method; end
* k.methods(false) #=> [:singleton_method]
*
* module M123; def m123; end end
* k.extend M123
* k.methods(false) #=> [:singleton_method]
*/ */
VALUE VALUE
@ -1225,8 +1386,8 @@ rb_obj_public_methods(int argc, VALUE *argv, VALUE obj)
VALUE VALUE
rb_obj_singleton_methods(int argc, VALUE *argv, VALUE obj) rb_obj_singleton_methods(int argc, VALUE *argv, VALUE obj)
{ {
VALUE recur, ary, klass; VALUE recur, ary, klass, origin;
st_table *list; st_table *list, *mtbl;
if (argc == 0) { if (argc == 0) {
recur = Qtrue; recur = Qtrue;
@ -1235,16 +1396,17 @@ rb_obj_singleton_methods(int argc, VALUE *argv, VALUE obj)
rb_scan_args(argc, argv, "01", &recur); rb_scan_args(argc, argv, "01", &recur);
} }
klass = CLASS_OF(obj); klass = CLASS_OF(obj);
origin = RCLASS_ORIGIN(klass);
list = st_init_numtable(); list = st_init_numtable();
if (klass && FL_TEST(klass, FL_SINGLETON)) { if (klass && FL_TEST(klass, FL_SINGLETON)) {
if (RCLASS_M_TBL(klass)) if ((mtbl = RCLASS_M_TBL(origin)) != 0)
st_foreach(RCLASS_M_TBL(klass), method_entry_i, (st_data_t)list); st_foreach(mtbl, method_entry_i, (st_data_t)list);
klass = RCLASS_SUPER(klass); klass = RCLASS_SUPER(klass);
} }
if (RTEST(recur)) { if (RTEST(recur)) {
while (klass && (FL_TEST(klass, FL_SINGLETON) || RB_TYPE_P(klass, T_ICLASS))) { while (klass && (FL_TEST(klass, FL_SINGLETON) || RB_TYPE_P(klass, T_ICLASS))) {
if (RCLASS_M_TBL(klass)) if (klass != origin && (mtbl = RCLASS_M_TBL(klass)) != 0)
st_foreach(RCLASS_M_TBL(klass), method_entry_i, (st_data_t)list); st_foreach(mtbl, method_entry_i, (st_data_t)list);
klass = RCLASS_SUPER(klass); klass = RCLASS_SUPER(klass);
} }
} }
@ -1397,7 +1559,7 @@ singleton_class_of(VALUE obj)
else { else {
enum ruby_value_type type = BUILTIN_TYPE(obj); enum ruby_value_type type = BUILTIN_TYPE(obj);
if (type == T_FLOAT || type == T_BIGNUM) { if (type == T_FLOAT || type == T_BIGNUM) {
rb_raise(rb_eTypeError, "can't define singleton"); rb_raise(rb_eTypeError, "can't define singleton");
} }
} }
@ -1415,17 +1577,31 @@ singleton_class_of(VALUE obj)
else { else {
FL_UNSET(klass, FL_TAINT); FL_UNSET(klass, FL_TAINT);
} }
if (OBJ_UNTRUSTED(obj)) {
OBJ_UNTRUST(klass);
}
else {
FL_UNSET(klass, FL_UNTRUSTED);
}
if (OBJ_FROZEN(obj)) OBJ_FREEZE(klass); if (OBJ_FROZEN(obj)) OBJ_FREEZE(klass);
return klass; return klass;
} }
/*!
* Returns the singleton class of \a obj, or nil if obj is not a
* singleton object.
*
* \param obj an arbitrary object.
* \return the singleton class or nil.
*/
VALUE
rb_singleton_class_get(VALUE obj)
{
VALUE klass;
if (SPECIAL_CONST_P(obj)) {
return rb_special_singleton_class(obj);
}
klass = RBASIC(obj)->klass;
if (!FL_TEST(klass, FL_SINGLETON)) return Qnil;
if (rb_ivar_get(klass, id_attached) != obj) return Qnil;
return klass;
}
/*! /*!
* Returns the singleton class of \a obj. Creates it if necessary. * Returns the singleton class of \a obj. Creates it if necessary.
@ -1609,8 +1785,11 @@ rb_scan_args(int argc, const VALUE *argv, const char *fmt, ...)
} }
else { else {
hash = rb_check_hash_type(last); hash = rb_check_hash_type(last);
if (!NIL_P(hash)) if (!NIL_P(hash)) {
argc--; VALUE opts = rb_extract_keywords(&hash);
if (!hash) argc--;
hash = opts ? opts : Qnil;
}
} }
} }
/* capture leading mandatory arguments */ /* capture leading mandatory arguments */
@ -1674,6 +1853,119 @@ rb_scan_args(int argc, const VALUE *argv, const char *fmt, ...)
return argc; return argc;
} }
NORETURN(static void keyword_error(const char *error, VALUE keys));
static void
keyword_error(const char *error, VALUE keys)
{
const char *msg = "";
if (RARRAY_LEN(keys) == 1) {
keys = RARRAY_AREF(keys, 0);
}
else {
keys = rb_ary_join(keys, rb_usascii_str_new2(", "));
msg = "s";
}
rb_raise(rb_eArgError, "%s keyword%s: %"PRIsVALUE, error, msg, keys);
}
NORETURN(static void unknown_keyword_error(VALUE hash, const ID *table, int keywords));
static void
unknown_keyword_error(VALUE hash, const ID *table, int keywords)
{
VALUE keys;
int i;
for (i = 0; i < keywords; i++) {
rb_hash_delete(hash, ID2SYM(table[i]));
}
keys = rb_funcall(hash, rb_intern("keys"), 0, 0);
if (!RB_TYPE_P(keys, T_ARRAY)) rb_raise(rb_eArgError, "unknown keyword");
keyword_error("unknown", keys);
}
static int
separate_symbol(st_data_t key, st_data_t value, st_data_t arg)
{
VALUE *kwdhash = (VALUE *)arg;
if (!SYMBOL_P(key)) kwdhash++;
if (!*kwdhash) *kwdhash = rb_hash_new();
rb_hash_aset(*kwdhash, (VALUE)key, (VALUE)value);
return ST_CONTINUE;
}
VALUE
rb_extract_keywords(VALUE *orighash)
{
VALUE parthash[2] = {0, 0};
VALUE hash = *orighash;
if (RHASH_EMPTY_P(hash)) {
*orighash = 0;
return hash;
}
st_foreach(rb_hash_tbl_raw(hash), separate_symbol, (st_data_t)&parthash);
*orighash = parthash[1];
return parthash[0];
}
int
rb_get_kwargs(VALUE keyword_hash, const ID *table, int required, int optional, VALUE *values)
{
int i = 0, j;
int rest = 0;
VALUE missing = Qnil;
st_data_t key;
#define extract_kwarg(keyword, val) \
(key = (st_data_t)(keyword), values ? \
st_delete(rb_hash_tbl_raw(keyword_hash), &key, (val)) : \
st_lookup(rb_hash_tbl_raw(keyword_hash), key, (val)))
if (optional < 0) {
rest = 1;
optional = -1-optional;
}
if (values) {
for (j = 0; j < required + optional; j++) {
values[j] = Qundef;
}
}
if (required) {
for (; i < required; i++) {
VALUE keyword = ID2SYM(table[i]);
if (keyword_hash) {
st_data_t val;
if (extract_kwarg(keyword, &val)) {
if (values) values[i] = (VALUE)val;
continue;
}
}
if (NIL_P(missing)) missing = rb_ary_tmp_new(1);
rb_ary_push(missing, keyword);
}
if (!NIL_P(missing)) {
keyword_error("missing", missing);
}
}
j = i;
if (optional && keyword_hash) {
for (i = 0; i < optional; i++) {
st_data_t val;
if (extract_kwarg(ID2SYM(table[required+i]), &val)) {
if (values) values[required+i] = (VALUE)val;
j++;
}
}
}
if (!rest && keyword_hash) {
if (RHASH_SIZE(keyword_hash) > (unsigned int)j) {
unknown_keyword_error(keyword_hash, table, required+optional);
}
}
return j;
#undef extract_kwarg
}
/*! /*!
* \} * \}
*/ */

269
common.mk
View file

@ -14,7 +14,7 @@ RUBYLIB = $(PATH_SEPARATOR)
RUBYOPT = - RUBYOPT = -
RUN_OPTS = --disable-gems RUN_OPTS = --disable-gems
SPEC_GIT_BASE = git://github.com/rubyspec SPEC_GIT_BASE = git://github.com/nurse
MSPEC_GIT_URL = $(SPEC_GIT_BASE)/mspec.git MSPEC_GIT_URL = $(SPEC_GIT_BASE)/mspec.git
RUBYSPEC_GIT_URL = $(SPEC_GIT_BASE)/rubyspec.git RUBYSPEC_GIT_URL = $(SPEC_GIT_BASE)/rubyspec.git
@ -33,7 +33,7 @@ MAINOBJ = $(NORMALMAINOBJ)
EXTOBJS = EXTOBJS =
DLDOBJS = $(DMYEXT) DLDOBJS = $(DMYEXT)
EXTSOLIBS = EXTSOLIBS =
MINIOBJS = $(ARCHMINIOBJS) dmyencoding.$(OBJEXT) dmyversion.$(OBJEXT) miniprelude.$(OBJEXT) MINIOBJS = $(ARCHMINIOBJS) miniinit.$(OBJEXT) miniprelude.$(OBJEXT)
ENC_MK = enc.mk ENC_MK = enc.mk
COMMONOBJS = array.$(OBJEXT) \ COMMONOBJS = array.$(OBJEXT) \
@ -43,6 +43,7 @@ COMMONOBJS = array.$(OBJEXT) \
complex.$(OBJEXT) \ complex.$(OBJEXT) \
dir.$(OBJEXT) \ dir.$(OBJEXT) \
dln_find.$(OBJEXT) \ dln_find.$(OBJEXT) \
encoding.$(OBJEXT) \
enum.$(OBJEXT) \ enum.$(OBJEXT) \
enumerator.$(OBJEXT) \ enumerator.$(OBJEXT) \
error.$(OBJEXT) \ error.$(OBJEXT) \
@ -84,6 +85,7 @@ COMMONOBJS = array.$(OBJEXT) \
transcode.$(OBJEXT) \ transcode.$(OBJEXT) \
util.$(OBJEXT) \ util.$(OBJEXT) \
variable.$(OBJEXT) \ variable.$(OBJEXT) \
version.$(OBJEXT) \
compile.$(OBJEXT) \ compile.$(OBJEXT) \
debug.$(OBJEXT) \ debug.$(OBJEXT) \
iseq.$(OBJEXT) \ iseq.$(OBJEXT) \
@ -98,8 +100,8 @@ COMMONOBJS = array.$(OBJEXT) \
$(MISSING) $(MISSING)
EXPORTOBJS = $(DLNOBJ) \ EXPORTOBJS = $(DLNOBJ) \
encoding.$(OBJEXT) \ localeinit.$(OBJEXT) \
version.$(OBJEXT) \ loadpath.$(OBJEXT) \
$(COMMONOBJS) $(COMMONOBJS)
OBJS = $(EXPORTOBJS) prelude.$(OBJEXT) OBJS = $(EXPORTOBJS) prelude.$(OBJEXT)
@ -109,8 +111,6 @@ GOLFOBJS = goruby.$(OBJEXT) golf_prelude.$(OBJEXT)
PRELUDE_SCRIPTS = $(srcdir)/prelude.rb $(srcdir)/enc/prelude.rb $(DEFAULT_PRELUDES) PRELUDE_SCRIPTS = $(srcdir)/prelude.rb $(srcdir)/enc/prelude.rb $(DEFAULT_PRELUDES)
GEM_PRELUDE = $(srcdir)/gem_prelude.rb GEM_PRELUDE = $(srcdir)/gem_prelude.rb
YES_GEM_PRELUDE = $(GEM_PRELUDE)
NO_GEM_PRELUDE =
PRELUDES = prelude.c miniprelude.c PRELUDES = prelude.c miniprelude.c
GOLFPRELUDES = golf_prelude.c GOLFPRELUDES = golf_prelude.c
@ -120,7 +120,7 @@ SCRIPT_ARGS = --dest-dir="$(DESTDIR)" \
--make-flags="$(MAKEFLAGS)" --make-flags="$(MAKEFLAGS)"
EXTMK_ARGS = $(SCRIPT_ARGS) --extension $(EXTS) --extstatic $(EXTSTATIC) \ EXTMK_ARGS = $(SCRIPT_ARGS) --extension $(EXTS) --extstatic $(EXTSTATIC) \
--make-flags="V=$(V) MINIRUBY='$(MINIRUBY)'" -- --make-flags="V=$(V) MINIRUBY='$(MINIRUBY)'" --
INSTRUBY = $(SUDO) $(MINIRUBY) $(srcdir)/tool/rbinstall.rb INSTRUBY = $(SUDO) $(RUNRUBY) -r./$(arch)-fake $(srcdir)/tool/rbinstall.rb
INSTRUBY_ARGS = $(SCRIPT_ARGS) \ INSTRUBY_ARGS = $(SCRIPT_ARGS) \
--data-mode=$(INSTALL_DATA_MODE) \ --data-mode=$(INSTALL_DATA_MODE) \
--prog-mode=$(INSTALL_PROG_MODE) \ --prog-mode=$(INSTALL_PROG_MODE) \
@ -159,12 +159,13 @@ showflags:
" DLDFLAGS = $(DLDFLAGS)" \ " DLDFLAGS = $(DLDFLAGS)" \
" SOLIBS = $(SOLIBS)" \ " SOLIBS = $(SOLIBS)" \
$(MESSAGE_END) $(MESSAGE_END)
-@$(CC_VERSION)
.PHONY: showconfig .PHONY: showconfig
showconfig: showconfig:
@$(MESSAGE_BEGIN) \ @$(ECHO_BEGIN) \
"$(configure_args)" \ $(configure_args) \
$(MESSAGE_END) $(ECHO_END)
exts: build-ext exts: build-ext
@ -183,9 +184,6 @@ $(MKMAIN_CMD): $(MKFILES) all-incs $(PREP) $(RBCONFIG) $(LIBRUBY)
prog: program wprogram prog: program wprogram
loadpath: $(PREP) PHONY
$(MINIRUBY) -e 'p $$:'
$(PREP): $(MKFILES) $(PREP): $(MKFILES)
miniruby$(EXEEXT): config.status $(ALLOBJS) $(ARCHFILE) $(DTRACE_OBJ) miniruby$(EXEEXT): config.status $(ALLOBJS) $(ARCHFILE) $(DTRACE_OBJ)
@ -206,10 +204,11 @@ $(CAPIOUT)/.timestamp: Doxyfile $(PREP)
Doxyfile: $(srcdir)/template/Doxyfile.tmpl $(PREP) $(srcdir)/tool/generic_erb.rb $(RBCONFIG) Doxyfile: $(srcdir)/template/Doxyfile.tmpl $(PREP) $(srcdir)/tool/generic_erb.rb $(RBCONFIG)
$(ECHO) generating $@ $(ECHO) generating $@
$(Q) $(MINIRUBY) $(srcdir)/tool/generic_erb.rb -o $@ $(srcdir)/template/Doxyfile.tmpl \ $(Q) $(MINIRUBY) $(srcdir)/tool/generic_erb.rb -o $@ $(srcdir)/template/Doxyfile.tmpl \
--srcdir="$(srcdir)" --miniruby="$(MINIRUBY)" --srcdir="$(srcdir)" --miniruby="$(BASERUBY)"
program: showflags $(PROGRAM) program: showflags $(PROGRAM)
wprogram: showflags $(WPROGRAM) wprogram: showflags $(WPROGRAM)
mini: PHONY miniruby$(EXEEXT)
$(PROGRAM) $(WPROGRAM): $(LIBRUBY) $(MAINOBJ) $(OBJS) $(EXTOBJS) $(SETUP) $(PREP) $(PROGRAM) $(WPROGRAM): $(LIBRUBY) $(MAINOBJ) $(OBJS) $(EXTOBJS) $(SETUP) $(PREP)
@ -224,8 +223,8 @@ $(STATIC_RUBY)$(EXEEXT): $(MAINOBJ) $(DLDOBJS) $(EXTOBJS) $(LIBRUBY_A)
$(Q)$(RM) $@ $(Q)$(RM) $@
$(PURIFY) $(CC) $(MAINOBJ) $(DLDOBJS) $(EXTOBJS) $(LIBRUBY_A) $(MAINLIBS) $(EXTLIBS) $(LIBS) $(OUTFLAG)$@ $(LDFLAGS) $(XLDFLAGS) $(PURIFY) $(CC) $(MAINOBJ) $(DLDOBJS) $(EXTOBJS) $(LIBRUBY_A) $(MAINLIBS) $(EXTLIBS) $(LIBS) $(OUTFLAG)$@ $(LDFLAGS) $(XLDFLAGS)
ruby.imp: $(EXPORTOBJS) ruby.imp: $(COMMONOBJS)
$(Q)$(NM) -Pgp $(EXPORTOBJS) | \ $(Q)$(NM) -Pgp $(COMMONOBJS) | \
awk 'BEGIN{print "#!"}; $$2~/^[BDT]$$/&&$$1!~/^(Init_|.*_threadptr_|\.)/{print $$1}' | \ awk 'BEGIN{print "#!"}; $$2~/^[BDT]$$/&&$$1!~/^(Init_|.*_threadptr_|\.)/{print $$1}' | \
sort -u -o $@ sort -u -o $@
@ -262,7 +261,7 @@ post-install-ext:: post-install-ext-arch post-install-ext-comm
install-arch: pre-install-arch do-install-arch post-install-arch install-arch: pre-install-arch do-install-arch post-install-arch
pre-install-arch:: pre-install-bin pre-install-ext-arch pre-install-arch:: pre-install-bin pre-install-ext-arch
do-install-arch: main do-install-arch: main
$(INSTRUBY) --make="$(MAKE)" $(INSTRUBY_ARGS) --install=bin --install=ext-arch $(INSTRUBY) --make="$(MAKE)" $(INSTRUBY_ARGS) --install=arch
post-install-arch:: post-install-bin post-install-ext-arch post-install-arch:: post-install-bin post-install-ext-arch
install-comm: pre-install-comm do-install-comm post-install-comm install-comm: pre-install-comm do-install-comm post-install-comm
@ -323,6 +322,11 @@ dont-install-all: $(PROGRAM)
post-no-install-all:: post-no-install-local post-no-install-ext post-no-install-doc post-no-install-all:: post-no-install-local post-no-install-ext post-no-install-doc
@$(NULLCMD) @$(NULLCMD)
uninstall: $(INSTALLED_LIST)
$(Q)$(SUDO) $(MINIRUBY) $(srcdir)/tool/rbuninstall.rb --destdir=$(DESTDIR) $(INSTALLED_LIST)
reinstall: uninstall install
what-where-nodoc: no-install-nodoc what-where-nodoc: no-install-nodoc
no-install-nodoc: pre-no-install-nodoc dont-install-nodoc post-no-install-nodoc no-install-nodoc: pre-no-install-nodoc dont-install-nodoc post-no-install-nodoc
pre-no-install-nodoc:: pre-no-install-local pre-no-install-ext pre-no-install-nodoc:: pre-no-install-local pre-no-install-ext
@ -405,6 +409,13 @@ do-install-doc: $(PROGRAM)
post-install-doc:: post-install-doc::
@$(NULLCMD) @$(NULLCMD)
install-gem: pre-install-gem do-install-gem post-install-gem
pre-install-gem:: pre-install-bin pre-install-lib pre-install-man
do-install-gem: $(PROGRAM)
$(INSTRUBY) --make="$(MAKE)" $(INSTRUBY_ARGS) --install=gem
post-install-gem::
@$(NULLCMD)
rdoc: PHONY main rdoc: PHONY main
@echo Generating RDoc documentation @echo Generating RDoc documentation
$(Q) $(XRUBY) "$(srcdir)/bin/rdoc" --root "$(srcdir)" --page-dir "$(srcdir)/doc" --encoding=UTF-8 --no-force-update --all --ri --op "$(RDOCOUT)" --debug $(RDOCFLAGS) "$(srcdir)" $(Q) $(XRUBY) "$(srcdir)/bin/rdoc" --root "$(srcdir)" --page-dir "$(srcdir)/doc" --encoding=UTF-8 --no-force-update --all --ri --op "$(RDOCOUT)" --debug $(RDOCFLAGS) "$(srcdir)"
@ -413,6 +424,16 @@ rdoc-coverage: PHONY main
@echo Generating RDoc coverage report @echo Generating RDoc coverage report
$(Q) $(XRUBY) "$(srcdir)/bin/rdoc" --root "$(srcdir)" --encoding=UTF-8 --all --quiet -C $(RDOCFLAGS) "$(srcdir)" $(Q) $(XRUBY) "$(srcdir)/bin/rdoc" --root "$(srcdir)" --encoding=UTF-8 --all --quiet -C $(RDOCFLAGS) "$(srcdir)"
RDOCBENCHOUT=/tmp/rdocbench
GCBENCH_ITEM=null
gcbench: PHONY
$(Q) $(XRUBY) "$(srcdir)/benchmark/gc/gcbench.rb" $(GCBENCH_ITEM)
gcbench-rdoc: PHONY
$(Q) $(XRUBY) "$(srcdir)/benchmark/gc/gcbench.rb" rdoc
nodoc: PHONY nodoc: PHONY
what-where-doc: no-install-doc what-where-doc: no-install-doc
@ -425,7 +446,7 @@ post-no-install-doc::
CLEAR_INSTALLED_LIST = clear-installed-list CLEAR_INSTALLED_LIST = clear-installed-list
install-prereq: $(CLEAR_INSTALLED_LIST) PHONY install-prereq: $(CLEAR_INSTALLED_LIST) yes-fake PHONY
clear-installed-list: PHONY clear-installed-list: PHONY
@> $(INSTALLED_LIST) set MAKE="$(MAKE)" @> $(INSTALLED_LIST) set MAKE="$(MAKE)"
@ -447,7 +468,7 @@ clean-docs: clean-rdoc clean-capi
distclean: distclean-ext distclean-local distclean-enc distclean-golf distclean-extout distclean-platform distclean: distclean-ext distclean-local distclean-enc distclean-golf distclean-extout distclean-platform
distclean-local:: clean-local distclean-local:: clean-local
$(Q)$(RM) $(MKFILES) yasmdata.rb *.inc $(Q)$(RM) $(MKFILES) yasmdata.rb *.inc
$(Q)$(RM) config.cache config.status config.status.lineno $(PRELUDES) $(Q)$(RM) config.cache config.status config.status.lineno
$(Q)$(RM) *~ *.bak *.stackdump core *.core gmon.out $(PREP) $(Q)$(RM) *~ *.bak *.stackdump core *.core gmon.out $(PREP)
distclean-ext:: PHONY distclean-ext:: PHONY
distclean-golf: clean-golf distclean-golf: clean-golf
@ -459,14 +480,15 @@ distclean-platform: clean-platform
realclean:: realclean-ext realclean-local realclean-enc realclean-golf realclean-extout realclean:: realclean-ext realclean-local realclean-enc realclean-golf realclean-extout
realclean-local:: distclean-local realclean-local:: distclean-local
$(Q)$(RM) parse.c parse.h lex.c newline.c revision.h $(Q)$(RM) parse.c parse.h lex.c newline.c miniprelude.c revision.h
realclean-ext:: realclean-ext:: PHONY
realclean-golf: distclean-golf realclean-golf: distclean-golf
realclean-capi: PHONY realclean-capi: PHONY
realclean-extout: distclean-extout realclean-extout: distclean-extout
clean-ext distclean-ext realclean-ext:: clean-ext distclean-ext realclean-ext::
$(Q)$(RM) $(EXTS_MK) $(Q)$(RM) $(EXTS_MK)
$(Q)$(RM) $(EXTOUT)/.timestamp/.*.time
clean-enc distclean-enc realclean-enc: PHONY clean-enc distclean-enc realclean-enc: PHONY
@ -481,23 +503,23 @@ no-fake: PHONY
btest: $(TEST_RUNNABLE)-btest btest: $(TEST_RUNNABLE)-btest
no-btest: PHONY no-btest: PHONY
yes-btest: fake miniruby$(EXEEXT) PHONY yes-btest: fake miniruby$(EXEEXT) PHONY
$(BOOTSTRAPRUBY) "$(srcdir)/bootstraptest/runner.rb" --ruby="$(BTESTRUBY)" $(OPTS) $(TESTOPTS) $(BOOTSTRAPRUBY) "$(srcdir)/bootstraptest/runner.rb" --ruby="$(BTESTRUBY) $(RUN_OPTS)" $(OPTS) $(TESTOPTS)
btest-ruby: $(TEST_RUNNABLE)-btest-ruby btest-ruby: $(TEST_RUNNABLE)-btest-ruby
no-btest-ruby: PHONY no-btest-ruby: PHONY
yes-btest-ruby: prog PHONY yes-btest-ruby: prog PHONY
$(Q)$(RUNRUBY) "$(srcdir)/bootstraptest/runner.rb" --ruby="$(PROGRAM) -I$(srcdir)/lib" -q $(OPTS) $(TESTOPTS) $(Q)$(RUNRUBY) "$(srcdir)/bootstraptest/runner.rb" --ruby="$(PROGRAM) -I$(srcdir)/lib $(RUN_OPTS)" -q $(OPTS) $(TESTOPTS)
test-sample: $(TEST_RUNNABLE)-test-sample test-sample: $(TEST_RUNNABLE)-test-sample
no-test-sample: PHONY no-test-sample: PHONY
yes-test-sample: prog PHONY yes-test-sample: prog PHONY
$(Q)$(RUNRUBY) $(srcdir)/tool/rubytest.rb $(OPTS) $(TESTOPTS) $(Q)$(RUNRUBY) $(srcdir)/tool/rubytest.rb --run-opt=$(RUN_OPTS) $(OPTS) $(TESTOPTS)
test-knownbugs: test-knownbug test-knownbugs: test-knownbug
test-knownbug: $(TEST_RUNNABLE)-test-knownbug test-knownbug: $(TEST_RUNNABLE)-test-knownbug
no-test-knownbug: PHONY no-test-knownbug: PHONY
yes-test-knownbug: prog PHONY yes-test-knownbug: prog PHONY
-$(RUNRUBY) "$(srcdir)/bootstraptest/runner.rb" --ruby="$(PROGRAM)" $(OPTS) $(TESTOPTS) $(srcdir)/KNOWNBUGS.rb -$(RUNRUBY) "$(srcdir)/bootstraptest/runner.rb" --ruby="$(PROGRAM) $(RUN_OPTS)" $(OPTS) $(TESTOPTS) $(srcdir)/KNOWNBUGS.rb
test: test-sample btest-ruby test-knownbug test: test-sample btest-ruby test-knownbug
@ -568,7 +590,7 @@ PHONY:
{$(srcdir)}.y.c: {$(srcdir)}.y.c:
$(ECHO) generating $@ $(ECHO) generating $@
$(Q)$(BASERUBY) $(srcdir)/tool/id2token.rb --path-separator=$(PATH_SEPARATOR) --vpath=$(VPATH) id.h $(SRC_FILE) > parse.tmp.y $(Q)$(BASERUBY) $(srcdir)/tool/id2token.rb --path-separator=.$(PATH_SEPARATOR)./ --vpath=$(VPATH) id.h $(SRC_FILE) > parse.tmp.y
$(Q)$(YACC) -d $(YFLAGS) -o y.tab.c parse.tmp.y $(Q)$(YACC) -d $(YFLAGS) -o y.tab.c parse.tmp.y
$(Q)$(RM) parse.tmp.y $(Q)$(RM) parse.tmp.y
$(Q)sed -f $(srcdir)/tool/ytab.sed -e "/^#/s!parse\.tmp\.[iy]!parse.y!" -e "/^#/s!y\.tab\.c!$@!" y.tab.c > $@.new $(Q)sed -f $(srcdir)/tool/ytab.sed -e "/^#/s!parse\.tmp\.[iy]!parse.y!" -e "/^#/s!y\.tab\.c!$@!" y.tab.c > $@.new
@ -576,31 +598,6 @@ PHONY:
$(Q)sed -e "/^#line.*y\.tab\.h/d;/^#line.*parse.*\.y/d" y.tab.h > $(@:.c=.h) $(Q)sed -e "/^#line.*y\.tab\.h/d;/^#line.*parse.*\.y/d" y.tab.h > $(@:.c=.h)
$(Q)$(RM) y.tab.c y.tab.h $(Q)$(RM) y.tab.c y.tab.h
acosh.$(OBJEXT): {$(VPATH)}acosh.c
alloca.$(OBJEXT): {$(VPATH)}alloca.c {$(VPATH)}config.h
crypt.$(OBJEXT): {$(VPATH)}crypt.c
dup2.$(OBJEXT): {$(VPATH)}dup2.c
erf.$(OBJEXT): {$(VPATH)}erf.c
finite.$(OBJEXT): {$(VPATH)}finite.c
flock.$(OBJEXT): {$(VPATH)}flock.c
memcmp.$(OBJEXT): {$(VPATH)}memcmp.c
memmove.$(OBJEXT): {$(VPATH)}memmove.c
mkdir.$(OBJEXT): {$(VPATH)}mkdir.c
setproctitle.$(OBJEXT): {$(VPATH)}setproctitle.c {$(VPATH)}util.h $(RUBY_H_INCLUDES)
strchr.$(OBJEXT): {$(VPATH)}strchr.c
strdup.$(OBJEXT): {$(VPATH)}strdup.c
strerror.$(OBJEXT): {$(VPATH)}strerror.c
strlcat.$(OBJEXT): {$(VPATH)}strlcat.c
strlcpy.$(OBJEXT): {$(VPATH)}strlcpy.c
strstr.$(OBJEXT): {$(VPATH)}strstr.c
strtod.$(OBJEXT): {$(VPATH)}strtod.c
strtol.$(OBJEXT): {$(VPATH)}strtol.c
nt.$(OBJEXT): {$(VPATH)}nt.c
os2.$(OBJEXT): {$(VPATH)}os2.c
dl_os2.$(OBJEXT): {$(VPATH)}dl_os2.c
ia64.$(OBJEXT): {$(VPATH)}ia64.s
$(CC) $(CFLAGS) -c $<
$(PLATFORM_D): $(PLATFORM_D):
$(Q) $(MAKEDIRS) $(PLATFORM_DIR) $(Q) $(MAKEDIRS) $(PLATFORM_DIR)
@exit > $@ @exit > $@
@ -614,18 +611,47 @@ ENCODING_H_INCLUDES= {$(VPATH)}encoding.h {$(VPATH)}oniguruma.h
PROBES_H_INCLUDES = {$(VPATH)}probes.h PROBES_H_INCLUDES = {$(VPATH)}probes.h
VM_CORE_H_INCLUDES = {$(VPATH)}vm_core.h {$(VPATH)}thread_$(THREAD_MODEL).h \ VM_CORE_H_INCLUDES = {$(VPATH)}vm_core.h {$(VPATH)}thread_$(THREAD_MODEL).h \
{$(VPATH)}node.h {$(VPATH)}method.h {$(VPATH)}ruby_atomic.h \ {$(VPATH)}node.h {$(VPATH)}method.h {$(VPATH)}ruby_atomic.h \
{$(VPATH)}vm_debug.h {$(VPATH)}id.h {$(VPATH)}vm_debug.h {$(VPATH)}id.h {$(VPATH)}thread_native.h
###
acosh.$(OBJEXT): {$(VPATH)}acosh.c
alloca.$(OBJEXT): {$(VPATH)}alloca.c {$(VPATH)}config.h
crypt.$(OBJEXT): {$(VPATH)}crypt.c
dup2.$(OBJEXT): {$(VPATH)}dup2.c
erf.$(OBJEXT): {$(VPATH)}erf.c
finite.$(OBJEXT): {$(VPATH)}finite.c
flock.$(OBJEXT): {$(VPATH)}flock.c
memcmp.$(OBJEXT): {$(VPATH)}memcmp.c
memmove.$(OBJEXT): {$(VPATH)}memmove.c
mkdir.$(OBJEXT): {$(VPATH)}mkdir.c
setproctitle.$(OBJEXT): {$(VPATH)}setproctitle.c {$(VPATH)}util.h $(RUBY_H_INCLUDES) $(hdrdir)/ruby.h
strchr.$(OBJEXT): {$(VPATH)}strchr.c
strdup.$(OBJEXT): {$(VPATH)}strdup.c
strerror.$(OBJEXT): {$(VPATH)}strerror.c
strlcat.$(OBJEXT): {$(VPATH)}strlcat.c
strlcpy.$(OBJEXT): {$(VPATH)}strlcpy.c
strstr.$(OBJEXT): {$(VPATH)}strstr.c
strtod.$(OBJEXT): {$(VPATH)}strtod.c
strtol.$(OBJEXT): {$(VPATH)}strtol.c
nt.$(OBJEXT): {$(VPATH)}nt.c
os2.$(OBJEXT): {$(VPATH)}os2.c
dl_os2.$(OBJEXT): {$(VPATH)}dl_os2.c
ia64.$(OBJEXT): {$(VPATH)}ia64.s
$(CC) $(CFLAGS) -c $<
###
addr2line.$(OBJEXT): {$(VPATH)}addr2line.c {$(VPATH)}addr2line.h {$(VPATH)}config.h addr2line.$(OBJEXT): {$(VPATH)}addr2line.c {$(VPATH)}addr2line.h {$(VPATH)}config.h
array.$(OBJEXT): {$(VPATH)}array.c $(RUBY_H_INCLUDES) {$(VPATH)}util.h \ array.$(OBJEXT): {$(VPATH)}array.c $(RUBY_H_INCLUDES) {$(VPATH)}util.h \
$(ENCODING_H_INCLUDES) {$(VPATH)}internal.h $(PROBES_H_INCLUDES) {$(VPATH)}id.h $(ENCODING_H_INCLUDES) {$(VPATH)}internal.h $(PROBES_H_INCLUDES) {$(VPATH)}id.h {$(VPATH)}vm_opts.h
bignum.$(OBJEXT): {$(VPATH)}bignum.c $(RUBY_H_INCLUDES) {$(VPATH)}util.h \ bignum.$(OBJEXT): {$(VPATH)}bignum.c $(RUBY_H_INCLUDES) {$(VPATH)}util.h \
{$(VPATH)}thread.h {$(VPATH)}internal.h {$(VPATH)}thread.h {$(VPATH)}internal.h
class.$(OBJEXT): {$(VPATH)}class.c $(RUBY_H_INCLUDES) \ class.$(OBJEXT): {$(VPATH)}class.c $(RUBY_H_INCLUDES) \
$(VM_CORE_H_INCLUDES) {$(VPATH)}internal.h {$(VPATH)}constant.h $(VM_CORE_H_INCLUDES) {$(VPATH)}internal.h {$(VPATH)}constant.h {$(VPATH)}vm_opts.h
compar.$(OBJEXT): {$(VPATH)}compar.c $(RUBY_H_INCLUDES) compar.$(OBJEXT): {$(VPATH)}compar.c $(RUBY_H_INCLUDES)
complex.$(OBJEXT): {$(VPATH)}complex.c $(RUBY_H_INCLUDES) \ complex.$(OBJEXT): {$(VPATH)}complex.c $(RUBY_H_INCLUDES) \
{$(VPATH)}internal.h {$(VPATH)}internal.h $(hdrdir)/ruby.h
dir.$(OBJEXT): {$(VPATH)}dir.c $(RUBY_H_INCLUDES) {$(VPATH)}util.h \ dir.$(OBJEXT): {$(VPATH)}dir.c $(RUBY_H_INCLUDES) {$(VPATH)}util.h \
$(ENCODING_H_INCLUDES) \ $(ENCODING_H_INCLUDES) \
{$(VPATH)}internal.h {$(VPATH)}internal.h
@ -633,26 +659,23 @@ dln.$(OBJEXT): {$(VPATH)}dln.c {$(VPATH)}dln.h $(RUBY_H_INCLUDES)
dln_find.$(OBJEXT): {$(VPATH)}dln_find.c {$(VPATH)}dln.h $(RUBY_H_INCLUDES) dln_find.$(OBJEXT): {$(VPATH)}dln_find.c {$(VPATH)}dln.h $(RUBY_H_INCLUDES)
dmydln.$(OBJEXT): {$(VPATH)}dmydln.c $(RUBY_H_INCLUDES) dmydln.$(OBJEXT): {$(VPATH)}dmydln.c $(RUBY_H_INCLUDES)
dmyext.$(OBJEXT): {$(VPATH)}dmyext.c dmyext.$(OBJEXT): {$(VPATH)}dmyext.c
dmyencoding.$(OBJEXT): {$(VPATH)}dmyencoding.c $(RUBY_H_INCLUDES) \
{$(VPATH)}regenc.h {$(VPATH)}util.h $(ENCODING_H_INCLUDES) \
{$(VPATH)}encoding.c {$(VPATH)}internal.h
encoding.$(OBJEXT): {$(VPATH)}encoding.c $(RUBY_H_INCLUDES) \ encoding.$(OBJEXT): {$(VPATH)}encoding.c $(RUBY_H_INCLUDES) \
$(ENCODING_H_INCLUDES) {$(VPATH)}regenc.h {$(VPATH)}util.h \ $(ENCODING_H_INCLUDES) {$(VPATH)}regenc.h {$(VPATH)}util.h \
{$(VPATH)}internal.h {$(VPATH)}internal.h
enum.$(OBJEXT): {$(VPATH)}enum.c $(RUBY_H_INCLUDES) {$(VPATH)}node.h \ enum.$(OBJEXT): {$(VPATH)}enum.c $(RUBY_H_INCLUDES) {$(VPATH)}node.h \
{$(VPATH)}util.h {$(VPATH)}id.h {$(VPATH)}util.h {$(VPATH)}id.h {$(VPATH)}internal.h
enumerator.$(OBJEXT): {$(VPATH)}enumerator.c $(RUBY_H_INCLUDES) \ enumerator.$(OBJEXT): {$(VPATH)}enumerator.c $(RUBY_H_INCLUDES) \
{$(VPATH)}internal.h {$(VPATH)}internal.h {$(VPATH)}node.h
error.$(OBJEXT): {$(VPATH)}error.c {$(VPATH)}known_errors.inc \ error.$(OBJEXT): {$(VPATH)}error.c {$(VPATH)}known_errors.inc \
$(RUBY_H_INCLUDES) $(VM_CORE_H_INCLUDES) $(ENCODING_H_INCLUDES) \ $(RUBY_H_INCLUDES) $(VM_CORE_H_INCLUDES) $(ENCODING_H_INCLUDES) \
{$(VPATH)}internal.h {$(VPATH)}internal.h {$(VPATH)}vm_opts.h
eval.$(OBJEXT): {$(VPATH)}eval.c {$(VPATH)}eval_intern.h {$(VPATH)}vm.h \ eval.$(OBJEXT): {$(VPATH)}eval.c {$(VPATH)}eval_intern.h {$(VPATH)}vm.h \
$(RUBY_H_INCLUDES) $(VM_CORE_H_INCLUDES) {$(VPATH)}eval_error.c \ $(RUBY_H_INCLUDES) $(VM_CORE_H_INCLUDES) {$(VPATH)}eval_error.c \
{$(VPATH)}eval_jump.c {$(VPATH)}gc.h {$(VPATH)}iseq.h \ {$(VPATH)}eval_jump.c {$(VPATH)}gc.h {$(VPATH)}iseq.h \
$(ENCODING_H_INCLUDES) {$(VPATH)}internal.h $(PROBES_H_INCLUDES) $(ENCODING_H_INCLUDES) {$(VPATH)}internal.h $(PROBES_H_INCLUDES) {$(VPATH)}vm_opts.h {$(VPATH)}probes_helper.h
load.$(OBJEXT): {$(VPATH)}load.c {$(VPATH)}eval_intern.h \ load.$(OBJEXT): {$(VPATH)}load.c {$(VPATH)}eval_intern.h \
{$(VPATH)}util.h $(RUBY_H_INCLUDES) $(VM_CORE_H_INCLUDES) \ {$(VPATH)}util.h $(RUBY_H_INCLUDES) $(VM_CORE_H_INCLUDES) \
{$(VPATH)}dln.h {$(VPATH)}internal.h $(PROBES_H_INCLUDES) {$(VPATH)}dln.h {$(VPATH)}internal.h $(PROBES_H_INCLUDES) {$(VPATH)}vm_opts.h
file.$(OBJEXT): {$(VPATH)}file.c $(RUBY_H_INCLUDES) {$(VPATH)}io.h \ file.$(OBJEXT): {$(VPATH)}file.c $(RUBY_H_INCLUDES) {$(VPATH)}io.h \
$(ENCODING_H_INCLUDES) {$(VPATH)}util.h {$(VPATH)}dln.h \ $(ENCODING_H_INCLUDES) {$(VPATH)}util.h {$(VPATH)}dln.h \
{$(VPATH)}internal.h {$(VPATH)}internal.h
@ -660,44 +683,45 @@ gc.$(OBJEXT): {$(VPATH)}gc.c $(RUBY_H_INCLUDES) {$(VPATH)}re.h \
{$(VPATH)}regex.h $(ENCODING_H_INCLUDES) $(VM_CORE_H_INCLUDES) \ {$(VPATH)}regex.h $(ENCODING_H_INCLUDES) $(VM_CORE_H_INCLUDES) \
{$(VPATH)}gc.h {$(VPATH)}io.h {$(VPATH)}eval_intern.h {$(VPATH)}util.h \ {$(VPATH)}gc.h {$(VPATH)}io.h {$(VPATH)}eval_intern.h {$(VPATH)}util.h \
{$(VPATH)}internal.h {$(VPATH)}constant.h \ {$(VPATH)}internal.h {$(VPATH)}constant.h \
{$(VPATH)}thread.h $(PROBES_H_INCLUDES) {$(VPATH)}thread.h $(PROBES_H_INCLUDES) {$(VPATH)}vm_opts.h {$(VPATH)}debug.h
hash.$(OBJEXT): {$(VPATH)}hash.c $(RUBY_H_INCLUDES) {$(VPATH)}util.h \ hash.$(OBJEXT): {$(VPATH)}hash.c $(RUBY_H_INCLUDES) {$(VPATH)}util.h \
$(ENCODING_H_INCLUDES) {$(VPATH)}internal.h $(PROBES_H_INCLUDES) $(ENCODING_H_INCLUDES) {$(VPATH)}internal.h $(PROBES_H_INCLUDES) {$(VPATH)}vm_opts.h
inits.$(OBJEXT): {$(VPATH)}inits.c $(RUBY_H_INCLUDES) \ inits.$(OBJEXT): {$(VPATH)}inits.c $(RUBY_H_INCLUDES) \
{$(VPATH)}internal.h {$(VPATH)}internal.h
io.$(OBJEXT): {$(VPATH)}io.c $(RUBY_H_INCLUDES) {$(VPATH)}io.h \ io.$(OBJEXT): {$(VPATH)}io.c $(RUBY_H_INCLUDES) {$(VPATH)}io.h \
{$(VPATH)}util.h $(ENCODING_H_INCLUDES) {$(VPATH)}dln.h \ {$(VPATH)}util.h $(ENCODING_H_INCLUDES) {$(VPATH)}dln.h \
{$(VPATH)}internal.h {$(VPATH)}thread.h {$(VPATH)}id.h {$(VPATH)}internal.h {$(VPATH)}thread.h {$(VPATH)}id.h {$(VPATH)}ruby_atomic.h
main.$(OBJEXT): {$(VPATH)}main.c $(RUBY_H_INCLUDES) {$(VPATH)}node.h {$(VPATH)}vm_debug.h main.$(OBJEXT): {$(VPATH)}main.c $(RUBY_H_INCLUDES) {$(VPATH)}node.h {$(VPATH)}vm_debug.h {$(VPATH)}vm_opts.h $(hdrdir)/ruby.h
marshal.$(OBJEXT): {$(VPATH)}marshal.c $(RUBY_H_INCLUDES) {$(VPATH)}io.h \ marshal.$(OBJEXT): {$(VPATH)}marshal.c $(RUBY_H_INCLUDES) {$(VPATH)}io.h \
$(ENCODING_H_INCLUDES) {$(VPATH)}util.h {$(VPATH)}internal.h $(ENCODING_H_INCLUDES) {$(VPATH)}util.h {$(VPATH)}internal.h
math.$(OBJEXT): {$(VPATH)}math.c $(RUBY_H_INCLUDES) \ math.$(OBJEXT): {$(VPATH)}math.c $(RUBY_H_INCLUDES) \
{$(VPATH)}internal.h {$(VPATH)}internal.h
node.$(OBJEXT): {$(VPATH)}node.c $(RUBY_H_INCLUDES) \ node.$(OBJEXT): {$(VPATH)}node.c $(RUBY_H_INCLUDES) \
$(VM_CORE_H_INCLUDES) $(VM_CORE_H_INCLUDES) {$(VPATH)}vm_opts.h {$(VPATH)}internal.h
numeric.$(OBJEXT): {$(VPATH)}numeric.c $(RUBY_H_INCLUDES) \ numeric.$(OBJEXT): {$(VPATH)}numeric.c $(RUBY_H_INCLUDES) \
{$(VPATH)}util.h $(ENCODING_H_INCLUDES) {$(VPATH)}internal.h {$(VPATH)}id.h {$(VPATH)}util.h $(ENCODING_H_INCLUDES) {$(VPATH)}internal.h {$(VPATH)}id.h
object.$(OBJEXT): {$(VPATH)}object.c $(RUBY_H_INCLUDES) {$(VPATH)}util.h \ object.$(OBJEXT): {$(VPATH)}object.c $(RUBY_H_INCLUDES) {$(VPATH)}util.h \
{$(VPATH)}internal.h {$(VPATH)}constant.h $(ENCODING_H_INCLUDES) $(PROBES_H_INCLUDES) {$(VPATH)}internal.h {$(VPATH)}constant.h $(ENCODING_H_INCLUDES) $(PROBES_H_INCLUDES) \
{$(VPATH)}vm_opts.h {$(VPATH)}id.h
pack.$(OBJEXT): {$(VPATH)}pack.c $(RUBY_H_INCLUDES) {$(VPATH)}encoding.h \ pack.$(OBJEXT): {$(VPATH)}pack.c $(RUBY_H_INCLUDES) {$(VPATH)}encoding.h \
{$(VPATH)}oniguruma.h {$(VPATH)}oniguruma.h {$(VPATH)}internal.h
parse.$(OBJEXT): {$(VPATH)}parse.c $(RUBY_H_INCLUDES) {$(VPATH)}node.h \ parse.$(OBJEXT): {$(VPATH)}parse.c $(RUBY_H_INCLUDES) {$(VPATH)}node.h \
$(ENCODING_H_INCLUDES) {$(VPATH)}id.h {$(VPATH)}regenc.h \ $(ENCODING_H_INCLUDES) {$(VPATH)}id.h {$(VPATH)}regenc.h \
{$(VPATH)}regex.h {$(VPATH)}util.h {$(VPATH)}lex.c \ {$(VPATH)}regex.h {$(VPATH)}util.h {$(VPATH)}lex.c \
{$(VPATH)}defs/keywords {$(VPATH)}id.c {$(VPATH)}parse.y \ {$(VPATH)}defs/keywords {$(VPATH)}id.c {$(VPATH)}parse.y \
{$(VPATH)}parse.h {$(VPATH)}internal.h $(PROBES_H_INCLUDES) {$(VPATH)}parse.h {$(VPATH)}internal.h $(PROBES_H_INCLUDES) {$(VPATH)}vm_opts.h
proc.$(OBJEXT): {$(VPATH)}proc.c {$(VPATH)}eval_intern.h \ proc.$(OBJEXT): {$(VPATH)}proc.c {$(VPATH)}eval_intern.h \
$(RUBY_H_INCLUDES) {$(VPATH)}gc.h $(VM_CORE_H_INCLUDES) \ $(RUBY_H_INCLUDES) {$(VPATH)}gc.h $(VM_CORE_H_INCLUDES) \
{$(VPATH)}internal.h {$(VPATH)}iseq.h {$(VPATH)}internal.h {$(VPATH)}iseq.h {$(VPATH)}vm_opts.h
process.$(OBJEXT): {$(VPATH)}process.c $(RUBY_H_INCLUDES) \ process.$(OBJEXT): {$(VPATH)}process.c $(RUBY_H_INCLUDES) \
{$(VPATH)}util.h {$(VPATH)}io.h $(ENCODING_H_INCLUDES) {$(VPATH)}dln.h \ {$(VPATH)}util.h {$(VPATH)}io.h $(ENCODING_H_INCLUDES) {$(VPATH)}dln.h \
$(VM_CORE_H_INCLUDES) {$(VPATH)}internal.h \ $(VM_CORE_H_INCLUDES) {$(VPATH)}internal.h \
{$(VPATH)}thread.h {$(VPATH)}thread.h {$(VPATH)}vm_opts.h
random.$(OBJEXT): {$(VPATH)}random.c $(RUBY_H_INCLUDES) \ random.$(OBJEXT): {$(VPATH)}random.c $(RUBY_H_INCLUDES) \
{$(VPATH)}siphash.c {$(VPATH)}siphash.h {$(VPATH)}siphash.c {$(VPATH)}siphash.h {$(VPATH)}internal.h
range.$(OBJEXT): {$(VPATH)}range.c $(RUBY_H_INCLUDES) \ range.$(OBJEXT): {$(VPATH)}range.c $(RUBY_H_INCLUDES) \
$(ENCODING_H_INCLUDES) {$(VPATH)}internal.h {$(VPATH)}id.h $(ENCODING_H_INCLUDES) {$(VPATH)}internal.h {$(VPATH)}id.h
rational.$(OBJEXT): {$(VPATH)}rational.c $(RUBY_H_INCLUDES) {$(VPATH)}internal.h rational.$(OBJEXT): {$(VPATH)}rational.c $(RUBY_H_INCLUDES) {$(VPATH)}internal.h $(hdrdir)/ruby.h
re.$(OBJEXT): {$(VPATH)}re.c $(RUBY_H_INCLUDES) {$(VPATH)}re.h \ re.$(OBJEXT): {$(VPATH)}re.c $(RUBY_H_INCLUDES) {$(VPATH)}re.h \
{$(VPATH)}regex.h $(ENCODING_H_INCLUDES) {$(VPATH)}util.h \ {$(VPATH)}regex.h $(ENCODING_H_INCLUDES) {$(VPATH)}util.h \
{$(VPATH)}regint.h {$(VPATH)}regenc.h {$(VPATH)}internal.h {$(VPATH)}regint.h {$(VPATH)}regenc.h {$(VPATH)}internal.h
@ -717,47 +741,52 @@ regsyntax.$(OBJEXT): {$(VPATH)}regsyntax.c {$(VPATH)}regint.h \
{$(VPATH)}regenc.h {$(VPATH)}oniguruma.h $(RUBY_H_INCLUDES) {$(VPATH)}regenc.h {$(VPATH)}oniguruma.h $(RUBY_H_INCLUDES)
ruby.$(OBJEXT): {$(VPATH)}ruby.c $(RUBY_H_INCLUDES) {$(VPATH)}util.h \ ruby.$(OBJEXT): {$(VPATH)}ruby.c $(RUBY_H_INCLUDES) {$(VPATH)}util.h \
$(ENCODING_H_INCLUDES) {$(VPATH)}eval_intern.h $(VM_CORE_H_INCLUDES) \ $(ENCODING_H_INCLUDES) {$(VPATH)}eval_intern.h $(VM_CORE_H_INCLUDES) \
{$(VPATH)}dln.h {$(VPATH)}internal.h {$(VPATH)}dln.h {$(VPATH)}internal.h {$(VPATH)}vm_opts.h
safe.$(OBJEXT): {$(VPATH)}safe.c $(RUBY_H_INCLUDES) $(VM_CORE_H_INCLUDES) safe.$(OBJEXT): {$(VPATH)}safe.c $(RUBY_H_INCLUDES) $(VM_CORE_H_INCLUDES) {$(VPATH)}vm_opts.h {$(VPATH)}internal.h
signal.$(OBJEXT): {$(VPATH)}signal.c $(RUBY_H_INCLUDES) \ signal.$(OBJEXT): {$(VPATH)}signal.c $(RUBY_H_INCLUDES) \
$(VM_CORE_H_INCLUDES) $(VM_CORE_H_INCLUDES) {$(VPATH)}vm_opts.h {$(VPATH)}internal.h {$(VPATH)}ruby_atomic.h {$(VPATH)}eval_intern.h
sprintf.$(OBJEXT): {$(VPATH)}sprintf.c $(RUBY_H_INCLUDES) {$(VPATH)}re.h \ sprintf.$(OBJEXT): {$(VPATH)}sprintf.c $(RUBY_H_INCLUDES) {$(VPATH)}re.h \
{$(VPATH)}regex.h {$(VPATH)}vsnprintf.c $(ENCODING_H_INCLUDES) {$(VPATH)}regex.h {$(VPATH)}vsnprintf.c $(ENCODING_H_INCLUDES) {$(VPATH)}internal.h
st.$(OBJEXT): {$(VPATH)}st.c $(RUBY_H_INCLUDES) st.$(OBJEXT): {$(VPATH)}st.c $(RUBY_H_INCLUDES)
strftime.$(OBJEXT): {$(VPATH)}strftime.c $(RUBY_H_INCLUDES) \ strftime.$(OBJEXT): {$(VPATH)}strftime.c $(RUBY_H_INCLUDES) \
{$(VPATH)}timev.h $(ENCODING_H_INCLUDES) {$(VPATH)}timev.h $(ENCODING_H_INCLUDES)
string.$(OBJEXT): {$(VPATH)}string.c $(RUBY_H_INCLUDES) {$(VPATH)}re.h \ string.$(OBJEXT): {$(VPATH)}string.c $(RUBY_H_INCLUDES) {$(VPATH)}re.h \
{$(VPATH)}regex.h $(ENCODING_H_INCLUDES) {$(VPATH)}internal.h $(PROBES_H_INCLUDES) {$(VPATH)}regex.h $(ENCODING_H_INCLUDES) {$(VPATH)}internal.h $(PROBES_H_INCLUDES) {$(VPATH)}vm_opts.h {$(VPATH)}node.h {$(VPATH)}ruby_atomic.h {$(VPATH)}vm_core.h {$(VPATH)}vm_debug.h {$(VPATH)}id.h {$(VPATH)}method.h {$(VPATH)}thread_$(THREAD_MODEL).h {$(VPATH)}thread_native.h
struct.$(OBJEXT): {$(VPATH)}struct.c $(RUBY_H_INCLUDES) {$(VPATH)}internal.h struct.$(OBJEXT): {$(VPATH)}struct.c $(RUBY_H_INCLUDES) {$(VPATH)}internal.h
thread.$(OBJEXT): {$(VPATH)}thread.c {$(VPATH)}eval_intern.h \ thread.$(OBJEXT): {$(VPATH)}thread.c {$(VPATH)}eval_intern.h \
$(RUBY_H_INCLUDES) {$(VPATH)}gc.h $(VM_CORE_H_INCLUDES) \ $(RUBY_H_INCLUDES) {$(VPATH)}gc.h $(VM_CORE_H_INCLUDES) \
{$(VPATH)}thread_$(THREAD_MODEL).c $(ENCODING_H_INCLUDES) \ {$(VPATH)}thread_$(THREAD_MODEL).c $(ENCODING_H_INCLUDES) \
{$(VPATH)}internal.h {$(VPATH)}io.h {$(VPATH)}thread.h {$(VPATH)}internal.h {$(VPATH)}io.h {$(VPATH)}thread.h {$(VPATH)}timev.h {$(VPATH)}vm_opts.h
transcode.$(OBJEXT): {$(VPATH)}transcode.c $(RUBY_H_INCLUDES) \ transcode.$(OBJEXT): {$(VPATH)}transcode.c $(RUBY_H_INCLUDES) \
$(ENCODING_H_INCLUDES) {$(VPATH)}transcode_data.h {$(VPATH)}internal.h $(ENCODING_H_INCLUDES) {$(VPATH)}transcode_data.h {$(VPATH)}internal.h
cont.$(OBJEXT): {$(VPATH)}cont.c $(RUBY_H_INCLUDES) \ cont.$(OBJEXT): {$(VPATH)}cont.c $(RUBY_H_INCLUDES) \
$(VM_CORE_H_INCLUDES) {$(VPATH)}gc.h {$(VPATH)}eval_intern.h \ $(VM_CORE_H_INCLUDES) {$(VPATH)}gc.h {$(VPATH)}eval_intern.h \
{$(VPATH)}internal.h {$(VPATH)}internal.h {$(VPATH)}vm_opts.h
time.$(OBJEXT): {$(VPATH)}time.c $(RUBY_H_INCLUDES) \ time.$(OBJEXT): {$(VPATH)}time.c $(RUBY_H_INCLUDES) \
$(ENCODING_H_INCLUDES) {$(VPATH)}timev.h {$(VPATH)}internal.h $(ENCODING_H_INCLUDES) {$(VPATH)}timev.h {$(VPATH)}internal.h
util.$(OBJEXT): {$(VPATH)}util.c $(RUBY_H_INCLUDES) {$(VPATH)}util.h \ util.$(OBJEXT): {$(VPATH)}util.c $(RUBY_H_INCLUDES) {$(VPATH)}util.h \
{$(VPATH)}internal.h {$(VPATH)}internal.h
variable.$(OBJEXT): {$(VPATH)}variable.c $(RUBY_H_INCLUDES) \ variable.$(OBJEXT): {$(VPATH)}variable.c $(RUBY_H_INCLUDES) \
{$(VPATH)}node.h {$(VPATH)}util.h {$(VPATH)}encoding.h \ {$(VPATH)}node.h {$(VPATH)}util.h {$(VPATH)}encoding.h {$(VPATH)}id.h \
{$(VPATH)}oniguruma.h {$(VPATH)}internal.h {$(VPATH)}constant.h {$(VPATH)}oniguruma.h {$(VPATH)}internal.h {$(VPATH)}constant.h
version.$(OBJEXT): {$(VPATH)}version.c $(RUBY_H_INCLUDES) \ version.$(OBJEXT): {$(VPATH)}version.c $(RUBY_H_INCLUDES) \
{$(VPATH)}version.h $(srcdir)/version.h $(srcdir)/revision.h {$(VPATH)}config.h \ $(srcdir)/include/ruby/version.h $(srcdir)/version.h $(srcdir)/revision.h {$(VPATH)}config.h
loadpath.$(OBJEXT): {$(VPATH)}loadpath.c $(RUBY_H_INCLUDES) \
$(srcdir)/include/ruby/version.h $(srcdir)/version.h {$(VPATH)}config.h \
verconf.h verconf.h
dmyversion.$(OBJEXT): {$(VPATH)}dmyversion.c version.$(OBJEXT) localeinit.$(OBJEXT): {$(VPATH)}localeinit.c $(RUBY_H_INCLUDES) \
$(ENCODING_H_INCLUDES) {$(VPATH)}internal.h
miniinit.$(OBJEXT): {$(VPATH)}miniinit.c $(RUBY_H_INCLUDES) \
$(ENCODING_H_INCLUDES)
compile.$(OBJEXT): {$(VPATH)}compile.c {$(VPATH)}iseq.h \ compile.$(OBJEXT): {$(VPATH)}compile.c {$(VPATH)}iseq.h \
$(RUBY_H_INCLUDES) $(VM_CORE_H_INCLUDES) {$(VPATH)}insns.inc \ $(RUBY_H_INCLUDES) $(VM_CORE_H_INCLUDES) {$(VPATH)}insns.inc \
{$(VPATH)}insns_info.inc {$(VPATH)}optinsn.inc \ {$(VPATH)}insns_info.inc {$(VPATH)}optinsn.inc \
{$(VPATH)}optunifs.inc {$(VPATH)}opt_sc.inc {$(VPATH)}insns.inc \ {$(VPATH)}optunifs.inc {$(VPATH)}opt_sc.inc {$(VPATH)}insns.inc \
{$(VPATH)}internal.h {$(VPATH)}internal.h {$(VPATH)}vm_opts.h
iseq.$(OBJEXT): {$(VPATH)}iseq.c {$(VPATH)}gc.h {$(VPATH)}iseq.h \ iseq.$(OBJEXT): {$(VPATH)}iseq.c {$(VPATH)}gc.h {$(VPATH)}iseq.h \
$(RUBY_H_INCLUDES) $(VM_CORE_H_INCLUDES) {$(VPATH)}insns.inc \ $(RUBY_H_INCLUDES) $(VM_CORE_H_INCLUDES) {$(VPATH)}insns.inc \
{$(VPATH)}insns_info.inc {$(VPATH)}node_name.inc {$(VPATH)}internal.h {$(VPATH)}insns_info.inc {$(VPATH)}node_name.inc {$(VPATH)}internal.h {$(VPATH)}vm_opts.h {$(VPATH)}ruby_atomic.h {$(VPATH)}eval_intern.h
vm.$(OBJEXT): {$(VPATH)}vm.c {$(VPATH)}gc.h {$(VPATH)}iseq.h \ vm.$(OBJEXT): {$(VPATH)}vm.c {$(VPATH)}gc.h {$(VPATH)}iseq.h \
{$(VPATH)}eval_intern.h $(RUBY_H_INCLUDES) $(ENCODING_H_INCLUDES) \ {$(VPATH)}eval_intern.h $(RUBY_H_INCLUDES) $(ENCODING_H_INCLUDES) \
$(VM_CORE_H_INCLUDES) {$(VPATH)}vm_method.c {$(VPATH)}vm_eval.c \ $(VM_CORE_H_INCLUDES) {$(VPATH)}vm_method.c {$(VPATH)}vm_eval.c \
@ -765,28 +794,30 @@ vm.$(OBJEXT): {$(VPATH)}vm.c {$(VPATH)}gc.h {$(VPATH)}iseq.h \
{$(VPATH)}vm_exec.h {$(VPATH)}insns.def {$(VPATH)}vmtc.inc \ {$(VPATH)}vm_exec.h {$(VPATH)}insns.def {$(VPATH)}vmtc.inc \
{$(VPATH)}vm.inc {$(VPATH)}insns.inc \ {$(VPATH)}vm.inc {$(VPATH)}insns.inc \
{$(VPATH)}internal.h {$(VPATH)}vm.h {$(VPATH)}constant.h \ {$(VPATH)}internal.h {$(VPATH)}vm.h {$(VPATH)}constant.h \
$(PROBES_H_INCLUDES) {$(VPATH)}probes_helper.h $(PROBES_H_INCLUDES) {$(VPATH)}probes_helper.h {$(VPATH)}vm_opts.h
vm_dump.$(OBJEXT): {$(VPATH)}vm_dump.c $(RUBY_H_INCLUDES) \ vm_dump.$(OBJEXT): {$(VPATH)}vm_dump.c $(RUBY_H_INCLUDES) \
$(VM_CORE_H_INCLUDES) {$(VPATH)}addr2line.h \ $(VM_CORE_H_INCLUDES) {$(VPATH)}addr2line.h \
{$(VPATH)}internal.h {$(VPATH)}internal.h {$(VPATH)}vm_opts.h
debug.$(OBJEXT): {$(VPATH)}debug.c $(RUBY_H_INCLUDES) \ debug.$(OBJEXT): {$(VPATH)}debug.c $(RUBY_H_INCLUDES) \
$(ENCODING_H_INCLUDES) $(VM_CORE_H_INCLUDES) {$(VPATH)}eval_intern.h \ $(ENCODING_H_INCLUDES) $(VM_CORE_H_INCLUDES) {$(VPATH)}eval_intern.h \
{$(VPATH)}util.h {$(VPATH)}util.h {$(VPATH)}vm_opts.h {$(VPATH)}internal.h
id.$(OBJEXT): {$(VPATH)}id.c $(RUBY_H_INCLUDES) {$(VPATH)}id.h {$(VPATH)}vm_opts.h id.$(OBJEXT): {$(VPATH)}id.c $(RUBY_H_INCLUDES) {$(VPATH)}id.h {$(VPATH)}vm_opts.h
vm_backtrace.$(OBJEXT): {$(VPATH)}vm_backtrace.c \ vm_backtrace.$(OBJEXT): {$(VPATH)}vm_backtrace.c \
$(VM_CORE_H_INCLUDES) $(RUBY_H_INCLUDES) $(ENCODING_H_INCLUDES) \ $(VM_CORE_H_INCLUDES) $(RUBY_H_INCLUDES) $(ENCODING_H_INCLUDES) \
{$(VPATH)}internal.h {$(VPATH)}iseq.h {$(VPATH)}debug.h {$(VPATH)}internal.h {$(VPATH)}iseq.h {$(VPATH)}debug.h {$(VPATH)}vm_opts.h {$(VPATH)}ruby_atomic.h {$(VPATH)}eval_intern.h
vm_trace.$(OBJEXT): {$(VPATH)}vm_trace.c $(ENCODING_H_INCLUDES) \ vm_trace.$(OBJEXT): {$(VPATH)}vm_trace.c $(ENCODING_H_INCLUDES) \
$(VM_CORE_H_INCLUDES) $(RUBY_H_INCLUDES) {$(VPATH)}debug.h \ $(VM_CORE_H_INCLUDES) $(RUBY_H_INCLUDES) {$(VPATH)}debug.h \
{$(VPATH)}internal.h {$(VPATH)}internal.h {$(VPATH)}vm_opts.h {$(VPATH)}ruby_atomic.h {$(VPATH)}eval_intern.h
miniprelude.$(OBJEXT): {$(VPATH)}miniprelude.c $(RUBY_H_INCLUDES) \ miniprelude.$(OBJEXT): {$(VPATH)}miniprelude.c $(RUBY_H_INCLUDES) \
$(VM_CORE_H_INCLUDES) {$(VPATH)}internal.h $(VM_CORE_H_INCLUDES) {$(VPATH)}internal.h {$(VPATH)}vm_opts.h
prelude.$(OBJEXT): {$(VPATH)}prelude.c $(RUBY_H_INCLUDES) \ prelude.$(OBJEXT): {$(VPATH)}prelude.c $(RUBY_H_INCLUDES) \
$(VM_CORE_H_INCLUDES) {$(VPATH)}internal.h $(VM_CORE_H_INCLUDES) {$(VPATH)}internal.h {$(VPATH)}vm_opts.h
golf_prelude.$(OBJEXT): {$(VPATH)}golf_prelude.c $(RUBY_H_INCLUDES) \ golf_prelude.$(OBJEXT): {$(VPATH)}golf_prelude.c $(RUBY_H_INCLUDES) \
$(VM_CORE_H_INCLUDES) {$(VPATH)}internal.h $(VM_CORE_H_INCLUDES) {$(VPATH)}internal.h {$(VPATH)}vm_opts.h
goruby.$(OBJEXT): {$(VPATH)}goruby.c {$(VPATH)}main.c $(RUBY_H_INCLUDES) \ goruby.$(OBJEXT): {$(VPATH)}goruby.c {$(VPATH)}main.c $(RUBY_H_INCLUDES) \
{$(VPATH)}vm_debug.h {$(VPATH)}node.h {$(VPATH)}vm_debug.h {$(VPATH)}node.h $(hdrdir)/ruby.h
sizes.$(OBJEXT): {$(VPATH)}sizes.c $(RUBY_H_INCLUDES)
ascii.$(OBJEXT): {$(VPATH)}ascii.c {$(VPATH)}regenc.h {$(VPATH)}config.h \ ascii.$(OBJEXT): {$(VPATH)}ascii.c {$(VPATH)}regenc.h {$(VPATH)}config.h \
{$(VPATH)}oniguruma.h {$(VPATH)}missing.h $(RUBY_H_INCLUDES) {$(VPATH)}oniguruma.h {$(VPATH)}missing.h $(RUBY_H_INCLUDES)
@ -802,7 +833,8 @@ unicode.$(OBJEXT): {$(VPATH)}unicode.c {$(VPATH)}regint.h \
utf_8.$(OBJEXT): {$(VPATH)}utf_8.c {$(VPATH)}regenc.h {$(VPATH)}config.h \ utf_8.$(OBJEXT): {$(VPATH)}utf_8.c {$(VPATH)}regenc.h {$(VPATH)}config.h \
{$(VPATH)}oniguruma.h {$(VPATH)}missing.h $(RUBY_H_INCLUDES) {$(VPATH)}oniguruma.h {$(VPATH)}missing.h $(RUBY_H_INCLUDES)
win32/win32.$(OBJEXT): {$(VPATH)}win32/win32.c $(RUBY_H_INCLUDES) $(PLATFORM_D) win32/win32.$(OBJEXT): {$(VPATH)}win32/win32.c {$(VPATH)}dln.h {$(VPATH)}dln_find.c \
{$(VPATH)}internal.h $(RUBY_H_INCLUDES) $(PLATFORM_D)
win32/file.$(OBJEXT): {$(VPATH)}win32/file.c $(RUBY_H_INCLUDES) $(PLATFORM_D) win32/file.$(OBJEXT): {$(VPATH)}win32/file.c $(RUBY_H_INCLUDES) $(PLATFORM_D)
$(NEWLINE_C): $(srcdir)/enc/trans/newline.trans $(srcdir)/tool/transcode-tblgen.rb $(NEWLINE_C): $(srcdir)/enc/trans/newline.trans $(srcdir)/tool/transcode-tblgen.rb
@ -811,6 +843,10 @@ newline.$(OBJEXT): $(NEWLINE_C) {$(VPATH)}defines.h \
{$(VPATH)}intern.h {$(VPATH)}missing.h {$(VPATH)}st.h \ {$(VPATH)}intern.h {$(VPATH)}missing.h {$(VPATH)}st.h \
{$(VPATH)}transcode_data.h {$(VPATH)}ruby.h {$(VPATH)}config.h {$(VPATH)}subst.h {$(VPATH)}transcode_data.h {$(VPATH)}ruby.h {$(VPATH)}config.h {$(VPATH)}subst.h
verconf.h: $(srcdir)/template/verconf.h.in $(srcdir)/tool/generic_erb.rb $(RBCONFIG)
$(ECHO) creating $@
$(Q) $(MINIRUBY) "$(srcdir)/tool/generic_erb.rb" $(srcdir)/template/verconf.h.in > $@
DTRACE_DEPENDENT_OBJS = array.$(OBJEXT) \ DTRACE_DEPENDENT_OBJS = array.$(OBJEXT) \
eval.$(OBJEXT) \ eval.$(OBJEXT) \
gc.$(OBJEXT) \ gc.$(OBJEXT) \
@ -847,7 +883,7 @@ INSNS2VMOPT = --srcdir="$(srcdir)"
srcs: {$(VPATH)}parse.c {$(VPATH)}lex.c {$(VPATH)}newline.c {$(VPATH)}id.c srcs-ext srcs-enc srcs: {$(VPATH)}parse.c {$(VPATH)}lex.c {$(VPATH)}newline.c {$(VPATH)}id.c srcs-ext srcs-enc
EXT_SRCS = $(srcdir)/ext/ripper/ripper.c $(srcdir)/ext/json/parser/parser.c \ EXT_SRCS = $(srcdir)/ext/ripper/ripper.c $(srcdir)/ext/json/parser/parser.c \
$(srcdir)/ext/dl/callback/callback.c $(srcdir)/ext/dl/callback/callback.c $(srcdir)/ext/rbconfig/sizeof/sizes.c
srcs-ext: $(EXT_SRCS) srcs-ext: $(EXT_SRCS)
@ -864,12 +900,12 @@ insns: $(INSNS)
id.h: $(srcdir)/tool/generic_erb.rb $(srcdir)/template/id.h.tmpl $(srcdir)/defs/id.def id.h: $(srcdir)/tool/generic_erb.rb $(srcdir)/template/id.h.tmpl $(srcdir)/defs/id.def
$(ECHO) generating $@ $(ECHO) generating $@
$(Q) $(BASERUBY) $(srcdir)/tool/generic_erb.rb --output=$@ \ $(Q) $(BASERUBY) $(srcdir)/tool/generic_erb.rb --output=$@ \
$(srcdir)/template/$@.tmpl $(srcdir)/template/id.h.tmpl
id.c: $(srcdir)/tool/generic_erb.rb $(srcdir)/template/id.c.tmpl $(srcdir)/defs/id.def id.c: $(srcdir)/tool/generic_erb.rb $(srcdir)/template/id.c.tmpl $(srcdir)/defs/id.def
$(ECHO) generating $@ $(ECHO) generating $@
$(Q) $(BASERUBY) $(srcdir)/tool/generic_erb.rb --output=$@ \ $(Q) $(BASERUBY) $(srcdir)/tool/generic_erb.rb --output=$@ \
$(srcdir)/template/$@.tmpl $(srcdir)/template/id.c.tmpl
node_name.inc: {$(VPATH)}node.h node_name.inc: {$(VPATH)}node.h
$(ECHO) generating $@ $(ECHO) generating $@
@ -921,21 +957,27 @@ $(REVISION_H): $(srcdir)/version.h $(srcdir)/ChangeLog $(srcdir)/tool/file2lastr
-$(Q) $(BASERUBY) $(srcdir)/tool/file2lastrev.rb --revision.h "$(srcdir)" > revision.tmp -$(Q) $(BASERUBY) $(srcdir)/tool/file2lastrev.rb --revision.h "$(srcdir)" > revision.tmp
$(Q)$(IFCHANGE) "--timestamp=$@" "$(srcdir)/revision.h" revision.tmp $(Q)$(IFCHANGE) "--timestamp=$@" "$(srcdir)/revision.h" revision.tmp
$(srcdir)/ext/ripper/ripper.c: parse.y $(srcdir)/ext/ripper/ripper.c: parse.y id.h
$(ECHO) generating $@ $(ECHO) generating $@
$(Q) $(CHDIR) $(@D) && $(exec) $(MAKE) -f depend $(MFLAGS) \ $(Q) $(CHDIR) $(@D) && $(exec) $(MAKE) -f depend $(MFLAGS) \
Q=$(Q) ECHO=$(ECHO) top_srcdir=../.. srcdir=. VPATH=../.. RUBY="$(BASERUBY)" Q=$(Q) ECHO=$(ECHO) top_srcdir=../.. srcdir=. VPATH=../.. RUBY="$(BASERUBY)" PATH_SEPARATOR="$(PATH_SEPARATOR)"
$(srcdir)/ext/json/parser/parser.c: $(srcdir)/ext/json/parser/parser.rl $(srcdir)/ext/json/parser/parser.c: $(srcdir)/ext/json/parser/parser.rl
$(ECHO) generating $@ $(ECHO) generating $@
$(Q) $(CHDIR) $(@D) && $(exec) $(MAKE) -f prereq.mk $(MFLAGS) \ $(Q) $(CHDIR) $(@D) && $(exec) $(MAKE) -f prereq.mk $(MFLAGS) \
Q=$(Q) ECHO=$(ECHO) top_srcdir=../../.. srcdir=. Q=$(Q) ECHO=$(ECHO) top_srcdir=../../.. srcdir=. VPATH=../../.. BASERUBY="$(BASERUBY)"
$(srcdir)/ext/dl/callback/callback.c: $(srcdir)/ext/dl/callback/mkcallback.rb $(srcdir)/ext/dl/dl.h $(srcdir)/ext/dl/callback/callback.c: $(srcdir)/ext/dl/callback/mkcallback.rb $(srcdir)/ext/dl/dl.h
$(ECHO) generating $@ $(ECHO) generating $@
$(Q) $(CHDIR) $(@D) && $(exec) $(MAKE) -f depend $(MFLAGS) \ $(Q) $(CHDIR) $(@D) && $(exec) $(MAKE) -f depend $(MFLAGS) \
Q=$(Q) ECHO=$(ECHO) top_srcdir=../.. srcdir=. VPATH=../.. RUBY="$(BASERUBY)" Q=$(Q) ECHO=$(ECHO) top_srcdir=../.. srcdir=. VPATH=../.. RUBY="$(BASERUBY)"
$(srcdir)/ext/rbconfig/sizeof/sizes.c: $(srcdir)/ext/rbconfig/sizeof/depend \
$(srcdir)/tool/generic_erb.rb $(srcdir)/template/sizes.c.tmpl $(srcdir)/configure.in
$(ECHO) generating $@
$(Q) $(CHDIR) $(@D) && $(exec) $(MAKE) -f depend $(MFLAGS) \
Q=$(Q) ECHO=$(ECHO) top_srcdir=../../.. srcdir=. VPATH=../../.. RUBY="$(BASERUBY)"
## ##
run: fake miniruby$(EXEEXT) PHONY run: fake miniruby$(EXEEXT) PHONY
@ -947,6 +989,12 @@ runruby: $(PROGRAM) PHONY
parse: fake miniruby$(EXEEXT) PHONY parse: fake miniruby$(EXEEXT) PHONY
$(BTESTRUBY) $(srcdir)/tool/parse.rb $(TESTRUN_SCRIPT) $(BTESTRUBY) $(srcdir)/tool/parse.rb $(TESTRUN_SCRIPT)
bisect: PHONY
$(srcdir)/tool/bisect.sh miniruby $(srcdir)
bisect-ruby: PHONY
$(srcdir)/tool/bisect.sh ruby $(srcdir)
COMPARE_RUBY = $(BASERUBY) COMPARE_RUBY = $(BASERUBY)
ITEM = ITEM =
OPTS = OPTS =
@ -967,7 +1015,8 @@ tbench: $(PROGRAM) PHONY
--pattern='bmx_' --directory=$(srcdir)/benchmark $(OPTS) --pattern='bmx_' --directory=$(srcdir)/benchmark $(OPTS)
run.gdb: run.gdb:
echo b ruby_debug_breakpoint > run.gdb echo set breakpoint pending on > run.gdb
echo b ruby_debug_breakpoint >> run.gdb
echo '# handle SIGINT nostop' >> run.gdb echo '# handle SIGINT nostop' >> run.gdb
echo '# handle SIGPIPE nostop' >> run.gdb echo '# handle SIGPIPE nostop' >> run.gdb
echo '# b rb_longjmp' >> run.gdb echo '# b rb_longjmp' >> run.gdb
@ -992,6 +1041,12 @@ dist:
up:: up::
-$(Q)$(MAKE) $(MFLAGS) REVISION_FORCE=PHONY "$(REVISION_H)" -$(Q)$(MAKE) $(MFLAGS) REVISION_FORCE=PHONY "$(REVISION_H)"
update-config_files: $(srcdir)/tool/config.guess $(srcdir)/tool/config.sub
$(srcdir)/tool/config.guess:
$(Q) $(BASERUBY) -C $(@D) get-config_files $(@F)
$(srcdir)/tool/config.sub:
$(Q) $(BASERUBY) -C $(@D) get-config_files $(@F)
info: info-program info-libruby_a info-libruby_so info-arch info: info-program info-libruby_a info-libruby_so info-arch
info-program: info-program:
@echo PROGRAM=$(PROGRAM) @echo PROGRAM=$(PROGRAM)
@ -1008,6 +1063,8 @@ change: PHONY
love: sudo-precheck up all test install test-all love: sudo-precheck up all test install test-all
@echo love is all you need @echo love is all you need
yes-test-all: sudo-precheck
sudo-precheck: sudo-precheck:
@$(SUDO) echo > $(NULL) @$(SUDO) echo > $(NULL)
@ -1028,10 +1085,12 @@ help: PHONY
" gdb-ruby: runs test.rb by ruby under gdb" \ " gdb-ruby: runs test.rb by ruby under gdb" \
" check: equals make test test-all" \ " check: equals make test test-all" \
" test: ruby core tests" \ " test: ruby core tests" \
" test-all: all ruby tests" \ " test-all: all ruby tests [TESTS=<test files>]" \
" test-rubyspec: run RubySpec test suite" \ " test-rubyspec: run RubySpec test suite" \
" update-rubyspec: update local copy of RubySpec" \ " update-rubyspec: update local copy of RubySpec" \
" benchmark: benchmark this ruby and COMPARE_RUBY" \ " benchmark: benchmark this ruby and COMPARE_RUBY" \
" gcbench: gc benchmark [GCBENCH_ITEM=<item_name>]" \
" gcbench-rdoc: gc benchmark with GCBENCH_ITEM=rdoc" \
" install: install all ruby distributions" \ " install: install all ruby distributions" \
" install-nodoc: install without rdoc" \ " install-nodoc: install without rdoc" \
" install-cross: install cross compiling staff" \ " install-cross: install cross compiling staff" \

View file

@ -31,10 +31,37 @@ rb_cmperr(VALUE x, VALUE y)
rb_obj_classname(x), classname); rb_obj_classname(x), classname);
} }
static VALUE
invcmp_recursive(VALUE x, VALUE y, int recursive)
{
if (recursive) return Qnil;
return rb_check_funcall(y, cmp, 1, &x);
}
VALUE
rb_invcmp(VALUE x, VALUE y)
{
VALUE invcmp = rb_exec_recursive(invcmp_recursive, x, y);
if (invcmp == Qundef || NIL_P(invcmp)) {
return Qnil;
}
else {
int result = -rb_cmpint(invcmp, x, y);
return INT2FIX(result);
}
}
static VALUE
cmp_eq_recursive(VALUE arg1, VALUE arg2, int recursive)
{
if (recursive) return Qfalse;
return rb_funcallv(arg1, cmp, 1, &arg2);
}
static VALUE static VALUE
cmp_eq(VALUE *a) cmp_eq(VALUE *a)
{ {
VALUE c = rb_funcall(a[0], cmp, 1, a[1]); VALUE c = rb_exec_recursive_paired_outer(cmp_eq_recursive, a[0], a[1], a[1]);
if (NIL_P(c)) return Qfalse; if (NIL_P(c)) return Qfalse;
if (rb_cmpint(c, a[0], a[1]) == 0) return Qtrue; if (rb_cmpint(c, a[0], a[1]) == 0) return Qtrue;
@ -54,6 +81,9 @@ cmp_failed(void)
* Compares two objects based on the receiver's <code><=></code> * Compares two objects based on the receiver's <code><=></code>
* method, returning true if it returns 0. Also returns true if * method, returning true if it returns 0. Also returns true if
* _obj_ and _other_ are the same object. * _obj_ and _other_ are the same object.
*
* Even if _obj_ <=> _other_ raised an exception, the exception
* is ignored and returns false.
*/ */
static VALUE static VALUE

1103
compile.c

File diff suppressed because it is too large Load diff

114
complex.c
View file

@ -210,17 +210,16 @@ f_negative_p(VALUE x)
inline static VALUE inline static VALUE
f_zero_p(VALUE x) f_zero_p(VALUE x)
{ {
switch (TYPE(x)) { if (RB_TYPE_P(x, T_FIXNUM)) {
case T_FIXNUM:
return f_boolcast(FIX2LONG(x) == 0); return f_boolcast(FIX2LONG(x) == 0);
case T_BIGNUM: }
else if (RB_TYPE_P(x, T_BIGNUM)) {
return Qfalse; return Qfalse;
case T_RATIONAL: }
{ else if (RB_TYPE_P(x, T_RATIONAL)) {
VALUE num = RRATIONAL(x)->num; VALUE num = RRATIONAL(x)->num;
return f_boolcast(FIXNUM_P(num) && FIX2LONG(num) == 0); return f_boolcast(FIXNUM_P(num) && FIX2LONG(num) == 0);
}
} }
return rb_funcall(x, id_eqeq_p, 1, ZERO); return rb_funcall(x, id_eqeq_p, 1, ZERO);
} }
@ -230,19 +229,18 @@ f_zero_p(VALUE x)
inline static VALUE inline static VALUE
f_one_p(VALUE x) f_one_p(VALUE x)
{ {
switch (TYPE(x)) { if (RB_TYPE_P(x, T_FIXNUM)) {
case T_FIXNUM:
return f_boolcast(FIX2LONG(x) == 1); return f_boolcast(FIX2LONG(x) == 1);
case T_BIGNUM: }
else if (RB_TYPE_P(x, T_BIGNUM)) {
return Qfalse; return Qfalse;
case T_RATIONAL: }
{ else if (RB_TYPE_P(x, T_RATIONAL)) {
VALUE num = RRATIONAL(x)->num; VALUE num = RRATIONAL(x)->num;
VALUE den = RRATIONAL(x)->den; VALUE den = RRATIONAL(x)->den;
return f_boolcast(FIXNUM_P(num) && FIX2LONG(num) == 1 && return f_boolcast(FIXNUM_P(num) && FIX2LONG(num) == 1 &&
FIXNUM_P(den) && FIX2LONG(den) == 1); FIXNUM_P(den) && FIX2LONG(den) == 1);
}
} }
return rb_funcall(x, id_eqeq_p, 1, ONE); return rb_funcall(x, id_eqeq_p, 1, ONE);
} }
@ -313,10 +311,10 @@ k_complex_p(VALUE x)
inline static VALUE inline static VALUE
nucomp_s_new_internal(VALUE klass, VALUE real, VALUE imag) nucomp_s_new_internal(VALUE klass, VALUE real, VALUE imag)
{ {
NEWOBJ_OF(obj, struct RComplex, klass, T_COMPLEX); NEWOBJ_OF(obj, struct RComplex, klass, T_COMPLEX | (RGENGC_WB_PROTECTED_COMPLEX ? FL_WB_PROTECTED : 0));
obj->real = real; RCOMPLEX_SET_REAL(obj, real);
obj->imag = imag; RCOMPLEX_SET_IMAG(obj, imag);
return (VALUE)obj; return (VALUE)obj;
} }
@ -383,13 +381,10 @@ nucomp_canonicalization(int f)
inline static void inline static void
nucomp_real_check(VALUE num) nucomp_real_check(VALUE num)
{ {
switch (TYPE(num)) { if (!RB_TYPE_P(num, T_FIXNUM) &&
case T_FIXNUM: !RB_TYPE_P(num, T_BIGNUM) &&
case T_BIGNUM: !RB_TYPE_P(num, T_FLOAT) &&
case T_FLOAT: !RB_TYPE_P(num, T_RATIONAL)) {
case T_RATIONAL:
break;
default:
if (!k_numeric_p(num) || !f_real_p(num)) if (!k_numeric_p(num) || !f_real_p(num))
rb_raise(rb_eTypeError, "not a real"); rb_raise(rb_eTypeError, "not a real");
} }
@ -483,6 +478,28 @@ f_complex_new2(VALUE klass, VALUE x, VALUE y)
* *
* Complex(1, 2) #=> (1+2i) * Complex(1, 2) #=> (1+2i)
* Complex('1+2i') #=> (1+2i) * Complex('1+2i') #=> (1+2i)
*
* Syntax of string form:
*
* string form = extra spaces , complex , extra spaces ;
* complex = real part | [ sign ] , imaginary part
* | real part , sign , imaginary part
* | rational , "@" , rational ;
* real part = rational ;
* imaginary part = imaginary unit | unsigned rational , imaginary unit ;
* rational = [ sign ] , unsigned rational ;
* unsigned rational = numerator | numerator , "/" , denominator ;
* numerator = integer part | fractional part | integer part , fractional part ;
* denominator = digits ;
* integer part = digits ;
* fractional part = "." , digits , [ ( "e" | "E" ) , [ sign ] , digits ] ;
* imaginary unit = "i" | "I" | "j" | "J" ;
* sign = "-" | "+" ;
* digits = digit , { digit | "_" , digit };
* digit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" ;
* extra spaces = ? \s* ? ;
*
* See String#to_c.
*/ */
static VALUE static VALUE
nucomp_f_complex(int argc, VALUE *argv, VALUE klass) nucomp_f_complex(int argc, VALUE *argv, VALUE klass)
@ -1220,11 +1237,9 @@ f_signbit(VALUE x)
!defined(signbit) !defined(signbit)
extern int signbit(double); extern int signbit(double);
#endif #endif
switch (TYPE(x)) { if (RB_TYPE_P(x, T_FLOAT)) {
case T_FLOAT: {
double f = RFLOAT_VALUE(x); double f = RFLOAT_VALUE(x);
return f_boolcast(!isnan(f) && signbit(f)); return f_boolcast(!isnan(f) && signbit(f));
}
} }
return f_negative_p(x); return f_negative_p(x);
} }
@ -1310,8 +1325,8 @@ nucomp_loader(VALUE self, VALUE a)
{ {
get_dat1(self); get_dat1(self);
dat->real = rb_ivar_get(a, id_i_real); RCOMPLEX_SET_REAL(dat, rb_ivar_get(a, id_i_real));
dat->imag = rb_ivar_get(a, id_i_imag); RCOMPLEX_SET_IMAG(dat, rb_ivar_get(a, id_i_imag));
return self; return self;
} }
@ -1324,6 +1339,7 @@ nucomp_marshal_dump(VALUE self)
get_dat1(self); get_dat1(self);
a = rb_assoc_new(dat->real, dat->imag); a = rb_assoc_new(dat->real, dat->imag);
rb_copy_generic_ivar(a, self);
return a; return a;
} }
@ -1334,8 +1350,8 @@ nucomp_marshal_load(VALUE self, VALUE a)
Check_Type(a, T_ARRAY); Check_Type(a, T_ARRAY);
if (RARRAY_LEN(a) != 2) if (RARRAY_LEN(a) != 2)
rb_raise(rb_eArgError, "marshaled complex must have an array whose length is 2 but %ld", RARRAY_LEN(a)); rb_raise(rb_eArgError, "marshaled complex must have an array whose length is 2 but %ld", RARRAY_LEN(a));
rb_ivar_set(self, id_i_real, RARRAY_PTR(a)[0]); rb_ivar_set(self, id_i_real, RARRAY_AREF(a, 0));
rb_ivar_set(self, id_i_imag, RARRAY_PTR(a)[1]); rb_ivar_set(self, id_i_imag, RARRAY_AREF(a, 1));
return self; return self;
} }
@ -1824,6 +1840,8 @@ string_to_c_strict(VALUE self)
* '-0.0-0.0i'.to_c #=> (-0.0-0.0i) * '-0.0-0.0i'.to_c #=> (-0.0-0.0i)
* '1/2+3/4i'.to_c #=> ((1/2)+(3/4)*i) * '1/2+3/4i'.to_c #=> ((1/2)+(3/4)*i)
* 'ruby'.to_c #=> (0+0i) * 'ruby'.to_c #=> (0+0i)
*
* See Kernel.Complex.
*/ */
static VALUE static VALUE
string_to_c(VALUE self) string_to_c(VALUE self)
@ -1862,30 +1880,17 @@ nucomp_s_convert(int argc, VALUE *argv, VALUE klass)
backref = rb_backref_get(); backref = rb_backref_get();
rb_match_busy(backref); rb_match_busy(backref);
switch (TYPE(a1)) { if (RB_TYPE_P(a1, T_STRING)) {
case T_FIXNUM:
case T_BIGNUM:
case T_FLOAT:
break;
case T_STRING:
a1 = string_to_c_strict(a1); a1 = string_to_c_strict(a1);
break;
} }
switch (TYPE(a2)) { if (RB_TYPE_P(a2, T_STRING)) {
case T_FIXNUM:
case T_BIGNUM:
case T_FLOAT:
break;
case T_STRING:
a2 = string_to_c_strict(a2); a2 = string_to_c_strict(a2);
break;
} }
rb_backref_set(backref); rb_backref_set(backref);
switch (TYPE(a1)) { if (RB_TYPE_P(a1, T_COMPLEX)) {
case T_COMPLEX:
{ {
get_dat1(a1); get_dat1(a1);
@ -1894,8 +1899,7 @@ nucomp_s_convert(int argc, VALUE *argv, VALUE klass)
} }
} }
switch (TYPE(a2)) { if (RB_TYPE_P(a2, T_COMPLEX)) {
case T_COMPLEX:
{ {
get_dat1(a2); get_dat1(a2);
@ -1904,8 +1908,7 @@ nucomp_s_convert(int argc, VALUE *argv, VALUE klass)
} }
} }
switch (TYPE(a1)) { if (RB_TYPE_P(a1, T_COMPLEX)) {
case T_COMPLEX:
if (argc == 1 || (k_exact_zero_p(a2))) if (argc == 1 || (k_exact_zero_p(a2)))
return a1; return a1;
} }
@ -1993,6 +1996,7 @@ numeric_arg(VALUE self)
/* /*
* call-seq: * call-seq:
* num.rect -> array * num.rect -> array
* num.rectangular -> array
* *
* Returns an array; [num, 0]. * Returns an array; [num, 0].
*/ */

File diff suppressed because it is too large Load diff

View file

@ -18,8 +18,8 @@ typedef enum {
typedef struct rb_const_entry_struct { typedef struct rb_const_entry_struct {
rb_const_flag_t flag; rb_const_flag_t flag;
VALUE value; /* should be mark */ const VALUE value; /* should be mark */
VALUE file; const VALUE file; /* should be mark */
int line; int line;
} rb_const_entry_t; } rb_const_entry_t;

164
cont.c
View file

@ -15,9 +15,6 @@
#include "gc.h" #include "gc.h"
#include "eval_intern.h" #include "eval_intern.h"
#if ((defined(_WIN32) && _WIN32_WINNT >= 0x0400) || (defined(HAVE_GETCONTEXT) && defined(HAVE_SETCONTEXT))) && !defined(__NetBSD__) && !defined(__sun) && !defined(FIBER_USE_NATIVE)
#define FIBER_USE_NATIVE 1
/* FIBER_USE_NATIVE enables Fiber performance improvement using system /* FIBER_USE_NATIVE enables Fiber performance improvement using system
* dependent method such as make/setcontext on POSIX system or * dependent method such as make/setcontext on POSIX system or
* CreateFiber() API on Windows. * CreateFiber() API on Windows.
@ -29,12 +26,45 @@
* in Proc. of 51th Programming Symposium, pp.21--28 (2010) (in Japanese). * in Proc. of 51th Programming Symposium, pp.21--28 (2010) (in Japanese).
*/ */
#if !defined(FIBER_USE_NATIVE)
# if defined(HAVE_GETCONTEXT) && defined(HAVE_SETCONTEXT)
# if 0
# elif defined(__NetBSD__)
/* On our experience, NetBSD doesn't support using setcontext() and pthread /* On our experience, NetBSD doesn't support using setcontext() and pthread
* simultaneously. This is because pthread_self(), TLS and other information * simultaneously. This is because pthread_self(), TLS and other information
* are represented by stack pointer (higher bits of stack pointer). * are represented by stack pointer (higher bits of stack pointer).
* TODO: check such constraint on configure. * TODO: check such constraint on configure.
*/ */
#elif !defined(FIBER_USE_NATIVE) # define FIBER_USE_NATIVE 0
# elif defined(__sun)
/* On Solaris because resuming any Fiber caused SEGV, for some reason.
*/
# define FIBER_USE_NATIVE 0
# elif defined(__ia64)
/* At least, Linux/ia64's getcontext(3) doesn't save register window.
*/
# define FIBER_USE_NATIVE 0
# elif defined(__GNU__)
/* GNU/Hurd doesn't fully support getcontext, setcontext, makecontext
* and swapcontext functions. Disabling their usage till support is
* implemented. More info at
* http://darnassus.sceen.net/~hurd-web/open_issues/glibc/#getcontext
*/
# define FIBER_USE_NATIVE 0
# else
# define FIBER_USE_NATIVE 1
# endif
# elif defined(_WIN32)
# if _WIN32_WINNT >= 0x0400
/* only when _WIN32_WINNT >= 0x0400 on Windows because Fiber APIs are
* supported only such building (and running) environments.
* [ruby-dev:41192]
*/
# define FIBER_USE_NATIVE 1
# endif
# endif
#endif
#if !defined(FIBER_USE_NATIVE)
#define FIBER_USE_NATIVE 0 #define FIBER_USE_NATIVE 0
#endif #endif
@ -77,6 +107,8 @@ typedef struct rb_context_struct {
rb_thread_t saved_thread; rb_thread_t saved_thread;
rb_jmpbuf_t jmpbuf; rb_jmpbuf_t jmpbuf;
size_t machine_stack_size; size_t machine_stack_size;
rb_ensure_entry_t *ensure_array;
rb_ensure_list_t *ensure_list;
} rb_context_t; } rb_context_t;
enum fiber_status { enum fiber_status {
@ -86,13 +118,13 @@ enum fiber_status {
}; };
#if FIBER_USE_NATIVE && !defined(_WIN32) #if FIBER_USE_NATIVE && !defined(_WIN32)
#define MAX_MAHINE_STACK_CACHE 10 #define MAX_MACHINE_STACK_CACHE 10
static int machine_stack_cache_index = 0; static int machine_stack_cache_index = 0;
typedef struct machine_stack_cache_struct { typedef struct machine_stack_cache_struct {
void *ptr; void *ptr;
size_t size; size_t size;
} machine_stack_cache_t; } machine_stack_cache_t;
static machine_stack_cache_t machine_stack_cache[MAX_MAHINE_STACK_CACHE]; static machine_stack_cache_t machine_stack_cache[MAX_MACHINE_STACK_CACHE];
static machine_stack_cache_t terminated_machine_stack; static machine_stack_cache_t terminated_machine_stack;
#endif #endif
@ -193,6 +225,7 @@ cont_free(void *ptr)
#if FIBER_USE_NATIVE #if FIBER_USE_NATIVE
if (cont->type == CONTINUATION_CONTEXT) { if (cont->type == CONTINUATION_CONTEXT) {
/* cont */ /* cont */
ruby_xfree(cont->ensure_array);
RUBY_FREE_UNLESS_NULL(cont->machine_stack); RUBY_FREE_UNLESS_NULL(cont->machine_stack);
} }
else { else {
@ -223,6 +256,7 @@ cont_free(void *ptr)
#endif #endif
} }
#else /* not FIBER_USE_NATIVE */ #else /* not FIBER_USE_NATIVE */
ruby_xfree(cont->ensure_array);
RUBY_FREE_UNLESS_NULL(cont->machine_stack); RUBY_FREE_UNLESS_NULL(cont->machine_stack);
#endif #endif
#ifdef __ia64 #ifdef __ia64
@ -321,7 +355,8 @@ fiber_memsize(const void *ptr)
size_t size = 0; size_t size = 0;
if (ptr) { if (ptr) {
size = sizeof(*fib); size = sizeof(*fib);
if (fib->cont.type != ROOT_FIBER_CONTEXT) { if (fib->cont.type != ROOT_FIBER_CONTEXT &&
fib->cont.saved_thread.local_storage != NULL) {
size += st_memsize(fib->cont.saved_thread.local_storage); size += st_memsize(fib->cont.saved_thread.local_storage);
} }
size += cont_memsize(&fib->cont); size += cont_memsize(&fib->cont);
@ -387,6 +422,7 @@ cont_save_machine_stack(rb_thread_t *th, rb_context_t *cont)
static const rb_data_type_t cont_data_type = { static const rb_data_type_t cont_data_type = {
"continuation", "continuation",
{cont_mark, cont_free, cont_memsize,}, {cont_mark, cont_free, cont_memsize,},
NULL, NULL, RUBY_TYPED_FREE_IMMEDIATELY
}; };
static void static void
@ -453,6 +489,22 @@ cont_capture(volatile int *stat)
cont_save_machine_stack(th, cont); cont_save_machine_stack(th, cont);
/* backup ensure_list to array for search in another context */
{
rb_ensure_list_t *p;
int size = 0;
rb_ensure_entry_t *entry;
for (p=th->ensure_list; p; p=p->next)
size++;
entry = cont->ensure_array = ALLOC_N(rb_ensure_entry_t,size+1);
for (p=th->ensure_list; p; p=p->next) {
if (!p->entry.marker)
p->entry.marker = rb_ary_tmp_new(0); /* dummy object */
*entry++ = p->entry;
}
entry->marker = 0;
}
if (ruby_setjmp(cont->jmpbuf)) { if (ruby_setjmp(cont->jmpbuf)) {
volatile VALUE value; volatile VALUE value;
@ -512,6 +564,10 @@ cont_restore_thread(rb_context_t *cont)
th->protect_tag = sth->protect_tag; th->protect_tag = sth->protect_tag;
th->errinfo = sth->errinfo; th->errinfo = sth->errinfo;
th->first_proc = sth->first_proc; th->first_proc = sth->first_proc;
th->root_lep = sth->root_lep;
th->root_svar = sth->root_svar;
th->ensure_list = sth->ensure_list;
} }
#if FIBER_USE_NATIVE #if FIBER_USE_NATIVE
@ -566,9 +622,10 @@ fiber_machine_stack_alloc(size_t size)
void *page; void *page;
STACK_GROW_DIR_DETECTION; STACK_GROW_DIR_DETECTION;
errno = 0;
ptr = mmap(NULL, size, PROT_READ | PROT_WRITE, FIBER_STACK_FLAGS, -1, 0); ptr = mmap(NULL, size, PROT_READ | PROT_WRITE, FIBER_STACK_FLAGS, -1, 0);
if (ptr == MAP_FAILED) { if (ptr == MAP_FAILED) {
rb_raise(rb_eFiberError, "can't alloc machine stack to fiber"); rb_raise(rb_eFiberError, "can't alloc machine stack to fiber: %s", strerror(errno));
} }
/* guard page setup */ /* guard page setup */
@ -882,6 +939,80 @@ make_passing_arg(int argc, VALUE *argv)
} }
} }
/* CAUTION!! : Currently, error in rollback_func is not supported */
/* same as rb_protect if set rollback_func to NULL */
void
ruby_register_rollback_func_for_ensure(VALUE (*ensure_func)(ANYARGS), VALUE (*rollback_func)(ANYARGS))
{
st_table **table_p = &GET_VM()->ensure_rollback_table;
if (UNLIKELY(*table_p == NULL)) {
*table_p = st_init_numtable();
}
st_insert(*table_p, (st_data_t)ensure_func, (st_data_t)rollback_func);
}
static inline VALUE
lookup_rollback_func(VALUE (*ensure_func)(ANYARGS))
{
st_table *table = GET_VM()->ensure_rollback_table;
st_data_t val;
if (table && st_lookup(table, (st_data_t)ensure_func, &val))
return (VALUE) val;
return Qundef;
}
static inline void
rollback_ensure_stack(VALUE self,rb_ensure_list_t *current,rb_ensure_entry_t *target)
{
rb_ensure_list_t *p;
rb_ensure_entry_t *entry;
size_t i;
size_t cur_size;
size_t target_size;
size_t base_point;
VALUE (*func)(ANYARGS);
cur_size = 0;
for (p=current; p; p=p->next)
cur_size++;
target_size = 0;
for (entry=target; entry->marker; entry++)
target_size++;
/* search common stack point */
p = current;
base_point = cur_size;
while (base_point) {
if (target_size >= base_point &&
p->entry.marker == target[target_size - base_point].marker)
break;
base_point --;
p = p->next;
}
/* rollback function check */
for (i=0; i < target_size - base_point; i++) {
if (!lookup_rollback_func(target[i].e_proc)) {
rb_raise(rb_eRuntimeError, "continuation called from out of critical rb_ensure scope");
}
}
/* pop ensure stack */
while (cur_size > base_point) {
/* escape from ensure block */
(*current->entry.e_proc)(current->entry.data2);
current = current->next;
cur_size--;
}
/* push ensure stack */
while (i--) {
func = (VALUE (*)(ANYARGS)) lookup_rollback_func(target[i].e_proc);
if ((VALUE)func != Qundef) {
(*func)(target[i].data2);
}
}
}
/* /*
* call-seq: * call-seq:
* cont.call(args, ...) * cont.call(args, ...)
@ -919,6 +1050,7 @@ rb_cont_call(int argc, VALUE *argv, VALUE contval)
rb_raise(rb_eRuntimeError, "continuation called across fiber"); rb_raise(rb_eRuntimeError, "continuation called across fiber");
} }
} }
rollback_ensure_stack(contval, th->ensure_list, cont->ensure_array);
cont->argc = argc; cont->argc = argc;
cont->value = make_passing_arg(argc, argv); cont->value = make_passing_arg(argc, argv);
@ -999,6 +1131,7 @@ rb_cont_call(int argc, VALUE *argv, VALUE contval)
static const rb_data_type_t fiber_data_type = { static const rb_data_type_t fiber_data_type = {
"fiber", "fiber",
{fiber_mark, fiber_free, fiber_memsize,}, {fiber_mark, fiber_free, fiber_memsize,},
NULL, NULL, RUBY_TYPED_FREE_IMMEDIATELY
}; };
static VALUE static VALUE
@ -1146,10 +1279,9 @@ rb_fiber_start(void)
TH_PUSH_TAG(th); TH_PUSH_TAG(th);
if ((state = EXEC_TAG()) == 0) { if ((state = EXEC_TAG()) == 0) {
int argc; int argc;
VALUE *argv, args; const VALUE *argv, args = cont->value;
GetProcPtr(cont->saved_thread.first_proc, proc); GetProcPtr(cont->saved_thread.first_proc, proc);
args = cont->value; argv = (argc = cont->argc) > 1 ? RARRAY_CONST_PTR(args) : &args;
argv = (argc = cont->argc) > 1 ? RARRAY_PTR(args) : &args;
cont->value = Qnil; cont->value = Qnil;
th->errinfo = Qnil; th->errinfo = Qnil;
th->root_lep = rb_vm_ep_local_ep(proc->block.ep); th->root_lep = rb_vm_ep_local_ep(proc->block.ep);
@ -1231,7 +1363,7 @@ fiber_store(rb_fiber_t *next_fib)
fiber_setcontext(next_fib, fib); fiber_setcontext(next_fib, fib);
#ifndef _WIN32 #ifndef _WIN32
if (terminated_machine_stack.ptr) { if (terminated_machine_stack.ptr) {
if (machine_stack_cache_index < MAX_MAHINE_STACK_CACHE) { if (machine_stack_cache_index < MAX_MACHINE_STACK_CACHE) {
machine_stack_cache[machine_stack_cache_index].ptr = terminated_machine_stack.ptr; machine_stack_cache[machine_stack_cache_index].ptr = terminated_machine_stack.ptr;
machine_stack_cache[machine_stack_cache_index].size = terminated_machine_stack.size; machine_stack_cache[machine_stack_cache_index].size = terminated_machine_stack.size;
machine_stack_cache_index++; machine_stack_cache_index++;
@ -1538,9 +1670,7 @@ Init_Cont(void)
rb_define_method(rb_cFiber, "resume", rb_fiber_m_resume, -1); rb_define_method(rb_cFiber, "resume", rb_fiber_m_resume, -1);
} }
#if defined __GNUC__ && __GNUC__ >= 4 RUBY_SYMBOL_EXPORT_BEGIN
#pragma GCC visibility push(default)
#endif
void void
ruby_Init_Continuation_body(void) ruby_Init_Continuation_body(void)
@ -1561,6 +1691,4 @@ ruby_Init_Fiber_as_Coroutine(void)
rb_define_singleton_method(rb_cFiber, "current", rb_fiber_s_current, 0); rb_define_singleton_method(rb_cFiber, "current", rb_fiber_s_current, 0);
} }
#if defined __GNUC__ && __GNUC__ >= 4 RUBY_SYMBOL_EXPORT_END
#pragma GCC visibility pop
#endif

View file

@ -24,6 +24,7 @@ const union {
enum ruby_tag_type tag_type; enum ruby_tag_type tag_type;
enum node_type node_type; enum node_type node_type;
enum ruby_method_ids method_ids; enum ruby_method_ids method_ids;
enum ruby_id_types id_types;
enum { enum {
RUBY_ENCODING_INLINE_MAX = ENCODING_INLINE_MAX, RUBY_ENCODING_INLINE_MAX = ENCODING_INLINE_MAX,
RUBY_ENCODING_SHIFT = ENCODING_SHIFT, RUBY_ENCODING_SHIFT = ENCODING_SHIFT,
@ -32,11 +33,10 @@ const union {
RUBY_ENC_CODERANGE_7BIT = ENC_CODERANGE_7BIT, RUBY_ENC_CODERANGE_7BIT = ENC_CODERANGE_7BIT,
RUBY_ENC_CODERANGE_VALID = ENC_CODERANGE_VALID, RUBY_ENC_CODERANGE_VALID = ENC_CODERANGE_VALID,
RUBY_ENC_CODERANGE_BROKEN = ENC_CODERANGE_BROKEN, RUBY_ENC_CODERANGE_BROKEN = ENC_CODERANGE_BROKEN,
RUBY_FL_RESERVED1 = FL_RESERVED1, RUBY_FL_WB_PROTECTED = FL_WB_PROTECTED,
RUBY_FL_RESERVED2 = FL_RESERVED2, RUBY_FL_PROMOTED = FL_PROMOTED,
RUBY_FL_FINALIZE = FL_FINALIZE, RUBY_FL_FINALIZE = FL_FINALIZE,
RUBY_FL_TAINT = FL_TAINT, RUBY_FL_TAINT = FL_TAINT,
RUBY_FL_UNTRUSTED = FL_UNTRUSTED,
RUBY_FL_EXIVAR = FL_EXIVAR, RUBY_FL_EXIVAR = FL_EXIVAR,
RUBY_FL_FREEZE = FL_FREEZE, RUBY_FL_FREEZE = FL_FREEZE,
RUBY_FL_SINGLETON = FL_SINGLETON, RUBY_FL_SINGLETON = FL_SINGLETON,

29
defs/gmake.mk Normal file
View file

@ -0,0 +1,29 @@
# -*- makefile-gmake -*-
TEST_TARGETS := $(filter check test check% test% btest%,$(MAKECMDGOALS))
TEST_TARGETS += $(subst check,test-all,$(patsubst check-%,test-%,$(TEST_TARGETS)))
TEST_TARGETS := $(patsubst test-%,yes-test-%,$(patsubst btest-%,yes-btest-%,$(TEST_TARGETS)))
TEST_DEPENDS := $(if $(TEST_TARGETS),$(filter all main exts,$(MAKECMDGOALS)))
TEST_DEPENDS += $(TEST_DEPENDS) $(if $(filter check%,$(MAKECMDGOALS)),main)
ifneq ($(filter check% test,$(MAKECMDGOALS)),)
yes-test-knownbug: $(TEST_DEPENDS) yes-btest-ruby
yes-btest-ruby: $(TEST_DEPENDS) yes-test-sample
yes-test-sample: $(TEST_DEPENDS)
endif
ifneq ($(filter check%,$(MAKECMDGOALS)) $(filter test-all,$(TEST_TARGETS)),)
yes-test-all yes-test-ruby: $(filter-out %test-all %test-ruby check%,$(TEST_TARGETS))
endif
ifneq ($(filter check%,$(MAKECMDGOALS))$(if $(filter test-all,$(MAKECMDGOALS)),$(filter test-knownbug,$(MAKECMDGOALS))),)
yes-test-all yes-test-ruby: yes-test-knownbug
endif
$(TEST_TARGETS): $(TEST_DEPENDS)
ifneq ($(if $(filter install,$(MAKECMDGOALS)),$(filter uninstall,$(MAKECMDGOALS))),)
install-targets := $(filter install uninstall,$(MAKECMDGOALS))
$(word 1,$(install-targets)): $(word 0,$(install-targets))
endif
ifneq ($(filter reinstall,$(MAKECMDGOALS)),)
install: uninstall
endif

View file

@ -1,15 +1,27 @@
# -*- mode: ruby; coding: us-ascii -*- # -*- mode: ruby; coding: us-ascii -*-
firstline, predefined = __LINE__+1, %[\ firstline, predefined = __LINE__+1, %[\
freeze
inspect
intern intern
object_id
const_missing
method_missing MethodMissing method_missing MethodMissing
method_added
singleton_method_added
method_removed
singleton_method_removed
method_undefined
singleton_method_undefined
length length
size size
gets gets
succ succ
each each
proc
lambda lambda
send send
__send__ __send__
__attached__
initialize initialize
initialize_copy initialize_copy
initialize_clone initialize_clone
@ -17,6 +29,7 @@ firstline, predefined = __LINE__+1, %[\
_ UScore _ UScore
"/*NULL*/" NULL "/*NULL*/" NULL
empty? empty?
eql?
respond_to? Respond_to respond_to? Respond_to
respond_to_missing? Respond_to_missing respond_to_missing? Respond_to_missing
<IFUNC> <IFUNC>
@ -48,7 +61,10 @@ const_ids = []
class_ids = [] class_ids = []
names = {} names = {}
predefined.split(/^/).each_with_index do |line, num| predefined.split(/^/).each_with_index do |line, num|
next if /^#/ =~ line or (name, token = line.split; !name) next if /^#/ =~ line
line.sub!(/\s+#.*/, '')
name, token = line.split
next unless name
token ||= name token ||= name
if /#/ =~ token if /#/ =~ token
token = "_#{token.gsub(/\W+/, '_')}" token = "_#{token.gsub(/\W+/, '_')}"

448
dir.c
View file

@ -63,10 +63,6 @@ char *strchr(char*,char);
#include "ruby/util.h" #include "ruby/util.h"
#if !defined HAVE_LSTAT && !defined lstat
#define lstat stat
#endif
/* define system APIs */ /* define system APIs */
#ifdef _WIN32 #ifdef _WIN32
#undef chdir #undef chdir
@ -79,7 +75,40 @@ char *strchr(char*,char);
#define opendir(p) rb_w32_uopendir(p) #define opendir(p) rb_w32_uopendir(p)
#endif #endif
#define rb_sys_fail_path(path) rb_sys_fail_str(path) #ifdef __APPLE__
# define HAVE_HFS 1
#else
# define HAVE_HFS 0
#endif
#if HAVE_HFS
#include <sys/param.h>
#include <sys/mount.h>
static inline int
is_hfs(DIR *dirp)
{
struct statfs buf;
if (fstatfs(dirfd(dirp), &buf) == 0) {
return buf.f_type == 17; /* HFS on darwin */
}
return FALSE;
}
static inline int
has_nonascii(const char *ptr, size_t len)
{
while (len > 0) {
if (!ISASCII(*ptr)) return 1;
ptr++;
--len;
}
return 0;
}
# define IF_HAVE_HFS(something) something
#else
# define IF_HAVE_HFS(something) /* nothing */
#endif
#define FNM_NOESCAPE 0x01 #define FNM_NOESCAPE 0x01
#define FNM_PATHNAME 0x02 #define FNM_PATHNAME 0x02
@ -137,7 +166,7 @@ bracket(
p = t2 + (r2 = rb_enc_mbclen(t2, pend, enc)); p = t2 + (r2 = rb_enc_mbclen(t2, pend, enc));
if (ok) continue; if (ok) continue;
if ((r <= (send-s) && memcmp(t1, s, r) == 0) || if ((r <= (send-s) && memcmp(t1, s, r) == 0) ||
(r2 <= (send-s) && memcmp(t2, s, r) == 0)) { (r2 <= (send-s) && memcmp(t2, s, r2) == 0)) {
ok = 1; ok = 1;
continue; continue;
} }
@ -352,6 +381,7 @@ dir_memsize(const void *ptr)
static const rb_data_type_t dir_data_type = { static const rb_data_type_t dir_data_type = {
"dir", "dir",
{dir_mark, dir_free, dir_memsize,}, {dir_mark, dir_free, dir_memsize,},
NULL, NULL, RUBY_TYPED_FREE_IMMEDIATELY
}; };
static VALUE dir_close(VALUE); static VALUE dir_close(VALUE);
@ -381,8 +411,12 @@ dir_s_alloc(VALUE klass)
/* /*
* call-seq: * call-seq:
* Dir.new( string ) -> aDir * Dir.new( string ) -> aDir
* Dir.new( string, encoding: enc ) -> aDir
* *
* Returns a new directory object for the named directory. * Returns a new directory object for the named directory.
*
* The optional <i>enc</i> argument specifies the encoding of the directory.
* If not specified, the filesystem encoding is used.
*/ */
static VALUE static VALUE
dir_initialize(int argc, VALUE *argv, VALUE dir) dir_initialize(int argc, VALUE *argv, VALUE dir)
@ -390,18 +424,20 @@ dir_initialize(int argc, VALUE *argv, VALUE dir)
struct dir_data *dp; struct dir_data *dp;
rb_encoding *fsenc; rb_encoding *fsenc;
VALUE dirname, opt, orig; VALUE dirname, opt, orig;
static VALUE sym_enc; static ID keyword_ids[1];
if (!sym_enc) { if (!keyword_ids[0]) {
sym_enc = ID2SYM(rb_intern("encoding")); keyword_ids[0] = rb_intern("encoding");
} }
fsenc = rb_filesystem_encoding(); fsenc = rb_filesystem_encoding();
rb_scan_args(argc, argv, "1:", &dirname, &opt); rb_scan_args(argc, argv, "1:", &dirname, &opt);
if (!NIL_P(opt)) { if (!NIL_P(opt)) {
VALUE enc = rb_hash_aref(opt, sym_enc); VALUE enc;
if (!NIL_P(enc)) { rb_get_kwargs(opt, keyword_ids, 0, 1, &enc);
if (enc != Qundef && !NIL_P(enc)) {
fsenc = rb_to_encoding(enc); fsenc = rb_to_encoding(enc);
} }
} }
@ -434,7 +470,12 @@ dir_initialize(int argc, VALUE *argv, VALUE dir)
/* /*
* call-seq: * call-seq:
* Dir.open( string ) -> aDir * Dir.open( string ) -> aDir
* Dir.open( string, encoding: enc ) -> aDir
* Dir.open( string ) {| aDir | block } -> anObject * Dir.open( string ) {| aDir | block } -> anObject
* Dir.open( string, encoding: enc ) {| aDir | block } -> anObject
*
* The optional <i>enc</i> argument specifies the encoding of the directory.
* If not specified, the filesystem encoding is used.
* *
* With no block, <code>open</code> is a synonym for * With no block, <code>open</code> is a synonym for
* <code>Dir::new</code>. If a block is present, it is passed * <code>Dir::new</code>. If a block is present, it is passed
@ -466,8 +507,6 @@ static struct dir_data *
dir_check(VALUE dir) dir_check(VALUE dir)
{ {
struct dir_data *dirp; struct dir_data *dirp;
if (!OBJ_UNTRUSTED(dir) && rb_safe_level() >= 4)
rb_raise(rb_eSecurityError, "Insecure: operation on trusted Dir");
rb_check_frozen(dir); rb_check_frozen(dir);
dirp = rb_check_typeddata(dir, &dir_data_type); dirp = rb_check_typeddata(dir, &dir_data_type);
if (!dirp->dir) dir_closed(); if (!dirp->dir) dir_closed();
@ -503,6 +542,7 @@ dir_inspect(VALUE dir)
/* /*
* call-seq: * call-seq:
* dir.path -> string or nil * dir.path -> string or nil
* dir.to_path -> string or nil
* *
* Returns the path parameter passed to <em>dir</em>'s constructor. * Returns the path parameter passed to <em>dir</em>'s constructor.
* *
@ -519,50 +559,10 @@ dir_path(VALUE dir)
return rb_str_dup(dirp->path); return rb_str_dup(dirp->path);
} }
#if defined HAVE_READDIR_R #if defined _WIN32
# define READDIR(dir, enc, entry, dp) (readdir_r((dir), (entry), &(dp)) == 0 && (dp) != 0) # define READDIR(dir, enc) rb_w32_readdir((dir), (enc))
#elif defined _WIN32
# define READDIR(dir, enc, entry, dp) (((dp) = rb_w32_readdir((dir), (enc))) != 0)
#else #else
# define READDIR(dir, enc, entry, dp) (((dp) = readdir(dir)) != 0) # define READDIR(dir, enc) readdir((dir))
#endif
#if defined HAVE_READDIR_R
# define IF_HAVE_READDIR_R(something) something
#else
# define IF_HAVE_READDIR_R(something) /* nothing */
#endif
#if defined SIZEOF_STRUCT_DIRENT_TOO_SMALL
# include <limits.h>
# define NAME_MAX_FOR_STRUCT_DIRENT 255
# if defined NAME_MAX
# if NAME_MAX_FOR_STRUCT_DIRENT < NAME_MAX
# undef NAME_MAX_FOR_STRUCT_DIRENT
# define NAME_MAX_FOR_STRUCT_DIRENT NAME_MAX
# endif
# endif
# if defined _POSIX_NAME_MAX
# if NAME_MAX_FOR_STRUCT_DIRENT < _POSIX_NAME_MAX
# undef NAME_MAX_FOR_STRUCT_DIRENT
# define NAME_MAX_FOR_STRUCT_DIRENT _POSIX_NAME_MAX
# endif
# endif
# if defined _XOPEN_NAME_MAX
# if NAME_MAX_FOR_STRUCT_DIRENT < _XOPEN_NAME_MAX
# undef NAME_MAX_FOR_STRUCT_DIRENT
# define NAME_MAX_FOR_STRUCT_DIRENT _XOPEN_NAME_MAX
# endif
# endif
# define DEFINE_STRUCT_DIRENT \
union { \
struct dirent dirent; \
char dummy[offsetof(struct dirent, d_name) + \
NAME_MAX_FOR_STRUCT_DIRENT + 1]; \
}
# define STRUCT_DIRENT(entry) ((entry).dirent)
#else
# define DEFINE_STRUCT_DIRENT struct dirent
# define STRUCT_DIRENT(entry) (entry)
#endif #endif
/* /*
@ -582,11 +582,10 @@ dir_read(VALUE dir)
{ {
struct dir_data *dirp; struct dir_data *dirp;
struct dirent *dp; struct dirent *dp;
IF_HAVE_READDIR_R(DEFINE_STRUCT_DIRENT entry);
GetDIR(dir, dirp); GetDIR(dir, dirp);
errno = 0; errno = 0;
if (READDIR(dirp->dir, dirp->enc, &STRUCT_DIRENT(entry), dp)) { if ((dp = READDIR(dirp->dir, dirp->enc)) != NULL) {
return rb_external_str_new_with_enc(dp->d_name, NAMLEN(dp), dirp->enc); return rb_external_str_new_with_enc(dp->d_name, NAMLEN(dp), dirp->enc);
} }
else { else {
@ -620,13 +619,25 @@ dir_each(VALUE dir)
{ {
struct dir_data *dirp; struct dir_data *dirp;
struct dirent *dp; struct dirent *dp;
IF_HAVE_READDIR_R(DEFINE_STRUCT_DIRENT entry); IF_HAVE_HFS(int hfs_p);
RETURN_ENUMERATOR(dir, 0, 0); RETURN_ENUMERATOR(dir, 0, 0);
GetDIR(dir, dirp); GetDIR(dir, dirp);
rewinddir(dirp->dir); rewinddir(dirp->dir);
while (READDIR(dirp->dir, dirp->enc, &STRUCT_DIRENT(entry), dp)) { IF_HAVE_HFS(hfs_p = is_hfs(dirp->dir));
rb_yield(rb_external_str_new_with_enc(dp->d_name, NAMLEN(dp), dirp->enc)); while ((dp = READDIR(dirp->dir, dirp->enc)) != NULL) {
const char *name = dp->d_name;
size_t namlen = NAMLEN(dp);
VALUE path;
#if HAVE_HFS
if (hfs_p && has_nonascii(name, namlen) &&
!NIL_P(path = rb_str_normalize_ospath(name, namlen))) {
path = rb_external_str_with_enc(path, dirp->enc);
}
else
#endif
path = rb_external_str_new_with_enc(name, namlen, dirp->enc);
rb_yield(path);
if (dirp->dir == NULL) dir_closed(); if (dirp->dir == NULL) dir_closed();
} }
return dir; return dir;
@ -689,9 +700,10 @@ dir_seek(VALUE dir, VALUE pos)
#define dir_seek rb_f_notimplement #define dir_seek rb_f_notimplement
#endif #endif
#ifdef HAVE_SEEKDIR
/* /*
* call-seq: * call-seq:
* dir.pos( integer ) -> integer * dir.pos = integer -> integer
* *
* Synonym for <code>Dir#seek</code>, but returns the position * Synonym for <code>Dir#seek</code>, but returns the position
* parameter. * parameter.
@ -709,6 +721,9 @@ dir_set_pos(VALUE dir, VALUE pos)
dir_seek(dir, pos); dir_seek(dir, pos);
return pos; return pos;
} }
#else
#define dir_set_pos rb_f_notimplement
#endif
/* /*
* call-seq: * call-seq:
@ -726,9 +741,6 @@ dir_rewind(VALUE dir)
{ {
struct dir_data *dirp; struct dir_data *dirp;
if (rb_safe_level() >= 4 && !OBJ_UNTRUSTED(dir)) {
rb_raise(rb_eSecurityError, "Insecure: can't close");
}
GetDIR(dir, dirp); GetDIR(dir, dirp);
rewinddir(dirp->dir); rewinddir(dirp->dir);
return dir; return dir;
@ -876,7 +888,6 @@ rb_dir_getwd(void)
char *path; char *path;
VALUE cwd; VALUE cwd;
rb_secure(4);
path = my_getcwd(); path = my_getcwd();
cwd = rb_tainted_str_new2(path); cwd = rb_tainted_str_new2(path);
rb_enc_associate(cwd, rb_filesystem_encoding()); rb_enc_associate(cwd, rb_filesystem_encoding());
@ -1021,18 +1032,25 @@ sys_warning_1(VALUE mesg)
*/ */
#define to_be_ignored(e) ((e) == ENOENT || (e) == ENOTDIR) #define to_be_ignored(e) ((e) == ENOENT || (e) == ENOTDIR)
#ifdef _WIN32
#define STAT(p, s) rb_w32_ustati64((p), (s))
#else
#define STAT(p, s) stat((p), (s))
#endif
/* System call with warning */ /* System call with warning */
static int static int
do_stat(const char *path, struct stat *pst, int flags) do_stat(const char *path, struct stat *pst, int flags)
{ {
int ret = stat(path, pst); int ret = STAT(path, pst);
if (ret < 0 && !to_be_ignored(errno)) if (ret < 0 && !to_be_ignored(errno))
sys_warning(path); sys_warning(path);
return ret; return ret;
} }
#if defined HAVE_LSTAT || defined lstat
static int static int
do_lstat(const char *path, struct stat *pst, int flags) do_lstat(const char *path, struct stat *pst, int flags)
{ {
@ -1042,6 +1060,9 @@ do_lstat(const char *path, struct stat *pst, int flags)
return ret; return ret;
} }
#else
#define do_lstat do_stat
#endif
static DIR * static DIR *
do_opendir(const char *path, int flags, rb_encoding *enc) do_opendir(const char *path, int flags, rb_encoding *enc)
@ -1248,9 +1269,8 @@ glob_free_pattern(struct glob_pattern *list)
} }
static char * static char *
join_path(const char *path, int dirsep, const char *name, size_t namlen) join_path(const char *path, long len, int dirsep, const char *name, size_t namlen)
{ {
long len = strlen(path);
char *buf = GLOB_ALLOC_N(char, len+namlen+(dirsep?1:0)+1); char *buf = GLOB_ALLOC_N(char, len+namlen+(dirsep?1:0)+1);
if (!buf) return 0; if (!buf) return 0;
@ -1313,6 +1333,7 @@ glob_helper(
struct glob_pattern **cur, **new_beg, **new_end; struct glob_pattern **cur, **new_beg, **new_end;
int plain = 0, magical = 0, recursive = 0, match_all = 0, match_dir = 0; int plain = 0, magical = 0, recursive = 0, match_all = 0, match_dir = 0;
int escape = !(flags & FNM_NOESCAPE); int escape = !(flags & FNM_NOESCAPE);
long pathlen;
for (cur = beg; cur < end; ++cur) { for (cur = beg; cur < end; ++cur) {
struct glob_pattern *p = *cur; struct glob_pattern *p = *cur;
@ -1338,6 +1359,7 @@ glob_helper(
} }
} }
pathlen = strlen(path);
if (*path) { if (*path) {
if (match_all && exist == UNKNOWN) { if (match_all && exist == UNKNOWN) {
if (do_lstat(path, &st, flags) == 0) { if (do_lstat(path, &st, flags) == 0) {
@ -1364,7 +1386,7 @@ glob_helper(
if (status) return status; if (status) return status;
} }
if (match_dir && isdir == YES) { if (match_dir && isdir == YES) {
char *tmp = join_path(path, dirsep, "", 0); char *tmp = join_path(path, pathlen, dirsep, "", 0);
if (!tmp) return -1; if (!tmp) return -1;
status = glob_call_func(func, tmp, arg, enc); status = glob_call_func(func, tmp, arg, enc);
GLOB_FREE(tmp); GLOB_FREE(tmp);
@ -1377,29 +1399,50 @@ glob_helper(
if (magical || recursive) { if (magical || recursive) {
struct dirent *dp; struct dirent *dp;
DIR *dirp; DIR *dirp;
IF_HAVE_READDIR_R(DEFINE_STRUCT_DIRENT entry); IF_HAVE_HFS(int hfs_p);
dirp = do_opendir(*path ? path : ".", flags, enc); dirp = do_opendir(*path ? path : ".", flags, enc);
if (dirp == NULL) return 0; if (dirp == NULL) return 0;
IF_HAVE_HFS(hfs_p = is_hfs(dirp));
while (READDIR(dirp, enc, &STRUCT_DIRENT(entry), dp)) { while ((dp = READDIR(dirp, enc)) != NULL) {
char *buf; char *buf;
enum answer new_isdir = UNKNOWN; enum answer new_isdir = UNKNOWN;
const char *name;
size_t namlen;
int dotfile = 0;
IF_HAVE_HFS(VALUE utf8str = Qnil);
if (recursive && dp->d_name[0] == '.') { if (recursive && dp->d_name[0] == '.') {
/* RECURSIVE never match dot files unless FNM_DOTMATCH is set */ ++dotfile;
if (!(flags & FNM_DOTMATCH)) continue; if (!dp->d_name[1]) {
/* unless DOTMATCH, skip current directories not to recurse infinitely */
/* always skip current and parent directories not to recurse infinitely */ if (!(flags & FNM_DOTMATCH)) continue;
if (!dp->d_name[1]) continue; ++dotfile;
if (dp->d_name[1] == '.' && !dp->d_name[2]) continue; }
else if (dp->d_name[1] == '.' && !dp->d_name[2]) {
/* always skip parent directories not to recurse infinitely */
continue;
}
} }
buf = join_path(path, dirsep, dp->d_name, NAMLEN(dp)); name = dp->d_name;
namlen = NAMLEN(dp);
# if HAVE_HFS
if (hfs_p && has_nonascii(name, namlen)) {
if (!NIL_P(utf8str = rb_str_normalize_ospath(name, namlen))) {
RSTRING_GETMEM(utf8str, name, namlen);
}
}
# endif
buf = join_path(path, pathlen, dirsep, name, namlen);
IF_HAVE_HFS(if (!NIL_P(utf8str)) rb_str_resize(utf8str, 0));
if (!buf) { if (!buf) {
status = -1; status = -1;
break; break;
} }
if (recursive) { name = buf + pathlen + (dirsep != 0);
if (recursive && dotfile < ((flags & FNM_DOTMATCH) ? 2 : 1)) {
/* RECURSIVE never match dot files unless FNM_DOTMATCH is set */
#ifndef _WIN32 #ifndef _WIN32
if (do_lstat(buf, &st, flags) == 0) if (do_lstat(buf, &st, flags) == 0)
new_isdir = S_ISDIR(st.st_mode) ? YES : S_ISLNK(st.st_mode) ? UNKNOWN : NO; new_isdir = S_ISDIR(st.st_mode) ? YES : S_ISLNK(st.st_mode) ? UNKNOWN : NO;
@ -1425,7 +1468,7 @@ glob_helper(
p = p->next; /* 0 times recursion */ p = p->next; /* 0 times recursion */
} }
if (p->type == PLAIN || p->type == MAGICAL) { if (p->type == PLAIN || p->type == MAGICAL) {
if (fnmatch(p->str, enc, dp->d_name, flags) == 0) if (fnmatch(p->str, enc, name, flags) == 0)
*new_end++ = p->next; *new_end++ = p->next;
} }
} }
@ -1475,7 +1518,7 @@ glob_helper(
} }
} }
buf = join_path(path, dirsep, name, len); buf = join_path(path, pathlen, dirsep, name, len);
GLOB_FREE(name); GLOB_FREE(name);
if (!buf) { if (!buf) {
GLOB_FREE(new_beg); GLOB_FREE(new_beg);
@ -1723,7 +1766,7 @@ rb_push_glob(VALUE str, int flags) /* '\0' is delimiter */
} }
static VALUE static VALUE
dir_globs(long argc, VALUE *argv, int flags) dir_globs(long argc, const VALUE *argv, int flags)
{ {
VALUE ary = rb_ary_new(); VALUE ary = rb_ary_new();
long i; long i;
@ -1760,49 +1803,56 @@ dir_s_aref(int argc, VALUE *argv, VALUE obj)
/* /*
* call-seq: * call-seq:
* Dir.glob( pattern, [flags] ) -> array * Dir.glob( pattern, [flags] ) -> matches
* Dir.glob( pattern, [flags] ) {| filename | block } -> nil * Dir.glob( pattern, [flags] ) { |filename| block } -> nil
* *
* Returns the filenames found by expanding <i>pattern</i> which is * Expands +pattern+, which is an Array of patterns or a pattern String, and
* an +Array+ of the patterns or the pattern +String+, either as an * returns the results as +matches+ or as arguments given to the block.
* <i>array</i> or as parameters to the block. Note that this pattern
* is not a regexp (it's closer to a shell glob). See
* <code>File::fnmatch</code> for the meaning of the <i>flags</i>
* parameter. Note that case sensitivity depends on your system (so
* <code>File::FNM_CASEFOLD</code> is ignored), as does the order
* in which the results are returned.
* *
* <code>*</code>:: Matches any file. Can be restricted by * Note that this pattern is not a regexp, it's closer to a shell glob. See
* other values in the glob. <code>*</code> * File::fnmatch for the meaning of the +flags+ parameter. Note that case
* will match all files; <code>c*</code> will * sensitivity depends on your system (so File::FNM_CASEFOLD is ignored), as
* match all files beginning with * does the order in which the results are returned.
* <code>c</code>; <code>*c</code> will match *
* all files ending with <code>c</code>; and * <code>*</code>::
* <code>\*c\*</code> will match all files that * Matches any file. Can be restricted by other values in the glob.
* have <code>c</code> in them (including at * Equivalent to <code>/ .* /x</code> in regexp.
* the beginning or end). Equivalent to *
* <code>/ .* /x</code> in regexp. Note, this * <code>*</code>:: Matches all files
* will not match Unix-like hidden files (dotfiles). * <code>c*</code>:: Matches all files beginning with <code>c</code>
* In order to include those in the match results, * <code>*c</code>:: Matches all files ending with <code>c</code>
* you must use something like <code>"{*,.*}"</code>. * <code>\*c\*</code>:: Match all files that have <code>c</code> in them
* <code>**</code>:: Matches directories recursively. * (including at the beginning or end).
* <code>?</code>:: Matches any one character. Equivalent to *
* <code>/.{1}/</code> in regexp. * Note, this will not match Unix-like hidden files (dotfiles). In order
* <code>[set]</code>:: Matches any one character in +set+. * to include those in the match results, you must use the
* Behaves exactly like character sets in * File::FNM_DOTMATCH flag or something like <code>"{*,.*}"</code>.
* Regexp, including set negation *
* (<code>[^a-z]</code>). * <code>**</code>::
* <code>{p,q}</code>:: Matches either literal <code>p</code> or * Matches directories recursively.
* literal <code>q</code>. Matching literals *
* may be more than one character in length. * <code>?</code>::
* More than two literals may be specified. * Matches any one character. Equivalent to <code>/.{1}/</code> in regexp.
* Equivalent to pattern alternation in *
* regexp. * <code>[set]</code>::
* <code> \\ </code>:: Escapes the next metacharacter. * Matches any one character in +set+. Behaves exactly like character sets
* Note that this means you cannot use backslash * in Regexp, including set negation (<code>[^a-z]</code>).
* in windows as part of a glob, *
* i.e. <code>Dir["c:\\foo*"]</code> will not work, * <code>{p,q}</code>::
* use <code>Dir["c:/foo*"]</code> instead. * Matches either literal <code>p</code> or literal <code>q</code>.
* Equivalent to pattern alternation in regexp.
*
* Matching literals may be more than one character in length. More than
* two literals may be specified.
*
* <code> \\ </code>::
* Escapes the next metacharacter.
*
* Note that this means you cannot use backslash on windows as part of a
* glob, i.e. <code>Dir["c:\\foo*"]</code> will not work, use
* <code>Dir["c:/foo*"]</code> instead.
*
* Examples:
* *
* Dir["config.?"] #=> ["config.h"] * Dir["config.?"] #=> ["config.h"]
* Dir.glob("config.?") #=> ["config.h"] * Dir.glob("config.?") #=> ["config.h"]
@ -1843,7 +1893,7 @@ dir_s_glob(int argc, VALUE *argv, VALUE obj)
} }
else { else {
volatile VALUE v = ary; volatile VALUE v = ary;
ary = dir_globs(RARRAY_LEN(v), RARRAY_PTR(v), flags); ary = dir_globs(RARRAY_LEN(v), RARRAY_CONST_PTR(v), flags);
} }
if (rb_block_given_p()) { if (rb_block_given_p()) {
@ -1865,8 +1915,10 @@ dir_open_dir(int argc, VALUE *argv)
/* /*
* call-seq: * call-seq:
* Dir.foreach( dirname ) {| filename | block } -> nil * Dir.foreach( dirname ) {| filename | block } -> nil
* Dir.foreach( dirname ) -> an_enumerator * Dir.foreach( dirname, encoding: enc ) {| filename | block } -> nil
* Dir.foreach( dirname ) -> an_enumerator
* Dir.foreach( dirname, encoding: enc ) -> an_enumerator
* *
* Calls the block once for each entry in the named directory, passing * Calls the block once for each entry in the named directory, passing
* the filename of each entry as a parameter to the block. * the filename of each entry as a parameter to the block.
@ -1896,12 +1948,16 @@ dir_foreach(int argc, VALUE *argv, VALUE io)
/* /*
* call-seq: * call-seq:
* Dir.entries( dirname ) -> array * Dir.entries( dirname ) -> array
* Dir.entries( dirname, encoding: enc ) -> array
* *
* Returns an array containing all of the filenames in the given * Returns an array containing all of the filenames in the given
* directory. Will raise a <code>SystemCallError</code> if the named * directory. Will raise a <code>SystemCallError</code> if the named
* directory doesn't exist. * directory doesn't exist.
* *
* The optional <i>enc</i> argument specifies the encoding of the directory.
* If not specified, the filesystem encoding is used.
*
* Dir.entries("testdir") #=> [".", "..", "config.h", "main.rb"] * Dir.entries("testdir") #=> [".", "..", "config.h", "main.rb"]
* *
*/ */
@ -1919,7 +1975,24 @@ fnmatch_brace(const char *pattern, VALUE val, void *enc)
{ {
struct brace_args *arg = (struct brace_args *)val; struct brace_args *arg = (struct brace_args *)val;
VALUE path = arg->value; VALUE path = arg->value;
rb_encoding *enc_pattern = enc;
rb_encoding *enc_path = rb_enc_get(path);
if (enc_pattern != enc_path) {
if (!rb_enc_asciicompat(enc_pattern))
return FNM_NOMATCH;
if (!rb_enc_asciicompat(enc_path))
return FNM_NOMATCH;
if (!rb_enc_str_asciionly_p(path)) {
int cr = ENC_CODERANGE_7BIT;
long len = strlen(pattern);
if (rb_str_coderange_scan_restartable(pattern, pattern + len,
enc_pattern, &cr) != len)
return FNM_NOMATCH;
if (cr != ENC_CODERANGE_7BIT)
return FNM_NOMATCH;
}
}
return (fnmatch(pattern, enc, RSTRING_PTR(path), arg->flags) == 0); return (fnmatch(pattern, enc, RSTRING_PTR(path), arg->flags) == 0);
} }
@ -1928,38 +2001,50 @@ fnmatch_brace(const char *pattern, VALUE val, void *enc)
* File.fnmatch( pattern, path, [flags] ) -> (true or false) * File.fnmatch( pattern, path, [flags] ) -> (true or false)
* File.fnmatch?( pattern, path, [flags] ) -> (true or false) * File.fnmatch?( pattern, path, [flags] ) -> (true or false)
* *
* Returns true if <i>path</i> matches against <i>pattern</i> The * Returns true if +path+ matches against +pattern+. The pattern is not a
* pattern is not a regular expression; instead it follows rules * regular expression; instead it follows rules similar to shell filename
* similar to shell filename globbing. It may contain the following * globbing. It may contain the following metacharacters:
* metacharacters:
* *
* <code>*</code>:: Matches any file. Can be restricted by * <code>*</code>::
* other values in the glob. <code>*</code> * Matches any file. Can be restricted by other values in the glob.
* will match all files; <code>c*</code> will * Equivalent to <code>/ .* /x</code> in regexp.
* match all files beginning with
* <code>c</code>; <code>*c</code> will match
* all files ending with <code>c</code>; and
* <code>\*c*</code> will match all files that
* have <code>c</code> in them (including at
* the beginning or end). Equivalent to
* <code>/ .* /x</code> in regexp.
* <code>**</code>:: Matches directories recursively or files
* expansively.
* <code>?</code>:: Matches any one character. Equivalent to
* <code>/.{1}/</code> in regexp.
* <code>[set]</code>:: Matches any one character in +set+.
* Behaves exactly like character sets in
* Regexp, including set negation
* (<code>[^a-z]</code>).
* <code> \ </code>:: Escapes the next metacharacter.
* *
* <i>flags</i> is a bitwise OR of the <code>FNM_xxx</code> * <code>*</code>:: Matches all files regular files
* parameters. The same glob pattern and flags are used by * <code>c*</code>:: Matches all files beginning with <code>c</code>
* <code>Dir::glob</code>. * <code>*c</code>:: Matches all files ending with <code>c</code>
* <code>\*c*</code>:: Matches all files that have <code>c</code> in them
* (including at the beginning or end).
*
* To match hidden files (that start with a <code>.</code> set the
* File::FNM_DOTMATCH flag.
*
* <code>**</code>::
* Matches directories recursively or files expansively.
*
* <code>?</code>::
* Matches any one character. Equivalent to <code>/.{1}/</code> in regexp.
*
* <code>[set]</code>::
* Matches any one character in +set+. Behaves exactly like character sets
* in Regexp, including set negation (<code>[^a-z]</code>).
*
* <code> \ </code>::
* Escapes the next metacharacter.
*
* <code>{a,b}</code>::
* Matches pattern a and pattern b if File::FNM_EXTGLOB flag is enabled.
* Behaves like a Regexp union (<code>(?:a|b)</code>).
*
* +flags+ is a bitwise OR of the <code>FNM_XXX</code> constants. The same
* glob pattern and flags are used by Dir::glob.
*
* Examples:
* *
* File.fnmatch('cat', 'cat') #=> true # match entire string * File.fnmatch('cat', 'cat') #=> true # match entire string
* File.fnmatch('cat', 'category') #=> false # only match partial string * File.fnmatch('cat', 'category') #=> false # only match partial string
* File.fnmatch('c{at,ub}s', 'cats') #=> false # { } isn't supported *
* File.fnmatch('c{at,ub}s', 'cats') #=> false # { } isn't supported by default
* File.fnmatch('c{at,ub}s', 'cats', File::FNM_EXTGLOB) #=> true # { } is supported on FNM_EXTGLOB
* *
* File.fnmatch('c?t', 'cat') #=> true # '?' match only 1 character * File.fnmatch('c?t', 'cat') #=> true # '?' match only 1 character
* File.fnmatch('c??t', 'cat') #=> false # ditto * File.fnmatch('c??t', 'cat') #=> false # ditto
@ -1977,7 +2062,7 @@ fnmatch_brace(const char *pattern, VALUE val, void *enc)
* *
* File.fnmatch('\?', '?') #=> true # escaped wildcard becomes ordinary * File.fnmatch('\?', '?') #=> true # escaped wildcard becomes ordinary
* File.fnmatch('\a', 'a') #=> true # escaped ordinary remains ordinary * File.fnmatch('\a', 'a') #=> true # escaped ordinary remains ordinary
* File.fnmatch('\a', '\a', File::FNM_NOESCAPE) #=> true # FNM_NOESACPE makes '\' ordinary * File.fnmatch('\a', '\a', File::FNM_NOESCAPE) #=> true # FNM_NOESCAPE makes '\' ordinary
* File.fnmatch('[\?]', '?') #=> true # can escape inside bracket expression * File.fnmatch('[\?]', '?') #=> true # can escape inside bracket expression
* *
* File.fnmatch('*', '.profile') #=> false # wildcard doesn't match leading * File.fnmatch('*', '.profile') #=> false # wildcard doesn't match leading
@ -2029,8 +2114,9 @@ file_s_fnmatch(int argc, VALUE *argv, VALUE obj)
return Qtrue; return Qtrue;
} }
else { else {
if (fnmatch(RSTRING_PTR(pattern), rb_enc_get(pattern), RSTRING_PTR(path), rb_encoding *enc = rb_enc_compatible(pattern, path);
flags) == 0) if (!enc) return Qfalse;
if (fnmatch(RSTRING_PTR(pattern), enc, RSTRING_PTR(path), flags) == 0)
return Qtrue; return Qtrue;
} }
RB_GC_GUARD(pattern); RB_GC_GUARD(pattern);
@ -2052,12 +2138,18 @@ dir_s_home(int argc, VALUE *argv, VALUE obj)
VALUE user; VALUE user;
const char *u = 0; const char *u = 0;
rb_scan_args(argc, argv, "01", &user); rb_check_arity(argc, 0, 1);
user = (argc > 0) ? argv[0] : Qnil;
if (!NIL_P(user)) { if (!NIL_P(user)) {
SafeStringValue(user); SafeStringValue(user);
rb_must_asciicompat(user);
u = StringValueCStr(user); u = StringValueCStr(user);
if (*u) {
return rb_home_dir_of(user, rb_str_new(0, 0));
}
} }
return rb_home_dir(u, rb_str_new(0, 0)); return rb_default_home_dir(rb_str_new(0, 0));
} }
#if 0 #if 0
@ -2076,6 +2168,13 @@ rb_file_directory_p()
} }
#endif #endif
static VALUE
rb_dir_exists_p(VALUE obj, VALUE fname)
{
rb_warning("Dir.exists? is a deprecated name, use Dir.exist? instead");
return rb_file_directory_p(obj, fname);
}
/* /*
* Objects of class <code>Dir</code> are directory streams representing * Objects of class <code>Dir</code> are directory streams representing
* directories in the underlying file system. They provide a variety of * directories in the underlying file system. They provide a variety of
@ -2125,15 +2224,42 @@ Init_Dir(void)
rb_define_singleton_method(rb_cDir,"glob", dir_s_glob, -1); rb_define_singleton_method(rb_cDir,"glob", dir_s_glob, -1);
rb_define_singleton_method(rb_cDir,"[]", dir_s_aref, -1); rb_define_singleton_method(rb_cDir,"[]", dir_s_aref, -1);
rb_define_singleton_method(rb_cDir,"exist?", rb_file_directory_p, 1); rb_define_singleton_method(rb_cDir,"exist?", rb_file_directory_p, 1);
rb_define_singleton_method(rb_cDir,"exists?", rb_file_directory_p, 1); rb_define_singleton_method(rb_cDir,"exists?", rb_dir_exists_p, 1);
rb_define_singleton_method(rb_cFile,"fnmatch", file_s_fnmatch, -1); rb_define_singleton_method(rb_cFile,"fnmatch", file_s_fnmatch, -1);
rb_define_singleton_method(rb_cFile,"fnmatch?", file_s_fnmatch, -1); rb_define_singleton_method(rb_cFile,"fnmatch?", file_s_fnmatch, -1);
/* Document-const: File::Constants::FNM_NOESCAPE
*
* Disables escapes in File.fnmatch and Dir.glob patterns
*/
rb_file_const("FNM_NOESCAPE", INT2FIX(FNM_NOESCAPE)); rb_file_const("FNM_NOESCAPE", INT2FIX(FNM_NOESCAPE));
/* Document-const: File::Constants::FNM_PATHNAME
*
* Wildcards in File.fnmatch and Dir.glob patterns do not match directory
* separators
*/
rb_file_const("FNM_PATHNAME", INT2FIX(FNM_PATHNAME)); rb_file_const("FNM_PATHNAME", INT2FIX(FNM_PATHNAME));
/* Document-const: File::Constants::FNM_DOTMATCH
*
* The '*' wildcard matches filenames starting with "." in File.fnmatch
* and Dir.glob patterns
*/
rb_file_const("FNM_DOTMATCH", INT2FIX(FNM_DOTMATCH)); rb_file_const("FNM_DOTMATCH", INT2FIX(FNM_DOTMATCH));
/* Document-const: File::Constants::FNM_CASEFOLD
*
* Makes File.fnmatch patterns case insensitive (but not Dir.glob
* patterns).
*/
rb_file_const("FNM_CASEFOLD", INT2FIX(FNM_CASEFOLD)); rb_file_const("FNM_CASEFOLD", INT2FIX(FNM_CASEFOLD));
/* Document-const: File::Constants::FNM_EXTGLOB
*
* Allows file globbing through "{a,b}" in File.fnmatch patterns.
*/
rb_file_const("FNM_EXTGLOB", INT2FIX(FNM_EXTGLOB)); rb_file_const("FNM_EXTGLOB", INT2FIX(FNM_EXTGLOB));
rb_file_const("FNM_SYSCASE", INT2FIX(FNM_SYSCASE)); rb_file_const("FNM_SYSCASE", INT2FIX(FNM_SYSCASE));
} }

19
dln.h
View file

@ -28,14 +28,17 @@
# define _(args) () # define _(args) ()
#endif #endif
#if defined __GNUC__ && __GNUC__ >= 4 RUBY_SYMBOL_EXPORT_BEGIN
#pragma GCC visibility push(default)
#ifndef DLN_FIND_EXTRA_ARG
#define DLN_FIND_EXTRA_ARG
#endif
#ifndef DLN_FIND_EXTRA_ARG_DECL
#define DLN_FIND_EXTRA_ARG_DECL
#endif #endif
DEPRECATED(char *dln_find_exe(const char*,const char*)); char *dln_find_exe_r(const char*,const char*,char*,size_t DLN_FIND_EXTRA_ARG_DECL);
DEPRECATED(char *dln_find_file(const char*,const char*)); char *dln_find_file_r(const char*,const char*,char*,size_t DLN_FIND_EXTRA_ARG_DECL);
char *dln_find_exe_r(const char*,const char*,char*,size_t);
char *dln_find_file_r(const char*,const char*,char*,size_t);
#ifdef USE_DLN_A_OUT #ifdef USE_DLN_A_OUT
extern char *dln_argv0; extern char *dln_argv0;
@ -43,8 +46,6 @@ extern char *dln_argv0;
void *dln_load(const char*); void *dln_load(const char*);
#if defined __GNUC__ && __GNUC__ >= 4 RUBY_SYMBOL_EXPORT_END
#pragma GCC visibility pop
#endif
#endif #endif

View file

@ -11,19 +11,11 @@
#ifdef RUBY_EXPORT #ifdef RUBY_EXPORT
#include "ruby/ruby.h" #include "ruby/ruby.h"
#define dln_notimplement rb_notimplement
#define dln_memerror rb_memerror
#define dln_exit rb_exit
#define dln_loaderror rb_loaderror
#define dln_warning rb_warning #define dln_warning rb_warning
#define dln_warning_arg #define dln_warning_arg
#else #else
#define dln_notimplement --->>> dln not implemented <<<---
#define dln_memerror abort
#define dln_exit exit
#define dln_warning fprintf #define dln_warning fprintf
#define dln_warning_arg stderr, #define dln_warning_arg stderr,
static void dln_loaderror(const char *format, ...);
#endif #endif
#include "dln.h" #include "dln.h"
@ -67,14 +59,16 @@ char *dln_argv0;
# include <unistd.h> # include <unistd.h>
#endif #endif
#ifndef _WIN32 #if !defined(_WIN32) && !HAVE_DECL_GETENV
char *getenv(); char *getenv();
#endif #endif
static char *dln_find_1(const char *fname, const char *path, char *buf, size_t size, int exe_flag); static char *dln_find_1(const char *fname, const char *path, char *buf, size_t size, int exe_flag
DLN_FIND_EXTRA_ARG_DECL);
char * char *
dln_find_exe_r(const char *fname, const char *path, char *buf, size_t size) dln_find_exe_r(const char *fname, const char *path, char *buf, size_t size
DLN_FIND_EXTRA_ARG_DECL)
{ {
char *envpath = 0; char *envpath = 0;
@ -90,35 +84,23 @@ dln_find_exe_r(const char *fname, const char *path, char *buf, size_t size)
path = "/usr/local/bin:/usr/ucb:/usr/bin:/bin:."; path = "/usr/local/bin:/usr/ucb:/usr/bin:/bin:.";
#endif #endif
} }
buf = dln_find_1(fname, path, buf, size, 1); buf = dln_find_1(fname, path, buf, size, 1 DLN_FIND_EXTRA_ARG);
if (envpath) free(envpath); if (envpath) free(envpath);
return buf; return buf;
} }
char * char *
dln_find_file_r(const char *fname, const char *path, char *buf, size_t size) dln_find_file_r(const char *fname, const char *path, char *buf, size_t size
DLN_FIND_EXTRA_ARG_DECL)
{ {
if (!path) path = "."; if (!path) path = ".";
return dln_find_1(fname, path, buf, size, 0); return dln_find_1(fname, path, buf, size, 0 DLN_FIND_EXTRA_ARG);
}
static char fbuf[MAXPATHLEN];
char *
dln_find_exe(const char *fname, const char *path)
{
return dln_find_exe_r(fname, path, fbuf, sizeof(fbuf));
}
char *
dln_find_file(const char *fname, const char *path)
{
return dln_find_file_r(fname, path, fbuf, sizeof(fbuf));
} }
static char * static char *
dln_find_1(const char *fname, const char *path, char *fbuf, size_t size, dln_find_1(const char *fname, const char *path, char *fbuf, size_t size,
int exe_flag /* non 0 if looking for executable. */) int exe_flag /* non 0 if looking for executable. */
DLN_FIND_EXTRA_ARG_DECL)
{ {
register const char *dp; register const char *dp;
register const char *ep; register const char *ep;

View file

@ -1,2 +0,0 @@
#define NO_LOCALE_CHARMAP 1
#include "encoding.c"

View file

@ -1,2 +0,0 @@
#define NO_INITIAL_LOAD_PATH 1
#include "version.c"

View file

@ -13763,7 +13763,7 @@ Tue Apr 17 17:33:55 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
* eval.c (handle_rescue): use === to compare exception match. * eval.c (handle_rescue): use === to compare exception match.
* error.c (syserr_eqq): comparison between SytemCallErrors should * error.c (syserr_eqq): comparison between SystemCallErrors should
based on their error numbers. based on their error numbers.
Tue Apr 17 16:54:39 2001 K.Kosako <kosako@sofnec.co.jp> Tue Apr 17 16:54:39 2001 K.Kosako <kosako@sofnec.co.jp>

View file

@ -14297,7 +14297,7 @@ Thu Jun 10 09:10:08 2010 Yukihiro Matsumoto <matz@ruby-lang.org>
Wed Jun 9 22:51:50 2010 Tanaka Akira <akr@fsij.org> Wed Jun 9 22:51:50 2010 Tanaka Akira <akr@fsij.org>
* time.c (find_time_t): always outerpolate from past. * time.c (find_time_t): always extrapolate from past.
[ruby-core:30672] reported by Benoit Daloze. [ruby-core:30672] reported by Benoit Daloze.
Wed Jun 9 22:13:08 2010 Tanaka Akira <akr@fsij.org> Wed Jun 9 22:13:08 2010 Tanaka Akira <akr@fsij.org>
@ -76917,7 +76917,7 @@ Tue May 31 15:52:45 2005 GOTOU Yuuzou <gotoyuzo@notwork.org>
break the loop if the socket reached to EOF. [ruby-talk:142285] break the loop if the socket reached to EOF. [ruby-talk:142285]
* lib/webrick/httpserver.rb (WEBrick::HTTPServer#run): send response * lib/webrick/httpserver.rb (WEBrick::HTTPServer#run): send response
without reading the whole request body if keep-alive is diabled. without reading the whole request body if keep-alive is disabled.
[experimental] [experimental]
Mon May 30 23:48:29 2005 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp> Mon May 30 23:48:29 2005 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
@ -76939,7 +76939,7 @@ Sat May 28 16:39:21 2005 GOTOU Yuuzou <gotoyuzo@notwork.org>
Sat May 28 05:15:44 2005 GOTOU Yuuzou <gotoyuzo@notwork.org> Sat May 28 05:15:44 2005 GOTOU Yuuzou <gotoyuzo@notwork.org>
* ext/openssl/ossl_x509store.c (ossl_x509stctx_set_time): should * ext/openssl/ossl_x509store.c (ossl_x509stctx_set_time): should
not set internal flag directry. not set internal flag directory.
Sat May 28 02:00:11 2005 GOTOU Yuuzou <gotoyuzo@notwork.org> Sat May 28 02:00:11 2005 GOTOU Yuuzou <gotoyuzo@notwork.org>

24015
doc/ChangeLog-2.0.0 Normal file

File diff suppressed because it is too large Load diff

View file

@ -4328,7 +4328,7 @@ Sun Dec 31 17:42:05 2006 Koichi Sasada <ko1@atdot.net>
* vm.c : fix to skip pushing value at "next" * vm.c : fix to skip pushing value at "next"
* yarvcore.h : move definision of * yarvcore.h : move definition of
"struct iseq_compile_data_ensure_node_stack" to compile.c "struct iseq_compile_data_ensure_node_stack" to compile.c
* compile.c : fix ensure catch table creation * compile.c : fix ensure catch table creation

View file

@ -54,7 +54,7 @@ with all sufficient information, see the ChangeLog file.
* Array#flatten * Array#flatten
* Array#flatten! * Array#flatten!
Take an optional argument that determines the level of recursion Takes an optional argument that determines the level of recursion
to flatten. to flatten.
* Array#eql? * Array#eql?
@ -77,6 +77,7 @@ with all sufficient information, see the ChangeLog file.
* Array#reject * Array#reject
* Array#reject! * Array#reject!
* Array#delete_if * Array#delete_if
* Array#select
Return an enumerator if no block is given. Return an enumerator if no block is given.
@ -161,6 +162,10 @@ with all sufficient information, see the ChangeLog file.
New alias to #inject. New alias to #inject.
* Enumerable#to_a
Can take optional arguments and pass them to #each.
* Hash#eql? * Hash#eql?
* Hash#hash * Hash#hash
* Hash#== * Hash#==
@ -262,12 +267,17 @@ with all sufficient information, see the ChangeLog file.
* Regexp.union accepts an array of patterns. * Regexp.union accepts an array of patterns.
* String#bytes
New method
* String#bytesize * String#bytesize
New method, returning the size in bytes. (alias length and size) New method, returning the size in bytes. (alias length and size)
* String#chars * String#chars
* String#each_char * String#each_char
* String#lines
* String#partition * String#partition
* String#rpartition * String#rpartition
* String#start_with? * String#start_with?
@ -501,6 +511,15 @@ with all sufficient information, see the ChangeLog file.
always use Date.strptime() when you know what you are dealing always use Date.strptime() when you know what you are dealing
with. with.
* REXML
* REXML::Document.entity_expansion_limit=
New method to set the entity expansion limit. By default the limit is
set to 10000. See the following URL for details.
http://www.ruby-lang.org/en/news/2008/08/23/dos-vulnerability-in-rexml/
* stringio * stringio
* StringIO#each_byte * StringIO#each_byte

View file

@ -1,6 +1,6 @@
# -*- rdoc -*- # -*- rdoc -*-
= NEWS for RDoc 1.9.1 = NEWS for Ruby 1.9.1
This document is a list of user visible feature changes made between This document is a list of user visible feature changes made between
releases except for bug fixes. releases except for bug fixes.
@ -335,6 +335,11 @@ See doc/NEWS-1.8.7 for changes between 1.8.6 and 1.8.7.
o Numeric#upto, #downto, #times, #step o Numeric#upto, #downto, #times, #step
o Numeric#real?, Complex#real? o Numeric#real?, Complex#real?
o Numeric#magnitude o Numeric#magnitude
o Numeric#round
* Float
o Float#round
* Integer
o Integer#round
* Rational / Complex * Rational / Complex
o They are in the core library now o They are in the core library now
* Math * Math

View file

@ -1,5 +1,4 @@
# -*- rdoc -*- # -*- rdoc -*-
= NEWS for Ruby 1.9.2 = NEWS for Ruby 1.9.2
This document is a list of user visible feature changes made between This document is a list of user visible feature changes made between
@ -15,7 +14,7 @@ with all sufficient information, see the ChangeLog file.
* builtin classes * builtin classes
* Array * Array
* new method: * new methods:
* Array#keep_if * Array#keep_if
* Array#repeated_combination * Array#repeated_combination
* Array#repeated_permutation * Array#repeated_permutation
@ -24,11 +23,11 @@ with all sufficient information, see the ChangeLog file.
* Array#select! * Array#select!
* Array#sort_by! * Array#sort_by!
* extended methods: * extended method:
* Array#{uniq,uniq!,product} can take a block. * Array#{uniq,uniq!,product} can take a block.
* Complex * Complex
* new methods: * new method:
* Complex#rationalize * Complex#rationalize
* Dir * Dir
@ -51,7 +50,7 @@ with all sufficient information, see the ChangeLog file.
* ascii_compatible? * ascii_compatible?
* Enumerable * Enumerable
* New methods: * new methods:
* Enumerable#chunk * Enumerable#chunk
* Enumerable#collect_concat * Enumerable#collect_concat
* Enumerable#each_entry * Enumerable#each_entry
@ -66,7 +65,7 @@ with all sufficient information, see the ChangeLog file.
* Enumerator#feed * Enumerator#feed
* StopIteration#result * StopIteration#result
* extended methods: * extended method:
* #with_index accepts an optional argument that specifies the * #with_index accepts an optional argument that specifies the
index number to start with, defaulted to 0. index number to start with, defaulted to 0.
@ -86,14 +85,13 @@ with all sufficient information, see the ChangeLog file.
* new constants: * new constants:
* Float::INFINITY * Float::INFINITY
* Float::NAN * Float::NAN
* new methods: * new method:
* Float#rationalize * Float#rationalize
* File * File
* new methods: * new methods:
* File.realpath * File.realpath
* File.realdirpath * File.realdirpath
* File#size
* GC::Profiler * GC::Profiler
* new method: * new method:
@ -105,14 +103,14 @@ with all sufficient information, see the ChangeLog file.
* Hash#select! * Hash#select!
* IO * IO
* new method: * new methods:
* IO#autoclose= * IO#autoclose=
* IO#autoclose? * IO#autoclose?
* IO#fdatasync * IO#fdatasync
* IO#codepoints * IO#codepoints
* IO#each_codepoint * IO#each_codepoint
* extended methods: * extended method:
* IO.pipe can take a block. * IO.pipe can take a block.
* new modules: * new modules:
@ -121,7 +119,7 @@ with all sufficient information, see the ChangeLog file.
They are used to extend non-blocking exceptions. They are used to extend non-blocking exceptions.
* Integer * Integer
* new methods: * new method:
* Integer#rationalize * Integer#rationalize
* Kernel * Kernel
@ -130,7 +128,7 @@ with all sufficient information, see the ChangeLog file.
* Kernel#singleton_class * Kernel#singleton_class
* Kernel#require_relative * Kernel#require_relative
* extended methods: * extended method:
* Kernel#respond_to? can be used to detect methods not implemented. * Kernel#respond_to? can be used to detect methods not implemented.
For example, Process.respond_to?(:fork) returns false on Windows. For example, Process.respond_to?(:fork) returns false on Windows.
@ -148,11 +146,15 @@ with all sufficient information, see the ChangeLog file.
platforms. platforms.
* MatchData * MatchData
* New method: * new method:
* MatchData#== * MatchData#==
* Method
* new method:
* Method#parameters
* NilClass * NilClass
* new methods: * new method:
* NilClass#rationalize * NilClass#rationalize
* Object * Object
@ -161,18 +163,20 @@ with all sufficient information, see the ChangeLog file.
* printf() supports %a/%A format. * printf() supports %a/%A format.
* Proc * Proc
* new method:
* Proc#parameters
* extended method: * extended method:
* Proc#source_location returns location even if receiver is a method * Proc#source_location returns location even if receiver is a method
defined by attr_reader / attr_writer / attr_accessor. defined by attr_reader / attr_writer / attr_accessor.
* Process * Process
* extended methods: * extended method:
* Process.spawn accepts [:child, FD] for a redirect target. * Process.spawn accepts [:child, FD] for a redirect target.
* Random (new class to generate pseudo-random numbers) * Random (new class to generate pseudo-random numbers)
* Rational * Rational
* new methods: * new method:
* Rational#rationalize * Rational#rationalize
* String * String
@ -185,22 +189,27 @@ with all sufficient information, see the ChangeLog file.
* Thread#set_trace_func * Thread#set_trace_func
* Time * Time
* extended feature: * extended features:
* time_t restriction is removed to represent before 1901 and after 2038. * time_t restriction is removed to represent before 1901 and after 2038.
Proleptic Gregorian calendar is used for old dates. Proleptic Gregorian calendar is used for old dates.
* Time.new have optional arguments to specify date with time offset. * Time.new have optional arguments to specify date with time offset.
* Time#getlocal, Time#localtime have optional time offset argument. * Time#getlocal, Time#localtime have optional time offset argument.
* new method: * new methods:
* Time#to_r * Time#to_r
* Time#subsec * Time#subsec
* Time#round * Time#round
* incompatible changes: * incompatible change:
* The year argument of Time.{utc,gm,local,mktime} is now interpreted as * The year argument of Time.{utc,gm,local,mktime} is now interpreted as
the value itself. For example, Time.utc(99) means the year 99 AD, the value itself. For example, Time.utc(99) means the year 99 AD,
not 1999 AD. not 1999 AD.
* UnboundMethod
* new method:
* UnboundMethod#parameters
* digest * digest
* new methods: * new methods:
* Digest::Class.base64digest * Digest::Class.base64digest

View file

@ -1,5 +1,4 @@
# -*- rdoc -*- # -*- rdoc -*-
= NEWS for Ruby 1.9.3 = NEWS for Ruby 1.9.3
This document is a list of user visible feature changes made between This document is a list of user visible feature changes made between
@ -15,6 +14,13 @@ with all sufficient information, see the ChangeLog file.
* Ruby's License is changed from a dual license with GPLv2 * Ruby's License is changed from a dual license with GPLv2
to a dual license with 2-clause BSDL. to a dual license with 2-clause BSDL.
=== Known platform dependent issues
==== OS X Lion
* You have to configure ruby with '--with-gcc=gcc-4.2' if you're using
Xcode 4.1, or, if you're using Xcode 4.2, you have to configure ruby
with '--with-gcc=clang'.
=== C API updates === C API updates
* rb_scan_args() is enhanced with support for option hash argument * rb_scan_args() is enhanced with support for option hash argument
@ -23,6 +29,9 @@ with all sufficient information, see the ChangeLog file.
* ruby_vm_at_exit() added. This enables extension libs to hook a VM * ruby_vm_at_exit() added. This enables extension libs to hook a VM
termination. termination.
* rb_reserved_fd_p() added. If you want to close all file descriptors,
check using this API. [ruby-core:37759]
=== Library updates (outstanding ones only) === Library updates (outstanding ones only)
* builtin classes * builtin classes
@ -103,16 +112,34 @@ with all sufficient information, see the ChangeLog file.
the platform don't support supplementary groups concept. the platform don't support supplementary groups concept.
* bigdecimal * bigdecimal
* BigDecimal#power and BigDecimal#** support non-integral exponent. * BigDecimal#power and BigDecimal#** support non-integral exponent.
* Kernel.BigDecimal and BigDecimal.new now accept instances of Integer, * Kernel.BigDecimal and BigDecimal.new now accept instances of Integer,
Rational, and Float. If you pass a Rational or a Float to them, you must Rational, Float, and BigDecimal. If you pass a Rational or a Float to
specify the precision to produce the digits of a BigDecimal. them, you must specify the precision to produce the digits of a BigDecimal.
* The behavior of BigDecimal#coerce with a Rational is changed. It uses * The behavior of BigDecimal#coerce with a Rational is changed. It uses
the precision of the receiver BigDecimal to produce the digits of a the precision of the receiver BigDecimal to produce the digits of a
BigDecimal from the given Rational. BigDecimal from the given Rational.
* bigdecimal/util
* BigDecimal#to_d and Integer#to_d are added.
* Float#to_d accepts a precision.
* Rational#to_d raises ArgumentError when passing zero or negative
precision.
* Rational#to_d
* Zero and an implicit precision is deprecated.
This feature is removed at the next release of bigdecimal.
* A negative precision isn't supported.
Be careful it is an incompatible change.
* date * date
* Accepts flonum explicitly with limitations. * Accepts flonum explicitly with limitations.
@ -165,6 +192,9 @@ with all sufficient information, see the ChangeLog file.
* IO#winsize * IO#winsize
* IO.console * IO.console
* json
* updated to v1.5.4.
* matrix * matrix
* new classes: * new classes:
* Matrix::EigenvalueDecomposition * Matrix::EigenvalueDecomposition
@ -213,9 +243,13 @@ with all sufficient information, see the ChangeLog file.
http.request_post('/continue', 'body=BODY', 'expect' => '100-continue') http.request_post('/continue', 'body=BODY', 'expect' => '100-continue')
* new method: * new method:
* Net::HTTPRequest#set_form: Added to support * Net::HTTPRequest#set_form): Added to support
both application/x-www-form-urlencoded and multipart/form-data. both application/x-www-form-urlencoded and multipart/form-data.
* objspace
* new method:
* ObjectSpace::memsize_of_all
* openssl * openssl
* PKey::RSA and PKey::DSA now use the generic X.509 encoding scheme * PKey::RSA and PKey::DSA now use the generic X.509 encoding scheme
(e.g. used in a X.509 certificate's Subject Public Key Info) when (e.g. used in a X.509 certificate's Subject Public Key Info) when
@ -237,18 +271,18 @@ with all sufficient information, see the ChangeLog file.
* support for bash/zsh completion. * support for bash/zsh completion.
* Rake * Rake
* Rake has been upgraded from 0.8.7 to 0.9.2.1. For full release notes see * Rake has been upgraded from 0.8.7 to 0.9.2.2. For full release notes see
https://github.com/jimweirich/rake/blob/master/CHANGES https://github.com/jimweirich/rake/blob/master/CHANGES
* RDoc * RDoc
* RDoc has been upgraded from 2.5.8 to 3.8. For full release notes see * RDoc has been upgraded to version 3.9.4. For full release notes see
http://docs.seattlerb.org/rdoc/History_txt.html http://docs.seattlerb.org/rdoc/History_txt.html
* rexml * rexml
* Support Ruby native encoding mechanism and iconv dependency is dropped. * Support Ruby native encoding mechanism and iconv dependency is dropped.
* RubyGems * RubyGems
* RubyGems has been upgraded to version 1.8.5.1. For full release notes see * RubyGems has been upgraded to version 1.8.10. For full release notes see
http://rubygems.rubyforge.org/rubygems-update/History_txt.html http://rubygems.rubyforge.org/rubygems-update/History_txt.html
* stringio * stringio
@ -302,4 +336,6 @@ with all sufficient information, see the ChangeLog file.
=== Compatibility issues (excluding feature bug fixes) === Compatibility issues (excluding feature bug fixes)
None * Rational#to_d
See above.

531
doc/NEWS-2.0.0 Normal file
View file

@ -0,0 +1,531 @@
# -*- rdoc -*-
= NEWS for Ruby 2.0.0
This document is a list of user visible feature changes made between
releases except for bug fixes.
Note that each entry is kept so brief that no reason behind or
reference information is supplied with. For a full list of changes
with all sufficient information, see the ChangeLog file.
== Changes since the 1.9.3 release
=== Language changes
* Added keyword arguments.
* Added %i and %I for symbol list creation (similar to %w and %W).
* Default source encoding is changed to UTF-8. (was US-ASCII)
* No warning for unused variables starting with '_'
=== Core classes updates (outstanding ones only)
* ARGF
* added method:
* added ARGF#codepoints and ARGF#each_codepoint, like the corresponding
methods for IO.
* Array
* added method:
* added Array#bsearch for binary search.
* incompatible changes:
* random parameter of Array#shuffle! and Array#sample now
will be called with one argument, maximum value.
* when given Range arguments, Array#values_at now returns nil for each
value that is out-of-range.
* Enumerable
* added method:
* added Enumerable#lazy method for lazy enumeration.
* Enumerator
* added method:
* added Enumerator#size for lazy size evaluation.
* extended method:
* Enumerator.new accept an argument for lazy size evaluation.
* new class Enumerator::Lazy for lazy enumeration
* ENV
* aliased method:
* ENV.to_h is a new alias for ENV.to_hash
* Fiber
* incompatible changes:
* Fiber#resume cannot resume a fiber which invokes "Fiber#transfer".
* File
* extended method:
* File.fnmatch? now expands braces in the pattern if
File::FNM_EXTGLOB option is given.
* GC
* improvements:
* introduced the bitmap marking which suppresses to copy a memory page
with Copy-on-Write.
* introduced the non-recursive marking which avoids unexpected stack overflow.
* GC::Profiler
* added method:
* added GC::Profiler.raw_data which returns raw profile data for GC.
* Hash
* added method:
* added Hash#to_h as explicit conversion method, like Array#to_a.
* extended method:
* Hash#default_proc= can be passed nil to clear the default proc.
* IO
* deprecated methods:
* IO#lines, #bytes, #chars and #codepoints are deprecated.
* Kernel
* added method:
* added Kernel#Hash conversion method like Array() or Float().
* added Kernel#__dir__ which returns the absolute path of the
directory of the file from which this method is called.
* added Kernel#caller_locations which returns an array of
frame information objects.
* extended method:
* Kernel#warn accepts multiple args in like puts.
* Kernel#caller accepts second optional argument `n' which specify
required caller size.
* Kernel#to_enum and enum_for accept a block for lazy size evaluation.
* incompatible changes:
* system() and exec() closes non-standard file descriptors
(The default of :close_others option is changed to true by default.)
* respond_to? against a protected method now returns false unless
the second argument is true.
* __callee__ has returned to the original behavior, and now
returns the called name but not the original name in an
aliased method.
* Kernel#inspect does not call #to_s anymore
(it used to call redefined #to_s).
* LoadError
* added method:
* added LoadError#path method to return the file name that could not be
loaded.
* Module
* added method:
* added Module#prepend which is similar to Module#include,
however a method in the prepended module overrides the
corresponding method in the prepending module.
* added Module.prepended and Module.prepend_features, similar
to included and append_features.
* added Module#refine, which extends a class or module locally.
[experimental]
* extended method:
* Module#define_method accepts a UnboundMethod from a Module.
* Module#const_get accepts a qualified constant string, e.g.
Object.const_get("Foo::Bar::Baz")
* Mutex
* added method:
* added Mutex#owned? which returns the mutex is held by current
thread or not. [experimental]
* incompatible changes:
* Mutex#lock, Mutex#unlock, Mutex#try_lock, Mutex#synchronize
and Mutex#sleep are no longer allowed to be used from trap handler
and raise a ThreadError in such case.
* Mutex#sleep may spurious wakeup. Check after wakeup.
* NilClass
* added method:
* added nil.to_h which returns {}
* ObjectSpace::WeakMap
* new low level class to hold weak references to objects.
* Proc
* incompatible change:
* removed Proc#== and #eql? so two procs are == only when they are
the same object.
* Process
* added method:
* added getsid for getting session id (unix only).
* Range
* added method:
* added Range#size for lazy size evaluation.
* added Range#bsearch for binary search.
* RubyVM (MRI specific)
* added RubyVM::InstructionSequence.of to get the instruction sequence
from a method or a block.
* added RubyVM::InstructionSequence#path, #absolute_path, #label,
#base_label and #first_lineno to retrieve information from where
the instruction sequence was defined.
* added Environment variables to specify stack usage:
* RUBY_THREAD_VM_STACK_SIZE: vm stack size used at thread creation.
default: 128KB (32bit CPU) or 256KB (64bit CPU).
* RUBY_THREAD_MACHINE_STACK_SIZE: machine stack size used at thread
creation. default: 512KB or 1024KB.
* RUBY_FIBER_VM_STACK_SIZE: vm stack size used at fiber creation.
default: 64KB or 128KB.
* RUBY_FIBER_MACHINE_STACK_SIZE: machine stack size used at fiber
creation. default: 256KB or 256KB.
These variables are checked only at launched time.
* added constant DEFAULT_PARAMS to get above default parameters.
* Signal
* added method:
* added Signal.signame which returns signal name
* incompatible changes:
* Signal.trap raises ArgumentError when :SEGV, :BUS, :ILL, :FPE, :VTALRM
are specified.
* String
* added method:
* added String#b returning a copied string whose encoding is ASCII-8BIT.
* change return value:
* String#lines now returns an array instead of an enumerator.
* String#chars now returns an array instead of an enumerator.
* String#codepoints now returns an array instead of an enumerator.
* String#bytes now returns an array instead of an enumerator.
* Struct
* added method:
* added Struct#to_h returning values with keys corresponding to the
instance variable names.
* Thread
* added method:
* added Thread#thread_variable_get for getting thread local variables
(these are different than Fiber local variables).
* added Thread#thread_variable_set for setting thread local variables.
* added Thread#thread_variables for getting a list of the thread local
variable keys.
* added Thread#thread_variable? for testing to see if a particular thread
variable has been set.
* added Thread.handle_interrupt as well as instance and singleton methods
pending_interrupt? for asynchronous handling of exceptions
* added Thread#backtrace_locations which returns similar information of
Kernel#caller_locations.
* new class Thread::Backtrace::Location to hold backtrace location
information. These are returned by Thread#backtrace_locations and
Kernel#caller_locations.
* incompatible changes:
* Thread#join and Thread#value now raises a ThreadError if target thread
is the current or main thread.
* Time
* change return value:
* Time#to_s now returns US-ASCII encoding instead of BINARY.
* TracePoint
* new class. This class is replacement of set_trace_func.
Easy to use and efficient implementation.
* toplevel
* added method:
* added main.define_method which defines a global function.
* added main.using, which imports refinements into the current file or
eval string. [experimental]
=== Core classes compatibility issues (excluding feature bug fixes)
* Array#values_at
See above.
* String#lines
* String#chars
* String#codepoints
* String#bytes
These methods no longer return an Enumerator, although passing a
block is still supported for backwards compatibility.
Code like str.lines.with_index(1) { |line, lineno| ... } no longer
works because str.lines returns an array. Replace lines with
each_line in such cases.
* IO#lines
* IO#chars
* IO#codepoints
* IO#bytes
* ARGF#lines
* ARGF#chars
* ARGF#bytes
* StringIO#lines
* StringIO#chars
* StringIO#codepoints
* StringIO#bytes
* Zlib::GzipReader#lines
* Zlib::GzipReader#bytes
These methods are deprecated in favor of each_line, each_byte,
each_char and each_codepoint.
* Proc#==
* Proc#eql?
These methods were removed. Two procs are == only when they are
the same object.
* Fixnum
* Bignum
* Float
Fixnums, Bignums and Floats are frozen.
* Signal.trap
See above.
* Merge Onigmo.
https://github.com/k-takata/Onigmo
* The :close_others option is true by default for system() and exec().
Also, the close-on-exec flag is set by default for all new file descriptors.
This means file descriptors doesn't inherit to spawned process unless
explicitly requested such as system(..., fd=>fd).
* Kernel#respond_to? against a protected method now returns false
unless the second argument is true.
* Kernel#respond_to_missing?
* Kernel#initialize_clone
* Kernel#initialize_dup
These methods are now private.
* Thread#join, Thread#value
See above.
* Mutex#lock, Mutex#unlock, Mutex#try_lock, Mutex#synchronize and Mutex#sleep
See above.
=== Stdlib updates (outstanding ones only)
* cgi
* Add HTML5 tag maker.
* CGI#header has been renamed to CGI#http_header and
aliased to CGI#header.
* When HTML5 tagmaker called, overwrite CGI#header,
CGI#header function is to create a <header> element.
* CSV
* Removed CSV::dump and CSV::load to protect users from dangerous
serialization vulnerability
* iconv
* Iconv has been removed. Use String#encode instead.
* io/console
* new methods:
* added IO#cooked which sets the terminal to cooked mode within the given block.
* added IO#cooked! which sets the terminal to cooked.
* extended method:
* IO#raw, IO#raw!, and IO#getch accept keyword arguments, :min and :time.
* io/wait
* new features:
* added IO#wait_writable method.
* added IO#wait_readable method as alias of IO#wait.
* json
* updated to 1.7.7.
* net/http
* new features:
* Proxies are now automatically detected from the http_proxy environment
variable. See Net::HTTP::new for details.
* gzip and deflate compression are now requested for all requests by
default. See Net::HTTP for details.
* SSL sessions are now reused across connections for a single instance.
This speeds up connection by using a previously negotiated session.
* Requests may be created from a URI which sets the request_uri and host
header of the request (but does not change the host connected to).
* Responses contain the URI requested which allows easier implementation of
redirect following.
* new methods:
* Net::HTTP#local_host
* Net::HTTP#local_host=
* Net::HTTP#local_port
* Net::HTTP#local_port=
* extended method:
* Net::HTTP#connect uses local_host and local_port if specified.
* net/imap
* new methods:
* Net::IMAP.default_port
* Net::IMAP.default_imap_port
* Net::IMAP.default_tls_port
* Net::IMAP.default_ssl_port
* Net::IMAP.default_imaps_port
* objspace
* new method:
* ObjectSpace.reachable_objects_from(obj)
* openssl
* Consistently raise an error when trying to encode nil values. All instances
of OpenSSL::ASN1::Primitive now raise TypeError when calling to_der on an
instance whose value is nil. All instances of OpenSSL::ASN1::Constructive
raise NoMethodError in the same case. Constructing such values is still
permitted.
* TLS 1.1 & 1.2 support by setting OpenSSL::SSL::SSLContext#ssl_version to
:TLSv1_2, :TLSv1_2_server, :TLSv1_2_client or :TLSv1_1, :TLSv1_1_server
:TLSv1_1_client. The version being effectively used can be queried
with OpenSSL::SSL#ssl_version. Furthermore, it is also possible to
blacklist the new TLS versions with OpenSSL::SSL:OP_NO_TLSv1_1 and
OpenSSL::SSL::OP_NO_TLSv1_2.
* Added OpenSSL::SSL::SSLContext#renegotiation_cb. A user-defined callback
may be set which gets called whenever a new handshake is negotiated. This
also allows to programmatically decline (client) renegotiation attempts.
* Support for "0/n" splitting of records as BEAST mitigation via
OpenSSL::SSL::OP_DONT_INSERT_EMPTY_FRAGMENTS.
* The default options for OpenSSL::SSL::SSLContext have changed to
OpenSSL::SSL::OP_ALL & ~OpenSSL::SSL::OP_DONT_INSERT_EMPTY_FRAGMENTS
instead of OpenSSL::SSL::OP_ALL only. This enables the countermeasure for
the BEAST attack by default.
* OpenSSL requires passwords for decrypting PEM-encoded files to be at least
four characters long. This led to awkward situations where an export with
a password with fewer than four characters was possible, but accessing the
file afterwards failed. OpenSSL::PKey::RSA, OpenSSL::PKey::DSA and
OpenSSL::PKey::EC therefore now enforce the same check when exporting a
private key to PEM with a password - it has to be at least four characters
long.
* SSL/TLS support for the Next Protocol Negotiation extension. Supported
with OpenSSL 1.0.1 and higher.
* OpenSSL::OPENSSL_FIPS allows client applications to detect whether OpenSSL
is FIPS-enabled. OpenSSL.fips_mode= allows turning on and off FIPS mode
manually in order to adapt to situations where FIPS mode would be an
explicit requirement.
* Authenticated Encryption with Associated Data (AEAD) is supported via
Cipher#auth_data= and Cipher#auth_tag/Cipher#auth_tag=.
Currently (OpenSSL 1.0.1c), only GCM mode is supported.
* ostruct
* new methods:
* OpenStruct#[], []=
* OpenStruct#each_pair
* OpenStruct#eql?
* OpenStruct#hash
* OpenStruct#to_h converts the struct to a hash.
* extended method:
* OpenStruct.new also accepts an OpenStruct / Struct.
* pathname
* extended method:
* Pathname#find returns an enumerator if no block is given.
* rake
* rake has been updated to version 0.9.5.
This version is backwards-compatible with previous rake versions and
contains many bug fixes.
See
http://rake.rubyforge.org/doc/release_notes/rake-0_9_5_rdoc.html for a list
of changes in rake 0.9.3, 0.9.4 and 0.9.5.
* RDoc
* RDoc has been updated to version 4.0
This version is largely backwards-compatible with previous rdoc versions.
The most notable change is an update to the ri data format (ri data must
be regenerated for gems shared across rdoc versions). Further API changes
are internal and won't affect most users.
Notable changes include:
* Page support for ri. Try `ri ruby:` for a list of pages in ruby or
`ri ruby:syntax/literals` for the syntax documentation for literals.
This also works for gems such as `ri rspec:README` for the rspec gem's
README file.
* Markdown support. See ri RDoc::Markdown for details.
See https://github.com/rdoc/rdoc/blob/master/History.rdoc for a full list
of changes in rdoc 4.0.
* resolv
* new methods:
* Resolv::DNS#timeouts=
* Resolv::DNS::Config#timeouts=
* rexml
* REXML::Document#write supports Hash arguments.
* REXML::Document#write supports new :encoding option. It changes
XML document encoding. Without :encoding option, encoding in
XML declaration is used for XML document encoding.
* RubyGems
* Updated to 2.0.0
RubyGems 2.0.0 features the following improvements:
* Improved support for default gems shipping with ruby 2.0.0+
* A gem can have arbitrary metadata through Gem::Specification#metadata
* `gem search` now defaults to --remote and is anchored like gem list.
* Added --document to replace --rdoc and --ri. Use --no-document to
disable documentation, --document=rdoc to only generate rdoc.
* Only ri-format documentation is generated by default.
* `gem server` uses RDoc::Servlet from RDoc 4.0 to generate HTML
documentation.
For an expanded list of updates and bug fixes see:
https://github.com/rubygems/rubygems/blob/master/History.txt
* shellwords
* Shellwords#shellescape now stringifies the given object using to_s.
* Shellwords#shelljoin accepts non-string objects in the given
array, each of which is stringified using to_s.
* stringio
* deprecated methods:
* StringIO#lines, #bytes, #chars and #codepoints are deprecated.
* syslog
* Added Syslog::Logger which provides a Logger API atop Syslog.
* Syslog::Priority, Syslog::Level, Syslog::Option and Syslog::Macros
are introduced for easy detection of available constants on a
running system.
* tmpdir
* incompatible changes:
* Dir.mktmpdir uses FileUtils.remove_entry instead of
FileUtils.remove_entry_secure. This means that applications should not
change the permission of the created temporary directory to make
accessible from other users.
* yaml
* Syck has been removed. YAML now completely depends on libyaml being
installed.
* libyaml is now bundled with ruby, for cases where the library is not
installed locally.
* zlib
* Added streaming support for Zlib::Inflate and Zlib::Deflate. This allows
processing of a stream without the use of large amounts of memory.
* Added support for the new deflate strategies Zlib::RLE and Zlib::FIXED.
* Zlib streams are now processed without the GVL. This allows gzip, zlib and
deflate streams to be processed in parallel.
* deprecated methods:
* Zlib::GzipReader#lines and #bytes are deprecated.
=== Stdlib compatibility issues (excluding feature bug fixes)
* OpenStruct new methods can conflict with custom attributes named
"each_pair", "eql?", "hash" or "to_h".
* Dir.mktmpdir in lib/tmpdir.rb
See above.
=== C API updates
* NUM2SHORT() and NUM2USHORT() added. They are similar to NUM2INT, but short.
* rb_newobj_of() and NEWOBJ_OF() added. They create a new object of a given class.

459
doc/contributing.rdoc Normal file
View file

@ -0,0 +1,459 @@
= Contributing to Ruby
Ruby has a vast and friendly community with hundreds of people contributing to
a thriving open-source ecosystem. This guide is designed to cover ways for
participating in the development of CRuby.
There are plenty of ways for you to help even if you're not ready to write
code or documentation. You can help by reporting issues, testing patches, and
trying out beta releases with your applications.
== How To Report
If you've encountered a bug in Ruby please report it to the redmine issue
tracker available at {bugs.ruby-lang.org}[http://bugs.ruby-lang.org/]. Do not
report security vulnerabilities here, there is a {separate
channel}[rdoc-label:label-Reporting+Security+Issues] for them.
There are a few simple steps you should follow in order to receive feedback
on your ticket.
* If you haven't already,
{sign up for an account}[https://bugs.ruby-lang.org/account/register] on the
bug tracker.
* Try the latest version.
If you aren't already using the latest version, try installing a newer
stable release. See
{Downloading Ruby}[http://www.ruby-lang.org/en/downloads/].
* Look to see if anyone already reported your issue, try
{searching on redmine}[https://bugs.ruby-lang.org/projects/ruby-trunk/issues]
for your problem.
* If you can't find a ticket addressing your issue,
{create a new one}[https://bugs.ruby-lang.org/projects/ruby-trunk/issues/new].
* Choose the target version, usually current. Bugs will be first fixed in the
current release and then {backported}[rdoc-label:label-Backport+Requests].
* Fill in the Ruby version you're using when experiencing this issue
(<code>ruby -v</code>).
* Attach any logs or reproducible programs to provide additional information.
Reproducible scripts should be as small as possible.
* Briefly describe your problem. A 2-3 sentence description will help give a
quick response.
* Pick a category, such as core for common problems, or lib for a standard
library.
* Check the {Maintainers
list}[https://bugs.ruby-lang.org/projects/ruby/wiki/Maintainers] and assign
the ticket if there is an active maintainer for the library or feature.
* If the ticket doesn't have any replies after 10 days, you can send a
reminder.
* Please reply to feedback requests. If a bug report doesn't get any feedback,
it'll eventually get rejected.
=== Reporting to downstream distributions
You can reports downstream issues for the following distributions via their bugtracker:
* {debian}[http://bugs.debian.org/cgi-bin/pkgreport.cgi?src=ruby-defaults]
* {freebsd}[http://www.freebsd.org/cgi/query-pr-summary.cgi?text=ruby]
* {redhat}[https://bugzilla.redhat.com/buglist.cgi?bug_status=NEW&bug_status=ASSIGNED&bug_status=REOPENED&bug_status=MODIFIED]
* {macports}[http://trac.macports.org/query?status=assigned&status=new&status=reopened&port=~ruby]
* etc (add your distribution bug tracker here)
=== Platform Maintainers
For platform specific bugs in Ruby, you can assign your ticket the current
maintainer for a specific platform.
The current active platform maintainers are as follows:
[mswin32, mswin64 (Microsoft Windows)]
NAKAMURA Usaku (usa)
[mingw32 (Minimalist GNU for Windows)]
Nobuyoshi Nakada (nobu)
[IA-64 (Debian GNU/Linux)]
TAKANO Mitsuhiro (takano32)
[Symbian OS]
Alexander Zavorine (azov)
[AIX]
Yutaka Kanemoto (kanemoto)
[FreeBSD]
Akinori MUSHA (knu)
[Solaris]
Naohisa Goto (ngoto)
[RHEL, CentOS]
KOSAKI Motohiro kosaki
[Mac OS X]
Kenta Murata (mrkn)
[cygwin, bcc32, djgpp, wince, ...]
none. (Maintainer WANTED)
== Reporting Security Issues
Security vulnerabilities receive special treatment since they may negatively
affect many users. There is a private mailing list that all security issues
should be reported to and will be handled discretely. Email the
mailto:security@ruby-lang.org list and the problem will be published after
fixes have been released. You can also encrypt the issue using {the PGP public
key}[http://www.ruby-lang.org/security.asc] for the list.
== Reporting Other Issues
If you're having an issue with the website, or maybe the mailing list, you can
contact the webmaster to help resolve the problem.
The current webmaster is:
* Hiroshi SHIBATA (hsbt)
You can also report issues with the ruby-lang.org website on the issue tracker:
* {issue tracker}[https://github.com/ruby/www.ruby-lang.org/issues]
== Resolve Existing Issues
As a next step beyond reporting issues you can help the core team resolve
existing issues. If you check the Everyone's Issues list in GitHub Issues,
you'll find lots of issues already requiring attention. What can you do for
these? Quite a bit, actually:
When a bug report goes for a while without any feedback, it goes to the bug
graveyard which is unfortunate. If you check the {issues
list}[https://bugs.ruby-lang.org/projects/ruby-trunk/issues] you'll find lots
of delinquent bugs that require attention.
You can help by verifying the existing tickets, try to reproduce the reported
issue on your own and comment if you still experience the bug. Some issues
lack attention because of too much ambiguity, to help you can narrow down the
problem and provide more specific details or instructions to reproduce the
bug. You might also try contributing a failing test in the form of a patch,
which we will cover later in this guide.
It may also help to try out patches other contributors have submitted to
redmine, if gone without notice. In this case the +patch+ command is your
friend, see <code>man patch</code> for more information. Basically this would
go something like this:
cd path/to/ruby/trunk
patch -p0 < path/to/patch
You will then be prompted to apply the patch with the associated files. After
building ruby again, you should try to run the tests and verify if the change
actually worked or fixed the bug. It's important to provide valuable feedback
on the patch that can help reach the overall goal, try to answer some of these
questions:
* What do you like about this change?
* What would you do differently?
* Are there any other edge cases not tested?
* Is there any documentation that would be affected by this change?
If you can answer some or all of these questions, you're on the right track.
If your comment simply says "+1", then odds are that other reviewers aren't
going to take it too seriously. Show that you took the time to review the
patch.
== How To Request Features
If there's a new feature that you want to see added to Ruby, you'll need to
write a convincing proposal and patch to implement the feature.
For new features in CRuby, use the {'Feature'
tracker}[https://bugs.ruby-lang.org/projects/ruby-trunk/issues?set_filter=1&tracker_id=2]
on ruby-trunk. For non-CRuby dependent features, features that would apply to
alternate Ruby implementations such as JRuby and Rubinius, use the {CommonRuby
tracker}[https://bugs.ruby-lang.org/projects/common-ruby].
When writing a proposal be sure to check for previous discussions on the
topic and have a solid use case. You will need to be persuasive and convince
Matz on your new feature. You should also consider the potential compatibility
issues that this new feature might raise.
Consider making your feature into a gem, and if there are enough people who
benefit from your feature it could help persuade ruby-core. Although feature
requests can seem like an alluring way to contribute to Ruby, often these
discussions can lead nowhere and exhaust time and energy that could be better
spent fixing bugs. Choose your battles.
A good template for feature proposal should look something like this:
[Abstract]
Summary of your feature
[Background]
Describe current behavior and why it is problem. Related work, such as
solutions in other language helps us to understand the problem.
[Proposal]
Describe your proposal in details
[Details]
If it has complicated feature, describe it
[Usecase]
How would your feature be used? Who will benefit from it?
[Discussion]
Discuss about this proposal. A list of pros and cons will help start
discussion.
[Limitation]
Limitation of your proposal
[Another alternative proposal]
If there are alternative proposals, show them.
[See also]
Links to the other related resources
=== Slideshow
On Ruby Developer Meeting Japan, committers discuss about Feature Proposals together at Tokyo. We'll judge proposals accept, reject, or feedback. If you have a stalled proposal, making a slide to submit is good way to get feedback.
Slides should be:
* One-page slide
* Include a corresponding ticket number
* MUST include a figure and/or short example code
* SHOULD have less sentence in natural language (try to write less than 140 characters)
* It is RECOMMENDED to itemize: motivation/use case, proposal, pros/cons, corner case
* PDF or Image (Web browsers can show it)
Please note:
* Even if the proposal is generally acceptable, it won't be accepted without writing corner cases in the ticket
* Slide's example: DevelopersMeeting20130727Japan
== Backport Requests
When a new version of Ruby is released it starts at patch level 0 (p0), and
bugs will be fixed first on the trunk branch. If its determined that a bug
exists in a previous version of Ruby that is still in the bug fix stage of
maintenance, then a patch will be backported. After the maintenance stage of a
particular Ruby version ends, it goes into "security fix only" mode which
means only security related vulnerabilities will be backported. Versions in
End-of-life (EOL) will not receive any updates and it is recommended you
upgrade as soon as possible.
If a major security issue is found or after a certain amount of time since the
last patch level release, a new patch-level release will be made.
When submitting a backport request please confirm the bug has been fixed in
newer versions and exists in maintenance mode versions. There is a backport
tracker for each major version still in maintenance where you can request a
particular revision merged in the affected version of Ruby.
Each major version of Ruby has a release manager that should be assigned to
handle backport requests. You can find the list of release managers on the
{wiki}[https://bugs.ruby-lang.org/projects/ruby/wiki/ReleaseEngineering].
=== Branch Maintainers
A branch maintainer maintains a branch and releases a new release of Ruby. The
branch depends on the associated version of Ruby, such as ruby_1_8_7 for
version 1.8.7. The current branch maintainers are as follows:
[trunk]
unnecessary
[ruby_2_0_0]
Chikanaga Tomoyuki (nagachika)
[ruby_1_9_3]
NAKAMURA Usaku (usa)
[ruby_1_9_2, ruby_1_9_1]
_unmaintained_
[ruby_1_8]
_unmaintained_
[ruby_1_8_7]
_unmaintained_
[ruby_1_8_6 ...]
_unmaintained_
== Running tests
In order to help resolve existing issues and contributing patches to Ruby you
need to be able to run the test suite.
CRuby uses subversion for source control, you can find installation
instructions and lots of great info to learn subversion on the
{svnbook.red-bean.com}[http://svnbook.red-bean.com/]. For other resources see
the {ruby-core documentation on
ruby-lang.org}[http://www.ruby-lang.org/en/community/ruby-core/].
This guide will use git for contributing. The {git
homepage}[http://git-scm.com/] has installation instructions with links to
documentation for learning more about git. There is a mirror of the subversion
repository on {github}[https://github.com/ruby/ruby].
Install the prerequisite dependencies for building the CRuby interpreter to
run tests.
* C compiler
* autoconf
* bison
* gperf
* ruby - Ruby itself is prerequisite in order to build Ruby from source. It
can be 1.8.
You should also have access to development headers for the following
libraries, but these are not required:
* Tcl/Tk
* NDBM/QDBM
* GDBM
* OpenSSL
* readline/editline(libedit)
* zlib
* libffi
* libyaml
* libexecinfo (FreeBSD)
Now let's build CRuby:
* Checkout the CRuby source code:
git clone git://github.com/ruby/ruby.git ruby-trunk
* Generate the configuration files and build:
cd ruby-trunk
autoconf
mkdir build && cd build # its good practice to build outside of source dir
mkdir ~/.rubies # we will install to .rubies/ruby-trunk in our home dir
../configure --prefix=~/.rubies/ruby-trunk
make && make install
After adding Ruby to your PATH, you should be ready to run the test suite:
make test
You can also use +test-all+ to run all of the tests with the RUNRUBY
interpreter just built. Use TESTS or RUNRUBYOPT to pass parameters, such as:
make test-all TESTS=-v
This is also how you can run a specific test from our build dir:
make test-all TESTS=drb/test_drb.rb
For older versions of Ruby you'll need to run the build setup again after
checking out the associated branch in git, for example if you wanted to
checkout 1.9.3:
git clone git://github.com/ruby/ruby.git --branch ruby_1_9_3
== Contributing Documentation
If you're interested in contributing documentation directly to CRuby there is
a wealth of information available at
{documenting-ruby.org}[http://documenting-ruby.org/].
There is also the {Ruby Reference
Manual}[https://bugs.ruby-lang.org/projects/rurema] in Japanese.
== Contributing A Patch
=== Deciding what to patch
Before you submit a patch, there are a few things you should know:
* Pay attention to the maintenance policy for stable and maintained versions of Ruby.
* Released versions in security mode will not merge feature changes.
* Search for previous discussions on ruby-core to verify the maintenance policy
* Patches must be distributed under Ruby's license.
* This license may change in the future, you must join the discussion if you don't agree to the change
To improve the chance your patch will be accepted please follow these simple rules:
* Bug fixes should be committed on trunk first
* Format of the patch file must be a unified diff (ie: diff -pu, svn diff, or git diff)
* Don't introduce cosmetic changes
* Follow the original coding style of the code
* Don't mix different changes in one commit
First thing you should do is check out the code if you haven't already:
git clone git://github.com/ruby/ruby.git ruby-trunk
Now create a dedicated branch:
cd ruby-trunk
git checkout -b my_new_branch
The name of your branch doesn't really matter because it will only exist on
your local computer and won't be part of the official Ruby repository. It will
be used to create patches based on the differences between your branch and
trunk, or edge Ruby.
=== Coding style
Here are some general rules to follow when writing Ruby and C code for CRuby:
* Indent 4 spaces for C with tabs for eight-space indentation (emacs default)
* Indent 2 space tabs for Ruby
* Do not use TABs in ruby codes
* ANSI C style for 1.9+ for function declarations
* Follow C90 (not C99) Standard
* PascalStyle for class/module names.
* UNDERSCORE_SEPARATED_UPPER_CASE for other constants.
* Capitalize words.
* ABBRs should be all upper case.
* Do as others do
=== ChangeLog
Although not required, if you wish to add a ChangeLog entry for your change
please note:
You can use the following template for the ChangeLog entry on your commit:
Thu Jan 1 00:00:00 2004 Your Name <yourmail@example.com>
* filename (function): short description of this commit.
This should include your intention of this change.
[bug:#number] [mailinglist:number]
* filename2 (function2): additional description for this file/function.
This follows {GNU Coding Standards for Change
Logs}[http://www.gnu.org/prep/standards/html_node/Change-Logs.html#Change-Logs],
some other requirements and tips:
* Timestamps must be in JST (+09:00) in the style as above.
* Two spaces between the timestamp and your name. Two spaces between
your name and your mail address.
* One blank line between the timestamp and the description.
* Indent the description with TAB. 2nd line should begin with TAB+2SP.
* Write a entry (*) for each change.
* Refer to redmine issue or discussion on the mailing list.
* For GitHub issues, use [GH-#] (such as [Fixes GH-234]
* One blank line between entries.
* Do as other committers do.
You can generate the ChangeLog entry by running <code>make change</code>
When you're ready to commit, copy your ChangeLog entry into the commit message,
keeping the same formatting and select your files:
git commit ChangeLog path/to/files
In the likely event that your branch becomes outdated, you will have to update
your working branch:
git fetch origin
git rebase remotes/origin/master
Now that you've got some code you want to contribute, let's get set up to
generate a patch. Start by forking the github mirror, check the {github docs on
forking}[https://help.github.com/articles/fork-a-repo] if you get stuck here.
here. You will also need a github account if you don't yet have one.
Next copy the writable url for your fork and add it as a git remote, replace
"my_username" with your github account name:
git remote add my_fork git@github.com:my_username/ruby.git
# Now we can push our branch to our fork
git push my_fork my_new_branch
In order to generate a patch that you can upload to the bug tracker, we can use
the github interface to review our changes just visit
https://github.com/my_username/ruby/compare/trunk...my_new_branch
Next, you can simply add '.patch' to the end of this URL and it will generate
the patch for you, save the file to your computer and upload it to the bug
tracker. Alternatively you can submit a pull request, but for the best chances
to receive feedback add it is recommended you add it to redmine.

778
doc/contributors.rdoc Normal file
View file

@ -0,0 +1,778 @@
= Contributors to Ruby
The following list might be imcomplete. Feel free to add your name if your
patch was accepted into Ruby.
== A
Ayumu AIZAWA (ayumin)
* committer
AKIYOSHI, Masamichi (akiyoshi)
* committer
* He had maintained the VMS support on 2003-2004.
Muhammad Ali
* wrote rdoc for Fiber
Minero Aoki (aamine)
* committer
* He is the maintainer of:
* fileutils
* net/http, net/https
* net/pop
* net/smtp
* racc
* ripper
* strscan
Wakou Aoyama (wakou)
* committer
* He was the maintainer of some standard libraries.
Koji Arai
* committer
arton
* He is the distributor of ActiveScriptRuby and experimental 1.9.0-x installers for win32.
* Wrote patches for win32ole, gc.c, tmpdir.rb
== B
Daniel Berger
* a patch for irb
* documentation
* He wrote forwardable.rb
David Black (dblack)
* committer
* He is the maintainer of scanf
Ken Bloom
* a patch for REXML.
Oliver M. Bolzer
* a patch for soap
Alexey Borzenkov
* a patch for mkmf.rb
Richard Brown
* a patch for configure.in
Dirkjan Bussink
* a patch for date.rb
Daniel Bovensiepen
* documentation
* a patch for irb
== C
Brian Candler
* a patch for configure.in, net/telnet
keith cascio
* a patch for optparse.rb
Frederick Cheung
* a patch for test/ruby/test_symbol.rb
Christoph
* patches for set.rb
Sean Chittenden
* pathces for net/http, cgi
William D. Clinger
* ruby_strtod is based on his paper.
== D
Ryan Davis (ryan)
* committer
* He wrote and is the maintainer of miniunit
Guy Decoux (ts)
* committer
Zach Dennis
Martin Duerst (duerst)
* committer
* M17N
Paul Duncan
* pathces for rdoc
Alexander Dymo
* a patch for lib/benchmark.rb
== E
Yusuke Endoh (mame)
* committer
* He wrote and is the maintainer of base64 library (1.9)
* did much upon YARV compiler.
erlercw
* wrote Integer::gcd2
== F
Frank S.Fejes
* a patch for net/pop
Fundakowski Feldman
* a patch for process.c
Mauricio Fernandez
* patches for parse.y
David Flanagan (davidflanagan)
* committer
* M17N
Takeyuki Fujioka (xibbar)
* committer
* He is the maintainer of cgi/*
FUKUMOTO, Atsushi
* a patch for tracer.rb
Shota Fukumori (sorah)
* committer
* #4415 parallel unit/test
Tadayoshi Funaba (tadf)
* committer
* He wrote and is the maintainer of
* date
* parsedate (1.8)
* He ported rational.rb and complex.rb, which 1.8 contains, into rational.c and complex.c of 1.9.
== G
David M. Gay
* ruby_strtod
Florian Gilcher
* documentation
GOTOU, Kentaro (gotoken)
* committer
* He wrote benchmark.rb
* He is the maintainer of:
* benchmark.rb
* open3
GOTOU, Yuuzou (gotoyuzo)
* committer
James Edward Gray II (jeg2)
* committer
* He wrote the faster implementation of CSV and is the maintainer of csv.
* Wrote documentation for rdoc
== H
Phil Hagelberg
* patch for ruby-mode.el's documentation.
Kirk Haines (wyhaines)
* committer
* the maintainer of ruby_1_8_6 branch
Shinichiro Hamaji
* fixed memory leaks (marshal.c, string.c)
Shin-ichiro HARA
* the developer and the sysop of ruby-{dev,list,core,talk} archive.
* a patch for numeric.c
Chris Heath (traumdeutung)
* a patch for proc.c
HIROKAWA Hisashi
* fixed socket/socket.c
Daniel Hob
* He wrote:
* SMTP-TLS support for net/smtp.
* POP3S support
Eric Hodel (drbrain)
* committer
* He is the maintainer of:
* rdoc
* ri
* rubygems
Erik Hollensbe
* a patch for delegate.rb
Johan Holmberg
* a patch for dir.c
* documentation
Erik Huelsmann
Dae San Hwang
* built a continuous integration environment on OpenSolaris.
== I
Nobuhiro IMAI
* a patch for logger.rb
"incorporate"
* a patch for sprintf.c
Keiju Ishitsuka (keiju)
* committer
* He wrote and is the maintainer of:
* cmath.rb (1.9)
* complex.rb (1.8)
* e2mmap.rb
* forwardable.rb
* irb
* mathn
* matrix.rb
* mutex_m.rb
* rational.rb (1.8)
* sync.rb
* shell/*
* thwait.rb
* tracer.rb
== J
Curtis Jackson
* missing/dup2.c
Alan Johnson
* a patch for net/ftp
Lyle Johnson
* patches for nkf, bigdecimal, numeric.c
== K
Yoshihiro Kambayashi
* a patch for enc/trans/single_byte.trans.
* He wrote supports for some encodings.
Yutaka Kanemoto
* patches for common.mk, AIX AF_INET6 support
Motoyuki Kasahara
* He wrote getoptlong.rb
Masahiro Kawato
* a patch for shellwords.rb
Wataru Kimura
* a patch for configure.in
Michael Klishin
* patch for make help.
Noritada Kobayashi
* a patch for optparse.rb
Shigeo Kobayashi (shigek)
* committer
* He is the maintainer of bigdecimal
KONISHI, Hiromasa (H_Konishi)
* committer
* He had maintained the bcc32 support in 2004.
Kornelius "murphy" Kalnbach
* documentation
K.Kosako (kosako)
* committer
* He wrote Oniguruma.
Takehiro Kubo
* patches for dl 64bit support.
== L
Marc-Andre Lafortune (marcandre)
* committer
* patches for hash.c, array.c, thread.c, enumc, string.c, range.c and rdoc documentation.
Hongli Lai
* improved pstore.rb
* patch for tool/file2lastrev.rb.
raspberry lemon
* a patch for webrick/httpproxy.rb.
Christian Loew
* a patch for fileutils.rb
== M
Shugo Maeda (shugo)
* committer
* A system administrator of ruby-lang.org servers.
* He wrote and is the maintainer of:
* monitor.rb
* net/ftp
* net/imap
Stephan Maka (mathew)
* documentation
Yukihiro Matsumoto (matz)
* Matz -- the founder, language designer of Ruby.
* committer
* Ruby itself, most of Ruby.
* He is the maintainer of:
* singleton
* timeout
* gdbm
* sdbm
Konrad Meyer
* documentation
Mib Software
* missing/vsnprintf.c
Todd C. Miller
* missing/strlcat.c
* missing/strlcpy.c
MIYASAKA, Masaru
* a patch for cgi.rb
Stefan Monnier
* regex.c was fixed with based on his Emacs21 patch.
Marcel Moolenaar
* patches for eval.c and gc.c.
moonwolf
* a patch for REXML, xmlrpc
Hiroshi Moriyama
* a patch for yaml.
Kyosuke Morohashi
* a patch for gem_prelude.rb
Kenta Murata
* patches for json, bignum.c
Akinori MUSHA (knu)
* committer
* He wrote and is the maintainer of:
* abbrev.rb
* generator (1.8)
* enumerator (1.8)
* set
* ipaddr.rb
* digest/*
* syslog
* He is the branch maintainer of ruby_1_8, the release manager of 1.8 series.
== N
Hidetoshi NAGAI (nagai)
* committer
* He is the maintainer of tk/*
Nobuyoshi Nakada (nobu)
* committer
* a.k.a. the "patch monster"
* He wrote and is the maintainer of:
* optparse
* stringio
* io/wait
* iconv
Satoshi Nakagawa
* patches for util.c
Narihiro Nakamura (nari)
* committer
* a.k.a. authorNari
* working at GC
NAKAMURA, Hiroshi (nahi)
* committer
* He is the maintainer of:
* csv.rb (1.8)
* logger.rb
* soap/* (1.8)
* wsdl/* (1.8)
* xsd/* (1.8)
NAKAMURA, Usaku (usa)
* committer
* a.k.a. unak
* He is the maintainer of mswin32 and mswin64 support.
NARUSE, Yui (naruse)
* committer
* a.k.a. "nurse"
* Did much upon m17n.
* He is the maintainer of:
* json
* nkf
Christian Neukirchen
* a patch for webrick/httputils
Michael Neumann (mneumann)
* committer
* He is the maintainer of
* xmlrpc (1.8)
* gserver (1.8)
NISHIO Hirokazu
* wrote a patch for CVE-2010-0541
Kazuhiro NISHIYAMA (kazu)
* committer
* a.k.a. znz
Go Noguchi
Martin Nordholts
* misc/rdebug.el
nmu
* a patch for socket
== O
okkez
* He is a sysop of the Ruby Reference Manual Renewal Project.
* fixed ipaddr.rb, ext/etc
Haruhiko Okumura
* some of missing/* is based on his book:
* missing/erf.c
* missing/lgamma_r.c
* missing/tgamma.c
OMAE, jun
* a patch for debug.rb
Eugene Ossintsev
* documentation
== P
Heesob Park
* a patch for win32/win32.c.
pegacorn
* a patch for instruby.rb
== Q
== R
Gaston Ramos
* documentation
The Regents of the University of California
* missing/crypt.c
* missing/vsnprintf.c
Sam Roberts
* patch for socket
* documentation
Michal Rokos (michal)
* committer
* He was the maintainer of DJGPP support.
rubikitch
* a patch for io.c
Marcus Rueckert
* a patch for mkconfig.rb.
Run Paint Run Run
* patch for enc/unicode.c
* documentation
Sean Russell (ser)
* committer
* He wrote and is the maintainer of REXML.
== S
Kazuo Saito (ksaito)
* committer
* M17N
Tadashi Saito
* patches for test/ruby/test_math.rb, thread_*.c, bignum.c
* working upon BigDecimal.
* did much upon documentation
Masahiro Sakai
* a patch for io.c
Laurent Sansonetti
* a patch for tool/ytab.sed
Jeff Saracco
* documentation
Koichi Sasada (ko1)
* committer
* He wrote YARV.
Hugh Sasse
* a patch for net/http
* documentation
Charlie Savage
* a patch for win32/Makefile.sub
Michael Scholz
* a patch for ruby-mode.el
Arthur Schreiber
* patch for net/http and rdoc.
Masatoshi SEKI (seki)
* committer
* He wrote and is the maintainer of:
* drb/*
* erb
* rinda
Roman Shterenzon
* a patch for open-uri.
Kent Sibilev
Gavin Sinclair (gsinclair)
* committer
John W. Small
* He wrote gserver.rb
Yuki Sonoda (yugui)
* committer
* She is the maintainer of man/* manual pages and is the release manager of 1.9 series.
* She wrote prime.rb.
* A developer and a sysop of redmine.ruby-lang.org.
SOUMA, Yutaka
* a patch for pack.c.
Tatsuki Sugiura
* WebDAV support for net/http
Masaki Suketa (suke)
* committer
* He is the maintainer of win32ole
sheepman
* patches for ruby.c, thread.c, stringio, enum.c, webrick, net/http
Siena. (siena)
* committer
Kirill A. Shutemov
* a patch for parse.y
Darren Smith
* a patch for golf_prelude.rb
Richard M. Stallman
* missing/alloca.c
Robin Stocker
* documentation
Adam Strzelecki
* a patch for compile.c
Masashi Sumi
* improved net/pop.rb
Eric Sunshine
* NeXT OpenStep, Rhapsody support
Kouhei Sutou (kou)
* committer
* He wrote and is the maintainer of rss/*
David Symonds
* documentation
== T
TAKANO Mitsuhiro (takano32)
* committer
* He is the maintainer of IA-64 support.
* BigDecimal
TAKAO, Kouji (kouji)
* committer
* He is the maintainer of readline.
Nathaniel Talbott (ntalbott)
* committer
* He was the maintainer of test/unit, runit, rubyunit.
TANAKA, Akira (akr)
* committer
* Did much upon m17n.
* And he is the maintainer of:
* open-uri
* pathname
* pp
* resolv-replace
* resolv
* time
* tsort
Takaaki Tateishi (ttate)
* committer
* He was the maintainer of dl
Technorama Ltd. (technoroma)
* committer
* openssl
Andrew Thompson
* a patch for socket.c IRIX support.
Dave Thomas (dave)
* committer
* a.k.a. the Pragmatic Programmer.
* He wrote rdoc.
Tietew
* patches for win32 support
Masahiro Tomita
* a patch for cgi.rb
Jakub Travnik
* a patch for eval.c
Tom Truscott
* missing/crypt.c
== U
UEDA, Satoshi
* a patch for uri
Takaaki Uematsu (uema2)
* committer
* He was the maintainer of WinCE support.
UENO, Katsuhiro (katsu)
* committer
* He is the maintainer of zlib
Hajimu UMEMOTO
* He wrote ipaddr.rb
URABE, Shyouhei (shyouhei)
* committer
* a.k.a. mput.
* He is the branch maintainer of ruby_1_8_6 and ruby_1_8_7
* and is the release manager of 1.8.x-pXXX.
== V
Joel VanderWerf
* a patch for numeric.c
Peter Vanbroekhoven
Corinna Vinschen
== W
wanabe (wanabe)
* committer
* fixed YARV and Oniguruma.
Chun Wang
* a patch for time.rb
WATANABE, Hirofumi (eban)
* committer
* He is the maintainer of
* ftools (1.8)
* tmpdir
* un
* Win32API
WATANABE, Tetsuya
* a patch for ruby.c
William Webber (wew)
* committer
Jim Weirich (jim)
* committer
* He wrote Rake.
Nathan Weizenbaum
* fixed misc/ruby-mode.el.
why the lukky stiff (why)
* committer
* He is the maintainer of syck
Caley Woods
* documentation
Gary Wright
* documentation
== X
== Y
Akira Yamada (akira)
* committer
* He is the maintainer of ruby related packages at Debian project.
Keita Yamaguchi
* patches for enum.c, parse.y
* documentation
Hirokazu Yamamoto (ocean)
* committer
Hirotaka Yoshioka
* a patch for improving SEGV handling
== Z
Aristarkh A Zagorodnikov
* a patch for io.c
Alexander Zavorine
* committer
* He is the maintainer for Symbian OS.
Chiyuan Zhang
* a patch for misc/ruby-mode.el.
Dee Zsombor (zunda)
* a patch for thread_pthread.c
Dan Zwell
* a patch for net/pop

178
doc/dtrace_probes.rdoc Normal file
View file

@ -0,0 +1,178 @@
= DTrace Probes
A list of DTrace probes and their functionality. "Module" and "Function" cannot
be defined in user defined probes (known as USDT), so they will not be
specified. Probe definitions are in the format of:
provider:module:function:name(arguments)
Since module and function cannot be specified, they will be blank. An example
probe definition for Ruby would then be:
ruby:::function-entry(class name, method name, file name, line number)
Where "ruby" is the provider name, module and function names are blank, the
probe name is "function-entry", and the probe takes four arguments:
* class name
* method name
* file name
* line number
== Probes List
=== Stability
Before we list the specific probes, let's talk about stability. Probe stability
is declared in the probes.d file at the bottom on the #pragma D attributes
lines. Here is a description of each of the stability declarations.
[Provider name stability]
The provider name of "ruby" has been declared as stable. It is unlikely that
we will change the provider name from "ruby" to something else.
[Module and Function stability]
Since we are not allowed to provide values for the module and function name,
the values we have provided (no value) is declared as stable.
[Probe name stability]
The probe names are likely to change in the future, so they are marked as
"Evolving". Consumers should not depend on these names to be stable.
[Probe argument stability]
The parameters passed to the probes are likely to change in the future, so
they are marked as "Evolving". Consumers should not depend on these to be
stable.
=== Declared probes
Probes are defined in the probes.d file. Here are the declared probes along
with when they are fired and the arguments they take:
[ruby:::method-entry(classname, methodname, filename, lineno);]
This probe is fired just before a method is entered.
classname name of the class (a string)
methodname name of the method about to be executed (a string)
filename the file name where the method is _being called_ (a string)
lineno the line number where the method is _being called_ (an int)
[ruby:::method-return(classname, methodname, filename, lineno);]
This probe is fired just after a method has returned. The arguments are the
same as "ruby:::function-entry".
[ruby:::cmethod-entry(classname, methodname, filename, lineno);]
This probe is fired just before a C method is entered. The arguments are the
same as "ruby:::function-entry".
[ruby:::cmethod-return(classname, methodname, filename, lineno);]
This probe is fired just before a C method returns. The arguments are the
same as "ruby:::function-entry".
[ruby:::require-entry(requiredfile, filename, lineno);]
This probe is fired on calls to rb_require_safe (when a file is required).
requiredfile is the name of the file to be required (string).
filename is the file that called "require" (string).
lineno is the line number where the call to require was made (int).
[ruby:::require-return(requiredfile, filename, lineno);]
This probe is fired just before rb_require_safe (when a file is required)
returns. The arguments are the same as "ruby:::require-entry". This probe
will not fire if there was an exception during file require.
[ruby:::find-require-entry(requiredfile, filename, lineno);]
This probe is fired right before search_required is called. search_required
determines whether the file has already been required by searching loaded
features ($"), and if not, figures out which file must be loaded.
requiredfile is the file to be required (string).
filename is the file that called "require" (string).
lineno is the line number where the call to require was made (int).
[ruby:::find-require-return(requiredfile, filename, lineno);]
This probe is fired right after search_required returns. See the
documentation for "ruby:::find-require-entry" for more details. Arguments for
this probe are the same as "ruby:::find-require-entry".
[ruby:::load-entry(loadedfile, filename, lineno);]
This probe is fired when calls to "load" are made. The arguments are the same
as "ruby:::require-entry".
[ruby:::load-return(loadedfile, filename, lineno);]
This probe is fired when "load" returns. The arguments are the same as
"ruby:::load-entry".
[ruby:::raise(classname, filename, lineno);]
This probe is fired when an exception is raised.
classname is the class name of the raised exception (string)
filename the name of the file where the exception was raised (string)
lineno the line number in the file where the exception was raised (int)
[ruby:::object-create(classname, filename, lineno);]
This probe is fired when an object is about to be allocated.
classname the class of the allocated object (string)
filename the name of the file where the object is allocated (string)
lineno the line number in the file where the object is allocated (int)
[ruby:::array-create(length, filename, lineno);]
This probe is fired when an Array is about to be allocated.
length the size of the array (long)
filename the name of the file where the array is allocated (string)
lineno the line number in the file where the array is allocated (int)
[ruby:::hash-create(length, filename, lineno);]
This probe is fired when a Hash is about to be allocated.
length the size of the hash (long)
filename the name of the file where the hash is allocated (string)
lineno the line number in the file where the hash is allocated (int)
[ruby:::string-create(length, filename, lineno);]
This probe is fired when a String is about to be allocated.
length the size of the string (long)
filename the name of the file where the string is allocated (string)
lineno the line number in the file where the string is allocated (int)
[ruby:::symbol-create(str, filename, lineno);]
This probe is fired when a Symbol is about to be allocated.
str the contents of the symbol (string)
filename the name of the file where the string is allocated (string)
lineno the line number in the file where the string is allocated (int)
[ruby:::parse-begin(sourcefile, lineno);]
Fired just before parsing and compiling a source file.
sourcefile the file being parsed (string)
lineno the line number where the source starts (int)
[ruby:::parse-end(sourcefile, lineno);]
Fired just after parsing and compiling a source file.
sourcefile the file being parsed (string)
lineno the line number where the source ended (int)
[ruby:::gc-mark-begin();]
Fired at the beginning of a mark phase.
[ruby:::gc-mark-end();]
Fired at the end of a mark phase.
[ruby:::gc-sweep-begin();]
Fired at the beginning of a sweep phase.
[ruby:::gc-sweep-end();]
Fired at the end of a sweep phase.
[ruby:::method-cache-clear(class, sourcefile, lineno);]
Fired when the method cache is cleared.
class is the classname being cleared, or "global" (string)
sourcefile the file being parsed (string)
lineno the line number where the source ended (int)

View file

@ -22,26 +22,34 @@ $_:: The last input line of string by gets or readline.
$0:: Contains the name of the script being executed. May be assignable. $0:: Contains the name of the script being executed. May be assignable.
$*:: Command line arguments given for the script sans args. $*:: Command line arguments given for the script sans args.
$$:: The process number of the Ruby running this script. $$:: The process number of the Ruby running this script.
$?:: The status of the last executed child process. $?:: The status of the last executed child process. This value is
thread-local.
$::: Load path for scripts and binary modules by load or require. $::: Load path for scripts and binary modules by load or require.
$":: The array contains the module names loaded by require. $":: The array contains the module names loaded by require.
$DEBUG:: The status of the -d switch. $DEBUG:: The debug flag, which is set by the -d switch. Enabling debug
output prints each exception raised to $stderr (but not its
backtrace). Setting this to a true value enables debug output as
if -d were given on the command line. Setting this to a false
value disables debug output.
$FILENAME:: Current input file from $<. Same as $<.filename. $FILENAME:: Current input file from $<. Same as $<.filename.
$LOAD_PATH:: The alias to the $:. $LOAD_PATH:: The alias to the $:.
$stderr:: The current standard error output. $stderr:: The current standard error output.
$stdin:: The current standard input. $stdin:: The current standard input.
$stdout:: The current standard output. $stdout:: The current standard output.
$VERBOSE:: The verbose flag, which is set by the -v switch. $VERBOSE:: The verbose flag, which is set by the -w or -v switch. Setting
this to a true value enables warnings as if -w or -v were given
on the command line. Setting this to nil disables warnings,
including from Kernel#warn.
$-0:: The alias to $/. $-0:: The alias to $/.
$-a:: True if option -a is set. Read-only variable. $-a:: True if option -a is set. Read-only variable.
$-d:: The alias to $DEBUG. $-d:: The alias of $DEBUG. See $DEBUG above for further discussion.
$-F:: The alias to $;. $-F:: The alias to $;.
$-i:: In in-place-edit mode, this variable holds the extension, otherwise nil. $-i:: In in-place-edit mode, this variable holds the extension, otherwise nil.
$-I:: The alias to $:. $-I:: The alias to $:.
$-l:: True if option -l is set. Read-only variable. $-l:: True if option -l is set. Read-only variable.
$-p:: True if option -p is set. Read-only variable. $-p:: True if option -p is set. Read-only variable.
$-v:: The alias to $VERBOSE. $-v:: An alias of $VERBOSE. See $VERBOSE above for further discussion.
$-w:: True if option -w is set. $-w:: An alias of $VERBOSE. See $VERBOSE above for further discussion.
== Pre-defined global constants == Pre-defined global constants

View file

@ -96,7 +96,7 @@ irb起動時に``~/.irbrc''を読み込みます. もし存在しない場合は
IRB.conf[:USE_TRACER] = false IRB.conf[:USE_TRACER] = false
IRB.conf[:IGNORE_SIGINT] = true IRB.conf[:IGNORE_SIGINT] = true
IRB.conf[:IGNORE_EOF] = false IRB.conf[:IGNORE_EOF] = false
IRB.conf[:PROMPT_MODE] = :DEFALUT IRB.conf[:PROMPT_MODE] = :DEFAULT
IRB.conf[:PROMPT] = {...} IRB.conf[:PROMPT] = {...}
IRB.conf[:DEBUG_LEVEL]=0 IRB.conf[:DEBUG_LEVEL]=0
IRB.conf[:VERBOSE]=true IRB.conf[:VERBOSE]=true

322
doc/maintainers.rdoc Normal file
View file

@ -0,0 +1,322 @@
= Maintainers
This page describes the current module, library, and extension maintainers of Ruby.
== Module Maintainers
A module maintainer is responsible for a certain part of Ruby.
* The maintainer fixes bugs of the part. Particularly, they should fix security vulnerabilities as soon as possible.
* They handle issues related the module on the Redmine or ML.
* They may be discharged by the 3 months rule [ruby-core:25764].
* They have commit right to Ruby's repository to modify their part in the repository.
* They have "developer" role on the Redmine to modify issues.
* They have authority to decide the feature of their part. But they should always respect discussions on ruby-core/ruby-dev.
A submaintainer of a module is like a maintainer. But The submaintainer does
not have authority to change/add a feature on his/her part. They need consensus
on ruby-core/ruby-dev before changing/adding. Some of submaintainers have
commit right, others don't.
=== Language core features including security
Yukihiro Matsumoto (matz)
=== Evaluator
Koichi Sasada (ko1)
=== Core classes
Yukihiro Matsumoto (matz)
=== Documentation
Zachary Scott (zzak)
== Library Maintainers
[lib/English.rb]
_unmaintained_
[lib/abbrev.rb]
Akinori MUSHA (knu)
[lib/base64.rb]
* 1.8: _unmaintained_
* 1.9: Yusuke Endoh (mame)
[lib/benchmark.rb]
_unmaintained_
[lib/cgi.rb, lib/cgi/*]
Takeyuki Fujioka (xibbar)
[lib/complex.rb]
* 1.8: _unmaintained_
* 1.9: moved into core
[lib/cmath.rb]
* 1.8: 1.9 feature
* 1.9: _unmaintained_
[lib/csv.rb]
* 1.8: Hiroshi Nakamura (nahi)
* 1.9: James Edward Gray II (jeg2)
[lib/date.rb, lib/date/*]
Tadayoshi Funaba (tadf)
[lib/drb.rb, lib/drb/*]
Masatoshi SEKI (seki)
[lib/debug.rb]
_unmaintained_
[lib/delegate.rb]
_unmaintained_
[lib/e2mmap.rb]
Keiju ISHITSUKA (keiju)
[lib/erb.rb]
Masatoshi SEKI (seki)
[lib/fileutils.rb]
_unmaintained_
[lib/find.rb]
Kazuki Tsujimoto (ktsj)
[lib/finalize.rb]
* 1.8: _unmaintained_
* 1.9: _deprecated_
[lib/forwardable.rb]
Keiju ISHITSUKA (keiju)
[lib/ftools.rb]
* 1.8: _unmaintained_
* 1.9: _deprecated_
[lib/generator.rb]
* 1.8: Akinori MUSHA (knu)
* 1.9: moved into core
[lib/getoptlong.rb]
_unmaintained_
[lib/getopts.rb]
* 1.8: Akinori MUSHA (knu)
* 1.9: _deprecated_
[lib/gserver.rb]
James Edward Gray II (jeg2)
[lib/ipaddr.rb]
Akinori MUSHA (knu)
[lib/irb.rb, lib/irb/*]
Keiju ISHITSUKA (keiju)
[lib/jcode.rb]
* 1.8: _unmaintained_
* 1.9: _deprecated_
[lib/logger.rb]
Hiroshi Nakamura (nahi)
[lib/mathn.rb]
Keiju ISHITSUKA (keiju)
[lib/matrix.rb]
Marc-Andre Lafortune (marcandre)
[lib/minitest/*]
* 1.8: 1.9 feature
* 1.9: Ryan Davis (ryan)
[lib/mkmf.rb]
_unmaintained_
[lib/monitor.rb]
Shugo Maeda (shugo)
[lib/mutex_m.rb]
Keiju ISHITSUKA (keiju)
[lib/net/ftp.rb]
Shugo Maeda (shugo)
[lib/net/imap.rb]
Shugo Maeda (shugo)
[lib/net/telnet.rb]
_unmaintained_
[lib/net/http.rb, lib/net/https]
NARUSE, Yui (naruse)
[lib/net/pop.rb]
_unmaintained_
[lib/net/smtp.rb]
_unmaintained_
[lib/observer.rb]
_unmaintained_
[lib/open-uri.rb]
Tanaka Akira (akr)
[lib/open3.rb]
_unmaintained_
[lib/optparse.rb, lib/optparse/*]
Nobuyuki Nakada (nobu)
[lib/ostruct.rb]
Marc-Andre Lafortune (marcandre)
[lib/parsearg.rb]
* 1.8: _unmaintained_
* 1.9: _deprecated_
[lib/parsedate.rb]
* 1.8: Tadayoshi Funaba (tadf)
* 1.9: _deprecated_
[lib/pathname.rb]
Tanaka Akira (akr)
[lib/ping.rb]
* 1.8: _unmaintained_
* 1.9: _deprecated_
[lib/pp.rb]
Tanaka Akira (akr)
[lib/prettyprint.rb]
Tanaka Akira (akr)
[lib/prime.rb]
Yuki Sonoda (yugui)
[lib/profile.rb]
_unmaintained_
[lib/profiler.rb]
_unmaintained_
[lib/pstore.rb]
_unmaintained_
[lib/racc/*]
Aaron Patterson (tenderlove)
[lib/rake/*]
Eric Hodel (drbrain)
[lib/rational.rb]
* 1.8: _unmaintained_
* 1.9: moved into core
[lib/rdoc/*]
Eric Hodel (drbrain)
[lib/readbytes.rb]
* 1.8: _unmaintained_
* 1.9: _deprecated_
[lib/resolv-replace.rb]
Tanaka Akira (akr)
[lib/resolv.rb]
Tanaka Akira (akr)
[lib/rexml/*]
Kouhei Sutou (kou)
[lib/rinda/*]
Masatoshi SEKI (seki)
[lib/rss/*]
Kouhei Sutou (kou)
[lib/rubygems.rb, lib/ubygems.rb, lib/rubygems/*]
* 1.8: 1.9 feature
* 1.9: Eric Hodel (drbrain)
[lib/rubyunit.rb, lib/runit/*]
* 1.8: _unmaintained_
* 1.9: _deprecated_
[lib/scanf.rb]
David A. Black (dblack)
[lib/set.rb]
Akinori MUSHA (knu)
[lib/securerandom.rb]
Tanaka Akira (akr)
[lib/shell.rb, lib/shell/*]
Keiju ISHITSUKA (keiju)
[lib/shellwords.rb]
Akinori MUSHA (knu)
[lib/singleton.rb]
Yukihiro Matsumoto (matz)
[lib/{soap|wsdl|xsd}/*]
* 1.8: Hiroshi Nakamura (nahi)
* 1.9: _deprecated_
[lib/sync.rb]
Keiju ISHITSUKA (keiju)
[lib/tempfile.rb]
_unmaintained_
[lib/test/*]
Shota Fukumori (sorah)
[lib/tmpdir.rb]
_unmaintained_
[lib/thread.rb]
_unmaintained_
[lib/thwait.rb]
Keiju ISHITSUKA (keiju)
[lib/time.rb]
Tanaka Akira (akr)
[lib/timeout.rb]
Yukihiro Matsumoto (matz)
[lib/tracer.rb]
Keiju ISHITSUKA (keiju)
[lib/tsort.rb]
Tanaka Akira (akr)
[lib/un.rb]
WATANABE Hirofumi (eban)
[lib/uri.rb, lib/uri/*]
YAMADA, Akira (akira)
[lib/weakref.rb]
_unmaintained_
[lib/webrick.rb, lib/webrick/*]
Hiroshi Nakamura (nahi)
[lib/xmlrpc/*]
Kouhei Sutou (kou)
[lib/yaml.rb, lib/yaml/*]
Aaron Patterson (tenderlove)
== Extension Maintainers
[ext/Win32API]
* 1.8: _unmaintained_
* 1.9: merged into dl
[ext/bigdecimal]
Kenta Murata (mrkn)
[ext/continuation]
* 1.8: 1.9 feature
* 1.9: Koichi Sasada (ko1)
[ext/coverage]
Yusuke Endoh (mame)
[ext/dbm]
_unmaintained_
[ext/digest, ext/digest/*]
Akinori MUSHA (knu)
[ext/dl]
Aaron Patterson (tenderlove)
[ext/dl/win32]
NAKAMURA Usaku (usa)
[ext/enumerator]
* 1.8: Akinori MUSHA (knu)
* 1.9: moved into core
[ext/etc]
_unmaintained_
[ext/fcntl]
_unmaintained_
[ext/fiber]
* 1.8: 1.9 feature
* 1.9: Koichi Sasada (ko1)
[ext/fiddle]
Aaron Patterson (tenderlove)
[ext/gdbm]
Yukihiro Matsumoto (matz)
[ext/iconv]
Nobuyuki Nakada (nobu)
[ext/io/wait]
Nobuyuki Nakada (nobu)
[ext/json]
NARUSE, Yui (naruse)
[ext/mathn/complex]
* 1.8: 1.9 feature
* 1.9: Keiju ISHITSUKA (keiju)
[ext/mathn/rational]
* 1.8: 1.9 feature
* 1.9: Keiju ISHITSUKA (keiju)
[ext/nkf]
NARUSE, Yui (narse)
[ext/objspace]
_unmaintained_
[ext/openssl]
Martin Boßlet (emboss)
[ext/psych]
Aaron Patterson (tenderlove)
[ext/pty]
_unmaintained_
[ext/racc]
Aaron Patterson (tenderlove)
[ext/readline]
TAKAO Kouji (kouji)
[ext/ripper]
_unmaintained_
[ext/sdbm]
Yukihiro Matsumoto (matz)
[ext/socket]
* Tanaka Akira (akr)
* API change needs matz's approval
[ext/stringio]
Nobuyuki Nakada (nobu)
[ext/strscan]
_unmaintained_
[ext/syck]
_unmaintained_
[ext/syslog]
Akinori MUSHA (knu)
[ext/thread]
* 1.8: _unmaintained_
* 1.9: 1.8 feature
[ext/tcltklib]
_deprecated_
[ext/tk]
Hidetoshi NAGAI (nagai)
[ext/win32ole]
Masaki Suketa (suke)
[ext/zlib]
_unmaintained_

313
doc/marshal.rdoc Normal file
View file

@ -0,0 +1,313 @@
= Marshal Format
The Marshal format is used to serialize ruby objects. The format can store
arbitrary objects through three user-defined extension mechanisms.
For documentation on using Marshal to serialize and deserialize objects, see
the Marshal module.
This document calls a serialized set of objects a stream. The Ruby
implementation can load a set of objects from a String, an IO or an object
that implements a +getc+ method.
== Stream Format
The first two bytes of the stream contain the major and minor version, each as
a single byte encoding a digit. The version implemented in Ruby is 4.8
(stored as "\x04\x08") and is supported by ruby 1.8.0 and newer.
Different major versions of the Marshal format are not compatible and cannot
be understood by other major versions. Lesser minor versions of the format
can be understood by newer minor versions. Format 4.7 can be loaded by a 4.8
implementation but format 4.8 cannot be loaded by a 4.7 implementation.
Following the version bytes is a stream describing the serialized object. The
stream contains nested objects (the same as a Ruby object) but objects in the
stream do not necessarily have a direct mapping to the Ruby object model.
Each object in the stream is described by a byte indicating its type followed
by one or more bytes describing the object. When "object" is mentioned below
it means any of the types below that defines a Ruby object.
=== true, false, nil
These objects are each one byte long. "T" is represents +true+, "F"
represents +false+ and "0" represents +nil+.
=== Fixnum and long
"i" represents a signed 32 bit value using a packed format. One through five
bytes follows the type. The value loaded will always be a Fixnum. On
32 bit platforms (where the precision of a Fixnum is less than 32 bits)
loading large values will cause overflow on CRuby.
The fixnum type is used to represent both ruby Fixnum objects and the sizes of
marshaled arrays, hashes, instance variables and other types. In the
following sections "long" will mean the format described below, which supports
full 32 bit precision.
The first byte has the following special values:
"\x00"::
The value of the integer is 0. No bytes follow.
"\x01"::
The total size of the integer is two bytes. The following byte is a
positive integer in the range of 0 through 255. Only values between 123
and 255 should be represented this way to save bytes.
"\xff"::
The total size of the integer is two bytes. The following byte is a
negative integer in the range of -1 through -256.
"\x02"::
The total size of the integer is three bytes. The following two bytes are a
positive little-endian integer.
"\xfe"::
The total size of the integer is three bytes. The following two bytes are a
negative little-endian integer.
"\x03"::
The total size of the integer is four bytes. The following three bytes are
a positive little-endian integer.
"\xfd"::
The total size of the integer is two bytes. The following three bytes are a
negative little-endian integer.
"\x04"::
The total size of the integer is five bytes. The following four bytes are a
positive little-endian integer. For compatibility with 32 bit ruby,
only Fixnums less than 1073741824 should be represented this way. For sizes
of stream objects full precision may be used.
"\xfc"::
The total size of the integer is two bytes. The following four bytes are a
negative little-endian integer. For compatibility with 32 bit ruby,
only Fixnums greater than -10737341824 should be represented this way. For
sizes of stream objects full precision may be used.
Otherwise the first byte is a sign-extended eight-bit value with an offset.
If the value is positive the value is determined by subtracting 5 from the
value. If the value is negative the value is determined by adding 5 to the
value.
There are multiple representations for many values. CRuby always outputs the
shortest representation possible.
=== Symbols and Byte Sequence
":" represents a real symbol. A real symbol contains the data needed to
define the symbol for the rest of the stream as future occurrences in the
stream will instead be references (a symbol link) to this one. The reference
is a zero-indexed 32 bit value (so the first occurrence of <code>:hello</code>
is 0).
Following the type byte is byte sequence which consists of a long indicating
the number of bytes in the sequence followed by that many bytes of data. Byte
sequences have no encoding.
For example, the following stream contains the Symbol <code>:hello</code>:
"\x04\x08:\x0ahello"
";" represents a Symbol link which references a previously defined Symbol.
Following the type byte is a long containing the index in the lookup table for
the linked (referenced) Symbol.
For example, the following stream contains <code>[:hello, :hello]</code>:
"\x04\b[\a:\nhello;\x00"
When a "symbol" is referenced below it may be either a real symbol or a
symbol link.
=== Object References
Separate from but similar to symbol references, the stream contains only one
copy of each object (as determined by #object_id) for all objects except
true, false, nil, Fixnums and Symbols (which are stored separately as
described above) a one-indexed 32 bit value will be stored and reused when the
object is encountered again. (The first object has an index of 1).
"@" represents an object link. Following the type byte is a long giving the
index of the object.
For example, the following stream contains an Array of the object
<code>"hello"</code> twice:
"\004\b[\a\"\nhello@\006"
=== Instance Variables
"I" indicates that instance variables follow the next object. An object
follows the type byte. Following the object is a length indicating the number
of instance variables for the object. Following the length is a set of
name-value pairs. The names are symbols while the values are objects. The
symbols must be instance variable names (<code>:@name</code>).
An Object ("o" type, described below) uses the same format for its instance
variables as described here.
For a String and Regexp (described below) a special instance variable
<code>:E</code> is used to indicate the Encoding.
=== Extended
"e" indicates that the next object is extended by a module. An object follows
the type byte. Following the object is a symbol that contains the name of the
module the object is extended by.
=== Array
"[" represents an Array. Following the type byte is a long indicating the
number of objects in the array. The given number of objects follow the
length.
=== Bignum
"l" represents a Bignum which is composed of three parts:
sign::
A single byte containing "+" for a positive value or "-" for a negative
value.
length::
A long indicating the number of bytes of Bignum data follows, divided by
two. Multiply the length by two to determine the number of bytes of data
that follow.
data::
Bytes of Bignum data representing the number.
The following ruby code will reconstruct the Bignum value from an array of
bytes:
result = 0
bytes.each_with_index do |byte, exp|
result += (byte * 2 ** (exp * 8))
end
=== Class and Module
"c" represents a Class object, "m" represents a Module and "M" represents
either a class or module (this is an old-style for compatibility). No class
or module content is included, this type is only a reference. Following the
type byte is a byte sequence which is used to look up an existing class or
module, respectively.
Instance variables are not allowed on a class or module.
If no class or module exists an exception should be raised.
For "c" and "m" types, the loaded object must be a class or module,
respectively.
=== Data
"d" represents a Data object. (Data objects are wrapped pointers from ruby
extensions.) Following the type byte is a symbol indicating the class for the
Data object and an object that contains the state of the Data object.
To dump a Data object Ruby calls _dump_data. To load a Data object Ruby calls
_load_data with the state of the object on a newly allocated instance.
=== Float
"f" represents a Float object. Following the type byte is a byte sequence
containing the float value. The following values are special:
"inf"::
Positive infinity
"-inf"::
Negative infinity
"nan"::
Not a Number
Otherwise the byte sequence contains a C double (loadable by strtod(3)).
Older minor versions of Marshal also stored extra mantissa bits to ensure
portability across platforms but 4.8 does not include these. See
[ruby-talk:69518] for some explanation.
=== Hash and Hash with Default Value
"{" represents a Hash object while "}" represents a Hash with a default value
set (<code>Hash.new 0</code>). Following the type byte is a long indicating
the number of key-value pairs in the Hash, the size. Double the given number
of objects follow the size.
For a Hash with a default value, the default value follows all the pairs.
=== Module and Old Module
=== Object
"o" represents an object that doesn't have any other special form (such as
a user-defined or built-in format). Following the type byte is a symbol
containing the class name of the object. Following the class name is a long
indicating the number of instance variable names and values for the object.
Double the given number of pairs of objects follow the size.
The keys in the pairs must be symbols containing instance variable names.
=== Regular Expression
"/" represents a regular expression. Following the type byte is a byte
sequence containing the regular expression source. Following the type byte is
a byte containing the regular expression options (case-insensitive, etc.) as a
signed 8-bit value.
Regular expressions can have an encoding attached through instance variables
(see above). If no encoding is attached escapes for the following regexp
specials not present in ruby 1.8 must be removed: g-m, o-q, u, y, E, F, H-L,
N-V, X, Y.
=== String
'"' represents a String. Following the type byte is a byte sequence
containing the string content. When dumped from ruby 1.9 an encoding instance
variable (<code>:E</code> see above) should be included unless the encoding is
binary.
=== Struct
"S" represents a Struct. Following the type byte is a symbol containing the
name of the struct. Following the name is a long indicating the number of
members in the struct. Double the number of objects follow the member count.
Each member is a pair containing the member's symbol and an object for the
value of that member.
If the struct name does not match a Struct subclass in the running ruby an
exception should be raised.
If there is a mismatch between the struct in the currently running ruby and
the member count in the marshaled struct an exception should be raised.
=== User Class
"C" represents a subclass of a String, Regexp, Array or Hash. Following the
type byte is a symbol containing the name of the subclass. Following the name
is the wrapped object.
=== User Defined
"u" represents an object with a user-defined serialization format using the
+_dump+ instance method and +_load+ class method. Following the type byte is
a symbol containing the class name. Following the class name is a byte
sequence containing the user-defined representation of the object.
The class method +_load+ is called on the class with a string created from the
byte-sequence.
=== User Marshal
"U" represents an object with a user-defined serialization format using the
+marshal_dump+ and +marshal_load+ instance methods. Following the type byte
is a symbol containing the class name. Following the class name is an object
containing the data.
Upon loading a new instance must be allocated and +marshal_load+ must be
called on the instance with the data.

View file

@ -1,84 +0,0 @@
pty extension version 0.3 by A.ito
1. Introduction
This extension module adds ruby a functionality to execute an
arbitrary command through pseudo tty (pty).
2. Install
Follow the instruction below.
(1) Execute
ruby extconf.rb
then Makefile is generated.
(3) Do make; make install.
3. What you can do
This extension module defines a module named PTY, which contains
following module fungtions:
getpty(command)
spawn(command)
This function reserves a pty, executes command over the pty
and returns an array. The return value is an array with three
elements. The first element in the array is for reading and the
second for writing. The third element is the process ID of the
child process. If this function is called with an iterator block,
the array is passed to the block as block parameters, and the
function itself returns nil.
When the child process is suspended or finished, an exception is
raised. If this function is called with an iterator block,
exception is raised only within the block. Child process
monitor is terminated on block exit.
protect_signal
reset_signal
These functions are obsolete in this version of pty.
PTY.open
Allocates a pty (pseudo-terminal).
It returns an array which contains an IO object and a File object.
The former is the master of the pty.
The latter is the slave of the pty.
If a block is given, it yields the array instead of return.
The value of the block is returned.
master_io and slave_file is closed when return if they are not closed.
PTY.check(pid[, raise=false])
checks the status of the child process specified by pid, and
returns nil if the process is still alive and active.
Otherwise, returns Process::Status about the process if raise is
false, or PTY::ChildExited exception is raised.
4. License
(C) Copyright 1998 by Akinori Ito.
This software may be redistributed freely for this purpose, in full
or in part, provided that this entire copyright notice is included
on any copies of this software and applications and derivations thereof.
This software is provided on an "as is" basis, without warranty of any
kind, either expressed or implied, as to any matter including, but not
limited to warranty of fitness of purpose, or merchantability, or
results obtained from use of this software.
5. Bug report
Please feel free to send E-mail to
aito@ei5sun.yz.yamagata-u.ac.jp
for any bug report, opinion, contribution, etc.

View file

@ -1,22 +0,0 @@
README for expect
by A. Ito, 28 October, 1998
Expect library adds IO class a method called expect(), which
does similar act to tcl's expect extension.
The usage of the method is:
IO#expect(pattern,timeout=9999999)
where `pattern' is an instance of String or Regexp and `timeout'
is Fixnum, which can be omitted.
When the method is called without block, it waits until the
input which matches the pattern is obtained from the IO or the time
specified as the timeout passes. When the pattern is obtained from the
IO, the method returns an array. The first element of the array is the
entire string obtained from the IO until the pattern matches. The
following elements indicates the specific pattern which matched to the
anchor in the regular expression. If the method ends because of
timeout, it returns nil.
When the method is called with block, the array is passed as
the block parameter.

View file

@ -1,440 +0,0 @@
= Rake Changelog
== Version 0.8.7
* Fixed EXEEXT for JRuby on windows.
== Version 0.8.6
* Minor fixes to the RDoc generation (removed dependency on darkfish
and removed inline source option).
== Version 0.8.5
* Better support for the system command on Windows.
== Version 0.8.4
* Preserve case when locating rakefiles (patch from James
M. Lawrence/quix)
* Better support for windows paths in the test task (patch from Simon
Chiang/bahuvrihi)
* Windows system dir search order is now: HOME, HOMEDRIVE + HOMEPATH,
APPDATA, USERPROFILE (patch from Luis Lavena)
* MingGW is now recognized as a windows platform. (patch from Luis
Lavena)
* Numerous fixes to the windows test suite (patch from Luis Lavena).
* Improved Rakefile case insensitivity testing (patch from Luis
Lavena).
* Fixed stray ARGV option problem that was interfering with
Test::Unit::Runner.
* Fixed default verbose mode (was accidently changed to false).
* Removed reference to manage_gem to fix the warning produced by the
gem package task.
== Version 0.8.3
* Enhanced the system directory detection in windows. We now check
HOMEDRIVE/HOMEPATH and USERPROFILE if APPDATA isn't found. (Patch
supplied by James Tucker). Rake no long aborts if it can't find the
directory.
* Added fix to handle ruby installations in directories with spaces in
their name.
== Version 0.8.2
* Fixed bug in package task so that it will include the subdir
directory in the package for testing. (Bug found by Adam Majer)
* Added ENV var to rakefile to prevent OS X from including extended
attribute junk in a tar file. (Bug found by Adam Majer)
* Fixed filename dependency order bug in test_inspect_pending and
test_to_s_pending. (Bug found by Adam Majer)
* Fixed check for file utils options to make them immune to the
symbol/string differences. (Patch supplied by Edwin Pratomo)
* Fixed bug with rules involving multiple source (Patch supplied by
Emanuel Indermühle)
* Switched from getoptlong to optparse (patches supplied by Edwin
Pratomo)
* The -T option will now attempt to dynamically sense the size of the
terminal. RAKE_COLUMNS will override any dynamic sensing.
* FileList#clone and FileList#dup have better sematics w.r.t. taint
and freeze.
* Added ability clear prerequisites, and/or actions from an existing
task.
* Added the ability to reenable a task to be invoked a second time.
* Changed RDoc test task to have no default template. This makes it
easier for the tempate to pick up the template from the environment.
* Changed from using Mutex to Monitor. Evidently Mutex causes thread
join errors when Ruby is compiled with -disable-pthreads. (Patch
supplied by Ittay Dror)
* Fixed bug in makefile parser that had problems with extra spaces in
file task names. (Patch supplied by Ittay Dror)
* Added a performance patch for reading large makefile dependency
files. (Patch supplied by Ittay Dror)
* Default values for task arguments can easily be specified with the
:with_defaults method. (Idea for default argument merging supplied
by (Adam Q. Salter)
* The -T output will only self-truncate if the output is a tty.
However, if RAKE_COLUMNS is explicitly set, it will be honored in
any case. (Patch provided by Gavin Stark).
* Numerous fixes for running under windows. A big thanks to Bheeshmar
Redheendran for spending a good part of the afternoon at the
Lonestar Ruby Conference to help me work out these issues.
== Version 0.8.1
* Removed requires on parsedate.rb (in Ftptools)
* Removed ftools from rake.rb. Made it options in sys.rb
== Version 0.8.0
* Added task parameters (e.g. "rake build[version7]")
* Made task parameters passable to prerequisites.
* Comments are limited to 80 columns or so (suggested by Jamis Buck).
* Added -D to display full comments (suggested by Jamis Buck).
* The rake program will set the status value used in any explicit
exit(n) calls. (patch provided by Stephen Touset)
* Fixed error in functional tests that were not including session (and
silently skipping the functionl tests.
* Removed --usage and make -h the same as -H.
* Make a prettier inspect for tasks.
== Version 0.7.3
* Added existing and existing! methods to FileList
* FileLists now claim to be Arrays (via is_a?) to get better support
from the FileUtil module.
* Added init and top_level for custom rake applications.
== Version 0.7.2
* Error messages are now send to stderr rather than stdout (from
Payton Quackenbush).
* Better error handling on invalid command line arguments (from Payton
Quackenbush).
* Added rcov task and updated unit testing for better code coverage.
* Fixed some bugs where the application object was going to the global
appliation instead of using its own data.
* Added square and curly bracket patterns to FileList#include (Tilman
Sauerbeck).
* Added plain filename support to rule dependents (suggested by Nobu
Nakada).
* Added pathmap support to rule dependents.
* Added a 'tasks' method to a namespace to get a list of tasks
associated with the namespace.
* Fixed the method name leak from FileUtils (bug found by Glenn
Vanderburg).
* Added rake_extension to handle detection of extension collisions.
* Added test for noop, bad_option and verbose flags to sh command.
* Removed dependency on internal fu_xxx functions from FileUtils.
* Added a 'shame' task to the Rakefile.
* Added tar_command and zip_command options to the Package task.
* Added a description to the gem task in GemPackageTask.
* Fixed a bug when rules have multiple prerequisites (patch by Joel
VanderWerf)
* Added a protected 'require "rubygems"' to test/test_application to
unbreak cruisecontrol.rb.
* Added the handful of RakeFileUtils to the private method as well.
* Added block based exclusion.
* The clean task will no longer delete 'core' if it is a directory.
* Removed rake_dup. Now we just simply rescue a bad dup.
* Refactored the FileList reject logic to remove duplication.
* Removed if __FILE__ at the end of the rake.rb file.
== Version 0.7.1
* Added optional filter parameter to the --tasks command line option.
* Added flatten to allow rule transform procs to return lists of
prereqs (Joel VanderWerf provided patch).
* Added pathmap to String and FileList.
* The -r option will now load .rake files (but a straight require
doesn't yet). NOTE: This is experimental ... it may be
discontinued.
* The -f option without a value will disable the search for a
Rakefile. The assumption is that the -r files are adequate.
* Fixed the safe_ln function to fall back to cp in more error
scenarios.
== Version 0.7.0
* Added Rake.original_dir to return the original starting directory of
the rake application.
* Added safe_ln support for openAFS (from Ludvig Omholt).
* Added --trace reminder on short exception messages (David Heinemeier
Hansson suggestion).
* Added multitask declaration that executes prerequisites in
parallel. (Doug Young providied an initial implementation).
* Fixed missing_const hack to be compatible with Rails. (Jamis Buck
supplied test case).
* Made the RDoc task default to internal (in-process) RDoc formatting.
The old behavior is still available by setting the +external+ flag
to true.
* Rakefiles are now loaded with the expanded path to prevent
accidental polution from the Ruby load path.
* The +namespace+ command now returns a NameSpace object that can be
used to lookup tasks defined in that namespace. This allows for
better anonymous namespace behavior.
* Task objects my now be used in prerequisite lists directly.
== Version 0.6.1
* Rebuilt 0.6.0 gem without signing.
== Version 0.6.0
* Fixed file creation bug in the unit tests (caused infinite loop on
windows).
* Fixed bug where session based functional tests were run under
windows.
* Fixed bug in directory tasks so that updating a directory will not
retrigger file tasks depending on the directory (see
FileCreationTask and EarlyTime).
* Added egrep to FileList
* ruby command now runs same ruby version as rake.
* Added investigation to task object. (suggested by Martin Fowler)
* Added ruby_opts to the test task to allow arbitrary ruby options to
be passed to the test script. (Greg Fast)
* Fixed the test loader to ignore options. (Greg Fast)
* Moved Task, FileTask, FileCreationTask and RakeApp into the Rake
module namespace. Old style namespace behavior can be invoked via
the --classic-namespace option. (requested by Kelly Felkins).
* GemTask is now sensitive to the gem platform (Masao Mutoh).
* A non-existing file prerequisite will no longer cause an exception
(Philipp Neubeck).
* Multiple prerequisites on Rake rules now allowed (initial patch
supplied by Stuart Jansen).
== Version 0.5.4
* Added double quotes to the test runner.
* Added .svn to default ignore list.
* Updated FileList#include to support nested arrays and filelists.
== Version 0.5.3
* Added support for importing Rakefile and other dependencies.
* Fixed bug so that now rules can chain off of existing tasks as well
as existing files.
* Fixed verbose flag bug in the testing task. Shortened some failure
messages.
* Make FileUtils methods private at the top level module to avoid
accidental method leaking into other objects.
* Added test loader option to test task. "testrb" is no longer the
default test loader. It is now eating syntax errors that should
halt the unit tests.
* Revamped FileList so that it works more like and array (addressed
flatten bug). Added many tests around file list.
* Added +ext+ method to both String and FileList.
== Version 0.5.0
* Fixed documentation that was lacking the Rake module name (Tilman
Sauerbeck).
* Added tar.gz and tar.bz2 support to package task (Tilman Sauerbeck).
* Recursive rules are now supported (Tilman Sauerbeck).
* Added warning option for the Test Task (requested by Eric Hodel).
* The jamis rdoc template is only used if it exists.
* Added fix for Ruby 1.8.2 test/unit and rails problem.
* Added contributed rake man file (Jani Monoses).
* Added Brian Candler's fix for problems in --trace and --dry-run
mode.
== Version 0.4.15
* Fixed a bug that prevented the TESTOPTS flag from working with the
revised for 1.8.2 test task.
* Updated the docs on --trace to indicate that it also enables a full
backtrace on errors.
== Version 0.4.14
* Modified the TestTask to workaround the Ruby 1.8.2 change in
autoexecuting unit tests.
== Version 0.4.13
* Fixed the dry-run flag so it is operating again.
* Multiple arguments to sh and ruby commands will not be interpreted
by the shell (patch provided by Jonathan Paisley).
== Version 0.4.12
* Added --silent (-s) to suppress the (in directory) rake message.
== Version 0.4.11
* Changed the "don't know how to rake" message (finally)
* Changes references to a literal "Rakefile" to reference the global
variable $rakefile (which contains the actual name of the rakefile).
== Version 0.4.10
* Added block support to the "sh" command, allowing users to take
special actions on the result of the system call. E.g.
sh "shell_command" do |ok, res|
puts "Program returned #{res.exitstatus}" if ! ok
end
== Version 0.4.9
* Switched to Jamis Buck's RDoc template.
* Removed autorequire from Rake's gem spec. This prevents the Rake
libraries from loading while using rails.
== Version 0.4.8
* Added support for .rb versions of Rakefile.
* Removed \\\n's from test task.
* Fixed Ruby 1.9 compatibility issue with FileList.
== Version 0.4.7
* Fixed problem in FileList that caused Ruby 1.9 to go into infinite
recursion. Since to_a was removed from Object, it does not need to
added back into the list of methods to rewrite in FileList. (Thanks
to Kent Sibilev for pointing this out).
== Version 0.4.6
* Removed test version of ln in FileUtils that prevented safe_ln from
using ln.
== Version 0.4.5
* Upgraded comments in TestTask.
* FileList to_s and inspect now automatically resolve pending changes.
* FileList#exclude properly returns the FileList.
== Version 0.4.4
* Fixed initialization problem with @comment.
* Now using multi -r technique in TestTask. Switch Rakefile back to
using the built-in test task macros because the rake runtime is no
longer needed.
* Added 'TEST=filename' and 'TESTOPTS=options' to the Test Task
macros.
* Allow a +test_files+ attribute in test tasks. This allows more
flexibility in specifying test files.
== Version 0.4.3
* Fixed Comment leakage.
== Version 0.4.2
* Added safe_ln that falls back to a copy if a file link is not supported.
* Package builder now uses safe_ln.
== Version 0.4.1
* Task comments are now additive, combined with "/".
* Works with (soon to be released) rubygems 0.6.2 (or 0.7.0)
== Version 0.4.0
* FileList now uses deferred loading. The file system is not searched
until the first call that needs the file names.
* VAR=VALUE options are now accepted on the command line and are
treated like environment variables. The values may be tested in a
Rakefile by referencing ENV['VAR'].
* File.mtime is now used (instead of File.new().mtime).
== Version 0.3.2.x
* Removed some hidden dependencies on rubygems. Tests now will test
gems only if they are installed.
* Removed Sys from some example files. I believe that is that last
reference to Sys outside of the contrib area.
* Updated all copyright notices to include 2004.
== Version 0.3.2
* GEM Installation now works with the application stub.
== Version 0.3.1
* FileLists now automatically ignore CVS, .bak, !
* GEM Installation now works.
== Version 0.3.0
Promoted 0.2.10.
== Version 0.2.10
General
* Added title to Rake's rdocs
* Contrib packages are no longer included in the documentation.
RDoc Issues
* Removed default for the '--main' option
* Fixed rendering of the rdoc options
* Fixed clean/clobber confusion with rerdoc
* 'title' attribute added
Package Task Library Issues
* Version (or explicit :noversion) is required.
* +package_file+ attribute is now writable
FileList Issues
* Dropped bang version of exclude. Now using ant-like include/exclude semantics.
* Enabled the "yield self" idiom in FileList#initialize.
== Version 0.2.9
This version contains numerous changes as the RubyConf.new(2003)
presentation was being prepared. The changes include:
* The monolithic rubyapp task library is in the process of being
dropped in favor of lighter weight task libraries.
== Version 0.2.7
* Added "desc" for task descriptions.
* -T will now display tasks with descriptions.
* -P will display tasks and prerequisites.
* Dropped the Sys module in favor of the 1.8.x FileUtils module. Sys
is still supported in the contrib area.
== Version 0.2.6
* Moved to RubyForge
== Version 0.2.5
* Switched to standard ruby app builder.
* Added no_match option to file matcher.
== Version 0.2.4
* Fixed indir, which neglected to actually change directories.
== Version 0.2.3
* Added rake module for a help target
* Added 'for_files' to Sys
* Added a $rakefile constant
* Added test for selecting proper rule with multiple targets.

View file

@ -1,196 +0,0 @@
= RAKE -- Ruby Make
Supporting Rake version: 0.8.6
This package contains Rake, a simple ruby build program with
capabilities similar to make.
Rake has the following features:
* Rakefiles (rake's version of Makefiles) are completely defined in
standard Ruby syntax. No XML files to edit. No quirky Makefile
syntax to worry about (is that a tab or a space?)
* Users can specify tasks with prerequisites.
* Rake supports rule patterns to synthesize implicit tasks.
* Flexible FileLists that act like arrays but know about manipulating
file names and paths.
* A library of prepackaged tasks to make building rakefiles easier. For example,
tasks for building tarballs, gems and RDoc output are provided.
* Supports parallel execution of tasks.
== Installation
=== Gem Installation
Download and install rake with the following.
gem install rake
=== Normal Installation
You can download the source tarball of the latest version of Rake from
* http://rubyforge.org/project/showfiles.php?group_id=50
Extract the tarball and run
% ruby install.rb
from its distribution directory.
== Usage
=== Simple Example
First, you must write a "Rakefile" file which contains the build rules. Here's
a simple example:
task :default => [:test]
task :test do
ruby "test/unittest.rb"
end
This Rakefile has two tasks:
* A task named "test", which - upon invocation - will run a unit test file in
Ruby.
* A task named "default". This task does nothing by itself, but it has exactly
one dependency, namely the "test" task. Invoking the "default" task will
cause Rake to invoke the "test" task as well.
Running the "rake" command without any options will cause it to run the
"default" task in the Rakefile:
% ls
Rakefile test/
% rake
(in /home/some_user/Projects/rake)
ruby test/unittest.rb
....unit test output here...
Type "rake --help" for all available options.
=== More Information
* For details on Rake's command-line invocation, read
doc/command_line_usage.rdoc[http://rake.rubyforge.org/files/doc/command_line_usage_rdoc.html]
* For details on writing Rakefiles, see
doc/rakefile.rdoc[http://rake.rubyforge.org/files/doc/rakefile_rdoc.html].
* For the original announcement of Rake, see
doc/rational.rdoc[http://rake.rubyforge.org/files/doc/rational_rdoc.html].
* For a glossary of terms, see
doc/glossary.rdoc[http://rake.rubyforge.org/files/doc/glossary_rdoc.html].
== Development
=== Source Repository
Rake is currently hosted at github. The github web page is
http://github.com/jimweirich/rake. The public git clone URL is
* git://github.com/jimweirich/rake.git
=== Running the Rake Test Suite
If you wish to run the unit and functional tests that come with Rake:
* Install the 'session' gem in order to run the functional tests.
* CD into the top project directory of rake.
* Type one of the following:
rake # If you have a version of rake installed
ruby -Ilib bin/rake # If you do not have a version of rake installed.
=== Issues and Bug Reports
Bugs, features requests and other issues can be logged at
* http://onestepback.org/redmine/projects/show/rake
You will need an account to before you can post issues. Register at
http://onestepback.org/redmine/account/register. Or you can send me
an email (at jim dot weirich at gmail dot com)
== Online Resources
=== Rake References
* Rake Documentation Home: http://docs.rubyrake.org
* Rake Project Page: http://rubyforge.org/projects/rake
* Rake API Documents: http://rake.rubyforge.org
* Rake Source Code Repo: http://github.com/jimweirich/rake
* Rake Git Repo Clone URL: git://github.com/jimweirich/rake.git
=== Presentations and Articles about Rake
* Jim Weirich's 2003 RubyConf presentation: http://onestepback.org/articles/buildingwithrake/
* Martin Fowler's article on Rake: http://martinfowler.com/articles/rake.html
== Other Make Reinvisionings ...
Rake is a late entry in the make replacement field. Here are links to
other projects with similar (and not so similar) goals.
* http://directory.fsf.org/bras.html -- Bras, one of earliest
implementations of "make in a scripting language".
* http://www.a-a-p.org -- Make in Python
* http://www.aromatic.com/tools/jam.txt -- JAM, Java Automated Make
* http://ant.apache.org -- The Ant project
* http://ppt.perl.org/commands/make/index.html -- Make from the Perl
Power Tools implementation.
* http://search.cpan.org/search?query=PerlBuildSystem -- The Perl Build System
* http://make.rubyforge.org -- Rant, another Ruby make tool.
== Credits
[<b>Ryan Dlugosz</b>] For the initial conversation that sparked Rake.
[<b>nobu.nokada@softhome.net</b>] For the initial patch for rule support.
[<b>Tilman Sauerbeck <tilman@code-monkey.de></b>] For the recursive rule patch.
== License
Rake is available under an MIT-style license.
:include: MIT-LICENSE
== Support
The Rake homepage is http://rake.rubyforge.org. You can find the Rake
RubyForge page at http://rubyforge.org/projects/rake.
Feel free to submit commits or feature requests. If you send a patch,
remember to update the corresponding unit tests. If fact, I prefer
new feature to be submitted in the form of new unit tests.
For other information, feel free to ask on the ruby-talk mailing list
(which is mirrored to comp.lang.ruby) or contact
jim dot weirich at gmail.com.
---
= Other stuff
Author:: Jim Weirich <jim.weirich@gmail.com>
Requires:: Ruby 1.8.0 or later
License:: Copyright 2003-2008 by Jim Weirich.
Released under an MIT-style license. See the LICENSE file
included in the distribution.
== Warranty
This software is provided "as is" and without any express or
implied warranties, including, without limitation, the implied
warranties of merchantibility and fitness for a particular
purpose.

View file

@ -1,169 +0,0 @@
= Rake Command Line Usage
Rake is invoked from the command line using:
% rake [options ...] [VAR=VALUE ...] [targets ...]
Options are:
[<tt><em>name</em>=<em>value</em></tt>]
Set the environment variable <em>name</em> to <em>value</em>
during the execution of the <b>rake</b> command. You can access
the value by using ENV['<em>name</em>'].
[<tt>--all</tt> (-A)]
Used in combination with the -T and -D options, will force
those options to show all the tasks, even the ones without comments.
[<tt>--backtrace</tt>{=_output_} (-n)]
Enable a full backtrace (i.e. like --trace, but without the task
tracing details). The _output_ parameter is optional, but if
specified it controls where the backtrace output is sent. If
_output_ is <tt>stdout</tt>, then backtrace output is directed to
stardard output. If _output_ is <tt>stderr</tt>, or if it is
missing, then the backtrace output is sent to standard error.
[<tt>--classic-namespace</tt> (-n)]
Import the Task, FileTask, and FileCreateTask into the top-level
scope to be compatible with older versions of Rake. Alternatively
you can include the line <code>require
'rake/classic_namespace'</code> in your Rakefile to get the
classic behavior.
[<tt>--comments</tt>]
Used in combination with the -W options to force the output to
contain commented options only. This is the reverse of
<tt>--all</tt>.
[<tt>--describe</tt> _pattern_ (-D)]
Describe the tasks (matching optional PATTERN), then exit.
[<tt>--dry-run</tt> (-n)]
Do a dry run. Print the tasks invoked and executed, but do not
actually execute any of the actions.
[<tt>--execute</tt> _code_ (-e)]
Execute some Ruby code and exit.
[<tt>--execute-print</tt> _code_ (-p)]
Execute some Ruby code, print the result, and exit.
[<tt>--execute-continue</tt> _code_ (-E)]
Execute some Ruby code, then continue with normal task processing.
[<tt>--help</tt> (-H)]
Display some help text and exit.
[<tt>--jobs</tt> _number_ (-j)]
Specifies the number of active concurrent tasks used. The
suggested value is equal to the number of CPUs. The concurrent
tasks are used to execute the <tt>multitask</tt> prerequisites.
Also see the <tt>-m</tt> option which turns all tasks into
multitasks.
Sample values:
(no -j) : unlimited concurrent tasks (standard rake behavior)
-j : 2 concurrent tasks (exact number may change)
-j 16 : 16 concurrent tasks
[<tt>--job-stats</tt> _level_]
Display job statistics at the completion of the run. By default,
this will display the requested number of active tasks (from the
-j options) and the maximum number of tasks in play at any given
time.
If the optional _level_ is <tt>history</tt>, then a complete trace
of task history will be displayed on standard output.
[<tt>--libdir</tt> _directory_ (-I)]
Add _directory_ to the list of directories searched for require.
[<tt>--multitask</tt> (-m)]
Treat all tasks as multitasks. ('make/drake' semantics)
[<tt>--nosearch</tt> (-N)]
Do not search for a Rakefile in parent directories.
[<tt>--prereqs</tt> (-P)]
Display a list of all tasks and their immediate prerequisites.
[<tt>--quiet</tt> (-q)]
Do not echo commands from FileUtils.
[<tt>--rakefile</tt> _filename_ (-f)]
Use _filename_ as the name of the rakefile. The default rakefile
names are +rakefile+ and +Rakefile+ (with +rakefile+ taking
precedence). If the rakefile is not found in the current
directory, +rake+ will search parent directories for a match. The
directory where the Rakefile is found will become the current
directory for the actions executed in the Rakefile.
[<tt>--rakelibdir</tt> _rakelibdir_ (-R)]
Auto-import any .rake files in RAKELIBDIR. (default is 'rakelib')
[<tt>--reduce-compat</tt>]
Remove the DSL commands from the Object inheritance hierarchy and
do not define top level constants. This reduces the backwards
compatibility of Rake, but allows rake to be used with software
that would otherwise have conflicting definitions.
*NOTE:* The next major version of Rake will only be able to be run
in "reduce-compat" mode.
[<tt>--require</tt> _name_ (-r)]
Require _name_ before executing the Rakefile.
[<tt>--rules</tt>]
Trace the rules resolution.
[<tt>--silent (-s)</tt>]
Like --quiet, but also suppresses the 'in directory' announcement.
[<tt>--suppress-backtrace _pattern_ </tt>]
Line matching the regular expression _pattern_ will be removed
from the backtrace output. Note that the --backtrace option is the
full backtrace without these lines suppressed.
[<tt>--system</tt> (-g)]
Use the system wide (global) rakefiles. The project Rakefile is
ignored. By default, the system wide rakefiles are used only if no
project Rakefile is found. On Unix-like system, the system wide
rake files are located in $HOME/.rake. On a windows system they
are stored in $APPDATA/Rake.
[<tt>--no-system</tt> (-G)]
Use the project level Rakefile, ignoring the system-wide (global)
rakefiles.
[<tt>--tasks</tt> <em>pattern</em> (-T)]
Display a list of the major tasks and their comments. Comments
are defined using the "desc" command. If a pattern is given, then
only tasks matching the pattern are displayed.
[<tt>--trace</tt>{=_output_} (-t)]
Turn on invoke/execute tracing. Also enable full backtrace on
errors. The _output_ parameter is optional, but if specified it
controls where the trace output is sent. If _output_ is
<tt>stdout</tt>, then trace output is directed to stardard output.
If _output_ is <tt>stderr</tt>, or if it is missing, then trace
output is sent to standard error.
[<tt>--verbose</tt> (-v)]
Echo the Sys commands to standard output.
[<tt>--version</tt> (-V)]
Display the program version and exit.
[<tt>--where</tt> <em>pattern</em> (-W)]
Display tasks that match <em>pattern</em> and the file and line
number where the task is defined. By default this option will
display all tasks, not just the tasks that have descriptions.
[<tt>--no-deprecation-warnings</tt> (-W)]
Do not display the deprecation warnings.
In addition, any command line option of the form
<em>VAR</em>=<em>VALUE</em> will be added to the environment hash
<tt>ENV</tt> and may be tested in the Rakefile.

View file

@ -1,38 +0,0 @@
# Example Rakefile -*- ruby -*-
task :default => [:main]
file "a.o" => ["a.c"] do |t|
src = t.name.sub(/\.o$/, '.c')
sh "gcc #{src} -c -o #{t.name}"
end
file "b.o" => ["b.c"] do |t|
src = t.name.sub(/\.o$/, '.c')
sh "gcc #{src} -c -o #{t.name}"
end
file "main.o" => ["main.c"] do |t|
src = t.name.sub(/\.o$/, '.c')
sh "gcc #{src} -c -o #{t.name}"
end
OBJFILES = ["a.o", "b.o", "main.o"]
task :obj => OBJFILES
file "main" => OBJFILES do |t|
sh "gcc -o #{t.name} main.o a.o b.o"
end
task :clean do
rm_f FileList['*.o']
Dir['*~'].each { |fn| rm_f fn }
end
task :clobber => [:clean] do
rm_f "main"
end
task :run => ["main"] do
sh "./main"
end

View file

@ -1,35 +0,0 @@
# Example Rakefile -*- ruby -*-
# Using the power of Ruby
task :default => [:main]
def ext(fn, newext)
fn.sub(/\.[^.]+$/, newext)
end
SRCFILES = Dir['*.c']
OBJFILES = SRCFILES.collect { |fn| ext(fn,".o") }
OBJFILES.each do |objfile|
srcfile = ext(objfile, ".c")
file objfile => [srcfile] do |t|
sh "gcc #{srcfile} -c -o #{t.name}"
end
end
file "main" => OBJFILES do |t|
sh "gcc -o #{t.name} main.o a.o b.o"
end
task :clean do
rm_f FileList['*.o']
Dir['*~'].each { |fn| rm_f fn }
end
task :clobber => [:clean] do
rm_f "main"
end
task :run => ["main"] do
sh "./main"
end

View file

@ -1,6 +0,0 @@
#include <stdio.h>
void a()
{
printf ("In function a\n");
}

View file

@ -1,6 +0,0 @@
#include <stdio.h>
void b()
{
printf ("In function b\n");
}

View file

@ -1,11 +0,0 @@
#include <stdio.h>
extern void a();
extern void b();
int main ()
{
a();
b();
return 0;
}

View file

@ -1,51 +0,0 @@
= Glossary
[<b>action</b>]
Code to be executed in order to perform a task. Actions in a
rakefile are specified in a code block (usually delimited by
+do+/+end+ pairs.
[<b>execute</b>]
When a task is executed, all of its actions are performed, in
the order they were defined. Note that unlike
<tt>invoke</tt>, <tt>execute</tt> always executes the actions
(without invoking or executing the prerequisites).
[<b>file task</b> (FileTask)]
A file task is a task whose purpose is to create a file
(which has the same name as the task). When invoked, a file
task will only execute if one or more of the following
conditions are true.
1. The associated file does not exist.
2. A prerequisite has a later time stamp than the existing file.
Because normal Tasks always have the current time as
timestamp, a FileTask that has a normal Task prerequisite
will always execute.
[<b>invoke</b>]
When a task is invoked, first we check to see if it has been
invoked before. if it has been, then nothing else is done.
If this is the first time its been invoked, then we invoke
each of its prerequisites. Finally, we check to see if we
need to execute the actions of this task by calling
<tt>needed?</tt>. Finally, if the task is needed, we execute
its actions.
NOTE: Currently prerequisites are invoked even if the task is
not needed. This may change in the future.
[<b>prerequisites</b>]
Every task has a set (possibly empty) of prerequisites. A
prerequisite P to Task T is itself a task that must be invoked
before Task T.
[<b>rule</b>]
A rule is a recipe for synthesizing a task when no task is
explicitly defined. Rules generally synthesize file tasks.
[<b>task</b> (Task)]
Basic unit of work in a rakefile. A task has a name, a set of
prerequisites and a list of actions to be performed.

View file

@ -1,591 +0,0 @@
module RDoc
module Page
FONTS = "\"Bitstream Vera Sans\", Verdana, Arial, Helvetica, sans-serif"
STYLE = <<CSS
a {
color: #00F;
text-decoration: none;
}
a:hover {
color: #77F;
text-decoration: underline;
}
body, td, p {
font-family: %fonts%;
background: #FFF;
color: #000;
margin: 0px;
font-size: small;
}
#content {
margin: 2em;
}
#description p {
margin-bottom: 0.5em;
}
.sectiontitle {
margin-top: 1em;
margin-bottom: 1em;
padding: 0.5em;
padding-left: 2em;
background: #005;
color: #FFF;
font-weight: bold;
border: 1px dotted black;
}
.attr-rw {
padding-left: 1em;
padding-right: 1em;
text-align: center;
color: #055;
}
.attr-name {
font-weight: bold;
}
.attr-desc {
}
.attr-value {
font-family: monospace;
}
.file-title-prefix {
font-size: large;
}
.file-title {
font-size: large;
font-weight: bold;
background: #005;
color: #FFF;
}
.banner {
background: #005;
color: #FFF;
border: 1px solid black;
padding: 1em;
}
.banner td {
background: transparent;
color: #FFF;
}
h1 a, h2 a, .sectiontitle a, .banner a {
color: #FF0;
}
h1 a:hover, h2 a:hover, .sectiontitle a:hover, .banner a:hover {
color: #FF7;
}
.dyn-source {
display: none;
background: #FFE;
color: #000;
border: 1px dotted black;
margin: 0.5em 2em 0.5em 2em;
padding: 0.5em;
}
.dyn-source .cmt {
color: #00F;
font-style: italic;
}
.dyn-source .kw {
color: #070;
font-weight: bold;
}
.method {
margin-left: 1em;
margin-right: 1em;
margin-bottom: 1em;
}
.description pre {
padding: 0.5em;
border: 1px dotted black;
background: #FFE;
}
.method .title {
font-family: monospace;
font-size: large;
border-bottom: 1px dashed black;
margin-bottom: 0.3em;
padding-bottom: 0.1em;
}
.method .description, .method .sourcecode {
margin-left: 1em;
}
.description p, .sourcecode p {
margin-bottom: 0.5em;
}
.method .sourcecode p.source-link {
text-indent: 0em;
margin-top: 0.5em;
}
.method .aka {
margin-top: 0.3em;
margin-left: 1em;
font-style: italic;
text-indent: 2em;
}
h1 {
padding: 1em;
border: 1px solid black;
font-size: x-large;
font-weight: bold;
color: #FFF;
background: #007;
}
h2 {
padding: 0.5em 1em 0.5em 1em;
border: 1px solid black;
font-size: large;
font-weight: bold;
color: #FFF;
background: #009;
}
h3, h4, h5, h6 {
padding: 0.2em 1em 0.2em 1em;
border: 1px dashed black;
color: #000;
background: #AAF;
}
.sourcecode > pre {
padding: 0.5em;
border: 1px dotted black;
background: #FFE;
}
CSS
XHTML_PREAMBLE = %{<?xml version="1.0" encoding="%charset%"?>
<!DOCTYPE html
PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
}
HEADER = XHTML_PREAMBLE + <<ENDHEADER
<html>
<head>
<title>%title%</title>
<meta http-equiv="Content-Type" content="text/html; charset=%charset%" />
<link rel="stylesheet" href="%style_url%" type="text/css" media="screen" />
<script language="JavaScript" type="text/javascript">
// <![CDATA[
function toggleSource( id )
{
var elem
var link
if( document.getElementById )
{
elem = document.getElementById( id )
link = document.getElementById( "l_" + id )
}
else if ( document.all )
{
elem = eval( "document.all." + id )
link = eval( "document.all.l_" + id )
}
else
return false;
if( elem.style.display == "block" )
{
elem.style.display = "none"
link.innerHTML = "show source"
}
else
{
elem.style.display = "block"
link.innerHTML = "hide source"
}
}
function openCode( url )
{
window.open( url, "SOURCE_CODE", "width=400,height=400,scrollbars=yes" )
}
// ]]>
</script>
</head>
<body>
ENDHEADER
FILE_PAGE = <<HTML
<table border='0' cellpadding='0' cellspacing='0' width="100%" class='banner'>
<tr><td>
<table width="100%" border='0' cellpadding='0' cellspacing='0'><tr>
<td class="file-title" colspan="2"><span class="file-title-prefix">File</span><br />%short_name%</td>
<td align="right">
<table border='0' cellspacing="0" cellpadding="2">
<tr>
<td>Path:</td>
<td>%full_path%
IF:cvsurl
&nbsp;(<a href="%cvsurl%">CVS</a>)
ENDIF:cvsurl
</td>
</tr>
<tr>
<td>Modified:</td>
<td>%dtm_modified%</td>
</tr>
</table>
</td></tr>
</table>
</td></tr>
</table><br>
HTML
###################################################################
CLASS_PAGE = <<HTML
<table width="100%" border='0' cellpadding='0' cellspacing='0' class='banner'><tr>
<td class="file-title"><span class="file-title-prefix">%classmod%</span><br />%full_name%</td>
<td align="right">
<table cellspacing=0 cellpadding=2>
<tr valign="top">
<td>In:</td>
<td>
START:infiles
HREF:full_path_url:full_path:
IF:cvsurl
&nbsp;(<a href="%cvsurl%">CVS</a>)
ENDIF:cvsurl
END:infiles
</td>
</tr>
IF:parent
<tr>
<td>Parent:</td>
<td>
IF:par_url
<a href="%par_url%">
ENDIF:par_url
%parent%
IF:par_url
</a>
ENDIF:par_url
</td>
</tr>
ENDIF:parent
</table>
</td>
</tr>
</table>
HTML
###################################################################
METHOD_LIST = <<HTML
<div id="content">
IF:diagram
<table cellpadding='0' cellspacing='0' border='0' width="100%"><tr><td align="center">
%diagram%
</td></tr></table>
ENDIF:diagram
IF:description
<div class="description">%description%</div>
ENDIF:description
IF:requires
<div class="sectiontitle">Required Files</div>
<ul>
START:requires
<li>HREF:aref:name:</li>
END:requires
</ul>
ENDIF:requires
IF:toc
<div class="sectiontitle">Contents</div>
<ul>
START:toc
<li><a href="#%href%">%secname%</a></li>
END:toc
</ul>
ENDIF:toc
IF:methods
<div class="sectiontitle">Methods</div>
<ul>
START:methods
<li>HREF:aref:name:</li>
END:methods
</ul>
ENDIF:methods
IF:includes
<div class="sectiontitle">Included Modules</div>
<ul>
START:includes
<li>HREF:aref:name:</li>
END:includes
</ul>
ENDIF:includes
START:sections
IF:sectitle
<div class="sectiontitle"><a nem="%secsequence%">%sectitle%</a></div>
IF:seccomment
<div class="description">
%seccomment%
</div>
ENDIF:seccomment
ENDIF:sectitle
IF:classlist
<div class="sectiontitle">Classes and Modules</div>
%classlist%
ENDIF:classlist
IF:constants
<div class="sectiontitle">Constants</div>
<table border='0' cellpadding='5'>
START:constants
<tr valign='top'>
<td class="attr-name">%name%</td>
<td>=</td>
<td class="attr-value">%value%</td>
</tr>
IF:desc
<tr valign='top'>
<td>&nbsp;</td>
<td colspan="2" class="attr-desc">%desc%</td>
</tr>
ENDIF:desc
END:constants
</table>
ENDIF:constants
IF:attributes
<div class="sectiontitle">Attributes</div>
<table border='0' cellpadding='5'>
START:attributes
<tr valign='top'>
<td class='attr-rw'>
IF:rw
[%rw%]
ENDIF:rw
</td>
<td class='attr-name'>%name%</td>
<td class='attr-desc'>%a_desc%</td>
</tr>
END:attributes
</table>
ENDIF:attributes
IF:method_list
START:method_list
IF:methods
<div class="sectiontitle">%type% %category% methods</div>
START:methods
<div class="method">
<div class="title">
IF:callseq
<a name="%aref%"></a><b>%callseq%</b>
ENDIF:callseq
IFNOT:callseq
<a name="%aref%"></a><b>%name%</b>%params%
ENDIF:callseq
IF:codeurl
[ <a href="javascript:openCode('%codeurl%')">source</a> ]
ENDIF:codeurl
</div>
IF:m_desc
<div class="description">
%m_desc%
</div>
ENDIF:m_desc
IF:aka
<div class="aka">
This method is also aliased as
START:aka
<a href="%aref%">%name%</a>
END:aka
</div>
ENDIF:aka
IF:sourcecode
<div class="sourcecode">
<p class="source-link">[ <a href="javascript:toggleSource('%aref%_source')" id="l_%aref%_source">show source</a> ]</p>
<div id="%aref%_source" class="dyn-source">
<pre>
%sourcecode%
</pre>
</div>
</div>
ENDIF:sourcecode
</div>
END:methods
ENDIF:methods
END:method_list
ENDIF:method_list
END:sections
</div>
HTML
FOOTER = <<ENDFOOTER
</body>
</html>
ENDFOOTER
BODY = HEADER + <<ENDBODY
!INCLUDE! <!-- banner header -->
<div id="bodyContent">
#{METHOD_LIST}
</div>
#{FOOTER}
ENDBODY
########################## Source code ##########################
SRC_PAGE = XHTML_PREAMBLE + <<HTML
<html>
<head><title>%title%</title>
<meta http-equiv="Content-Type" content="text/html; charset=%charset%">
<style>
.ruby-comment { color: green; font-style: italic }
.ruby-constant { color: #4433aa; font-weight: bold; }
.ruby-identifier { color: #222222; }
.ruby-ivar { color: #2233dd; }
.ruby-keyword { color: #3333FF; font-weight: bold }
.ruby-node { color: #777777; }
.ruby-operator { color: #111111; }
.ruby-regexp { color: #662222; }
.ruby-value { color: #662222; font-style: italic }
.kw { color: #3333FF; font-weight: bold }
.cmt { color: green; font-style: italic }
.str { color: #662222; font-style: italic }
.re { color: #662222; }
</style>
</head>
<body bgcolor="white">
<pre>%code%</pre>
</body>
</html>
HTML
########################## Index ################################
FR_INDEX_BODY = <<HTML
!INCLUDE!
HTML
FILE_INDEX = XHTML_PREAMBLE + <<HTML
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=%charset%">
<style>
<!--
body {
background-color: #EEE;
font-family: #{FONTS};
color: #000;
margin: 0px;
}
.banner {
background: #005;
color: #FFF;
padding: 0.2em;
font-size: small;
font-weight: bold;
text-align: center;
}
.entries {
margin: 0.25em 1em 0 1em;
font-size: x-small;
}
a {
color: #00F;
text-decoration: none;
white-space: nowrap;
}
a:hover {
color: #77F;
text-decoration: underline;
}
-->
</style>
<base target="docwin">
</head>
<body>
<div class="banner">%list_title%</div>
<div class="entries">
START:entries
<a href="%href%">%name%</a><br>
END:entries
</div>
</body></html>
HTML
CLASS_INDEX = FILE_INDEX
METHOD_INDEX = FILE_INDEX
INDEX = XHTML_PREAMBLE + <<HTML
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<title>%title%</title>
<meta http-equiv="Content-Type" content="text/html; charset=%charset%">
</head>
<frameset cols="20%,*">
<frameset rows="15%,35%,50%">
<frame src="fr_file_index.html" title="Files" name="Files" />
<frame src="fr_class_index.html" name="Classes" />
<frame src="fr_method_index.html" name="Methods" />
</frameset>
IF:inline_source
<frame src="%initial_page%" name="docwin">
ENDIF:inline_source
IFNOT:inline_source
<frameset rows="80%,20%">
<frame src="%initial_page%" name="docwin">
<frame src="blank.html" name="source">
</frameset>
ENDIF:inline_source
<noframes>
<body bgcolor="white">
Click <a href="html/index.html">here</a> for a non-frames
version of this page.
</body>
</noframes>
</frameset>
</html>
HTML
end
end

View file

@ -1,127 +0,0 @@
= Original Prototype Rake
This is the original 100 line prototype rake program.
---
#!/usr/bin/env ruby
require 'ftools'
class Task
TASKS = Hash.new
attr_reader :prerequisites
def initialize(task_name)
@name = task_name
@prerequisites = []
@actions = []
end
def enhance(deps=nil, &block)
@prerequisites |= deps if deps
@actions << block if block_given?
self
end
def name
@name.to_s
end
def invoke
@prerequisites.each { |n| Task[n].invoke }
execute if needed?
end
def execute
return if @triggered
@triggered = true
@actions.collect { |act| result = act.call(self) }.last
end
def needed?
true
end
def timestamp
Time.now
end
class << self
def [](task_name)
TASKS[intern(task_name)] or fail "Don't know how to rake #{task_name}"
end
def define_task(args, &block)
case args
when Hash
fail "Too Many Target Names: #{args.keys.join(' ')}" if args.size > 1
fail "No Task Name Given" if args.size < 1
task_name = args.keys[0]
deps = args[task_name]
else
task_name = args
deps = []
end
deps = deps.collect {|d| intern(d) }
get(task_name).enhance(deps, &block)
end
def get(task_name)
name = intern(task_name)
TASKS[name] ||= self.new(name)
end
def intern(task_name)
(Symbol === task_name) ? task_name : task_name.intern
end
end
end
class FileTask < Task
def needed?
return true unless File.exist?(name)
latest_prereq = @prerequisites.collect{|n| Task[n].timestamp}.max
return false if latest_prereq.nil?
timestamp < latest_prereq
end
def timestamp
File.new(name.to_s).mtime
end
end
def task(args, &block)
Task.define_task(args, &block)
end
def file(args, &block)
FileTask.define_task(args, &block)
end
def sys(cmd)
puts cmd
system(cmd) or fail "Command Failed: [#{cmd}]"
end
def rake
begin
here = Dir.pwd
while ! File.exist?("Rakefile")
Dir.chdir("..")
fail "No Rakefile found" if Dir.pwd == here
here = Dir.pwd
end
puts "(in #{Dir.pwd})"
load "./Rakefile"
ARGV.push("default") if ARGV.size == 0
ARGV.each { |task_name| Task[task_name].invoke }
rescue Exception => ex
puts "rake aborted ... #{ex.message}"
puts ex.backtrace.find {|str| str =~ /Rakefile/ } || ""
end
end
if __FILE__ == $0 then
rake
end

View file

@ -1,557 +0,0 @@
= Rakefile Format (as of version 0.8.7)
First of all, there is no special format for a Rakefile. A Rakefile
contains executable Ruby code. Anything legal in a ruby script is
allowed in a Rakefile.
Now that we understand there is no special syntax in a Rakefile, there
are some conventions that are used in a Rakefile that are a little
unusual in a typical Ruby program. Since a Rakefile is tailored to
specifying tasks and actions, the idioms used in a Rakefile are
designed to support that.
So, what goes into a Rakefile?
== Tasks
Tasks are the main unit of work in a Rakefile. Tasks have a name
(usually given as a symbol or a string), a list of prerequisites (more
symbols or strings) and a list of actions (given as a block).
=== Simple Tasks
A task is declared by using the +task+ method. +task+ takes a single
parameter that is the name of the task.
task :name
=== Tasks with Prerequisites
Any prerequisites are given as a list (enclosed in square brackets)
following the name and an arrow (=>).
task :name => [:prereq1, :prereq2]
<b>NOTE:</b> Although this syntax looks a little funky, it is legal
Ruby. We are constructing a hash where the key is :name and the value
for that key is the list of prerequisites. It is equivalent to the
following ...
hash = Hash.new
hash[:name] = [:prereq1, :prereq2]
task(hash)
=== Tasks with Actions
Actions are defined by passing a block to the +task+ method. Any Ruby
code can be placed in the block. The block may reference the task
object via the block parameter.
task :name => [:prereq1, :prereq2] do |t|
# actions (may reference t)
end
=== Multiple Definitions
A task may be specified more than once. Each specification adds its
prerequisites and actions to the existing definition. This allows one
part of a rakefile to specify the actions and a different rakefile
(perhaps separately generated) to specify the dependencies.
For example, the following is equivalent to the single task
specification given above.
task :name
task :name => [:prereq1]
task :name => [:prereq2]
task :name do |t|
# actions
end
== File Tasks
Some tasks are designed to create a file from one or more other files.
Tasks that generate these files may be skipped if the file already
exists. File tasks are used to specify file creation tasks.
File tasks are declared using the +file+ method (instead of the +task+
method). In addition, file tasks are usually named with a string
rather than a symbol.
The following file task creates a executable program (named +prog+)
given two object files name <tt>a.o</tt> and <tt>b.o</tt>. The tasks
for creating <tt>a.o</tt> and <tt>b.o</tt> are not shown.
file "prog" => ["a.o", "b.o"] do |t|
sh "cc -o #{t.name} #{t.prerequisites.join(' ')}"
end
== Directory Tasks
It is common to need to create directories upon demand. The
+directory+ convenience method is a short-hand for creating a FileTask
that creates the directory. For example, the following declaration
...
directory "testdata/examples/doc"
is equivalent to ...
file "testdata" do |t| mkdir t.name end
file "testdata/examples" do |t| mkdir t.name end
file "testdata/examples/doc" do |t| mkdir t.name end
The +directory+ method does not accept prerequisites or actions, but
both prerequisites and actions can be added later. For example ...
directory "testdata"
file "testdata" => ["otherdata"]
file "testdata" do
cp Dir["standard_data/*.data"], "testdata"
end
== Tasks with Parallel Prerequisites
Rake allows parallel execution of prerequisites using the following syntax:
multitask :copy_files => [:copy_src, :copy_doc, :copy_bin] do
puts "All Copies Complete"
end
In this example, +copy_files+ is a normal rake task. Its actions are
executed whenever all of its prerequisites are done. The big
difference is that the prerequisites (+copy_src+, +copy_bin+ and
+copy_doc+) are executed in parallel. Each of the prerequisites are
run in their own Ruby thread, possibly allowing faster overall runtime.
=== Secondary Prerequisites
If any of the primary prerequisites of a multitask have common secondary
prerequisites, all of the primary/parallel prerequisites will wait
until the common prerequisites have been run.
For example, if the <tt>copy_<em>xxx</em></tt> tasks have the
following prerequisites:
task :copy_src => [:prep_for_copy]
task :copy_bin => [:prep_for_copy]
task :copy_doc => [:prep_for_copy]
Then the +prep_for_copy+ task is run before starting all the copies in
parallel. Once +prep_for_copy+ is complete, +copy_src+, +copy_bin+,
and +copy_doc+ are all run in parallel. Note that +prep_for_copy+ is
run only once, even though it is referenced in multiple threads.
=== Thread Safety
The Rake internal data structures are thread-safe with respect
to the multitask parallel execution, so there is no need for the user
to do extra synchronization for Rake's benefit. However, if there are
user data structures shared between the parallel prerequisites, the
user must do whatever is necessary to prevent race conditions.
== Tasks with Arguments
Prior to version 0.8.0, rake was only able to handle command line
arguments of the form NAME=VALUE that were passed into Rake via the
ENV hash. Many folks had asked for some kind of simple command line
arguments, perhaps using "--" to separate regular task names from
argument values on the command line. The problem is that there was no
easy way to associate positional arguments on the command line with
different tasks. Suppose both tasks :a and :b expect a command line
argument: does the first value go with :a? What if :b is run first?
Should it then get the first command line argument.
Rake 0.8.0 solves this problem by explicitly passing values directly
to the tasks that need them. For example, if I had a release task
that required a version number, I could say:
rake release[0.8.2]
And the string "0.8.2" will be passed to the :release task. Multiple
arguments can be passed by separating them with a comma, for example:
rake name[john,doe]
Just a few words of caution. The rake task name and its arguments
need to be a single command line argument to rake. This generally
means no spaces. If spaces are needed, then the entire rake +
argument string should be quoted. Something like this:
rake "name[billy bob, smith]"
(Quoting rules vary between operating systems and shells, so make sure
you consult the proper docs for your OS/shell).
=== Tasks Arguments and the Environment
Task argument values can also be picked up from the environment. For
example, if the "release" task expected a parameter named
"release_version", then either
rake release[0.8.2]
or
RELEASE_VERSION rake release
will work. Environment variable names must either match the task
parameter exactly, or match an all-uppercase version of the task
parameter.
=== Tasks that Expect Parameters
Parameters are only given to tasks that are setup to expect them. In
order to handle named parameters, the task declaration syntax for
tasks has been extended slightly.
For example, a task that needs a first name and last name might be
declared as:
task :name, [:first_name, :last_name]
The first argument is still the name of the task (:name in this case).
The next two arguments are the names of the parameters expected by
:name in an array (:first_name and :last_name in the example).
To access the values of the parameters, the block defining the task
behaviour can now accept a second parameter:
task :name, [:first_name, :last_name] do |t, args|
puts "First name is #{args.first_name}"
puts "Last name is #{args.last_name}"
end
The first argument of the block "t" is always bound to the current
task object. The second argument "args" is an open-struct like object
that allows access to the task arguments. Extra command line
arguments to a task are ignored. Missing command line arguments are
picked up from matching environment variables. If there are no
matching environment variables, they are given the nil value.
If you wish to specify default values for the arguments, you can use
the with_defaults method in the task body. Here is the above example
where we specify default values for the first and last names:
task :name, [:first_name, :last_name] do |t, args|
args.with_defaults(:first_name => "John", :last_name => "Dough")
puts "First name is #{args.first_name}"
puts "Last name is #{args.last_name}"
end
=== Tasks that Expect Parameters and Have Prerequisites
Tasks that use parameters have a slightly different format for
prerequisites. Use the arrow notation to indicate the prerequisites
for tasks with arguments. For example:
task :name, [:first_name, :last_name] => [:pre_name] do |t, args|
args.with_defaults(:first_name => "John", :last_name => "Dough")
puts "First name is #{args.first_name}"
puts "Last name is #{args.last_name}"
end
=== Deprecated Task Parameters Format
There is an older format for declaring task parameters that omitted
the task argument array and used the :needs keyword to introduce the
dependencies. That format is still supported for compatibility, but
is not recommended for use. The older format may be dropped in future
versions of rake.
== Accessing Task Programmatically
Sometimes it is useful to manipulate tasks programmatically in a
Rakefile. To find a task object, use the <tt>:[]</tt> operator on the
<tt>Rake::Task</tt>.
=== Programmatic Task Example
For example, the following Rakefile defines two tasks. The :doit task
simply prints a simple "DONE" message. The :dont class will lookup
the doit class and remove (clear) all of its prerequisites and
actions.
task :doit do
puts "DONE"
end
task :dont do
Rake::Task[:doit].clear
end
Running this example:
$ rake doit
(in /Users/jim/working/git/rake/x)
DONE
$ rake dont doit
(in /Users/jim/working/git/rake/x)
$
The ability to programmatically manipulate tasks gives rake very
powerful meta-programming capabilities w.r.t. task execution, but
should be used with cation.
== Rules
When a file is named as a prerequisite, but does not have a file task
defined for it, Rake will attempt to synthesize a task by looking at a
list of rules supplied in the Rakefile.
Suppose we were trying to invoke task "mycode.o", but no task is
defined for it. But the rakefile has a rule that look like this ...
rule '.o' => ['.c'] do |t|
sh "cc #{t.source} -c -o #{t.name}"
end
This rule will synthesize any task that ends in ".o". It has a
prerequisite a source file with an extension of ".c" must exist. If
Rake is able to find a file named "mycode.c", it will automatically
create a task that builds "mycode.o" from "mycode.c".
If the file "mycode.c" does not exist, rake will attempt
to recursively synthesize a rule for it.
When a task is synthesized from a rule, the +source+ attribute of the
task is set to the matching source file. This allows us to write
rules with actions that reference the source file.
=== Advanced Rules
Any regular expression may be used as the rule pattern. Additionally,
a proc may be used to calculate the name of the source file. This
allows for complex patterns and sources.
The following rule is equivalent to the example above.
rule( /\.o$/ => [
proc {|task_name| task_name.sub(/\.[^.]+$/, '.c') }
]) do |t|
sh "cc #{t.source} -c -o #{t.name}"
end
<b>NOTE:</b> Because of a _quirk_ in Ruby syntax, parenthesis are
required on *rule* when the first argument is a regular expression.
The following rule might be used for Java files ...
rule '.java' => [
proc { |tn| tn.sub(/\.class$/, '.java').sub(/^classes\//, 'src/') }
] do |t|
java_compile(t.source, t.name)
end
<b>NOTE:</b> +java_compile+ is a hypothetical method that invokes the
java compiler.
== Importing Dependencies
Any ruby file (including other rakefiles) can be included with a
standard Ruby +require+ command. The rules and declarations in the
required file are just added to the definitions already accumulated.
Because the files are loaded _before_ the rake targets are evaluated,
the loaded files must be "ready to go" when the rake command is
invoked. This make generated dependency files difficult to use. By
the time rake gets around to updating the dependencies file, it is too
late to load it.
The +Rake.import+ command addresses this by specifying a file to be
loaded _after_ the main rakefile is loaded, but _before_ any targets
on the command line are invoked. In addition, if the file name
matches an explicit task, that task is invoked before loading the
file. This allows dependency files to be generated and used in a
single rake command invocation.
<b>NOTE:</b> Starting in Rake version 0.9.0, the top level +import+
command is deprecated and we recommend using the scoped
"+Rake.import+" command mentioned above. Future versions of Rake will
drop support for the top level +import+ command.
=== Example:
require 'rake/loaders/makefile'
file ".depends.mf" => [SRC_LIST] do |t|
sh "makedepend -f- -- #{CFLAGS} -- #{t.prerequisites} > #{t.name}"
end
Rake.import ".depends.mf"
If ".depends" does not exist, or is out of date w.r.t. the source
files, a new ".depends" file is generated using +makedepend+ before
loading.
== Comments
Standard Ruby comments (beginning with "#") can be used anywhere it is
legal in Ruby source code, including comments for tasks and rules.
However, if you wish a task to be described using the "-T" switch,
then you need to use the +desc+ command to describe the task.
=== Example:
desc "Create a distribution package"
task :package => [ ... ] do ... end
The "-T" switch (or "--tasks" if you like to spell things out) will
display a list of tasks that have a description. If you use +desc+ to
describe your major tasks, you have a semi-automatic way of generating
a summary of your Rake file.
traken$ rake -T
(in /home/.../rake)
rake clean # Remove any temporary products.
rake clobber # Remove any generated file.
rake clobber_rdoc # Remove rdoc products
rake contrib_test # Run tests for contrib_test
rake default # Default Task
rake install # Install the application
rake lines # Count lines in the main rake file
rake rdoc # Build the rdoc HTML Files
rake rerdoc # Force a rebuild of the RDOC files
rake test # Run tests
rake testall # Run all test targets
Only tasks with descriptions will be displayed with the "-T" switch.
Use "-P" (or "--prereqs") to get a list of all tasks and their
prerequisites.
== Namespaces
As projects grow (and along with it, the number of tasks), it is
common for task names to begin to clash. For example, if you might
have a main program and a set of sample programs built by a single
Rakefile. By placing the tasks related to the main program in one
namespace, and the tasks for building the sample programs in a
different namespace, the task names will not will not interfere with
each other.
For example:
namespace "main" do
task :build do
# Build the main program
end
end
namespace "samples" do
task :build do
# Build the sample programs
end
end
task :build => ["main:build", "samples:build"]
Referencing a task in a separate namespace can be achieved by
prefixing the task name with the namespace and a colon
(e.g. "main:build" refers to the :build task in the +main+ namespace).
Nested namespaces are supported, so
Note that the name given in the +task+ command is always the unadorned
task name without any namespace prefixes. The +task+ command always
defines a task in the current namespace.
=== FileTasks
File task names are not scoped by the namespace command. Since the
name of a file task is the name of an actual file in the file system,
it makes little sense to include file task names in name space.
Directory tasks (created by the +directory+ command) are a type of
file task and are also not affected by namespaces.
=== Name Resolution
When looking up a task name, rake will start with the current
namespace and attempt to find the name there. If it fails to find a
name in the current namespace, it will search the parent namespaces
until a match is found (or an error occurs if there is no match).
The "rake" namespace is a special implicit namespace that refers to
the toplevel names.
If a task name begins with a "^" character, the name resolution will
start in the parent namespace. Multiple "^" characters are allowed.
Here is an example file with multiple :run tasks and how various names
resolve in different locations.
task :run
namespace "one" do
task :run
namespace "two" do
task :run
# :run => "one:two:run"
# "two:run" => "one:two:run"
# "one:two:run" => "one:two:run"
# "one:run" => "one:run"
# "^run" => "one:run"
# "^^run" => "rake:run" (the top level task)
# "rake:run" => "rake:run" (the top level task)
end
# :run => "one:run"
# "two:run" => "one:two:run"
# "^run" => "rake:run"
end
# :run => "rake:run"
# "one:run" => "one:run"
# "one:two:run" => "one:two:run"
== FileLists
FileLists are the way Rake manages lists of files. You can treat a
FileList as an array of strings for the most part, but FileLists
support some additional operations.
=== Creating a FileList
Creating a file list is easy. Just give it the list of file names:
fl = FileList['file1.rb', file2.rb']
Or give it a glob pattern:
fl = FileList['*.rb']
== Odds and Ends
=== do/end versus { }
Blocks may be specified with either a +do+/+end+ pair, or with curly
braces in Ruby. We _strongly_ recommend using +do+/+end+ to specify the
actions for tasks and rules. Because the rakefile idiom tends to
leave off parentheses on the task/file/rule methods, unusual
ambiguities can arise when using curly braces.
For example, suppose that the method +object_files+ returns a list of
object files in a project. Now we use +object_files+ as the
prerequisites in a rule specified with actions in curly braces.
# DON'T DO THIS!
file "prog" => object_files {
# Actions are expected here (but it doesn't work)!
}
Because curly braces have a higher precedence than +do+/+end+, the
block is associated with the +object_files+ method rather than the
+file+ method.
This is the proper way to specify the task ...
# THIS IS FINE
file "prog" => object_files do
# Actions go here
end
----
== See
* README.rdoc -- Main documentation for Rake.

View file

@ -1,151 +0,0 @@
= Why rake?
Ok, let me state from the beginning that I never intended to write this
code. I'm not convinced it is useful, and I'm not convinced anyone
would even be interested in it. All I can say is that Why's onion truck
must by been passing through the Ohio valley.
What am I talking about? ... A Ruby version of Make.
See, I can sense you cringing already, and I agree. The world certainly
doesn't need yet another reworking of the "make" program. I mean, we
already have "ant". Isn't that enough?
It started yesterday. I was helping a coworker fix a problem in one of
the Makefiles we use in our project. Not a particularly tough problem,
but during the course of the conversation I began lamenting some of the
shortcomings of make. In particular, in one of my makefiles I wanted to
determine the name of a file dynamically and had to resort to some
simple scripting (in Ruby) to make it work. "Wouldn't it be nice if you
could just use Ruby inside a Makefile" I said.
My coworker (a recent convert to Ruby) agreed, but wondered what it
would look like. So I sketched the following on the whiteboard...
"What if you could specify the make tasks in Ruby, like this ..."
task "build" do
java_compile(...args, etc ...)
end
"The task function would register "build" as a target to be made,
and the block would be the action executed whenever the build
system determined that it was time to do the build target."
We agreed that would be cool, but writing make from scratch would be WAY
too much work. And that was the end of that!
... Except I couldn't get the thought out of my head. What exactly
would be needed to make the about syntax work as a make file? Hmmm, you
would need to register the tasks, you need some way of specifying
dependencies between tasks, and some way of kicking off the process.
Hey! What if we did ... and fifteen minutes later I had a working
prototype of Ruby make, complete with dependencies and actions.
I showed the code to my coworker and we had a good laugh. It was just
about a page worth of code that reproduced an amazing amount of the
functionality of make. We were both truly stunned with the power of
Ruby.
But it didn't do everything make did. In particular, it didn't have
timestamp based file dependencies (where a file is rebuilt if any of its
prerequisite files have a later timestamp). Obviously THAT would be a
pain to add and so Ruby Make would remain an interesting experiment.
... Except as I walked back to my desk, I started thinking about what
file based dependencies would really need. Rats! I was hooked again,
and by adding a new class and two new methods, file/timestamp
dependencies were implemented.
Ok, now I was really hooked. Last night (during CSI!) I massaged the
code and cleaned it up a bit. The result is a bare-bones replacement
for make in exactly 100 lines of code.
For the curious, you can see it at ...
* doc/proto_rake.rdoc
Oh, about the name. When I wrote the example Ruby Make task on my
whiteboard, my coworker exclaimed "Oh! I have the perfect name: Rake ...
Get it? Ruby-Make. Rake!" He said he envisioned the tasks as leaves
and Rake would clean them up ... or something like that. Anyways, the
name stuck.
Some quick examples ...
A simple task to delete backup files ...
task :clean do
Dir['*~'].each {|fn| rm fn rescue nil}
end
Note that task names are symbols (they are slightly easier to type
than quoted strings ... but you may use quoted string if you would
rather). Rake makes the methods of the FileUtils module directly
available, so we take advantage of the <tt>rm</tt> command. Also note
the use of "rescue nil" to trap and ignore errors in the <tt>rm</tt>
command.
To run it, just type "rake clean". Rake will automatically find a
Rakefile in the current directory (or above!) and will invoke the
targets named on the command line. If there are no targets explicitly
named, rake will invoke the task "default".
Here's another task with dependencies ...
task :clobber => [:clean] do
rm_r "tempdir"
end
Task :clobber depends upon task :clean, so :clean will be run before
:clobber is executed.
Files are specified by using the "file" command. It is similar to the
task command, except that the task name represents a file, and the task
will be run only if the file doesn't exist, or if its modification time
is earlier than any of its prerequisites.
Here is a file based dependency that will compile "hello.cc" to
"hello.o".
file "hello.cc"
file "hello.o" => ["hello.cc"] do |t|
srcfile = t.name.sub(/\.o$/, ".cc")
sh %{g++ #{srcfile} -c -o #{t.name}}
end
I normally specify file tasks with string (rather than symbols). Some
file names can't be represented by symbols. Plus it makes the
distinction between them more clear to the casual reader.
Currently writing a task for each and every file in the project would be
tedious at best. I envision a set of libraries to make this job
easier. For instance, perhaps something like this ...
require 'rake/ctools'
Dir['*.c'].each do |fn|
c_source_file(fn)
end
where "c_source_file" will create all the tasks need to compile all the
C source files in a directory. Any number of useful libraries could be
created for rake.
That's it. There's no documentation (other than whats in this
message). Does this sound interesting to anyone? If so, I'll continue
to clean it up and write it up and publish it on RAA. Otherwise, I'll
leave it as an interesting exercise and a tribute to the power of Ruby.
Why /might/ rake be interesting to Ruby programmers. I don't know,
perhaps ...
* No weird make syntax (only weird Ruby syntax :-)
* No need to edit or read XML (a la ant)
* Platform independent build scripts.
* Will run anywhere Ruby exists, so no need to have "make" installed.
If you stay away from the "sys" command and use things like
'ftools', you can have a perfectly platform independent
build script. Also rake is only 100 lines of code, so it can
easily be packaged along with the rest of your code.
So ... Sorry for the long rambling message. Like I said, I never
intended to write this code at all.

Some files were not shown because too many files have changed in this diff Show more