metasm 1.0.1 → 1.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +1 -0
- data/.hgtags +3 -0
- data/Gemfile +1 -0
- data/INSTALL +61 -0
- data/LICENCE +458 -0
- data/README +29 -21
- data/Rakefile +10 -0
- data/TODO +10 -12
- data/doc/code_organisation.txt +2 -0
- data/doc/core/DynLdr.txt +247 -0
- data/doc/core/ExeFormat.txt +43 -0
- data/doc/core/Expression.txt +220 -0
- data/doc/core/GNUExports.txt +27 -0
- data/doc/core/Ia32.txt +236 -0
- data/doc/core/SerialStruct.txt +108 -0
- data/doc/core/VirtualString.txt +145 -0
- data/doc/core/WindowsExports.txt +61 -0
- data/doc/core/index.txt +1 -0
- data/doc/style.css +6 -3
- data/doc/usage/debugger.txt +327 -0
- data/doc/usage/index.txt +1 -0
- data/doc/use_cases.txt +2 -2
- data/metasm.gemspec +22 -0
- data/{lib/metasm.rb → metasm.rb} +11 -3
- data/{lib/metasm → metasm}/compile_c.rb +13 -7
- data/metasm/cpu/arc.rb +8 -0
- data/metasm/cpu/arc/decode.rb +425 -0
- data/metasm/cpu/arc/main.rb +191 -0
- data/metasm/cpu/arc/opcodes.rb +588 -0
- data/{lib/metasm → metasm/cpu}/arm.rb +7 -5
- data/{lib/metasm → metasm/cpu}/arm/debug.rb +2 -2
- data/{lib/metasm → metasm/cpu}/arm/decode.rb +13 -12
- data/{lib/metasm → metasm/cpu}/arm/encode.rb +23 -8
- data/{lib/metasm → metasm/cpu}/arm/main.rb +0 -3
- data/metasm/cpu/arm/opcodes.rb +324 -0
- data/{lib/metasm → metasm/cpu}/arm/parse.rb +25 -13
- data/{lib/metasm → metasm/cpu}/arm/render.rb +2 -2
- data/metasm/cpu/arm64.rb +15 -0
- data/metasm/cpu/arm64/debug.rb +38 -0
- data/metasm/cpu/arm64/decode.rb +289 -0
- data/metasm/cpu/arm64/encode.rb +41 -0
- data/metasm/cpu/arm64/main.rb +105 -0
- data/metasm/cpu/arm64/opcodes.rb +232 -0
- data/metasm/cpu/arm64/parse.rb +20 -0
- data/metasm/cpu/arm64/render.rb +95 -0
- data/{lib/metasm/ppc.rb → metasm/cpu/bpf.rb} +2 -4
- data/metasm/cpu/bpf/decode.rb +142 -0
- data/metasm/cpu/bpf/main.rb +60 -0
- data/metasm/cpu/bpf/opcodes.rb +81 -0
- data/metasm/cpu/bpf/render.rb +41 -0
- data/metasm/cpu/cy16.rb +9 -0
- data/metasm/cpu/cy16/decode.rb +253 -0
- data/metasm/cpu/cy16/main.rb +63 -0
- data/metasm/cpu/cy16/opcodes.rb +78 -0
- data/metasm/cpu/cy16/render.rb +41 -0
- data/metasm/cpu/dalvik.rb +11 -0
- data/{lib/metasm → metasm/cpu}/dalvik/decode.rb +35 -13
- data/{lib/metasm → metasm/cpu}/dalvik/main.rb +51 -2
- data/{lib/metasm → metasm/cpu}/dalvik/opcodes.rb +19 -11
- data/metasm/cpu/ia32.rb +17 -0
- data/{lib/metasm → metasm/cpu}/ia32/compile_c.rb +5 -7
- data/{lib/metasm → metasm/cpu}/ia32/debug.rb +5 -5
- data/{lib/metasm → metasm/cpu}/ia32/decode.rb +246 -59
- data/{lib/metasm → metasm/cpu}/ia32/decompile.rb +7 -7
- data/{lib/metasm → metasm/cpu}/ia32/encode.rb +19 -13
- data/{lib/metasm → metasm/cpu}/ia32/main.rb +51 -8
- data/metasm/cpu/ia32/opcodes.rb +1424 -0
- data/{lib/metasm → metasm/cpu}/ia32/parse.rb +47 -16
- data/{lib/metasm → metasm/cpu}/ia32/render.rb +31 -4
- data/metasm/cpu/mips.rb +14 -0
- data/{lib/metasm → metasm/cpu}/mips/compile_c.rb +1 -1
- data/metasm/cpu/mips/debug.rb +42 -0
- data/{lib/metasm → metasm/cpu}/mips/decode.rb +46 -16
- data/{lib/metasm → metasm/cpu}/mips/encode.rb +4 -3
- data/{lib/metasm → metasm/cpu}/mips/main.rb +11 -4
- data/{lib/metasm → metasm/cpu}/mips/opcodes.rb +86 -17
- data/{lib/metasm → metasm/cpu}/mips/parse.rb +1 -1
- data/{lib/metasm → metasm/cpu}/mips/render.rb +1 -1
- data/{lib/metasm/dalvik.rb → metasm/cpu/msp430.rb} +1 -1
- data/metasm/cpu/msp430/decode.rb +247 -0
- data/metasm/cpu/msp430/main.rb +62 -0
- data/metasm/cpu/msp430/opcodes.rb +101 -0
- data/{lib/metasm → metasm/cpu}/pic16c/decode.rb +6 -7
- data/{lib/metasm → metasm/cpu}/pic16c/main.rb +0 -0
- data/{lib/metasm → metasm/cpu}/pic16c/opcodes.rb +1 -1
- data/{lib/metasm/mips.rb → metasm/cpu/ppc.rb} +4 -4
- data/{lib/metasm → metasm/cpu}/ppc/decode.rb +18 -12
- data/{lib/metasm → metasm/cpu}/ppc/decompile.rb +3 -3
- data/{lib/metasm → metasm/cpu}/ppc/encode.rb +2 -2
- data/{lib/metasm → metasm/cpu}/ppc/main.rb +17 -12
- data/{lib/metasm → metasm/cpu}/ppc/opcodes.rb +11 -5
- data/metasm/cpu/ppc/parse.rb +55 -0
- data/metasm/cpu/python.rb +8 -0
- data/metasm/cpu/python/decode.rb +136 -0
- data/metasm/cpu/python/main.rb +36 -0
- data/metasm/cpu/python/opcodes.rb +180 -0
- data/{lib/metasm → metasm/cpu}/sh4.rb +1 -1
- data/{lib/metasm → metasm/cpu}/sh4/decode.rb +48 -17
- data/{lib/metasm → metasm/cpu}/sh4/main.rb +13 -4
- data/{lib/metasm → metasm/cpu}/sh4/opcodes.rb +7 -8
- data/metasm/cpu/x86_64.rb +15 -0
- data/{lib/metasm → metasm/cpu}/x86_64/compile_c.rb +28 -17
- data/{lib/metasm → metasm/cpu}/x86_64/debug.rb +4 -4
- data/{lib/metasm → metasm/cpu}/x86_64/decode.rb +57 -15
- data/{lib/metasm → metasm/cpu}/x86_64/encode.rb +55 -26
- data/{lib/metasm → metasm/cpu}/x86_64/main.rb +14 -6
- data/metasm/cpu/x86_64/opcodes.rb +136 -0
- data/{lib/metasm → metasm/cpu}/x86_64/parse.rb +10 -2
- data/metasm/cpu/x86_64/render.rb +35 -0
- data/metasm/cpu/z80.rb +9 -0
- data/metasm/cpu/z80/decode.rb +313 -0
- data/metasm/cpu/z80/main.rb +67 -0
- data/metasm/cpu/z80/opcodes.rb +224 -0
- data/metasm/cpu/z80/render.rb +59 -0
- data/{lib/metasm/os/main.rb → metasm/debug.rb} +160 -401
- data/{lib/metasm → metasm}/decode.rb +35 -4
- data/{lib/metasm → metasm}/decompile.rb +15 -16
- data/{lib/metasm → metasm}/disassemble.rb +201 -45
- data/{lib/metasm → metasm}/disassemble_api.rb +651 -87
- data/{lib/metasm → metasm}/dynldr.rb +220 -133
- data/{lib/metasm → metasm}/encode.rb +10 -1
- data/{lib/metasm → metasm}/exe_format/a_out.rb +9 -6
- data/{lib/metasm → metasm}/exe_format/autoexe.rb +1 -0
- data/{lib/metasm → metasm}/exe_format/bflt.rb +57 -27
- data/{lib/metasm → metasm}/exe_format/coff.rb +11 -3
- data/{lib/metasm → metasm}/exe_format/coff_decode.rb +53 -20
- data/{lib/metasm → metasm}/exe_format/coff_encode.rb +11 -13
- data/{lib/metasm → metasm}/exe_format/dex.rb +13 -5
- data/{lib/metasm → metasm}/exe_format/dol.rb +1 -0
- data/{lib/metasm → metasm}/exe_format/elf.rb +93 -57
- data/{lib/metasm → metasm}/exe_format/elf_decode.rb +143 -34
- data/{lib/metasm → metasm}/exe_format/elf_encode.rb +122 -31
- data/metasm/exe_format/gb.rb +65 -0
- data/metasm/exe_format/javaclass.rb +424 -0
- data/{lib/metasm → metasm}/exe_format/macho.rb +204 -16
- data/{lib/metasm → metasm}/exe_format/main.rb +26 -3
- data/{lib/metasm → metasm}/exe_format/mz.rb +1 -0
- data/{lib/metasm → metasm}/exe_format/nds.rb +7 -4
- data/{lib/metasm → metasm}/exe_format/pe.rb +71 -8
- data/metasm/exe_format/pyc.rb +167 -0
- data/{lib/metasm → metasm}/exe_format/serialstruct.rb +67 -14
- data/{lib/metasm → metasm}/exe_format/shellcode.rb +7 -3
- data/metasm/exe_format/shellcode_rwx.rb +114 -0
- data/metasm/exe_format/swf.rb +205 -0
- data/{lib/metasm → metasm}/exe_format/xcoff.rb +7 -7
- data/metasm/exe_format/zip.rb +335 -0
- data/metasm/gui.rb +13 -0
- data/{lib/metasm → metasm}/gui/cstruct.rb +35 -41
- data/{lib/metasm → metasm}/gui/dasm_coverage.rb +11 -11
- data/{lib/metasm → metasm}/gui/dasm_decomp.rb +7 -20
- data/{lib/metasm → metasm}/gui/dasm_funcgraph.rb +0 -0
- data/metasm/gui/dasm_graph.rb +1695 -0
- data/{lib/metasm → metasm}/gui/dasm_hex.rb +12 -8
- data/{lib/metasm → metasm}/gui/dasm_listing.rb +43 -28
- data/{lib/metasm → metasm}/gui/dasm_main.rb +310 -53
- data/{lib/metasm → metasm}/gui/dasm_opcodes.rb +5 -19
- data/{lib/metasm → metasm}/gui/debug.rb +93 -27
- data/{lib/metasm → metasm}/gui/gtk.rb +162 -40
- data/{lib/metasm → metasm}/gui/qt.rb +12 -2
- data/{lib/metasm → metasm}/gui/win32.rb +179 -42
- data/{lib/metasm → metasm}/gui/x11.rb +59 -59
- data/{lib/metasm → metasm}/main.rb +389 -264
- data/{lib/metasm/os/remote.rb → metasm/os/gdbremote.rb} +146 -54
- data/{lib/metasm → metasm}/os/gnu_exports.rb +1 -1
- data/{lib/metasm → metasm}/os/linux.rb +628 -151
- data/metasm/os/main.rb +330 -0
- data/{lib/metasm → metasm}/os/windows.rb +132 -42
- data/{lib/metasm → metasm}/os/windows_exports.rb +141 -0
- data/{lib/metasm → metasm}/parse.rb +26 -24
- data/{lib/metasm → metasm}/parse_c.rb +221 -116
- data/{lib/metasm → metasm}/preprocessor.rb +55 -40
- data/{lib/metasm → metasm}/render.rb +14 -38
- data/misc/hexdump.rb +2 -1
- data/misc/lint.rb +58 -0
- data/misc/txt2html.rb +9 -7
- data/samples/bindiff.rb +3 -4
- data/samples/dasm-plugins/bindiff.rb +15 -0
- data/samples/dasm-plugins/bookmark.rb +133 -0
- data/samples/dasm-plugins/c_constants.rb +57 -0
- data/samples/dasm-plugins/colortheme_solarized.rb +125 -0
- data/samples/dasm-plugins/cppobj_funcall.rb +60 -0
- data/samples/dasm-plugins/dasm_all.rb +70 -0
- data/samples/dasm-plugins/demangle_cpp.rb +31 -0
- data/samples/dasm-plugins/deobfuscate.rb +251 -0
- data/samples/dasm-plugins/dump_text.rb +35 -0
- data/samples/dasm-plugins/export_graph_svg.rb +86 -0
- data/samples/dasm-plugins/findgadget.rb +75 -0
- data/samples/dasm-plugins/hl_opcode.rb +32 -0
- data/samples/dasm-plugins/hotfix_gtk_dbg.rb +19 -0
- data/samples/dasm-plugins/imm2off.rb +34 -0
- data/samples/dasm-plugins/match_libsigs.rb +93 -0
- data/samples/dasm-plugins/patch_file.rb +95 -0
- data/samples/dasm-plugins/scanfuncstart.rb +36 -0
- data/samples/dasm-plugins/scanxrefs.rb +26 -0
- data/samples/dasm-plugins/selfmodify.rb +197 -0
- data/samples/dasm-plugins/stringsxrefs.rb +28 -0
- data/samples/dasmnavig.rb +1 -1
- data/samples/dbg-apihook.rb +24 -9
- data/samples/dbg-plugins/heapscan.rb +283 -0
- data/samples/dbg-plugins/heapscan/compiled_heapscan_lin.c +155 -0
- data/samples/dbg-plugins/heapscan/compiled_heapscan_win.c +128 -0
- data/samples/dbg-plugins/heapscan/graphheap.rb +616 -0
- data/samples/dbg-plugins/heapscan/heapscan.rb +709 -0
- data/samples/dbg-plugins/heapscan/winheap.h +174 -0
- data/samples/dbg-plugins/heapscan/winheap7.h +307 -0
- data/samples/dbg-plugins/trace_func.rb +214 -0
- data/samples/disassemble-gui.rb +35 -5
- data/samples/disassemble.rb +31 -6
- data/samples/dump_upx.rb +24 -12
- data/samples/dynamic_ruby.rb +12 -3
- data/samples/exeencode.rb +6 -5
- data/samples/factorize-headers-peimports.rb +1 -1
- data/samples/lindebug.rb +175 -381
- data/samples/metasm-shell.rb +1 -2
- data/samples/peldr.rb +2 -2
- data/tests/all.rb +1 -1
- data/tests/arc.rb +26 -0
- data/tests/dynldr.rb +22 -4
- data/tests/expression.rb +55 -0
- data/tests/graph_layout.rb +285 -0
- data/tests/ia32.rb +79 -26
- data/tests/mips.rb +9 -2
- data/tests/x86_64.rb +66 -18
- metadata +330 -218
- data/lib/metasm/arm/opcodes.rb +0 -177
- data/lib/metasm/gui.rb +0 -23
- data/lib/metasm/gui/dasm_graph.rb +0 -1354
- data/lib/metasm/ia32.rb +0 -14
- data/lib/metasm/ia32/opcodes.rb +0 -873
- data/lib/metasm/ppc/parse.rb +0 -52
- data/lib/metasm/x86_64.rb +0 -12
- data/lib/metasm/x86_64/opcodes.rb +0 -118
- data/samples/gdbclient.rb +0 -583
- data/samples/rubstop.rb +0 -399
@@ -740,6 +740,147 @@ EOL
|
|
740
740
|
end
|
741
741
|
|
742
742
|
patch_rubylib_to_current_interpreter
|
743
|
+
|
744
|
+
# mandiant import hash crap with ordinal imports (from pefile.py)
|
745
|
+
ih_ws232 = {
|
746
|
+
1 => 'accept', 2 => 'bind', 3 => 'closesocket', 4 => 'connect',
|
747
|
+
5 => 'getpeername', 6 => 'getsockname', 7 => 'getsockopt', 8 => 'htonl',
|
748
|
+
9 => 'htons', 10 => 'ioctlsocket', 11 => 'inet_addr', 12 => 'inet_ntoa',
|
749
|
+
13 => 'listen', 14 => 'ntohl', 15 => 'ntohs', 16 => 'recv',
|
750
|
+
17 => 'recvfrom', 18 => 'select', 19 => 'send', 20 => 'sendto',
|
751
|
+
21 => 'setsockopt', 22 => 'shutdown', 23 => 'socket', 24 => 'GetAddrInfoW',
|
752
|
+
25 => 'GetNameInfoW', 26 => 'WSApSetPostRoutine', 27 => 'FreeAddrInfoW', 28 => 'WPUCompleteOverlappedRequest',
|
753
|
+
29 => 'WSAAccept', 30 => 'WSAAddressToStringA', 31 => 'WSAAddressToStringW', 32 => 'WSACloseEvent',
|
754
|
+
33 => 'WSAConnect', 34 => 'WSACreateEvent', 35 => 'WSADuplicateSocketA', 36 => 'WSADuplicateSocketW',
|
755
|
+
37 => 'WSAEnumNameSpaceProvidersA', 38 => 'WSAEnumNameSpaceProvidersW', 39 => 'WSAEnumNetworkEvents', 40 => 'WSAEnumProtocolsA',
|
756
|
+
41 => 'WSAEnumProtocolsW', 42 => 'WSAEventSelect', 43 => 'WSAGetOverlappedResult', 44 => 'WSAGetQOSByName',
|
757
|
+
45 => 'WSAGetServiceClassInfoA', 46 => 'WSAGetServiceClassInfoW', 47 => 'WSAGetServiceClassNameByClassIdA', 48 => 'WSAGetServiceClassNameByClassIdW',
|
758
|
+
49 => 'WSAHtonl', 50 => 'WSAHtons', 51 => 'gethostbyaddr', 52 => 'gethostbyname',
|
759
|
+
53 => 'getprotobyname', 54 => 'getprotobynumber', 55 => 'getservbyname', 56 => 'getservbyport',
|
760
|
+
57 => 'gethostname', 58 => 'WSAInstallServiceClassA', 59 => 'WSAInstallServiceClassW', 60 => 'WSAIoctl',
|
761
|
+
61 => 'WSAJoinLeaf', 62 => 'WSALookupServiceBeginA', 63 => 'WSALookupServiceBeginW', 64 => 'WSALookupServiceEnd',
|
762
|
+
65 => 'WSALookupServiceNextA', 66 => 'WSALookupServiceNextW', 67 => 'WSANSPIoctl', 68 => 'WSANtohl',
|
763
|
+
69 => 'WSANtohs', 70 => 'WSAProviderConfigChange', 71 => 'WSARecv', 72 => 'WSARecvDisconnect',
|
764
|
+
73 => 'WSARecvFrom', 74 => 'WSARemoveServiceClass', 75 => 'WSAResetEvent', 76 => 'WSASend',
|
765
|
+
77 => 'WSASendDisconnect', 78 => 'WSASendTo', 79 => 'WSASetEvent', 80 => 'WSASetServiceA',
|
766
|
+
81 => 'WSASetServiceW', 82 => 'WSASocketA', 83 => 'WSASocketW', 84 => 'WSAStringToAddressA',
|
767
|
+
85 => 'WSAStringToAddressW', 86 => 'WSAWaitForMultipleEvents', 87 => 'WSCDeinstallProvider', 88 => 'WSCEnableNSProvider',
|
768
|
+
89 => 'WSCEnumProtocols', 90 => 'WSCGetProviderPath', 91 => 'WSCInstallNameSpace', 92 => 'WSCInstallProvider',
|
769
|
+
93 => 'WSCUnInstallNameSpace', 94 => 'WSCUpdateProvider', 95 => 'WSCWriteNameSpaceOrder', 96 => 'WSCWriteProviderOrder',
|
770
|
+
97 => 'freeaddrinfo', 98 => 'getaddrinfo', 99 => 'getnameinfo', 101 => 'WSAAsyncSelect',
|
771
|
+
102 => 'WSAAsyncGetHostByAddr', 103 => 'WSAAsyncGetHostByName', 104 => 'WSAAsyncGetProtoByNumber', 105 => 'WSAAsyncGetProtoByName',
|
772
|
+
106 => 'WSAAsyncGetServByPort', 107 => 'WSAAsyncGetServByName', 108 => 'WSACancelAsyncRequest', 109 => 'WSASetBlockingHook',
|
773
|
+
110 => 'WSAUnhookBlockingHook', 111 => 'WSAGetLastError', 112 => 'WSASetLastError', 113 => 'WSACancelBlockingCall',
|
774
|
+
114 => 'WSAIsBlocking', 115 => 'WSAStartup', 116 => 'WSACleanup', 151 => '__WSAFDIsSet',
|
775
|
+
500 => 'WEP',
|
776
|
+
}
|
777
|
+
|
778
|
+
IMPORT_HASH = {
|
779
|
+
'ws2_32' => ih_ws232,
|
780
|
+
'wsock2' => ih_ws232,
|
781
|
+
'oleaut' => {
|
782
|
+
2 => 'SysAllocString', 3 => 'SysReAllocString', 4 => 'SysAllocStringLen', 5 => 'SysReAllocStringLen',
|
783
|
+
6 => 'SysFreeString', 7 => 'SysStringLen', 8 => 'VariantInit', 9 => 'VariantClear',
|
784
|
+
10 => 'VariantCopy', 11 => 'VariantCopyInd', 12 => 'VariantChangeType', 13 => 'VariantTimeToDosDateTime',
|
785
|
+
14 => 'DosDateTimeToVariantTime', 15 => 'SafeArrayCreate', 16 => 'SafeArrayDestroy', 17 => 'SafeArrayGetDim',
|
786
|
+
18 => 'SafeArrayGetElemsize', 19 => 'SafeArrayGetUBound', 20 => 'SafeArrayGetLBound', 21 => 'SafeArrayLock',
|
787
|
+
22 => 'SafeArrayUnlock', 23 => 'SafeArrayAccessData', 24 => 'SafeArrayUnaccessData', 25 => 'SafeArrayGetElement',
|
788
|
+
26 => 'SafeArrayPutElement', 27 => 'SafeArrayCopy', 28 => 'DispGetParam', 29 => 'DispGetIDsOfNames',
|
789
|
+
30 => 'DispInvoke', 31 => 'CreateDispTypeInfo', 32 => 'CreateStdDispatch', 33 => 'RegisterActiveObject',
|
790
|
+
34 => 'RevokeActiveObject', 35 => 'GetActiveObject', 36 => 'SafeArrayAllocDescriptor', 37 => 'SafeArrayAllocData',
|
791
|
+
38 => 'SafeArrayDestroyDescriptor', 39 => 'SafeArrayDestroyData', 40 => 'SafeArrayRedim', 41 => 'SafeArrayAllocDescriptorEx',
|
792
|
+
42 => 'SafeArrayCreateEx', 43 => 'SafeArrayCreateVectorEx', 44 => 'SafeArraySetRecordInfo', 45 => 'SafeArrayGetRecordInfo',
|
793
|
+
46 => 'VarParseNumFromStr', 47 => 'VarNumFromParseNum', 48 => 'VarI2FromUI1', 49 => 'VarI2FromI4',
|
794
|
+
50 => 'VarI2FromR4', 51 => 'VarI2FromR8', 52 => 'VarI2FromCy', 53 => 'VarI2FromDate',
|
795
|
+
54 => 'VarI2FromStr', 55 => 'VarI2FromDisp', 56 => 'VarI2FromBool', 57 => 'SafeArraySetIID',
|
796
|
+
58 => 'VarI4FromUI1', 59 => 'VarI4FromI2', 60 => 'VarI4FromR4', 61 => 'VarI4FromR8',
|
797
|
+
62 => 'VarI4FromCy', 63 => 'VarI4FromDate', 64 => 'VarI4FromStr', 65 => 'VarI4FromDisp',
|
798
|
+
66 => 'VarI4FromBool', 67 => 'SafeArrayGetIID', 68 => 'VarR4FromUI1', 69 => 'VarR4FromI2',
|
799
|
+
70 => 'VarR4FromI4', 71 => 'VarR4FromR8', 72 => 'VarR4FromCy', 73 => 'VarR4FromDate',
|
800
|
+
74 => 'VarR4FromStr', 75 => 'VarR4FromDisp', 76 => 'VarR4FromBool', 77 => 'SafeArrayGetVartype',
|
801
|
+
78 => 'VarR8FromUI1', 79 => 'VarR8FromI2', 80 => 'VarR8FromI4', 81 => 'VarR8FromR4',
|
802
|
+
82 => 'VarR8FromCy', 83 => 'VarR8FromDate', 84 => 'VarR8FromStr', 85 => 'VarR8FromDisp',
|
803
|
+
86 => 'VarR8FromBool', 87 => 'VarFormat', 88 => 'VarDateFromUI1', 89 => 'VarDateFromI2',
|
804
|
+
90 => 'VarDateFromI4', 91 => 'VarDateFromR4', 92 => 'VarDateFromR8', 93 => 'VarDateFromCy',
|
805
|
+
94 => 'VarDateFromStr', 95 => 'VarDateFromDisp', 96 => 'VarDateFromBool', 97 => 'VarFormatDateTime',
|
806
|
+
98 => 'VarCyFromUI1', 99 => 'VarCyFromI2', 100 => 'VarCyFromI4', 101 => 'VarCyFromR4',
|
807
|
+
102 => 'VarCyFromR8', 103 => 'VarCyFromDate', 104 => 'VarCyFromStr', 105 => 'VarCyFromDisp',
|
808
|
+
106 => 'VarCyFromBool', 107 => 'VarFormatNumber', 108 => 'VarBstrFromUI1', 109 => 'VarBstrFromI2',
|
809
|
+
110 => 'VarBstrFromI4', 111 => 'VarBstrFromR4', 112 => 'VarBstrFromR8', 113 => 'VarBstrFromCy',
|
810
|
+
114 => 'VarBstrFromDate', 115 => 'VarBstrFromDisp', 116 => 'VarBstrFromBool', 117 => 'VarFormatPercent',
|
811
|
+
118 => 'VarBoolFromUI1', 119 => 'VarBoolFromI2', 120 => 'VarBoolFromI4', 121 => 'VarBoolFromR4',
|
812
|
+
122 => 'VarBoolFromR8', 123 => 'VarBoolFromDate', 124 => 'VarBoolFromCy', 125 => 'VarBoolFromStr',
|
813
|
+
126 => 'VarBoolFromDisp', 127 => 'VarFormatCurrency', 128 => 'VarWeekdayName', 129 => 'VarMonthName',
|
814
|
+
130 => 'VarUI1FromI2', 131 => 'VarUI1FromI4', 132 => 'VarUI1FromR4', 133 => 'VarUI1FromR8',
|
815
|
+
134 => 'VarUI1FromCy', 135 => 'VarUI1FromDate', 136 => 'VarUI1FromStr', 137 => 'VarUI1FromDisp',
|
816
|
+
138 => 'VarUI1FromBool', 139 => 'VarFormatFromTokens', 140 => 'VarTokenizeFormatString', 141 => 'VarAdd',
|
817
|
+
142 => 'VarAnd', 143 => 'VarDiv', 144 => 'DllCanUnloadNow', 145 => 'DllGetClassObject',
|
818
|
+
146 => 'DispCallFunc', 147 => 'VariantChangeTypeEx', 148 => 'SafeArrayPtrOfIndex', 149 => 'SysStringByteLen',
|
819
|
+
150 => 'SysAllocStringByteLen', 151 => 'DllRegisterServer', 152 => 'VarEqv', 153 => 'VarIdiv',
|
820
|
+
154 => 'VarImp', 155 => 'VarMod', 156 => 'VarMul', 157 => 'VarOr',
|
821
|
+
158 => 'VarPow', 159 => 'VarSub', 160 => 'CreateTypeLib', 161 => 'LoadTypeLib',
|
822
|
+
162 => 'LoadRegTypeLib', 163 => 'RegisterTypeLib', 164 => 'QueryPathOfRegTypeLib', 165 => 'LHashValOfNameSys',
|
823
|
+
166 => 'LHashValOfNameSysA', 167 => 'VarXor', 168 => 'VarAbs', 169 => 'VarFix',
|
824
|
+
170 => 'OaBuildVersion', 171 => 'ClearCustData', 172 => 'VarInt', 173 => 'VarNeg',
|
825
|
+
174 => 'VarNot', 175 => 'VarRound', 176 => 'VarCmp', 177 => 'VarDecAdd',
|
826
|
+
178 => 'VarDecDiv', 179 => 'VarDecMul', 180 => 'CreateTypeLib2', 181 => 'VarDecSub',
|
827
|
+
182 => 'VarDecAbs', 183 => 'LoadTypeLibEx', 184 => 'SystemTimeToVariantTime', 185 => 'VariantTimeToSystemTime',
|
828
|
+
186 => 'UnRegisterTypeLib', 187 => 'VarDecFix', 188 => 'VarDecInt', 189 => 'VarDecNeg',
|
829
|
+
190 => 'VarDecFromUI1', 191 => 'VarDecFromI2', 192 => 'VarDecFromI4', 193 => 'VarDecFromR4',
|
830
|
+
194 => 'VarDecFromR8', 195 => 'VarDecFromDate', 196 => 'VarDecFromCy', 197 => 'VarDecFromStr',
|
831
|
+
198 => 'VarDecFromDisp', 199 => 'VarDecFromBool', 200 => 'GetErrorInfo', 201 => 'SetErrorInfo',
|
832
|
+
202 => 'CreateErrorInfo', 203 => 'VarDecRound', 204 => 'VarDecCmp', 205 => 'VarI2FromI1',
|
833
|
+
206 => 'VarI2FromUI2', 207 => 'VarI2FromUI4', 208 => 'VarI2FromDec', 209 => 'VarI4FromI1',
|
834
|
+
210 => 'VarI4FromUI2', 211 => 'VarI4FromUI4', 212 => 'VarI4FromDec', 213 => 'VarR4FromI1',
|
835
|
+
214 => 'VarR4FromUI2', 215 => 'VarR4FromUI4', 216 => 'VarR4FromDec', 217 => 'VarR8FromI1',
|
836
|
+
218 => 'VarR8FromUI2', 219 => 'VarR8FromUI4', 220 => 'VarR8FromDec', 221 => 'VarDateFromI1',
|
837
|
+
222 => 'VarDateFromUI2', 223 => 'VarDateFromUI4', 224 => 'VarDateFromDec', 225 => 'VarCyFromI1',
|
838
|
+
226 => 'VarCyFromUI2', 227 => 'VarCyFromUI4', 228 => 'VarCyFromDec', 229 => 'VarBstrFromI1',
|
839
|
+
230 => 'VarBstrFromUI2', 231 => 'VarBstrFromUI4', 232 => 'VarBstrFromDec', 233 => 'VarBoolFromI1',
|
840
|
+
234 => 'VarBoolFromUI2', 235 => 'VarBoolFromUI4', 236 => 'VarBoolFromDec', 237 => 'VarUI1FromI1',
|
841
|
+
238 => 'VarUI1FromUI2', 239 => 'VarUI1FromUI4', 240 => 'VarUI1FromDec', 241 => 'VarDecFromI1',
|
842
|
+
242 => 'VarDecFromUI2', 243 => 'VarDecFromUI4', 244 => 'VarI1FromUI1', 245 => 'VarI1FromI2',
|
843
|
+
246 => 'VarI1FromI4', 247 => 'VarI1FromR4', 248 => 'VarI1FromR8', 249 => 'VarI1FromDate',
|
844
|
+
250 => 'VarI1FromCy', 251 => 'VarI1FromStr', 252 => 'VarI1FromDisp', 253 => 'VarI1FromBool',
|
845
|
+
254 => 'VarI1FromUI2', 255 => 'VarI1FromUI4', 256 => 'VarI1FromDec', 257 => 'VarUI2FromUI1',
|
846
|
+
258 => 'VarUI2FromI2', 259 => 'VarUI2FromI4', 260 => 'VarUI2FromR4', 261 => 'VarUI2FromR8',
|
847
|
+
262 => 'VarUI2FromDate', 263 => 'VarUI2FromCy', 264 => 'VarUI2FromStr', 265 => 'VarUI2FromDisp',
|
848
|
+
266 => 'VarUI2FromBool', 267 => 'VarUI2FromI1', 268 => 'VarUI2FromUI4', 269 => 'VarUI2FromDec',
|
849
|
+
270 => 'VarUI4FromUI1', 271 => 'VarUI4FromI2', 272 => 'VarUI4FromI4', 273 => 'VarUI4FromR4',
|
850
|
+
274 => 'VarUI4FromR8', 275 => 'VarUI4FromDate', 276 => 'VarUI4FromCy', 277 => 'VarUI4FromStr',
|
851
|
+
278 => 'VarUI4FromDisp', 279 => 'VarUI4FromBool', 280 => 'VarUI4FromI1', 281 => 'VarUI4FromUI2',
|
852
|
+
282 => 'VarUI4FromDec', 283 => 'BSTR_UserSize', 284 => 'BSTR_UserMarshal', 285 => 'BSTR_UserUnmarshal',
|
853
|
+
286 => 'BSTR_UserFree', 287 => 'VARIANT_UserSize', 288 => 'VARIANT_UserMarshal', 289 => 'VARIANT_UserUnmarshal',
|
854
|
+
290 => 'VARIANT_UserFree', 291 => 'LPSAFEARRAY_UserSize', 292 => 'LPSAFEARRAY_UserMarshal', 293 => 'LPSAFEARRAY_UserUnmarshal',
|
855
|
+
294 => 'LPSAFEARRAY_UserFree', 295 => 'LPSAFEARRAY_Size', 296 => 'LPSAFEARRAY_Marshal', 297 => 'LPSAFEARRAY_Unmarshal',
|
856
|
+
298 => 'VarDecCmpR8', 299 => 'VarCyAdd', 300 => 'DllUnregisterServer', 301 => 'OACreateTypeLib2',
|
857
|
+
303 => 'VarCyMul', 304 => 'VarCyMulI4', 305 => 'VarCySub', 306 => 'VarCyAbs',
|
858
|
+
307 => 'VarCyFix', 308 => 'VarCyInt', 309 => 'VarCyNeg', 310 => 'VarCyRound',
|
859
|
+
311 => 'VarCyCmp', 312 => 'VarCyCmpR8', 313 => 'VarBstrCat', 314 => 'VarBstrCmp',
|
860
|
+
315 => 'VarR8Pow', 316 => 'VarR4CmpR8', 317 => 'VarR8Round', 318 => 'VarCat',
|
861
|
+
319 => 'VarDateFromUdateEx', 322 => 'GetRecordInfoFromGuids', 323 => 'GetRecordInfoFromTypeInfo', 325 => 'SetVarConversionLocaleSetting',
|
862
|
+
326 => 'GetVarConversionLocaleSetting', 327 => 'SetOaNoCache', 329 => 'VarCyMulI8', 330 => 'VarDateFromUdate',
|
863
|
+
331 => 'VarUdateFromDate', 332 => 'GetAltMonthNames', 333 => 'VarI8FromUI1', 334 => 'VarI8FromI2',
|
864
|
+
335 => 'VarI8FromR4', 336 => 'VarI8FromR8', 337 => 'VarI8FromCy', 338 => 'VarI8FromDate',
|
865
|
+
339 => 'VarI8FromStr', 340 => 'VarI8FromDisp', 341 => 'VarI8FromBool', 342 => 'VarI8FromI1',
|
866
|
+
343 => 'VarI8FromUI2', 344 => 'VarI8FromUI4', 345 => 'VarI8FromDec', 346 => 'VarI2FromI8',
|
867
|
+
347 => 'VarI2FromUI8', 348 => 'VarI4FromI8', 349 => 'VarI4FromUI8', 360 => 'VarR4FromI8',
|
868
|
+
361 => 'VarR4FromUI8', 362 => 'VarR8FromI8', 363 => 'VarR8FromUI8', 364 => 'VarDateFromI8',
|
869
|
+
365 => 'VarDateFromUI8', 366 => 'VarCyFromI8', 367 => 'VarCyFromUI8', 368 => 'VarBstrFromI8',
|
870
|
+
369 => 'VarBstrFromUI8', 370 => 'VarBoolFromI8', 371 => 'VarBoolFromUI8', 372 => 'VarUI1FromI8',
|
871
|
+
373 => 'VarUI1FromUI8', 374 => 'VarDecFromI8', 375 => 'VarDecFromUI8', 376 => 'VarI1FromI8',
|
872
|
+
377 => 'VarI1FromUI8', 378 => 'VarUI2FromI8', 379 => 'VarUI2FromUI8', 401 => 'OleLoadPictureEx',
|
873
|
+
402 => 'OleLoadPictureFileEx', 411 => 'SafeArrayCreateVector', 412 => 'SafeArrayCopyData', 413 => 'VectorFromBstr',
|
874
|
+
414 => 'BstrFromVector', 415 => 'OleIconToCursor', 416 => 'OleCreatePropertyFrameIndirect', 417 => 'OleCreatePropertyFrame',
|
875
|
+
418 => 'OleLoadPicture', 419 => 'OleCreatePictureIndirect', 420 => 'OleCreateFontIndirect', 421 => 'OleTranslateColor',
|
876
|
+
422 => 'OleLoadPictureFile', 423 => 'OleSavePictureFile', 424 => 'OleLoadPicturePath', 425 => 'VarUI4FromI8',
|
877
|
+
426 => 'VarUI4FromUI8', 427 => 'VarI8FromUI8', 428 => 'VarUI8FromI8', 429 => 'VarUI8FromUI1',
|
878
|
+
430 => 'VarUI8FromI2', 431 => 'VarUI8FromR4', 432 => 'VarUI8FromR8', 433 => 'VarUI8FromCy',
|
879
|
+
434 => 'VarUI8FromDate', 435 => 'VarUI8FromStr', 436 => 'VarUI8FromDisp', 437 => 'VarUI8FromBool',
|
880
|
+
438 => 'VarUI8FromI1', 439 => 'VarUI8FromUI2', 440 => 'VarUI8FromUI4', 441 => 'VarUI8FromDec',
|
881
|
+
442 => 'RegisterTypeLibForUser', 443 => 'UnRegisterTypeLibForUser',
|
882
|
+
},
|
883
|
+
}
|
743
884
|
end
|
744
885
|
end
|
745
886
|
|
@@ -159,13 +159,20 @@ class AsmPreprocessor < Preprocessor
|
|
159
159
|
end
|
160
160
|
end
|
161
161
|
|
162
|
+
class Preprocessor::Token
|
163
|
+
# token already preprocessed for macro def/expansion
|
164
|
+
attr_accessor :alreadyapp
|
165
|
+
end
|
166
|
+
|
162
167
|
# the program (used to create new label names)
|
163
168
|
attr_accessor :program
|
164
169
|
# hash macro name => Macro
|
165
170
|
attr_accessor :macro
|
171
|
+
attr_accessor :may_apreprocess
|
166
172
|
|
167
173
|
def initialize(text='', program=nil)
|
168
174
|
@program = program
|
175
|
+
@may_apreprocess = false
|
169
176
|
@macro = {}
|
170
177
|
super(text)
|
171
178
|
end
|
@@ -184,13 +191,21 @@ class AsmPreprocessor < Preprocessor
|
|
184
191
|
t
|
185
192
|
end
|
186
193
|
|
187
|
-
|
188
|
-
|
189
|
-
|
194
|
+
def feed!(*a)
|
195
|
+
super(*a)
|
196
|
+
if not @may_apreprocess and (@text =~ / (macro|equ) / or not @macro.empty?)
|
197
|
+
@may_apreprocess = true
|
198
|
+
end
|
199
|
+
self
|
200
|
+
end
|
201
|
+
|
202
|
+
# reads a token, handles macros/comments/etc
|
203
|
+
def readtok
|
190
204
|
tok = super()
|
205
|
+
return tok if not tok or tok.alreadyapp
|
191
206
|
|
192
207
|
# handle ; comments
|
193
|
-
if tok
|
208
|
+
if tok.type == :punct and tok.raw[0] == ?;
|
194
209
|
tok.type = :eol
|
195
210
|
begin
|
196
211
|
tok = tok.dup
|
@@ -203,30 +218,13 @@ class AsmPreprocessor < Preprocessor
|
|
203
218
|
end
|
204
219
|
end
|
205
220
|
|
206
|
-
# aggregate space/eol
|
207
|
-
if tok and (tok.type == :space or tok.type == :eol)
|
208
|
-
if ntok = readtok(true) and ntok.type == :space
|
209
|
-
tok = tok.dup
|
210
|
-
tok.raw << ntok.raw
|
211
|
-
elsif ntok and ntok.type == :eol
|
212
|
-
tok = tok.dup
|
213
|
-
tok.raw << ntok.raw
|
214
|
-
tok.type = :eol
|
215
|
-
else
|
216
|
-
unreadtok ntok
|
217
|
-
end
|
218
|
-
end
|
219
|
-
|
220
|
-
|
221
221
|
# handle macros
|
222
|
-
|
223
|
-
if not rec and tok and tok.type == :string
|
222
|
+
if @may_apreprocess and tok.type == :string
|
224
223
|
if @macro[tok.raw]
|
225
224
|
@macro[tok.raw].apply(tok, self, @program).reverse_each { |t| unreadtok t }
|
226
225
|
tok = readtok
|
227
|
-
|
228
226
|
else
|
229
|
-
if ntok =
|
227
|
+
if ntok = super() and ntok.type == :space and nntok = super() and nntok.type == :string and (nntok.raw == 'macro' or nntok.raw == 'equ')
|
230
228
|
puts "W: asm: redefinition of macro #{tok.raw} at #{tok.backtrace_str}, previous definition at #{@macro[tok.raw].name.backtrace_str}" if @macro[tok.raw]
|
231
229
|
m = Macro.new tok
|
232
230
|
# XXX this allows nested macro definition..
|
@@ -252,6 +250,7 @@ class AsmPreprocessor < Preprocessor
|
|
252
250
|
end
|
253
251
|
end
|
254
252
|
|
253
|
+
tok.alreadyapp = true if tok
|
255
254
|
tok
|
256
255
|
end
|
257
256
|
end
|
@@ -314,6 +313,7 @@ class ExeFormat
|
|
314
313
|
lname = @locallabels_bkw[tok.raw] = @locallabels_fwd.delete(tok.raw) || new_label('local_'+tok.raw)
|
315
314
|
else
|
316
315
|
lname = tok.raw
|
316
|
+
raise tok, "invalid label name: #{lname.inspect} is reserved" if @cpu.check_reserved_name(lname)
|
317
317
|
raise tok, "label redefinition" if new_label(lname) != lname
|
318
318
|
end
|
319
319
|
l = Label.new(lname)
|
@@ -780,7 +780,7 @@ class Expression
|
|
780
780
|
pp = Preprocessor.new(str)
|
781
781
|
|
782
782
|
e = parse(pp, &b)
|
783
|
-
|
783
|
+
|
784
784
|
# update arg
|
785
785
|
len = pp.pos
|
786
786
|
pp.queue.each { |t| len -= t.raw.length }
|
@@ -821,6 +821,8 @@ class IndExpression < Expression
|
|
821
821
|
break
|
822
822
|
when ':' # symbols, eg ':eax'
|
823
823
|
n = lexer.readtok
|
824
|
+
nil while tok = lexer.readtok and tok.type == :space
|
825
|
+
lexer.unreadtok tok
|
824
826
|
return n.raw.to_sym
|
825
827
|
else
|
826
828
|
lexer.unreadtok tok
|
@@ -249,7 +249,7 @@ module C
|
|
249
249
|
end
|
250
250
|
|
251
251
|
def findmember(name, igncase=false)
|
252
|
-
raise
|
252
|
+
raise 'undefined structure' if not members
|
253
253
|
return @fldlist[name] if fldlist and @fldlist[name]
|
254
254
|
|
255
255
|
name = name.downcase if igncase
|
@@ -267,7 +267,7 @@ module C
|
|
267
267
|
end
|
268
268
|
|
269
269
|
def offsetof(parser, name)
|
270
|
-
raise parser, 'undefined structure' if not
|
270
|
+
raise parser, 'undefined structure' if not members
|
271
271
|
update_member_cache(parser) if not fldlist
|
272
272
|
return 0 if @fldlist[name]
|
273
273
|
|
@@ -284,7 +284,7 @@ module C
|
|
284
284
|
end
|
285
285
|
|
286
286
|
def bitoffsetof(parser, name)
|
287
|
-
raise parser, 'undefined structure' if not
|
287
|
+
raise parser, 'undefined structure' if not members
|
288
288
|
update_member_cache(parser) if not fldlist
|
289
289
|
return if @fldlist[name] or @members.include?(name)
|
290
290
|
raise parser, 'undefined union' if not @members
|
@@ -390,6 +390,22 @@ module C
|
|
390
390
|
end
|
391
391
|
idx + 1
|
392
392
|
end
|
393
|
+
|
394
|
+
# resolve structptr + offset into 'str.membername'
|
395
|
+
# handles 'var.substruct1.array[12].foo'
|
396
|
+
# updates str
|
397
|
+
# returns the final member type itself
|
398
|
+
# works for Struct/Union/Array
|
399
|
+
def expand_member_offset(c_parser, off, str)
|
400
|
+
# XXX choose in members, check sizeof / prefer structs
|
401
|
+
m = @members.first
|
402
|
+
str << '.' << m.name if m.name
|
403
|
+
if m.type.respond_to?(:expand_member_offset)
|
404
|
+
m.type.expand_member_offset(c_parser, off, str)
|
405
|
+
else
|
406
|
+
m.type
|
407
|
+
end
|
408
|
+
end
|
393
409
|
end
|
394
410
|
class Struct < Union
|
395
411
|
attr_accessor :pack
|
@@ -397,9 +413,10 @@ module C
|
|
397
413
|
def align(parser) [@members.to_a.map { |m| m.type.align(parser) }.max || 1, (pack || 8)].min end
|
398
414
|
|
399
415
|
def offsetof(parser, name)
|
400
|
-
raise parser, 'undefined structure' if not
|
416
|
+
raise parser, 'undefined structure' if not members
|
401
417
|
update_member_cache(parser) if not fldlist
|
402
418
|
return @fldoffset[name] if @fldoffset[name]
|
419
|
+
return @fldoffset[name.name] if name.respond_to?(:name) and @fldoffset[name.name]
|
403
420
|
|
404
421
|
# this is almost never reached, only for <struct>.offsetof(anonymoussubstructmembername)
|
405
422
|
raise parser, 'unknown structure member' if (name.kind_of?(::String) ? !findmember(name) : !@members.include?(name))
|
@@ -433,7 +450,7 @@ module C
|
|
433
450
|
end
|
434
451
|
mal = [m.type.align(parser), al].min
|
435
452
|
off = (off + mal - 1) / mal * mal
|
436
|
-
|
453
|
+
if m.name == name or m == name
|
437
454
|
break
|
438
455
|
elsif indirect and m.type.untypedef.kind_of? Union and m.type.untypedef.findmember(name)
|
439
456
|
off += m.type.untypedef.offsetof(parser, name)
|
@@ -449,18 +466,28 @@ module C
|
|
449
466
|
# returns the [bitoffset, bitlength] of the field if it is a bitfield
|
450
467
|
# this should be added to the offsetof(field)
|
451
468
|
def bitoffsetof(parser, name)
|
452
|
-
raise parser, 'undefined structure' if not
|
469
|
+
raise parser, 'undefined structure' if not members
|
453
470
|
update_member_cache(parser) if not fldlist
|
454
471
|
return @fldbitoffset[name] if fldbitoffset and @fldbitoffset[name]
|
472
|
+
return @fldbitoffset[name.name] if fldbitoffset and name.respond_to?(:name) and @fldbitoffset[name.name]
|
455
473
|
return if @fldlist[name] or @members.include?(name)
|
456
474
|
raise parser, 'undefined union' if not @members
|
457
475
|
raise parser, 'unknown union member' if not findmember(name)
|
458
476
|
|
459
477
|
@members.find { |m|
|
460
|
-
m.type.untypedef.kind_of?
|
478
|
+
m.type.untypedef.kind_of?(Union) and m.type.untypedef.findmember(name)
|
461
479
|
}.type.untypedef.bitoffsetof(parser, name)
|
462
480
|
end
|
463
481
|
|
482
|
+
# returns the @member element that has offsetof(m) == off
|
483
|
+
def findmember_atoffset(parser, off)
|
484
|
+
return if not members
|
485
|
+
update_member_cache(parser) if not fldlist
|
486
|
+
if m = @fldoffset.index(off)
|
487
|
+
@fldlist[m]
|
488
|
+
end
|
489
|
+
end
|
490
|
+
|
464
491
|
def parse_members(parser, scope)
|
465
492
|
super(parser, scope)
|
466
493
|
|
@@ -515,6 +542,32 @@ module C
|
|
515
542
|
end
|
516
543
|
}
|
517
544
|
end
|
545
|
+
|
546
|
+
# see Union#expand_member_offset
|
547
|
+
def expand_member_offset(c_parser, off, str)
|
548
|
+
members.to_a.each { |m|
|
549
|
+
mo = offsetof(c_parser, m)
|
550
|
+
if mo == off or mo + c_parser.sizeof(m) > off
|
551
|
+
if bitoffsetof(c_parser, m)
|
552
|
+
# ignore bitfields
|
553
|
+
str << "+#{off}" if off > 0
|
554
|
+
return self
|
555
|
+
end
|
556
|
+
|
557
|
+
str << '.' << m.name if m.name
|
558
|
+
if m.type.respond_to?(:expand_member_offset)
|
559
|
+
return m.type.expand_member_offset(c_parser, off-mo, str)
|
560
|
+
else
|
561
|
+
return m.type
|
562
|
+
end
|
563
|
+
elsif mo > off
|
564
|
+
break
|
565
|
+
end
|
566
|
+
}
|
567
|
+
# XXX that works only for pointer-style str
|
568
|
+
str << "+#{off}" if off > 0
|
569
|
+
nil
|
570
|
+
end
|
518
571
|
end
|
519
572
|
class Enum < Type
|
520
573
|
# name => value
|
@@ -557,6 +610,11 @@ module C
|
|
557
610
|
parse_attributes(parser)
|
558
611
|
end
|
559
612
|
|
613
|
+
def compare_deep(o)
|
614
|
+
return true if o.object_id == self.object_id
|
615
|
+
return if o.class != self.class or o.name != self.name or o.attributes != self.attributes
|
616
|
+
members == o.members
|
617
|
+
end
|
560
618
|
end
|
561
619
|
class Pointer < Type
|
562
620
|
attr_accessor :type
|
@@ -684,6 +742,17 @@ module C
|
|
684
742
|
end
|
685
743
|
idx + 1
|
686
744
|
end
|
745
|
+
|
746
|
+
# see Union#expand_member_offset
|
747
|
+
def expand_member_offset(c_parser, off, str)
|
748
|
+
tsz = c_parser.sizeof(@type)
|
749
|
+
str << "[#{off/tsz}]"
|
750
|
+
if @type.respond_to?(:expand_member_offset)
|
751
|
+
@type.expand_member_offset(c_parser, off%tsz, str)
|
752
|
+
else
|
753
|
+
@type
|
754
|
+
end
|
755
|
+
end
|
687
756
|
end
|
688
757
|
|
689
758
|
class Variable
|
@@ -880,7 +949,7 @@ module C
|
|
880
949
|
when :space; body << ' '
|
881
950
|
when :eol; body << "\n"
|
882
951
|
when :punct; body << tok.raw
|
883
|
-
when :quoted; body << tok.value
|
952
|
+
when :quoted; body << CExpression.string_inspect(tok.value) # concat adjacent c strings
|
884
953
|
when :string
|
885
954
|
body << \
|
886
955
|
case tok.raw
|
@@ -923,7 +992,7 @@ module C
|
|
923
992
|
break
|
924
993
|
else body << tok.raw
|
925
994
|
end
|
926
|
-
when :quoted; body << (body.empty? ? tok.value : tok.value
|
995
|
+
when :quoted; body << (body.empty? ? tok.value : CExpression.string_inspect(tok.value)) # asm "pop\nret" VS asm add al, 'z'
|
927
996
|
when :string
|
928
997
|
body << \
|
929
998
|
case tok.raw
|
@@ -997,7 +1066,7 @@ module C
|
|
997
1066
|
raise "invalid CExpr #{[l, o, r, t].inspect}" if (o and not o.kind_of? ::Symbol) or not t.kind_of? Type
|
998
1067
|
@lexpr, @op, @rexpr, @type = l, o, r, t
|
999
1068
|
end
|
1000
|
-
|
1069
|
+
|
1001
1070
|
# overwrites @lexpr @op @rexpr @type from the arg
|
1002
1071
|
def replace(o)
|
1003
1072
|
@lexpr, @op, @rexpr, @type = o.lexpr, o.op, o.rexpr, o.type
|
@@ -1033,7 +1102,7 @@ module C
|
|
1033
1102
|
else
|
1034
1103
|
x2 = splat[args[2]]
|
1035
1104
|
end
|
1036
|
-
|
1105
|
+
new(splat[args[0]], op, x2, args[3])
|
1037
1106
|
when 3
|
1038
1107
|
op = args[1]
|
1039
1108
|
x1 = splat[args[0]]
|
@@ -1047,7 +1116,7 @@ module C
|
|
1047
1116
|
when :funcall
|
1048
1117
|
rt = x1.type.untypedef
|
1049
1118
|
rt = rt.type.untypedef if rt.pointer?
|
1050
|
-
|
1119
|
+
new(x1, op, x2, rt.type)
|
1051
1120
|
when :[]; new(x1, op, x2, x1.type.untypedef.type)
|
1052
1121
|
when :+; new(x1, op, x2, (x2.type.pointer? ? x2.type : x1.type))
|
1053
1122
|
when :-; new(x1, op, x2, ((x1.type.pointer? and x2.type.pointer?) ? BaseType.new(:int) : x2.type.pointer? ? x2.type : x1.type))
|
@@ -1111,13 +1180,14 @@ module C
|
|
1111
1180
|
attr_accessor :lexer, :toplevel, :typesize, :pragma_pack
|
1112
1181
|
attr_accessor :endianness
|
1113
1182
|
attr_accessor :allow_bad_c
|
1183
|
+
attr_accessor :program
|
1114
1184
|
# allowed arguments: ExeFormat, CPU, Preprocessor, Symbol (for the data model)
|
1115
1185
|
def initialize(*args)
|
1116
1186
|
model = args.grep(Symbol).first || :ilp32
|
1117
1187
|
lexer = args.grep(Preprocessor).first || Preprocessor.new
|
1118
|
-
|
1188
|
+
@program = args.grep(ExeFormat).first
|
1119
1189
|
cpu = args.grep(CPU).first
|
1120
|
-
cpu ||=
|
1190
|
+
cpu ||= @program.cpu if @program
|
1121
1191
|
@lexer = lexer
|
1122
1192
|
@prev_pragma_callback = @lexer.pragma_callback
|
1123
1193
|
@lexer.pragma_callback = lambda { |tok| parse_pragma_callback(tok) }
|
@@ -1128,7 +1198,7 @@ module C
|
|
1128
1198
|
:char => 1, :float => 4, :double => 8, :longdouble => 12 }
|
1129
1199
|
send model
|
1130
1200
|
cpu.tune_cparser(self) if cpu
|
1131
|
-
|
1201
|
+
@program.tune_cparser(self) if @program
|
1132
1202
|
end
|
1133
1203
|
|
1134
1204
|
def ilp16
|
@@ -1513,6 +1583,7 @@ EOH
|
|
1513
1583
|
when Struct
|
1514
1584
|
raise self, "unknown structure size #{type.name}" if not type.members
|
1515
1585
|
al = type.align(self)
|
1586
|
+
al = 1 if (var.kind_of?(Attributes) and var.has_attribute('sizeof_packed')) or type.has_attribute('sizeof_packed')
|
1516
1587
|
lm = type.members.last
|
1517
1588
|
lm ? (type.offsetof(self, lm) + sizeof(lm) + al - 1) / al * al : 0
|
1518
1589
|
when Union
|
@@ -1703,6 +1774,7 @@ EOH
|
|
1703
1774
|
Goto.new name
|
1704
1775
|
when 'return'
|
1705
1776
|
expr = CExpression.parse(self, scope) # nil allowed
|
1777
|
+
raise tok || self, "cannot return #{expr} in function returning void" if expr and nest[0].kind_of?(Type) and nest[0].void?
|
1706
1778
|
p, i = nest[0].pointer?, nest[0].integral? if expr
|
1707
1779
|
r = expr.reduce(self) if p or i
|
1708
1780
|
if (not p and not i) or (i and not r.kind_of? ::Integer) or (p and r != 0)
|
@@ -1770,6 +1842,7 @@ EOH
|
|
1770
1842
|
end
|
1771
1843
|
|
1772
1844
|
# returns all numeric constants defined with their value, either macros or enums
|
1845
|
+
# for enums, also return the enum name
|
1773
1846
|
def numeric_constants
|
1774
1847
|
ret = []
|
1775
1848
|
# macros
|
@@ -1779,8 +1852,17 @@ EOH
|
|
1779
1852
|
end
|
1780
1853
|
}
|
1781
1854
|
# enums
|
1855
|
+
seen_enum = {}
|
1856
|
+
@toplevel.struct.each { |k, v|
|
1857
|
+
if v.kind_of?(Enum)
|
1858
|
+
v.members.each { |kk, vv|
|
1859
|
+
ret << [kk, vv, k]
|
1860
|
+
seen_enum[kk] = true
|
1861
|
+
}
|
1862
|
+
end
|
1863
|
+
}
|
1782
1864
|
@toplevel.symbol.each { |k, v|
|
1783
|
-
ret << [k, v] if v.kind_of?
|
1865
|
+
ret << [k, v] if v.kind_of?(::Numeric) and not seen_enum[k]
|
1784
1866
|
}
|
1785
1867
|
ret
|
1786
1868
|
end
|
@@ -1933,7 +2015,10 @@ EOH
|
|
1933
2015
|
name = :int
|
1934
2016
|
tok = nil
|
1935
2017
|
loop do
|
1936
|
-
|
2018
|
+
if not tok = parser.skipspaces
|
2019
|
+
raise parser if specifier.empty?
|
2020
|
+
break
|
2021
|
+
end
|
1937
2022
|
if tok.type != :string
|
1938
2023
|
parser.unreadtok tok
|
1939
2024
|
break
|
@@ -2239,12 +2324,13 @@ EOH
|
|
2239
2324
|
else
|
2240
2325
|
l = CExpression.new(nil, nil, l, BaseType.new(:int)) if l.kind_of? ::Integer
|
2241
2326
|
r = CExpression.new(nil, nil, r, BaseType.new(:int)) if r.kind_of? ::Integer
|
2242
|
-
|
2327
|
+
CExpression.new(l, @op, r, @type)
|
2243
2328
|
end
|
2244
2329
|
when :'.'
|
2245
2330
|
le = CExpression.reduce(parser, @lexpr)
|
2246
2331
|
if le.kind_of? Variable and le.initializer.kind_of? ::Array
|
2247
|
-
|
2332
|
+
t = le.type.untypedef
|
2333
|
+
midx = t.members.index(t.findmember(@rexpr))
|
2248
2334
|
CExpression.reduce(parser, le.initializer[midx] || 0)
|
2249
2335
|
else
|
2250
2336
|
CExpression.new(le, @op, @rexpr, @type)
|
@@ -2282,7 +2368,7 @@ EOH
|
|
2282
2368
|
end
|
2283
2369
|
else
|
2284
2370
|
l = CExpression.reduce(parser, @lexpr)
|
2285
|
-
|
2371
|
+
if not l.kind_of?(::Numeric) or not r.kind_of?(::Numeric)
|
2286
2372
|
l = CExpression.new(nil, nil, l, BaseType.new(:int)) if l.kind_of? ::Integer
|
2287
2373
|
r = CExpression.new(nil, nil, r, BaseType.new(:int)) if r.kind_of? ::Integer
|
2288
2374
|
return CExpression.new(l, @op, r, @type)
|
@@ -2325,7 +2411,7 @@ EOH
|
|
2325
2411
|
o.object_id == self.object_id or
|
2326
2412
|
(self.class == o.class and op == o.op and lexpr == o.lexpr and rexpr == o.rexpr)
|
2327
2413
|
end
|
2328
|
-
|
2414
|
+
|
2329
2415
|
def ===(o)
|
2330
2416
|
(self.class == o.class and op == o.op and lexpr === o.lexpr and rexpr === o.rexpr) or
|
2331
2417
|
(o.class == Variable and not @op and @rexpr == o)
|
@@ -2506,6 +2592,7 @@ EOH
|
|
2506
2592
|
type = :long if suffix.count('l') == 1
|
2507
2593
|
end
|
2508
2594
|
val = CExpression[val, BaseType.new(type, *specifier)]
|
2595
|
+
val = parse_value_postfix(parser, scope, val)
|
2509
2596
|
else raise parser, "internal error #{val.inspect}"
|
2510
2597
|
end
|
2511
2598
|
|
@@ -2513,6 +2600,7 @@ EOH
|
|
2513
2600
|
if tok.raw[0] == ?'
|
2514
2601
|
raise tok, 'invalid character constant' if not [1, 2, 4, 8].include? tok.value.length # TODO 0fill
|
2515
2602
|
val = CExpression[Expression.decode_imm(tok.value, tok.value.length, :big), BaseType.new(:int)]
|
2603
|
+
val = parse_value_postfix(parser, scope, val)
|
2516
2604
|
else
|
2517
2605
|
val = CExpression[tok.value, Pointer.new(BaseType.new(tok.raw[0, 2] == 'L"' ? :short : :char))]
|
2518
2606
|
val = parse_value_postfix(parser, scope, val)
|
@@ -2712,96 +2800,109 @@ EOH
|
|
2712
2800
|
end
|
2713
2801
|
end
|
2714
2802
|
|
2715
|
-
def
|
2716
|
-
|
2717
|
-
|
2718
|
-
|
2719
|
-
|
2720
|
-
|
2721
|
-
|
2722
|
-
|
2723
|
-
|
2724
|
-
|
2725
|
-
|
2726
|
-
|
2803
|
+
def parse_popstack(parser, stack, opstack)
|
2804
|
+
r = stack.pop
|
2805
|
+
l = stack.pop
|
2806
|
+
case op = opstack.pop
|
2807
|
+
when :'?:'
|
2808
|
+
stack << CExpression.new(stack.pop, op, [l, r], l.type)
|
2809
|
+
when :','
|
2810
|
+
stack << CExpression.new(l, op, r, r.type)
|
2811
|
+
when :'='
|
2812
|
+
unless r.kind_of?(CExpression) and not r.lexpr and r.type.kind_of?(BaseType) and
|
2813
|
+
((not r.op and r.rexpr.kind_of?(Integer)) or
|
2814
|
+
(r.op == :- and r.rexpr.kind_of?(CExpression) and not r.rexpr.op and not r.rexpr.lexpr and r.rexpr.rexpr.kind_of?(Integer))) and
|
2815
|
+
l.kind_of?(Typed) and (l.type.untypedef.kind_of?(BaseType) or (l.type.untypedef.kind_of?(Pointer) and r.rexpr == 0))
|
2816
|
+
# avoid useless warnings on unsigned foo = -1 / void *foo = 0
|
2727
2817
|
parser.check_compatible_type(parser, r.type, l.type)
|
2728
|
-
|
2729
|
-
|
2730
|
-
|
2818
|
+
end
|
2819
|
+
if l.kind_of?(Typed) and (lt = l.type.untypedef).kind_of?(BaseType) and r.kind_of?(Typed) and (rt = r.type.untypedef).kind_of?(BaseType) and lt.specifier != :unsigned and rt.specifier == :unsigned and parser.typesize[lt.name] > parser.typesize[rt.name]
|
2820
|
+
# (int32)i = (uchar)255 => 255, not -1
|
2821
|
+
r = CExpression.new(nil, nil, r, BaseType.new(lt.name, :unsigned))
|
2822
|
+
end
|
2823
|
+
stack << CExpression.new(l, op, r, l.type)
|
2824
|
+
when :'&&', :'||'
|
2825
|
+
stack << CExpression.new(l, op, r, BaseType.new(:int))
|
2826
|
+
else
|
2827
|
+
# XXX struct == struct ?
|
2828
|
+
raise parser, "invalid type #{l.type} #{l} for #{op.inspect}" if not l.type.arithmetic? and not parser.allow_bad_c
|
2829
|
+
raise parser, "invalid type #{r.type} #{r} for #{op.inspect}" if not r.type.arithmetic? and not parser.allow_bad_c
|
2830
|
+
|
2831
|
+
if l.type.pointer? and r.type.pointer?
|
2832
|
+
type = \
|
2833
|
+
case op
|
2834
|
+
when :'-'; BaseType.new(:long) # addr_t or sumthin ?
|
2835
|
+
when :'-='; l.type
|
2836
|
+
when :'>', :'>=', :'<', :'<=', :'==', :'!='; BaseType.new(:long)
|
2837
|
+
else raise parser, "cannot do #{op.inspect} on pointers" unless parser.allow_bad_c ; l.type
|
2838
|
+
end
|
2839
|
+
elsif l.type.pointer? or r.type.pointer?
|
2840
|
+
puts parser.exception("should not #{op.inspect} a pointer").message if $VERBOSE and not [:'+', :'-', :'=', :'+=', :'-=', :==, :'!='].include? op
|
2841
|
+
type = l.type.pointer? ? l.type : r.type
|
2842
|
+
elsif RIGHTASSOC[op] and op != :'?:' # += etc
|
2843
|
+
type = l.type
|
2731
2844
|
else
|
2732
|
-
#
|
2733
|
-
|
2734
|
-
|
2735
|
-
|
2736
|
-
|
2737
|
-
|
2738
|
-
|
2739
|
-
|
2740
|
-
|
2741
|
-
|
2742
|
-
|
2743
|
-
|
2744
|
-
|
2745
|
-
|
2746
|
-
|
2747
|
-
|
2748
|
-
|
2749
|
-
|
2750
|
-
|
2751
|
-
|
2752
|
-
|
2753
|
-
|
2754
|
-
# long double > double > float ...
|
2755
|
-
type = t
|
2756
|
-
elsif true
|
2757
|
-
# custom integer rules based on type sizes
|
2758
|
-
lts = parser.typesize[lt.name]
|
2759
|
-
rts = parser.typesize[rt.name]
|
2760
|
-
its = parser.typesize[:int]
|
2761
|
-
if not lts or not rts
|
2762
|
-
type = BaseType.new(:int)
|
2763
|
-
elsif lts > rts and lts >= its
|
2764
|
-
type = lt
|
2765
|
-
elsif rts > lts and rts >= its
|
2766
|
-
type = rt
|
2767
|
-
elsif lts == rts and lts >= its
|
2768
|
-
type = lt
|
2769
|
-
type = rt if rt.specifier == :unsigned
|
2770
|
-
else
|
2771
|
-
type = BaseType.new(:int)
|
2772
|
-
end
|
2773
|
-
# end of custom rules
|
2774
|
-
elsif ((t = lt).name == :long and t.specifier == :unsigned) or
|
2775
|
-
((t = rt).name == :long and t.specifier == :unsigned)
|
2776
|
-
# ... ulong ...
|
2777
|
-
type = t
|
2778
|
-
elsif (lt.name == :long and rt.name == :int and rt.specifier == :unsigned) or
|
2779
|
-
(rt.name == :long and lt.name == :int and lt.specifier == :unsigned)
|
2780
|
-
# long+uint => ulong
|
2781
|
-
type = BaseType.new(:long, :unsigned)
|
2782
|
-
elsif (t = lt).name == :long or (t = rt).name == :long or
|
2783
|
-
((t = lt).name == :int and t.specifier == :unsigned) or
|
2784
|
-
((t = rt).name == :int and t.specifier == :unsigned)
|
2785
|
-
# ... long > uint ...
|
2786
|
-
type = t
|
2845
|
+
# yay integer promotion
|
2846
|
+
lt = l.type.untypedef
|
2847
|
+
rt = r.type.untypedef
|
2848
|
+
if (t = lt).name == :longdouble or (t = rt).name == :longdouble or
|
2849
|
+
(t = lt).name == :double or (t = rt).name == :double or
|
2850
|
+
(t = lt).name == :float or (t = rt).name == :float
|
2851
|
+
# long double > double > float ...
|
2852
|
+
type = t
|
2853
|
+
elsif true
|
2854
|
+
# custom integer rules based on type sizes
|
2855
|
+
lts = parser.typesize[lt.name]
|
2856
|
+
rts = parser.typesize[rt.name]
|
2857
|
+
its = parser.typesize[:int]
|
2858
|
+
if not lts or not rts
|
2859
|
+
type = BaseType.new(:int)
|
2860
|
+
elsif lts > rts and lts >= its
|
2861
|
+
type = lt
|
2862
|
+
elsif rts > lts and rts >= its
|
2863
|
+
type = rt
|
2864
|
+
elsif lts == rts and lts >= its
|
2865
|
+
type = lt
|
2866
|
+
type = rt if rt.specifier == :unsigned
|
2787
2867
|
else
|
2788
|
-
# int
|
2789
2868
|
type = BaseType.new(:int)
|
2790
2869
|
end
|
2791
|
-
|
2792
|
-
|
2793
|
-
|
2794
|
-
|
2795
|
-
|
2796
|
-
|
2797
|
-
|
2798
|
-
|
2870
|
+
# end of custom rules
|
2871
|
+
elsif ((t = lt).name == :long and t.specifier == :unsigned) or
|
2872
|
+
((t = rt).name == :long and t.specifier == :unsigned)
|
2873
|
+
# ... ulong ...
|
2874
|
+
type = t
|
2875
|
+
elsif (lt.name == :long and rt.name == :int and rt.specifier == :unsigned) or
|
2876
|
+
(rt.name == :long and lt.name == :int and lt.specifier == :unsigned)
|
2877
|
+
# long+uint => ulong
|
2878
|
+
type = BaseType.new(:long, :unsigned)
|
2879
|
+
elsif (t = lt).name == :long or (t = rt).name == :long or
|
2880
|
+
((t = lt).name == :int and t.specifier == :unsigned) or
|
2881
|
+
((t = rt).name == :int and t.specifier == :unsigned)
|
2882
|
+
# ... long > uint ...
|
2883
|
+
type = t
|
2799
2884
|
else
|
2800
|
-
|
2801
|
-
|
2885
|
+
# int
|
2886
|
+
type = BaseType.new(:int)
|
2802
2887
|
end
|
2803
2888
|
end
|
2804
|
-
|
2889
|
+
|
2890
|
+
case op
|
2891
|
+
when :'>', :'>=', :'<', :'<=', :'==', :'!='
|
2892
|
+
# cast both sides
|
2893
|
+
l = CExpression[l, type] if l.type != type
|
2894
|
+
r = CExpression[r, type] if r.type != type
|
2895
|
+
stack << CExpression.new(l, op, r, BaseType.new(:int))
|
2896
|
+
else
|
2897
|
+
# promote result
|
2898
|
+
stack << CExpression.new(l, op, r, type)
|
2899
|
+
end
|
2900
|
+
end
|
2901
|
+
end
|
2902
|
+
|
2903
|
+
def parse(parser, scope, allow_coma = true)
|
2904
|
+
opstack = []
|
2905
|
+
stack = []
|
2805
2906
|
|
2806
2907
|
return if not e = parse_value(parser, scope)
|
2807
2908
|
|
@@ -2812,7 +2913,7 @@ EOH
|
|
2812
2913
|
when :'?'
|
2813
2914
|
# a, b ? c, d : e, f == a, (b ? (c, d) : e), f
|
2814
2915
|
until opstack.empty? or OP_PRIO[opstack.last][:'?:']
|
2815
|
-
|
2916
|
+
parse_popstack(parser, stack, opstack)
|
2816
2917
|
end
|
2817
2918
|
stack << parse(parser, scope)
|
2818
2919
|
raise op || parser, '":" expected' if not op = readop(parser) or op.value != :':'
|
@@ -2827,7 +2928,7 @@ EOH
|
|
2827
2928
|
break
|
2828
2929
|
end
|
2829
2930
|
until opstack.empty? or OP_PRIO[op.value][opstack.last]
|
2830
|
-
|
2931
|
+
parse_popstack(parser, stack, opstack)
|
2831
2932
|
end
|
2832
2933
|
end
|
2833
2934
|
|
@@ -2837,7 +2938,7 @@ EOH
|
|
2837
2938
|
end
|
2838
2939
|
|
2839
2940
|
until opstack.empty?
|
2840
|
-
|
2941
|
+
parse_popstack(parser, stack, opstack)
|
2841
2942
|
end
|
2842
2943
|
|
2843
2944
|
CExpression[stack.first]
|
@@ -2929,8 +3030,9 @@ EOH
|
|
2929
3030
|
end
|
2930
3031
|
|
2931
3032
|
a, val = a
|
2932
|
-
|
2933
|
-
a
|
3033
|
+
f = a
|
3034
|
+
raise "#{a.inspect} not a struct member" if not f.kind_of? C::Variable and not f = @struct.findmember(a.to_s, true)
|
3035
|
+
a = f.name || f
|
2934
3036
|
val = sizeof if val == :size
|
2935
3037
|
off = @stroff + @struct.offsetof(@cp, a)
|
2936
3038
|
|
@@ -2972,7 +3074,6 @@ EOH
|
|
2972
3074
|
str.last << "struct #{@struct.name || '_'} x = " if not off
|
2973
3075
|
@struct.update_member_cache(@cp) if not @struct.fldlist
|
2974
3076
|
fldoff = @struct.fldoffset
|
2975
|
-
fbo = @struct.fldbitoffset || {}
|
2976
3077
|
mlist = @struct.members.map { |m| m.name || m }
|
2977
3078
|
else
|
2978
3079
|
str.last << "union #{@struct.name || '_'} x = " if not off
|
@@ -3203,8 +3304,7 @@ EOH
|
|
3203
3304
|
all = @toplevel.struct.values + @toplevel.symbol.values
|
3204
3305
|
all -= all.grep(::Integer) # Enum values
|
3205
3306
|
|
3206
|
-
|
3207
|
-
r.join("\n")
|
3307
|
+
@toplevel.dump_reorder(all, todo_rndr, todo_deps)[0].join("\n")
|
3208
3308
|
end
|
3209
3309
|
|
3210
3310
|
# returns a string containing the C definition(s) of toplevel functions, with their dependencies
|
@@ -3783,7 +3883,7 @@ EOH
|
|
3783
3883
|
r.last << 'asm '
|
3784
3884
|
r.last << 'volatile ' if @volatile
|
3785
3885
|
r.last << '('
|
3786
|
-
r.last << @body
|
3886
|
+
r.last << CExpression.string_inspect(@body)
|
3787
3887
|
if @output or @input or @clobber
|
3788
3888
|
if @output and @output != []
|
3789
3889
|
# TODO
|
@@ -3801,13 +3901,18 @@ EOH
|
|
3801
3901
|
end
|
3802
3902
|
end
|
3803
3903
|
if @clobber and @clobber != []
|
3804
|
-
r << (': ' << @clobber.map { |c| c
|
3904
|
+
r << (': ' << @clobber.map { |c| CExpression.string_inspect(c) }.join(', '))
|
3805
3905
|
end
|
3806
3906
|
r.last << ');'
|
3807
3907
|
[r, dep]
|
3808
3908
|
end
|
3809
3909
|
end
|
3810
3910
|
class CExpression
|
3911
|
+
def self.string_inspect(s)
|
3912
|
+
# keep all ascii printable except \ and "
|
3913
|
+
'"' + s.gsub(/[^ !\x23-\x5b\x5d-\x7e]/) { |o| '\\x' + o.unpack('H*').first } + '"'
|
3914
|
+
end
|
3915
|
+
|
3811
3916
|
def self.dump(e, scope, r=[''], dep=[], brace = false)
|
3812
3917
|
if $DEBUG
|
3813
3918
|
brace = false
|
@@ -3820,7 +3925,7 @@ EOH
|
|
3820
3925
|
r, dep = \
|
3821
3926
|
case e
|
3822
3927
|
when ::Numeric; r.last << e.to_s ; [r, dep]
|
3823
|
-
when ::String; r.last << e
|
3928
|
+
when ::String; r.last << string_inspect(e) ; [r, dep]
|
3824
3929
|
when CExpression; e.dump_inner(scope, r, dep, brace)
|
3825
3930
|
when Variable; e.dump(scope, r, dep)
|
3826
3931
|
when nil; [r, dep]
|
@@ -3865,7 +3970,7 @@ EOH
|
|
3865
3970
|
end
|
3866
3971
|
when ::String
|
3867
3972
|
r.last << 'L' if @type.kind_of? Pointer and @type.type.kind_of? BaseType and @type.type.name == :short
|
3868
|
-
r.last << @rexpr
|
3973
|
+
r.last << CExpression.string_inspect(@rexpr)
|
3869
3974
|
when CExpression # cast
|
3870
3975
|
r, dep = @type.dump_cast(scope, r, dep)
|
3871
3976
|
r, dep = CExpression.dump(@rexpr, scope, r, dep, true)
|
@@ -3899,7 +4004,7 @@ EOH
|
|
3899
4004
|
l = lexpr.lexpr.type.pointed.untypedef.findmember(lexpr.rexpr) if lexpr.kind_of? CExpression and lexpr.op == :'->'
|
3900
4005
|
# honor __attribute__((indexenum(enumname)))
|
3901
4006
|
if l and l.attributes and rexpr.kind_of? CExpression and not rexpr.op and rexpr.rexpr.kind_of? ::Integer and
|
3902
|
-
|
4007
|
+
n = l.has_attribute_var('indexenum') and enum = scope.struct_ancestors[n] and i = enum.members.index(rexpr.rexpr)
|
3903
4008
|
r.last << i
|
3904
4009
|
dep |= [enum]
|
3905
4010
|
else
|