3 Routines for handling Flash2 AVM2 ABC contantpool entries.
5 Extension module for the rfxswf library.
6 Part of the swftools package.
8 Copyright (c) 2008 Matthias Kramm <kramm@quiss.org>
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
26 char* access2str(int type)
28 if(type==0x08) return "";
29 else if(type==0x16) return "package";
30 else if(type==0x17) return "packageinternal";
31 else if(type==0x18) return "protected";
32 else if(type==0x19) return "explicit";
33 else if(type==0x1A) return "staticprotected";
34 else if(type==0x05) return "private";
35 else return "undefined";
38 char* multiname_to_string(multiname_t*m)
41 if(m->type==0x07 || m->type==0x0d) {
42 mname = malloc(strlen(m->ns->name)+strlen(m->name)+32);
43 sprintf(mname, "<%s>\0", access2str(m->ns->access));
44 strcat(mname, m->ns->name);
46 strcat(mname, m->name);
47 } else if(m->type==0x0f || m->type==0x10) {
48 mname = strdup(m->name);
49 } else if(m->type==0x11 || m->type==0x12) {
51 } else if(m->type==0x09 || m->type==0x0e) {
52 char*s = namespace_set_to_string(m->namespace_set);
53 mname = malloc(strlen(s)+strlen(m->name)+16);
57 strcat(mname, m->name);
58 } else if(m->type==0x1b || m->type==0x1c) {
59 mname = namespace_set_to_string(m->namespace_set);
64 char* namespace_to_string(namespace_t*ns)
68 if(type==0x08) access = "";
69 else if(type==0x16) access = "Package";
70 else if(type==0x17) access = "PackageInternal";
71 else if(type==0x18) access = "Protected";
72 else if(type==0x19) access = "Explicit";
73 else if(type==0x1A) access = "StaticProtected";
74 else if(type==0x05) access = "Private";
76 fprintf(stderr, "Undefined namespace type %02x\n", type);
79 char*string = malloc(strlen(access)+strlen(ns->name)+3);
80 sprintf(string, "<%s>%s", access, ns->name);
84 char* namespace_set_to_string(namespace_set_t*set)
86 /* TODO: is the order of the namespaces important (does it
87 change the lookup order?). E.g. flex freely shuffles namespaces
89 If the order is not important, we can optimize constant pools by sorting
93 namespace_list_t*lns = set->namespaces;
95 char*s = namespace_to_string(lns->namespace);
100 char*desc = malloc(l+16);
102 lns = set->namespaces;
104 char*s = namespace_to_string(lns->namespace);
115 int pool_register_string(pool_t*pool, const char*s)
117 return array_append_if_new(pool->strings, s, 0);
120 int pool_register_namespace(pool_t*pool, namespace_t*ns)
124 char*name = namespace_to_string(ns);
125 int i = array_append_if_new(pool->namespaces, name, ns);
129 int pool_register_namespace_set(pool_t*pool, namespace_set_t*set)
131 char*name = namespace_set_to_string(set);
132 int i = array_append_if_new(pool->namespace_sets, name, set);
136 int pool_register_multiname(pool_t*pool, multiname_t*n)
140 char*name = multiname_to_string(n);
141 int i =array_append_if_new(pool->multinames, name, n);
145 int pool_register_multiname2(pool_t*pool, char*name)
147 multiname_t*n = multiname_fromstring(name);
148 int i =array_append_if_new(pool->multinames, name, n);
151 int pool_find_namespace(pool_t*pool, namespace_t*ns)
155 char*name = namespace_to_string(ns);
156 int i = array_find(pool->namespaces, name);
158 fprintf(stderr, "Couldn't find namespace \"%s\" %08x in constant pool\n", name, ns);
164 int pool_find_namespace_set(pool_t*pool, namespace_set_t*set)
166 char*name = namespace_set_to_string(set);
167 int i = array_find(pool->namespace_sets, name);
170 fprintf(stderr, "Couldn't find namespace_set \"%s\" in constant pool\n", name);
175 int pool_find_string(pool_t*pool, const char*s)
177 int i = array_find(pool->strings, s);
179 fprintf(stderr, "Couldn't find string \"%s\" in constant pool\n", s);
185 int pool_find_multiname(pool_t*pool, multiname_t*name)
187 char*n = multiname_to_string(name);
188 int i = array_find(pool->multinames, n);
190 fprintf(stderr, "Couldn't find multiname \"%s\" in constant pool\n", n);
196 multiname_t*pool_lookup_multiname(pool_t*pool, int i)
198 multiname_t*m = (multiname_t*)array_getvalue(pool->multinames, i);
202 multiname_t* multiname_fromstring(const char*name2)
206 char*n = strdup(name2);
207 char*p = strstr(n, "::");
208 char*namespace=0,*name=0;
211 fprintf(stderr, "Error: single ':' in name\n");
219 if(strchr(namespace, ':')) {
220 fprintf(stderr, "Error: single ':' in namespace\n");
222 if(strchr(name, ':')) {
223 fprintf(stderr, "Error: single ':' in qualified name\n");
227 multiname_t*m = malloc(sizeof(multiname_t));
228 memset(m, 0, sizeof(multiname_t));
230 m->namespace_set = 0;
242 p->ints = array_new();
243 array_append(p->ints, 0, (void*)(ptroff_t)0);
244 p->uints = array_new();
245 array_append(p->uints, 0, (void*)(ptroff_t)0);
246 p->floats = array_new();
247 array_append(p->floats, 0, 0);
248 p->strings = array_new();
249 array_append(p->strings, "--<UNDEFINED_STRING>--", 0);
250 p->namespaces = array_new();
251 array_append(p->namespaces, "--<UNDEFINED_NAMESPACE>--", 0);
252 p->namespace_sets = array_new();
253 array_append(p->namespace_sets, "--<UNDEFINED_NSSET>--", 0);
254 p->multinames = array_new();
255 array_append(p->multinames, "--<UNDEFINED_MULTINAME>--", 0);
262 void pool_read(pool_t*pool, TAG*tag)
264 int num_ints = swf_GetU30(tag);
265 DEBUG printf("%d ints\n", num_ints);
267 for(t=1;t<num_ints;t++) {
268 S32 v = swf_GetS30(tag);
269 DEBUG printf("int %d) %d\n", t, v);
270 array_append(pool->ints, 0, (void*)(ptroff_t)v);
273 int num_uints = swf_GetU30(tag);
274 DEBUG printf("%d uints\n", num_uints);
275 for(t=1;t<num_uints;t++) {
276 U32 v = swf_GetU30(tag);
277 DEBUG printf("uint %d) %d\n", t, v);
278 array_append(pool->uints, 0, (void*)(ptroff_t)v);
281 int num_floats = swf_GetU30(tag);
282 DEBUG printf("%d floats\n", num_floats);
283 for(t=1;t<num_floats;t++) {
284 double d = swf_GetD64(tag);
285 DEBUG printf("float %d) %f\n", t, d);
286 array_append(pool->floats, 0, 0);
289 int num_strings = swf_GetU30(tag);
290 DEBUG printf("%d strings\n", num_strings);
291 for(t=1;t<num_strings;t++) {
292 int len = swf_GetU30(tag);
293 char*s = malloc(len+1);
294 swf_GetBlock(tag, s, len);
296 array_append(pool->strings, s, 0);
297 DEBUG printf("%d) \"%s\"\n", t, pool->strings->d[t].name);
299 int num_namespaces = swf_GetU30(tag);
300 DEBUG printf("%d namespaces\n", num_namespaces);
301 for(t=1;t<num_namespaces;t++) {
302 U8 type = swf_GetU8(tag);
303 int namenr = swf_GetU30(tag);
304 const char*name = array_getkey(pool->strings, namenr);
305 NEW(namespace_t, ns);
306 memset(ns, 0, sizeof(namespace_t));
308 ns->name = strdup(name);
309 array_append(pool->namespaces, name, ns);
311 int num_sets = swf_GetU30(tag);
312 DEBUG printf("%d namespace sets\n", num_sets);
313 for(t=1;t<num_sets;t++) {
314 int count = swf_GetU30(tag);
317 NEW(namespace_set_t, nsset);
318 for(s=0;s<count;s++) {
319 int nsnr = swf_GetU30(tag);
320 namespace_t*ns = (namespace_t*)array_getvalue(pool->namespaces, nsnr);
321 list_append(nsset->namespaces, ns);
323 char*desc = namespace_set_to_string(nsset);
325 array_append(pool->namespace_sets, desc, nsset);
326 DEBUG printf("set %d) %s\n", t, desc);
329 int num_multinames = swf_GetU30(tag);
330 DEBUG printf("%d multinames\n", num_multinames);
331 for(t=1;t<num_multinames;t++) {
334 m->type = swf_GetU8(tag);
335 if(m->type==0x07 || m->type==0x0d) {
336 int namespace_index = swf_GetU30(tag);
337 m->ns = (namespace_t*)array_getvalue(pool->namespaces, namespace_index);
338 int name_index = swf_GetU30(tag);
339 m->name = array_getkey(pool->strings, name_index);
340 } else if(m->type==0x0f || m->type==0x10) {
341 int name_index = swf_GetU30(tag);
342 m->name = array_getkey(pool->strings, name_index);
343 } else if(m->type==0x11 || m->type==0x12) {
344 } else if(m->type==0x09 || m->type==0x0e) {
345 int name_index = swf_GetU30(tag);
346 int namespace_set_index = swf_GetU30(tag);
347 m->name = array_getkey(pool->strings, name_index);
348 m->namespace_set = (namespace_set_t*)array_getvalue(pool->namespace_sets, namespace_set_index);
349 } else if(m->type==0x1b || m->type==0x1c) {
350 int namespace_set_index = swf_GetU30(tag);
351 m->namespace_set = (namespace_set_t*)array_getvalue(pool->namespace_sets, namespace_set_index);
353 printf("can't parse type %d multinames yet\n", m->type);
355 char*mname = multiname_to_string(m);
356 DEBUG printf("multiname %d) %s\n", t, mname);
357 array_append(pool->multinames, mname, m);
362 void pool_destroy(pool_t*pool)
365 array_free(pool->ints);
366 array_free(pool->uints);
367 array_free(pool->floats);
369 for(t=1;t<pool->strings->num;t++) {
370 free((void*)array_getkey(pool->strings, t));
372 array_free(pool->strings);
374 for(t=1;t<pool->namespaces->num;t++) {
375 free(array_getvalue(pool->namespaces, t));
377 array_free(pool->namespaces);
379 for(t=1;t<pool->namespace_sets->num;t++) {
380 namespace_set_t*set = (namespace_set_t*)array_getvalue(pool->namespace_sets, t);
381 list_free(set->namespaces);
384 array_free(pool->namespace_sets);
386 for(t=1;t<pool->multinames->num;t++) {
387 free(array_getvalue(pool->multinames, t));
389 array_free(pool->multinames);