summaryrefslogtreecommitdiff
path: root/trunk/win32/mkexports.rb
diff options
context:
space:
mode:
authoryugui <yugui@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2008-08-25 15:02:05 +0000
committeryugui <yugui@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2008-08-25 15:02:05 +0000
commit0dc342de848a642ecce8db697b8fecd83a63e117 (patch)
tree2b7ed4724aff1f86073e4740134bda9c4aac1a39 /trunk/win32/mkexports.rb
parentef70cf7138ab8034b5b806f466e4b484b24f0f88 (diff)
added tag v1_9_0_4
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/tags/v1_9_0_4@18845 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'trunk/win32/mkexports.rb')
-rwxr-xr-xtrunk/win32/mkexports.rb153
1 files changed, 153 insertions, 0 deletions
diff --git a/trunk/win32/mkexports.rb b/trunk/win32/mkexports.rb
new file mode 100755
index 0000000000..2ed251ec1c
--- /dev/null
+++ b/trunk/win32/mkexports.rb
@@ -0,0 +1,153 @@
+#!./miniruby -s
+
+$name = $library = $description = nil
+
+module RbConfig
+ autoload :CONFIG, "rbconfig"
+end
+
+class Exports
+ @subclass = []
+ def self.inherited(klass)
+ @subclass << [/#{klass.name.sub(/.*::/, '').downcase}/i, klass]
+ end
+
+ def self.create(*args, &block)
+ platform = RUBY_PLATFORM
+ pat, klass = @subclass.find {|p, k| p =~ platform}
+ unless klass
+ raise ArgumentError, "unsupported platform: #{platform}"
+ end
+ klass.new(*args, &block)
+ end
+
+ def self.extract(objs, *rest)
+ create(objs).exports(*rest)
+ end
+
+ def self.output(output = $output, &block)
+ if output
+ open(output, 'wb', &block)
+ else
+ yield STDOUT
+ end
+ end
+
+ def initialize(objs)
+ syms = {}
+ winapis = {}
+ each_export(objs) do |internal, export|
+ syms[internal] = export
+ winapis[$1] = internal if /^_?(rb_w32_\w+)(?:@\d+)?$/ =~ internal
+ end
+ win32h = File.join(File.dirname(File.dirname(__FILE__)), "include/ruby/win32.h")
+ IO.foreach(win32h) do |line|
+ if /^#define (\w+)\((.*?)\)\s+(?:\(void\))?(rb_w32_\w+)\((.*?)\)\s*$/ =~ line and
+ $2.delete(" ") == $4.delete(" ")
+ export, internal = $1, $3
+ if syms[internal] or internal = winapis[internal]
+ syms[forwarding(internal, export)] = internal
+ end
+ end
+ end
+ syms["NtInitialize"] ||= "ruby_sysinit" if syms["ruby_sysinit"]
+ @syms = syms
+ end
+
+ def exports(name = $name, library = $library, description = $description)
+ exports = []
+ if name
+ exports << "Name " + name
+ elsif library
+ exports << "Library " + library
+ end
+ exports << "Description " + description.dump if description
+ exports << "EXPORTS" << symbols()
+ exports
+ end
+
+ private
+ def forwarding(internal, export)
+ internal.sub(/^[^@]+/, "\\1#{export}")
+ end
+
+ def each_export(objs)
+ end
+
+ def objdump(objs, &block)
+ if objs.empty?
+ $stdin.each_line(&block)
+ else
+ each_line(objs, &block)
+ end
+ end
+
+ def symbols()
+ @syms.sort.collect {|k, v| v ? v == true ? "#{k} DATA" : "#{k}=#{v}" : k}
+ end
+end
+
+class Exports::Mswin < Exports
+ def each_line(objs, &block)
+ IO.popen(%w"dumpbin -symbols -exports" + objs) do |f|
+ f.each(&block)
+ end
+ end
+
+ def each_export(objs)
+ noprefix = ($arch ||= nil and /^(sh|i\d86)/ !~ $arch)
+ objs = objs.collect {|s| s.tr('/', '\\')}
+ filetype = nil
+ objdump(objs) do |l|
+ if (filetype = l[/^File Type: (.+)/, 1])..(/^\f/ =~ l)
+ case filetype
+ when /OBJECT/, /LIBRARY/
+ next if /^[[:xdigit:]]+ 0+ UNDEF / =~ l
+ next unless /External/ =~ l
+ next unless l.sub!(/.*?\s(\(\)\s+)?External\s+\|\s+/, '')
+ is_data = !$1
+ if noprefix or /^[@_]/ =~ l
+ next if /(?!^)@.*@/ =~ l || /@[[:xdigit:]]{16}$/ =~ l
+ l.sub!(/^[@_]/, '') if /@\d+$/ !~ l
+ elsif !l.sub!(/^(\S+) \([^@?\`\']*\)$/, '\1')
+ next
+ end
+ when /DLL/
+ next unless l.sub!(/^\s*\d+\s+[[:xdigit:]]+\s+[[:xdigit:]]+\s+/, '')
+ else
+ next
+ end
+ yield l.strip, is_data
+ end
+ end
+ yield "strcasecmp", "msvcrt.stricmp"
+ yield "strncasecmp", "msvcrt.strnicmp"
+ end
+end
+
+class Exports::Mingw < Exports
+ def self.nm
+ @@nm ||= RbConfig::CONFIG["NM"]
+ end
+
+ def each_line(objs, &block)
+ IO.foreach("|#{self.class.nm} --extern --defined #{objs.join(' ')}", &block)
+ end
+
+ def each_export(objs)
+ objdump(objs) do |l|
+ yield $1 if / [[:upper:]] _(.*)$/ =~ l
+ end
+ yield "strcasecmp", "_stricmp"
+ yield "strncasecmp", "_strnicmp"
+ end
+
+ def symbols()
+ @syms.select {|k, v| v}.sort.collect {|k, v| "#{k}=#{v}"}
+ end
+end
+
+END {
+ exports = Exports.extract(ARGV)
+ Exports.output {|f| f.puts(*exports)}
+}