~ubuntu-branches/ubuntu/lucid/mtasc/lucid

« back to all changes in this revision

Viewing changes to ocaml/swflib/as3code.ml

  • Committer: Bazaar Package Importer
  • Author(s): Paul Wise
  • Date: 2007-05-23 19:17:16 UTC
  • mto: (2.1.1 gutsy)
  • mto: This revision was merged to the branch mainline in revision 3.
  • Revision ID: james.westby@ubuntu.com-20070523191716-lpvac307yorewp3g
Tags: upstream-1.13
ImportĀ upstreamĀ versionĀ 1.13

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
(*
 
2
 *  This file is part of SwfLib
 
3
 *  Copyright (c)2004-2006 Nicolas Cannasse
 
4
 *
 
5
 *  This program is free software; you can redistribute it and/or modify
 
6
 *  it under the terms of the GNU General Public License as published by
 
7
 *  the Free Software Foundation; either version 2 of the License, or
 
8
 *  (at your option) any later version.
 
9
 *
 
10
 *  This program is distributed in the hope that it will be useful,
 
11
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
13
 *  GNU General Public License for more details.
 
14
 *
 
15
 *  You should have received a copy of the GNU General Public License
 
16
 *  along with this program; if not, write to the Free Software
 
17
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
18
 *)
 
19
open IO
 
20
open As3
 
21
 
 
22
let s = Printf.sprintf
 
23
 
 
24
let f_int_length : (int -> int) ref = ref (fun _ -> assert false)
 
25
let f_int_read : (IO.input -> int) ref = ref (fun _ -> assert false)
 
26
let f_int_write : (unit IO.output -> int -> unit) ref = ref (fun _ _ -> assert false)
 
27
 
 
28
let int_length i = (!f_int_length) i
 
29
let read_int ch = (!f_int_read) ch
 
30
let write_int (ch : 'a IO.output) i = (!f_int_write) (Obj.magic ch) i
 
31
 
 
32
let int_index (x : 'a index) : int = Obj.magic x
 
33
let index_int (x : int) : 'a index = Obj.magic x
 
34
let int_index_nz (x : 'a index_nz) : int = Obj.magic x
 
35
let index_nz_int (x : int) : 'a index_nz = Obj.magic x
 
36
 
 
37
let read_index ch = index_int (read_int ch)
 
38
let write_index ch i = write_int ch (int_index i)
 
39
 
 
40
let read_index_nz ch = index_nz_int (read_int ch)
 
41
let write_index_nz ch i = write_int ch (int_index_nz i)
 
42
 
 
43
let iget (t : 'a array) (i : 'a index) : 'a =
 
44
        t.(Obj.magic i - 1)
 
45
 
 
46
let write_signed_byte = write_byte
 
47
 
 
48
let max_i24 = 1 lsl 23 - 1
 
49
 
 
50
let read_i24 ch =
 
51
        let a = read_byte ch in
 
52
        let b = read_byte ch in
 
53
        let c = read_byte ch in
 
54
        let n = a lor (b lsl 8) lor (c lsl 16) in
 
55
        if c land 128 <> 0 then
 
56
                n - (1 lsl 24)
 
57
        else
 
58
                n
 
59
 
 
60
let rec write_i24 ch n =
 
61
        if n < -max_i24 || n > max_i24 then assert false;
 
62
        let n = (if n land (1 lsl 23) <> 0 then n + (1 lsl 24) else n) in
 
63
        write_byte ch n;
 
64
        write_byte ch (n lsr 8);
 
65
        write_byte ch (n lsr 16)
 
66
 
 
67
let ops , ops_ids =
 
68
        let h = Hashtbl.create 0 in
 
69
        let h2 = Hashtbl.create 0 in
 
70
        List.iter (fun (o,b) -> Hashtbl.add h b o; Hashtbl.add h2 o b)
 
71
        [
 
72
                A3OAs, 0x87;
 
73
                A3ONeg, 0x90;
 
74
                A3OIncr, 0x91;
 
75
                A3ODecr, 0x93;
 
76
                A3ONot, 0x96;
 
77
                A3OBitNot, 0x97;
 
78
                A3OAdd, 0xA0;
 
79
                A3OSub, 0xA1;
 
80
                A3OMul, 0xA2;
 
81
                A3ODiv, 0xA3;
 
82
                A3OMod, 0xA4;
 
83
                A3OShl, 0xA5;
 
84
                A3OShr, 0xA6;
 
85
                A3OUShr, 0xA7;
 
86
                A3OAnd, 0xA8;
 
87
                A3OOr, 0xA9;
 
88
                A3OXor, 0xAA;
 
89
                A3OEq, 0xAB;
 
90
                A3OPhysEq, 0xAC;
 
91
                A3OLt, 0xAD;
 
92
                A3OLte, 0xAE;
 
93
                A3OGt, 0xAF;
 
94
                A3OGte, 0xB0;
 
95
                A3OIs, 0xB3;
 
96
                A3OIn, 0xB4;
 
97
                A3OIIncr, 0xC0;
 
98
                A3OIDecr, 0xC1;
 
99
        ];
 
100
        h , h2
 
101
 
 
102
let length = function   
 
103
        | A3SmallInt _ -> 2
 
104
        | A3StackCall n
 
105
        | A3StackNew n
 
106
        | A3Object n
 
107
        | A3RegReset n
 
108
        | A3SuperConstr n
 
109
        | A3GetSlot n
 
110
        | A3SetSlot n
 
111
        | A3Catch n
 
112
        | A3IncrReg n   
 
113
        | A3Array n
 
114
        | A3Int n
 
115
        | A3ClassDef n
 
116
        | A3DebugLine n ->
 
117
                1 + int_length n
 
118
        | A3String f
 
119
        | A3DebugFile f ->
 
120
                1 + int_length (int_index f)
 
121
        | A3IntRef f ->
 
122
                1 + int_length (int_index f)
 
123
        | A3Float f ->
 
124
                1 + int_length (int_index f)
 
125
        | A3Function f ->
 
126
                1 + int_length (int_index_nz f) 
 
127
        | A3Set f
 
128
        | A3Get f
 
129
        | A3Delete f
 
130
        | A3SetInf f
 
131
        | A3GetInf f
 
132
        | A3GetProp f
 
133
        | A3SetProp f
 
134
        | A3Cast f
 
135
        | A3GetSuper f
 
136
        | A3XmlOp1 f
 
137
        | A3SetSuper f ->
 
138
                1 + int_length (int_index f)
 
139
        | A3Op _
 
140
        | A3Undefined
 
141
        | A3Null
 
142
        | A3True
 
143
        | A3False
 
144
        | A3NaN
 
145
        | A3RetVoid
 
146
        | A3Ret
 
147
        | A3Pop
 
148
        | A3Dup
 
149
        | A3CatchDone
 
150
        | A3ToObject
 
151
        | A3ToXml
 
152
        | A3ToInt
 
153
        | A3ToUInt
 
154
        | A3ToNumber
 
155
        | A3ToBool
 
156
        | A3ToString
 
157
        | A3This
 
158
        | A3Throw
 
159
        | A3Nop
 
160
        | A3Typeof
 
161
        | A3InstanceOf
 
162
        | A3Scope
 
163
        | A3ForIn
 
164
        | A3NewBlock
 
165
        | A3ForEach
 
166
        | A3PopScope
 
167
        | A3XmlOp3
 
168
        | A3XmlOp2
 
169
        | A3Unk _ -> 1
 
170
        | A3DebugReg (a,b,c,line) -> 1 + int_length a + int_length b + int_length c + int_length line
 
171
        | A3GetScope0 -> 1
 
172
        | A3GetScope n -> 1 + int_length n
 
173
        | A3Reg n | A3SetReg n -> if n >= 1 && n <= 3 then 1 else (1 + int_length n)
 
174
        | A3SuperCall (f,n) | A3Call (f,n) | A3New (f,n) | A3CallUnknown (f,n) | A3SuperCallUnknown(f,n) -> 1 + int_length n + int_length (int_index f)
 
175
        | A3Jump _ -> 4
 
176
        | A3Next (a,b) -> 1 + int_length a + int_length b
 
177
        | A3Switch (_,cases,_) -> 
 
178
                let ncases = List.length cases in
 
179
                1 + 3 + int_length ncases + 3 * (ncases + 1)
 
180
 
 
181
let jump ch kind =
 
182
        A3Jump (kind,read_i24 ch)
 
183
 
 
184
let opcode ch =
 
185
        let op = (try Some (read_byte ch) with IO.No_more_input -> None) in
 
186
        match op with
 
187
        | None -> None
 
188
        | Some op -> Some (
 
189
                match op with
 
190
                | 0x03 -> A3Throw
 
191
                | 0x04 -> A3GetSuper (read_index ch)
 
192
                | 0x05 -> A3SetSuper (read_index ch)
 
193
                | 0x08 -> A3RegReset (read_int ch)
 
194
                | 0x09 -> A3Nop
 
195
                | 0x0C -> jump ch J3NotLt
 
196
                | 0x0D -> jump ch J3NotLte
 
197
                | 0x0E -> jump ch J3NotGt
 
198
                | 0x0F -> jump ch J3NotGte
 
199
                | 0x10 -> jump ch J3Always
 
200
                | 0x11 -> jump ch J3True
 
201
                | 0x12 -> jump ch J3False
 
202
                | 0x13 -> jump ch J3Eq
 
203
                | 0x14 -> jump ch J3Neq
 
204
                | 0x15 -> jump ch J3Lt
 
205
                | 0x16 -> jump ch J3Lte
 
206
                | 0x17 -> jump ch J3Gt
 
207
                | 0x18 -> jump ch J3Gte
 
208
                | 0x19 -> jump ch J3PhysEq
 
209
                | 0x1A -> jump ch J3PhysNeq
 
210
                | 0x1B -> 
 
211
                        let def = read_i24 ch in
 
212
                        let rec loop n =
 
213
                                if n = 0 then
 
214
                                        []
 
215
                                else
 
216
                                        let j = read_i24 ch in
 
217
                                        j :: loop (n - 1)
 
218
                        in
 
219
                        let cases = loop (read_int ch) in
 
220
                        let def2 = read_i24 ch in
 
221
                        A3Switch (def,cases,def2)
 
222
                | 0x1D -> A3PopScope
 
223
                | 0x1C -> A3XmlOp3
 
224
                | 0x1E -> A3ForIn
 
225
                | 0x20 -> A3Null
 
226
                | 0x21 -> A3Undefined
 
227
                | 0x23 -> A3ForEach
 
228
                | 0x24 -> A3SmallInt (read_signed_byte ch)
 
229
                | 0x25 -> A3Int (read_int ch)
 
230
                | 0x26 -> A3True
 
231
                | 0x27 -> A3False
 
232
                | 0x28 -> A3NaN
 
233
                | 0x29 -> A3Pop
 
234
                | 0x2A -> A3Dup
 
235
                | 0x2B -> A3CatchDone
 
236
                | 0x2C -> A3String (read_index ch)
 
237
                | 0x2D -> A3IntRef (read_index ch)
 
238
                | 0x2F -> A3Float (read_index ch)
 
239
                | 0x30 -> A3Scope
 
240
                | 0x32 -> 
 
241
                        let r1 = read_int ch in
 
242
                        let r2 = read_int ch in
 
243
                        A3Next (r1,r2)
 
244
                | 0x40 -> A3Function (read_index_nz ch)
 
245
                | 0x41 -> A3StackCall (read_int ch)
 
246
                | 0x42 -> A3StackNew (read_int ch)
 
247
                | 0x45 ->
 
248
                        let id = read_index ch in
 
249
                        let nargs = read_int ch in
 
250
                        A3SuperCall (id,nargs)
 
251
                | 0x46 ->
 
252
                        let id = read_index ch in
 
253
                        let nargs = read_int ch in
 
254
                        A3Call (id,nargs)
 
255
                | 0x47 -> A3RetVoid
 
256
                | 0x48 -> A3Ret
 
257
                | 0x49 -> A3SuperConstr (read_int ch)
 
258
                | 0x4A ->
 
259
                        let id = read_index ch in
 
260
                        let nargs = read_int ch in
 
261
                        A3New (id,nargs)
 
262
                | 0x4E ->
 
263
                        let id = read_index ch in
 
264
                        let nargs = read_int ch in
 
265
                        A3SuperCallUnknown (id,nargs)
 
266
                | 0x4F ->
 
267
                        let id = read_index ch in
 
268
                        let nargs = read_int ch in
 
269
                        A3CallUnknown (id,nargs)
 
270
                | 0x55 -> A3Object (read_int ch)
 
271
                | 0x56 -> A3Array (read_int ch)
 
272
                | 0x57 -> A3NewBlock
 
273
                | 0x58 -> A3ClassDef (read_int ch)
 
274
                | 0x59 -> A3XmlOp1 (read_index ch)
 
275
                | 0x5A -> A3Catch (read_int ch)
 
276
                | 0x5D -> A3GetInf (read_index ch)
 
277
                | 0x5E -> A3SetInf (read_index ch)
 
278
                | 0x60 -> A3GetProp (read_index ch)
 
279
                | 0x61 -> A3SetProp (read_index ch)
 
280
                | 0x62 -> A3Reg (read_int ch)
 
281
                | 0x63 -> A3SetReg (read_int ch)
 
282
                | 0x64 -> A3GetScope0
 
283
                | 0x65 -> A3GetScope (read_int ch)
 
284
                | 0x66 -> A3Get (read_index ch)
 
285
                | 0x68 -> A3Set (read_index ch)
 
286
                | 0x6A -> A3Delete (read_index ch)
 
287
                | 0x6C -> A3GetSlot (read_int ch)
 
288
                | 0x6D -> A3SetSlot (read_int ch)
 
289
                | 0x71 -> A3ToXml
 
290
                | 0x73 -> A3ToInt
 
291
                | 0x74 -> A3ToUInt
 
292
                | 0x75 -> A3ToNumber
 
293
                | 0x76 -> A3ToBool
 
294
                | 0x78 -> A3XmlOp2
 
295
                | 0x80 -> A3Cast (read_index ch)
 
296
                | 0x82 -> A3ToObject
 
297
                | 0x85 -> A3ToString
 
298
                | 0x95 -> A3Typeof
 
299
                | 0xB1 -> A3InstanceOf
 
300
                | 0xC2 -> A3IncrReg (read_int ch)
 
301
                | 0xD0 -> A3This
 
302
                | 0xD1 -> A3Reg 1
 
303
                | 0xD2 -> A3Reg 2
 
304
                | 0xD3 -> A3Reg 3
 
305
                | 0xD5 -> A3SetReg 1
 
306
                | 0xD6 -> A3SetReg 2
 
307
                | 0xD7 -> A3SetReg 3
 
308
                | 0xEF ->
 
309
                        let a = read_int ch in
 
310
                        let b = read_int ch in
 
311
                        let c = read_int ch in
 
312
                        let line = read_int ch in
 
313
                        A3DebugReg (a,b,c,line)
 
314
                | 0xF0 -> A3DebugLine (read_int ch)
 
315
                | 0xF1 -> A3DebugFile (read_index ch)
 
316
                | _ ->
 
317
                        try
 
318
                                A3Op (Hashtbl.find ops op)
 
319
                        with Not_found ->
 
320
                                Printf.printf "Unknown opcode 0x%.2X\n" op;
 
321
                                A3Unk (char_of_int op)
 
322
        )
 
323
 
 
324
let parse ch len =
 
325
        let data = nread ch len in
 
326
        let ch = input_string data in
 
327
        let rec loop acc =
 
328
                match (try opcode ch with _ -> match acc with A3Unk '\xff' :: _ -> None | _ -> Some (A3Unk '\xff')) with
 
329
                | None -> List.rev acc
 
330
                | Some o -> loop (o :: acc)
 
331
        in
 
332
        loop []
 
333
 
 
334
let write ch = function
 
335
        | A3Throw ->
 
336
                write_byte ch 0x03
 
337
        | A3GetSuper f ->
 
338
                write_byte ch 0x04;
 
339
                write_index ch f
 
340
        | A3SetSuper f ->
 
341
                write_byte ch 0x05;
 
342
                write_index ch f
 
343
        | A3RegReset n ->
 
344
                write_byte ch 0x08;
 
345
                write_int ch n
 
346
        | A3Nop ->
 
347
                write_byte ch 0x09
 
348
        | A3Jump (k,n) ->
 
349
                write_byte ch (match k with
 
350
                        | J3NotLt -> 0x0C
 
351
                        | J3NotLte -> 0x0D
 
352
                        | J3NotGt -> 0x0E
 
353
                        | J3NotGte -> 0x0F
 
354
                        | J3Always -> 0x10
 
355
                        | J3True -> 0x11
 
356
                        | J3False -> 0x12
 
357
                        | J3Eq -> 0x13
 
358
                        | J3Neq -> 0x14
 
359
                        | J3Lt -> 0x15
 
360
                        | J3Lte -> 0x16
 
361
                        | J3Gt -> 0x17
 
362
                        | J3Gte -> 0x18
 
363
                        | J3PhysEq -> 0x19
 
364
                        | J3PhysNeq -> 0x1A
 
365
                );
 
366
                write_i24 ch n
 
367
        | A3Switch (def,cases,def2) ->
 
368
                write_byte ch 0x1B;
 
369
                write_i24 ch def;
 
370
                write_int ch (List.length cases);
 
371
                List.iter (write_i24 ch) cases;
 
372
                write_i24 ch def2
 
373
        | A3XmlOp3 ->
 
374
                write_byte ch 0x1C
 
375
        | A3PopScope ->
 
376
                write_byte ch 0x1D
 
377
        | A3ForIn ->
 
378
                write_byte ch 0x1E
 
379
        | A3Null ->
 
380
                write_byte ch 0x20
 
381
        | A3Undefined ->
 
382
                write_byte ch 0x21
 
383
        | A3ForEach ->
 
384
                write_byte ch 0x23
 
385
        | A3SmallInt b ->
 
386
                write_byte ch 0x24;
 
387
                write_signed_byte ch b
 
388
        | A3Int i ->
 
389
                write_byte ch 0x25;
 
390
                write_int ch i
 
391
        | A3True ->
 
392
                write_byte ch 0x26
 
393
        | A3False ->
 
394
                write_byte ch 0x27
 
395
        | A3NaN ->
 
396
                write_byte ch 0x28
 
397
        | A3Pop ->
 
398
                write_byte ch 0x29
 
399
        | A3Dup ->
 
400
                write_byte ch 0x2A
 
401
        | A3CatchDone ->
 
402
                write_byte ch 0x2B
 
403
        | A3String s ->
 
404
                write_byte ch 0x2C;
 
405
                write_index ch s
 
406
        | A3IntRef i ->
 
407
                write_byte ch 0x2D;
 
408
                write_index ch i
 
409
        | A3Float f ->
 
410
                write_byte ch 0x2F;
 
411
                write_index ch f
 
412
        | A3Scope ->
 
413
                write_byte ch 0x30
 
414
        | A3Next (r1,r2) ->
 
415
                write_byte ch 0x32;
 
416
                write_int ch r1;
 
417
                write_int ch r2
 
418
        | A3Function f ->
 
419
                write_byte ch 0x40;
 
420
                write_index_nz ch f
 
421
        | A3StackCall n ->
 
422
                write_byte ch 0x41;
 
423
                write_int ch n
 
424
        | A3StackNew n ->
 
425
                write_byte ch 0x42;
 
426
                write_int ch n
 
427
        | A3SuperCall (f,n) ->
 
428
                write_byte ch 0x45;
 
429
                write_index ch f;
 
430
                write_int ch n
 
431
        | A3Call (f,n) ->
 
432
                write_byte ch 0x46;
 
433
                write_index ch f;
 
434
                write_int ch n
 
435
        | A3RetVoid ->
 
436
                write_byte ch 0x47
 
437
        | A3Ret ->
 
438
                write_byte ch 0x48
 
439
        | A3SuperConstr n ->
 
440
                write_byte ch 0x49;
 
441
                write_int ch n
 
442
        | A3New (f,n) ->
 
443
                write_byte ch 0x4A;
 
444
                write_index ch f;
 
445
                write_int ch n
 
446
        | A3SuperCallUnknown (f,n) ->
 
447
                write_byte ch 0x4E;
 
448
                write_index ch f;
 
449
                write_int ch n
 
450
        | A3CallUnknown (f,n) ->
 
451
                write_byte ch 0x4F;
 
452
                write_index ch f;
 
453
                write_int ch n
 
454
        | A3Object n ->
 
455
                write_byte ch 0x55;
 
456
                write_int ch n
 
457
        | A3Array n ->
 
458
                write_byte ch 0x56;
 
459
                write_int ch n
 
460
        | A3NewBlock ->
 
461
                write_byte ch 0x57
 
462
        | A3ClassDef f ->
 
463
                write_byte ch 0x58;
 
464
                write_int ch f
 
465
        | A3XmlOp1 f ->
 
466
                write_byte ch 0x59;
 
467
                write_index ch f
 
468
        | A3Catch n ->
 
469
                write_byte ch 0x5A;
 
470
                write_int ch n
 
471
        | A3GetInf f ->
 
472
                write_byte ch 0x5D;
 
473
                write_index ch f
 
474
        | A3SetInf f ->
 
475
                write_byte ch 0x5E;
 
476
                write_index ch f
 
477
        | A3GetProp f ->
 
478
                write_byte ch 0x60;
 
479
                write_index ch f
 
480
        | A3SetProp f ->
 
481
                write_byte ch 0x61;
 
482
                write_index ch f
 
483
        | A3Reg n ->
 
484
                (match n with
 
485
                | 1 -> write_byte ch 0xD1;
 
486
                | 2 -> write_byte ch 0xD2;
 
487
                | 3 -> write_byte ch 0xD3;
 
488
                | _ ->
 
489
                        write_byte ch 0x62;
 
490
                        write_int ch n)
 
491
        | A3SetReg n ->
 
492
                (match n with
 
493
                | 1 -> write_byte ch 0xD5;
 
494
                | 2 -> write_byte ch 0xD6;
 
495
                | 3 -> write_byte ch 0xD7;
 
496
                | _ ->
 
497
                        write_byte ch 0x63;
 
498
                        write_int ch n)
 
499
        | A3GetScope0 ->
 
500
                write_byte ch 0x64
 
501
        | A3GetScope n ->               
 
502
                write_byte ch 0x65;
 
503
                write_int ch n
 
504
        | A3Get f ->
 
505
                write_byte ch 0x66;
 
506
                write_index ch f
 
507
        | A3Set f ->
 
508
                write_byte ch 0x68;
 
509
                write_index ch f
 
510
        | A3Delete f ->
 
511
                write_byte ch 0x6A;
 
512
                write_index ch f
 
513
        | A3GetSlot n ->
 
514
                write_byte ch 0x6C;
 
515
                write_int ch n
 
516
        | A3SetSlot n ->
 
517
                write_byte ch 0x6D;
 
518
                write_int ch n
 
519
        | A3ToXml ->
 
520
                write_byte ch 0x71
 
521
        | A3ToInt ->
 
522
                write_byte ch 0x73
 
523
        | A3ToUInt ->
 
524
                write_byte ch 0x74
 
525
        | A3ToNumber ->
 
526
                write_byte ch 0x75
 
527
        | A3ToBool ->
 
528
                write_byte ch 0x76
 
529
        | A3XmlOp2 ->
 
530
                write_byte ch 0x78
 
531
        | A3Cast f ->
 
532
                write_byte ch 0x80;
 
533
                write_index ch f
 
534
        | A3ToObject ->
 
535
                write_byte ch 0x82
 
536
        | A3ToString ->
 
537
                write_byte ch 0x85
 
538
        | A3Typeof ->
 
539
                write_byte ch 0x95
 
540
        | A3InstanceOf ->
 
541
                write_byte ch 0xB1
 
542
        | A3IncrReg r ->
 
543
                write_byte ch 0xC2;
 
544
                write_int ch r
 
545
        | A3This ->
 
546
                write_byte ch 0xD0
 
547
        | A3DebugReg (a,b,c,line) ->
 
548
                write_byte ch 0xEF;
 
549
                write_int ch a;
 
550
                write_int ch b;
 
551
                write_int ch c;
 
552
                write_int ch line;
 
553
        | A3DebugLine f ->
 
554
                write_byte ch 0xF0;
 
555
                write_int ch f;
 
556
        | A3DebugFile f ->
 
557
                write_byte ch 0xF1;
 
558
                write_index ch f;
 
559
        | A3Op op ->
 
560
                write_byte ch (try Hashtbl.find ops_ids op with Not_found -> assert false)
 
561
        | A3Unk x ->
 
562
                write ch x
 
563
 
 
564
let dump_op = function
 
565
        | A3OAs -> "as"
 
566
        | A3ONeg -> "neg"
 
567
        | A3OIncr -> "incr"
 
568
        | A3ODecr -> "decr"
 
569
        | A3ONot -> "not"
 
570
        | A3OBitNot -> "bitnot"
 
571
        | A3OAdd -> "add"
 
572
        | A3OSub -> "sub"
 
573
        | A3OMul -> "mul"
 
574
        | A3ODiv -> "div"
 
575
        | A3OMod -> "mod"
 
576
        | A3OShl -> "shl"
 
577
        | A3OShr -> "shr"
 
578
        | A3OUShr -> "ushr"
 
579
        | A3OAnd -> "and"
 
580
        | A3OOr -> "or"
 
581
        | A3OXor -> "xor"
 
582
        | A3OEq -> "eq"
 
583
        | A3OPhysEq -> "physeq"
 
584
        | A3OLt -> "lt"
 
585
        | A3OLte -> "lte"
 
586
        | A3OGt -> "gt"
 
587
        | A3OGte -> "gte"
 
588
        | A3OIs -> "is"
 
589
        | A3OIn -> "in"
 
590
        | A3OIIncr -> "iincr"
 
591
        | A3OIDecr -> "idecr"
 
592
 
 
593
let dump_jump = function
 
594
        | J3NotLt -> "-nlt"
 
595
        | J3NotLte -> "-nlte"
 
596
        | J3NotGt -> "-ngt"
 
597
        | J3NotGte -> "-ngte"
 
598
        | J3Always -> ""
 
599
        | J3True -> "-if"
 
600
        | J3False -> "-ifnot"
 
601
        | J3Eq -> "-eq"
 
602
        | J3Neq -> "-neq"
 
603
        | J3Lt -> "-lt"
 
604
        | J3Lte -> "-lte"
 
605
        | J3Gt -> "-gt"
 
606
        | J3Gte -> "-gte"
 
607
        | J3PhysEq -> "-peq"
 
608
        | J3PhysNeq -> "-pneq"
 
609
 
 
610
let dump ctx op =
 
611
        let ident n = ctx.as3_idents.(int_index n - 1) in
 
612
        let field n =
 
613
                let t = ctx.as3_types.(int_index n - 1) in
 
614
                match t with
 
615
                | A3TClassInterface (Some ident,_) -> "[" ^ iget ctx.as3_idents ident ^ "]"
 
616
                | A3TMethodVar (ident,_) -> iget ctx.as3_idents ident
 
617
                | A3TArrayAccess idx -> "~array"
 
618
                | _ -> "???"
 
619
        in
 
620
        match op with
 
621
        | A3Throw -> "throw"
 
622
        | A3GetSuper f -> s "super.%s" (field f)
 
623
        | A3SetSuper f -> s "set super.%s" (field f)
 
624
        | A3RegReset n -> s "reset %d" n
 
625
        | A3Nop -> "nop"
 
626
        | A3Jump (k,n) -> s "jump%s %d" (dump_jump k) n
 
627
        | A3Switch (def,cases,def2) -> s "switch %d [%s] %d" def (String.concat "," (List.map (s "%d") cases)) def2
 
628
        | A3XmlOp3 -> "xml3"
 
629
        | A3PopScope -> "popscope"
 
630
        | A3ForIn -> "forin"
 
631
        | A3Null -> "null"
 
632
        | A3Undefined -> "undefined"
 
633
        | A3ForEach -> "foreach"
 
634
        | A3SmallInt b -> s "int %d" b
 
635
        | A3Int n -> s "int %d" n
 
636
        | A3True -> "true"
 
637
        | A3False -> "false"
 
638
        | A3NaN -> "nan"
 
639
        | A3Pop -> "pop"
 
640
        | A3Dup -> "dup"
 
641
        | A3CatchDone -> "catch-done?"
 
642
        | A3String n -> s "string [%s]" (ident n)
 
643
        | A3IntRef n -> s "int [%ld]" ctx.as3_ints.(int_index n - 1)
 
644
        | A3Float n -> s "float [%f]" ctx.as3_floats.(int_index n - 1)
 
645
        | A3Scope -> "scope"
 
646
        | A3Next (r1,r2) -> s "next %d %d" r1 r2
 
647
        | A3Function f -> s "function #%d" (int_index_nz f)
 
648
        | A3StackCall n -> s "stackcall (%d)" n
 
649
        | A3StackNew n -> s "stacknew (%d)" n
 
650
        | A3SuperCall (f,n) -> s "supercall %s (%d)" (field f) n
 
651
        | A3Call (f,n) -> s "call %s (%d)" (field f) n
 
652
        | A3RetVoid -> "ret void"
 
653
        | A3Ret -> "ret"
 
654
        | A3SuperConstr n -> s "superconstr %d" n
 
655
        | A3New (f,n) -> s "new %s (%d)" (field f) n
 
656
        | A3SuperCallUnknown (f,n) -> s "?supercall %s (%d)" (field f) n
 
657
        | A3CallUnknown (f,n) -> s "?call %s (%d)" (field f) n
 
658
        | A3Object n -> s "obj %d" n
 
659
        | A3Array n -> s "array %d" n
 
660
        | A3NewBlock -> "newblock"
 
661
        | A3ClassDef n -> s "classdef %d" n
 
662
        | A3XmlOp1 f -> s "xml1 %s" (field f)
 
663
        | A3Catch n -> s "catch %d" n
 
664
        | A3GetInf f -> s "iget %s" (field f)
 
665
        | A3SetInf f -> s "iset %s" (field f)
 
666
        | A3GetProp f -> s "getp %s" (field f)
 
667
        | A3SetProp f -> s "setp %s" (field f)
 
668
        | A3Reg n -> s "reg %d" n
 
669
        | A3SetReg n -> s "setreg %d" n
 
670
        | A3GetScope0 -> "getscope0"
 
671
        | A3GetScope n -> s "getscope %d" n
 
672
        | A3Get f -> s "get %s" (field f)
 
673
        | A3Set f -> s "set %s" (field f)
 
674
        | A3Delete f -> s "delete %s" (field f)
 
675
        | A3GetSlot n -> s "getslot %d" n
 
676
        | A3SetSlot n -> s "setslot %d" n
 
677
        | A3ToXml -> "to_xml"
 
678
        | A3ToInt -> "to_int"
 
679
        | A3ToUInt -> "to_uint"
 
680
        | A3ToNumber -> "to_number"
 
681
        | A3ToBool -> "to_bool"
 
682
        | A3XmlOp2 -> "xml2"
 
683
        | A3Cast f -> s "cast %s" (field f)
 
684
        | A3ToObject -> "to_obj"
 
685
        | A3ToString -> "to_str"
 
686
        | A3Typeof -> "typeof"
 
687
        | A3InstanceOf -> "instanceof"
 
688
        | A3IncrReg r -> s "incr-reg %d" r
 
689
        | A3This -> "this"
 
690
        | A3DebugReg (a,b,c,line) -> s ".reg %d %d %d line:%d" a b c line
 
691
        | A3DebugLine l -> s ".line %d" l
 
692
        | A3DebugFile f -> s ".file %s" (ident f)
 
693
        | A3Op o -> dump_op o
 
694
        | A3Unk x -> s "??? 0x%X" (int_of_char x)