core/zed.rb
# TODO: Finish adding some layer structure to the core library. This file is a
# complete mess at the moment.
#
# A proper layered structure for the core library would enable and encourage
# composition and make visible where pieces are loosely or tightly coupled. A
# reasonable layer for something as complex as the Ruby core library would be:
#
# 1. Simple values like Fixnum, Bignum, Float;
# 2. Basic data structures like Tuple, ByteArray, Array, Hash;
# 3. More complicated values like String, Regexp, Complex, Rational;
# 4. Fairly simple system-dependent facilities like IO, File, Process;
# 5. Even more complex facilities like FFI;
# 6. Something like Socket that composes multiple lower layers;
# 7. A complex facility like CodeLoader or RubyGems.
# The virtual concatenation file of the files given on command line (or
# from $stdin if no files were given.) Usable like an IO.
ARGF = Rubinius::ARGFClass.new
class Module
def alias_method(new_name, current_name)
new_name = Rubinius::Type.coerce_to_symbol(new_name)
current_name = Rubinius::Type.coerce_to_symbol(current_name)
mod, entry = lookup_method(current_name, true, false)
if entry
Rubinius::VM.reset_method_cache self, new_name
method_visibility = visibility_for_aliased_method(new_name, entry.visibility)
# If we're aliasing a method we contain, just reference it directly, no
# need for the alias wrapper
#
# The 'and entry.get_method' is there to force us to use the alias code
# when the original method exists only to change the visibility of a
# parent method.
if mod == self and entry.get_method
@method_table.store new_name, entry.method_id, entry.method,
entry.scope, entry.serial, method_visibility
else
@method_table.alias new_name, method_visibility, current_name,
entry.get_method, mod
end
if ai = Rubinius::Type.singleton_class_object(self)
Rubinius.privately do
ai.singleton_method_added new_name
end
else
method_added new_name
end
self
else
if ai = Rubinius::Type.singleton_class_object(self)
raise NameError, "Unable to find '#{current_name}' for object #{ai.inspect}"
else
thing = Rubinius::Type.object_kind_of?(self, Class) ? "class" : "module"
raise NameError, "undefined method `#{current_name}' for #{thing} `#{self.name}'"
end
end
end
private :alias_method
def const_set(name, value)
name = Rubinius::Type.coerce_to_constant_name name
Rubinius.check_frozen
if Rubinius::Type.object_kind_of? value, Module
Rubinius::Type.set_module_name value, name, self
if Object.equal? self
value.constant_table.each do |n, c, _|
if Rubinius::Type.object_kind_of? c, Module and !c.name
Rubinius::Type.set_module_name c, n, value
end
end
end
end
@constant_table.store(name, value, :public)
Rubinius.inc_global_serial
return value
end
def module_function(*args)
if kind_of? Class
raise TypeError, "invalid receiver class #{__class__}, expected Module"
end
if args.empty?
vs = Rubinius::VariableScope.of_sender
vs.method_visibility = :module
else
sc = Rubinius::Type.object_singleton_class(self)
args.each do |meth|
method_name = Rubinius::Type.coerce_to_symbol meth
Rubinius::VM.reset_method_cache sc, method_name
mod, entry = lookup_method(method_name)
sc.method_table.store method_name, entry.method_id, entry.method,
entry.scope, entry.serial, :public
set_visibility method_name, :private
end
end
return self
end
private :module_function
def public(*args)
if args.empty?
vs = Rubinius::VariableScope.of_sender
vs.method_visibility = nil
else
args.each { |meth| set_visibility(meth, :public) }
end
self
end
private :public
def private(*args)
if args.empty?
vs = Rubinius::VariableScope.of_sender
vs.method_visibility = :private
else
args.each { |meth| set_visibility(meth, :private) }
end
self
end
private :private
def protected(*args)
if args.empty?
vs = Rubinius::VariableScope.of_sender
vs.method_visibility = :protected
else
args.each { |meth| set_visibility(meth, :protected) }
end
self
end
private :protected
def private_class_method(*args)
args.each do |meth|
set_class_visibility(meth, :private)
end
self
end
def public_class_method(*args)
args.each do |meth|
set_class_visibility(meth, :public)
end
self
end
# Invokes <code>Module#append_features</code> and
# <code>Module#included</code> on each argument, passing in self.
#
def include(*modules)
modules.reverse_each do |mod|
if !mod.kind_of?(Module) or mod.kind_of?(Class)
raise TypeError, "wrong argument type #{mod.class} (expected Module)"
end
Rubinius.privately do
mod.append_features self
end
Rubinius.privately do
mod.included self
end
end
self
end
# Add all constants, instance methods and module variables
# of this Module and all Modules that this one includes to +klass+
#
# This method is aliased as append_features as the default implementation
# for that method. Kernel#extend calls this method directly through
# Module#extend_object, because Kernel#extend should not use append_features.
def include_into(klass)
unless klass.kind_of? Module
raise TypeError, "invalid argument class #{klass.class}, expected Module"
end
if kind_of? Class
raise TypeError, "invalid receiver class #{__class__}, expected Module"
end
Rubinius::Type.include_modules_from(self, klass.origin)
Rubinius::Type.infect(klass, self)
self
end
# Called when this Module is being included in another Module.
# This may be overridden for custom behaviour. The default
# is to add constants, instance methods and module variables
# of this Module and all Modules that this one includes to +klass+.
#
# See also #include.
#
alias_method :append_features, :include_into
private :append_features
def attr_reader(*names)
vis = Rubinius::VariableScope.of_sender.method_visibility
names.each { |name| Rubinius.add_reader name, self, vis }
return nil
end
private :attr_reader
def attr_writer(*names)
vis = Rubinius::VariableScope.of_sender.method_visibility
names.each { |name| Rubinius::add_writer name, self, vis }
return nil
end
private :attr_writer
def attr_accessor(*names)
vis = Rubinius::VariableScope.of_sender.method_visibility
names.each do |name|
Rubinius.add_reader name, self, vis
Rubinius.add_writer name, self, vis
end
return nil
end
private :attr_accessor
def undef_method(*names)
return self if names.empty?
names.map!{ |name| Rubinius::Type.coerce_to_symbol name }
Rubinius.check_frozen
names.each do |name|
# Will raise a NameError if the method doesn't exist.
instance_method name
undef_method! name
end
self
end
private :undef_method
# Like undef_method, but doesn't even check that the method exists. Used
# mainly to implement rb_undef_method.
def undef_method!(name)
Rubinius.check_frozen
name = Rubinius::Type.coerce_to_symbol(name)
Rubinius::VM.reset_method_cache self, name
@method_table.store name, nil, nil, nil, 0, :undef
if obj = Rubinius::Type.singleton_class_object(self)
Rubinius.privately do
obj.singleton_method_undefined(name)
end
else
method_undefined(name)
end
name
end
def remove_method(*names)
names.each do |name|
name = Rubinius::Type.coerce_to_symbol(name)
Rubinius.check_frozen
unless @method_table.lookup(name)
raise NameError.new("method `#{name}' not defined in #{self.name}", name)
end
Rubinius::VM.reset_method_cache self, name
@method_table.delete name
if obj = Rubinius::Type.singleton_class_object(self)
Rubinius.privately do
obj.singleton_method_removed(name)
end
else
method_removed(name)
end
end
self
end
private :remove_method
def name
Rubinius::Type.module_name self
end
def to_s
Rubinius::Type.module_inspect self
end
def inspect
to_s
end
end
module Rubinius
Config = Configuration.new
Globals = GlobalVariables.new
@add_method_hook = Rubinius::Hook.new
def self.open_class(name, sup, scope)
if scope
under = scope.module
else
under = Object
end
open_class_under name, sup, under
end
def self.open_class_under(name, sup, mod)
unless Type.object_kind_of? mod, Module
raise TypeError, "'#{mod.inspect}' is not a class/module"
end
tbl = mod.constant_table
if !tbl.has_name?(name)
# Create the class
sup = Object unless sup
obj = Class.new sup, name, mod
else
entry = tbl.lookup(name)
obj = entry.constant
if Type.object_kind_of? obj, Autoload
obj = begin
obj.call(mod, true)
rescue NameError # Constant not found in loaded file
nil
end
# nil is returned if the autoload was abort, usually because
# the file to be required has already been loaded. In which case
# act like the autoload wasn't there.
unless obj
supr = sup ? sup : Object
obj = Class.new supr, name, mod
end
end
if Type.object_kind_of? obj, Class
if sup and obj.superclass != sup
raise TypeError, "Superclass mismatch: #{obj.superclass} != #{sup}"
end
else
raise TypeError, "#{name} is not a class"
end
end
return obj
end
def self.open_module(name, scope)
if scope
under = scope.module
else
under = Object
end
open_module_under name, under
end
def self.open_module_under(name, mod)
unless Type.object_kind_of? mod, Module
raise TypeError, "'#{mod.inspect}' is not a class/module"
end
tbl = mod.constant_table
found = tbl.has_name?(name)
# Object has special behavior, we check it's included
# modules also
if !found and mod.equal? Object
check = mod.direct_superclass
while check
tbl = check.constant_table
found = tbl.has_name?(name)
break if found
check = check.direct_superclass
end
end
if !found
# Create the module
obj = Module.new
mod.const_set name, obj
else
entry = tbl.lookup(name)
obj = entry.constant
if Type.object_kind_of? obj, Autoload
obj = obj.call(mod, true)
# See comment above about autoload returning nil
unless obj
obj = Module.new
mod.const_set name, obj
end
end
if Type.object_kind_of?(obj, Class) || !Type.object_kind_of?(obj, Module)
raise TypeError, "#{name} is not a module, but a #{obj.class}"
end
end
return obj
end
def self.add_function(name, executable, lexical_scope)
scope = lexical_scope
while scope.parent
scope = scope.parent
end
unless scope.functions.kind_of? Rubinius::LookupTable
scope.functions = Rubinius::LookupTable.new
end
scope.functions[name] = executable
end
def self.add_defn_method(name, executable, lexical_scope, vis)
# TODO: puts serial on MethodTable entry
unless Type.object_kind_of? executable, String
executable.serial = 1
if executable.respond_to? :scope=
# If we're adding a method inside ane eval, dup it so that
# we don't share the CompiledCode with the eval, since
# we're going to mutate it.
if lexical_scope and script = lexical_scope.current_script
if script.eval?
executable = executable.dup
end
end
executable.scope = lexical_scope
end
end
mod = lexical_scope.for_method_definition
if ai = Type.singleton_class_object(mod)
if Type.object_kind_of? ai, Numeric
# Such a weird protocol. If :singleton_method_added exists, allow this.
# le sigh.
unless Type.object_respond_to? ai, :singleton_method_added
raise TypeError, "Unable to define singleton methods on Numerics"
end
end
end
add_method name, executable, mod, lexical_scope, 1, vis
name
end
# Must be AFTER add_method, because otherwise we'll run this attach_method to add
# add_method itself and fail.
def self.attach_method(name, executable, lexical_scope, recv)
# TODO: puts serial on MethodTable entry
unless Type.object_kind_of? executable, String
executable.serial = 1
if executable.respond_to? :scope=
# If we're adding a method inside ane eval, dup it so that
# we don't share the CompiledCode with the eval, since
# we're going to mutate it.
if lexical_scope and script = lexical_scope.current_script
if script.eval?
executable = executable.dup
end
end
executable.scope = lexical_scope
end
end
mod = Rubinius::Type.object_singleton_class recv
add_method name, executable, mod, lexical_scope, 1, :public
name
end
def self.add_reader(name, mod, vis)
normalized = Rubinius::Type.coerce_to_symbol(name)
add_method normalized, AccessVariable.get_ivar(normalized), mod, nil, 0, vis
end
def self.add_writer(name, mod, vis)
normalized = Rubinius::Type.coerce_to_symbol(name)
writer_name = "#{normalized}=".to_sym
add_method writer_name, AccessVariable.set_ivar(normalized), mod, nil, 0, vis
end
class << self
attr_reader :add_method_hook
end
module CAPI
INTEGER_PACK_MSWORD_FIRST = 0x01
INTEGER_PACK_LSWORD_FIRST = 0x02
INTEGER_PACK_MSBYTE_FIRST = 0x10
INTEGER_PACK_LSBYTE_FIRST = 0x20
INTEGER_PACK_NATIVE_BYTE_ORDER = 0x40
INTEGER_PACK_2COMP = 0x80
INTEGER_PACK_FORCE_BIGNUM = 0x100
INTEGER_PACK_NEGATIVE = 0x200
INTEGER_PACK_LITTLE_ENDIAN = INTEGER_PACK_LSWORD_FIRST|INTEGER_PACK_LSBYTE_FIRST
INTEGER_PACK_BIG_ENDIAN = INTEGER_PACK_MSWORD_FIRST|INTEGER_PACK_MSBYTE_FIRST
INTEGER_PACK_DIGITS = [
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0,10,11,12,13,14,15, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
]
end
module CType
Printed = Rubinius::Tuple.new 256
i = 0
while i < 256
Printed[i] = toprint(i)
i += 1
end
Lowered = Rubinius::Tuple.new 256
i = 0
while i < 256
Lowered[i] = tolower(i).chr
i += 1
end
end
module FFI
# Shorthand for the current process, i.e. all code that
# the process image itself contains. In addition to the
# Rubinius codebase, this also includes libc etc.
#
# Use this constant instead of nil directly.
#
CURRENT_PROCESS = nil
TypeDefs = Rubinius::LookupTable.new
# Converts a char
add_typedef TYPE_CHAR, :char
# Converts an unsigned char
add_typedef TYPE_UCHAR, :uchar
# The C++ boolean type
add_typedef TYPE_BOOL, :bool
# Converts a short
add_typedef TYPE_SHORT, :short
# Converts an unsigned short
add_typedef TYPE_USHORT, :ushort
add_typedef TYPE_USHORT, :mode_t
add_typedef TYPE_USHORT, :nlink_t
# Converts an int
add_typedef TYPE_INT, :int
add_typedef TYPE_INT, :dev_t
add_typedef TYPE_INT, :blksize_t
add_typedef TYPE_INT, :time_t
# Converts an unsigned int
add_typedef TYPE_UINT, :uint
add_typedef TYPE_UINT, :uid_t
add_typedef TYPE_UINT, :gid_t
add_typedef TYPE_UINT, :id_t
# Converts a long
add_typedef TYPE_LONG, :long
add_typedef TYPE_LONG, :ssize_t
# Converts an unsigned long
add_typedef TYPE_ULONG, :ulong
# Converts a size_t
add_typedef TYPE_ULONG, :size_t
# Converts a long long
add_typedef TYPE_LL, :long_long
add_typedef TYPE_LL, :blkcnt_t
add_typedef TYPE_LL, :off_t
# Converts an unsigned long long
add_typedef TYPE_ULL, :ulong_long
add_typedef TYPE_ULL, :ino64_t
# Converts a float
add_typedef TYPE_FLOAT, :float
# Converts a double
add_typedef TYPE_DOUBLE, :double
# Converts a pointer to opaque data
add_typedef TYPE_PTR, :pointer
# For when a function has no return value
add_typedef TYPE_VOID, :void
# Converts NULL-terminated C strings
add_typedef TYPE_STRING, :string
# Use strptr when you need to free the result of some operation.
add_typedef TYPE_STRPTR, :strptr
add_typedef TYPE_STRPTR, :string_and_pointer
# Use for a C struct with a char [] embedded inside.
add_typedef TYPE_CHARARR, :char_array
# A set of unambigious integer types
add_typedef TYPE_CHAR, :int8
add_typedef TYPE_UCHAR, :uint8
add_typedef TYPE_SHORT, :int16
add_typedef TYPE_USHORT, :uint16
add_typedef TYPE_INT, :int32
add_typedef TYPE_UINT, :uint32
# Converts a varargs argument
add_typedef TYPE_VARARGS, :varargs
if Rubinius::L64
add_typedef TYPE_LONG, :int64
add_typedef TYPE_ULONG, :uint64
else
add_typedef TYPE_LL, :int64
add_typedef TYPE_ULL, :uint64
end
TypeSizes = Rubinius::LookupTable.new
TypeSizes[1] = :char
TypeSizes[2] = :short
TypeSizes[4] = :int
TypeSizes[8] = Rubinius::L64 ? :long : :long_long
# Load all the platform dependent types
Rubinius::Config.section("rbx.platform.typedef.") do |key, value|
add_typedef(find_type(value.to_sym), key.substring(21, key.length).to_sym)
end
class DynamicLibrary
extend FFI::Library
# Bootstrap dlsym, dlopen, and dlerror
pointer_as_function :find_symbol, FFI::Pointer::DLSYM, [:pointer, :string], :pointer
pointer_as_function :open_library, FFI::Pointer::DLOPEN, [:string, :int], :pointer
pointer_as_function :last_error, FFI::Pointer::DLERROR, [], :string
if Rubinius.windows?
RTLD_LAZY = 0
RTLD_NOW = 0
RTLD_GLOBAL = 0
RTLD_LOCAL = 0
else
RTLD_LAZY = Rubinius::Config['rbx.platform.dlopen.RTLD_LAZY']
RTLD_NOW = Rubinius::Config['rbx.platform.dlopen.RTLD_NOW']
RTLD_GLOBAL = Rubinius::Config['rbx.platform.dlopen.RTLD_GLOBAL']
RTLD_LOCAL = Rubinius::Config['rbx.platform.dlopen.RTLD_LOCAL']
end
class << self
alias_method :open, :new
end
def initialize(name, flags=nil)
# Accept nil and check for ruby-ffi API compat
flags ||= RTLD_LAZY | RTLD_GLOBAL
unless name
@name = "[current process]"
@handle = FFI::Pointer::CURRENT_PROCESS
return
end
@name = name
@handle = DynamicLibrary.open_library name, flags
unless @handle
orig_error = last_error
libnames = FFI::LIB_SUFFIXES.map {|suffix| "#{name}.#{suffix}" }
libnames << "lib#{name}"
libnames += FFI::LIB_SUFFIXES.map {|suffix| "lib#{name}.#{suffix}" }
libnames.detect do |libname|
@name = libname
@handle = DynamicLibrary.open_library libname, flags
end
end
unless @handle
orig_error = orig_error.split("\n").first
# API Compat. LoadError is wrong here.
raise LoadError, "Could not open library #{name} - #{orig_error}"
end
end
private :initialize
attr_reader :name
def find_symbol(name)
ptr = DynamicLibrary.find_symbol @handle, name
return nil unless ptr
# defined in core/pointer.rb
FFI::DynamicLibrary::Symbol.new(self, ptr, name)
end
alias_method :find_function, :find_symbol
alias_method :find_variable, :find_symbol
def last_error
DynamicLibrary.last_error
end
CURRENT_PROCESS = DynamicLibrary.new(nil)
end
module Platform
ARCH = Rubinius::CPU
# ruby-ffi compatible
LONG_SIZE = Rubinius::SIZEOF_LONG * 8
ADDRESS_SIZE = Rubinius::WORDSIZE
case
when Rubinius.windows?
LIBSUFFIX = "dll"
IS_WINDOWS = true
OS = 'windows'
when Rubinius.darwin?
LIBSUFFIX = "dylib"
IS_WINDOWS = false
OS = 'darwin'
else
LIBSUFFIX = "so"
IS_WINDOWS = false
OS = 'linux'
end
module File
SEPARATOR = '/'
ALT_SEPARATOR = nil
PATH_SEPARATOR = ':'
end
module Math
extend FFI::Library
attach_function :fabs, [:double], :double
attach_function :atan2, [:double, :double], :double
attach_function :cos, [:double], :double
attach_function :sin, [:double], :double
attach_function :tan, [:double], :double
attach_function :acos, [:double], :double
attach_function :asin, [:double], :double
attach_function :atan, [:double], :double
attach_function :cosh, [:double], :double
attach_function :sinh, [:double], :double
attach_function :tanh, [:double], :double
attach_function :acosh, [:double], :double
attach_function :asinh, [:double], :double
attach_function :atanh, [:double], :double
attach_function :exp, [:double], :double
attach_function :log, [:double], :double
attach_function :log10, [:double], :double
attach_function :sqrt, [:double], :double
attach_function :frexp, [:double, :pointer], :double
attach_function :ldexp, [:double, :int], :double
attach_function :hypot, [:double, :double], :double
attach_function :erf, [:double], :double
attach_function :erfc, [:double], :double
attach_function :cbrt, [:double], :double
attach_function :tgamma, [:double], :double
attach_function :lgamma_r, [:double, :pointer], :double
# Rubinius-specific, used in Marshal
attach_function :modf, [:double, :pointer], :double
# TODO: we need a way to determine whether a function
# is defined for a particular platform.
#
# attach_function :log2, [:double], :double
def self.log2(x)
log10(x) / log10(2.0)
end
end
module POSIX
extend FFI::Library
# errors
attach_function :errno, 'ffi_errno', [], :int
attach_function :errno=, 'ffi_set_errno', [:int], :void
# memory
attach_function :malloc, [:size_t], :pointer
attach_function :realloc, [:pointer, :size_t], :pointer
attach_function :free, [:pointer], :void
attach_function :memset, [:pointer, :int, :size_t], :pointer
attach_function :memcpy, [:pointer, :pointer, :size_t], :pointer
# file system
attach_function :access, [:string, :int], :int
attach_function :chmod, [:string, :mode_t], :int
attach_function :fchmod, [:int, :mode_t], :int
attach_function :lchmod, [:string, :mode_t], :int
attach_function :chown, [:string, :uid_t, :gid_t], :int
attach_function :fchown, [:int, :uid_t, :gid_t], :int
attach_function :lchown, [:string, :uid_t, :gid_t], :int
attach_function :unlink, [:string], :int
attach_function :getcwd, [:string, :size_t], :string
attach_function :umask, [:mode_t], :int
attach_function :link, [:string, :string], :int
attach_function :symlink, [:string, :string], :int
attach_function :readlink, [:string, :pointer, :size_t], :ssize_t
attach_function :rename, [:string, :string], :int
attach_function :utimes, [:string, :pointer], :int
attach_function :mkfifo, [:string, :mode_t], :int
# directories
attach_function :chdir, [:string], :int
attach_function :mkdir, [:string, :mode_t], :int
attach_function :rmdir, [:string], :int
attach_function :chroot, [:string], :int
# File/IO
attach_function :fcntl, [:int, :int, :long], :int
attach_function :ioctl, [:int, :ulong, :long], :int
attach_function :fsync, [:int], :int
attach_function :dup, [:int], :int
attach_function :dup2, [:int, :int], :int
attach_function :open, [:string, :int, :mode_t], :int
attach_function :close, [:int], :int
attach_function :lseek, [:int, :off_t, :int], :off_t
attach_function :read, [:int, :pointer, :size_t], :ssize_t
attach_function :ftruncate, [:int, :off_t], :int
attach_function :truncate, [:string, :off_t], :int
attach_function :write, [:int, :pointer, :size_t], :ssize_t
attach_function :select, [:int, :pointer, :pointer, :pointer, :pointer], :int
# Other I/O
attach_function :pipe, [:pointer], :int
attach_function :mmap, [:pointer, :size_t, :int, :int, :int, :off_t], :pointer
attach_function :msync, [:pointer, :size_t, :int], :int
attach_function :munmap, [:pointer, :size_t], :int
attach_function :getpagesize, [], :int
attach_function :shutdown, [:int, :int], :int
attach_function :posix_fadvise, [:int, :off_t, :off_t, :int], :int
# inspecting
attach_function :isatty, [:int], :int
attach_function :ttyname, [:int], :string
# locking
attach_function :flock, [:int, :int], :int
# UID/GID
attach_function :getuid, [], :uid_t
attach_function :getgid, [], :gid_t
attach_function :geteuid, [], :uid_t
attach_function :getegid, [], :gid_t
attach_function :setgid, [:gid_t], :int
attach_function :setuid, [:uid_t], :int
attach_function :setegid, [:gid_t], :int
attach_function :seteuid, [:uid_t], :int
attach_function :setregid, [:gid_t, :gid_t], :int
attach_function :setreuid, [:uid_t, :uid_t], :int
attach_function :setresgid, [:gid_t, :gid_t, :gid_t], :int
attach_function :setresuid, [:uid_t, :uid_t, :uid_t], :int
attach_function :getpriority, [:int, :id_t], :int
attach_function :setpriority, [:int, :id_t, :int], :int
attach_function :getgroups, [:int, :pointer], :int
attach_function :setgroups, [:int, :pointer], :int
attach_function :initgroups, [:string, :gid_t], :int
attach_function :setrlimit, [:int, :pointer], :int
attach_function :getrlimit, [:int, :pointer], :int
# password and group file access
attach_function :getpwnam, [:string], :pointer
attach_function :getpwuid, [:uid_t], :pointer
attach_function :setpwent, [], :void
attach_function :getpwent, [], :pointer
attach_function :endpwent, [], :void
attach_function :getgrnam, [:string], :pointer
attach_function :getgrgid, [:gid_t], :pointer
attach_function :setgrent, [], :void
attach_function :getgrent, [], :pointer
attach_function :endgrent, [], :void
# processes and signals
attach_function :kill, [:pid_t, :int], :int
attach_function :getpgid, [:pid_t], :pid_t
attach_function :setpgid, [:pid_t, :pid_t], :int
attach_function :getpid, [], :pid_t
attach_function :getppid, [], :pid_t
attach_function :getpgrp, [], :pid_t
attach_function :setsid, [], :pid_t
# related to stat()
attach_function :major, 'ffi_major', [:dev_t], :dev_t
attach_function :minor, 'ffi_minor', [:dev_t], :dev_t
# time
attach_function :gettimeofday, [:pointer, :pointer], :int
#--
# Internal class for accessing timevals
#++
class TimeVal < FFI::Struct
config 'rbx.platform.timeval', :tv_sec, :tv_usec
end
end
end
end
module EnvironmentAccess
extend FFI::Library
attach_function :getenv, [:string], :string
attach_function :putenv, [:string], :int
attach_function :setenv, [:string, :string, :int], :int
attach_function :unsetenv, [:string], :int
attach_function :environ, 'ffi_environ', [], :pointer
end
class EnvironmentVariables
include EnvironmentAccess
end
::ENV = EnvironmentVariables.new
module Metrics
class Data
MetricsHash = Hash.new
end
end
class Stat
S_IRUSR = Rubinius::Config['rbx.platform.file.S_IRUSR']
S_IWUSR = Rubinius::Config['rbx.platform.file.S_IWUSR']
S_IXUSR = Rubinius::Config['rbx.platform.file.S_IXUSR']
S_IRGRP = Rubinius::Config['rbx.platform.file.S_IRGRP']
S_IWGRP = Rubinius::Config['rbx.platform.file.S_IWGRP']
S_IXGRP = Rubinius::Config['rbx.platform.file.S_IXGRP']
S_IROTH = Rubinius::Config['rbx.platform.file.S_IROTH']
S_IWOTH = Rubinius::Config['rbx.platform.file.S_IWOTH']
S_IXOTH = Rubinius::Config['rbx.platform.file.S_IXOTH']
S_IRUGO = S_IRUSR | S_IRGRP | S_IROTH
S_IWUGO = S_IWUSR | S_IWGRP | S_IWOTH
S_IXUGO = S_IXUSR | S_IXGRP | S_IXOTH
S_IFMT = Rubinius::Config['rbx.platform.file.S_IFMT']
S_IFIFO = Rubinius::Config['rbx.platform.file.S_IFIFO']
S_IFCHR = Rubinius::Config['rbx.platform.file.S_IFCHR']
S_IFDIR = Rubinius::Config['rbx.platform.file.S_IFDIR']
S_IFBLK = Rubinius::Config['rbx.platform.file.S_IFBLK']
S_IFREG = Rubinius::Config['rbx.platform.file.S_IFREG']
S_IFLNK = Rubinius::Config['rbx.platform.file.S_IFLNK']
S_IFSOCK = Rubinius::Config['rbx.platform.file.S_IFSOCK']
S_IFWHT = Rubinius::Config['rbx.platform.file.S_IFWHT']
S_ISUID = Rubinius::Config['rbx.platform.file.S_ISUID']
S_ISGID = Rubinius::Config['rbx.platform.file.S_ISGID']
S_ISVTX = Rubinius::Config['rbx.platform.file.S_ISVTX']
end
end
code = Class.method_table.lookup(:new).get_method
code.serial = Rubinius::CompiledCode::KernelMethodSerial
class Class
undef_method :append_features
undef_method :extend_object
undef_method :module_function
undef_method :prepend_features
end
class Complex < Numeric
I = Complex(0, 1)
end
class NilClass
include ImmediateValue
end
class FalseClass
include ImmediateValue
end
class TrueClass
include ImmediateValue
end
class Symbol
include ImmediateValue
end
class Fixnum
include ImmediateValue
end
# Default Ruby Record Separator
# Used in this file and by various methods that need to ignore $/
DEFAULT_RECORD_SEPARATOR = "\n"
class Dir
# This seems silly, I know. But we do this to make Dir more resistent to people
# screwing with ::File later (ie, fakefs)
PrivateFile = ::File
FFI = Rubinius::FFI
module Glob
total = Rubinius::Config['glob.cache']
case total
when Fixnum
if total == 0
@glob_cache = nil
else
@glob_cache = Rubinius::LRUCache.new(total)
end
when false
@glob_cache = nil
else
@glob_cache = Rubinius::LRUCache.new(50)
end
end
end
class Encoding
class Converter
class TranscodingPath
@paths = {}
@load_cache = true
@cache_valid = false
@transcoders_count = TranscodingMap.size
end
end
end
module Errno
FFI = Rubinius::FFI
end
class File < IO
# these will be necessary when we run on Windows
DOSISH = false # !!(RUBY_PLATFORM =~ /mswin/)
CASEFOLD_FILESYSTEM = DOSISH
FNM_SYSCASE = CASEFOLD_FILESYSTEM ? FNM_CASEFOLD : 0
module Constants
F_GETFL = Rubinius::Config['rbx.platform.fcntl.F_GETFL']
F_SETFL = Rubinius::Config['rbx.platform.fcntl.F_SETFL']
# O_ACCMODE is /undocumented/ for fcntl() on some platforms
ACCMODE = Rubinius::Config['rbx.platform.fcntl.O_ACCMODE']
O_ACCMODE = Rubinius::Config['rbx.platform.fcntl.O_ACCMODE']
F_GETFD = Rubinius::Config['rbx.platform.fcntl.F_GETFD']
F_SETFD = Rubinius::Config['rbx.platform.fcntl.F_SETFD']
FD_CLOEXEC = Rubinius::Config['rbx.platform.fcntl.FD_CLOEXEC']
O_CLOEXEC = Rubinius::Config['rbx.platform.file.O_CLOEXEC']
O_NONBLOCK = Rubinius::Config['rbx.platform.file.O_NONBLOCK']
RDONLY = Rubinius::Config['rbx.platform.file.O_RDONLY']
WRONLY = Rubinius::Config['rbx.platform.file.O_WRONLY']
RDWR = Rubinius::Config['rbx.platform.file.O_RDWR']
CREAT = Rubinius::Config['rbx.platform.file.O_CREAT']
EXCL = Rubinius::Config['rbx.platform.file.O_EXCL']
NOCTTY = Rubinius::Config['rbx.platform.file.O_NOCTTY']
TRUNC = Rubinius::Config['rbx.platform.file.O_TRUNC']
APPEND = Rubinius::Config['rbx.platform.file.O_APPEND']
NONBLOCK = Rubinius::Config['rbx.platform.file.O_NONBLOCK']
SYNC = Rubinius::Config['rbx.platform.file.O_SYNC']
# TODO: these flags should probably be imported from Platform
LOCK_SH = 0x01
LOCK_EX = 0x02
LOCK_NB = 0x04
LOCK_UN = 0x08
BINARY = 0x04
# TODO: "OK" constants aren't in File::Constants in MRI
F_OK = 0 # test for existence of file
X_OK = 1 # test for execute or search permission
W_OK = 2 # test for write permission
R_OK = 4 # test for read permission
FNM_NOESCAPE = 0x01
FNM_PATHNAME = 0x02
FNM_DOTMATCH = 0x04
FNM_CASEFOLD = 0x08
FNM_EXTGLOB = 0x10
FNM_SYSCASE = File::FNM_SYSCASE
if Rubinius.windows?
NULL = 'NUL'
else
NULL = '/dev/null'
end
end
Stat = Rubinius::Stat
class Stat
@module_name = :"File::Stat"
def world_readable?
if mode & S_IROTH == S_IROTH
tmp = mode & (S_IRUGO | S_IWUGO | S_IXUGO)
return Rubinius::Type.coerce_to tmp, Fixnum, :to_int
end
end
def world_writable?
if mode & S_IWOTH == S_IWOTH
tmp = mode & (S_IRUGO | S_IWUGO | S_IXUGO)
return Rubinius::Type.coerce_to tmp, Fixnum, :to_int
end
end
end
FFI = Rubinius::FFI
SEPARATOR = FFI::Platform::File::SEPARATOR
Separator = FFI::Platform::File::SEPARATOR
ALT_SEPARATOR = FFI::Platform::File::ALT_SEPARATOR
PATH_SEPARATOR = FFI::Platform::File::PATH_SEPARATOR
POSIX = FFI::Platform::POSIX
end
class Float
FFI = Rubinius::FFI
end
class IO
include File::Constants
FFI = Rubinius::FFI
SEEK_SET = Rubinius::Config['rbx.platform.io.SEEK_SET']
SEEK_CUR = Rubinius::Config['rbx.platform.io.SEEK_CUR']
SEEK_END = Rubinius::Config['rbx.platform.io.SEEK_END']
# Not available on all platforms, so these constants may be nil
POSIX_FADV_NORMAL = Rubinius::Config['rbx.platform.advise.POSIX_FADV_NORMAL']
POSIX_FADV_SEQUENTIAL = Rubinius::Config['rbx.platform.advise.POSIX_FADV_SEQUENTIAL']
POSIX_FADV_RANDOM = Rubinius::Config['rbx.platform.advise.POSIX_FADV_RANDOM']
POSIX_FADV_WILLNEED = Rubinius::Config['rbx.platform.advise.POSIX_FADV_WILLNEED']
POSIX_FADV_DONTNEED = Rubinius::Config['rbx.platform.advise.POSIX_FADV_DONTNEED']
POSIX_FADV_NOREUSE = Rubinius::Config['rbx.platform.advise.POSIX_FADV_NOREUSE']
class FileDescriptor
@@max_descriptors = Rubinius::AtomicReference.new(2)
include File::Constants
O_RDONLY = Rubinius::Config['rbx.platform.file.O_RDONLY']
O_WRONLY = Rubinius::Config['rbx.platform.file.O_WRONLY']
O_RDWR = Rubinius::Config['rbx.platform.file.O_RDWR']
end
class Select
FD_SETSIZE = Rubinius::Config['rbx.platform.select.FD_SETSIZE']
end
end
class NilClass
include ImmediateValue
end
class FalseClass
include ImmediateValue
end
class TrueClass
include ImmediateValue
end
class Symbol
include ImmediateValue
end
class Fixnum
include ImmediateValue
end
module Rubinius
class Mirror
module Process
class Execute
# Mapping of string open modes to integer oflag versions.
OFLAGS = {
"r" => ::File::RDONLY,
"r+" => ::File::RDWR | ::File::CREAT,
"w" => ::File::WRONLY | ::File::CREAT | ::File::TRUNC,
"w+" => ::File::RDWR | ::File::CREAT | ::File::TRUNC,
"a" => ::File::WRONLY | ::File::APPEND | ::File::CREAT,
"a+" => ::File::RDWR | ::File::APPEND | ::File::CREAT
}
end
end
end
end
class Regexp
IGNORECASE = 1
EXTENDED = 2
MULTILINE = 4
FIXEDENCODING = 16
NOENCODING = 32
DONT_CAPTURE_GROUP = 128
CAPTURE_GROUP = 256
KCODE_NONE = (1 << 9)
KCODE_EUC = (2 << 9)
KCODE_SJIS = (3 << 9)
KCODE_UTF8 = (4 << 9)
KCODE_MASK = KCODE_NONE | KCODE_EUC | KCODE_SJIS | KCODE_UTF8
OPTION_MASK = IGNORECASE | EXTENDED | MULTILINE | FIXEDENCODING | NOENCODING | DONT_CAPTURE_GROUP | CAPTURE_GROUP
ESCAPE_TABLE = Rubinius::Tuple.new(256)
# Seed it with direct replacements
i = 0
while i < 256
ESCAPE_TABLE[i] = i.chr
i += 1
end
# The character literals (?x) are Fixnums in 1.8 and Strings in 1.9
# so we use literal values instead so this is 1.8/1.9 compatible.
ESCAPE_TABLE[9] = '\\t'
ESCAPE_TABLE[10] = '\\n'
ESCAPE_TABLE[11] = '\\v'
ESCAPE_TABLE[12] = '\\f'
ESCAPE_TABLE[13] = '\\r'
ESCAPE_TABLE[32] = '\\ '
ESCAPE_TABLE[35] = '\\#'
ESCAPE_TABLE[36] = '\\$'
ESCAPE_TABLE[40] = '\\('
ESCAPE_TABLE[41] = '\\)'
ESCAPE_TABLE[42] = '\\*'
ESCAPE_TABLE[43] = '\\+'
ESCAPE_TABLE[45] = '\\-'
ESCAPE_TABLE[46] = '\\.'
ESCAPE_TABLE[63] = '\\?'
ESCAPE_TABLE[91] = '\\['
ESCAPE_TABLE[92] = '\\\\'
ESCAPE_TABLE[93] = '\\]'
ESCAPE_TABLE[94] = '\\^'
ESCAPE_TABLE[123] = '\\{'
ESCAPE_TABLE[124] = '\\|'
ESCAPE_TABLE[125] = '\\}'
class SourceParser
class Part
OPTIONS_MAP = {
'm' => Regexp::MULTILINE,
'i' => Regexp::IGNORECASE,
'x' => Regexp::EXTENDED
}
end
PossibleOptions = [[MULTILINE, "m"], [IGNORECASE, "i"], [EXTENDED, "x"]]
end
end
class String
class Rationalizer
SPACE = "\\s*"
DIGITS = "(?:[0-9](?:_[0-9]|[0-9])*)"
NUMERATOR = "(?:#{DIGITS}?\\.)?#{DIGITS}(?:[eE][-+]?#{DIGITS})?"
DENOMINATOR = DIGITS
RATIONAL = "\\A#{SPACE}([-+])?(#{NUMERATOR})(?:\\/(#{DENOMINATOR}))?#{SPACE}"
PATTERN = Regexp.new RATIONAL
end
class Complexifier
SPACE = Rationalizer::SPACE
NUMERATOR = Rationalizer::NUMERATOR
DENOMINATOR = Rationalizer::DENOMINATOR
NUMBER = "[-+]?#{NUMERATOR}(?:\\/#{DENOMINATOR})?"
NUMBERNOS = "#{NUMERATOR}(?:\\/#{DENOMINATOR})?"
PATTERN0 = Regexp.new "\\A#{SPACE}(#{NUMBER})@(#{NUMBER})#{SPACE}"
PATTERN1 = Regexp.new "\\A#{SPACE}([-+])?(#{NUMBER})?[iIjJ]#{SPACE}"
PATTERN2 = Regexp.new "\\A#{SPACE}(#{NUMBER})(([-+])(#{NUMBERNOS})?[iIjJ])?#{SPACE}"
end
end
module Signal
Names = {
"EXIT" => 0
}
Numbers = {
0 => "EXIT"
}
@handlers = {}
Rubinius::Config.section 'rbx.platform.signal.' do |key, value|
name = key[23, key.length]
number = value.to_i
Names[name] = number
Numbers[number] = name
end
# special case of signal.c
if Names["CHLD"]
Names["CLD"] = Names["CHLD"]
end
end
class Integer < Numeric
alias_method :magnitude, :abs
end
module Kernel
def extend(*modules)
raise ArgumentError, "wrong number of arguments (0 for 1+)" if modules.empty?
Rubinius.check_frozen
modules.reverse_each do |mod|
Rubinius.privately do
mod.extend_object self
end
Rubinius.privately do
mod.extended self
end
end
self
end
alias_method :__extend__, :extend
def method_missing(meth, *args)
cls = NoMethodError
case Rubinius.method_missing_reason
when :private
msg = "private method `#{meth}' called"
when :protected
msg = "protected method `#{meth}' called"
when :super
msg = "no superclass method `#{meth}'"
when :vcall
msg = "undefined local variable or method `#{meth}'"
cls = NameError
else
msg = "undefined method `#{meth}'"
end
object_class = Rubinius::Type.object_class(self)
if Rubinius::Type.object_kind_of?(self, Module)
msg << " on #{self} (#{object_class})"
# A separate case for nil, because people like to patch methods to
# nil, so we can't call methods on it reliably.
elsif nil.equal?(self)
msg << " on nil:NilClass"
if $rbx_show_nil_location
m = Rubinius::Mirror::Object.reflect self
code_id = m.nil_code_id
# TODO: implement in CodeDB
code = nil
ObjectSpace.each_object(Rubinius::CompiledCode).each do |c|
code = c if c.code_id.start_with? code_id
end
if code
ip = m.nil_ip
msg << " originating in '#{code.name}' at #{code.file}:#{code.line_from_ip(ip)}+#{ip}"
end
end
msg << "."
elsif ImmediateValue === self
msg << " on #{self}:#{object_class}."
else
msg << " on an instance of #{object_class}."
end
Kernel.raise(cls.new(msg, meth, args, receiver: self))
end
private :method_missing
def raise(exc=undefined, msg=undefined, ctx=nil, cause: nil)
if undefined.equal? exc
exc = $!
exc = RuntimeError.new("No current exception") unless exc
exc.cause = cause unless exc.cause or exc == cause
else
if exc.respond_to? :exception
if undefined.equal? msg
exc = exc.exception
else
exc = exc.exception msg
end
raise ::TypeError, 'exception class/object expected' unless exc.kind_of?(::Exception)
elsif exc.kind_of? String
exc = ::RuntimeError.exception exc
else
raise ::TypeError, 'exception class/object expected'
end
exc.cause = cause unless exc.cause or exc == cause
exc.cause = $! unless exc.cause or exc == $!
end
if ctx.kind_of? Array
exc.set_backtrace ctx
else
exc.capture_backtrace!(2) unless exc.backtrace?
end
if $DEBUG and $VERBOSE != nil
if loc = exc.locations and loc[1]
pos = loc[1].position
else
pos = Rubinius::VM.backtrace(1)[0].position
end
STDERR.puts "Exception: `#{exc.class}' #{pos} - #{exc.message}"
end
Rubinius.raise_exception exc
end
module_function :raise
alias_method :fail, :raise
module_function :fail
def to_s
Rubinius::Type.infect("#<#{self.class}:0x#{self.__id__.to_s(16)}>", self)
end
# Add in $! in as a hook, to just do $!. This is for accesses to $!
# that the compiler can't see.
Rubinius::Globals.set_hook(:$!) { $! }
get = proc do
# We raise an exception here because Regexp.last_match won't work
raise TypeError, "Unable to handle $~ in this context"
end
set = proc do |key, val|
if val.nil? || val.kind_of?(MatchData)
Rubinius.invoke_primitive :regexp_set_last_match, val
else
raise TypeError, "Cannot assign #{val.class}, expexted nil or instance MatchData."
end
end
Rubinius::Globals.set_hook(:$~, get, set)
Rubinius::Globals.set_hook(:$*) { ARGV }
Rubinius::Globals.set_hook(:$@) { $! ? $!.backtrace : nil }
Rubinius::Globals.set_hook(:$$) { Process.pid }
prc = proc { ARGF.filename }
Rubinius::Globals.set_hook(:$FILENAME, prc, :raise_readonly)
write_filter = proc do |key, io|
unless io.respond_to? :write
raise ::TypeError, "#{key} must have write method, #{io.class} given"
end
io
end
get = proc { |key| Thread.current[:$_] }
set = proc { |key, val| Thread.current[:$_] = val }
Rubinius::Globals.set_hook(:$_, get, set)
Rubinius::Globals.add_alias :$stdout, :$>
Rubinius::Globals.set_filter(:$stdout, write_filter)
Rubinius::Globals.set_filter(:$stderr, write_filter)
get = proc do
warn "$KCODE is unused in Ruby 1.9 and later"
nil
end
set = proc do |key, io|
warn "$KCODE is unused in Ruby 1.9 and later, changes are ignored"
nil
end
Rubinius::Globals.set_hook(:$KCODE, get, set)
set = proc do |key, val|
val = Rubinius::Type.coerce_to val, String, :to_str
Rubinius.invoke_primitive :vm_set_process_title, val
end
Rubinius::Globals.set_hook(:$0, :[], set)
set = proc { |key, val| STDERR.puts("WARNING: $SAFE is not supported on Rubinius."); val }
Rubinius::Globals.set_hook(:$SAFE, :[], set)
# Alias $0 $PROGRAM_NAME
Rubinius::Globals.add_alias(:$0, :$PROGRAM_NAME)
Rubinius::Globals.read_only :$:, :$LOAD_PATH, :$-I
Rubinius::Globals.read_only :$", :$LOADED_FEATURES
Rubinius::Globals.read_only :$<
Rubinius::Globals[:$-a] = false
Rubinius::Globals[:$-l] = false
Rubinius::Globals[:$-p] = false
Rubinius::Globals.read_only :$-a, :$-l, :$-p
Rubinius::Globals.add_alias :$DEBUG, :$-d
Rubinius::Globals.add_alias :$VERBOSE, :$-v
Rubinius::Globals.add_alias :$VERBOSE, :$-w
set_string = proc do |key, value|
unless value.nil? or value.kind_of? String
raise TypeError, "value of #{key} must be a String"
end
Rubinius::Globals.set! key, value
end
Rubinius::Globals.set_filter :$/, set_string
Rubinius::Globals.add_alias :$/, :$-0
Rubinius::Globals.set_filter :$,, set_string
end
module Math
FFI = Rubinius::FFI
# Constants
PI = 3.14159_26535_89793_23846
E = 2.71828_18284_59045_23536
FactorialTable = [
1.0,
1.0,
2.0,
6.0,
24.0,
120.0,
720.0,
5040.0,
40320.0,
362880.0,
3628800.0,
39916800.0,
479001600.0,
6227020800.0,
87178291200.0,
1307674368000.0,
20922789888000.0,
355687428096000.0,
6402373705728000.0,
121645100408832000.0,
2432902008176640000.0,
51090942171709440000.0,
1124000727777607680000.0
]
if Errno.const_defined? :EDOM
DomainError = Errno::EDOM
elsif Errno.const_defined? :ERANGE
DomainError = Errno::ERANGE
else
class DomainError < SystemCallError
end
end
end
module Process
module Constants
EXIT_SUCCESS = Rubinius::Config['rbx.platform.process.EXIT_SUCCESS'] || 0
EXIT_FAILURE = Rubinius::Config['rbx.platform.process.EXIT_FAILURE'] || 1
PRIO_PGRP = Rubinius::Config['rbx.platform.process.PRIO_PGRP']
PRIO_PROCESS = Rubinius::Config['rbx.platform.process.PRIO_PROCESS']
PRIO_USER = Rubinius::Config['rbx.platform.process.PRIO_USER']
RLIM_INFINITY = Rubinius::Config['rbx.platform.process.RLIM_INFINITY']
RLIM_SAVED_MAX = Rubinius::Config['rbx.platform.process.RLIM_SAVED_MAX']
RLIM_SAVED_CUR = Rubinius::Config['rbx.platform.process.RLIM_SAVED_CUR']
RLIMIT_AS = Rubinius::Config['rbx.platform.process.RLIMIT_AS']
RLIMIT_CORE = Rubinius::Config['rbx.platform.process.RLIMIT_CORE']
RLIMIT_CPU = Rubinius::Config['rbx.platform.process.RLIMIT_CPU']
RLIMIT_DATA = Rubinius::Config['rbx.platform.process.RLIMIT_DATA']
RLIMIT_FSIZE = Rubinius::Config['rbx.platform.process.RLIMIT_FSIZE']
RLIMIT_MEMLOCK = Rubinius::Config['rbx.platform.process.RLIMIT_MEMLOCK']
RLIMIT_NOFILE = Rubinius::Config['rbx.platform.process.RLIMIT_NOFILE']
RLIMIT_NPROC = Rubinius::Config['rbx.platform.process.RLIMIT_NPROC']
RLIMIT_RSS = Rubinius::Config['rbx.platform.process.RLIMIT_RSS']
RLIMIT_SBSIZE = Rubinius::Config['rbx.platform.process.RLIMIT_SBSIZE']
RLIMIT_STACK = Rubinius::Config['rbx.platform.process.RLIMIT_STACK']
RLIMIT_RTPRIO = Rubinius::Config['rbx.platform.process.RLIMIT_RTPRIO']
RLIMIT_RTTIME = Rubinius::Config['rbx.platform.process.RLIMIT_RTTIME']
RLIMIT_SIGPENDING = Rubinius::Config['rbx.platform.process.RLIMIT_SIGPENDING']
RLIMIT_MSGQUEUE = Rubinius::Config['rbx.platform.process.RLIMIT_MSGQUEUE']
RLIMIT_NICE = Rubinius::Config['rbx.platform.process.RLIMIT_NICE']
WNOHANG = 1
WUNTRACED = 2
end
include Constants
FFI = Rubinius::FFI
class Rlimit < FFI::Struct
config "rbx.platform.rlimit", :rlim_cur, :rlim_max
end
Rubinius::Globals.read_only :$?
Rubinius::Globals.set_hook(:$?) { Thread.current[:$?] }
end
STDIN = Rubinius::IOUtility.redefine_io(0, :read_only)
STDOUT = Rubinius::IOUtility.redefine_io(1, :write_only)
STDERR = Rubinius::IOUtility.redefine_io(2, :write_only)
Rubinius::Globals.set!(:$stdin, STDIN)
Rubinius::Globals.set!(:$stdout, STDOUT)
Rubinius::Globals.set!(:$stderr, STDERR)
module Rubinius
begin
is_tty = STDIN.tty?
rescue IOError
is_tty = false
end
Terminal = is_tty
AtExit = []
class Sprinter
total = Rubinius::Config['printf.cache']
case total
when Fixnum
if total == 0
@cache = nil
else
@cache = Rubinius::LRUCache.new(total)
end
when false
@cache = nil
else
@cache = Rubinius::LRUCache.new(50)
end
class Builder
RADIX = { 'u' => 10, 'x' => 16, 'X' => 16, 'o' => 8, 'b' => 2, 'B' => 2 }
PREFIX = { 'o' => '0', 'x' => '0x', 'X' => '0X', 'b' => '0b', 'B' => '0B' }
AtomMap = Rubinius::LookupTable.new
AtomMap[?c] = CharAtom
AtomMap[?s] = StringAtom
AtomMap[?p] = InspectAtom
AtomMap[?e] = FloatAtom
AtomMap[?E] = FloatAtom
AtomMap[?g] = FloatAtom
AtomMap[?G] = FloatAtom
AtomMap[?f] = FloatAtom
AtomMap[?d] = IntegerAtom
AtomMap[?i] = IntegerAtom
AtomMap[?u] = IntegerAtom
AtomMap[?b] = ExtIntegerAtom
AtomMap[?B] = ExtIntegerAtom
AtomMap[?x] = ExtIntegerAtom
AtomMap[?X] = ExtIntegerAtom
AtomMap[?o] = ExtIntegerAtom
RE = /
([^%]+|%(?:[\n\0]|\z)) # 1
|
%
( # 2
(<[^>]+>)? # 3
([0# +-]*) # 4
(?:([0-9]+)\$)? # 5
([0# +-]*) # 6
(?:
(\*(?:([0-9]+)\$)?|([1-9][0-9]*))? # 7 8 9
(?:\.(\*(?:([0-9]+)\$)?|([0-9][0-9]*))?)? # 10 11 12
)
(?:([0-9]+)\$)? # 13
([BbcdEefGgiopsuXx]) # 14
)
|
(%)(?:%|[-+0-9# *.$]+\$[0-9.]*\z) # 15
|
(%{[^}]+}) #16
|
(%) # 17
/x
end
end
end
class Struct
Struct.new 'Tms', :utime, :stime, :cutime, :cstime, :tutime, :tstime
class Tms
def initialize(utime=nil, stime=nil, cutime=nil, cstime=nil,
tutime=nil, tstime=nil)
@utime = utime
@stime = stime
@cutime = cutime
@cstime = cstime
@tutime = tutime
@tstime = tstime
end
private :initialize
end
def self._specialize(attrs)
# Because people are crazy, they subclass Struct directly, ie.
# class Craptastic < Struct
#
# NOT
#
# class Fine < Struct.new(:x, :y)
#
# When they do this craptastic act, they'll sometimes define their
# own #initialize and super into Struct#initialize.
#
# When they do this and then do Craptastic.new(:x, :y), this code
# will accidentally shadow their #initialize. So for now, only run
# the specialize if we're trying new Struct's directly from Struct itself,
# not a craptastic Struct subclass.
return unless superclass.equal? Struct
# To allow for optimization, we generate code with normal ivar
# references for all attributes whose names can be written as
# tIVAR tokens. For example, of the following struct attributes
#
# Struct.new(:a, :@b, :c?, :'d-e')
#
# only the first, :a, can be written as a valid tIVAR token:
#
# * :a can be written as @a
# * :@b becomes @@b and would be interpreted as a tCVAR
# * :c? becomes @c? and be interpreted as the beginning of
# a ternary expression
# * :'d-e' becomes @d-e and would be interpreted as a method
# invocation
#
# Attribute names that cannot be written as tIVAR tokens will
# fall back to using #instance_variable_(get|set).
args, assigns, hashes, vars = [], [], [], []
attrs.each_with_index do |name, i|
name = "@#{name}"
if name =~ /^@[a-z_]\w*$/i
assigns << "#{name} = a#{i}"
vars << name
else
assigns << "instance_variable_set(:#{name.inspect}, a#{i})"
vars << "instance_variable_get(:#{name.inspect})"
end
args << "a#{i} = nil"
hashes << "#{vars[-1]}.hash"
end
code = <<-CODE
def initialize(#{args.join(", ")})
#{assigns.join(';')}
self
end
private :initialize
def hash
hash = #{hashes.size}
return hash if Thread.detect_outermost_recursion(self) do
hash = hash ^ #{hashes.join(' ^ ')}
end
hash
end
def to_a
[#{vars.join(', ')}]
end
def length
#{vars.size}
end
CODE
begin
mod = Module.new do
module_eval code
end
include mod
rescue SyntaxError
# SyntaxError means that something is wrong with the
# specialization code. Just eat the error and don't specialize.
end
end
end
class Thread
MUTEX_FOR_THREAD_EXCLUSIVE = Mutex.new
Thread.initialize_main_thread(Thread.current)
ThreadGroup::Default.add Thread.current
sm = Rubinius::Mirror.reflect Rubinius.signal_thread
sm.group = ThreadGroup::Default
end
class Time
MonthValue = {
'JAN' => 1, 'FEB' => 2, 'MAR' => 3, 'APR' => 4, 'MAY' => 5, 'JUN' => 6,
'JUL' => 7, 'AUG' => 8, 'SEP' => 9, 'OCT' =>10, 'NOV' =>11, 'DEC' =>12
}
end
class Random
DEFAULT = new
end
module Rubinius
class Prediction
def valid?
Rubinius.primitive :prediction_valid_p
raise PrimitiveFailure, "Rubinius::Prediction#valid? primitive failed"
end
end
class CodeDB
class << self
undef :new
end
end
module FFI
module Library
# Once the core library is loaded, we want to raise an error if
# attempting to attach to a non-existent function.
def ffi_function_missing(name, *args)
raise FFI::NotFoundError, "Unable to find foreign function '#{name}'"
end
end
end
end