metasm 1.0.0 → 1.0.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +3 -0
- data/.gitignore +3 -0
- data/.hgtags +3 -0
- data/Gemfile +3 -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 +3 -1
- 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 +23 -0
- data/{lib/metasm.rb → metasm.rb} +15 -3
- data/{lib/metasm → metasm}/compile_c.rb +15 -9
- data/metasm/cpu/arc.rb +8 -0
- data/metasm/cpu/arc/decode.rb +404 -0
- data/metasm/cpu/arc/main.rb +191 -0
- data/metasm/cpu/arc/opcodes.rb +588 -0
- data/metasm/cpu/arm.rb +14 -0
- data/{lib/metasm → metasm/cpu}/arm/debug.rb +2 -2
- data/{lib/metasm → metasm/cpu}/arm/decode.rb +15 -18
- data/{lib/metasm → metasm/cpu}/arm/encode.rb +23 -8
- data/{lib/metasm → metasm/cpu}/arm/main.rb +3 -6
- 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 +285 -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/mips/compile_c.rb → metasm/cpu/bpf.rb} +4 -2
- data/metasm/cpu/bpf/decode.rb +110 -0
- data/metasm/cpu/bpf/main.rb +60 -0
- data/metasm/cpu/bpf/opcodes.rb +81 -0
- data/metasm/cpu/bpf/render.rb +30 -0
- data/{lib/metasm/ppc.rb → metasm/cpu/cy16.rb} +2 -4
- data/metasm/cpu/cy16/decode.rb +247 -0
- data/metasm/cpu/cy16/main.rb +63 -0
- data/metasm/cpu/cy16/opcodes.rb +78 -0
- data/metasm/cpu/cy16/render.rb +30 -0
- data/metasm/cpu/dalvik.rb +11 -0
- data/{lib/metasm → metasm/cpu}/dalvik/decode.rb +34 -34
- data/{lib/metasm → metasm/cpu}/dalvik/main.rb +71 -4
- data/{lib/metasm → metasm/cpu}/dalvik/opcodes.rb +21 -12
- data/{lib/metasm/mips.rb → metasm/cpu/ebpf.rb} +3 -4
- data/metasm/cpu/ebpf/debug.rb +61 -0
- data/metasm/cpu/ebpf/decode.rb +142 -0
- data/metasm/cpu/ebpf/main.rb +58 -0
- data/metasm/cpu/ebpf/opcodes.rb +97 -0
- data/metasm/cpu/ebpf/render.rb +36 -0
- data/metasm/cpu/ia32.rb +17 -0
- data/{lib/metasm → metasm/cpu}/ia32/compile_c.rb +23 -9
- data/{lib/metasm → metasm/cpu}/ia32/debug.rb +44 -6
- data/{lib/metasm → metasm/cpu}/ia32/decode.rb +342 -128
- data/{lib/metasm → metasm/cpu}/ia32/decompile.rb +75 -53
- data/{lib/metasm → metasm/cpu}/ia32/encode.rb +19 -13
- data/{lib/metasm → metasm/cpu}/ia32/main.rb +66 -8
- data/metasm/cpu/ia32/opcodes.rb +1424 -0
- data/{lib/metasm → metasm/cpu}/ia32/parse.rb +55 -17
- data/{lib/metasm → metasm/cpu}/ia32/render.rb +32 -5
- data/metasm/cpu/mcs51.rb +8 -0
- data/metasm/cpu/mcs51/decode.rb +99 -0
- data/metasm/cpu/mcs51/main.rb +87 -0
- data/metasm/cpu/mcs51/opcodes.rb +120 -0
- data/metasm/cpu/mips.rb +14 -0
- data/metasm/cpu/mips/debug.rb +42 -0
- data/{lib/metasm → metasm/cpu}/mips/decode.rb +59 -38
- data/{lib/metasm → metasm/cpu}/mips/encode.rb +4 -3
- data/{lib/metasm → metasm/cpu}/mips/main.rb +13 -6
- data/{lib/metasm → metasm/cpu}/mips/opcodes.rb +87 -18
- 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 +243 -0
- data/metasm/cpu/msp430/main.rb +62 -0
- data/metasm/cpu/msp430/opcodes.rb +101 -0
- data/metasm/cpu/openrisc.rb +11 -0
- data/metasm/cpu/openrisc/debug.rb +106 -0
- data/metasm/cpu/openrisc/decode.rb +182 -0
- data/metasm/cpu/openrisc/decompile.rb +350 -0
- data/metasm/cpu/openrisc/main.rb +70 -0
- data/metasm/cpu/openrisc/opcodes.rb +109 -0
- data/metasm/cpu/openrisc/render.rb +37 -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/metasm/cpu/ppc.rb +11 -0
- data/{lib/metasm → metasm/cpu}/ppc/decode.rb +18 -37
- 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 +23 -18
- data/{lib/metasm → metasm/cpu}/ppc/opcodes.rb +11 -6
- data/metasm/cpu/ppc/parse.rb +55 -0
- data/metasm/cpu/python.rb +8 -0
- data/metasm/cpu/python/decode.rb +116 -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 +50 -23
- data/{lib/metasm → metasm/cpu}/sh4/main.rb +38 -27
- data/{lib/metasm → metasm/cpu}/sh4/opcodes.rb +7 -8
- data/metasm/cpu/st20.rb +9 -0
- data/metasm/cpu/st20/decode.rb +173 -0
- data/metasm/cpu/st20/decompile.rb +283 -0
- data/metasm/cpu/st20/main.rb +37 -0
- data/metasm/cpu/st20/opcodes.rb +140 -0
- data/{lib/metasm/arm.rb → metasm/cpu/webasm.rb} +4 -5
- data/metasm/cpu/webasm/debug.rb +31 -0
- data/metasm/cpu/webasm/decode.rb +321 -0
- data/metasm/cpu/webasm/decompile.rb +386 -0
- data/metasm/cpu/webasm/encode.rb +104 -0
- data/metasm/cpu/webasm/main.rb +81 -0
- data/metasm/cpu/webasm/opcodes.rb +214 -0
- data/metasm/cpu/x86_64.rb +15 -0
- data/{lib/metasm → metasm/cpu}/x86_64/compile_c.rb +40 -25
- data/{lib/metasm → metasm/cpu}/x86_64/debug.rb +4 -4
- data/{lib/metasm → metasm/cpu}/x86_64/decode.rb +58 -15
- data/{lib/metasm → metasm/cpu}/x86_64/encode.rb +59 -28
- data/{lib/metasm → metasm/cpu}/x86_64/main.rb +18 -6
- data/metasm/cpu/x86_64/opcodes.rb +138 -0
- data/{lib/metasm → metasm/cpu}/x86_64/parse.rb +12 -4
- data/metasm/cpu/x86_64/render.rb +35 -0
- data/metasm/cpu/z80.rb +9 -0
- data/metasm/cpu/z80/decode.rb +286 -0
- data/metasm/cpu/z80/main.rb +67 -0
- data/metasm/cpu/z80/opcodes.rb +224 -0
- data/metasm/cpu/z80/render.rb +48 -0
- data/{lib/metasm/os/main.rb → metasm/debug.rb} +201 -407
- data/{lib/metasm → metasm}/decode.rb +104 -24
- data/{lib/metasm → metasm}/decompile.rb +804 -478
- data/{lib/metasm → metasm}/disassemble.rb +385 -170
- data/{lib/metasm → metasm}/disassemble_api.rb +684 -105
- data/{lib/metasm → metasm}/dynldr.rb +231 -138
- data/{lib/metasm → metasm}/encode.rb +20 -5
- data/{lib/metasm → metasm}/exe_format/a_out.rb +9 -6
- data/{lib/metasm → metasm}/exe_format/autoexe.rb +3 -0
- data/{lib/metasm → metasm}/exe_format/bflt.rb +57 -27
- data/{lib/metasm → metasm}/exe_format/coff.rb +35 -7
- data/{lib/metasm → metasm}/exe_format/coff_decode.rb +70 -23
- data/{lib/metasm → metasm}/exe_format/coff_encode.rb +24 -22
- data/{lib/metasm → metasm}/exe_format/dex.rb +26 -8
- data/{lib/metasm → metasm}/exe_format/dol.rb +1 -0
- data/{lib/metasm → metasm}/exe_format/elf.rb +108 -58
- data/{lib/metasm → metasm}/exe_format/elf_decode.rb +202 -36
- data/{lib/metasm → metasm}/exe_format/elf_encode.rb +126 -32
- data/metasm/exe_format/gb.rb +65 -0
- data/metasm/exe_format/javaclass.rb +424 -0
- data/{lib/metasm → metasm}/exe_format/macho.rb +218 -16
- data/{lib/metasm → metasm}/exe_format/main.rb +28 -3
- data/{lib/metasm → metasm}/exe_format/mz.rb +2 -0
- data/{lib/metasm → metasm}/exe_format/nds.rb +7 -4
- data/{lib/metasm → metasm}/exe_format/pe.rb +96 -11
- 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/metasm/exe_format/wasm.rb +402 -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 +177 -114
- data/{lib/metasm → metasm}/gui/dasm_funcgraph.rb +0 -0
- data/metasm/gui/dasm_graph.rb +1754 -0
- data/{lib/metasm → metasm}/gui/dasm_hex.rb +16 -12
- data/{lib/metasm → metasm}/gui/dasm_listing.rb +43 -28
- data/{lib/metasm → metasm}/gui/dasm_main.rb +360 -77
- data/{lib/metasm → metasm}/gui/dasm_opcodes.rb +5 -19
- data/{lib/metasm → metasm}/gui/debug.rb +109 -34
- data/{lib/metasm → metasm}/gui/gtk.rb +174 -44
- data/{lib/metasm → metasm}/gui/qt.rb +14 -4
- data/{lib/metasm → metasm}/gui/win32.rb +180 -43
- data/{lib/metasm → metasm}/gui/x11.rb +59 -59
- data/{lib/metasm → metasm}/main.rb +421 -286
- data/metasm/os/emulator.rb +175 -0
- 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 +335 -0
- data/{lib/metasm → metasm}/os/windows.rb +151 -58
- data/{lib/metasm → metasm}/os/windows_exports.rb +141 -0
- data/{lib/metasm → metasm}/parse.rb +49 -36
- data/{lib/metasm → metasm}/parse_c.rb +405 -246
- data/{lib/metasm → metasm}/preprocessor.rb +71 -41
- data/{lib/metasm → metasm}/render.rb +14 -38
- data/misc/hexdump.rb +4 -3
- data/misc/lint.rb +58 -0
- data/misc/objdiff.rb +4 -1
- data/misc/objscan.rb +1 -1
- data/misc/openrisc-parser.rb +79 -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 +29 -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 +48 -7
- data/samples/disassemble.rb +31 -6
- data/samples/dump_upx.rb +24 -12
- data/samples/dynamic_ruby.rb +35 -27
- data/samples/elfencode.rb +15 -0
- data/samples/emubios.rb +251 -0
- data/samples/emudbg.rb +127 -0
- data/samples/exeencode.rb +6 -5
- data/samples/factorize-headers-peimports.rb +1 -1
- data/samples/lindebug.rb +186 -391
- data/samples/metasm-shell.rb +68 -57
- 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 +57 -0
- data/tests/graph_layout.rb +285 -0
- data/tests/ia32.rb +80 -26
- data/tests/mcs51.rb +27 -0
- data/tests/mips.rb +10 -3
- data/tests/preprocessor.rb +18 -0
- data/tests/x86_64.rb +66 -18
- metadata +465 -219
- metadata.gz.sig +2 -0
- 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 -872
- 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
|
|
@@ -26,18 +26,10 @@ class CPU
|
|
26
26
|
while tok = lexer.readtok and parse_prefix(i, tok.raw)
|
27
27
|
lexer.skip_space_eol
|
28
28
|
end
|
29
|
-
return if not tok
|
30
29
|
|
31
|
-
|
32
|
-
tok =
|
33
|
-
|
34
|
-
tok.raw << lexer.readtok.raw
|
35
|
-
ntok = lexer.readtok
|
36
|
-
raise tok, 'invalid opcode name' if not ntok or ntok.type != :string
|
37
|
-
tok.raw << ntok.raw
|
38
|
-
end
|
39
|
-
|
40
|
-
raise tok, 'invalid opcode' if not opcode_list_byname[tok.raw]
|
30
|
+
lexer.unreadtok(tok)
|
31
|
+
tok = parse_instruction_mnemonic(lexer)
|
32
|
+
return if not tok
|
41
33
|
|
42
34
|
i.opname = tok.raw
|
43
35
|
i.backtrace = tok.backtrace
|
@@ -63,6 +55,23 @@ class CPU
|
|
63
55
|
i
|
64
56
|
end
|
65
57
|
|
58
|
+
# return a lexer token with an instruction mnemonic in #raw
|
59
|
+
# allows '.' in opcode name
|
60
|
+
# return nil at eof
|
61
|
+
def parse_instruction_mnemonic(lexer)
|
62
|
+
return if not tok = lexer.readtok
|
63
|
+
tok = tok.dup
|
64
|
+
while ntok = lexer.nexttok and ntok.type == :punct and ntok.raw == '.'
|
65
|
+
tok.raw << lexer.readtok.raw
|
66
|
+
ntok = lexer.readtok
|
67
|
+
raise tok, 'invalid opcode name' if not ntok or ntok.type != :string
|
68
|
+
tok.raw << ntok.raw
|
69
|
+
end
|
70
|
+
|
71
|
+
raise tok, 'invalid opcode' if not opcode_list_byname[tok.raw]
|
72
|
+
tok
|
73
|
+
end
|
74
|
+
|
66
75
|
def parse_instruction_checkproto(i)
|
67
76
|
opcode_list_byname[i.opname].to_a.find { |o|
|
68
77
|
o.args.length == i.args.length and o.args.zip(i.args).all? { |f, a| parse_arg_valid?(o, f, a) }
|
@@ -159,13 +168,20 @@ class AsmPreprocessor < Preprocessor
|
|
159
168
|
end
|
160
169
|
end
|
161
170
|
|
171
|
+
class Preprocessor::Token
|
172
|
+
# token already preprocessed for macro def/expansion
|
173
|
+
attr_accessor :alreadyapp
|
174
|
+
end
|
175
|
+
|
162
176
|
# the program (used to create new label names)
|
163
177
|
attr_accessor :program
|
164
178
|
# hash macro name => Macro
|
165
179
|
attr_accessor :macro
|
180
|
+
attr_accessor :may_apreprocess
|
166
181
|
|
167
182
|
def initialize(text='', program=nil)
|
168
183
|
@program = program
|
184
|
+
@may_apreprocess = false
|
169
185
|
@macro = {}
|
170
186
|
super(text)
|
171
187
|
end
|
@@ -184,13 +200,21 @@ class AsmPreprocessor < Preprocessor
|
|
184
200
|
t
|
185
201
|
end
|
186
202
|
|
187
|
-
|
188
|
-
|
189
|
-
|
203
|
+
def feed!(*a)
|
204
|
+
super(*a)
|
205
|
+
if not @may_apreprocess and (@text =~ / (macro|equ) / or not @macro.empty?)
|
206
|
+
@may_apreprocess = true
|
207
|
+
end
|
208
|
+
self
|
209
|
+
end
|
210
|
+
|
211
|
+
# reads a token, handles macros/comments/etc
|
212
|
+
def readtok
|
190
213
|
tok = super()
|
214
|
+
return tok if not tok or tok.alreadyapp
|
191
215
|
|
192
216
|
# handle ; comments
|
193
|
-
if tok
|
217
|
+
if tok.type == :punct and tok.raw[0] == ?;
|
194
218
|
tok.type = :eol
|
195
219
|
begin
|
196
220
|
tok = tok.dup
|
@@ -203,30 +227,13 @@ class AsmPreprocessor < Preprocessor
|
|
203
227
|
end
|
204
228
|
end
|
205
229
|
|
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
230
|
# handle macros
|
222
|
-
|
223
|
-
if not rec and tok and tok.type == :string
|
231
|
+
if @may_apreprocess and tok.type == :string
|
224
232
|
if @macro[tok.raw]
|
225
233
|
@macro[tok.raw].apply(tok, self, @program).reverse_each { |t| unreadtok t }
|
226
234
|
tok = readtok
|
227
|
-
|
228
235
|
else
|
229
|
-
if ntok =
|
236
|
+
if ntok = super() and ntok.type == :space and nntok = super() and nntok.type == :string and (nntok.raw == 'macro' or nntok.raw == 'equ')
|
230
237
|
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
238
|
m = Macro.new tok
|
232
239
|
# XXX this allows nested macro definition..
|
@@ -252,6 +259,7 @@ class AsmPreprocessor < Preprocessor
|
|
252
259
|
end
|
253
260
|
end
|
254
261
|
|
262
|
+
tok.alreadyapp = true if tok
|
255
263
|
tok
|
256
264
|
end
|
257
265
|
end
|
@@ -314,6 +322,7 @@ class ExeFormat
|
|
314
322
|
lname = @locallabels_bkw[tok.raw] = @locallabels_fwd.delete(tok.raw) || new_label('local_'+tok.raw)
|
315
323
|
else
|
316
324
|
lname = tok.raw
|
325
|
+
raise tok, "invalid label name: #{lname.inspect} is reserved" if @cpu.check_reserved_name(lname)
|
317
326
|
raise tok, "label redefinition" if new_label(lname) != lname
|
318
327
|
end
|
319
328
|
l = Label.new(lname)
|
@@ -421,7 +430,7 @@ class ExeFormat
|
|
421
430
|
@cursource << Padding.new(fillwith, tok.backtrace) << Offset.new(e, tok.backtrace)
|
422
431
|
|
423
432
|
else
|
424
|
-
@cpu.parse_parser_instruction(
|
433
|
+
@cpu.parse_parser_instruction(@lexer, tok)
|
425
434
|
end
|
426
435
|
end
|
427
436
|
|
@@ -746,6 +755,8 @@ class Expression
|
|
746
755
|
|
747
756
|
# for boolean operators, true is 1 (or anything != 0), false is 0
|
748
757
|
def parse(lexer)
|
758
|
+
lexer = Preprocessor.new(lexer) if lexer.kind_of?(::String)
|
759
|
+
|
749
760
|
opstack = []
|
750
761
|
stack = []
|
751
762
|
|
@@ -780,7 +791,7 @@ class Expression
|
|
780
791
|
pp = Preprocessor.new(str)
|
781
792
|
|
782
793
|
e = parse(pp, &b)
|
783
|
-
|
794
|
+
|
784
795
|
# update arg
|
785
796
|
len = pp.pos
|
786
797
|
pp.queue.each { |t| len -= t.raw.length }
|
@@ -821,6 +832,8 @@ class IndExpression < Expression
|
|
821
832
|
break
|
822
833
|
when ':' # symbols, eg ':eax'
|
823
834
|
n = lexer.readtok
|
835
|
+
nil while tok = lexer.readtok and tok.type == :space
|
836
|
+
lexer.unreadtok tok
|
824
837
|
return n.raw.to_sym
|
825
838
|
else
|
826
839
|
lexer.unreadtok tok
|
@@ -22,7 +22,17 @@ module C
|
|
22
22
|
__builtin_offsetof
|
23
23
|
].inject({}) { |h, w| h.update w => true }
|
24
24
|
|
25
|
+
module Misc
|
26
|
+
attr_accessor :misc
|
27
|
+
|
28
|
+
def with_misc(m)
|
29
|
+
@misc = m if m or misc
|
30
|
+
self
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
25
34
|
class Statement
|
35
|
+
include Misc
|
26
36
|
end
|
27
37
|
|
28
38
|
module Typed # allows quick testing whether an object is an CExpr or a Variable
|
@@ -114,6 +124,7 @@ module C
|
|
114
124
|
|
115
125
|
class Type
|
116
126
|
include Attributes
|
127
|
+
include Misc
|
117
128
|
attr_accessor :qualifier # const volatile
|
118
129
|
|
119
130
|
def pointer? ; false end
|
@@ -249,7 +260,7 @@ module C
|
|
249
260
|
end
|
250
261
|
|
251
262
|
def findmember(name, igncase=false)
|
252
|
-
raise
|
263
|
+
raise 'undefined structure' if not members
|
253
264
|
return @fldlist[name] if fldlist and @fldlist[name]
|
254
265
|
|
255
266
|
name = name.downcase if igncase
|
@@ -267,7 +278,7 @@ module C
|
|
267
278
|
end
|
268
279
|
|
269
280
|
def offsetof(parser, name)
|
270
|
-
raise parser, 'undefined structure' if not
|
281
|
+
raise parser, 'undefined structure' if not members
|
271
282
|
update_member_cache(parser) if not fldlist
|
272
283
|
return 0 if @fldlist[name]
|
273
284
|
|
@@ -284,7 +295,7 @@ module C
|
|
284
295
|
end
|
285
296
|
|
286
297
|
def bitoffsetof(parser, name)
|
287
|
-
raise parser, 'undefined structure' if not
|
298
|
+
raise parser, 'undefined structure' if not members
|
288
299
|
update_member_cache(parser) if not fldlist
|
289
300
|
return if @fldlist[name] or @members.include?(name)
|
290
301
|
raise parser, 'undefined union' if not @members
|
@@ -390,6 +401,22 @@ module C
|
|
390
401
|
end
|
391
402
|
idx + 1
|
392
403
|
end
|
404
|
+
|
405
|
+
# resolve structptr + offset into 'str.membername'
|
406
|
+
# handles 'var.substruct1.array[12].foo'
|
407
|
+
# updates str
|
408
|
+
# returns the final member type itself
|
409
|
+
# works for Struct/Union/Array
|
410
|
+
def expand_member_offset(c_parser, off, str)
|
411
|
+
# XXX choose in members, check sizeof / prefer structs
|
412
|
+
m = @members.first
|
413
|
+
str << '.' << m.name if m.name
|
414
|
+
if m.type.respond_to?(:expand_member_offset)
|
415
|
+
m.type.expand_member_offset(c_parser, off, str)
|
416
|
+
else
|
417
|
+
m.type
|
418
|
+
end
|
419
|
+
end
|
393
420
|
end
|
394
421
|
class Struct < Union
|
395
422
|
attr_accessor :pack
|
@@ -397,9 +424,10 @@ module C
|
|
397
424
|
def align(parser) [@members.to_a.map { |m| m.type.align(parser) }.max || 1, (pack || 8)].min end
|
398
425
|
|
399
426
|
def offsetof(parser, name)
|
400
|
-
raise parser, 'undefined structure' if not
|
427
|
+
raise parser, 'undefined structure' if not members
|
401
428
|
update_member_cache(parser) if not fldlist
|
402
429
|
return @fldoffset[name] if @fldoffset[name]
|
430
|
+
return @fldoffset[name.name] if name.respond_to?(:name) and @fldoffset[name.name]
|
403
431
|
|
404
432
|
# this is almost never reached, only for <struct>.offsetof(anonymoussubstructmembername)
|
405
433
|
raise parser, 'unknown structure member' if (name.kind_of?(::String) ? !findmember(name) : !@members.include?(name))
|
@@ -433,7 +461,7 @@ module C
|
|
433
461
|
end
|
434
462
|
mal = [m.type.align(parser), al].min
|
435
463
|
off = (off + mal - 1) / mal * mal
|
436
|
-
|
464
|
+
if m.name == name or m == name
|
437
465
|
break
|
438
466
|
elsif indirect and m.type.untypedef.kind_of? Union and m.type.untypedef.findmember(name)
|
439
467
|
off += m.type.untypedef.offsetof(parser, name)
|
@@ -449,18 +477,28 @@ module C
|
|
449
477
|
# returns the [bitoffset, bitlength] of the field if it is a bitfield
|
450
478
|
# this should be added to the offsetof(field)
|
451
479
|
def bitoffsetof(parser, name)
|
452
|
-
raise parser, 'undefined structure' if not
|
480
|
+
raise parser, 'undefined structure' if not members
|
453
481
|
update_member_cache(parser) if not fldlist
|
454
482
|
return @fldbitoffset[name] if fldbitoffset and @fldbitoffset[name]
|
483
|
+
return @fldbitoffset[name.name] if fldbitoffset and name.respond_to?(:name) and @fldbitoffset[name.name]
|
455
484
|
return if @fldlist[name] or @members.include?(name)
|
456
485
|
raise parser, 'undefined union' if not @members
|
457
486
|
raise parser, 'unknown union member' if not findmember(name)
|
458
487
|
|
459
488
|
@members.find { |m|
|
460
|
-
m.type.untypedef.kind_of?
|
489
|
+
m.type.untypedef.kind_of?(Union) and m.type.untypedef.findmember(name)
|
461
490
|
}.type.untypedef.bitoffsetof(parser, name)
|
462
491
|
end
|
463
492
|
|
493
|
+
# returns the @member element that has offsetof(m) == off
|
494
|
+
def findmember_atoffset(parser, off)
|
495
|
+
return if not members
|
496
|
+
update_member_cache(parser) if not fldlist
|
497
|
+
if m = @fldoffset.index(off)
|
498
|
+
@fldlist[m]
|
499
|
+
end
|
500
|
+
end
|
501
|
+
|
464
502
|
def parse_members(parser, scope)
|
465
503
|
super(parser, scope)
|
466
504
|
|
@@ -515,6 +553,32 @@ module C
|
|
515
553
|
end
|
516
554
|
}
|
517
555
|
end
|
556
|
+
|
557
|
+
# see Union#expand_member_offset
|
558
|
+
def expand_member_offset(c_parser, off, str)
|
559
|
+
members.to_a.each { |m|
|
560
|
+
mo = offsetof(c_parser, m)
|
561
|
+
if mo == off or mo + c_parser.sizeof(m) > off
|
562
|
+
if bitoffsetof(c_parser, m)
|
563
|
+
# ignore bitfields
|
564
|
+
str << "+#{off}" if off > 0
|
565
|
+
return self
|
566
|
+
end
|
567
|
+
|
568
|
+
str << '.' << m.name if m.name
|
569
|
+
if m.type.respond_to?(:expand_member_offset)
|
570
|
+
return m.type.expand_member_offset(c_parser, off-mo, str)
|
571
|
+
else
|
572
|
+
return m.type
|
573
|
+
end
|
574
|
+
elsif mo > off
|
575
|
+
break
|
576
|
+
end
|
577
|
+
}
|
578
|
+
# XXX that works only for pointer-style str
|
579
|
+
str << "+#{off}" if off > 0
|
580
|
+
nil
|
581
|
+
end
|
518
582
|
end
|
519
583
|
class Enum < Type
|
520
584
|
# name => value
|
@@ -557,6 +621,11 @@ module C
|
|
557
621
|
parse_attributes(parser)
|
558
622
|
end
|
559
623
|
|
624
|
+
def compare_deep(o)
|
625
|
+
return true if o.object_id == self.object_id
|
626
|
+
return if o.class != self.class or o.name != self.name or o.attributes != self.attributes
|
627
|
+
members == o.members
|
628
|
+
end
|
560
629
|
end
|
561
630
|
class Pointer < Type
|
562
631
|
attr_accessor :type
|
@@ -684,11 +753,23 @@ module C
|
|
684
753
|
end
|
685
754
|
idx + 1
|
686
755
|
end
|
756
|
+
|
757
|
+
# see Union#expand_member_offset
|
758
|
+
def expand_member_offset(c_parser, off, str)
|
759
|
+
tsz = c_parser.sizeof(@type)
|
760
|
+
str << "[#{off/tsz}]"
|
761
|
+
if @type.respond_to?(:expand_member_offset)
|
762
|
+
@type.expand_member_offset(c_parser, off%tsz, str)
|
763
|
+
else
|
764
|
+
@type
|
765
|
+
end
|
766
|
+
end
|
687
767
|
end
|
688
768
|
|
689
769
|
class Variable
|
690
770
|
include Attributes
|
691
771
|
include Typed
|
772
|
+
include Misc
|
692
773
|
|
693
774
|
attr_accessor :type
|
694
775
|
attr_accessor :initializer # CExpr / Block (for Functions)
|
@@ -704,6 +785,8 @@ module C
|
|
704
785
|
# found in a block's Statements, used to know the initialization order
|
705
786
|
# eg { int i; i = 4; struct foo { int k; } toto = {i}; }
|
706
787
|
class Declaration
|
788
|
+
include Misc
|
789
|
+
|
707
790
|
attr_accessor :var
|
708
791
|
def initialize(var)
|
709
792
|
@var = var
|
@@ -877,10 +960,10 @@ module C
|
|
877
960
|
raise ftok, 'unterminated asm block' if not tok = parser.lexer.readtok
|
878
961
|
break if tok.type == :punct and tok.raw == '}'
|
879
962
|
case tok.type
|
880
|
-
when :space; body << ' '
|
881
|
-
when :eol; body << "\n"
|
963
|
+
when :space; body << ' ' unless body.empty?
|
964
|
+
when :eol; body << "\n" unless body.empty?
|
882
965
|
when :punct; body << tok.raw
|
883
|
-
when :quoted; body << tok.value
|
966
|
+
when :quoted; body << CExpression.string_inspect(tok.value) # concat adjacent c strings
|
884
967
|
when :string
|
885
968
|
body << \
|
886
969
|
case tok.raw
|
@@ -923,7 +1006,7 @@ module C
|
|
923
1006
|
break
|
924
1007
|
else body << tok.raw
|
925
1008
|
end
|
926
|
-
when :quoted; body << (body.empty? ? tok.value : tok.value
|
1009
|
+
when :quoted; body << (body.empty? ? tok.value : CExpression.string_inspect(tok.value)) # asm "pop\nret" VS asm add al, 'z'
|
927
1010
|
when :string
|
928
1011
|
body << \
|
929
1012
|
case tok.raw
|
@@ -987,17 +1070,20 @@ module C
|
|
987
1070
|
class CExpression < Statement
|
988
1071
|
include Typed
|
989
1072
|
|
1073
|
+
AssignOp = [:'=', :'+=', :'-=', :'*=', :'/=', :'%=', :'^=', :'&=', :'|=', :'>>=', :'<<=', :'++', :'--']
|
1074
|
+
|
990
1075
|
# may be :,, :., :'->', :funcall (function, [arglist]), :[] (array indexing), nil (cast)
|
991
1076
|
attr_accessor :op
|
992
1077
|
# nil/CExpr/Variable/Label/::String( = :quoted/struct member name)/::Integer/::Float/Block
|
993
1078
|
attr_accessor :lexpr, :rexpr
|
994
1079
|
# a Type
|
995
1080
|
attr_accessor :type
|
1081
|
+
|
996
1082
|
def initialize(l, o, r, t)
|
997
1083
|
raise "invalid CExpr #{[l, o, r, t].inspect}" if (o and not o.kind_of? ::Symbol) or not t.kind_of? Type
|
998
1084
|
@lexpr, @op, @rexpr, @type = l, o, r, t
|
999
1085
|
end
|
1000
|
-
|
1086
|
+
|
1001
1087
|
# overwrites @lexpr @op @rexpr @type from the arg
|
1002
1088
|
def replace(o)
|
1003
1089
|
@lexpr, @op, @rexpr, @type = o.lexpr, o.op, o.rexpr, o.type
|
@@ -1023,7 +1109,7 @@ module C
|
|
1023
1109
|
# sub-arrays in args are to be passed to self.[] recursively (syntaxic sugar)
|
1024
1110
|
splat = lambda { |e| e.kind_of?(::Array) ? self[*e] : e }
|
1025
1111
|
|
1026
|
-
args.shift while args.first == nil # CExpr[nil, :&, bla] => CExpr[:&, bla]
|
1112
|
+
args.shift while args.length > 0 and args.first == nil # CExpr[nil, :&, bla] => CExpr[:&, bla]
|
1027
1113
|
|
1028
1114
|
case args.length
|
1029
1115
|
when 4
|
@@ -1033,7 +1119,7 @@ module C
|
|
1033
1119
|
else
|
1034
1120
|
x2 = splat[args[2]]
|
1035
1121
|
end
|
1036
|
-
|
1122
|
+
new(splat[args[0]], op, x2, args[3])
|
1037
1123
|
when 3
|
1038
1124
|
op = args[1]
|
1039
1125
|
x1 = splat[args[0]]
|
@@ -1045,9 +1131,9 @@ module C
|
|
1045
1131
|
|
1046
1132
|
case op
|
1047
1133
|
when :funcall
|
1048
|
-
|
1049
|
-
|
1050
|
-
|
1134
|
+
rt = x1.type.untypedef
|
1135
|
+
rt = rt.type.untypedef if rt.pointer?
|
1136
|
+
new(x1, op, x2, rt.type)
|
1051
1137
|
when :[]; new(x1, op, x2, x1.type.untypedef.type)
|
1052
1138
|
when :+; new(x1, op, x2, (x2.type.pointer? ? x2.type : x1.type))
|
1053
1139
|
when :-; new(x1, op, x2, ((x1.type.pointer? and x2.type.pointer?) ? BaseType.new(:int) : x2.type.pointer? ? x2.type : x1.type))
|
@@ -1111,13 +1197,14 @@ module C
|
|
1111
1197
|
attr_accessor :lexer, :toplevel, :typesize, :pragma_pack
|
1112
1198
|
attr_accessor :endianness
|
1113
1199
|
attr_accessor :allow_bad_c
|
1200
|
+
attr_accessor :program
|
1114
1201
|
# allowed arguments: ExeFormat, CPU, Preprocessor, Symbol (for the data model)
|
1115
1202
|
def initialize(*args)
|
1116
1203
|
model = args.grep(Symbol).first || :ilp32
|
1117
1204
|
lexer = args.grep(Preprocessor).first || Preprocessor.new
|
1118
|
-
|
1205
|
+
@program = args.grep(ExeFormat).first
|
1119
1206
|
cpu = args.grep(CPU).first
|
1120
|
-
cpu ||=
|
1207
|
+
cpu ||= @program.cpu if @program
|
1121
1208
|
@lexer = lexer
|
1122
1209
|
@prev_pragma_callback = @lexer.pragma_callback
|
1123
1210
|
@lexer.pragma_callback = lambda { |tok| parse_pragma_callback(tok) }
|
@@ -1128,7 +1215,7 @@ module C
|
|
1128
1215
|
:char => 1, :float => 4, :double => 8, :longdouble => 12 }
|
1129
1216
|
send model
|
1130
1217
|
cpu.tune_cparser(self) if cpu
|
1131
|
-
|
1218
|
+
@program.tune_cparser(self) if @program
|
1132
1219
|
end
|
1133
1220
|
|
1134
1221
|
def ilp16
|
@@ -1513,6 +1600,7 @@ EOH
|
|
1513
1600
|
when Struct
|
1514
1601
|
raise self, "unknown structure size #{type.name}" if not type.members
|
1515
1602
|
al = type.align(self)
|
1603
|
+
al = 1 if (var.kind_of?(Attributes) and var.has_attribute('sizeof_packed')) or type.has_attribute('sizeof_packed')
|
1516
1604
|
lm = type.members.last
|
1517
1605
|
lm ? (type.offsetof(self, lm) + sizeof(lm) + al - 1) / al * al : 0
|
1518
1606
|
when Union
|
@@ -1703,6 +1791,7 @@ EOH
|
|
1703
1791
|
Goto.new name
|
1704
1792
|
when 'return'
|
1705
1793
|
expr = CExpression.parse(self, scope) # nil allowed
|
1794
|
+
raise tok || self, "cannot return #{expr} in function returning void" if expr and nest[0].kind_of?(Type) and nest[0].void?
|
1706
1795
|
p, i = nest[0].pointer?, nest[0].integral? if expr
|
1707
1796
|
r = expr.reduce(self) if p or i
|
1708
1797
|
if (not p and not i) or (i and not r.kind_of? ::Integer) or (p and r != 0)
|
@@ -1770,6 +1859,7 @@ EOH
|
|
1770
1859
|
end
|
1771
1860
|
|
1772
1861
|
# returns all numeric constants defined with their value, either macros or enums
|
1862
|
+
# for enums, also return the enum name
|
1773
1863
|
def numeric_constants
|
1774
1864
|
ret = []
|
1775
1865
|
# macros
|
@@ -1779,8 +1869,17 @@ EOH
|
|
1779
1869
|
end
|
1780
1870
|
}
|
1781
1871
|
# enums
|
1872
|
+
seen_enum = {}
|
1873
|
+
@toplevel.struct.each { |k, v|
|
1874
|
+
if v.kind_of?(Enum)
|
1875
|
+
v.members.each { |kk, vv|
|
1876
|
+
ret << [kk, vv, k]
|
1877
|
+
seen_enum[kk] = true
|
1878
|
+
}
|
1879
|
+
end
|
1880
|
+
}
|
1782
1881
|
@toplevel.symbol.each { |k, v|
|
1783
|
-
ret << [k, v] if v.kind_of?
|
1882
|
+
ret << [k, v] if v.kind_of?(::Numeric) and not seen_enum[k]
|
1784
1883
|
}
|
1785
1884
|
ret
|
1786
1885
|
end
|
@@ -1933,7 +2032,10 @@ EOH
|
|
1933
2032
|
name = :int
|
1934
2033
|
tok = nil
|
1935
2034
|
loop do
|
1936
|
-
|
2035
|
+
if not tok = parser.skipspaces
|
2036
|
+
raise parser if specifier.empty?
|
2037
|
+
break
|
2038
|
+
end
|
1937
2039
|
if tok.type != :string
|
1938
2040
|
parser.unreadtok tok
|
1939
2041
|
break
|
@@ -2239,12 +2341,13 @@ EOH
|
|
2239
2341
|
else
|
2240
2342
|
l = CExpression.new(nil, nil, l, BaseType.new(:int)) if l.kind_of? ::Integer
|
2241
2343
|
r = CExpression.new(nil, nil, r, BaseType.new(:int)) if r.kind_of? ::Integer
|
2242
|
-
|
2344
|
+
CExpression.new(l, @op, r, @type)
|
2243
2345
|
end
|
2244
2346
|
when :'.'
|
2245
2347
|
le = CExpression.reduce(parser, @lexpr)
|
2246
2348
|
if le.kind_of? Variable and le.initializer.kind_of? ::Array
|
2247
|
-
|
2349
|
+
t = le.type.untypedef
|
2350
|
+
midx = t.members.index(t.findmember(@rexpr))
|
2248
2351
|
CExpression.reduce(parser, le.initializer[midx] || 0)
|
2249
2352
|
else
|
2250
2353
|
CExpression.new(le, @op, @rexpr, @type)
|
@@ -2282,7 +2385,7 @@ EOH
|
|
2282
2385
|
end
|
2283
2386
|
else
|
2284
2387
|
l = CExpression.reduce(parser, @lexpr)
|
2285
|
-
|
2388
|
+
if not l.kind_of?(::Numeric) or not r.kind_of?(::Numeric)
|
2286
2389
|
l = CExpression.new(nil, nil, l, BaseType.new(:int)) if l.kind_of? ::Integer
|
2287
2390
|
r = CExpression.new(nil, nil, r, BaseType.new(:int)) if r.kind_of? ::Integer
|
2288
2391
|
return CExpression.new(l, @op, r, @type)
|
@@ -2325,7 +2428,7 @@ EOH
|
|
2325
2428
|
o.object_id == self.object_id or
|
2326
2429
|
(self.class == o.class and op == o.op and lexpr == o.lexpr and rexpr == o.rexpr)
|
2327
2430
|
end
|
2328
|
-
|
2431
|
+
|
2329
2432
|
def ===(o)
|
2330
2433
|
(self.class == o.class and op == o.op and lexpr === o.lexpr and rexpr === o.rexpr) or
|
2331
2434
|
(o.class == Variable and not @op and @rexpr == o)
|
@@ -2506,6 +2609,7 @@ EOH
|
|
2506
2609
|
type = :long if suffix.count('l') == 1
|
2507
2610
|
end
|
2508
2611
|
val = CExpression[val, BaseType.new(type, *specifier)]
|
2612
|
+
val = parse_value_postfix(parser, scope, val)
|
2509
2613
|
else raise parser, "internal error #{val.inspect}"
|
2510
2614
|
end
|
2511
2615
|
|
@@ -2513,6 +2617,7 @@ EOH
|
|
2513
2617
|
if tok.raw[0] == ?'
|
2514
2618
|
raise tok, 'invalid character constant' if not [1, 2, 4, 8].include? tok.value.length # TODO 0fill
|
2515
2619
|
val = CExpression[Expression.decode_imm(tok.value, tok.value.length, :big), BaseType.new(:int)]
|
2620
|
+
val = parse_value_postfix(parser, scope, val)
|
2516
2621
|
else
|
2517
2622
|
val = CExpression[tok.value, Pointer.new(BaseType.new(tok.raw[0, 2] == 'L"' ? :short : :char))]
|
2518
2623
|
val = parse_value_postfix(parser, scope, val)
|
@@ -2712,96 +2817,109 @@ EOH
|
|
2712
2817
|
end
|
2713
2818
|
end
|
2714
2819
|
|
2715
|
-
def
|
2716
|
-
|
2717
|
-
|
2718
|
-
|
2719
|
-
|
2720
|
-
|
2721
|
-
|
2722
|
-
|
2723
|
-
|
2724
|
-
|
2725
|
-
|
2726
|
-
|
2820
|
+
def parse_popstack(parser, stack, opstack)
|
2821
|
+
r = stack.pop
|
2822
|
+
l = stack.pop
|
2823
|
+
case op = opstack.pop
|
2824
|
+
when :'?:'
|
2825
|
+
stack << CExpression.new(stack.pop, op, [l, r], l.type)
|
2826
|
+
when :','
|
2827
|
+
stack << CExpression.new(l, op, r, r.type)
|
2828
|
+
when :'='
|
2829
|
+
unless r.kind_of?(CExpression) and not r.lexpr and r.type.kind_of?(BaseType) and
|
2830
|
+
((not r.op and r.rexpr.kind_of?(Integer)) or
|
2831
|
+
(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
|
2832
|
+
l.kind_of?(Typed) and (l.type.untypedef.kind_of?(BaseType) or (l.type.untypedef.kind_of?(Pointer) and r.rexpr == 0))
|
2833
|
+
# avoid useless warnings on unsigned foo = -1 / void *foo = 0
|
2727
2834
|
parser.check_compatible_type(parser, r.type, l.type)
|
2728
|
-
|
2729
|
-
|
2730
|
-
|
2835
|
+
end
|
2836
|
+
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]
|
2837
|
+
# (int32)i = (uchar)255 => 255, not -1
|
2838
|
+
r = CExpression.new(nil, nil, r, BaseType.new(lt.name, :unsigned))
|
2839
|
+
end
|
2840
|
+
stack << CExpression.new(l, op, r, l.type)
|
2841
|
+
when :'&&', :'||'
|
2842
|
+
stack << CExpression.new(l, op, r, BaseType.new(:int))
|
2843
|
+
else
|
2844
|
+
# XXX struct == struct ?
|
2845
|
+
raise parser, "invalid type #{l.type} #{l} for #{op.inspect}" if not l.type.arithmetic? and not parser.allow_bad_c
|
2846
|
+
raise parser, "invalid type #{r.type} #{r} for #{op.inspect}" if not r.type.arithmetic? and not parser.allow_bad_c
|
2847
|
+
|
2848
|
+
if l.type.pointer? and r.type.pointer?
|
2849
|
+
type = \
|
2850
|
+
case op
|
2851
|
+
when :'-'; BaseType.new(:long) # addr_t or sumthin ?
|
2852
|
+
when :'-='; l.type
|
2853
|
+
when :'>', :'>=', :'<', :'<=', :'==', :'!='; BaseType.new(:long)
|
2854
|
+
else raise parser, "cannot do #{op.inspect} on pointers" unless parser.allow_bad_c ; l.type
|
2855
|
+
end
|
2856
|
+
elsif l.type.pointer? or r.type.pointer?
|
2857
|
+
puts parser.exception("should not #{op.inspect} a pointer").message if $VERBOSE and not [:'+', :'-', :'=', :'+=', :'-=', :==, :'!='].include? op
|
2858
|
+
type = l.type.pointer? ? l.type : r.type
|
2859
|
+
elsif RIGHTASSOC[op] and op != :'?:' # += etc
|
2860
|
+
type = l.type
|
2731
2861
|
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
|
2862
|
+
# yay integer promotion
|
2863
|
+
lt = l.type.untypedef
|
2864
|
+
rt = r.type.untypedef
|
2865
|
+
if (t = lt).name == :longdouble or (t = rt).name == :longdouble or
|
2866
|
+
(t = lt).name == :double or (t = rt).name == :double or
|
2867
|
+
(t = lt).name == :float or (t = rt).name == :float
|
2868
|
+
# long double > double > float ...
|
2869
|
+
type = t
|
2870
|
+
elsif true
|
2871
|
+
# custom integer rules based on type sizes
|
2872
|
+
lts = parser.typesize[lt.name]
|
2873
|
+
rts = parser.typesize[rt.name]
|
2874
|
+
its = parser.typesize[:int]
|
2875
|
+
if not lts or not rts
|
2876
|
+
type = BaseType.new(:int)
|
2877
|
+
elsif lts > rts and lts >= its
|
2878
|
+
type = lt
|
2879
|
+
elsif rts > lts and rts >= its
|
2880
|
+
type = rt
|
2881
|
+
elsif lts == rts and lts >= its
|
2882
|
+
type = lt
|
2883
|
+
type = rt if rt.specifier == :unsigned
|
2787
2884
|
else
|
2788
|
-
# int
|
2789
2885
|
type = BaseType.new(:int)
|
2790
2886
|
end
|
2791
|
-
|
2792
|
-
|
2793
|
-
|
2794
|
-
|
2795
|
-
|
2796
|
-
|
2797
|
-
|
2798
|
-
|
2887
|
+
# end of custom rules
|
2888
|
+
elsif ((t = lt).name == :long and t.specifier == :unsigned) or
|
2889
|
+
((t = rt).name == :long and t.specifier == :unsigned)
|
2890
|
+
# ... ulong ...
|
2891
|
+
type = t
|
2892
|
+
elsif (lt.name == :long and rt.name == :int and rt.specifier == :unsigned) or
|
2893
|
+
(rt.name == :long and lt.name == :int and lt.specifier == :unsigned)
|
2894
|
+
# long+uint => ulong
|
2895
|
+
type = BaseType.new(:long, :unsigned)
|
2896
|
+
elsif (t = lt).name == :long or (t = rt).name == :long or
|
2897
|
+
((t = lt).name == :int and t.specifier == :unsigned) or
|
2898
|
+
((t = rt).name == :int and t.specifier == :unsigned)
|
2899
|
+
# ... long > uint ...
|
2900
|
+
type = t
|
2799
2901
|
else
|
2800
|
-
|
2801
|
-
|
2902
|
+
# int
|
2903
|
+
type = BaseType.new(:int)
|
2802
2904
|
end
|
2803
2905
|
end
|
2804
|
-
|
2906
|
+
|
2907
|
+
case op
|
2908
|
+
when :'>', :'>=', :'<', :'<=', :'==', :'!='
|
2909
|
+
# cast both sides
|
2910
|
+
l = CExpression[l, type] if l.type != type
|
2911
|
+
r = CExpression[r, type] if r.type != type
|
2912
|
+
stack << CExpression.new(l, op, r, BaseType.new(:int))
|
2913
|
+
else
|
2914
|
+
# promote result
|
2915
|
+
stack << CExpression.new(l, op, r, type)
|
2916
|
+
end
|
2917
|
+
end
|
2918
|
+
end
|
2919
|
+
|
2920
|
+
def parse(parser, scope, allow_coma = true)
|
2921
|
+
opstack = []
|
2922
|
+
stack = []
|
2805
2923
|
|
2806
2924
|
return if not e = parse_value(parser, scope)
|
2807
2925
|
|
@@ -2812,7 +2930,7 @@ EOH
|
|
2812
2930
|
when :'?'
|
2813
2931
|
# a, b ? c, d : e, f == a, (b ? (c, d) : e), f
|
2814
2932
|
until opstack.empty? or OP_PRIO[opstack.last][:'?:']
|
2815
|
-
|
2933
|
+
parse_popstack(parser, stack, opstack)
|
2816
2934
|
end
|
2817
2935
|
stack << parse(parser, scope)
|
2818
2936
|
raise op || parser, '":" expected' if not op = readop(parser) or op.value != :':'
|
@@ -2827,7 +2945,7 @@ EOH
|
|
2827
2945
|
break
|
2828
2946
|
end
|
2829
2947
|
until opstack.empty? or OP_PRIO[op.value][opstack.last]
|
2830
|
-
|
2948
|
+
parse_popstack(parser, stack, opstack)
|
2831
2949
|
end
|
2832
2950
|
end
|
2833
2951
|
|
@@ -2837,7 +2955,7 @@ EOH
|
|
2837
2955
|
end
|
2838
2956
|
|
2839
2957
|
until opstack.empty?
|
2840
|
-
|
2958
|
+
parse_popstack(parser, stack, opstack)
|
2841
2959
|
end
|
2842
2960
|
|
2843
2961
|
CExpression[stack.first]
|
@@ -2929,8 +3047,9 @@ EOH
|
|
2929
3047
|
end
|
2930
3048
|
|
2931
3049
|
a, val = a
|
2932
|
-
|
2933
|
-
a
|
3050
|
+
f = a
|
3051
|
+
raise "#{a.inspect} not a struct member" if not f.kind_of? C::Variable and not f = @struct.findmember(a.to_s, true)
|
3052
|
+
a = f.name || f
|
2934
3053
|
val = sizeof if val == :size
|
2935
3054
|
off = @stroff + @struct.offsetof(@cp, a)
|
2936
3055
|
|
@@ -2972,7 +3091,6 @@ EOH
|
|
2972
3091
|
str.last << "struct #{@struct.name || '_'} x = " if not off
|
2973
3092
|
@struct.update_member_cache(@cp) if not @struct.fldlist
|
2974
3093
|
fldoff = @struct.fldoffset
|
2975
|
-
fbo = @struct.fldbitoffset || {}
|
2976
3094
|
mlist = @struct.members.map { |m| m.name || m }
|
2977
3095
|
else
|
2978
3096
|
str.last << "union #{@struct.name || '_'} x = " if not off
|
@@ -3075,7 +3193,7 @@ EOH
|
|
3075
3193
|
end
|
3076
3194
|
|
3077
3195
|
# parse a given String as an AllocCStruct
|
3078
|
-
# offset is an
|
3196
|
+
# offset is an optional offset from the string start
|
3079
3197
|
# modification to the structure will modify the underlying string
|
3080
3198
|
def decode_c_struct(structname, str, offset=0)
|
3081
3199
|
struct = find_c_struct(structname)
|
@@ -3203,8 +3321,7 @@ EOH
|
|
3203
3321
|
all = @toplevel.struct.values + @toplevel.symbol.values
|
3204
3322
|
all -= all.grep(::Integer) # Enum values
|
3205
3323
|
|
3206
|
-
|
3207
|
-
r.join("\n")
|
3324
|
+
@toplevel.dump_reorder(all, todo_rndr, todo_deps)[0].join("\n")
|
3208
3325
|
end
|
3209
3326
|
|
3210
3327
|
# returns a string containing the C definition(s) of toplevel functions, with their dependencies
|
@@ -3221,19 +3338,49 @@ EOH
|
|
3221
3338
|
end
|
3222
3339
|
end
|
3223
3340
|
|
3341
|
+
# used to render a C to a source string, while keeping the information of which each character comes from which C object
|
3342
|
+
class CRenderString < ::String
|
3343
|
+
attr_accessor :my_c # default C obj with which raw characters are associated
|
3344
|
+
# hash offset => C::Statement, means bytes from this offset to the next entry comes from rendering this C object
|
3345
|
+
def c_at_offset
|
3346
|
+
@c_at_offset ||= {}
|
3347
|
+
end
|
3348
|
+
|
3349
|
+
# concatenate another CRenderString: merge @c_at_offset
|
3350
|
+
def <<(o)
|
3351
|
+
if o.kind_of?(self.class)
|
3352
|
+
o.c_at_offset.each { |k, v|
|
3353
|
+
c_at_offset[length+k] ||= v
|
3354
|
+
}
|
3355
|
+
elsif my_c
|
3356
|
+
c_at_offset[length] ||= my_c
|
3357
|
+
end
|
3358
|
+
super(o)
|
3359
|
+
end
|
3360
|
+
|
3361
|
+
def initialize(*a)
|
3362
|
+
if cs = a.grep(Statement).first
|
3363
|
+
a -= [cs]
|
3364
|
+
@my_c = cs
|
3365
|
+
c_at_offset[0] = cs
|
3366
|
+
end
|
3367
|
+
super(*a)
|
3368
|
+
end
|
3369
|
+
end
|
3370
|
+
|
3224
3371
|
class Statement
|
3225
|
-
def self.dump(e, scope, r=[
|
3372
|
+
def self.dump(e, scope, r=[CRenderString.new], dep=[])
|
3226
3373
|
case e
|
3227
3374
|
when nil; r.last << ';'
|
3228
3375
|
when Block
|
3229
3376
|
r.last << ' ' if not r.last.empty?
|
3230
3377
|
r.last << '{'
|
3231
|
-
tr, dep = e.dump(scope, [
|
3378
|
+
tr, dep = e.dump(scope, [CRenderString.new], dep)
|
3232
3379
|
tr.pop if tr.last.empty?
|
3233
3380
|
r.concat tr.map { |s| Case.dump_indent(s) }
|
3234
|
-
(r.last[-1] == ?{ ? r.last : r) << '}'
|
3381
|
+
(r.last[-1] == ?{ ? r.last : r) << CRenderString.new('}')
|
3235
3382
|
else
|
3236
|
-
tr, dep = e.dump(scope, [
|
3383
|
+
tr, dep = e.dump(scope, [CRenderString.new], dep)
|
3237
3384
|
r.concat tr.map { |s| Case.dump_indent(s) }
|
3238
3385
|
end
|
3239
3386
|
[r, dep]
|
@@ -3248,7 +3395,7 @@ EOH
|
|
3248
3395
|
def to_s() dump(nil)[0].join("\n") end
|
3249
3396
|
|
3250
3397
|
# return array of c source lines and array of dependencies (objects)
|
3251
|
-
def dump(scp, r=[
|
3398
|
+
def dump(scp, r=[CRenderString.new], dep=[])
|
3252
3399
|
mydefs = @symbol.values.grep(TypeDef) + @struct.values + anonymous_enums.to_a
|
3253
3400
|
todo_rndr = {}
|
3254
3401
|
todo_deps = {}
|
@@ -3260,7 +3407,7 @@ EOH
|
|
3260
3407
|
[r, dep]
|
3261
3408
|
end
|
3262
3409
|
|
3263
|
-
def dump_reorder(mydefs, todo_rndr, todo_deps, r=[
|
3410
|
+
def dump_reorder(mydefs, todo_rndr, todo_deps, r=[CRenderString.new], dep=[])
|
3264
3411
|
val = todo_deps.values.flatten.uniq
|
3265
3412
|
dep |= val
|
3266
3413
|
dep -= mydefs | todo_deps.keys
|
@@ -3275,6 +3422,7 @@ EOH
|
|
3275
3422
|
# predeclare structs involved in cyclic dependencies
|
3276
3423
|
dep_cycle = lambda { |ary|
|
3277
3424
|
# sexyness inside (c)
|
3425
|
+
# XXX 5 years later, i have no idea whats going on here
|
3278
3426
|
deps = todo_deps[ary.last]
|
3279
3427
|
if deps.include? ary.first; ary
|
3280
3428
|
elsif (deps-ary).find { |d| deps = dep_cycle[ary + [d]] }; deps
|
@@ -3284,7 +3432,7 @@ EOH
|
|
3284
3432
|
oldc = nil
|
3285
3433
|
while c = dep_cycle[[t]]
|
3286
3434
|
break if oldc == c
|
3287
|
-
r << "#{t.kind_of?(Struct) ? 'struct' : 'union'} #{t.name};" if not oldc
|
3435
|
+
r << CRenderString.new(t, "#{t.kind_of?(Struct) ? 'struct' : 'union'} #{t.name};") if not oldc
|
3288
3436
|
oldc = c
|
3289
3437
|
c.each { |s|
|
3290
3438
|
# XXX struct z { struct a* }; struct a { void (*foo)(struct z); };
|
@@ -3303,7 +3451,7 @@ EOH
|
|
3303
3451
|
end
|
3304
3452
|
todo_now.sort_by { |k| k.name || '0' }.each { |k|
|
3305
3453
|
if k.kind_of? Variable and k.type.kind_of? Function and k.initializer
|
3306
|
-
r <<
|
3454
|
+
r << CRenderString.new
|
3307
3455
|
r.concat todo_rndr.delete(k)
|
3308
3456
|
else
|
3309
3457
|
r.pop if r.last == ''
|
@@ -3313,12 +3461,12 @@ EOH
|
|
3313
3461
|
todo_deps.delete k
|
3314
3462
|
}
|
3315
3463
|
todo_deps.each_key { |k| todo_deps[k] -= todo_now }
|
3316
|
-
r <<
|
3464
|
+
r << CRenderString.new << CRenderString.new << CRenderString.new
|
3317
3465
|
end
|
3318
3466
|
|
3319
3467
|
@statements.each { |s|
|
3320
|
-
r <<
|
3321
|
-
if s.kind_of?
|
3468
|
+
r << CRenderString.new if not r.last.empty?
|
3469
|
+
if s.kind_of?(Block)
|
3322
3470
|
r, dep = Statement.dump(s, self, r, dep)
|
3323
3471
|
else
|
3324
3472
|
r, dep = s.dump(self, r, dep)
|
@@ -3329,10 +3477,10 @@ EOH
|
|
3329
3477
|
end
|
3330
3478
|
end
|
3331
3479
|
class Declaration
|
3332
|
-
def dump(scope, r=[
|
3333
|
-
tr, dep = @var.dump_def(scope, [
|
3334
|
-
if @var.kind_of?
|
3335
|
-
r <<
|
3480
|
+
def dump(scope, r=[CRenderString.new], dep=[])
|
3481
|
+
tr, dep = @var.dump_def(scope, [CRenderString.new], dep)
|
3482
|
+
if @var.kind_of?(Variable) and @var.type.kind_of?(Function) and @var.initializer
|
3483
|
+
r << CRenderString.new
|
3336
3484
|
r.concat tr
|
3337
3485
|
else
|
3338
3486
|
r.pop if r.last == ''
|
@@ -3361,14 +3509,14 @@ EOH
|
|
3361
3509
|
end
|
3362
3510
|
end
|
3363
3511
|
class Variable
|
3364
|
-
def dump(scope, r=[
|
3512
|
+
def dump(scope, r=[CRenderString.new], dep=[])
|
3365
3513
|
if name
|
3366
3514
|
dep |= [scope.symbol_ancestors[@name]]
|
3367
3515
|
r.last << @name
|
3368
3516
|
end
|
3369
3517
|
[r, dep]
|
3370
3518
|
end
|
3371
|
-
def dump_def(scope, r=[
|
3519
|
+
def dump_def(scope, r=[CRenderString.new], dep=[], skiptype=false)
|
3372
3520
|
# int a=1, b=2;
|
3373
3521
|
r.last << dump_attributes_pre
|
3374
3522
|
if not skiptype
|
@@ -3376,7 +3524,7 @@ EOH
|
|
3376
3524
|
r, dep = @type.base.dump(scope, r, dep)
|
3377
3525
|
r.last << ' ' if name
|
3378
3526
|
end
|
3379
|
-
r, dep = @type.dump_declarator([(name ? @name.dup : '') << dump_attributes], scope, r, dep)
|
3527
|
+
r, dep = @type.dump_declarator([CRenderString.new(name ? @name.dup : '') << dump_attributes], scope, r, dep)
|
3380
3528
|
|
3381
3529
|
if initializer
|
3382
3530
|
r.last << ' = ' if not @type.kind_of?(Function)
|
@@ -3390,7 +3538,7 @@ EOH
|
|
3390
3538
|
end
|
3391
3539
|
end
|
3392
3540
|
class Type
|
3393
|
-
def dump_initializer(init, scope, r=[
|
3541
|
+
def dump_initializer(init, scope, r=[CRenderString.new], dep=[])
|
3394
3542
|
case init
|
3395
3543
|
when ::Numeric
|
3396
3544
|
r.last << init.to_s
|
@@ -3402,9 +3550,9 @@ EOH
|
|
3402
3550
|
end
|
3403
3551
|
end
|
3404
3552
|
|
3405
|
-
def dump_declarator(decl, scope, r=[
|
3553
|
+
def dump_declarator(decl, scope, r=[CRenderString.new], dep=[])
|
3406
3554
|
r.last << decl.shift
|
3407
|
-
r.concat decl
|
3555
|
+
r.concat decl.map { |d| CRenderString.new << d }
|
3408
3556
|
[r, dep]
|
3409
3557
|
end
|
3410
3558
|
|
@@ -3412,11 +3560,11 @@ EOH
|
|
3412
3560
|
dump(*a)
|
3413
3561
|
end
|
3414
3562
|
|
3415
|
-
def dump_cast(scope, r=[
|
3563
|
+
def dump_cast(scope, r=[CRenderString.new], dep=[])
|
3416
3564
|
r.last << '('
|
3417
3565
|
r.last << dump_attributes_pre if not kind_of? TypeDef
|
3418
3566
|
r, dep = base.dump(scope, r, dep)
|
3419
|
-
r, dep = dump_declarator([kind_of?(TypeDef) ? '' : dump_attributes], scope, r, dep)
|
3567
|
+
r, dep = dump_declarator([CRenderString.new(kind_of?(TypeDef) ? '' : dump_attributes)], scope, r, dep)
|
3420
3568
|
r.last << ')'
|
3421
3569
|
[r, dep]
|
3422
3570
|
end
|
@@ -3426,28 +3574,29 @@ EOH
|
|
3426
3574
|
end
|
3427
3575
|
end
|
3428
3576
|
class Pointer
|
3429
|
-
def dump_declarator(decl, scope, r=[
|
3577
|
+
def dump_declarator(decl, scope, r=[CRenderString.new], dep=[])
|
3430
3578
|
d = decl[0]
|
3431
|
-
decl[0] =
|
3579
|
+
decl[0] = CRenderString.new
|
3580
|
+
decl[0] << '*'
|
3432
3581
|
decl[0] << ' ' << @qualifier.map { |q| q.to_s }.join(' ') << ' ' if qualifier
|
3433
3582
|
decl[0] << d
|
3434
|
-
if @type.kind_of?
|
3435
|
-
decl[0] = '(' << decl[0]
|
3583
|
+
if @type.kind_of?(Function) or @type.kind_of?(Array)
|
3584
|
+
decl[0] = CRenderString.new << '(' << decl[0]
|
3436
3585
|
decl.last << ')'
|
3437
3586
|
end
|
3438
3587
|
@type.dump_declarator(decl, scope, r, dep)
|
3439
3588
|
end
|
3440
3589
|
end
|
3441
3590
|
class Array
|
3442
|
-
def dump_declarator(decl, scope, r=[
|
3591
|
+
def dump_declarator(decl, scope, r=[CRenderString.new], dep=[])
|
3443
3592
|
decl.last << '()' if decl.last.empty?
|
3444
3593
|
decl.last << '['
|
3445
3594
|
decl, dep = CExpression.dump(@length, scope, decl, dep) if length
|
3446
3595
|
decl.last << ']'
|
3447
3596
|
@type.dump_declarator(decl, scope, r, dep)
|
3448
3597
|
end
|
3449
|
-
def dump_initializer(init, scope, r=[
|
3450
|
-
return super(init, scope, r, dep) if not init.kind_of?
|
3598
|
+
def dump_initializer(init, scope, r=[CRenderString.new], dep=[])
|
3599
|
+
return super(init, scope, r, dep) if not init.kind_of?(::Array)
|
3451
3600
|
r.last << '{ '
|
3452
3601
|
showname = false
|
3453
3602
|
init.each_with_index { |v, i|
|
@@ -3456,21 +3605,21 @@ EOH
|
|
3456
3605
|
next
|
3457
3606
|
end
|
3458
3607
|
r.last << ', ' if r.last[-2, 2] != '{ '
|
3459
|
-
rt = [
|
3608
|
+
rt = [CRenderString.new]
|
3460
3609
|
if showname
|
3461
3610
|
showname = false
|
3462
|
-
rt << "[#{i}] = "
|
3611
|
+
rt << CRenderString.new("[#{i}] = ")
|
3463
3612
|
end
|
3464
3613
|
rt, dep = @type.dump_initializer(v, scope, rt, dep)
|
3465
3614
|
r.last << rt.shift
|
3466
|
-
r.concat rt.map { |s| "\t" << s }
|
3615
|
+
r.concat rt.map { |s| CRenderString.new << "\t" << s }
|
3467
3616
|
}
|
3468
3617
|
r.last << ' }'
|
3469
3618
|
[r, dep]
|
3470
3619
|
end
|
3471
3620
|
end
|
3472
3621
|
class Function
|
3473
|
-
def dump_declarator(decl, scope, r=[
|
3622
|
+
def dump_declarator(decl, scope, r=[CRenderString.new], dep=[])
|
3474
3623
|
decl.last << '()' if decl.last.empty?
|
3475
3624
|
decl.last << '('
|
3476
3625
|
if args
|
@@ -3489,12 +3638,12 @@ EOH
|
|
3489
3638
|
@type.dump_declarator(decl, scope, r, dep)
|
3490
3639
|
end
|
3491
3640
|
|
3492
|
-
def dump_initializer(init, scope, r=[
|
3493
|
-
Statement.dump(init, scope, r <<
|
3641
|
+
def dump_initializer(init, scope, r=[CRenderString.new], dep=[])
|
3642
|
+
Statement.dump(init, scope, r << CRenderString.new, dep)
|
3494
3643
|
end
|
3495
3644
|
end
|
3496
3645
|
class BaseType
|
3497
|
-
def dump(scope, r=[
|
3646
|
+
def dump(scope, r=[CRenderString.new], dep=[])
|
3498
3647
|
r.last << @qualifier.map { |q| q.to_s << ' ' }.join if qualifier
|
3499
3648
|
r.last << @specifier.to_s << ' ' if specifier and @name != :ptr
|
3500
3649
|
r.last << case @name
|
@@ -3507,27 +3656,27 @@ EOH
|
|
3507
3656
|
end
|
3508
3657
|
end
|
3509
3658
|
class TypeDef
|
3510
|
-
def dump(scope, r=[
|
3659
|
+
def dump(scope, r=[CRenderString.new], dep=[])
|
3511
3660
|
r.last << @qualifier.map { |q| q.to_s << ' ' }.join if qualifier
|
3512
3661
|
r.last << @name
|
3513
3662
|
dep |= [scope.symbol_ancestors[@name]]
|
3514
3663
|
[r, dep]
|
3515
3664
|
end
|
3516
3665
|
|
3517
|
-
def dump_def(scope, r=[
|
3666
|
+
def dump_def(scope, r=[CRenderString.new], dep=[])
|
3518
3667
|
r.last << 'typedef '
|
3519
3668
|
r.last << dump_attributes_pre
|
3520
3669
|
r, dep = @type.base.dump(scope, r, dep)
|
3521
3670
|
r.last << ' '
|
3522
|
-
@type.dump_declarator([(name ? @name.dup : '') << dump_attributes], scope, r, dep)
|
3671
|
+
@type.dump_declarator([CRenderString.new(name ? @name.dup : '') << dump_attributes], scope, r, dep)
|
3523
3672
|
end
|
3524
3673
|
|
3525
|
-
def dump_initializer(init, scope, r=[
|
3674
|
+
def dump_initializer(init, scope, r=[CRenderString.new], dep=[])
|
3526
3675
|
@type.dump_initializer(init, scope, r, dep)
|
3527
3676
|
end
|
3528
3677
|
end
|
3529
3678
|
class Union
|
3530
|
-
def dump(scope, r=[
|
3679
|
+
def dump(scope, r=[CRenderString.new], dep=[])
|
3531
3680
|
if name
|
3532
3681
|
r.last << @qualifier.map { |q| q.to_s << ' ' }.join if qualifier
|
3533
3682
|
r.last << self.class.name.downcase[/(?:.*::)?(.*)/, 1] << ' ' << @name
|
@@ -3538,26 +3687,26 @@ EOH
|
|
3538
3687
|
end
|
3539
3688
|
end
|
3540
3689
|
|
3541
|
-
def dump_def(scope, r=[
|
3542
|
-
r <<
|
3690
|
+
def dump_def(scope, r=[CRenderString.new], dep=[])
|
3691
|
+
r << CRenderString.new
|
3543
3692
|
r.last << @qualifier.map { |q| q.to_s << ' ' }.join if qualifier
|
3544
3693
|
r.last << self.class.name.downcase[/(?:.*::)?(.*)/, 1]
|
3545
3694
|
r.last << ' ' << @name if name
|
3546
3695
|
if members
|
3547
3696
|
r.last << ' {'
|
3548
3697
|
@members.each_with_index { |m,i|
|
3549
|
-
tr, dep = m.dump_def(scope, [
|
3698
|
+
tr, dep = m.dump_def(scope, [CRenderString.new], dep)
|
3550
3699
|
tr.last << ':' << @bits[i].to_s if bits and @bits[i]
|
3551
3700
|
tr.last << ';'
|
3552
|
-
r.concat tr.map { |s| "\t" << s }
|
3701
|
+
r.concat tr.map { |s| CRenderString.new << "\t" << s }
|
3553
3702
|
}
|
3554
|
-
r << '}'
|
3703
|
+
r << CRenderString.new('}')
|
3555
3704
|
end
|
3556
3705
|
r.last << dump_attributes
|
3557
3706
|
[r, dep]
|
3558
3707
|
end
|
3559
3708
|
|
3560
|
-
def dump_initializer(init, scope, r=[
|
3709
|
+
def dump_initializer(init, scope, r=[CRenderString.new], dep=[])
|
3561
3710
|
return super(init, scope, r, dep) if not init.kind_of? ::Array
|
3562
3711
|
r.last << '{ '
|
3563
3712
|
showname = false
|
@@ -3567,21 +3716,21 @@ EOH
|
|
3567
3716
|
next
|
3568
3717
|
end
|
3569
3718
|
r.last << ', ' if r.last[-2, 2] != '{ '
|
3570
|
-
rt = [
|
3719
|
+
rt = [CRenderString.new]
|
3571
3720
|
if showname
|
3572
3721
|
showname = false
|
3573
3722
|
rt << ".#{m.name} = "
|
3574
3723
|
end
|
3575
3724
|
rt, dep = m.type.dump_initializer(i, scope, rt, dep)
|
3576
3725
|
r.last << rt.shift
|
3577
|
-
r.concat rt.map { |s| "\t" << s }
|
3726
|
+
r.concat rt.map { |s| CRenderString.new << "\t" << s }
|
3578
3727
|
}
|
3579
3728
|
r.last << ' }'
|
3580
3729
|
[r, dep]
|
3581
3730
|
end
|
3582
3731
|
end
|
3583
3732
|
class Struct
|
3584
|
-
def dump_def(scope, r=[
|
3733
|
+
def dump_def(scope, r=[CRenderString.new], dep=[])
|
3585
3734
|
if pack
|
3586
3735
|
r, dep = super(scope, r, dep)
|
3587
3736
|
r.last <<
|
@@ -3595,7 +3744,7 @@ EOH
|
|
3595
3744
|
end
|
3596
3745
|
end
|
3597
3746
|
class Enum
|
3598
|
-
def dump(scope, r=[
|
3747
|
+
def dump(scope, r=[CRenderString.new], dep=[])
|
3599
3748
|
if name
|
3600
3749
|
r.last << @qualifier.map { |q| q.to_s << ' ' }.join if qualifier
|
3601
3750
|
r.last << 'enum ' << @name
|
@@ -3606,7 +3755,7 @@ EOH
|
|
3606
3755
|
end
|
3607
3756
|
end
|
3608
3757
|
|
3609
|
-
def dump_def(scope, r=[
|
3758
|
+
def dump_def(scope, r=[CRenderString.new], dep=[])
|
3610
3759
|
r.last << @qualifier.map { |q| q.to_s << ' ' }.join if qualifier
|
3611
3760
|
r.last << 'enum'
|
3612
3761
|
r.last << ' ' << @name if name
|
@@ -3626,7 +3775,7 @@ EOH
|
|
3626
3775
|
[r, dep]
|
3627
3776
|
end
|
3628
3777
|
|
3629
|
-
def dump_initializer(init, scope, r=[
|
3778
|
+
def dump_initializer(init, scope, r=[CRenderString.new], dep=[])
|
3630
3779
|
if members and (
|
3631
3780
|
k = @members.index(init) or
|
3632
3781
|
(init.kind_of? CExpression and not init.op and k = @members.index(init.rexpr))
|
@@ -3639,14 +3788,14 @@ EOH
|
|
3639
3788
|
end
|
3640
3789
|
end
|
3641
3790
|
class If
|
3642
|
-
def dump(scope, r=[
|
3643
|
-
r.last << 'if ('
|
3791
|
+
def dump(scope, r=[CRenderString.new], dep=[])
|
3792
|
+
r.last << CRenderString.new(self, 'if (')
|
3644
3793
|
r, dep = CExpression.dump(@test, scope, r, dep)
|
3645
3794
|
r.last << ')'
|
3646
3795
|
r, dep = Statement.dump(@bthen, scope, r, dep)
|
3647
3796
|
if belse
|
3648
|
-
@bthen.kind_of?(Block) ? (r.last << ' else') : (r << 'else')
|
3649
|
-
if @belse.kind_of?
|
3797
|
+
@bthen.kind_of?(Block) ? (r.last << CRenderString.new(' else')) : (r << CRenderString.new(self, 'else'))
|
3798
|
+
if @belse.kind_of?(If)
|
3650
3799
|
# skip indent
|
3651
3800
|
r.last << ' '
|
3652
3801
|
r, dep = @belse.dump(scope, r, dep)
|
@@ -3658,9 +3807,9 @@ EOH
|
|
3658
3807
|
end
|
3659
3808
|
end
|
3660
3809
|
class For
|
3661
|
-
def dump(scope, r=[
|
3662
|
-
r.last << 'for ('
|
3663
|
-
if @init.kind_of?
|
3810
|
+
def dump(scope, r=[CRenderString.new], dep=[])
|
3811
|
+
r.last << CRenderString.new(self, 'for (')
|
3812
|
+
if @init.kind_of?(Block)
|
3664
3813
|
scope = @init
|
3665
3814
|
skiptype = false
|
3666
3815
|
@init.symbol.each_value { |s|
|
@@ -3684,56 +3833,57 @@ EOH
|
|
3684
3833
|
end
|
3685
3834
|
end
|
3686
3835
|
class While
|
3687
|
-
def dump(scope, r=[
|
3688
|
-
r.last << 'while ('
|
3836
|
+
def dump(scope, r=[CRenderString.new], dep=[])
|
3837
|
+
r.last << CRenderString.new(self, 'while (')
|
3689
3838
|
r, dep = CExpression.dump(@test, scope, r, dep)
|
3690
3839
|
r.last << ')'
|
3691
3840
|
Statement.dump(@body, scope, r, dep)
|
3692
3841
|
end
|
3693
3842
|
end
|
3694
3843
|
class DoWhile
|
3695
|
-
def dump(scope, r=[
|
3696
|
-
r.last << 'do'
|
3844
|
+
def dump(scope, r=[CRenderString.new], dep=[])
|
3845
|
+
r.last << CRenderString.new(self, 'do')
|
3697
3846
|
r, dep = Statement.dump(@body, scope, r, dep)
|
3698
|
-
|
3847
|
+
r << CRenderString.new if not @body.kind_of?(Block)
|
3848
|
+
r.last << CRenderString.new(self, ' while (')
|
3699
3849
|
r, dep = CExpression.dump(@test, scope, r, dep)
|
3700
3850
|
r.last << ');'
|
3701
3851
|
[r, dep]
|
3702
3852
|
end
|
3703
3853
|
end
|
3704
3854
|
class Switch
|
3705
|
-
def dump(scope, r=[
|
3706
|
-
r.last << 'switch ('
|
3855
|
+
def dump(scope, r=[CRenderString.new], dep=[])
|
3856
|
+
r.last << CRenderString.new(self, 'switch (')
|
3707
3857
|
r, dep = CExpression.dump(@test, scope, r, dep)
|
3708
3858
|
r.last << ')'
|
3709
|
-
r.last << ' {' if @body.kind_of?
|
3710
|
-
tr, dep = @body.dump(scope, [
|
3859
|
+
r.last << ' {' if @body.kind_of?(Block)
|
3860
|
+
tr, dep = @body.dump(scope, [CRenderString.new], dep)
|
3711
3861
|
r.concat tr.map { |s| Case.dump_indent(s, true) }
|
3712
|
-
r << '}' if @body.kind_of? Block
|
3862
|
+
r << CRenderString.new('}') if @body.kind_of? Block
|
3713
3863
|
[r, dep]
|
3714
3864
|
end
|
3715
3865
|
end
|
3716
3866
|
class Continue
|
3717
|
-
def dump(scope, r=[
|
3718
|
-
r.last << 'continue;'
|
3867
|
+
def dump(scope, r=[CRenderString.new], dep=[])
|
3868
|
+
r.last << CRenderString.new(self, 'continue;')
|
3719
3869
|
[r, dep]
|
3720
3870
|
end
|
3721
3871
|
end
|
3722
3872
|
class Break
|
3723
|
-
def dump(scope, r=[
|
3724
|
-
r.last << 'break;'
|
3873
|
+
def dump(scope, r=[CRenderString.new], dep=[])
|
3874
|
+
r.last << CRenderString.new(self, 'break;')
|
3725
3875
|
[r, dep]
|
3726
3876
|
end
|
3727
3877
|
end
|
3728
3878
|
class Goto
|
3729
|
-
def dump(scope, r=[
|
3730
|
-
r.last << "goto #@target;"
|
3879
|
+
def dump(scope, r=[CRenderString.new], dep=[])
|
3880
|
+
r.last << CRenderString.new(self, "goto #@target;")
|
3731
3881
|
[r, dep]
|
3732
3882
|
end
|
3733
3883
|
end
|
3734
3884
|
class Return
|
3735
|
-
def dump(scope, r=[
|
3736
|
-
r.last << 'return '
|
3885
|
+
def dump(scope, r=[CRenderString.new], dep=[])
|
3886
|
+
r.last << CRenderString.new(self, 'return ')
|
3737
3887
|
r, dep = CExpression.dump(@value, scope, r, dep)
|
3738
3888
|
r.last.chop! if r.last[-1] == ?\ # the space character
|
3739
3889
|
r.last << ';'
|
@@ -3741,12 +3891,12 @@ EOH
|
|
3741
3891
|
end
|
3742
3892
|
end
|
3743
3893
|
class Case
|
3744
|
-
def dump(scope, r=[
|
3894
|
+
def dump(scope, r=[CRenderString.new], dep=[])
|
3745
3895
|
case @expr
|
3746
3896
|
when 'default'
|
3747
3897
|
r.last << @expr
|
3748
3898
|
else
|
3749
|
-
r.last << 'case '
|
3899
|
+
r.last << CRenderString.new(self, 'case ')
|
3750
3900
|
r, dep = CExpression.dump(@expr, scope, r, dep)
|
3751
3901
|
if exprup
|
3752
3902
|
r.last << ' ... '
|
@@ -3759,35 +3909,35 @@ EOH
|
|
3759
3909
|
|
3760
3910
|
def self.dump_indent(s, short=false)
|
3761
3911
|
case s
|
3762
|
-
when /^(case|default)\W/; (short ? ' ' : "\t") << s
|
3763
|
-
when /^\s+(case|default)\W/; "\t" << s
|
3912
|
+
when /^(case|default)\W/; CRenderString.new(short ? ' ' : "\t") << s
|
3913
|
+
when /^\s+(case|default)\W/; CRenderString.new("\t") << s
|
3764
3914
|
when /:$/; s
|
3765
|
-
else "\t" << s
|
3915
|
+
else CRenderString.new("\t") << s
|
3766
3916
|
end
|
3767
3917
|
end
|
3768
3918
|
end
|
3769
3919
|
class Label
|
3770
|
-
def dump(scope, r=[
|
3771
|
-
r.last << @name << ':'
|
3920
|
+
def dump(scope, r=[CRenderString.new], dep=[])
|
3921
|
+
r.last << CRenderString.new(self, @name) << ':'
|
3772
3922
|
dump_inner(scope, r, dep)
|
3773
3923
|
end
|
3774
|
-
def dump_inner(scope, r=[
|
3924
|
+
def dump_inner(scope, r=[CRenderString.new], dep=[])
|
3775
3925
|
if not @statement; [r, dep]
|
3776
|
-
elsif @statement.kind_of?
|
3777
|
-
else @statement.dump(scope, r <<
|
3926
|
+
elsif @statement.kind_of?(Block); Statement.dump(@statement, scope, r, dep)
|
3927
|
+
else @statement.dump(scope, r << CRenderString.new, dep)
|
3778
3928
|
end
|
3779
3929
|
end
|
3780
3930
|
end
|
3781
3931
|
class Asm
|
3782
|
-
def dump(scope, r=[
|
3783
|
-
r.last << 'asm '
|
3932
|
+
def dump(scope, r=[CRenderString.new], dep=[])
|
3933
|
+
r.last << CRenderString.new(self, 'asm ')
|
3784
3934
|
r.last << 'volatile ' if @volatile
|
3785
3935
|
r.last << '('
|
3786
|
-
r.last << @body
|
3936
|
+
r.last << CRenderString.new(self, CExpression.string_inspect(@body))
|
3787
3937
|
if @output or @input or @clobber
|
3788
3938
|
if @output and @output != []
|
3789
3939
|
# TODO
|
3790
|
-
r << ': /* todo */'
|
3940
|
+
r << CRenderString.new(': /* todo */')
|
3791
3941
|
elsif (@input and @input != []) or (@clobber and @clobber != [])
|
3792
3942
|
r.last << ' :'
|
3793
3943
|
end
|
@@ -3795,51 +3945,60 @@ EOH
|
|
3795
3945
|
if @input or @clobber
|
3796
3946
|
if @input and @input != []
|
3797
3947
|
# TODO
|
3798
|
-
r << ': /* todo */'
|
3948
|
+
r << CRenderString.new(': /* todo */')
|
3799
3949
|
elsif @clobber and @clobber != []
|
3800
3950
|
r.last << ' :'
|
3801
3951
|
end
|
3802
3952
|
end
|
3803
3953
|
if @clobber and @clobber != []
|
3804
|
-
r << (': ' << @clobber.map { |c| c
|
3954
|
+
r << (CRenderString.new(': ') << @clobber.map { |c| CExpression.string_inspect(c) }.join(', '))
|
3805
3955
|
end
|
3806
3956
|
r.last << ');'
|
3807
3957
|
[r, dep]
|
3808
3958
|
end
|
3809
3959
|
end
|
3810
3960
|
class CExpression
|
3811
|
-
def self.
|
3812
|
-
|
3813
|
-
|
3814
|
-
case
|
3815
|
-
when
|
3816
|
-
|
3961
|
+
def self.string_inspect(s)
|
3962
|
+
# keep all ascii printable except \ and "
|
3963
|
+
'"' + s.gsub(/[^ !\x23-\x5b\x5d-\x7e]/) { |o|
|
3964
|
+
case hex = o.unpack('H*').first.downcase
|
3965
|
+
when '00'; '\\0'
|
3966
|
+
when '0a'; '\\n'
|
3967
|
+
when '0d'; '\\r'
|
3968
|
+
when '1b'; '\\e'
|
3969
|
+
when '22'; '\\"'
|
3970
|
+
when '5c'; '\\\\'
|
3971
|
+
else "\\x#{hex}"
|
3817
3972
|
end
|
3818
|
-
|
3819
|
-
|
3973
|
+
} + '"'
|
3974
|
+
end
|
3975
|
+
|
3976
|
+
def self.dump(e, scope, r=[CRenderString.new], dep=[], brace = false)
|
3820
3977
|
r, dep = \
|
3821
3978
|
case e
|
3822
3979
|
when ::Numeric; r.last << e.to_s ; [r, dep]
|
3823
|
-
when ::String; r.last << e
|
3980
|
+
when ::String; r.last << string_inspect(e) ; [r, dep]
|
3824
3981
|
when CExpression; e.dump_inner(scope, r, dep, brace)
|
3825
3982
|
when Variable; e.dump(scope, r, dep)
|
3826
3983
|
when nil; [r, dep]
|
3827
3984
|
else raise 'wtf?' + e.inspect
|
3828
3985
|
end
|
3829
|
-
if $DEBUG
|
3830
|
-
r.last << ')'
|
3831
|
-
end
|
3832
3986
|
[r, dep]
|
3833
3987
|
end
|
3834
3988
|
|
3835
|
-
def dump(scope, r=[
|
3989
|
+
def dump(scope, r=[CRenderString.new], dep=[])
|
3836
3990
|
r, dep = dump_inner(scope, r, dep)
|
3837
|
-
r.last << ';'
|
3991
|
+
r.last << CRenderString.new(self, ';')
|
3838
3992
|
[r, dep]
|
3839
3993
|
end
|
3840
3994
|
|
3841
|
-
def dump_inner(scope, r=[
|
3842
|
-
r.last <<
|
3995
|
+
def dump_inner(scope, r=[CRenderString.new], dep=[], brace = false)
|
3996
|
+
r.last << CRenderString.new(self)
|
3997
|
+
if misc and misc[:custom_display]
|
3998
|
+
r.last << misc[:custom_display]
|
3999
|
+
return [r, dep]
|
4000
|
+
end
|
4001
|
+
r.last << '(' if brace and @op != :'->' and @op != :'.' and @op != :'[]' and (@op or @rexpr.kind_of?(CExpression))
|
3843
4002
|
if not @lexpr
|
3844
4003
|
if not @op
|
3845
4004
|
case @rexpr
|
@@ -3855,7 +4014,7 @@ EOH
|
|
3855
4014
|
else
|
3856
4015
|
r.last << re.to_s
|
3857
4016
|
end
|
3858
|
-
if @type.kind_of?
|
4017
|
+
if @type.kind_of?(BaseType)
|
3859
4018
|
r.last << 'U' if @type.specifier == :unsigned
|
3860
4019
|
case @type.name
|
3861
4020
|
when :longlong, :__int64; r.last << 'LL'
|
@@ -3864,8 +4023,8 @@ EOH
|
|
3864
4023
|
end
|
3865
4024
|
end
|
3866
4025
|
when ::String
|
3867
|
-
r.last << 'L' if @type.kind_of?
|
3868
|
-
r.last << @rexpr
|
4026
|
+
r.last << 'L' if @type.kind_of?(Pointer) and @type.type.kind_of?(BaseType) and @type.type.name == :short
|
4027
|
+
r.last << CExpression.string_inspect(@rexpr)
|
3869
4028
|
when CExpression # cast
|
3870
4029
|
r, dep = @type.dump_cast(scope, r, dep)
|
3871
4030
|
r, dep = CExpression.dump(@rexpr, scope, r, dep, true)
|
@@ -3877,11 +4036,11 @@ EOH
|
|
3877
4036
|
r.last << ' )'
|
3878
4037
|
when Label
|
3879
4038
|
r.last << '&&' << @rexpr.name
|
3880
|
-
else raise "wtf? #{inspect}"
|
4039
|
+
else raise "(wtf? #{inspect})"
|
3881
4040
|
end
|
3882
4041
|
else
|
3883
4042
|
r.last << @op.to_s
|
3884
|
-
r, dep = CExpression.dump(@rexpr, scope, r, dep, (@rexpr.kind_of?
|
4043
|
+
r, dep = CExpression.dump(@rexpr, scope, r, dep, (@rexpr.kind_of?(C::CExpression) and @rexpr.lexpr))
|
3885
4044
|
end
|
3886
4045
|
elsif not @rexpr
|
3887
4046
|
r, dep = CExpression.dump(@lexpr, scope, r, dep)
|
@@ -3890,16 +4049,16 @@ EOH
|
|
3890
4049
|
case @op
|
3891
4050
|
when :'->', :'.'
|
3892
4051
|
r, dep = CExpression.dump(@lexpr, scope, r, dep, true)
|
3893
|
-
r.last << @op.to_s << @rexpr
|
4052
|
+
r.last << CRenderString.new(self, @op.to_s) << @rexpr
|
3894
4053
|
when :'[]'
|
3895
4054
|
r, dep = CExpression.dump(@lexpr, scope, r, dep, true)
|
3896
4055
|
r.last << '['
|
3897
|
-
l = lexpr if lexpr.kind_of?
|
3898
|
-
l = lexpr.lexpr.type.untypedef.findmember(lexpr.rexpr) if lexpr.kind_of?
|
3899
|
-
l = lexpr.lexpr.type.pointed.untypedef.findmember(lexpr.rexpr) if lexpr.kind_of?
|
4056
|
+
l = lexpr if lexpr.kind_of?(Variable)
|
4057
|
+
l = lexpr.lexpr.type.untypedef.findmember(lexpr.rexpr) if lexpr.kind_of?(CExpression) and lexpr.op == :'.'
|
4058
|
+
l = lexpr.lexpr.type.pointed.untypedef.findmember(lexpr.rexpr) if lexpr.kind_of?(CExpression) and lexpr.op == :'->'
|
3900
4059
|
# honor __attribute__((indexenum(enumname)))
|
3901
|
-
if l and l.attributes and rexpr.kind_of?
|
3902
|
-
|
4060
|
+
if l and l.attributes and rexpr.kind_of?(CExpression) and not rexpr.op and rexpr.rexpr.kind_of?(::Integer) and
|
4061
|
+
n = l.has_attribute_var('indexenum') and enum = scope.struct_ancestors[n] and i = enum.members.index(rexpr.rexpr)
|
3903
4062
|
r.last << i
|
3904
4063
|
dep |= [enum]
|
3905
4064
|
else
|
@@ -3911,22 +4070,22 @@ EOH
|
|
3911
4070
|
r.last << '('
|
3912
4071
|
@rexpr.each { |arg|
|
3913
4072
|
r.last << ', ' if r.last[-1] != ?(
|
3914
|
-
r, dep = CExpression.dump(arg, scope, r, dep)
|
4073
|
+
r, dep = CExpression.dump(arg, scope, r, dep, (arg.kind_of?(CExpression) and arg.op == :','))
|
3915
4074
|
}
|
3916
4075
|
r.last << ')'
|
3917
4076
|
when :'?:'
|
3918
4077
|
r, dep = CExpression.dump(@lexpr, scope, r, dep, true)
|
3919
|
-
r.last << ' ? '
|
4078
|
+
r.last << CRenderString.new(self, ' ? ')
|
3920
4079
|
r, dep = CExpression.dump(@rexpr[0], scope, r, dep, true)
|
3921
|
-
r.last << ' : '
|
4080
|
+
r.last << CRenderString.new(self, ' : ')
|
3922
4081
|
r, dep = CExpression.dump(@rexpr[1], scope, r, dep, true)
|
3923
4082
|
else
|
3924
|
-
r, dep = CExpression.dump(@lexpr, scope, r, dep, (@lexpr.kind_of?
|
3925
|
-
r.last << ' ' << @op.to_s << ' '
|
3926
|
-
r, dep = CExpression.dump(@rexpr, scope, r, dep, (@rexpr.kind_of?
|
4083
|
+
r, dep = CExpression.dump(@lexpr, scope, r, dep, (@lexpr.kind_of?(CExpression) and @lexpr.lexpr and @lexpr.op != @op and @lexpr.op != :funcall))
|
4084
|
+
r.last << CRenderString.new(self, ' ' << @op.to_s << ' ')
|
4085
|
+
r, dep = CExpression.dump(@rexpr, scope, r, dep, (@rexpr.kind_of?(CExpression) and @rexpr.lexpr and @rexpr.op != @op and @rexpr.op != :funcall and @op != :'='))
|
3927
4086
|
end
|
3928
4087
|
end
|
3929
|
-
r.last << ')' if brace and @op != :'->' and @op != :'.' and @op != :'[]' and (@op or @rexpr.kind_of?
|
4088
|
+
r.last << ')' if brace and @op != :'->' and @op != :'.' and @op != :'[]' and (@op or @rexpr.kind_of?(CExpression))
|
3930
4089
|
[r, dep]
|
3931
4090
|
end
|
3932
4091
|
|