Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

"hello world" windows port #5339

Merged
merged 8 commits into from Dec 20, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
10 changes: 10 additions & 0 deletions src/callstack.cr
@@ -1,3 +1,13 @@
{% if flag?(:win32) %}
struct CallStack
def self.skip(*args)
# do nothing
end
end

{% skip_file() %}
{% end %}

require "c/dlfcn"
require "c/stdio"
require "c/string"
Expand Down
4 changes: 3 additions & 1 deletion src/crystal/hasher.cr
Expand Up @@ -82,7 +82,9 @@ struct Crystal::Hasher
private HASH_INF_MINUS = (-314159_i64).unsafe_as(UInt64)

@@seed = uninitialized UInt64[2]
Random::Secure.random_bytes(Slice.new(pointerof(@@seed).as(UInt8*), sizeof(typeof(@@seed))))
{% unless flag?(:win32) %}
Random::Secure.random_bytes(Slice.new(pointerof(@@seed).as(UInt8*), sizeof(typeof(@@seed))))
{% end %}

def initialize(@a : UInt64 = @@seed[0], @b : UInt64 = @@seed[1])
end
Expand Down
12 changes: 9 additions & 3 deletions src/crystal/main.cr
Expand Up @@ -114,9 +114,15 @@ module Crystal

# :nodoc:
def self.remember_blocking_state
@@stdin_is_blocking = IO::FileDescriptor.fcntl(0, LibC::F_GETFL) & LibC::O_NONBLOCK == 0
@@stdout_is_blocking = IO::FileDescriptor.fcntl(1, LibC::F_GETFL) & LibC::O_NONBLOCK == 0
@@stderr_is_blocking = IO::FileDescriptor.fcntl(2, LibC::F_GETFL) & LibC::O_NONBLOCK == 0
{% if flag?(:win32) %}
@@stdin_is_blocking = true
@@stdout_is_blocking = true
@@stderr_is_blocking = true
{% else %}
@@stdin_is_blocking = IO::FileDescriptor.fcntl(0, LibC::F_GETFL) & LibC::O_NONBLOCK == 0
@@stdout_is_blocking = IO::FileDescriptor.fcntl(1, LibC::F_GETFL) & LibC::O_NONBLOCK == 0
@@stderr_is_blocking = IO::FileDescriptor.fcntl(2, LibC::F_GETFL) & LibC::O_NONBLOCK == 0
{% end %}
end

# :nodoc:
Expand Down
6 changes: 5 additions & 1 deletion src/crystal/system/file_descriptor.cr
@@ -1 +1,5 @@
require "./unix/file_descriptor"
{% if flag?(:win32) %}
require "./win32/file_descriptor"
{% else %}
require "./unix/file_descriptor"
{% end %}
7 changes: 5 additions & 2 deletions src/crystal/system/random.cr
Expand Up @@ -14,7 +14,10 @@ end
require "./unix/getrandom"
{% elsif flag?(:openbsd) %}
require "./unix/arc4random"
{% else %}
# TODO: restrict on flag?(:unix) after crystal > 0.22.0 is released
{% elsif flag?(:unix) %}
require "./unix/urandom"
{% elsif flag?(:win32) %}
require "./win32/random"
{% else %}
{% raise "No Crystal::System::Random implementation available" %}
{% end %}
8 changes: 7 additions & 1 deletion src/crystal/system/time.cr
Expand Up @@ -6,6 +6,12 @@ module Crystal::System::Time
# Returns the current UTC time measured in `{seconds, nanoseconds}`
# since `0001-01-01 00:00:00`.
# def self.compute_utc_seconds_and_nanoseconds : {Int64, Int32}

# def self.monotonic : {Int64, Int32}
end

require "./unix/time"
{% if flag?(:win32) %}
require "./win32/time"
{% else %}
require "./unix/time"
{% end %}
2 changes: 1 addition & 1 deletion src/crystal/system/unix/time.cr
Expand Up @@ -47,7 +47,7 @@ module Crystal::System::Time
{% end %}
end

def self.monotonic
def self.monotonic : {Int64, Int32}
{% if flag?(:darwin) %}
info = mach_timebase_info
total_nanoseconds = LibC.mach_absolute_time * info.numer / info.denom
Expand Down
98 changes: 98 additions & 0 deletions src/crystal/system/win32/file_descriptor.cr
@@ -0,0 +1,98 @@
require "file/stat"
require "c/io"

module Crystal::System::FileDescriptor
@fd : LibC::Int

private def unbuffered_read(slice : Bytes)
bytes_read = LibC._read(@fd, slice, slice.size)
if bytes_read == -1
raise Errno.new("Error reading file")
end
bytes_read
end

private def unbuffered_write(slice : Bytes)
loop do
bytes_written = LibC._write(@fd, slice, slice.size)
if bytes_written == -1
raise Errno.new("Error writing file")
end

slice += bytes_written
return if slice.size == 0
end
end

private def system_blocking?
true
end

private def system_blocking=(blocking)
raise NotImplementedError.new("Crystal::System::FileDescriptor#system_blocking=") unless blocking
end

private def system_close_on_exec?
false
end

private def system_close_on_exec=(close_on_exec)
raise NotImplementedError.new("Crystal::System::FileDescriptor#system_close_on_exec=") if close_on_exec
end

private def system_stat
if LibC._fstat64(@fd, out stat) != 0
raise Errno.new("Unable to get stat")
end
::File::Stat.new(stat)
end

private def system_seek(offset, whence : IO::Seek) : Nil
seek_value = LibC._lseek(@fd, offset, whence)

if seek_value == -1
raise Errno.new "Unable to seek"
end
end

private def system_pos
pos = LibC._lseek(@fd, 0, IO::Seek::Current)
raise Errno.new "Unable to tell" if pos == -1
pos
end

private def system_tty?
LibC._isatty(@fd) != 0
end

private def system_reopen(other : IO::FileDescriptor)
{% if LibC.methods.includes? "dup3".id %}
# dup doesn't copy the CLOEXEC flag, so copy it manually using dup3
flags = other.close_on_exec? ? LibC::O_CLOEXEC : 0
if LibC.dup3(other.fd, self.fd, flags) == -1
raise Errno.new("Could not reopen file descriptor")
end
{% else %}
# dup doesn't copy the CLOEXEC flag, copy it manually to the new
if LibC.dup2(other.fd, self.fd) == -1
raise Errno.new("Could not reopen file descriptor")
end

if other.close_on_exec?
self.close_on_exec = true
end
{% end %}
end

private def system_close
err = nil
if LibC._close(@fd) != 0
case Errno.value
when Errno::EINTR
# ignore
else
raise Errno.new("Error closing file")
end
end
end
end
9 changes: 9 additions & 0 deletions src/crystal/system/win32/random.cr
@@ -0,0 +1,9 @@
module Crystal::System::Random
def self.random_bytes(buf : Bytes) : Nil
raise NotImplementedError.new("Crystal::System::Random.random_bytes")
end

def self.next_u : UInt8
raise NotImplementedError.new("Crystal::System::Random.next_u")
end
end
9 changes: 9 additions & 0 deletions src/crystal/system/win32/time.cr
@@ -0,0 +1,9 @@
module Crystal::System::Time
def self.compute_utc_offset(seconds : Int64) : Int32
raise NotImplementedError.new("Crystal::System::Time.compute_utc_offset")
end

def self.compute_utc_seconds_and_nanoseconds : {Int64, Int32}
raise NotImplementedError.new("Crystal::System::Time.compute_utc_seconds_and_nanoseconds")
end
end
11 changes: 11 additions & 0 deletions src/errno.cr
Expand Up @@ -13,6 +13,9 @@ lib LibC
fun __error : Int*
{% elsif flag?(:openbsd) %}
fun __error = __errno : Int*
{% elsif flag?(:win32) %}
fun _get_errno(value : Int*) : Int
fun _set_errno(value : Int) : Int
{% end %}
end

Expand Down Expand Up @@ -227,6 +230,10 @@ class Errno < Exception
{% end %}
{% elsif flag?(:darwin) || flag?(:freebsd) || flag?(:openbsd) %}
LibC.__error.value
{% elsif flag?(:win32) %}
ret = LibC._get_errno(out errno)
raise Errno.new("get_errno", ret) unless ret == 0
errno
{% end %}
end

Expand All @@ -240,6 +247,10 @@ class Errno < Exception
{% end %}
{% elsif flag?(:darwin) || flag?(:freebsd) || flag?(:openbsd) %}
LibC.__error.value = value
{% elsif flag?(:win32) %}
ret = LibC._set_errno(value)
raise Errno.new("set_errno", ret) unless ret == 0
value
{% end %}
end
end
16 changes: 15 additions & 1 deletion src/exception.cr
Expand Up @@ -32,7 +32,11 @@ class Exception
# The backtrace is an array of strings, each containing
# “0xAddress: Function at File Line Column”.
def backtrace?
@callstack.try &.printable_backtrace
{% if flag?(:win32) %}
nil
{% else %}
@callstack.try &.printable_backtrace
{% end %}
end

def to_s(io : IO)
Expand Down Expand Up @@ -118,3 +122,13 @@ class DivisionByZeroError < Exception
super(message)
end
end

# Raised when a method is not implemented.
#
# This can be used either to stub out method bodies, or when the method is not
# implemented on the current platform.
class NotImplementedError < Exception
def initialize(item)
super("Not Implemented: #{item}")
end
end
65 changes: 48 additions & 17 deletions src/file/stat.cr
Expand Up @@ -2,34 +2,51 @@ require "c/sys/stat"

class File
struct Stat
def initialize(filename : String)
if LibC.stat(filename, out @stat) != 0
raise Errno.new("Unable to get stat for '#{filename}'")
end
def self.new(filename : String)
File.stat(filename)
end

def initialize(@stat : LibC::Stat)
end
{% if flag?(:win32) %}
# :nodoc:
def initialize(@stat : LibC::Stat64)
end
{% else %}
# :nodoc:
def initialize(@stat : LibC::Stat)
end
{% end %}

def atime
{% if flag?(:darwin) %}
time @stat.st_atimespec
{% elsif flag?(:win32) %}
time @stat.st_atime
{% else %}
time @stat.st_atim
{% end %}
end

def blksize
@stat.st_blksize
{% if flag?(:win32) %}
raise NotImplementedError.new("File::Stat#blksize")
{% else %}
@stat.st_blksize
{% end %}
end

def blocks
@stat.st_blocks
{% if flag?(:win32) %}
raise NotImplementedError.new("File::Stat#blocks")
{% else %}
@stat.st_blocks
{% end %}
end

def ctime
{% if flag?(:darwin) %}
time @stat.st_ctimespec
{% elsif flag?(:win32) %}
time @stat.st_ctime
{% else %}
time @stat.st_ctim
{% end %}
Expand Down Expand Up @@ -59,6 +76,8 @@ class File
def mtime
{% if flag?(:darwin) %}
time @stat.st_mtimespec
{% elsif flag?(:win32) %}
time @stat.st_mtime
{% else %}
time @stat.st_mtim
{% end %}
Expand Down Expand Up @@ -93,8 +112,11 @@ class File
io << ", rdev=0x"
rdev.to_s(16, io)
io << ", size=" << size
io << ", blksize=" << blksize
io << ", blocks=" << blocks
{% unless flag?(:win32) %}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe add a comment saying that it's ignored on windows because those getter are currently not implemented and would raise?

# These two getters raise NotImplementedError on windows.
io << ", blksize=" << blksize
io << ", blocks=" << blocks
{% end %}
io << ", atime=" << atime
io << ", mtime=" << mtime
io << ", ctime=" << ctime
Expand All @@ -119,10 +141,13 @@ class File
pp.comma
pp.text "size=#{size}"
pp.comma
pp.text "blksize=#{blksize}"
pp.comma
pp.text "blocks=#{blocks}"
pp.comma
{% unless flag?(:win32) %}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ditto

# These two getters raise NotImplementedError on windows.
pp.text "blksize=#{blksize}"
pp.comma
pp.text "blocks=#{blocks}"
pp.comma
{% end %}
pp.text "atime=#{atime}"
pp.comma
pp.text "mtime=#{mtime}"
Expand Down Expand Up @@ -171,8 +196,14 @@ class File
(@stat.st_mode & LibC::S_IFMT) == LibC::S_ISVTX
end

private def time(value)
Time.new value, Time::Kind::Utc
end
{% if flag?(:win32) %}
private def time(value)
Time.epoch(value)
end
{% else %}
private def time(value)
Time.new value, Time::Kind::Utc
end
{% end %}
end
end