class SystemNavigation::InstructionStream::Instruction

Attributes

op_id[R]
opcode[R]

Public Class Methods

new(str) click to toggle source
# File lib/system_navigation/instruction_stream/instruction.rb, line 8
def initialize(str)
  @raw = StringScanner.new(str)
  @pos = nil
  @opcode = ''
  @operand = nil
  @evaling_str = nil
  @lineno = nil
  @op_id = nil
  @ivar = nil
  @gvar = nil
  @cvar = nil
  @service_instruction = false
end
parse(str) click to toggle source
# File lib/system_navigation/instruction_stream/instruction.rb, line 4
def self.parse(str)
  self.new(str).parse
end

Public Instance Methods

accessing_cvar?() click to toggle source
# File lib/system_navigation/instruction_stream/instruction.rb, line 129
def accessing_cvar?
  @opcode == 'getclassvariable' || @opcode == 'setclassvariable'
end
accessing_gvar?() click to toggle source
# File lib/system_navigation/instruction_stream/instruction.rb, line 125
def accessing_gvar?
  @opcode == 'getglobal' || @opcode == 'setglobal'
end
accessing_ivar?() click to toggle source
# File lib/system_navigation/instruction_stream/instruction.rb, line 121
def accessing_ivar?
  @opcode == 'getinstancevariable' || @opcode == 'setinstancevariable'
end
duparrays?(str) click to toggle source
# File lib/system_navigation/instruction_stream/instruction.rb, line 204
def duparrays?(str)
  s = case str
      when Array, Hash then Regexp.escape(str.inspect)
      else str
      end

  !!(self.opcode == 'duparray' && @operand.match(/:#{s}[,\]]/))
end
dynamically_reads_ivar?() click to toggle source
# File lib/system_navigation/instruction_stream/instruction.rb, line 145
def dynamically_reads_ivar?
  self.op_id == 'instance_variable_get'
end
dynamically_writes_ivar?() click to toggle source
# File lib/system_navigation/instruction_stream/instruction.rb, line 149
def dynamically_writes_ivar?
  @op_id == 'instance_variable_set'
end
evaling_str() click to toggle source
# File lib/system_navigation/instruction_stream/instruction.rb, line 217
def evaling_str
  @evaling_str ||= @operand.sub!(/\A"(.+)"/, '\1')
end
evals?() click to toggle source
# File lib/system_navigation/instruction_stream/instruction.rb, line 169
def evals?
  self.op_id == 'eval'
end
find_message() click to toggle source
# File lib/system_navigation/instruction_stream/instruction.rb, line 221
def find_message
  return unless sending?

  @op_id
end
parse() click to toggle source
# File lib/system_navigation/instruction_stream/instruction.rb, line 22
def parse
  return if parse_service_instruction

  parse_position
  parse_opcode
  parse_operand
  parse_lineno
  parse_op_id
  parse_var

  self
end
parse_cvar() click to toggle source
# File lib/system_navigation/instruction_stream/instruction.rb, line 112
def parse_cvar
  return unless accessing_cvar?

  cvar = StringScanner.new(@operand)
  @cvar = cvar.scan(/:[^,]+/)[1..-1].to_sym
  cvar.terminate
  @cvar
end
parse_gvar() click to toggle source
# File lib/system_navigation/instruction_stream/instruction.rb, line 103
def parse_gvar
  return unless accessing_gvar?

  gvar = StringScanner.new(@operand)
  @gvar = gvar.scan(/[^,]+/).to_sym
  gvar.terminate
  @gvar
end
parse_ivar() click to toggle source
# File lib/system_navigation/instruction_stream/instruction.rb, line 94
def parse_ivar
  return unless accessing_ivar?

  ivar = StringScanner.new(@operand)
  @ivar = ivar.scan(/:[^,]+/)[1..-1].to_sym
  ivar.terminate
  @ivar
end
parse_lineno() click to toggle source
# File lib/system_navigation/instruction_stream/instruction.rb, line 73
def parse_lineno
  n = @raw.scan(/[0-9]+/)
  @lineno = n.to_i if n
  @raw.skip(/\)/)
end
parse_op_id() click to toggle source
# File lib/system_navigation/instruction_stream/instruction.rb, line 79
def parse_op_id
  return unless sending?

  callinfo = StringScanner.new(@operand)
  callinfo.skip(/<callinfo!mid:/)
  @op_id = callinfo.scan(/\S+(?=,)/)
  callinfo.terminate
end
parse_opcode() click to toggle source
# File lib/system_navigation/instruction_stream/instruction.rb, line 47
def parse_opcode
  @opcode = @raw.scan(/[a-zA-Z0-9_]+/)
  @raw.skip(/\s*/)
end
parse_operand() click to toggle source
# File lib/system_navigation/instruction_stream/instruction.rb, line 52
def parse_operand
  if @raw.check(/</)
    @operand = @raw.scan(/<.+>/)
  elsif @raw.check(/\[/)
    @operand = @raw.scan(/\[.*\]/)
  elsif @raw.check(/"/)
    @operand = @raw.scan(/".*"/)
  elsif @raw.check(%r{/})
    @operand = @raw.scan(%r{/.*/})
  else
    @operand = @raw.scan(/-?[0-9a-zA-Z:@_=.$]+/)

    if @raw.peek(1) == ','
      @operand << @raw.scan(/[^\(]*/).rstrip
    end
  end

  @raw.skip(/\s*\(?/)
  @raw.skip(/\s*/)
end
parse_position() click to toggle source
# File lib/system_navigation/instruction_stream/instruction.rb, line 41
def parse_position
  n = @raw.scan(/[0-9]{4,6}/)
  @pos = n.to_i if n
  @raw.skip(/\s*/)
end
parse_service_instruction() click to toggle source
# File lib/system_navigation/instruction_stream/instruction.rb, line 35
def parse_service_instruction
  if @raw.peek(2) == '==' || @raw.peek(6) !~ /[0-9]{4,6} /
    @service_instruction = true
  end
end
parse_var() click to toggle source
# File lib/system_navigation/instruction_stream/instruction.rb, line 88
def parse_var
  parse_ivar
  parse_gvar
  parse_cvar
end
putnils?(str) click to toggle source
# File lib/system_navigation/instruction_stream/instruction.rb, line 199
def putnils?(str)
  return false unless self.opcode == 'putnil'
  @operand == str.inspect
end
putobjects?(str) click to toggle source
# File lib/system_navigation/instruction_stream/instruction.rb, line 188
def putobjects?(str)
  return false unless @opcode == 'putobject'

  s = (str.instance_of?(String) ? Regexp.escape(str) : str)

  return true if @operand.match(/(?::#{s}\z|\[.*:#{s},.*\])/)
  return true if @operand == str.inspect

  false
end
putstrings?(str) click to toggle source
# File lib/system_navigation/instruction_stream/instruction.rb, line 173
def putstrings?(str)
  return false unless self.opcode == 'putstring'

  s = str.inspect

  return true if @operand == s || @operand == %|"#{s}"|
  if @operand.match(/(eval\()?.*:?#{str}[^[\w;]].*\)?/)
    return true
  else

  end

  false
end
reads_cvar?(cvar) click to toggle source
# File lib/system_navigation/instruction_stream/instruction.rb, line 161
def reads_cvar?(cvar)
  @opcode == 'getclassvariable' && @cvar == cvar
end
reads_gvar?(gvar) click to toggle source
# File lib/system_navigation/instruction_stream/instruction.rb, line 153
def reads_gvar?(gvar)
  @opcode == 'getglobal' && @gvar == gvar
end
reads_ivar?(ivar) click to toggle source
# File lib/system_navigation/instruction_stream/instruction.rb, line 137
def reads_ivar?(ivar)
  @opcode == 'getinstancevariable' && @ivar == ivar
end
sends_msg?(message) click to toggle source
# File lib/system_navigation/instruction_stream/instruction.rb, line 213
def sends_msg?(message)
  !!(sending? && @op_id == message.to_s)
end
vm_operative?() click to toggle source
# File lib/system_navigation/instruction_stream/instruction.rb, line 133
def vm_operative?
  @service_instruction == false
end
writes_cvar?(cvar) click to toggle source
# File lib/system_navigation/instruction_stream/instruction.rb, line 165
def writes_cvar?(cvar)
  @opcode == 'setclassvariable' && @cvar == cvar
end
writes_gvar?(gvar) click to toggle source
# File lib/system_navigation/instruction_stream/instruction.rb, line 157
def writes_gvar?(gvar)
  @opcode == 'setglobal' && @gvar == gvar
end
writes_ivar?(ivar) click to toggle source
# File lib/system_navigation/instruction_stream/instruction.rb, line 141
def writes_ivar?(ivar)
  @opcode == 'setinstancevariable' && @ivar == ivar
end

Private Instance Methods

sending?() click to toggle source
# File lib/system_navigation/instruction_stream/instruction.rb, line 229
def sending?
  @opcode == 'opt_send_without_block' || @opcode == 'send'
end