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.
Files changed (235) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +1 -0
  3. data/.hgtags +3 -0
  4. data/Gemfile +1 -0
  5. data/INSTALL +61 -0
  6. data/LICENCE +458 -0
  7. data/README +29 -21
  8. data/Rakefile +10 -0
  9. data/TODO +10 -12
  10. data/doc/code_organisation.txt +2 -0
  11. data/doc/core/DynLdr.txt +247 -0
  12. data/doc/core/ExeFormat.txt +43 -0
  13. data/doc/core/Expression.txt +220 -0
  14. data/doc/core/GNUExports.txt +27 -0
  15. data/doc/core/Ia32.txt +236 -0
  16. data/doc/core/SerialStruct.txt +108 -0
  17. data/doc/core/VirtualString.txt +145 -0
  18. data/doc/core/WindowsExports.txt +61 -0
  19. data/doc/core/index.txt +1 -0
  20. data/doc/style.css +6 -3
  21. data/doc/usage/debugger.txt +327 -0
  22. data/doc/usage/index.txt +1 -0
  23. data/doc/use_cases.txt +2 -2
  24. data/metasm.gemspec +22 -0
  25. data/{lib/metasm.rb → metasm.rb} +11 -3
  26. data/{lib/metasm → metasm}/compile_c.rb +13 -7
  27. data/metasm/cpu/arc.rb +8 -0
  28. data/metasm/cpu/arc/decode.rb +425 -0
  29. data/metasm/cpu/arc/main.rb +191 -0
  30. data/metasm/cpu/arc/opcodes.rb +588 -0
  31. data/{lib/metasm → metasm/cpu}/arm.rb +7 -5
  32. data/{lib/metasm → metasm/cpu}/arm/debug.rb +2 -2
  33. data/{lib/metasm → metasm/cpu}/arm/decode.rb +13 -12
  34. data/{lib/metasm → metasm/cpu}/arm/encode.rb +23 -8
  35. data/{lib/metasm → metasm/cpu}/arm/main.rb +0 -3
  36. data/metasm/cpu/arm/opcodes.rb +324 -0
  37. data/{lib/metasm → metasm/cpu}/arm/parse.rb +25 -13
  38. data/{lib/metasm → metasm/cpu}/arm/render.rb +2 -2
  39. data/metasm/cpu/arm64.rb +15 -0
  40. data/metasm/cpu/arm64/debug.rb +38 -0
  41. data/metasm/cpu/arm64/decode.rb +289 -0
  42. data/metasm/cpu/arm64/encode.rb +41 -0
  43. data/metasm/cpu/arm64/main.rb +105 -0
  44. data/metasm/cpu/arm64/opcodes.rb +232 -0
  45. data/metasm/cpu/arm64/parse.rb +20 -0
  46. data/metasm/cpu/arm64/render.rb +95 -0
  47. data/{lib/metasm/ppc.rb → metasm/cpu/bpf.rb} +2 -4
  48. data/metasm/cpu/bpf/decode.rb +142 -0
  49. data/metasm/cpu/bpf/main.rb +60 -0
  50. data/metasm/cpu/bpf/opcodes.rb +81 -0
  51. data/metasm/cpu/bpf/render.rb +41 -0
  52. data/metasm/cpu/cy16.rb +9 -0
  53. data/metasm/cpu/cy16/decode.rb +253 -0
  54. data/metasm/cpu/cy16/main.rb +63 -0
  55. data/metasm/cpu/cy16/opcodes.rb +78 -0
  56. data/metasm/cpu/cy16/render.rb +41 -0
  57. data/metasm/cpu/dalvik.rb +11 -0
  58. data/{lib/metasm → metasm/cpu}/dalvik/decode.rb +35 -13
  59. data/{lib/metasm → metasm/cpu}/dalvik/main.rb +51 -2
  60. data/{lib/metasm → metasm/cpu}/dalvik/opcodes.rb +19 -11
  61. data/metasm/cpu/ia32.rb +17 -0
  62. data/{lib/metasm → metasm/cpu}/ia32/compile_c.rb +5 -7
  63. data/{lib/metasm → metasm/cpu}/ia32/debug.rb +5 -5
  64. data/{lib/metasm → metasm/cpu}/ia32/decode.rb +246 -59
  65. data/{lib/metasm → metasm/cpu}/ia32/decompile.rb +7 -7
  66. data/{lib/metasm → metasm/cpu}/ia32/encode.rb +19 -13
  67. data/{lib/metasm → metasm/cpu}/ia32/main.rb +51 -8
  68. data/metasm/cpu/ia32/opcodes.rb +1424 -0
  69. data/{lib/metasm → metasm/cpu}/ia32/parse.rb +47 -16
  70. data/{lib/metasm → metasm/cpu}/ia32/render.rb +31 -4
  71. data/metasm/cpu/mips.rb +14 -0
  72. data/{lib/metasm → metasm/cpu}/mips/compile_c.rb +1 -1
  73. data/metasm/cpu/mips/debug.rb +42 -0
  74. data/{lib/metasm → metasm/cpu}/mips/decode.rb +46 -16
  75. data/{lib/metasm → metasm/cpu}/mips/encode.rb +4 -3
  76. data/{lib/metasm → metasm/cpu}/mips/main.rb +11 -4
  77. data/{lib/metasm → metasm/cpu}/mips/opcodes.rb +86 -17
  78. data/{lib/metasm → metasm/cpu}/mips/parse.rb +1 -1
  79. data/{lib/metasm → metasm/cpu}/mips/render.rb +1 -1
  80. data/{lib/metasm/dalvik.rb → metasm/cpu/msp430.rb} +1 -1
  81. data/metasm/cpu/msp430/decode.rb +247 -0
  82. data/metasm/cpu/msp430/main.rb +62 -0
  83. data/metasm/cpu/msp430/opcodes.rb +101 -0
  84. data/{lib/metasm → metasm/cpu}/pic16c/decode.rb +6 -7
  85. data/{lib/metasm → metasm/cpu}/pic16c/main.rb +0 -0
  86. data/{lib/metasm → metasm/cpu}/pic16c/opcodes.rb +1 -1
  87. data/{lib/metasm/mips.rb → metasm/cpu/ppc.rb} +4 -4
  88. data/{lib/metasm → metasm/cpu}/ppc/decode.rb +18 -12
  89. data/{lib/metasm → metasm/cpu}/ppc/decompile.rb +3 -3
  90. data/{lib/metasm → metasm/cpu}/ppc/encode.rb +2 -2
  91. data/{lib/metasm → metasm/cpu}/ppc/main.rb +17 -12
  92. data/{lib/metasm → metasm/cpu}/ppc/opcodes.rb +11 -5
  93. data/metasm/cpu/ppc/parse.rb +55 -0
  94. data/metasm/cpu/python.rb +8 -0
  95. data/metasm/cpu/python/decode.rb +136 -0
  96. data/metasm/cpu/python/main.rb +36 -0
  97. data/metasm/cpu/python/opcodes.rb +180 -0
  98. data/{lib/metasm → metasm/cpu}/sh4.rb +1 -1
  99. data/{lib/metasm → metasm/cpu}/sh4/decode.rb +48 -17
  100. data/{lib/metasm → metasm/cpu}/sh4/main.rb +13 -4
  101. data/{lib/metasm → metasm/cpu}/sh4/opcodes.rb +7 -8
  102. data/metasm/cpu/x86_64.rb +15 -0
  103. data/{lib/metasm → metasm/cpu}/x86_64/compile_c.rb +28 -17
  104. data/{lib/metasm → metasm/cpu}/x86_64/debug.rb +4 -4
  105. data/{lib/metasm → metasm/cpu}/x86_64/decode.rb +57 -15
  106. data/{lib/metasm → metasm/cpu}/x86_64/encode.rb +55 -26
  107. data/{lib/metasm → metasm/cpu}/x86_64/main.rb +14 -6
  108. data/metasm/cpu/x86_64/opcodes.rb +136 -0
  109. data/{lib/metasm → metasm/cpu}/x86_64/parse.rb +10 -2
  110. data/metasm/cpu/x86_64/render.rb +35 -0
  111. data/metasm/cpu/z80.rb +9 -0
  112. data/metasm/cpu/z80/decode.rb +313 -0
  113. data/metasm/cpu/z80/main.rb +67 -0
  114. data/metasm/cpu/z80/opcodes.rb +224 -0
  115. data/metasm/cpu/z80/render.rb +59 -0
  116. data/{lib/metasm/os/main.rb → metasm/debug.rb} +160 -401
  117. data/{lib/metasm → metasm}/decode.rb +35 -4
  118. data/{lib/metasm → metasm}/decompile.rb +15 -16
  119. data/{lib/metasm → metasm}/disassemble.rb +201 -45
  120. data/{lib/metasm → metasm}/disassemble_api.rb +651 -87
  121. data/{lib/metasm → metasm}/dynldr.rb +220 -133
  122. data/{lib/metasm → metasm}/encode.rb +10 -1
  123. data/{lib/metasm → metasm}/exe_format/a_out.rb +9 -6
  124. data/{lib/metasm → metasm}/exe_format/autoexe.rb +1 -0
  125. data/{lib/metasm → metasm}/exe_format/bflt.rb +57 -27
  126. data/{lib/metasm → metasm}/exe_format/coff.rb +11 -3
  127. data/{lib/metasm → metasm}/exe_format/coff_decode.rb +53 -20
  128. data/{lib/metasm → metasm}/exe_format/coff_encode.rb +11 -13
  129. data/{lib/metasm → metasm}/exe_format/dex.rb +13 -5
  130. data/{lib/metasm → metasm}/exe_format/dol.rb +1 -0
  131. data/{lib/metasm → metasm}/exe_format/elf.rb +93 -57
  132. data/{lib/metasm → metasm}/exe_format/elf_decode.rb +143 -34
  133. data/{lib/metasm → metasm}/exe_format/elf_encode.rb +122 -31
  134. data/metasm/exe_format/gb.rb +65 -0
  135. data/metasm/exe_format/javaclass.rb +424 -0
  136. data/{lib/metasm → metasm}/exe_format/macho.rb +204 -16
  137. data/{lib/metasm → metasm}/exe_format/main.rb +26 -3
  138. data/{lib/metasm → metasm}/exe_format/mz.rb +1 -0
  139. data/{lib/metasm → metasm}/exe_format/nds.rb +7 -4
  140. data/{lib/metasm → metasm}/exe_format/pe.rb +71 -8
  141. data/metasm/exe_format/pyc.rb +167 -0
  142. data/{lib/metasm → metasm}/exe_format/serialstruct.rb +67 -14
  143. data/{lib/metasm → metasm}/exe_format/shellcode.rb +7 -3
  144. data/metasm/exe_format/shellcode_rwx.rb +114 -0
  145. data/metasm/exe_format/swf.rb +205 -0
  146. data/{lib/metasm → metasm}/exe_format/xcoff.rb +7 -7
  147. data/metasm/exe_format/zip.rb +335 -0
  148. data/metasm/gui.rb +13 -0
  149. data/{lib/metasm → metasm}/gui/cstruct.rb +35 -41
  150. data/{lib/metasm → metasm}/gui/dasm_coverage.rb +11 -11
  151. data/{lib/metasm → metasm}/gui/dasm_decomp.rb +7 -20
  152. data/{lib/metasm → metasm}/gui/dasm_funcgraph.rb +0 -0
  153. data/metasm/gui/dasm_graph.rb +1695 -0
  154. data/{lib/metasm → metasm}/gui/dasm_hex.rb +12 -8
  155. data/{lib/metasm → metasm}/gui/dasm_listing.rb +43 -28
  156. data/{lib/metasm → metasm}/gui/dasm_main.rb +310 -53
  157. data/{lib/metasm → metasm}/gui/dasm_opcodes.rb +5 -19
  158. data/{lib/metasm → metasm}/gui/debug.rb +93 -27
  159. data/{lib/metasm → metasm}/gui/gtk.rb +162 -40
  160. data/{lib/metasm → metasm}/gui/qt.rb +12 -2
  161. data/{lib/metasm → metasm}/gui/win32.rb +179 -42
  162. data/{lib/metasm → metasm}/gui/x11.rb +59 -59
  163. data/{lib/metasm → metasm}/main.rb +389 -264
  164. data/{lib/metasm/os/remote.rb → metasm/os/gdbremote.rb} +146 -54
  165. data/{lib/metasm → metasm}/os/gnu_exports.rb +1 -1
  166. data/{lib/metasm → metasm}/os/linux.rb +628 -151
  167. data/metasm/os/main.rb +330 -0
  168. data/{lib/metasm → metasm}/os/windows.rb +132 -42
  169. data/{lib/metasm → metasm}/os/windows_exports.rb +141 -0
  170. data/{lib/metasm → metasm}/parse.rb +26 -24
  171. data/{lib/metasm → metasm}/parse_c.rb +221 -116
  172. data/{lib/metasm → metasm}/preprocessor.rb +55 -40
  173. data/{lib/metasm → metasm}/render.rb +14 -38
  174. data/misc/hexdump.rb +2 -1
  175. data/misc/lint.rb +58 -0
  176. data/misc/txt2html.rb +9 -7
  177. data/samples/bindiff.rb +3 -4
  178. data/samples/dasm-plugins/bindiff.rb +15 -0
  179. data/samples/dasm-plugins/bookmark.rb +133 -0
  180. data/samples/dasm-plugins/c_constants.rb +57 -0
  181. data/samples/dasm-plugins/colortheme_solarized.rb +125 -0
  182. data/samples/dasm-plugins/cppobj_funcall.rb +60 -0
  183. data/samples/dasm-plugins/dasm_all.rb +70 -0
  184. data/samples/dasm-plugins/demangle_cpp.rb +31 -0
  185. data/samples/dasm-plugins/deobfuscate.rb +251 -0
  186. data/samples/dasm-plugins/dump_text.rb +35 -0
  187. data/samples/dasm-plugins/export_graph_svg.rb +86 -0
  188. data/samples/dasm-plugins/findgadget.rb +75 -0
  189. data/samples/dasm-plugins/hl_opcode.rb +32 -0
  190. data/samples/dasm-plugins/hotfix_gtk_dbg.rb +19 -0
  191. data/samples/dasm-plugins/imm2off.rb +34 -0
  192. data/samples/dasm-plugins/match_libsigs.rb +93 -0
  193. data/samples/dasm-plugins/patch_file.rb +95 -0
  194. data/samples/dasm-plugins/scanfuncstart.rb +36 -0
  195. data/samples/dasm-plugins/scanxrefs.rb +26 -0
  196. data/samples/dasm-plugins/selfmodify.rb +197 -0
  197. data/samples/dasm-plugins/stringsxrefs.rb +28 -0
  198. data/samples/dasmnavig.rb +1 -1
  199. data/samples/dbg-apihook.rb +24 -9
  200. data/samples/dbg-plugins/heapscan.rb +283 -0
  201. data/samples/dbg-plugins/heapscan/compiled_heapscan_lin.c +155 -0
  202. data/samples/dbg-plugins/heapscan/compiled_heapscan_win.c +128 -0
  203. data/samples/dbg-plugins/heapscan/graphheap.rb +616 -0
  204. data/samples/dbg-plugins/heapscan/heapscan.rb +709 -0
  205. data/samples/dbg-plugins/heapscan/winheap.h +174 -0
  206. data/samples/dbg-plugins/heapscan/winheap7.h +307 -0
  207. data/samples/dbg-plugins/trace_func.rb +214 -0
  208. data/samples/disassemble-gui.rb +35 -5
  209. data/samples/disassemble.rb +31 -6
  210. data/samples/dump_upx.rb +24 -12
  211. data/samples/dynamic_ruby.rb +12 -3
  212. data/samples/exeencode.rb +6 -5
  213. data/samples/factorize-headers-peimports.rb +1 -1
  214. data/samples/lindebug.rb +175 -381
  215. data/samples/metasm-shell.rb +1 -2
  216. data/samples/peldr.rb +2 -2
  217. data/tests/all.rb +1 -1
  218. data/tests/arc.rb +26 -0
  219. data/tests/dynldr.rb +22 -4
  220. data/tests/expression.rb +55 -0
  221. data/tests/graph_layout.rb +285 -0
  222. data/tests/ia32.rb +79 -26
  223. data/tests/mips.rb +9 -2
  224. data/tests/x86_64.rb +66 -18
  225. metadata +330 -218
  226. data/lib/metasm/arm/opcodes.rb +0 -177
  227. data/lib/metasm/gui.rb +0 -23
  228. data/lib/metasm/gui/dasm_graph.rb +0 -1354
  229. data/lib/metasm/ia32.rb +0 -14
  230. data/lib/metasm/ia32/opcodes.rb +0 -873
  231. data/lib/metasm/ppc/parse.rb +0 -52
  232. data/lib/metasm/x86_64.rb +0 -12
  233. data/lib/metasm/x86_64/opcodes.rb +0 -118
  234. data/samples/gdbclient.rb +0 -583
  235. data/samples/rubstop.rb +0 -399
@@ -9,31 +9,31 @@ module Metasm
9
9
  module Gui
10
10
  class XGui < DynLdr
11
11
  new_api_c <<EOS, 'libX11.so'
12
- #define KeyPressMask (1L<<0)
13
- #define KeyReleaseMask (1L<<1)
14
- #define ButtonPressMask (1L<<2)
15
- #define ButtonReleaseMask (1L<<3)
16
- #define EnterWindowMask (1L<<4)
17
- #define LeaveWindowMask (1L<<5)
18
- #define PointerMotionMask (1L<<6)
19
- #define PointerMotionHintMask (1L<<7)
20
- #define Button1MotionMask (1L<<8)
21
- #define Button2MotionMask (1L<<9)
22
- #define Button3MotionMask (1L<<10)
23
- #define Button4MotionMask (1L<<11)
24
- #define Button5MotionMask (1L<<12)
25
- #define ButtonMotionMask (1L<<13)
12
+ #define KeyPressMask (1L<<0)
13
+ #define KeyReleaseMask (1L<<1)
14
+ #define ButtonPressMask (1L<<2)
15
+ #define ButtonReleaseMask (1L<<3)
16
+ #define EnterWindowMask (1L<<4)
17
+ #define LeaveWindowMask (1L<<5)
18
+ #define PointerMotionMask (1L<<6)
19
+ #define PointerMotionHintMask (1L<<7)
20
+ #define Button1MotionMask (1L<<8)
21
+ #define Button2MotionMask (1L<<9)
22
+ #define Button3MotionMask (1L<<10)
23
+ #define Button4MotionMask (1L<<11)
24
+ #define Button5MotionMask (1L<<12)
25
+ #define ButtonMotionMask (1L<<13)
26
26
  #define KeymapStateMask (1L<<14)
27
- #define ExposureMask (1L<<15)
28
- #define VisibilityChangeMask (1L<<16)
29
- #define StructureNotifyMask (1L<<17)
30
- #define ResizeRedirectMask (1L<<18)
31
- #define SubstructureNotifyMask (1L<<19)
32
- #define SubstructureRedirectMask (1L<<20)
33
- #define FocusChangeMask (1L<<21)
34
- #define PropertyChangeMask (1L<<22)
35
- #define ColormapChangeMask (1L<<23)
36
- #define OwnerGrabButtonMask (1L<<24)
27
+ #define ExposureMask (1L<<15)
28
+ #define VisibilityChangeMask (1L<<16)
29
+ #define StructureNotifyMask (1L<<17)
30
+ #define ResizeRedirectMask (1L<<18)
31
+ #define SubstructureNotifyMask (1L<<19)
32
+ #define SubstructureRedirectMask (1L<<20)
33
+ #define FocusChangeMask (1L<<21)
34
+ #define PropertyChangeMask (1L<<22)
35
+ #define ColormapChangeMask (1L<<23)
36
+ #define OwnerGrabButtonMask (1L<<24)
37
37
 
38
38
  #define KeyPress 2
39
39
  #define KeyRelease 3
@@ -84,7 +84,7 @@ typedef struct _XGC *GC;
84
84
  typedef XID Pixmap;
85
85
  typedef XID Window;
86
86
 
87
- typedef
87
+ typedef
88
88
  struct {
89
89
  int type;
90
90
  unsigned long serial;
@@ -92,7 +92,7 @@ struct {
92
92
  Display *display;
93
93
  Window window;
94
94
  } XAnyEvent;
95
- typedef
95
+ typedef
96
96
  struct {
97
97
  int type;
98
98
  unsigned long serial;
@@ -110,7 +110,7 @@ struct {
110
110
  unsigned int button;
111
111
  int same_screen;
112
112
  } XButtonEvent;
113
- typedef
113
+ typedef
114
114
  struct {
115
115
  int type;
116
116
  unsigned long serial;
@@ -120,7 +120,7 @@ struct {
120
120
  Window window;
121
121
  int place;
122
122
  } XCirculateEvent;
123
- typedef
123
+ typedef
124
124
  struct {
125
125
  int type;
126
126
  unsigned long serial;
@@ -130,7 +130,7 @@ struct {
130
130
  Window window;
131
131
  int place;
132
132
  } XCirculateRequestEvent;
133
- typedef
133
+ typedef
134
134
  struct {
135
135
  int type;
136
136
  unsigned long serial;
@@ -146,7 +146,7 @@ struct {
146
146
  long l[5];
147
147
  } data;
148
148
  } XClientMessageEvent;
149
- typedef
149
+ typedef
150
150
  struct {
151
151
  int type;
152
152
  unsigned long serial;
@@ -157,7 +157,7 @@ struct {
157
157
  int new;
158
158
  int state;
159
159
  } XColormapEvent;
160
- typedef
160
+ typedef
161
161
  struct {
162
162
  int type;
163
163
  unsigned long serial;
@@ -173,7 +173,7 @@ struct {
173
173
  Window above;
174
174
  int override_redirect;
175
175
  } XConfigureEvent;
176
- typedef
176
+ typedef
177
177
  struct {
178
178
  int type;
179
179
  unsigned long serial;
@@ -190,7 +190,7 @@ struct {
190
190
  int detail;
191
191
  unsigned long value_mask;
192
192
  } XConfigureRequestEvent;
193
- typedef
193
+ typedef
194
194
  struct {
195
195
  int type;
196
196
  unsigned long serial;
@@ -205,7 +205,7 @@ struct {
205
205
  int border_width;
206
206
  int override_redirect;
207
207
  } XCreateWindowEvent;
208
- typedef
208
+ typedef
209
209
  struct {
210
210
  int type;
211
211
  unsigned long serial;
@@ -225,7 +225,7 @@ struct {
225
225
  int focus;
226
226
  unsigned int state;
227
227
  } XCrossingEvent;
228
- typedef
228
+ typedef
229
229
  struct {
230
230
  int type;
231
231
  unsigned long serial;
@@ -234,7 +234,7 @@ struct {
234
234
  Window event;
235
235
  Window window;
236
236
  } XDestroyWindowEvent;
237
- typedef
237
+ typedef
238
238
  struct {
239
239
  int type;
240
240
  Display *display;
@@ -244,7 +244,7 @@ struct {
244
244
  unsigned char request_code;
245
245
  unsigned char minor_code;
246
246
  } XErrorEvent;
247
- typedef
247
+ typedef
248
248
  struct {
249
249
  int type;
250
250
  unsigned long serial;
@@ -257,7 +257,7 @@ struct {
257
257
  int height;
258
258
  int count;
259
259
  } XExposeEvent;
260
- typedef
260
+ typedef
261
261
  struct {
262
262
  int type;
263
263
  unsigned long serial;
@@ -267,7 +267,7 @@ struct {
267
267
  int mode;
268
268
  int detail;
269
269
  } XFocusChangeEvent;
270
- typedef
270
+ typedef
271
271
  struct {
272
272
  int function;
273
273
  unsigned long plane_mask;
@@ -293,7 +293,7 @@ struct {
293
293
  int dash_offset;
294
294
  char dashes;
295
295
  } XGCValues;
296
- typedef
296
+ typedef
297
297
  struct {
298
298
  int type;
299
299
  unsigned long serial;
@@ -302,7 +302,7 @@ struct {
302
302
  int extension;
303
303
  int evtype;
304
304
  } XGenericEvent;
305
- typedef
305
+ typedef
306
306
  struct {
307
307
  int type;
308
308
  unsigned long serial;
@@ -313,7 +313,7 @@ struct {
313
313
  unsigned int cookie;
314
314
  void *data;
315
315
  } XGenericEventCookie;
316
- typedef
316
+ typedef
317
317
  struct {
318
318
  int type;
319
319
  unsigned long serial;
@@ -328,7 +328,7 @@ struct {
328
328
  int major_code;
329
329
  int minor_code;
330
330
  } XGraphicsExposeEvent;
331
- typedef
331
+ typedef
332
332
  struct {
333
333
  int type;
334
334
  unsigned long serial;
@@ -339,7 +339,7 @@ struct {
339
339
  int x;
340
340
  int y;
341
341
  } XGravityEvent;
342
- typedef
342
+ typedef
343
343
  struct {
344
344
  int type;
345
345
  unsigned long serial;
@@ -357,7 +357,7 @@ struct {
357
357
  unsigned int keycode;
358
358
  int same_screen;
359
359
  } XKeyEvent;
360
- typedef
360
+ typedef
361
361
  struct {
362
362
  int type;
363
363
  unsigned long serial;
@@ -366,7 +366,7 @@ struct {
366
366
  Window window;
367
367
  char key_vector[32];
368
368
  } XKeymapEvent;
369
- typedef
369
+ typedef
370
370
  struct {
371
371
  int type;
372
372
  unsigned long serial;
@@ -376,7 +376,7 @@ struct {
376
376
  Window window;
377
377
  int override_redirect;
378
378
  } XMapEvent;
379
- typedef
379
+ typedef
380
380
  struct {
381
381
  int type;
382
382
  unsigned long serial;
@@ -385,7 +385,7 @@ struct {
385
385
  Window parent;
386
386
  Window window;
387
387
  } XMapRequestEvent;
388
- typedef
388
+ typedef
389
389
  struct {
390
390
  int type;
391
391
  unsigned long serial;
@@ -396,7 +396,7 @@ struct {
396
396
  int first_keycode;
397
397
  int count;
398
398
  } XMappingEvent;
399
- typedef
399
+ typedef
400
400
  struct {
401
401
  int type;
402
402
  unsigned long serial;
@@ -414,7 +414,7 @@ struct {
414
414
  char is_hint;
415
415
  int same_screen;
416
416
  } XMotionEvent;
417
- typedef
417
+ typedef
418
418
  struct {
419
419
  int type;
420
420
  unsigned long serial;
@@ -424,7 +424,7 @@ struct {
424
424
  int major_code;
425
425
  int minor_code;
426
426
  } XNoExposeEvent;
427
- typedef
427
+ typedef
428
428
  struct {
429
429
  int type;
430
430
  unsigned long serial;
@@ -435,7 +435,7 @@ struct {
435
435
  Time time;
436
436
  int state;
437
437
  } XPropertyEvent;
438
- typedef
438
+ typedef
439
439
  struct {
440
440
  int type;
441
441
  unsigned long serial;
@@ -448,7 +448,7 @@ struct {
448
448
  int y;
449
449
  int override_redirect;
450
450
  } XReparentEvent;
451
- typedef
451
+ typedef
452
452
  struct {
453
453
  int type;
454
454
  unsigned long serial;
@@ -458,7 +458,7 @@ struct {
458
458
  int width;
459
459
  int height;
460
460
  } XResizeRequestEvent;
461
- typedef
461
+ typedef
462
462
  struct {
463
463
  int type;
464
464
  unsigned long serial;
@@ -468,7 +468,7 @@ struct {
468
468
  Atom selection;
469
469
  Time time;
470
470
  } XSelectionClearEvent;
471
- typedef
471
+ typedef
472
472
  struct {
473
473
  int type;
474
474
  unsigned long serial;
@@ -480,7 +480,7 @@ struct {
480
480
  Atom property;
481
481
  Time time;
482
482
  } XSelectionEvent;
483
- typedef
483
+ typedef
484
484
  struct {
485
485
  int type;
486
486
  unsigned long serial;
@@ -493,7 +493,7 @@ struct {
493
493
  Atom property;
494
494
  Time time;
495
495
  } XSelectionRequestEvent;
496
- typedef
496
+ typedef
497
497
  struct {
498
498
  int type;
499
499
  unsigned long serial;
@@ -503,7 +503,7 @@ struct {
503
503
  Window window;
504
504
  int from_configure;
505
505
  } XUnmapEvent;
506
- typedef
506
+ typedef
507
507
  struct {
508
508
  int type;
509
509
  unsigned long serial;
@@ -579,7 +579,7 @@ EOS
579
579
  def self.test
580
580
  d = xopendisplay(nil)
581
581
  s = xdefaultscreen(d)
582
- cmap = xdefaultcolormap(d, s)
582
+ #cmap = xdefaultcolormap(d, s)
583
583
  w = xcreatesimplewindow(d, xdefaultrootwindow(d), 0, 0, 28, 28, 0, xblackpixel(d, s), xblackpixel(d, s))
584
584
  xstorename(d, w, "lol")
585
585
  gc = xcreategc(d, w, 0, 0)
@@ -23,7 +23,7 @@ class CPU
23
23
  attr_accessor :valid_args, :valid_props, :fields_mask
24
24
  attr_accessor :endianness, :size
25
25
  attr_accessor :generate_PIC
26
-
26
+
27
27
  def opcode_list
28
28
  @opcode_list ||= init_opcode_list
29
29
  end
@@ -32,8 +32,8 @@ class CPU
32
32
  def initialize
33
33
  @fields_mask = {}
34
34
  @fields_shift= {}
35
- @valid_args = []
36
- @valid_props = [:setip, :saveip, :stopexec]
35
+ @valid_args = {}
36
+ @valid_props = { :setip => true, :saveip => true, :stopexec => true }
37
37
  @generate_PIC = true
38
38
  end
39
39
 
@@ -81,6 +81,17 @@ class CPU
81
81
  def shortname
82
82
  self.class.name.sub(/.*::/, '').downcase
83
83
  end
84
+
85
+ # some userinterface wants to hilight a word, return a regexp
86
+ # useful for register aliases
87
+ # the regexp will be enclosed in \b and should not contain captures
88
+ def gui_hilight_word_regexp(word)
89
+ Regexp.escape(word)
90
+ end
91
+
92
+ # returns true if the name is invalid as a label name (eg register name)
93
+ def check_reserved_name(name)
94
+ end
84
95
  end
85
96
 
86
97
  # generic CPU, with no instructions, just size/endianness
@@ -120,6 +131,15 @@ class Opcode
120
131
  def basename
121
132
  @name.sub(/\..*/, '')
122
133
  end
134
+
135
+ def dup
136
+ o = Opcode.new(@name.dup, @bin)
137
+ o.bin = @bin.dup if @bin.kind_of?(::Array)
138
+ o.args = @args.dup
139
+ o.fields = @fields.dup
140
+ o.props = @props.dup
141
+ o
142
+ end
123
143
  end
124
144
 
125
145
  # defines an attribute self.backtrace (array of filename/lineno)
@@ -341,7 +361,7 @@ class Expression < ExpressionType
341
361
  if not op
342
362
  raise ArgumentError, 'invalid Expression[nil]' if not l
343
363
  return l if l.kind_of? Expression
344
- if l.kind_of? ::Numeric and l < 0
364
+ if l.kind_of?(::Numeric) and l < 0
345
365
  r = -l
346
366
  op = :'-'
347
367
  else
@@ -354,9 +374,9 @@ class Expression < ExpressionType
354
374
  end
355
375
  l = nil
356
376
  else
357
- l = self[*l] if l.kind_of? ::Array
377
+ l = self[*l] if l.kind_of?(::Array)
358
378
  end
359
- r = self[*r] if r.kind_of? ::Array
379
+ r = self[*r] if r.kind_of?(::Array)
360
380
  new(op, r, l)
361
381
  end
362
382
 
@@ -364,7 +384,7 @@ class Expression < ExpressionType
364
384
  # returns true if it is, false if it overflows, and nil if cannot be determined (eg unresolved variable)
365
385
  def self.in_range?(val, type)
366
386
  val = val.reduce if val.kind_of? self
367
- return unless val.kind_of? ::Numeric
387
+ return unless val.kind_of?(::Numeric)
368
388
 
369
389
  if INT_MIN[type]
370
390
  val == val.to_i and
@@ -374,8 +394,11 @@ class Expression < ExpressionType
374
394
 
375
395
  # casts an unsigned value to a two-complement signed if the sign bit is set
376
396
  def self.make_signed(val, bitlength)
377
- if val.kind_of? Integer
378
- val = val - (1 << bitlength) if val >> (bitlength - 1) == 1
397
+ case val
398
+ when Integer
399
+ val = val - (1 << bitlength) if val > 0 and val >> (bitlength - 1) == 1
400
+ when Expression
401
+ val = Expression[val, :-, [(1<<bitlength), :*, [[val, :>>, (bitlength-1)], :==, 1]]]
379
402
  end
380
403
  val
381
404
  end
@@ -390,8 +413,10 @@ class Expression < ExpressionType
390
413
  # basic constructor
391
414
  # XXX funny args order, you should use +Expression[]+ instead
392
415
  def initialize(op, rexpr, lexpr)
393
- raise ArgumentError, "Expression: invalid arg order: #{[lexpr, op, rexpr].inspect}" if not op.kind_of? ::Symbol
394
- @op, @lexpr, @rexpr = op, lexpr, rexpr
416
+ raise ArgumentError, "Expression: invalid arg order: #{[lexpr, op, rexpr].inspect}" if not op.kind_of?(::Symbol)
417
+ @op = op
418
+ @lexpr = lexpr
419
+ @rexpr = rexpr
395
420
  end
396
421
 
397
422
  # recursive check of equity using #==
@@ -415,20 +440,21 @@ class Expression < ExpressionType
415
440
  return binding[self].dup
416
441
  end
417
442
 
418
- l, r = @lexpr, @rexpr
443
+ l = @lexpr
444
+ r = @rexpr
419
445
  if l and binding[l]
420
- raise "internal error - bound #{l.inspect}" if l.kind_of? ::Numeric
446
+ raise "internal error - bound #{l.inspect}" if l.kind_of?(::Numeric)
421
447
  l = binding[l]
422
448
  elsif l.kind_of? ExpressionType
423
449
  l = l.bind(binding)
424
450
  end
425
451
  if r and binding[r]
426
- raise "internal error - bound #{r.inspect}" if r.kind_of? ::Numeric
452
+ raise "internal error - bound #{r.inspect}" if r.kind_of?(::Numeric)
427
453
  r = binding[r]
428
454
  elsif r.kind_of? ExpressionType
429
455
  r = r.bind(binding)
430
456
  end
431
- Expression[l, @op, r]
457
+ Expression.new(@op, r, l)
432
458
  end
433
459
 
434
460
  # bind in place (replace self.lexpr/self.rexpr with the binding value)
@@ -492,10 +518,13 @@ class Expression < ExpressionType
492
518
  end
493
519
 
494
520
  v =
495
- if r.kind_of?(::Numeric) and (l == nil or l.kind_of?(::Numeric))
496
- # calculate numerics
497
- if [:'&&', :'||', :'>', :'<', :'>=', :'<=', :'==', :'!='].include?(@op)
498
- # bool expr
521
+ if r.kind_of?(::Numeric) and (not l or l.kind_of?(::Numeric))
522
+ case @op
523
+ when :+; l ? l + r : r
524
+ when :-; l ? l - r : -r
525
+ when :'!'; raise 'internal error' if l ; (r == 0) ? 1 : 0
526
+ when :'~'; raise 'internal error' if l ; ~r
527
+ when :'&&', :'||', :'>', :'<', :'>=', :'<=', :'==', :'!='
499
528
  raise 'internal error' if not l
500
529
  case @op
501
530
  when :'&&'; (l != 0) && (r != 0)
@@ -507,194 +536,18 @@ class Expression < ExpressionType
507
536
  when :'=='; l == r
508
537
  when :'!='; l != r
509
538
  end ? 1 : 0
510
- elsif not l
511
- case @op
512
- when :'!'; (r == 0) ? 1 : 0
513
- when :+; r
514
- when :-; -r
515
- when :~; ~r
516
- end
517
539
  else
518
- # use ruby evaluator
519
540
  l.send(@op, r)
520
541
  end
521
-
522
- elsif @op == :'&&'
523
- if l == 0 # shortcircuit eval
524
- 0
525
- elsif l == 1
526
- Expression[r, :'!=', 0].reduce_rec
527
- elsif r == 0
528
- 0 # XXX l could be a special ExprType with sideeffects ?
529
- end
530
- elsif @op == :'||'
531
- if l.kind_of? ::Numeric and l != 0 # shortcircuit eval
532
- 1
533
- elsif l == 0
534
- Expression[r, :'!=', 0].reduce_rec
535
- elsif r == 0
536
- Expression[l, :'!=', 0].reduce_rec
537
- end
538
- elsif @op == :>> or @op == :<<
539
- if l == 0; 0
540
- elsif r == 0; l
541
- elsif l.kind_of? Expression and l.op == @op
542
- Expression[l.lexpr, @op, [l.rexpr, :+, r]].reduce_rec
543
- # XXX (a >> 1) << 1 != a (lose low bit)
544
- # XXX (a << 1) >> 1 != a (with real cpus, lose high bit)
545
- # (a | b) << i
546
- elsif r.kind_of? Integer and l.kind_of? Expression and [:&, :|, :^].include? l.op
547
- Expression[[l.lexpr, @op, r], l.op, [l.rexpr, @op, r]].reduce_rec
548
- end
549
- elsif @op == :'!'
550
- if r.kind_of? Expression and op = {:'==' => :'!=', :'!=' => :'==', :< => :>=, :> => :<=, :<= => :>, :>= => :<}[r.op]
551
- Expression[r.lexpr, op, r.rexpr].reduce_rec
552
- end
553
- elsif @op == :==
554
- if l == r; 1
555
- elsif r == 0 and l.kind_of? Expression and op = {:'==' => :'!=', :'!=' => :'==', :< => :>=, :> => :<=, :<= => :>, :>= => :<}[l.op]
556
- Expression[l.lexpr, op, l.rexpr].reduce_rec
557
- elsif r == 1 and l.kind_of? Expression and op = {:'==' => :'!=', :'!=' => :'==', :< => :>=, :> => :<=, :<= => :>, :>= => :<}[l.op]
558
- l
559
- elsif r == 0 and l.kind_of? Expression and l.op == :+
560
- if l.rexpr.kind_of? Expression and l.rexpr.op == :- and not l.rexpr.lexpr
561
- Expression[l.lexpr, @op, l.rexpr.rexpr].reduce_rec
562
- elsif l.rexpr.kind_of? ::Integer
563
- Expression[l.lexpr, @op, -l.rexpr].reduce_rec
564
- end
565
- end
566
- elsif @op == :'!='
567
- if l == r; 0
568
- end
569
- elsif @op == :^
570
- if l == :unknown or r == :unknown; :unknown
571
- elsif l == 0; r
572
- elsif r == 0; l
573
- elsif l == r; 0
574
- elsif r == 1 and l.kind_of? Expression and [:'==', :'!=', :<, :>, :<=, :>=].include? l.op
575
- Expression[nil, :'!', l].reduce_rec
576
- elsif l.kind_of?(::Numeric)
577
- if r.kind_of? Expression and r.op == :^
578
- # 1^(x^y) => x^(y^1)
579
- Expression[r.lexpr, :^, [r.rexpr, :^, l]].reduce_rec
580
- else
581
- # 1^a => a^1
582
- Expression[r, :^, l].reduce_rec
583
- end
584
- elsif l.kind_of? Expression and l.op == :^
585
- # (a^b)^c => a^(b^c)
586
- Expression[l.lexpr, :^, [l.rexpr, :^, r]].reduce_rec
587
- elsif r.kind_of? Expression and r.op == :^
588
- if r.rexpr == l
589
- # a^(a^b) => b
590
- r.lexpr
591
- elsif r.lexpr == l
592
- # a^(b^a) => b
593
- r.rexpr
594
- else
595
- # a^(b^(c^(a^d))) => b^(a^(c^(a^d)))
596
- # XXX ugly..
597
- tr = r
598
- found = false
599
- while not found and tr.kind_of?(Expression) and tr.op == :^
600
- found = true if tr.lexpr == l or tr.rexpr == l
601
- tr = tr.rexpr
602
- end
603
- if found
604
- Expression[r.lexpr, :^, [l, :^, r.rexpr]].reduce_rec
605
- end
606
- end
607
- elsif l.kind_of?(Expression) and l.op == :& and l.rexpr.kind_of?(::Integer) and (l.rexpr & (l.rexpr+1)) == 0
608
- if r.kind_of?(::Integer) and r & l.rexpr == r
609
- # (a&0xfff)^12 => (a^12)&0xfff
610
- Expression[[l.lexpr, :^, r], :&, l.rexpr].reduce_rec
611
- elsif r.kind_of?(Expression) and r.op == :& and r.rexpr.kind_of?(::Integer) and r.rexpr == l.rexpr
612
- # (a&0xfff)^(b&0xfff) => (a^b)&0xfff
613
- Expression[[l.lexpr, :^, r.lexpr], :&, l.rexpr].reduce_rec
614
- end
615
- end
616
- elsif @op == :&
617
- if l == 0 or r == 0; 0
618
- elsif r == 1 and l.kind_of?(Expression) and [:'==', :'!=', :<, :>, :<=, :>=].include?(l.op)
619
- l
620
- elsif l == r; l
621
- elsif l.kind_of?(Integer); Expression[r, @op, l].reduce_rec
622
- elsif l.kind_of?(Expression) and l.op == @op; Expression[l.lexpr, @op, [l.rexpr, @op, r]].reduce_rec
623
- elsif l.kind_of?(Expression) and [:|, :^].include?(l.op) and r.kind_of?(Integer) and (l.op == :| or (r & (r+1)) != 0)
624
- # (a ^| b) & i => (a&i ^| b&i)
625
- Expression[[l.lexpr, :&, r], l.op, [l.rexpr, :&, r]].reduce_rec
626
- elsif r.kind_of?(::Integer) and l.kind_of?(Expression) and (r & (r+1)) == 0
627
- # foo & 0xffff
628
- reduce_rec_mod2(l, r)
629
- end
630
- elsif @op == :|
631
- if l == 0; r
632
- elsif r == 0; l
633
- elsif l == -1 or r == -1; -1
634
- elsif l == r; l
635
- elsif l.kind_of? Integer; Expression[r, @op, l].reduce_rec
636
- elsif l.kind_of? Expression and l.op == @op; Expression[l.lexpr, @op, [l.rexpr, @op, r]].reduce_rec
637
- end
638
- elsif @op == :*
639
- if l == 0 or r == 0; 0
640
- elsif l == 1; r
641
- elsif r == 1; l
642
- elsif r.kind_of? Integer; Expression[r, @op, l].reduce_rec
643
- elsif r.kind_of? Expression and r.op == @op; Expression[[l, @op, r.lexpr], @op, r.rexpr].reduce_rec
644
- elsif l.kind_of? Integer and r.kind_of? Expression and r.op == :* and r.lexpr.kind_of? Integer; Expression[l*r.lexpr, :*, r.rexpr].reduce_rec # XXX need & regsize..
645
- elsif l.kind_of? Integer and r.kind_of? Expression and r.op == :+ and r.rexpr.kind_of? Integer; Expression[[l, :*, r.lexpr], :+, l*r.rexpr].reduce_rec
646
- end
647
- elsif @op == :/
648
- if r == 0
649
- elsif r.kind_of? Integer and l.kind_of? Expression and l.op == :+ and l.rexpr.kind_of? Integer and l.rexpr % r == 0
650
- Expression[[l.lexpr, :/, r], :+, l.rexpr/r].reduce_rec
651
- elsif r.kind_of? Integer and l.kind_of? Expression and l.op == :* and l.lexpr % r == 0
652
- Expression[l.lexpr/r, :*, l.rexpr].reduce_rec
653
- end
654
- elsif @op == :-
655
- if l == :unknown or r == :unknown; :unknown
656
- elsif not l and r.kind_of? Expression and (r.op == :- or r.op == :+)
657
- if r.op == :- # no lexpr (reduced)
658
- # -(-x) => x
659
- r.rexpr
660
- else # :+ and lexpr (r is reduced)
661
- # -(a+b) => (-a)+(-b)
662
- Expression[[:-, r.lexpr], :+, [:-, r.rexpr]].reduce_rec
663
- end
664
- elsif l.kind_of? Expression and l.op == :+ and l.lexpr == r
665
- # shortcircuit for a common occurence [citation needed]
666
- # (a+b)-a
667
- l.rexpr
668
- elsif l
669
- # a-b => a+(-b)
670
- Expression[l, :+, [:-, r]].reduce_rec
671
- end
672
- elsif @op == :+
673
- if l == :unknown or r == :unknown; :unknown
674
- elsif not l; r # +x => x
675
- elsif r == 0; l # x+0 => x
676
- elsif l.kind_of?(::Numeric)
677
- if r.kind_of? Expression and r.op == :+
678
- # 1+(x+y) => x+(y+1)
679
- Expression[r.lexpr, :+, [r.rexpr, :+, l]].reduce_rec
680
- else
681
- # 1+a => a+1
682
- Expression[r, :+, l].reduce_rec
683
- end
684
- # (a+b)+foo => a+(b+foo)
685
- elsif l.kind_of? Expression and l.op == @op; Expression[l.lexpr, @op, [l.rexpr, @op, r]].reduce_rec
686
- elsif l.kind_of? Expression and r.kind_of? Expression and l.op == :% and r.op == :% and l.rexpr.kind_of?(::Integer) and l.rexpr == r.rexpr
687
- Expression[[l.lexpr, :+, r.lexpr], :%, l.rexpr].reduce_rec
688
- else
689
- reduce_rec_add(l, r)
690
- end
542
+ elsif rp = @@reduce_op[@op]
543
+ rp[self, l, r]
691
544
  end
692
545
 
693
546
  ret = case v
694
547
  when nil
695
548
  # no dup if no new value
696
549
  (r == :unknown or l == :unknown) ? :unknown :
697
- ((r == @rexpr and l == @lexpr) ? self : Expression[l, @op, r])
550
+ ((r == @rexpr and l == @lexpr) ? self : Expression.new(@op, r, l))
698
551
  when Expression
699
552
  (v.lexpr == :unknown or v.rexpr == :unknown) ? :unknown : v
700
553
  else v
@@ -709,54 +562,248 @@ class Expression < ExpressionType
709
562
  ret
710
563
  end
711
564
 
565
+ @@reduce_op = {
566
+ :+ => lambda { |e, l, r| e.reduce_op_plus(l, r) },
567
+ :- => lambda { |e, l, r| e.reduce_op_minus(l, r) },
568
+ :'&&' => lambda { |e, l, r| e.reduce_op_andand(l, r) },
569
+ :'||' => lambda { |e, l, r| e.reduce_op_oror(l, r) },
570
+ :>> => lambda { |e, l, r| e.reduce_op_shr(l, r) },
571
+ :<< => lambda { |e, l, r| e.reduce_op_shl(l, r) },
572
+ :'!' => lambda { |e, l, r| e.reduce_op_not(l, r) },
573
+ :== => lambda { |e, l, r| e.reduce_op_eql(l, r) },
574
+ :'!=' => lambda { |e, l, r| e.reduce_op_neq(l, r) },
575
+ :^ => lambda { |e, l, r| e.reduce_op_xor(l, r) },
576
+ :& => lambda { |e, l, r| e.reduce_op_and(l, r) },
577
+ :| => lambda { |e, l, r| e.reduce_op_or(l, r) },
578
+ :* => lambda { |e, l, r| e.reduce_op_times(l, r) },
579
+ :/ => lambda { |e, l, r| e.reduce_op_div(l, r) },
580
+ :% => lambda { |e, l, r| e.reduce_op_mod(l, r) },
581
+ }
582
+
583
+
584
+ def self.reduce_op
585
+ @@reduce_op
586
+ end
712
587
 
713
- # a+(b+(c+(-a))) => b+c+0
714
- # a+((-a)+(b+c)) => 0+b+c
715
- def reduce_rec_add(l, r)
716
- if l.kind_of? Expression and l.op == :- and not l.lexpr
717
- neg_l = l.rexpr
588
+ def reduce_op_plus(l, r)
589
+ if not l; r # +x => x
590
+ elsif r == 0; l # x+0 => x
591
+ elsif l == :unknown or r == :unknown; :unknown
592
+ elsif l.kind_of?(::Numeric)
593
+ if r.kind_of? Expression and r.op == :+
594
+ # 1+(x+y) => x+(y+1)
595
+ Expression[r.lexpr, :+, [r.rexpr, :+, l]].reduce_rec
596
+ else
597
+ # 1+a => a+1
598
+ Expression[r, :+, l].reduce_rec
599
+ end
600
+ # (a+b)+foo => a+(b+foo)
601
+ elsif l.kind_of? Expression and l.op == :+; Expression[l.lexpr, :+, [l.rexpr, :+, r]].reduce_rec
602
+ elsif l.kind_of? Expression and r.kind_of? Expression and l.op == :% and r.op == :% and l.rexpr.kind_of?(::Integer) and l.rexpr == r.rexpr
603
+ Expression[[l.lexpr, :+, r.lexpr], :%, l.rexpr].reduce_rec
604
+ elsif l.kind_of? Expression and l.op == :- and not l.lexpr
605
+ reduce_rec_add_rec(r, l.rexpr)
606
+ elsif l.kind_of? Expression and r.kind_of? Expression and l.op == :& and r.op == :& and l.rexpr.kind_of?(::Integer) and r.rexpr.kind_of?(::Integer) and l.rexpr & r.rexpr == 0
607
+ # (a&0xf0)+(b&0x0f) => (a&0xf0)|(b&0x0f)
608
+ Expression[l, :|, r].reduce_rec
718
609
  else
719
- neg_l = Expression[:-, l]
610
+ reduce_rec_add_rec(r, Expression.new(:-, l, nil))
720
611
  end
612
+ end
613
+
614
+ def reduce_rec_add_rec(cur, neg_l)
615
+ if neg_l == cur
616
+ # -l found
617
+ 0
618
+ elsif cur.kind_of?(Expression) and cur.op == :+
619
+ # recurse
620
+ if newl = reduce_rec_add_rec(cur.lexpr, neg_l)
621
+ Expression[newl, cur.op, cur.rexpr].reduce_rec
622
+ elsif newr = reduce_rec_add_rec(cur.rexpr, neg_l)
623
+ Expression[cur.lexpr, cur.op, newr].reduce_rec
624
+ end
625
+ end
626
+ end
721
627
 
722
- # recursive search & replace -lexpr by 0
723
- simplifier = lambda { |cur|
724
- if neg_l == cur
725
- # -l found
726
- 0
727
- elsif cur.kind_of? Expression and cur.op == :+
728
- # recurse
729
- if newl = simplifier[cur.lexpr]
730
- Expression[newl, cur.op, cur.rexpr].reduce_rec
731
- elsif newr = simplifier[cur.rexpr]
732
- Expression[cur.lexpr, cur.op, newr].reduce_rec
628
+ def reduce_op_minus(l, r)
629
+ if l == :unknown or r == :unknown; :unknown
630
+ elsif not l and r.kind_of? Expression and (r.op == :- or r.op == :+)
631
+ if r.op == :- # no lexpr (reduced)
632
+ # -(-x) => x
633
+ r.rexpr
634
+ else # :+ and lexpr (r is reduced)
635
+ # -(a+b) => (-a)+(-b)
636
+ Expression.new(:+, Expression.new(:-, r.rexpr, nil), Expression.new(:-, r.lexpr, nil)).reduce_rec
637
+ end
638
+ elsif l.kind_of? Expression and l.op == :+ and l.lexpr == r
639
+ # shortcircuit for a common occurence [citation needed]
640
+ # (a+b)-a
641
+ l.rexpr
642
+ elsif l
643
+ # a-b => a+(-b)
644
+ Expression[l, :+, [:-, r]].reduce_rec
645
+ end
646
+ end
647
+
648
+ def reduce_op_andand(l, r)
649
+ if l == 0 # shortcircuit eval
650
+ 0
651
+ elsif l == 1
652
+ Expression[r, :'!=', 0].reduce_rec
653
+ elsif r == 0
654
+ 0 # XXX l could be a special ExprType with sideeffects ?
655
+ end
656
+ end
657
+
658
+ def reduce_op_oror(l, r)
659
+ if l.kind_of?(::Numeric) and l != 0 # shortcircuit eval
660
+ 1
661
+ elsif l == 0
662
+ Expression[r, :'!=', 0].reduce_rec
663
+ elsif r == 0
664
+ Expression[l, :'!=', 0].reduce_rec
665
+ end
666
+ end
667
+
668
+ def reduce_op_shr(l, r)
669
+ if l == 0; 0
670
+ elsif r == 0; l
671
+ elsif l.kind_of? Expression and l.op == :>>
672
+ Expression[l.lexpr, :>>, [l.rexpr, :+, r]].reduce_rec
673
+ elsif r.kind_of? Integer and l.kind_of? Expression and [:&, :|, :^].include? l.op
674
+ # (a | b) << i => (a<<i | b<<i)
675
+ Expression[[l.lexpr, :>>, r], l.op, [l.rexpr, :>>, r]].reduce_rec
676
+ end
677
+ end
678
+
679
+ def reduce_op_shl(l, r)
680
+ if l == 0; 0
681
+ elsif r == 0; l
682
+ elsif l.kind_of? Expression and l.op == :<<
683
+ Expression[l.lexpr, :<<, [l.rexpr, :+, r]].reduce_rec
684
+ elsif l.kind_of? Expression and l.op == :>> and r.kind_of? Integer and l.rexpr.kind_of? Integer
685
+ # (a >> 1) << 1 == a & 0xfffffe
686
+ if r == l.rexpr
687
+ Expression[l.lexpr, :&, (-1 << r)].reduce_rec
688
+ elsif r > l.rexpr
689
+ Expression[[l.lexpr, :<<, r-l.rexpr], :&, (-1 << r)].reduce_rec
690
+ else
691
+ Expression[[l.lexpr, :>>, l.rexpr-r], :&, (-1 << r)].reduce_rec
692
+ end
693
+ elsif r.kind_of? Integer and l.kind_of? Expression and [:&, :|, :^].include? l.op
694
+ # (a | b) << i => (a<<i | b<<i)
695
+ Expression[[l.lexpr, :<<, r], l.op, [l.rexpr, :<<, r]].reduce_rec
696
+ end
697
+ end
698
+
699
+ NEG_OP = {:'==' => :'!=', :'!=' => :'==', :< => :>=, :> => :<=, :<= => :>, :>= => :<}
700
+
701
+ def reduce_op_not(l, r)
702
+ if r.kind_of? Expression and nop = NEG_OP[r.op]
703
+ Expression[r.lexpr, nop, r.rexpr].reduce_rec
704
+ end
705
+ end
706
+
707
+ def reduce_op_eql(l, r)
708
+ if l == r; 1
709
+ elsif r == 0 and l.kind_of? Expression and nop = NEG_OP[l.op]
710
+ Expression[l.lexpr, nop, l.rexpr].reduce_rec
711
+ elsif r == 1 and l.kind_of? Expression and NEG_OP[l.op]
712
+ l
713
+ elsif r == 0 and l.kind_of? Expression and l.op == :+
714
+ if l.rexpr.kind_of? Expression and l.rexpr.op == :- and not l.rexpr.lexpr
715
+ Expression[l.lexpr, :==, l.rexpr.rexpr].reduce_rec
716
+ elsif l.rexpr.kind_of?(::Integer)
717
+ Expression[l.lexpr, :==, -l.rexpr].reduce_rec
718
+ end
719
+ end
720
+ end
721
+
722
+ def reduce_op_neq(l, r)
723
+ if l == r; 0
724
+ end
725
+ end
726
+
727
+ def reduce_op_xor(l, r)
728
+ if l == :unknown or r == :unknown; :unknown
729
+ elsif l == 0; r
730
+ elsif r == 0; l
731
+ elsif l == r; 0
732
+ elsif r == 1 and l.kind_of? Expression and NEG_OP[l.op]
733
+ Expression[nil, :'!', l].reduce_rec
734
+ elsif l.kind_of?(::Numeric)
735
+ if r.kind_of? Expression and r.op == :^
736
+ # 1^(x^y) => x^(y^1)
737
+ Expression[r.lexpr, :^, [r.rexpr, :^, l]].reduce_rec
738
+ else
739
+ # 1^a => a^1
740
+ Expression[r, :^, l].reduce_rec
741
+ end
742
+ elsif l.kind_of? Expression and l.op == :^
743
+ # (a^b)^c => a^(b^c)
744
+ Expression[l.lexpr, :^, [l.rexpr, :^, r]].reduce_rec
745
+ elsif r.kind_of? Expression and r.op == :^
746
+ if r.rexpr == l
747
+ # a^(a^b) => b
748
+ r.lexpr
749
+ elsif r.lexpr == l
750
+ # a^(b^a) => b
751
+ r.rexpr
752
+ else
753
+ # a^(b^(c^(a^d))) => b^(a^(c^(a^d)))
754
+ # XXX ugly..
755
+ tr = r
756
+ found = false
757
+ while not found and tr.kind_of?(Expression) and tr.op == :^
758
+ found = true if tr.lexpr == l or tr.rexpr == l
759
+ tr = tr.rexpr
760
+ end
761
+ if found
762
+ Expression[r.lexpr, :^, [l, :^, r.rexpr]].reduce_rec
733
763
  end
734
764
  end
735
- }
765
+ elsif l.kind_of?(Expression) and l.op == :& and l.rexpr.kind_of?(::Integer) and (l.rexpr & (l.rexpr+1)) == 0
766
+ if r.kind_of?(::Integer) and r & l.rexpr == r
767
+ # (a&0xfff)^12 => (a^12)&0xfff
768
+ Expression[[l.lexpr, :^, r], :&, l.rexpr].reduce_rec
769
+ elsif r.kind_of?(Expression) and r.op == :& and r.rexpr.kind_of?(::Integer) and r.rexpr == l.rexpr
770
+ # (a&0xfff)^(b&0xfff) => (a^b)&0xfff
771
+ Expression[[l.lexpr, :^, r.lexpr], :&, l.rexpr].reduce_rec
772
+ end
773
+ end
774
+ end
736
775
 
737
- simplifier[r]
738
- end
739
-
740
- # expr & 0xffff
741
- def reduce_rec_mod2(e, mask)
742
- case e.op
743
- when :+, :^
744
- if e.lexpr.kind_of?(Expression) and e.lexpr.op == :& and
745
- e.lexpr.rexpr.kind_of?(::Integer) and e.lexpr.rexpr & mask == mask
746
- # ((a&m) + b) & m => (a+b) & m
747
- Expression[[e.lexpr.lexpr, e.op, e.rexpr], :&, mask].reduce_rec
748
- elsif e.rexpr.kind_of?(Expression) and e.rexpr.op == :& and
749
- e.rexpr.rexpr.kind_of?(::Integer) and e.rexpr.rexpr & mask == mask
750
- # (a + (b&m)) & m => (a+b) & m
751
- Expression[[e.lexpr, e.op, e.rexpr.lexpr], :&, mask].reduce_rec
776
+ def reduce_op_and(l, r)
777
+ if l == 0 or r == 0; 0
778
+ elsif r == 1 and l.kind_of?(Expression) and [:'==', :'!=', :<, :>, :<=, :>=].include?(l.op)
779
+ l
780
+ elsif l == r; l
781
+ elsif l.kind_of?(Integer); Expression[r, :&, l].reduce_rec
782
+ elsif l.kind_of?(Expression) and l.op == :&; Expression[l.lexpr, :&, [l.rexpr, :&, r]].reduce_rec
783
+ elsif l.kind_of?(Expression) and [:|, :^].include?(l.op) and r.kind_of?(Integer) and (l.op == :| or (r & (r+1)) != 0)
784
+ # (a ^| b) & i => (a&i ^| b&i)
785
+ Expression[[l.lexpr, :&, r], l.op, [l.rexpr, :&, r]].reduce_rec
786
+ elsif r.kind_of?(::Integer) and l.kind_of?(Expression) and (r & (r+1)) == 0
787
+ # foo & 0xffff
788
+ case l.op
789
+ when :+, :^
790
+ if l.lexpr.kind_of?(Expression) and l.lexpr.op == :& and
791
+ l.lexpr.rexpr.kind_of?(::Integer) and l.lexpr.rexpr & r == r
792
+ # ((a&m) + b) & m => (a+b) & m
793
+ Expression[[l.lexpr.lexpr, l.op, l.rexpr], :&, r].reduce_rec
794
+ elsif l.rexpr.kind_of?(Expression) and l.rexpr.op == :& and
795
+ l.rexpr.rexpr.kind_of?(::Integer) and l.rexpr.rexpr & r == r
796
+ # (a + (b&m)) & m => (a+b) & m
797
+ Expression[[l.lexpr, l.op, l.rexpr.lexpr], :&, r].reduce_rec
798
+ else
799
+ Expression[l, :&, r]
800
+ end
801
+ when :|
802
+ # rol/ror composition
803
+ reduce_rec_composerol l, r
752
804
  else
753
- Expression[e, :&, mask]
805
+ Expression[l, :&, r]
754
806
  end
755
- when :|
756
- # rol/ror composition
757
- reduce_rec_composerol e, mask
758
- else
759
- Expression[e, :&, mask]
760
807
  end
761
808
  end
762
809
 
@@ -766,14 +813,14 @@ class Expression < ExpressionType
766
813
  m = Expression[['var', :sh_op, 'amt'], :|, ['var', :inv_sh_op, 'inv_amt']]
767
814
  if vars = e.match(m, 'var', :sh_op, 'amt', :inv_sh_op, 'inv_amt') and vars[:sh_op] == {:>> => :<<, :<< => :>>}[vars[:inv_sh_op]] and
768
815
  ((vars['amt'].kind_of?(::Integer) and vars['inv_amt'].kind_of?(::Integer) and ampl = vars['amt'] + vars['inv_amt']) or
769
- (vars['amt'].kind_of? Expression and vars['amt'].op == :% and vars['amt'].rexpr.kind_of? ::Integer and
816
+ (vars['amt'].kind_of? Expression and vars['amt'].op == :% and vars['amt'].rexpr.kind_of?(::Integer) and
770
817
  vars['inv_amt'].kind_of? Expression and vars['inv_amt'].op == :% and vars['amt'].rexpr == vars['inv_amt'].rexpr and ampl = vars['amt'].rexpr)) and
771
818
  mask == (1<<ampl)-1 and vars['var'].kind_of? Expression and # it's a rotation
772
819
 
773
820
  vars['var'].op == :& and vars['var'].rexpr == mask and
774
821
  ivars = vars['var'].lexpr.match(m, 'var', :sh_op, 'amt', :inv_sh_op, 'inv_amt') and ivars[:sh_op] == {:>> => :<<, :<< => :>>}[ivars[:inv_sh_op]] and
775
822
  ((ivars['amt'].kind_of?(::Integer) and ivars['inv_amt'].kind_of?(::Integer) and ampl = ivars['amt'] + ivars['inv_amt']) or
776
- (ivars['amt'].kind_of? Expression and ivars['amt'].op == :% and ivars['amt'].rexpr.kind_of? ::Integer and
823
+ (ivars['amt'].kind_of? Expression and ivars['amt'].op == :% and ivars['amt'].rexpr.kind_of?(::Integer) and
777
824
  ivars['inv_amt'].kind_of? Expression and ivars['inv_amt'].op == :% and ivars['amt'].rexpr == ivars['inv_amt'].rexpr and ampl = ivars['amt'].rexpr))
778
825
  if ivars[:sh_op] != vars[:sh_op]
779
826
  # ensure the rotations are the same orientation
@@ -788,6 +835,48 @@ class Expression < ExpressionType
788
835
  end
789
836
  end
790
837
 
838
+ def reduce_op_or(l, r)
839
+ if l == 0; r
840
+ elsif r == 0; l
841
+ elsif l == -1 or r == -1; -1
842
+ elsif l == r; l
843
+ elsif l.kind_of? Integer; Expression[r, :|, l].reduce_rec
844
+ elsif l.kind_of? Expression and l.op == :|
845
+ # (a|b)|c => a|(b|c)
846
+ Expression[l.lexpr, :|, [l.rexpr, :|, r]].reduce_rec
847
+ elsif l.kind_of? Expression and l.op == :& and r.kind_of? Expression and r.op == :& and l.lexpr == r.lexpr
848
+ # (a&b)|(a&c) => a&(b|c)
849
+ Expression[l.lexpr, :&, [l.rexpr, :|, r.rexpr]].reduce_rec
850
+ end
851
+ end
852
+
853
+ def reduce_op_times(l, r)
854
+ if l == 0 or r == 0; 0
855
+ elsif l == 1; r
856
+ elsif r == 1; l
857
+ elsif r.kind_of? Integer; Expression[r, :*, l].reduce_rec
858
+ elsif r.kind_of? Expression and r.op == :*; Expression[[l, :*, r.lexpr], :*, r.rexpr].reduce_rec
859
+ elsif l.kind_of? Integer and r.kind_of? Expression and r.op == :* and r.lexpr.kind_of? Integer; Expression[l*r.lexpr, :*, r.rexpr].reduce_rec # XXX need & regsize..
860
+ elsif l.kind_of? Integer and r.kind_of? Expression and r.op == :+ and r.rexpr.kind_of? Integer; Expression[[l, :*, r.lexpr], :+, l*r.rexpr].reduce_rec
861
+ end
862
+ end
863
+
864
+ def reduce_op_div(l, r)
865
+ if r == 0
866
+ elsif r.kind_of? Integer and l.kind_of? Expression and l.op == :+ and l.rexpr.kind_of? Integer and l.rexpr % r == 0
867
+ Expression[[l.lexpr, :/, r], :+, l.rexpr/r].reduce_rec
868
+ elsif r.kind_of? Integer and l.kind_of? Expression and l.op == :* and l.lexpr % r == 0
869
+ Expression[l.lexpr/r, :*, l.rexpr].reduce_rec
870
+ end
871
+ end
872
+
873
+ def reduce_op_mod(l, r)
874
+ if r.kind_of?(Integer) and r != 0 and (r & (r-1) == 0)
875
+ Expression[l, :&, r-1].reduce_rec
876
+ end
877
+ end
878
+
879
+
791
880
  # a pattern-matching method
792
881
  # Expression[42, :+, 28].match(Expression['any', :+, 28], 'any') => {'any' => 42}
793
882
  # Expression[42, :+, 28].match(Expression['any', :+, 'any'], 'any') => false
@@ -816,24 +905,29 @@ class Expression < ExpressionType
816
905
  # returns the array of non-numeric members of the expression
817
906
  # if a variables appears 3 times, it will be present 3 times in the returned array
818
907
  def externals
819
- [@rexpr, @lexpr].inject([]) { |a, e|
908
+ a = []
909
+ [@rexpr, @lexpr].each { |e|
820
910
  case e
821
911
  when ExpressionType; a.concat e.externals
822
912
  when nil, ::Numeric; a
823
913
  else a << e
824
914
  end
825
915
  }
916
+ a
826
917
  end
827
918
 
828
919
  # returns the externals that appears in the expression, does not walk through other ExpressionType
829
- def expr_externals
830
- [@rexpr, @lexpr].inject([]) { |a, e|
920
+ def expr_externals(include_exprs=false)
921
+ a = []
922
+ [@rexpr, @lexpr].each { |e|
831
923
  case e
832
- when Expression; a.concat e.expr_externals
833
- when nil, ::Numeric, ExpressionType; a
924
+ when Expression; a.concat e.expr_externals(include_exprs)
925
+ when nil, ::Numeric; a
926
+ when ExpressionType; include_exprs ? a << e : a
834
927
  else a << e
835
928
  end
836
929
  }
930
+ a
837
931
  end
838
932
 
839
933
  def inspect
@@ -843,6 +937,25 @@ class Expression < ExpressionType
843
937
  Unknown = self[:unknown]
844
938
  end
845
939
 
940
+ # An Expression with a custom string representation
941
+ # used to show #define constants, struct offsets, func local vars, etc
942
+ class ExpressionString < ExpressionType
943
+ attr_accessor :expr, :str, :type, :hide_str
944
+ def reduce; expr.reduce; end
945
+ def reduce_rec; expr.reduce_rec; end
946
+ def bind(*a); expr.bind(*a); end
947
+ def externals; expr.externals; end
948
+ def expr_externals; expr.expr_externals; end
949
+ def match_rec(*a); expr.match_rec(*a); end
950
+ def initialize(expr, str, type=nil)
951
+ @expr = Expression[expr]
952
+ @str = str
953
+ @type = type
954
+ end
955
+ def render_str ; [str] ; end
956
+ def inspect ; "ExpressionString.new(#{@expr.inspect}, #{str.inspect}, #{type.inspect})" ; end
957
+ end
958
+
846
959
  # an EncodedData relocation, specifies a value to patch in
847
960
  class Relocation
848
961
  # the relocation value (an Expression)
@@ -855,7 +968,7 @@ class Relocation
855
968
  include Backtrace
856
969
 
857
970
  def initialize(target, type, endianness, backtrace = nil)
858
- raise ArgumentError, "bad args #{[target, type, endianness].inspect}" if not target.kind_of? Expression or not type.kind_of? ::Symbol or not endianness.kind_of? ::Symbol
971
+ raise ArgumentError, "bad args #{[target, type, endianness].inspect}" if not target.kind_of? Expression or not type.kind_of?(::Symbol) or not endianness.kind_of?(::Symbol)
859
972
  @target, @type, @endianness, @backtrace = target, type, endianness, backtrace
860
973
  end
861
974
 
@@ -890,7 +1003,11 @@ class EncodedData
890
1003
  def ptr=(p) @ptr = @export[p] || p end
891
1004
 
892
1005
  # opts' keys in :reloc, :export, :virtsize, defaults to empty/empty/data.length
893
- def initialize(data = '', opts={})
1006
+ def initialize(data='', opts={})
1007
+ if data.respond_to?(:force_encoding) and data.encoding.name != 'ASCII-8BIT' and data.length > 0
1008
+ puts "Forcing edata.data.encoding = BINARY at", caller if $DEBUG
1009
+ data = data.dup.force_encoding('binary')
1010
+ end
894
1011
  @data = data
895
1012
  @reloc = opts[:reloc] || {}
896
1013
  @export = opts[:export] || {}
@@ -904,9 +1021,10 @@ class EncodedData
904
1021
  if set_inv or not @inv_export[off]
905
1022
  @inv_export[off] = label
906
1023
  end
1024
+ label
907
1025
  end
908
1026
 
909
- def del_export(label, off=@ptr)
1027
+ def del_export(label, off=@export[label])
910
1028
  @export.delete label
911
1029
  if e = @export.index(off)
912
1030
  @inv_export[off] = e
@@ -942,6 +1060,7 @@ class EncodedData
942
1060
  # if numeric, replace the raw data with the encoding of this value (+fill+s preceding data if needed) and remove the reloc
943
1061
  # if replace_target is true, the reloc target is replaced with its bound counterpart
944
1062
  def fixup_choice(binding, replace_target)
1063
+ return if binding.empty?
945
1064
  @reloc.keys.each { |off|
946
1065
  val = @reloc[off].target.bind(binding).reduce
947
1066
  if val.kind_of? Integer
@@ -973,13 +1092,15 @@ class EncodedData
973
1092
  return {} if not key
974
1093
  base = (@export[key] == 0 ? key : Expression[key, :-, @export[key]])
975
1094
  end
976
- @export.inject({}) { |binding, (n, o)| binding.update n => Expression.new(:+, o, base) }
1095
+ binding = {}
1096
+ @export.each { |n, o| binding.update n => Expression.new(:+, o, base) }
1097
+ binding
977
1098
  end
978
1099
 
979
1100
  # returns an array of variables that needs to be defined for a complete #fixup
980
1101
  # ie the list of externals for all relocations
981
- def reloc_externals
982
- @reloc.values.map { |r| r.target.externals }.flatten.uniq - @export.keys
1102
+ def reloc_externals(interns = @export.keys)
1103
+ @reloc.values.map { |r| r.target.externals }.flatten.uniq - interns
983
1104
  end
984
1105
 
985
1106
  # returns the offset where the relocation for target t is to be applied
@@ -1008,7 +1129,7 @@ class EncodedData
1008
1129
  end
1009
1130
 
1010
1131
  # concatenation of another +EncodedData+ (or nil/Fixnum/anything supporting String#<<)
1011
- def << other
1132
+ def <<(other)
1012
1133
  case other
1013
1134
  when nil
1014
1135
  when ::Fixnum
@@ -1036,6 +1157,10 @@ class EncodedData
1036
1157
  @virtsize += other.virtsize
1037
1158
  else
1038
1159
  fill
1160
+ if other.respond_to?(:force_encoding) and other.encoding.name != 'ASCII-8BIT'
1161
+ puts "Forcing edata.data.encoding = BINARY at", caller if $DEBUG
1162
+ other = other.dup.force_encoding('binary')
1163
+ end
1039
1164
  if @data.empty?; @data = other.dup
1040
1165
  elsif not @data.kind_of?(String); @data = @data.to_str << other
1041
1166
  else @data << other
@@ -1047,7 +1172,7 @@ class EncodedData
1047
1172
  end
1048
1173
 
1049
1174
  # equivalent to dup << other, filters out Integers & nil
1050
- def + other
1175
+ def +(other)
1051
1176
  raise ArgumentError if not other or other.kind_of?(Integer)
1052
1177
  dup << other
1053
1178
  end
@@ -1092,7 +1217,7 @@ class EncodedData
1092
1217
  val = len
1093
1218
  len = nil
1094
1219
  end
1095
- if not len and from.kind_of? ::Range
1220
+ if not len and from.kind_of?(::Range)
1096
1221
  b = from.begin
1097
1222
  e = from.end
1098
1223
  b = @export[b] if @export[b]
@@ -1104,14 +1229,14 @@ class EncodedData
1104
1229
  from = b
1105
1230
  end
1106
1231
  from = @export[from] || from
1107
- raise "invalid offset #{from}" if not from.kind_of? ::Integer
1232
+ raise "invalid offset #{from}" if not from.kind_of?(::Integer)
1108
1233
  from = from + @virtsize if from < 0
1109
1234
 
1110
1235
  if not len
1111
- val = val.chr if val.kind_of? ::Integer
1236
+ val = val.chr if val.kind_of?(::Integer)
1112
1237
  len = val.length
1113
1238
  end
1114
- raise "invalid slice length #{len}" if not len.kind_of? ::Integer or len < 0
1239
+ raise "invalid slice length #{len}" if not len.kind_of?(::Integer) or len < 0
1115
1240
 
1116
1241
  if from >= @virtsize
1117
1242
  len = 0
@@ -1170,24 +1295,24 @@ class EncodedData
1170
1295
  def pattern_scan(pat, chunksz=nil, margin=nil)
1171
1296
  chunksz ||= 4*1024*1024 # scan 4MB at a time
1172
1297
  margin ||= 65536 # add this much bytes at each chunk to find /pat/ over chunk boundaries
1173
- pat = Regexp.new(Regexp.escape(pat)) if pat.kind_of? ::String
1298
+ pat = Regexp.new(Regexp.escape(pat)) if pat.kind_of?(::String)
1174
1299
 
1175
1300
  found = []
1176
1301
  chunkoff = 0
1177
1302
  while chunkoff < @data.length
1178
1303
  chunk = @data[chunkoff, chunksz+margin].to_str
1179
1304
  off = 0
1180
- while match_off = (chunk[off..-1] =~ pat)
1181
- break if off+match_off >= chunksz # match fully in margin
1182
- match_addr = chunkoff + off + match_off
1305
+ while match = chunk[off..-1].match(pat)
1306
+ off += match.pre_match.length
1307
+ m_l = match[0].length
1308
+ break if off >= chunksz # match fully in margin
1309
+ match_addr = chunkoff + off
1183
1310
  found << match_addr if not block_given? or yield(match_addr)
1184
- off += match_off + 1
1185
- # XXX +1 or +lastmatch.length ?
1186
- # 'aaaabc'.pattern_scan(/a*bc/) will match 5 times here
1311
+ off += m_l
1187
1312
  end
1188
1313
  chunkoff += chunksz
1189
1314
  end
1190
- found
1315
+ found
1191
1316
  end
1192
1317
  end
1193
1318
  end