metasm 1.0.1 → 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|