def generate(src, options={})
options = {:expand_types=>options} unless Hash === options
expand_types = options[:expand_types]
singleton = options[:singleton]
result = self.strip_comments(src)
signature = parse_signature(src, !expand_types)
function_name = signature['name']
method_name = options[:method_name]
method_name ||= test_to_normal function_name
return_type = signature['return']
arity = signature['arity']
raise ArgumentError, "too many arguments" if arity > MAGIC_ARITY_THRESHOLD
if expand_types then
prefix = "static VALUE #{function_name}("
if arity == MAGIC_ARITY then
prefix += "int argc, VALUE *argv, VALUE self"
else
prefix += "VALUE self"
prefix += signature['args'].map { |arg, type| ", VALUE _#{arg}"}.join
end
prefix += ") {\n"
prefix += signature['args'].map { |arg, type|
" #{type} #{arg} = #{ruby2c(type)}(_#{arg});\n"
}.join
result.sub!(/[^;\/\"\>]+#{function_name}\s*\([^\{]+\{/, "\n" + prefix)
result.sub!(/\A\n/, '')
unless return_type == "void" then
raise SyntaxError, "Couldn't find return statement for #{function_name}" unless
result =~ /return/
result.gsub!(/return\s+([^\;\}]+)/) do
"return #{c2ruby(return_type)}(#{$1})"
end
else
result.sub!(/\s*\}\s*\Z/, "\nreturn Qnil;\n}")
end
else
prefix = "static #{return_type} #{function_name}("
result.sub!(/[^;\/\"\>]+#{function_name}\s*\(/, prefix)
result.sub!(/\A\n/, '')
end
delta = if result =~ /\A(static.*?\{)/m then
$1.split(/\n/).size
else
warn "WAR\NING: Can't find signature in #{result.inspect}\n" unless $TESTING
0
end
file, line = caller[1].split(/:/)
result = "# line #{line.to_i + delta} \"#{file}\"\n" + result unless $DEBUG and not $TESTING
@src << result
@sig[function_name] = [arity,singleton,method_name]
return result if $TESTING
end