Subversion Repositories dloadsdl

Rev

Rev 2 | Blame | Compare with Previous | Last modification | View Log | RSS feed

#!/usr/bin/env ruby
# Example Application for Dynamic Loading of SDL
# Copyright (C) 2010  Matthias -apoc- Hecker <apoc@sixserv.org>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

DEBUG = false

LIBSDL_HANDLE = 'sdlhandle'
LIBSDL_REFSTRUCT = 'proc_symbols_sdl'
DLSYM = 'LoadSymbol'

sdl_include = "/usr/include/SDL"
sdl_include = ARGV[0] if ARGV.length == 1
if not File.directory? sdl_include
  puts "Include Path not a directory"
  exit
end

so_lib = "/usr/lib/libSDL.so"
so_lib = ARGV[1] if ARGV.length == 2
if not File.exists? so_lib
  puts "Shared Object file not found"
  exit
end

puts "Load Library Symbol Names from #{so_lib}"
sdl_symbols = []
nm = `nm #{so_lib} | grep ' T '`
nm_scan = nm.scan /^[^ ]+ T (.*)$/
nm_scan.each do |sym|
  sdl_symbols << sym[0] if not sym[0].match /^_/
end
puts "Found #{sdl_symbols.length} Symbols"

puts "Search for SDL headers in #{sdl_include}"

sdl_headers = []

include_dir = Dir.new(sdl_include)
include_dir.each do |file|
  if file.match /^SDL.*\.h$/
    next if file == 'SDL_syswm.h'

    sdl_headers << file
  end
end

puts "Found #{sdl_headers.length} SDL headers"
exit if sdl_headers.length == 0

puts "Parse for function declarations"
header_fnk_declarations = {}
num_declarations = 0

sdl_headers.each do |sdl_header|
  header_fnk_declarations[sdl_header] = "" if not header_fnk_declarations.has_key?(sdl_header)

  header = ''
  IO.readlines(sdl_include + "/" + sdl_header).each { |line| header += line }

  fnk_declarations = []
 
  parse_fnk_declarations = header.scan /extern DECLSPEC (.*) SDLCALL ([^\(]+)\(([^\)]+)\);/
  parse_fnk_declarations.each do |declaration|
    if not sdl_symbols.include? declaration[1].strip
      puts "WARNING: Ignore symbol name #{declaration[1]}" if DEBUG
      next
    end

    puts if DEBUG
    puts declaration.inspect if DEBUG

    fnk_declaration = {
      :return => declaration[0].strip,
      :name   => declaration[1].strip,
      :params => declaration[2].split(',').map { |param|
        if param.match(/ /)
          param.gsub(/([^ ^*]+)$/, '').strip
        elsif not param.empty?
          param
        end
      }
    }
    # remove empty params
    fnk_declaration[:params].each_index do |i|
      if fnk_declaration[:params][i].empty?
        fnk_declaration[:params].delete_at(i)
      end
    end
    num_declarations += 1

    puts fnk_declaration.inspect if DEBUG
    puts " ##### ERROR: :return is empty" if fnk_declaration[:return].empty? and DEBUG
    puts " ##### ERROR: :name is empty"   if fnk_declaration[:name].empty?   and DEBUG
    puts " ##### ERROR: :params is empty" if fnk_declaration[:params].empty? and DEBUG
    puts "--------------------------------------------------------------------------------" if DEBUG

    fnk_declarations << fnk_declaration
  end

  header_fnk_declarations[sdl_header] = fnk_declarations
end

puts "Found #{num_declarations} function declarations in #{header_fnk_declarations.length} headers"

puts
puts "/**** Auto generated function pointer declarations (by libsdl_header_parser.rb) ****/"
header_fnk_declarations.each_pair do |header, fnk_declarations|
  next if fnk_declarations.empty?
  puts "// Function declarations for #{header}"
  fnk_declarations.each do |fnk_declaration|
    puts "#{fnk_declaration[:return]} (*#{fnk_declaration[:name]})(#{fnk_declaration[:params].join(', ')});"
  end
  puts
end
puts "/**** End auto generated function pointer declarations ****/"
puts

puts
puts "/**** Auto generated function symbol resolve via #{DLSYM} (by libsdl_header_parser.rb) ****/"
header_fnk_declarations.each_pair do |header, fnk_declarations|
  next if fnk_declarations.empty?
  puts "// Function declarations for #{header}"
  fnk_declarations.each do |fnk_declaration|
    puts "#{LIBSDL_REFSTRUCT}->#{fnk_declaration[:name]} = (#{fnk_declaration[:return]} (*)(#{fnk_declaration[:params].join(', ')})) LoadSymbol(\"#{fnk_declaration[:name]}\");"
  end
  puts
end
puts "/**** End auto generated function symbol resolve ****/"
puts