as3parse.ml 33 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111
  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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
  18. *)
  19. open Extlib_leftovers
  20. open As3
  21. let parse_idents = true
  22. let parse_namespaces = true && parse_idents
  23. let parse_ns_sets = true && parse_namespaces
  24. let parse_names = true && parse_ns_sets
  25. let parse_mtypes = true && parse_names
  26. let parse_metadata = true && parse_mtypes
  27. let parse_classes = true && parse_metadata
  28. let parse_statics = true && parse_classes
  29. let parse_inits = true && parse_statics
  30. let parse_functions = true && parse_inits
  31. let parse_bytecode = true && parse_functions
  32. let magic_index (i : int) : 'a index =
  33. Obj.magic i
  34. let magic_index_nz (i : int) : 'a index_nz =
  35. Obj.magic i
  36. let index (t : 'a array) (i : int) : 'a index =
  37. if i <= 0 || i - 1 >= Array.length t then assert false;
  38. magic_index i
  39. let index_opt t i =
  40. if i = 0 then
  41. None
  42. else
  43. Some (index t i)
  44. let index_nz (t : 'a array) (i : int) : 'a index_nz =
  45. if i < 0 || i >= Array.length t then assert false;
  46. Obj.magic i
  47. let index_int (i : 'a index) =
  48. (Obj.magic i : int)
  49. let index_nz_int (i : 'a index_nz) =
  50. (Obj.magic i : int)
  51. let iget (t : 'a array) (i : 'a index) : 'a =
  52. t.(index_int i - 1)
  53. let no_nz (i : 'a index_nz) : 'a index =
  54. Obj.magic ((Obj.magic i) + 1)
  55. (* ************************************************************************ *)
  56. (* LENGTH *)
  57. let as3_empty_index ctx =
  58. let empty_index = ref 0 in
  59. try
  60. Array.iteri (fun i x -> if x = "" then begin empty_index := (i + 1); raise Exit; end) ctx.as3_idents;
  61. if parse_idents then assert false;
  62. magic_index 0
  63. with Exit ->
  64. index ctx.as3_idents (!empty_index)
  65. let as3_int_length i =
  66. if Int32.compare (Int32.shift_right_logical i 28) 0l > 0 then
  67. 5
  68. else if Int32.compare (Int32.shift_right i 21) 0l > 0 then
  69. 4
  70. else if Int32.compare (Int32.shift_right i 14) 0l > 0 then
  71. 3
  72. else if Int32.compare (Int32.shift_right i 7) 0l > 0 then
  73. 2
  74. else
  75. 1
  76. let as3_uint_length i =
  77. as3_int_length i
  78. let sum f l =
  79. List.fold_left (fun acc n -> acc + f n) 0 l
  80. let int_length i =
  81. as3_int_length (Int32.of_int i)
  82. let idx_length i =
  83. int_length (index_int i)
  84. let idx_length_nz i =
  85. int_length (index_nz_int i)
  86. let idx_opt_length = function
  87. | None -> int_length 0
  88. | Some i -> idx_length i
  89. let as3_ident_length s =
  90. let n = String.length s in
  91. n + int_length n
  92. let as3_namespace_length ei = function
  93. | A3NStaticProtected o
  94. | A3NPrivate o ->
  95. 1 + (match o with None -> int_length 0 | Some n -> idx_length n)
  96. | A3NPublic o
  97. | A3NInternal o ->
  98. 1 + idx_length (match o with None -> ei | Some n -> n)
  99. | A3NExplicit n
  100. | A3NNamespace n
  101. | A3NProtected n ->
  102. 1 + idx_length n
  103. let as3_ns_set_length l =
  104. int_length (List.length l) + sum idx_length l
  105. let rec as3_name_length t =
  106. 1 +
  107. match t with
  108. | A3MMultiName (id,r) ->
  109. idx_opt_length id + idx_length r
  110. | A3MName (id,r) ->
  111. idx_length r + idx_length id
  112. | A3MNSAny (id) ->
  113. int_length 0 + idx_length id
  114. | A3MAny ->
  115. int_length 0 + int_length 0
  116. | A3MRuntimeName i ->
  117. idx_length i
  118. | A3MRuntimeNameLate ->
  119. 0
  120. | A3MMultiNameLate idx ->
  121. idx_length idx
  122. | A3MAttrib n ->
  123. as3_name_length n - 1
  124. | A3MParams (id,pl) ->
  125. idx_length id + 1 + (sum idx_length pl)
  126. let as3_value_length extra = function
  127. | A3VNone -> if extra then 2 else 1
  128. | A3VNull | A3VBool _ -> 2
  129. | A3VString s -> 1 + idx_length s
  130. | A3VInt s -> 1 + idx_length s
  131. | A3VUInt s -> 1 + idx_length s
  132. | A3VFloat s -> 1 + idx_length s
  133. | A3VNamespace (_,s) -> 1 + idx_length s
  134. let as3_method_type_length m =
  135. 1 +
  136. idx_opt_length m.mt3_ret +
  137. sum idx_opt_length m.mt3_args +
  138. idx_opt_length m.mt3_debug_name +
  139. 1 +
  140. (match m.mt3_dparams with None -> 0 | Some l -> 1 + sum (as3_value_length true) l) +
  141. (match m.mt3_pnames with None -> 0 | Some l -> sum idx_opt_length l)
  142. let list_length f l =
  143. match Array.length l with
  144. | 0 -> int_length 0
  145. | n ->
  146. Array.fold_left (fun acc x -> acc + f x) (int_length (n + 1)) l
  147. let list2_length f l =
  148. Array.fold_left (fun acc x -> acc + f x) (int_length (Array.length l)) l
  149. let as3_field_length f =
  150. idx_length f.f3_name +
  151. 1 +
  152. int_length f.f3_slot +
  153. (match f.f3_kind with
  154. | A3FMethod m ->
  155. idx_length_nz m.m3_type
  156. | A3FClass c ->
  157. idx_length_nz c
  158. | A3FFunction id ->
  159. idx_length_nz id
  160. | A3FVar v ->
  161. idx_opt_length v.v3_type + as3_value_length false v.v3_value) +
  162. match f.f3_metas with
  163. | None -> 0
  164. | Some l -> list2_length idx_length_nz l
  165. let as3_class_length c =
  166. idx_length c.cl3_name +
  167. idx_opt_length c.cl3_super +
  168. 1 +
  169. (match c.cl3_namespace with None -> 0 | Some r -> idx_length r) +
  170. list2_length idx_length c.cl3_implements +
  171. idx_length_nz c.cl3_construct +
  172. list2_length as3_field_length c.cl3_fields
  173. let as3_static_length s =
  174. idx_length_nz s.st3_method +
  175. list2_length as3_field_length s.st3_fields
  176. let as3_metadata_length m =
  177. idx_length m.meta3_name +
  178. list2_length (fun (i1,i2) -> idx_opt_length i1 + idx_length i2) m.meta3_data
  179. let as3_try_catch_length t =
  180. int_length t.tc3_start +
  181. int_length t.tc3_end +
  182. int_length t.tc3_handle +
  183. idx_opt_length t.tc3_type +
  184. idx_opt_length t.tc3_name
  185. let as3_function_length f =
  186. let clen = MultiArray.fold_left (fun acc op -> acc + As3code.length op) 0 f.fun3_code in
  187. idx_length_nz f.fun3_id +
  188. int_length f.fun3_stack_size +
  189. int_length f.fun3_nregs +
  190. int_length f.fun3_init_scope +
  191. int_length f.fun3_max_scope +
  192. int_length clen +
  193. clen +
  194. list2_length as3_try_catch_length f.fun3_trys +
  195. list2_length as3_field_length f.fun3_locals
  196. let as3_length ctx =
  197. let ei = as3_empty_index ctx in
  198. String.length ctx.as3_unknown +
  199. 4 +
  200. list_length as3_int_length ctx.as3_ints +
  201. list_length as3_uint_length ctx.as3_uints +
  202. list_length (fun _ -> 8) ctx.as3_floats
  203. + if parse_idents then list_length as3_ident_length ctx.as3_idents
  204. + if parse_namespaces then list_length (as3_namespace_length ei) ctx.as3_namespaces
  205. + if parse_ns_sets then list_length as3_ns_set_length ctx.as3_nsets
  206. + if parse_names then list_length as3_name_length ctx.as3_names
  207. + if parse_mtypes then list2_length as3_method_type_length ctx.as3_method_types
  208. + if parse_metadata then list2_length as3_metadata_length ctx.as3_metadatas
  209. + if parse_classes then list2_length as3_class_length ctx.as3_classes
  210. + if parse_statics then Array.fold_left (fun acc x -> acc + as3_static_length x) 0 ctx.as3_statics
  211. + if parse_inits then list2_length as3_static_length ctx.as3_inits
  212. + if parse_functions then list2_length as3_function_length ctx.as3_functions
  213. else 0 else 0 else 0 else 0 else 0 else 0 else 0 else 0 else 0 else 0
  214. (* ************************************************************************ *)
  215. (* PARSING *)
  216. let read_as3_int ch =
  217. let a = IO.read_byte ch in
  218. if a < 128 then
  219. Int32.of_int a
  220. else
  221. let a = a land 127 in
  222. let b = IO.read_byte ch in
  223. if b < 128 then
  224. Int32.of_int ((b lsl 7) lor a)
  225. else
  226. let b = b land 127 in
  227. let c = IO.read_byte ch in
  228. if c < 128 then
  229. Int32.of_int ((c lsl 14) lor (b lsl 7) lor a)
  230. else
  231. let c = c land 127 in
  232. let d = IO.read_byte ch in
  233. if d < 128 then
  234. Int32.of_int ((d lsl 21) lor (c lsl 14) lor (b lsl 7) lor a)
  235. else
  236. let d = d land 127 in
  237. let e = IO.read_byte ch in
  238. if e > 15 then assert false;
  239. let small = Int32.of_int ((d lsl 21) lor (c lsl 14) lor (b lsl 7) lor a) in
  240. let big = Int32.shift_left (Int32.of_int e) 28 in
  241. Int32.logor big small
  242. let read_as3_uint ch =
  243. read_as3_int ch
  244. let read_int ch =
  245. Int32.to_int (read_as3_int ch)
  246. let read_ident ch =
  247. IO.nread_string ch (read_int ch)
  248. let read_namespace idents ch =
  249. let k = IO.read_byte ch in
  250. let p = index_opt idents (read_int ch) in
  251. match k with
  252. | 0x05 ->
  253. A3NPrivate p
  254. | 0x08 ->
  255. (match p with
  256. | None -> assert false
  257. | Some idx -> A3NNamespace idx)
  258. | 0x16 ->
  259. (match p with
  260. | None -> assert false
  261. | Some p when iget idents p = "" -> A3NPublic None
  262. | _ -> A3NPublic p)
  263. | 0x17 ->
  264. (match p with
  265. | None -> assert false
  266. | Some p when iget idents p = "" -> A3NInternal None
  267. | _ -> A3NInternal p)
  268. | 0x18 ->
  269. (match p with
  270. | None -> assert false
  271. | Some idx -> A3NProtected idx)
  272. | 0x19 ->
  273. (match p with
  274. | None -> assert false
  275. | Some idx -> A3NExplicit idx)
  276. | 0x1A ->
  277. A3NStaticProtected p
  278. | _ ->
  279. assert false
  280. let read_ns_set namespaces ch =
  281. let rec loop n =
  282. if n = 0 then
  283. []
  284. else
  285. let r = index namespaces (read_int ch) in
  286. r :: loop (n - 1)
  287. in
  288. loop (IO.read_byte ch)
  289. let rec read_name ctx ?k ch =
  290. let k = (match k with None -> IO.read_byte ch | Some k -> k) in
  291. match k with
  292. | 0x07 ->
  293. let i = read_int ch in
  294. let j = read_int ch in
  295. if i = 0 && j = 0 then
  296. A3MAny
  297. else if i = 0 && j <> 0 then
  298. let id = index ctx.as3_idents j in
  299. A3MNSAny(id)
  300. else
  301. let ns = index ctx.as3_namespaces i in
  302. let id = index ctx.as3_idents j in
  303. (* both ns and id can be 0 <=> '*' *)
  304. A3MName (id,ns)
  305. | 0x09 ->
  306. let id = index_opt ctx.as3_idents (read_int ch) in
  307. let ns = index ctx.as3_nsets (read_int ch) in
  308. A3MMultiName (id,ns)
  309. | 0x0D ->
  310. A3MAttrib (read_name ctx ~k:0x07 ch)
  311. | 0x0E ->
  312. A3MAttrib (read_name ctx ~k:0x09 ch)
  313. | 0x0F ->
  314. let id = index ctx.as3_idents (read_int ch) in
  315. A3MRuntimeName id
  316. | 0x10 ->
  317. A3MAttrib (read_name ctx ~k:0x0F ch)
  318. | 0x11 ->
  319. A3MRuntimeNameLate
  320. | 0x12 ->
  321. A3MAttrib (read_name ctx ~k:0x11 ch)
  322. | 0x1B ->
  323. let ns = index ctx.as3_nsets (read_int ch) in
  324. A3MMultiNameLate ns
  325. | 0x1C ->
  326. A3MAttrib (read_name ctx ~k:0x1B ch)
  327. | 0x1D ->
  328. let rec loop n =
  329. if n = 0 then
  330. []
  331. else
  332. let name = magic_index (read_int ch) in
  333. name :: loop (n - 1)
  334. in
  335. let id = magic_index (read_int ch) in
  336. A3MParams (id,loop (IO.read_byte ch))
  337. | n ->
  338. prerr_endline (string_of_int n);
  339. assert false
  340. let read_value ctx ch extra =
  341. let idx = read_int ch in
  342. if idx = 0 then begin
  343. if extra && IO.read_byte ch <> 0 then assert false;
  344. A3VNone
  345. end else match IO.read_byte ch with
  346. | 0x01 ->
  347. A3VString (index ctx.as3_idents idx)
  348. | 0x03 ->
  349. A3VInt (index ctx.as3_ints idx)
  350. | 0x04 ->
  351. A3VUInt (index ctx.as3_uints idx)
  352. | 0x06 ->
  353. A3VFloat (index ctx.as3_floats idx)
  354. | 0x08 | 0x16 | 0x17 | 0x18 | 0x19 | 0x1A | 0x05 as n->
  355. A3VNamespace (n,index ctx.as3_namespaces idx)
  356. | 0x0A ->
  357. if idx <> 0x0A then assert false;
  358. A3VBool false
  359. | 0x0B ->
  360. if idx <> 0x0B then assert false;
  361. A3VBool true
  362. | 0x0C ->
  363. if idx <> 0x0C then assert false;
  364. A3VNull
  365. | _ ->
  366. assert false
  367. let read_method_type ctx ch =
  368. let nargs = IO.read_byte ch in
  369. let tret = index_opt ctx.as3_names (read_int ch) in
  370. let targs = Array.to_list (Array.init nargs (fun _ -> index_opt ctx.as3_names (read_int ch))) in
  371. let dname = index_opt ctx.as3_idents (read_int ch) in
  372. let flags = IO.read_byte ch in
  373. let dparams = (if flags land 0x08 <> 0 then
  374. Some (Array.to_list (Array.init (IO.read_byte ch) (fun _ -> read_value ctx ch true)))
  375. else
  376. None
  377. ) in
  378. let pnames = (if flags land 0x80 <> 0 then
  379. Some (Array.to_list (Array.init nargs (fun _ -> index_opt ctx.as3_idents (read_int ch))))
  380. else
  381. None
  382. ) in
  383. {
  384. mt3_ret = tret;
  385. mt3_args = targs;
  386. mt3_var_args = flags land 0x04 <> 0;
  387. mt3_native = flags land 0x20 <> 0;
  388. mt3_new_block = flags land 0x02 <> 0;
  389. mt3_debug_name = dname;
  390. mt3_dparams = dparams;
  391. mt3_pnames = pnames;
  392. mt3_arguments_defined = flags land 0x01 <> 0;
  393. mt3_uses_dxns = flags land 0x40 <> 0;
  394. mt3_unused_flag = flags land 0x10 <> 0;
  395. }
  396. let read_list ch f =
  397. match read_int ch with
  398. | 0 -> [||]
  399. | n -> Array.init (n - 1) (fun _ -> f ch)
  400. let read_list2 ch f =
  401. Array.init (read_int ch) (fun _ -> f ch)
  402. let read_field ctx ch =
  403. let name = index ctx.as3_names (read_int ch) in
  404. let kind = IO.read_byte ch in
  405. let has_meta = kind land 0x40 <> 0 in
  406. let slot = read_int ch in
  407. let kind = (match kind land 0xF with
  408. | 0x00 | 0x06 as kind ->
  409. let t = index_opt ctx.as3_names (read_int ch) in
  410. let value = read_value ctx ch false in
  411. A3FVar {
  412. v3_type = t;
  413. v3_value = value;
  414. v3_const = kind = 0x06;
  415. }
  416. | 0x02
  417. | 0x03
  418. | 0x01 ->
  419. let meth = index_nz ctx.as3_method_types (read_int ch) in
  420. let final = kind land 0x10 <> 0 in
  421. let override = kind land 0x20 <> 0 in
  422. A3FMethod {
  423. m3_type = meth;
  424. m3_final = final;
  425. m3_override = override;
  426. m3_kind = (match kind land 0xF with 0x01 -> MK3Normal | 0x02 -> MK3Getter | 0x03 -> MK3Setter | _ -> assert false);
  427. }
  428. | 0x04 ->
  429. let c = index_nz ctx.as3_classes (read_int ch) in
  430. A3FClass c
  431. | 0x05 ->
  432. let f = index_nz ctx.as3_method_types (read_int ch) in
  433. A3FFunction f
  434. | _ ->
  435. assert false
  436. ) in
  437. let metas = (if has_meta then
  438. Some (read_list2 ch (fun _ -> index_nz ctx.as3_metadatas (read_int ch)))
  439. else
  440. None
  441. ) in
  442. {
  443. f3_name = name;
  444. f3_slot = slot;
  445. f3_kind = kind;
  446. f3_metas = metas;
  447. }
  448. let read_class ctx ch =
  449. let name = index ctx.as3_names (read_int ch) in
  450. let csuper = index_opt ctx.as3_names (read_int ch) in
  451. let flags = IO.read_byte ch in
  452. let namespace =
  453. if flags land 8 <> 0 then
  454. let r = index ctx.as3_namespaces (read_int ch) in
  455. Some r
  456. else
  457. None
  458. in
  459. let impls = read_list2 ch (fun _ -> index ctx.as3_names (read_int ch)) in
  460. let construct = index_nz ctx.as3_method_types (read_int ch) in
  461. let fields = read_list2 ch (read_field ctx) in
  462. {
  463. cl3_name = name;
  464. cl3_super = csuper;
  465. cl3_sealed = (flags land 1) <> 0;
  466. cl3_final = (flags land 2) <> 0;
  467. cl3_interface = (flags land 4) <> 0;
  468. cl3_namespace = namespace;
  469. cl3_implements = impls;
  470. cl3_construct = construct;
  471. cl3_fields = fields;
  472. }
  473. let read_static ctx ch =
  474. let meth = index_nz ctx.as3_method_types (read_int ch) in
  475. let fields = read_list2 ch (read_field ctx) in
  476. {
  477. st3_method = meth;
  478. st3_fields = fields;
  479. }
  480. let read_metadata ctx ch =
  481. let name = index ctx.as3_idents (read_int ch) in
  482. let data = read_list2 ch (fun _ -> index_opt ctx.as3_idents (read_int ch)) in
  483. let data = Array.map (fun i1 -> i1 , index ctx.as3_idents (read_int ch)) data in
  484. {
  485. meta3_name = name;
  486. meta3_data = data;
  487. }
  488. let read_try_catch ctx ch =
  489. let start = read_int ch in
  490. let pend = read_int ch in
  491. let handle = read_int ch in
  492. let t = index_opt ctx.as3_names (read_int ch) in
  493. let name = index_opt ctx.as3_names (read_int ch) in
  494. {
  495. tc3_start = start;
  496. tc3_end = pend;
  497. tc3_handle = handle;
  498. tc3_type = t;
  499. tc3_name = name;
  500. }
  501. let read_function ctx ch =
  502. let id = index_nz ctx.as3_method_types (read_int ch) in
  503. let ss = read_int ch in
  504. let nregs = read_int ch in
  505. let init_scope = read_int ch in
  506. let max_scope = read_int ch in
  507. let size = read_int ch in
  508. let code = if parse_bytecode then As3code.parse ch size else MultiArray.init size (fun _ -> A3Unk (IO.read ch)) in
  509. let trys = read_list2 ch (read_try_catch ctx) in
  510. let local_funs = read_list2 ch (read_field ctx) in
  511. {
  512. fun3_id = id;
  513. fun3_stack_size = ss;
  514. fun3_nregs = nregs;
  515. fun3_init_scope = init_scope;
  516. fun3_max_scope = max_scope;
  517. fun3_code = code;
  518. fun3_trys = trys;
  519. fun3_locals = local_funs;
  520. }
  521. let header_magic = 0x002E0010
  522. let parse ch len =
  523. let ch, get_pos = IO.pos_in ch in
  524. if IO.read_i32 ch <> header_magic then assert false;
  525. let ints = read_list ch read_as3_int in
  526. let uints = read_list ch read_as3_uint in
  527. let floats = read_list ch IO.read_double in
  528. let idents = (if parse_idents then read_list ch read_ident else [||]) in
  529. let idents = (if parse_idents then begin if ExtArray.Array.exists (fun i -> i="") idents then idents else Array.append idents [|""|] end else [||]) in
  530. let namespaces = (if parse_namespaces then read_list ch (read_namespace idents) else [||]) in
  531. let nsets = (if parse_ns_sets then read_list ch (read_ns_set namespaces) else [||]) in
  532. let ctx = {
  533. as3_ints = ints;
  534. as3_uints = uints;
  535. as3_floats = floats;
  536. as3_idents = idents;
  537. as3_namespaces = namespaces;
  538. as3_nsets = nsets;
  539. as3_names = [||];
  540. as3_method_types = [||];
  541. as3_metadatas = [||];
  542. as3_classes = [||];
  543. as3_statics = [||];
  544. as3_inits = [||];
  545. as3_functions = [||];
  546. as3_unknown = "";
  547. } in
  548. if parse_names then ctx.as3_names <- read_list ch (read_name ctx);
  549. if parse_mtypes then ctx.as3_method_types <- read_list2 ch (read_method_type ctx);
  550. if parse_metadata then ctx.as3_metadatas <- read_list2 ch (read_metadata ctx);
  551. if parse_classes then ctx.as3_classes <- read_list2 ch (read_class ctx);
  552. if parse_statics then ctx.as3_statics <- Array.map (fun _ -> read_static ctx ch) ctx.as3_classes;
  553. if parse_inits then ctx.as3_inits <- read_list2 ch (read_static ctx);
  554. if parse_functions then ctx.as3_functions <- read_list2 ch (read_function ctx);
  555. ctx.as3_unknown <- IO.really_nread_string ch (len - (get_pos()));
  556. if parse_functions && String.length ctx.as3_unknown <> 0 then assert false;
  557. (* let len2 = as3_length ctx in
  558. if len2 <> len then begin Printf.printf "%d != %d" len len2; assert false; end;
  559. *) ctx
  560. (* ************************************************************************ *)
  561. (* WRITING *)
  562. let write_as3_int ch i =
  563. let e = Int32.to_int (Int32.shift_right_logical i 28) in
  564. let d = Int32.to_int (Int32.shift_right i 21) land 0x7F in
  565. let c = Int32.to_int (Int32.shift_right i 14) land 0x7F in
  566. let b = Int32.to_int (Int32.shift_right i 7) land 0x7F in
  567. let a = Int32.to_int (Int32.logand i 0x7Fl) in
  568. if b <> 0 || c <> 0 || d <> 0 || e <> 0 then begin
  569. IO.write_byte ch (a lor 0x80);
  570. if c <> 0 || d <> 0 || e <> 0 then begin
  571. IO.write_byte ch (b lor 0x80);
  572. if d <> 0 || e <> 0 then begin
  573. IO.write_byte ch (c lor 0x80);
  574. if e <> 0 then begin
  575. IO.write_byte ch (d lor 0x80);
  576. IO.write_byte ch e;
  577. end else
  578. IO.write_byte ch d;
  579. end else
  580. IO.write_byte ch c;
  581. end else
  582. IO.write_byte ch b;
  583. end else
  584. IO.write_byte ch a
  585. let write_as3_uint = write_as3_int
  586. let write_int ch i =
  587. write_as3_int ch (Int32.of_int i)
  588. let write_index ch n =
  589. write_int ch (index_int n)
  590. let write_index_nz ch n =
  591. write_int ch (index_nz_int n)
  592. let write_index_opt ch = function
  593. | None -> write_int ch 0
  594. | Some n -> write_index ch n
  595. let write_as3_ident ch id =
  596. write_int ch (String.length id);
  597. IO.nwrite_string ch id
  598. let write_namespace empty_index ch = function
  599. | A3NPrivate n ->
  600. IO.write_byte ch 0x05;
  601. (match n with
  602. | None -> write_int ch 0
  603. | Some n -> write_index ch n);
  604. | A3NPublic n ->
  605. IO.write_byte ch 0x16;
  606. (match n with
  607. | None -> write_index ch empty_index
  608. | Some n -> write_index ch n);
  609. | A3NInternal n ->
  610. IO.write_byte ch 0x17;
  611. (match n with
  612. | None -> write_index ch empty_index
  613. | Some n -> write_index ch n);
  614. | A3NProtected n ->
  615. IO.write_byte ch 0x18;
  616. write_index ch n
  617. | A3NNamespace n ->
  618. IO.write_byte ch 0x08;
  619. write_index ch n
  620. | A3NExplicit n ->
  621. IO.write_byte ch 0x19;
  622. write_index ch n
  623. | A3NStaticProtected n ->
  624. IO.write_byte ch 0x1A;
  625. (match n with
  626. | None -> write_int ch 0
  627. | Some n -> write_index ch n)
  628. let write_rights ch l =
  629. IO.write_byte ch (List.length l);
  630. List.iter (write_index ch) l
  631. let rec write_name ch ?k x =
  632. let b n = match k with None -> n | Some v -> v in
  633. match x with
  634. | A3MMultiName (id,r) ->
  635. IO.write_byte ch (b 0x09);
  636. write_index_opt ch id;
  637. write_index ch r;
  638. | A3MName (id,r) ->
  639. IO.write_byte ch (b 0x07);
  640. write_index ch r;
  641. write_index ch id
  642. | A3MNSAny(id) ->
  643. IO.write_byte ch (b 0x07);
  644. write_int ch 0;
  645. write_index ch id;
  646. | A3MAny ->
  647. IO.write_byte ch (b 0x07);
  648. write_int ch 0;
  649. write_int ch 0;
  650. | A3MRuntimeName i ->
  651. IO.write_byte ch (b 0x0F);
  652. write_index ch i
  653. | A3MRuntimeNameLate ->
  654. IO.write_byte ch (b 0x11);
  655. | A3MMultiNameLate id ->
  656. IO.write_byte ch (b 0x1B);
  657. write_index ch id
  658. | A3MAttrib n ->
  659. write_name ch ~k:(match n with
  660. | A3MName _ | A3MNSAny _ | A3MAny -> 0x0D
  661. | A3MMultiName _ -> 0x0E
  662. | A3MRuntimeName _ -> 0x10
  663. | A3MRuntimeNameLate -> 0x12
  664. | A3MMultiNameLate _ -> 0x1C
  665. | A3MAttrib _ | A3MParams _ -> assert false
  666. ) n
  667. | A3MParams (id,pl) ->
  668. IO.write_byte ch (b 0x1D);
  669. write_index ch id;
  670. IO.write_byte ch (List.length pl);
  671. List.iter (write_index ch) pl
  672. let write_value ch extra v =
  673. match v with
  674. | A3VNone ->
  675. IO.write_byte ch 0x00;
  676. if extra then IO.write_byte ch 0x00;
  677. | A3VNull ->
  678. IO.write_byte ch 0x0C;
  679. IO.write_byte ch 0x0C;
  680. | A3VBool b ->
  681. IO.write_byte ch (if b then 0x0B else 0x0A);
  682. IO.write_byte ch (if b then 0x0B else 0x0A);
  683. | A3VString s ->
  684. write_index ch s;
  685. IO.write_byte ch 0x01;
  686. | A3VInt s ->
  687. write_index ch s;
  688. IO.write_byte ch 0x03;
  689. | A3VUInt s ->
  690. write_index ch s;
  691. IO.write_byte ch 0x04;
  692. | A3VFloat s ->
  693. write_index ch s;
  694. IO.write_byte ch 0x06
  695. | A3VNamespace (n,s) ->
  696. write_index ch s;
  697. IO.write_byte ch n
  698. let write_method_type ch m =
  699. let nargs = List.length m.mt3_args in
  700. IO.write_byte ch nargs;
  701. write_index_opt ch m.mt3_ret;
  702. List.iter (write_index_opt ch) m.mt3_args;
  703. write_index_opt ch m.mt3_debug_name;
  704. let flags =
  705. (if m.mt3_arguments_defined then 0x01 else 0) lor
  706. (if m.mt3_new_block then 0x02 else 0) lor
  707. (if m.mt3_var_args then 0x04 else 0) lor
  708. (if m.mt3_dparams <> None then 0x08 else 0) lor
  709. (if m.mt3_unused_flag then 0x10 else 0) lor
  710. (if m.mt3_native then 0x20 else 0) lor
  711. (if m.mt3_uses_dxns then 0x40 else 0) lor
  712. (if m.mt3_pnames <> None then 0x80 else 0)
  713. in
  714. IO.write_byte ch flags;
  715. (match m.mt3_dparams with
  716. | None -> ()
  717. | Some l ->
  718. IO.write_byte ch (List.length l);
  719. List.iter (write_value ch true) l);
  720. match m.mt3_pnames with
  721. | None -> ()
  722. | Some l ->
  723. if List.length l <> nargs then assert false;
  724. List.iter (write_index_opt ch) l
  725. let write_list ch f l =
  726. match Array.length l with
  727. | 0 -> IO.write_byte ch 0
  728. | n ->
  729. write_int ch (n + 1);
  730. Array.iter (f ch) l
  731. let write_list2 ch f l =
  732. write_int ch (Array.length l);
  733. Array.iter (f ch) l
  734. let write_field ch f =
  735. write_index ch f.f3_name;
  736. let flags = (if f.f3_metas <> None then 0x40 else 0) in
  737. (match f.f3_kind with
  738. | A3FMethod m ->
  739. let base = (match m.m3_kind with MK3Normal -> 0x01 | MK3Getter -> 0x02 | MK3Setter -> 0x03) in
  740. let flags = flags lor (if m.m3_final then 0x10 else 0) lor (if m.m3_override then 0x20 else 0) in
  741. IO.write_byte ch (base lor flags);
  742. write_int ch f.f3_slot;
  743. write_index_nz ch m.m3_type;
  744. | A3FClass c ->
  745. IO.write_byte ch (0x04 lor flags);
  746. write_int ch f.f3_slot;
  747. write_index_nz ch c
  748. | A3FFunction i ->
  749. IO.write_byte ch (0x05 lor flags);
  750. write_int ch f.f3_slot;
  751. write_index_nz ch i
  752. | A3FVar v ->
  753. IO.write_byte ch (flags lor (if v.v3_const then 0x06 else 0x00));
  754. write_int ch f.f3_slot;
  755. write_index_opt ch v.v3_type;
  756. write_value ch false v.v3_value);
  757. match f.f3_metas with
  758. | None -> ()
  759. | Some l ->
  760. write_list2 ch write_index_nz l
  761. let write_class ch c =
  762. write_index ch c.cl3_name;
  763. write_index_opt ch c.cl3_super;
  764. let flags =
  765. (if c.cl3_sealed then 1 else 0) lor
  766. (if c.cl3_final then 2 else 0) lor
  767. (if c.cl3_interface then 4 else 0) lor
  768. (if c.cl3_namespace <> None then 8 else 0)
  769. in
  770. IO.write_byte ch flags;
  771. (match c.cl3_namespace with
  772. | None -> ()
  773. | Some r -> write_index ch r);
  774. write_list2 ch write_index c.cl3_implements;
  775. write_index_nz ch c.cl3_construct;
  776. write_list2 ch write_field c.cl3_fields
  777. let write_static ch s =
  778. write_index_nz ch s.st3_method;
  779. write_list2 ch write_field s.st3_fields
  780. let write_metadata ch m =
  781. write_index ch m.meta3_name;
  782. write_list2 ch (fun _ (i1,_) -> write_index_opt ch i1) m.meta3_data;
  783. Array.iter (fun (_,i2) -> write_index ch i2) m.meta3_data
  784. let write_try_catch ch t =
  785. write_int ch t.tc3_start;
  786. write_int ch t.tc3_end;
  787. write_int ch t.tc3_handle;
  788. write_index_opt ch t.tc3_type;
  789. write_index_opt ch t.tc3_name
  790. let write_function ch f =
  791. write_index_nz ch f.fun3_id;
  792. write_int ch f.fun3_stack_size;
  793. write_int ch f.fun3_nregs;
  794. write_int ch f.fun3_init_scope;
  795. write_int ch f.fun3_max_scope;
  796. let clen = MultiArray.fold_left (fun acc op -> acc + As3code.length op) 0 f.fun3_code in
  797. write_int ch clen;
  798. MultiArray.iter (As3code.write ch) f.fun3_code;
  799. write_list2 ch write_try_catch f.fun3_trys;
  800. write_list2 ch write_field f.fun3_locals
  801. let write ch1 ctx =
  802. let ch = IO.output_strings() in
  803. let empty_index = as3_empty_index ctx in
  804. IO.write_i32 ch header_magic;
  805. write_list ch write_as3_int ctx.as3_ints;
  806. write_list ch write_as3_uint ctx.as3_uints;
  807. write_list ch IO.write_double ctx.as3_floats;
  808. if parse_idents then write_list ch write_as3_ident ctx.as3_idents;
  809. if parse_namespaces then write_list ch (write_namespace empty_index) ctx.as3_namespaces;
  810. if parse_ns_sets then write_list ch write_rights ctx.as3_nsets;
  811. if parse_names then write_list ch (write_name ?k:None) ctx.as3_names;
  812. if parse_mtypes then write_list2 ch write_method_type ctx.as3_method_types;
  813. if parse_metadata then write_list2 ch write_metadata ctx.as3_metadatas;
  814. if parse_classes then write_list2 ch write_class ctx.as3_classes;
  815. if parse_statics then Array.iter (write_static ch) ctx.as3_statics;
  816. if parse_inits then write_list2 ch write_static ctx.as3_inits;
  817. if parse_functions then write_list2 ch write_function ctx.as3_functions;
  818. IO.nwrite_string ch ctx.as3_unknown;
  819. let str = IO.close_out ch in
  820. List.iter (IO.nwrite_string ch1) str
  821. (* ************************************************************************ *)
  822. (* DUMP *)
  823. let dump_code_size = ref true
  824. let ident_str ctx i =
  825. iget ctx.as3_idents i
  826. let namespace_str ctx i =
  827. match iget ctx.as3_namespaces i with
  828. | A3NPrivate None -> "private"
  829. | A3NPrivate (Some n) -> "private:" ^ ident_str ctx n
  830. | A3NPublic None -> "public"
  831. | A3NPublic (Some n) -> "public:" ^ ident_str ctx n
  832. | A3NInternal None -> "internal"
  833. | A3NInternal (Some n) -> "internal:" ^ ident_str ctx n
  834. | A3NProtected n -> "protected:" ^ ident_str ctx n
  835. | A3NExplicit n -> "explicit:" ^ ident_str ctx n
  836. | A3NStaticProtected None -> "static_protected"
  837. | A3NStaticProtected (Some n) -> "static_protectec:" ^ ident_str ctx n
  838. | A3NNamespace n -> "namespace:" ^ ident_str ctx n
  839. let ns_set_str ctx i =
  840. let l = iget ctx.as3_nsets i in
  841. String.concat " " (List.map (fun r -> namespace_str ctx r) l)
  842. let rec name_str ctx kind t =
  843. let rec loop = function
  844. | A3MName (id,r) -> Printf.sprintf "%s %s%s" (namespace_str ctx r) kind (ident_str ctx id)
  845. | A3MNSAny (id) -> Printf.sprintf "%s %s%s" "ANY" kind (ident_str ctx id)
  846. | A3MAny -> "ANY"
  847. | A3MMultiName (id,r) -> Printf.sprintf "[%s %s%s]" (ns_set_str ctx r) kind (match id with None -> "NO" | Some i -> ident_str ctx i)
  848. | A3MRuntimeName id -> Printf.sprintf "'%s'" (ident_str ctx id)
  849. | A3MRuntimeNameLate -> "RTLATE"
  850. | A3MMultiNameLate id -> Printf.sprintf "late:(%s)" (ns_set_str ctx id)
  851. | A3MAttrib n -> "attrib " ^ loop n
  852. | A3MParams (id,pl) -> Printf.sprintf "%s<%s>" (name_str ctx kind id) (String.concat "," (List.map (name_str ctx kind) pl))
  853. in
  854. loop (iget ctx.as3_names t)
  855. let value_str ctx v =
  856. match v with
  857. | A3VNone -> "<none>"
  858. | A3VNull -> "null"
  859. | A3VString s -> "\"" ^ ident_str ctx s ^ "\""
  860. | A3VBool b -> if b then "true" else "false"
  861. | A3VInt s -> Printf.sprintf "%ld" (iget ctx.as3_ints s)
  862. | A3VUInt s -> Printf.sprintf "%ld" (iget ctx.as3_uints s)
  863. | A3VFloat s -> Printf.sprintf "%f" (iget ctx.as3_floats s)
  864. | A3VNamespace (_,s) -> "ns::" ^ namespace_str ctx s
  865. let metadata_str ctx i =
  866. let m = iget ctx.as3_metadatas i in
  867. let data = List.map (fun (i1,i2) -> Printf.sprintf "%s=\"%s\"" (match i1 with None -> "NO" | Some i -> ident_str ctx i) (ident_str ctx i2)) (Array.to_list m.meta3_data) in
  868. Printf.sprintf "%s(%s)" (ident_str ctx m.meta3_name) (String.concat ", " data)
  869. let method_str ?(infos=false) ctx m =
  870. let m = iget ctx.as3_method_types m in
  871. let pcount = ref 0 in
  872. Printf.sprintf "%s(%s%s)%s"
  873. (if m.mt3_native then " native " else "")
  874. (String.concat ", " (List.map (fun a ->
  875. let id = (match m.mt3_pnames with
  876. | None -> "p" ^ string_of_int !pcount
  877. | Some l ->
  878. match List.nth l !pcount with
  879. | None -> "p" ^ string_of_int !pcount
  880. | Some i -> ident_str ctx i
  881. ) in
  882. let p = (match a with None -> id | Some t -> name_str ctx (id ^ " : ") t) in
  883. let p = (match m.mt3_dparams with
  884. | None -> p
  885. | Some l ->
  886. let vargs = List.length m.mt3_args - List.length l in
  887. if !pcount >= vargs then
  888. let v = List.nth l (!pcount - vargs) in
  889. p ^ " = " ^ value_str ctx v
  890. else
  891. p
  892. ) in
  893. incr pcount;
  894. p
  895. ) m.mt3_args))
  896. (if m.mt3_var_args then " ..." else "")
  897. (match m.mt3_ret with None -> "" | Some t -> " : " ^ name_str ctx "" t)
  898. ^ (if infos then begin
  899. let name = (match m.mt3_debug_name with None -> "" | Some idx -> Printf.sprintf " '%s'" (ident_str ctx idx)) in
  900. Printf.sprintf "%s blk:%b args:%b dxns:%b%s" name m.mt3_new_block m.mt3_arguments_defined m.mt3_uses_dxns (if m.mt3_unused_flag then " SPECIAL-FLAG" else "")
  901. end else "")
  902. let dump_field ctx ch stat f =
  903. (* (match f.f3_metas with
  904. | None -> ()
  905. | Some l -> Array.iter (fun i -> IO.printf ch " [%s]\n" (metadata_str ctx (no_nz i))) l);
  906. *) IO.printf ch " ";
  907. if stat then IO.printf ch "static ";
  908. (match f.f3_kind with
  909. | A3FVar v ->
  910. IO.printf ch "%s" (name_str ctx (if v.v3_const then "const " else "var ") f.f3_name);
  911. (match v.v3_type with
  912. | None -> ()
  913. | Some id -> IO.printf ch " : %s" (name_str ctx "" id));
  914. if v.v3_value <> A3VNone then IO.printf ch " = %s" (value_str ctx v.v3_value);
  915. | A3FClass c ->
  916. let c = iget ctx.as3_classes (no_nz c) in
  917. IO.printf ch "%s = %s" (name_str ctx "CLASS " c.cl3_name) (name_str ctx "class " f.f3_name);
  918. | A3FFunction id ->
  919. IO.printf ch "%s = %s" (method_str ~infos:false ctx (no_nz id)) (name_str ctx "method " f.f3_name);
  920. | A3FMethod m ->
  921. if m.m3_final then IO.printf ch "final ";
  922. if m.m3_override then IO.printf ch "override ";
  923. let k = "function " ^ (match m.m3_kind with
  924. | MK3Normal -> ""
  925. | MK3Getter -> "get "
  926. | MK3Setter -> "set "
  927. ) in
  928. IO.printf ch "%s%s #%d" (name_str ctx k f.f3_name) (method_str ctx (no_nz m.m3_type)) (index_nz_int m.m3_type);
  929. );
  930. if f.f3_slot <> 0 then IO.printf ch " = [SLOT:%d]" f.f3_slot;
  931. IO.printf ch ";\n"
  932. let dump_class ctx ch idx c =
  933. let st = if parse_statics then ctx.as3_statics.(idx) else { st3_method = magic_index_nz (-1); st3_fields = [||] } in
  934. if not c.cl3_sealed then IO.printf ch "dynamic ";
  935. if c.cl3_final then IO.printf ch "final ";
  936. (match c.cl3_namespace with
  937. | None -> ()
  938. | Some r -> IO.printf ch "%s " (namespace_str ctx r));
  939. let kind = (if c.cl3_interface then "interface " else "class ") in
  940. IO.printf ch "%s " (name_str ctx kind c.cl3_name);
  941. (match c.cl3_super with
  942. | None -> ()
  943. | Some s -> IO.printf ch "extends %s " (name_str ctx "" s));
  944. (match Array.to_list c.cl3_implements with
  945. | [] -> ()
  946. | l ->
  947. IO.printf ch "implements %s " (String.concat ", " (List.map (fun i -> name_str ctx "" i) l)));
  948. IO.printf ch "{\n";
  949. Array.iter (dump_field ctx ch false) c.cl3_fields;
  950. Array.iter (dump_field ctx ch true) st.st3_fields;
  951. IO.printf ch "} constructor#%d statics#%d\n\n" (index_nz_int c.cl3_construct) (index_nz_int st.st3_method)
  952. let dump_init ctx ch idx s =
  953. IO.printf ch "init #%d {\n" (index_nz_int s.st3_method);
  954. Array.iter (dump_field ctx ch false) s.st3_fields;
  955. IO.printf ch "}\n\n"
  956. let dump_try_catch ctx ch t =
  957. IO.printf ch " try %d %d %d (%s) (%s)\n"
  958. t.tc3_start t.tc3_end t.tc3_handle
  959. (match t.tc3_type with None -> "*" | Some idx -> name_str ctx "" idx)
  960. (match t.tc3_name with None -> "NO" | Some idx -> name_str ctx "" idx)
  961. let dump_function ctx ch idx f =
  962. IO.printf ch "function #%d %s\n" (index_nz_int f.fun3_id) (method_str ~infos:true ctx (no_nz f.fun3_id));
  963. IO.printf ch " stack:%d nregs:%d scope:%d-%d\n" f.fun3_stack_size f.fun3_nregs f.fun3_init_scope f.fun3_max_scope;
  964. Array.iter (dump_field ctx ch false) f.fun3_locals;
  965. Array.iter (dump_try_catch ctx ch) f.fun3_trys;
  966. let pos = ref 0 in
  967. MultiArray.iter (fun op ->
  968. IO.printf ch "%4d %s\n" !pos (As3code.dump ctx op);
  969. if !dump_code_size then pos := !pos + As3code.length op else incr pos;
  970. ) f.fun3_code;
  971. IO.printf ch "\n"
  972. let dump_ident ctx ch idx _ =
  973. IO.printf ch "I%d = %s\n" (idx + 1) (ident_str ctx (index ctx.as3_idents (idx + 1)))
  974. let dump_namespace ctx ch idx _ =
  975. IO.printf ch "N%d = %s\n" (idx + 1) (namespace_str ctx (index ctx.as3_namespaces (idx + 1)))
  976. let dump_ns_set ctx ch idx _ =
  977. IO.printf ch "S%d = %s\n" (idx + 1) (ns_set_str ctx (index ctx.as3_nsets (idx + 1)))
  978. let dump_name ctx ch idx _ =
  979. IO.printf ch "T%d = %s\n" (idx + 1) (name_str ctx "" (index ctx.as3_names (idx + 1)))
  980. let dump_method_type ctx ch idx _ =
  981. IO.printf ch "M%d = %s\n" (idx + 1) (method_str ~infos:true ctx (index ctx.as3_method_types (idx + 1)))
  982. let dump_metadata ctx ch idx _ =
  983. IO.printf ch "D%d = %s\n" (idx + 1) (metadata_str ctx (index ctx.as3_metadatas (idx + 1)))
  984. let dump_int ctx ch idx i =
  985. IO.printf ch "INT %d = 0x%lX\n" (idx + 1) i
  986. let dump_float ctx ch idx f =
  987. IO.printf ch "FLOAT %d = %f\n" (idx + 1) f
  988. let dump ch ctx id =
  989. (match id with
  990. | None -> IO.printf ch "\n---------------- AS3 -------------------------\n\n";
  991. | Some (id,f) -> IO.printf ch "\n---------------- AS3 %s [%d] -----------------\n\n" f id);
  992. (* Array.iteri (dump_int ctx ch) ctx.as3_ints;
  993. Array.iteri (dump_float ctx ch) ctx.as3_floats;
  994. Array.iteri (dump_ident ctx ch) ctx.as3_idents;
  995. IO.printf ch "\n";
  996. Array.iteri (dump_namespace ctx ch) ctx.as3_namespaces;
  997. IO.printf ch "\n";
  998. Array.iteri (dump_ns_set ctx ch) ctx.as3_nsets;
  999. IO.printf ch "\n";
  1000. Array.iteri (dump_name ctx ch) ctx.as3_names;
  1001. IO.printf ch "\n"; *)
  1002. (* Array.iteri (dump_metadata ctx ch) ctx.as3_metadatas; *)
  1003. Array.iteri (dump_class ctx ch) ctx.as3_classes;
  1004. Array.iteri (dump_init ctx ch) ctx.as3_inits;
  1005. Array.iteri (dump_function ctx ch) ctx.as3_functions;
  1006. IO.printf ch "\n"
  1007. ;;
  1008. As3code.f_int_length := int_length;
  1009. As3code.f_int_read := read_int;
  1010. As3code.f_int_write := write_int;