* lib/mkmf.rb (convertible_int): detect convertible integer type.
port RUBY_REPLACE_INT from configure.in. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@30069 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
7031b99bca
commit
e33b7f3381
@ -1,4 +1,7 @@
|
|||||||
Fri Dec 3 19:48:11 2010 Nobuyoshi Nakada <nobu@ruby-lang.org>
|
Fri Dec 3 19:53:50 2010 Nobuyoshi Nakada <nobu@ruby-lang.org>
|
||||||
|
|
||||||
|
* lib/mkmf.rb (convertible_int): detect convertible integer type.
|
||||||
|
port RUBY_REPLACE_INT from configure.in.
|
||||||
|
|
||||||
* lib/mkmf.rb (check_sizeof): should return integer always.
|
* lib/mkmf.rb (check_sizeof): should return integer always.
|
||||||
|
|
||||||
|
80
lib/mkmf.rb
80
lib/mkmf.rb
@ -1084,6 +1084,23 @@ STRING_OR_FAILED_FORMAT = "%s"
|
|||||||
def STRING_OR_FAILED_FORMAT.%(x)
|
def STRING_OR_FAILED_FORMAT.%(x)
|
||||||
x ? super : "failed"
|
x ? super : "failed"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def typedef_expr(type, headers)
|
||||||
|
typename, member = type.split('.', 2)
|
||||||
|
prelude = cpp_include(headers).split(/$/)
|
||||||
|
prelude << "typedef #{typename} rbcv_typedef_;\n"
|
||||||
|
return "rbcv_typedef_", member, prelude
|
||||||
|
end
|
||||||
|
|
||||||
|
def try_signedness(type, member, headers = nil, opts = nil, &b)
|
||||||
|
raise ArgumentError, "don't know how to tell signedness of members" if member
|
||||||
|
if try_static_assert("(#{type})-1 < 0", headers, opts)
|
||||||
|
return -1
|
||||||
|
elsif try_static_assert("(#{type})-1 > 0", headers, opts)
|
||||||
|
return +1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
# :startdoc:
|
# :startdoc:
|
||||||
|
|
||||||
# Returns the size of the given +type+. You may optionally specify additional
|
# Returns the size of the given +type+. You may optionally specify additional
|
||||||
@ -1097,10 +1114,8 @@ end
|
|||||||
# SIZEOF_MYSTRUCT=12 preprocessor macro would be passed to the compiler.
|
# SIZEOF_MYSTRUCT=12 preprocessor macro would be passed to the compiler.
|
||||||
#
|
#
|
||||||
def check_sizeof(type, headers = nil, opts = "", &b)
|
def check_sizeof(type, headers = nil, opts = "", &b)
|
||||||
typename, member = type.split('.', 2)
|
typedef, member, prelude = typedef_expr(type, headers)
|
||||||
prelude = cpp_include(headers).split(/$/)
|
prelude << "static #{typedef} *rbcv_ptr_;\n"
|
||||||
prelude << "typedef #{typename} rbcv_typedef_;\n"
|
|
||||||
prelude << "static rbcv_typedef_ *rbcv_ptr_;\n"
|
|
||||||
prelude = [prelude]
|
prelude = [prelude]
|
||||||
expr = "sizeof((*rbcv_ptr_)#{"." << member if member})"
|
expr = "sizeof((*rbcv_ptr_)#{"." << member if member})"
|
||||||
fmt = STRING_OR_FAILED_FORMAT
|
fmt = STRING_OR_FAILED_FORMAT
|
||||||
@ -1127,22 +1142,63 @@ end
|
|||||||
# compiler, and SIGNEDNESS_OF_INT=-1 if check_signedness('int') is
|
# compiler, and SIGNEDNESS_OF_INT=-1 if check_signedness('int') is
|
||||||
# done.
|
# done.
|
||||||
#
|
#
|
||||||
def check_signedness(type, headers = nil)
|
def check_signedness(type, headers = nil, opts = nil, &b)
|
||||||
|
typedef, member, prelude = typedef_expr(type, headers)
|
||||||
signed = nil
|
signed = nil
|
||||||
checking_for("signedness of #{type}", STRING_OR_FAILED_FORMAT) do
|
checking_for("signedness of #{type}", STRING_OR_FAILED_FORMAT) do
|
||||||
if try_static_assert("(#{type})-1 < 0")
|
signed = try_signedness(typedef, member, headers, opts, &b) or next nil
|
||||||
signed = -1
|
|
||||||
elsif try_static_assert("(#{type})-1 > 0")
|
|
||||||
signed = +1
|
|
||||||
else
|
|
||||||
next nil
|
|
||||||
end
|
|
||||||
$defs.push("-DSIGNEDNESS_OF_%s=%+d" % [type.tr_cpp, signed])
|
$defs.push("-DSIGNEDNESS_OF_%s=%+d" % [type.tr_cpp, signed])
|
||||||
signed < 0 ? "signed" : "unsigned"
|
signed < 0 ? "signed" : "unsigned"
|
||||||
end
|
end
|
||||||
signed
|
signed
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Returns the convertible integer type of the given +type+. You may
|
||||||
|
# optionally specify additional +headers+ to search in for the +type+.
|
||||||
|
# _Convertible_ means actually same type, or typedefed from same type.
|
||||||
|
#
|
||||||
|
# If the +type+ is a integer type and _convertible_ type is found,
|
||||||
|
# following macros are passed as preprocessor constants to the
|
||||||
|
# compiler using the +type+ name, in uppercase.
|
||||||
|
#
|
||||||
|
# * 'TYPEOF_', followed by the +type+ name, followed by '=X' where 'X'
|
||||||
|
# is the found _convertible_ type name.
|
||||||
|
# * 'TYP2NUM' and 'NUM2TYP, where 'TYP' is the +type+ name in uppercase sans '_t'
|
||||||
|
# suffix, followed by '=X' where 'X' is the macro name to convert
|
||||||
|
# +type+ to +Integer+ object, and vice versa.
|
||||||
|
#
|
||||||
|
# For example, if foobar_t is defined as unsigned long, then
|
||||||
|
# convertible_int("foobar_t") would return "unsigned long", and define
|
||||||
|
# macros:
|
||||||
|
#
|
||||||
|
# #define TYPEOF_FOOBAR_T unsigned long
|
||||||
|
# #define FOOBAR2NUM ULONG2NUM
|
||||||
|
# #define NUM2FOOBAR NUM2ULONG
|
||||||
|
def convertible_int(type, headers = nil, opts = nil, &b)
|
||||||
|
type, macname = *type
|
||||||
|
checking_for("convertible type of #{type}", STRING_OR_FAILED_FORMAT) do
|
||||||
|
if UNIVERSAL_INTS.include?(type)
|
||||||
|
type
|
||||||
|
else
|
||||||
|
typedef, member, prelude = typedef_expr(type, headers, &b)
|
||||||
|
next unless signed = try_signedness(typedef, member, [prelude])
|
||||||
|
u = "unsigned " if signed > 0
|
||||||
|
prelude << "extern rbcv_typedef_ foo();"
|
||||||
|
compat = UNIVERSAL_INTS.find {|t|
|
||||||
|
try_compile([prelude, "extern #{u}#{t} foo();"].join("\n"), opts, &b)
|
||||||
|
}
|
||||||
|
if compat
|
||||||
|
macname ||= type.chomp("_t").tr_cpp
|
||||||
|
conv = (u ? "U" : "") + (compat == "long long" ? "LL" : compat.upcase)
|
||||||
|
compat = "#{u}#{compat}"
|
||||||
|
$defs.push(format("-DTYPEOF_%s=%s", type.tr_cpp, compat.quote))
|
||||||
|
$defs.push(format("-D%s2NUM=%s2NUM", macname, conv))
|
||||||
|
$defs.push(format("-DNUM2%s=NUM2%s", macname, conv))
|
||||||
|
compat
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
# :stopdoc:
|
# :stopdoc:
|
||||||
|
|
||||||
# Used internally by the what_type? method to determine if +type+ is a scalar
|
# Used internally by the what_type? method to determine if +type+ is a scalar
|
||||||
|
26
test/mkmf/test_convertible.rb
Normal file
26
test/mkmf/test_convertible.rb
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
require_relative 'base'
|
||||||
|
|
||||||
|
class TestMkmf
|
||||||
|
class TestConvertible < TestMkmf
|
||||||
|
def test_typeof_builtin
|
||||||
|
["", ["signed ", ""], "unsigned "].each do |signed, prefix|
|
||||||
|
%w[short int long].each do |type|
|
||||||
|
assert_equal((prefix || signed)+type,
|
||||||
|
mkmf {convertible_int(signed+type)})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_typeof_typedef
|
||||||
|
["", ["signed ", ""], "unsigned "].each do |signed, prefix|
|
||||||
|
%w[short int long].each do |type|
|
||||||
|
open("confdefs.h", "w") {|f|
|
||||||
|
f.puts "typedef #{signed}#{type} test1_t;"
|
||||||
|
}
|
||||||
|
assert_equal((prefix || signed)+type,
|
||||||
|
mkmf {convertible_int("test1_t", "confdefs.h")})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
Loading…
x
Reference in New Issue
Block a user