Permalink
Browse files

Added more IO stuff and platform methods.

I'm still a little unhappy with the input buffer situation.
(ie, there is none.)

Adds IO#sysread and IO#syswrite as well as a bunch of POSIX stuff.
  • Loading branch information...
1 parent 12a7550 commit 54cae1196db08f6a734c35079db8df62e491f300 @evanphx evanphx committed Aug 24, 2007
View
@@ -9,6 +9,7 @@ def newer?(file, cmp)
end
@pb = "runtime/pristine_bootstrap.rba"
+@pp = "runtime/pristine_platform.rba"
@pc = "runtime/pristine_core.rba"
@pl = "runtime/pristine_loader.rbc"
@@ -27,6 +28,11 @@ if File.exists?(@pl)
ENV['LOADER'] = @pl
end
+if File.exists?(@pp)
+ puts "Using #{@pp} for the platform."
+ ENV['PLATFORM'] = @pp
+end
+
@compiler = ENV['COMPILER']
def update_archive(files, archive, dir=nil)
@@ -260,6 +266,8 @@ namespace :dev do
task :setup do
sh "cp runtime/core.rba #{@pc}"
sh "cp runtime/bootstrap.rba #{@pb}"
+ sh "cp runtime/platform.rba #{@pp}"
+ sh "cp runtime/loader.rbc #{@pl}"
end
end
@@ -13,7 +13,7 @@ module Bootstrap
"String"=>{:@bytes=>0, :@characters=>1, :@encoding=>2, :@data=>3, :@hash => 4, :@shared => 5},
"CompiledMethod"=>{:@file=>6, :@required=>2, :@bytecodes=>4, :@locals=>7, :@path=>13, :@serial=>3, :@arguments=>9, :@scope=>10, :@lines=>12, :@cache=>14, :@name=>5, :@literals=>8, :@exceptions=>11, :@__ivars__=>0, :@primitive=>1},
"SymbolTable"=>{:@symbols=>1, :@strings=>2, :@__ivars__=>0},
- "IO"=>{:@__ivars__ => 0, :@descriptor => 1, :@buffer => 2 },
+ "IO"=>{:@__ivars__ => 0, :@descriptor => 1, :@buffer => 2, :mode => 3 },
"Module"=>{:@methods=>1, :@method_cache=>2, :@constants=>4, :@parent=>5, :@name=>3, :@__ivars__=>0},
"MethodContext"=>{:@raiseable=>5, :@bytecodes=>7, :@locals=>10, :@argcount=>11, :@receiver=>9, :@method=>6, :@sender=>1, :@module=>13, :@ip=>2, :@name=>12, :@sp=>3, :@literals=>8, :@__ivars__=>0, :@block=>4},
"Hash"=>{:@entries=>4, :@default=>5, :@default_proc=>6, :@keys=>1, :@values=>2, :@__ivars__=>0, :@bins=>3},
@@ -3,10 +3,6 @@ def self.open_with_mode(path, mode)
Ruby.primitive :io_open
end
- def self.raw_stat(path)
- Ruby.primitive :stat_file
- end
-
def self.unlink(path)
Ruby.primitive :file_unlink
end
@@ -15,4 +11,10 @@ def self.to_sexp_full(path, newlines)
Ruby.primitive :file_to_sexp
end
+ class Stat
+ def self.stat(path)
+ Ruby.primitive :stat_file
+ end
+ end
+
end
View
@@ -6,15 +6,17 @@ class IOError < StandardError
class IO
+ BufferSize = 8096
+
def initialize(fd)
@descriptor = fd
end
- ivar_as_index :__ivars__ => 0, :descriptor => 1
+ ivar_as_index :__ivars__ => 0, :descriptor => 1, :buffer => 2, :mode => 3
def __ivars__ ; @__ivars__ ; end
def inspect
- "#<#{self.class}:#{object_id.to_s(16)} fd=#{@descriptor}>"
+ "#<#{self.class}:#{object_id.to_s(16)}>"
end
def puts(*args)
@@ -38,26 +40,40 @@ def <<(obj)
end
alias :print :<<
+
+ def sysread(size, buf=nil)
+ buf = String.new(size) unless buf
+ chan = Channel.new
+ Scheduler.send_on_readable chan, self, buf, size
+ raise EOFError if chan.receive.nil?
+ return buf
+ end
+
+ alias :syswrite :write
- def read(size=nil)
+ def read(size=nil, buf=nil)
if size
- buf = String.new(size)
- chan = Channel.new
- Scheduler.send_on_readable chan, self, buf, size
- chan.receive
+ begin
+ sysread(size, buf)
+ rescue EOFError
+ return nil
+ end
else
out = ""
loop do
- chunk = read(32)
- return out unless chunk
+ begin
+ chunk = sysread(BufferSize, buf)
+ rescue EOFError
+ return out
+ end
out << chunk
- end
+ end
end
end
def close
unless io_close
- raise IOError.new("Unable to close instance of IO")
+ raise IOError "Unable to close instance of IO"
end
end
View
@@ -35,8 +35,8 @@ def self.open(path, mode="r")
end
def self.exist?(path)
- out = raw_stat(path)
- if Tuple === out
+ out = Stat.stat(path)
+ if out.kind_of? Stat
return true
else
return false
@@ -48,36 +48,49 @@ class << self
end
def self.file?(path)
- stat(path).kind == :file
+ st = Stat.stat(path)
+ return false unless st.kind_of? Stat
+ st.kind == :file
end
def self.directory?(path)
- stat(path).kind == :dir
+ st = Stat.stat(path)
+ return false unless st.kind_of? Stat
+ st.kind == :dir
end
def self.link?(path)
- stat(path).kind == :link
+ st = Stat.stat(path)
+ return false unless st.kind_of? Stat
+ st.kind == :link
end
def self.blockdev?(path)
- stat(path).kind == :block
+ st = Stat.stat(path)
+ return false unless st.kind_of? Stat
+ st.kind == :block
end
def self.chardev?(path)
- stat(path).kind == :char
+ st = Stat.stat(path)
+ return false unless st.kind_of? Stat
+ st.kind == :char
end
def self.zero?(path)
- exists?(path) && stat(path).size == 0
+ st = Stat.stat(path)
+ return false unless st.kind_of? Stat
+ st.size == 0
end
def self.size(path)
stat(path).size
end
def self.size?(path)
- return nil unless exists?(path)
- size(path)
+ st = Stat.stat(path)
+ return false unless st.kind_of? Stat
+ st.size
end
def self.writable_real?(path)
@@ -95,7 +108,7 @@ def self.readable_real?(path)
def self.unlink(*paths)
paths.each do |path|
path = enforce_string(path)
- raise Errno::ENOENT unless exists?(path)
+ raise Errno::ENOENT, path unless exists?(path)
Platform::POSIX.unlink(path)
end
paths.size
@@ -224,31 +237,23 @@ def atime; @atime; end
def mtime; @mtime; end
def ctime; @ctime; end
def path; @path; end
-
- def self.from_tuple(tup, path)
- obj = allocate
- obj.copy_from tup, 0
- obj.put 10, path
- return obj
- end
-
-
+
def inspect
- "#<#{self.class}:0x#{object_id.to_s(16)} path=#{self.path} kind=#{self.kind}>"
+ "#<#{self.class}:0x#{object_id.to_s(16)} path=#{@path} kind=#{@kind}>"
end
end
def self.stat(path)
path = enforce_string(path)
- out = raw_stat(path)
+ out = Stat.stat(path)
if !out
raise UnableToStat, "Unable to perform stat on '#{path}'"
elsif out == 1
raise NoFileError, "'#{path}' does not exist"
elsif out == 2
raise PermissionError, "Unable to access '#{path}'"
else
- return Stat.from_tuple(out, path)
+ return out
end
end
@@ -339,7 +339,8 @@ def to_sexp(name="(eval)",line=1,newlines=true)
def initialize(arg)
if Fixnum === arg
- @data = ByteArray.new(arg)
+ # + 1 for the null on the end.
+ @data = ByteArray.new(arg+1)
@bytes = arg
@characters = arg
@encoding = nil
@@ -1,9 +1,54 @@
module Platform::POSIX
+
+ def self.add(ret, name, *args)
+ attach_function nil, name, args, ret
+ end
+
+ # errors
+ attach_function nil, 'ffi_errno', :errno, [], :int
+ attach_function nil, 'strerror', [:int], :string
+ attach_function nil, 'perror', [:string], :void
+
+ # memory
+ add :pointer, 'malloc', :int
+ add :pointer, 'realloc', :pointer, :int
+ add :void, 'free', :pointer
+
+ # rand
attach_function nil, 'srand', [:uint], :void
- attach_function nil, 'rand', [], :int
+ attach_function nil, 'rand', [], :int
+
+ # file system
attach_function nil, 'access', [:string, :int], :int
- attach_function nil, 'chmod', [:string, :int], :int
+ attach_function nil, 'chmod', [:string, :int], :int
attach_function nil, 'fchmod', [:int, :int], :int
attach_function nil, 'unlink', [:string], :int
attach_function nil, 'getcwd', [:string, :int], :string
+
+ # File/IO
+ # opening/closing
+ attach_function nil, 'fdopen', [:int, :string], :pointer
+ attach_function nil, 'fopen', [:string, :string], :pointer
+ attach_function nil, 'fclose', [:int, :pointer], :int
+
+ # buffering
+ attach_function nil, 'fflush', [:pointer], :int
+
+ # inspecting
+ attach_function nil, 'fileno', [:pointer], :int
+ attach_function nil, 'feof', [:pointer], :int
+ attach_function nil, 'ferror', [:pointer], :int
+ attach_function nil, 'clearerr', [:pointer], :void
+ attach_function nil, 'fseek', [:pointer, :int, :int], :int
+ attach_function nil, 'ftell', [:pointer], :int
+
+
+ # reading
+ attach_function nil, 'fread', [:string, :int, :int, :pointer], :int
+ attach_function nil, 'fgets', [:string, :int, :pointer], :void
+ attach_function nil, 'fgetc', [:pointer], :int
+
+ # writing
+ attach_function nil, 'fwrite', [:string, :int, :int, :pointer], :int
+ attach_function nil, 'ungetc', [:int, :pointer], :int
end
View
Binary file not shown.
View
Binary file not shown.
View
Binary file not shown.
@@ -111,10 +111,11 @@ void _cpu_wake_channel(int fd, short event, void *arg) {
void _cpu_wake_channel_and_read(int fd, short event, void *arg) {
STATE;
- size_t sz;
+ size_t sz, total;
ssize_t i;
char *buf;
OBJECT ret, ba;
+ int bytes_read;
struct thread_info *ti = (struct thread_info*)arg;
state = ti->state;
@@ -124,6 +125,12 @@ void _cpu_wake_channel_and_read(int fd, short event, void *arg) {
} else {
ba = string_get_data(ti->buffer);
sz = (size_t)ti->count;
+
+ /* Clamp the read size so we don't overrun */
+ total = SIZE_OF_BODY(ba) - 1;
+ if(total < sz) {
+ sz = total;
+ }
buf = bytearray_byte_address(state, ba);
while(1) {
@@ -135,14 +142,13 @@ void _cpu_wake_channel_and_read(int fd, short event, void *arg) {
It might be better to re-schedule this in libevent and try again,
but libevent just said SOMETHING was there... */
if(errno == EINTR) continue;
- ret = I2N(errno);
- } else {
+ ret = Qfalse;
+ } else {
buf[i] = 0;
string_set_bytes(ti->buffer, I2N(i));
- ret = ti->buffer;
+ ret = I2N(i);
}
-
break;
}
}
Oops, something went wrong.

0 comments on commit 54cae11

Please sign in to comment.