metasm 1.0.1 → 1.0.2

Sign up to get free protection for your applications and to get access to all the features.
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