Skip to content

Commit

Permalink
Rename Crystal::System.print_error(fmt, *args, &) to printf (#14617)
Browse files Browse the repository at this point in the history
  • Loading branch information
ysbaddaden committed May 24, 2024
1 parent eb2e70f commit e043a25
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 24 deletions.
24 changes: 12 additions & 12 deletions spec/std/crystal/system_spec.cr
Original file line number Diff line number Diff line change
@@ -1,48 +1,48 @@
require "../spec_helper"

private def print_error_to_s(format, *args)
private def printf_to_s(format, *args)
io = IO::Memory.new
Crystal::System.print_error(format, *args) do |bytes|
Crystal::System.printf(format, *args) do |bytes|
io.write_string(bytes)
end
io.to_s
end

describe "Crystal::System" do
describe ".print_error" do
describe ".printf" do
it "works" do
print_error_to_s("abcde").should eq("abcde")
printf_to_s("abcde").should eq("abcde")
end

it "supports %d" do
print_error_to_s("%d,%d,%d,%d,%d", 0, 1234, Int32::MAX, Int32::MIN, UInt64::MAX).should eq("0,1234,2147483647,-2147483648,-1")
printf_to_s("%d,%d,%d,%d,%d", 0, 1234, Int32::MAX, Int32::MIN, UInt64::MAX).should eq("0,1234,2147483647,-2147483648,-1")
end

it "supports %u" do
print_error_to_s("%u,%u,%u,%u,%u", 0, 1234, UInt32::MAX, Int32::MIN, UInt64::MAX).should eq("0,1234,4294967295,2147483648,4294967295")
printf_to_s("%u,%u,%u,%u,%u", 0, 1234, UInt32::MAX, Int32::MIN, UInt64::MAX).should eq("0,1234,4294967295,2147483648,4294967295")
end

it "supports %x" do
print_error_to_s("%x,%x,%x,%x,%x", 0, 0x1234, UInt32::MAX, Int32::MIN, UInt64::MAX).should eq("0,1234,ffffffff,80000000,ffffffff")
printf_to_s("%x,%x,%x,%x,%x", 0, 0x1234, UInt32::MAX, Int32::MIN, UInt64::MAX).should eq("0,1234,ffffffff,80000000,ffffffff")
end

# TODO: investigate why this prints `(???)`
pending_interpreted "supports %p" do
print_error_to_s("%p,%p,%p", Pointer(Void).new(0x0), Pointer(Void).new(0x1234), Pointer(Void).new(UInt64::MAX)).should eq("0x0,0x1234,0xffffffffffffffff")
printf_to_s("%p,%p,%p", Pointer(Void).new(0x0), Pointer(Void).new(0x1234), Pointer(Void).new(UInt64::MAX)).should eq("0x0,0x1234,0xffffffffffffffff")
end

it "supports %s" do
print_error_to_s("%s,%s,%s", "abc\0def", "ghi".to_unsafe, Pointer(UInt8).null).should eq("abc\0def,ghi,(null)")
printf_to_s("%s,%s,%s", "abc\0def", "ghi".to_unsafe, Pointer(UInt8).null).should eq("abc\0def,ghi,(null)")
end

# BUG: missing downcast_distinct from Tuple(Int64 | UInt64, Int64 | UInt64, Int64 | UInt64, Int64 | UInt64) to Tuple(Int64, Int64, Int64, Int64)
pending_interpreted "supports %l width" do
values = {LibC::Long::MIN, LibC::Long::MAX, LibC::LongLong::MIN, LibC::LongLong::MAX}
print_error_to_s("%ld,%ld,%lld,%lld", *values).should eq(values.join(','))
printf_to_s("%ld,%ld,%lld,%lld", *values).should eq(values.join(','))

values = {LibC::ULong::MIN, LibC::ULong::MAX, LibC::ULongLong::MIN, LibC::ULongLong::MAX}
print_error_to_s("%lu,%lu,%llu,%llu", *values).should eq(values.join(','))
print_error_to_s("%lx,%lx,%llx,%llx", *values).should eq(values.join(',', &.to_s(16)))
printf_to_s("%lu,%lu,%llu,%llu", *values).should eq(values.join(','))
printf_to_s("%lx,%lx,%llx,%llx", *values).should eq(values.join(',', &.to_s(16)))
end
end
end
25 changes: 13 additions & 12 deletions src/crystal/system/print_error.cr
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,18 @@ module Crystal::System
# This is useful for error messages from components that are required for
# IO to work (fibers, scheduler, event_loop).
def self.print_error(message, *args)
print_error(message, *args) do |bytes|
{% if flag?(:unix) || flag?(:wasm32) %}
LibC.write 2, bytes, bytes.size
{% elsif flag?(:win32) %}
LibC.WriteFile(LibC.GetStdHandle(LibC::STD_ERROR_HANDLE), bytes, bytes.size, out _, nil)
{% end %}
end
printf(message, *args) { |bytes| print_error(bytes) }
end

def self.print_error(bytes : Bytes) : Nil
{% if flag?(:unix) || flag?(:wasm32) %}
LibC.write 2, bytes, bytes.size
{% elsif flag?(:win32) %}
LibC.WriteFile(LibC.GetStdHandle(LibC::STD_ERROR_HANDLE), bytes, bytes.size, out _, nil)
{% end %}
end

# Minimal drop-in replacement for a C `printf` function. Yields successive
# Minimal drop-in replacement for C `printf` function. Yields successive
# non-empty `Bytes` to the block, which should do the actual printing.
#
# *format* only supports the `%(l|ll)?[dpsux]` format specifiers; more should
Expand All @@ -23,9 +25,9 @@ module Crystal::System
# corrupted heap, its implementation should be as low-level as possible,
# avoiding memory allocations.
#
# NOTE: C's `printf` is incompatible with Crystal's `sprintf`, because the
# latter does not support argument width specifiers nor `%p`.
def self.print_error(format, *args, &)
# NOTE: Crystal's `printf` only supports a subset of C's `printf` format specifiers.
# NOTE: MSVC uses `%X` rather than `0x%x`, we follow the latter on all platforms.
def self.printf(format, *args, &)
format = to_string_slice(format)
format_len = format.size
ptr = format.to_unsafe
Expand Down Expand Up @@ -73,7 +75,6 @@ module Crystal::System
end
when 'p'
read_arg(Pointer(Void)) do |arg|
# NOTE: MSVC uses `%X` rather than `0x%x`, we follow the latter on all platforms
yield "0x".to_slice
to_int_slice(arg.address, 16, false, 2) { |bytes| yield bytes }
end
Expand Down

0 comments on commit e043a25

Please sign in to comment.