as3parse.ml 33 KB

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