PageRenderTime 44ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/src/ruby/rjmethod.rb

http://github.com/koichiro/rava
Ruby | 227 lines | 186 code | 24 blank | 17 comment | 14 complexity | 5bc69673c5a93ec13e7fb1193d2ac58c MD5 | raw file
  1. #!/usr/bin/ruby
  2. # -*- coding: utf-8 -*-
  3. # @file rjmethod.rb
  4. # @author K.S.
  5. #
  6. # $Date: 2002/10/14 13:59:49 $
  7. # $Id: rjmethod.rb,v 1.2 2002/10/14 13:59:49 ko1 Exp $
  8. #
  9. # Create : K.S. 02/10/09 06:10:01
  10. #
  11. #
  12. #
  13. #
  14. require 'rjopcodeinfo'
  15. require 'rjnative'
  16. class RJMethod
  17. include RJOpcodeinfo
  18. attr_reader :mname
  19. attr_reader :mdesc
  20. attr_reader :code
  21. attr_reader :max_local
  22. attr_reader :max_stack
  23. attr_reader :arg_size
  24. attr_reader :ret_size
  25. attr_reader :owner
  26. def initialize owner,cls
  27. @cls = cls
  28. @owner = owner
  29. @exception_table = []
  30. load
  31. end
  32. def load
  33. @access_flag = u2
  34. @mname = @owner.const[u2]
  35. @mdesc = @owner.const[u2]
  36. @arg_size = calc_arg_size
  37. @ret_size = calc_ret_size
  38. @max_local = @arg_size # native では最低 arg_size
  39. @max_stack = 2 # native では最低 2
  40. attributes_count = u2
  41. attributes_count.times{
  42. load_attributes
  43. }
  44. end
  45. def load_attributes
  46. attr_name = @owner.const[u2]
  47. attribute_length = u4
  48. if attr_name == 'Code'
  49. @max_stack = u2
  50. @max_local = u2
  51. @code_length = u4
  52. @code = @cls.read @code_length
  53. exception_table_length = u2
  54. exception_table_length.times{
  55. start_pc = u2
  56. end_pc = u2
  57. handler_pc = u2
  58. catch_type = u2
  59. @exception_table << [start_pc,end_pc,handler_pc,catch_type]
  60. }
  61. attributes_count = u2
  62. attributes_count.times{
  63. attr_name = u2
  64. attr_length = u4
  65. @cls.read attr_length
  66. # raise 'not supported'
  67. }
  68. else
  69. @cls.read attribute_length
  70. end
  71. end
  72. def to_s
  73. "RJMethod . #{@mname} : #{@mdesc} @ #{@owner.this_class}"
  74. end
  75. def verbose
  76. ret =
  77. "name : #{@mname}\n" +
  78. "type : #{@mdesc}\n" +
  79. "stack: #{@max_stack}\n" +
  80. "local: #{@max_local}\n" +
  81. "len : #{@code_length}\n"+
  82. "code :\n"
  83. if is_native?
  84. ret +=
  85. " : ==> native method\n"
  86. return ret
  87. end
  88. i = 0
  89. while i<@code_length
  90. c = @code[i]
  91. len = get_opcode_length c
  92. if len == 0
  93. len += 1
  94. len += (4 - (i+1)%4) % 4
  95. if c == 0xab # lookupswitch
  96. len += 4
  97. pairs = (@code[i+len] << 24) + (@code[i+len+1] << 16) +
  98. (@code[i+len+2] << 8)+ (@code[i+len+3])
  99. len += 4 + pairs * 2
  100. else # tableswitch
  101. len += 4
  102. low = (@code[i+len] << 24) + (@code[i+len+1] << 16) +
  103. (@code[i+len+2] << 8)+ (@code[i+len+3])
  104. len += 4
  105. high = (@code[i+len] << 24) + (@code[i+len+1] << 16) +
  106. (@code[i+len+2] << 8)+ (@code[i+len+3])
  107. len += 4
  108. len += 4 + (high - low + 1) * 4
  109. end
  110. end
  111. opt = get_opcode_arg c
  112. case opt
  113. when 'cc'
  114. opt = @owner.const[(@code[i+1] << 8) + @code[i+2]]
  115. when 'ii'
  116. opt = @code[i+1,2].reverse.unpack 's'
  117. when '1'
  118. opt = @code[i+1].to_i
  119. end
  120. ret += "#{sprintf("%4d",i)}\t#{OpcodeName[c]} #{opt}\n"
  121. i+=len
  122. end
  123. ret
  124. end
  125. def const idx
  126. @owner.const[idx]
  127. end
  128. def calc_arg_size
  129. i = 0
  130. @mdesc =~ /\((.*)\)/
  131. ret = 0
  132. lflg = false
  133. $1.split('').each{|c|
  134. if lflg
  135. if c == ';'
  136. lflg = false
  137. end
  138. next
  139. end
  140. case c
  141. when 'B','C','F','I','S','Z'
  142. ret += 1
  143. when 'D','J'
  144. ret += 2
  145. when 'L'
  146. ret += 1 ; lflg = true
  147. end
  148. # [ は見なくていいのかって
  149. # いいんじゃないの 無視しちゃって
  150. }
  151. ret + (is_static? ? 0 : 1)
  152. end
  153. def calc_ret_size
  154. i = 0
  155. ret = 0
  156. flg = false
  157. @mdesc =~ /\(.*\)(.)/
  158. case $1
  159. when 'B','C','F','I','S','Z','L','['
  160. return 1
  161. when 'J'
  162. return 2
  163. when 'D'
  164. return 3
  165. end
  166. return 0 # void
  167. end
  168. def is_static?
  169. @access_flag & 0x0008 != 0
  170. end
  171. def is_native?
  172. @access_flag & 0x0100 != 0
  173. end
  174. def invoke_native args
  175. # native 探し
  176. nm = 'RJN_' + @owner.this_class.gsub('/','_')
  177. begin
  178. nc = Module.const_get(nm)
  179. rescue NameError
  180. puts "can't find that native method support class : #{nm}"
  181. puts "plz write this class :-) jrnative.rb will helps this."
  182. puts "ex) ruby rjnative.rb #{@owner.this_class}"
  183. puts ''
  184. raise
  185. end
  186. nc.__send__ @mname,@mdesc,args
  187. end
  188. # read helper
  189. private
  190. def u4
  191. ((@cls.read 4).unpack 'N')[0]
  192. end
  193. def u2
  194. ((@cls.read 2).unpack 'n')[0]
  195. end
  196. def u1
  197. ((@cls.read 1).unpack 'C')[0]
  198. end
  199. end