RubyでHSPのオブジェクトファイルのインスペクタを作り中:2
TYPENAMES = %w( TYPE_MARK TYPE_VAR TYPE_STRING TYPE_DNUM TYPE_INUM TYPE_STRUCT TYPE_XLABEL TYPE_LABEL TYPE_INTCMD TYPE_EXTCMD TYPE_EXTSYSVAR TYPE_CMPCMD TYPE_MODCMD TYPE_INTFUNC TYPE_SYSVAR TYPE_PROGCMD TYPE_DLLFUNC TYPE_DLLCTRL TYPE_USERDEF ) TYPENAMES.each_with_index do |typename, i| Object.const_set( typename, i ) end PROGCMDS = %w( goto gosub return break repeat loop continue wait await dim sdim foreach * dimtype dup dupptr end stop newmod * delmod mref run exgoto on mcall assert logmes ) INTCMDS = %w( onexit onerror onkey onclick oncmd * * * * * * * * * * * * exist delete mkdir chdir dirlist bload bsave bcopy memfile poke wpoke lpoke getstr chdpm memexpand memcpy memset notesel noteadd notedel noteload notesave randomize noteunsel noteget ) CMPCMDS = %w( if else ) EXTCMDS = %w( button chgdisp exec dialog * * * * mmload mmplay mmstop mci pset pget syscolor mes title pos circle cls font sysfont objsize picload color palcolor palette redraw width gsel gcopy gzoom gmode bmpsave hsvcolor getkey listbox chkbox combox input mesbox buffer screen bgscr mouse objsel groll line clrobj boxf objprm objmode stick grect grotate gsquare ) EXTSYSVARS = %w( mousex mousey mousew hwnd hinstance hdc ) EXTFUNCS = %w( ginfo objinfo dirinfo sysinfo ) DLLCTRLS = %w( newcom querycom delcom cnvstow comres axobj winobj sendmsg comevent comevarg sarrayconv ) DLLCTRL_FUNCS = %w( callfunc cnvwtos comevdisp libptr ) SYSVARS = %w( system hspstat hspver stat cnt err strsize looplev sublev iparam wparam lparam refstr refdval ) INTFUNCS = %w( int rnd strlen length length2 length3 length4 vartype gettime peek wpeek lpeek varptr varuse noteinfo instr abs limit ) INTFUNCS[0x100,0] = %w( str strmid strf getpath ) INTFUNCS[0x180,0] = %w( sin cos tan atan sqrt double absf expf logf limitf ) def get_ds( ds, i ) ds[i..-1].split("\0")[0] end obj = ARGF.read max_val = obj[8,4].unpack('i')[0] pt_cs, max_cs, pt_ds, max_ds, pt_ot, max_ot, pt_dinfo, max_dinfo = obj[16,32].unpack('i8') cs = obj[pt_cs, max_cs] ds = obj[pt_ds, max_ds] ot = obj[pt_ot, max_ot] dinfo = obj[pt_dinfo, max_dinfo] labels = {} ot.unpack( 'i*' ).each_with_index do |ofs,id| if labels[ofs] labels[ofs] << id else labels[ofs] = [id] end end varnames = [] i = 0 while i < max_dinfo && dinfo[i] != 255 ofs = dinfo[i] i += 1 case ofs when 254 filename = get_ds( ds, (dinfo[i,3]+"\0").unpack('i')[0] ) lineno = dinfo[i,2].unpack('s')[0] i += 3 + 2 when 253 varnames << get_ds( ds, (dinfo[i,3]+"\0").unpack('i')[0] ) i += 3 + 2 when 252 i += 2 else i += 1 end end i = 0 while i < max_cs if labels[i/2] labels[i/2].each do |id| puts "*label#{id}" end end c = *cs[i,2].unpack('s') type = c & 0x1fff ex1 = c & 0x2000 != 0 ex2 = c & 0x4000 != 0 if big_flag = c & 0x8000 != 0 code = cs[i+2,4].unpack('i')[0] else code = cs[i+2,2].unpack('S')[0] end print "#{TYPENAMES[type]}" case type when TYPE_INTFUNC if INTFUNCS[code] print '(%s)' % INTFUNCS[code] else print '(0x%x)' % code end when TYPE_EXTCMD if EXTCMDS[code] print '(%s)' % EXTCMDS[code] else print '(0x%x)' % code end when TYPE_PROGCMD if PROGCMDS[code] print '(%s)' % PROGCMDS[code] else print '(0x%x)' % code end when TYPE_VAR print '(%p)' % ( varnames[code] || code ) when TYPE_INUM print "(#{code})" when TYPE_DNUM print '(%s)' % ds[code,8].unpack('d') when TYPE_MARK if (0x20..0x7e) === code print "('#{code.chr}')" else print '(0x%02x)' % code end when TYPE_STRING print '(%p)' % get_ds( ds, code ) else print '(0x%x)' % code end print ' ex1' if ex1 print ' ex2' if ex2 puts if big_flag i += 2 + 4 else i += 2 + 2 end end
単項 - が内部的には * -1 となっていたとは知らなかった。