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)
42 return strdup("--<UNDEFINED_MULTINAME>--");
43 if(m->type==0x07 || m->type==0x0d) {
44 mname = malloc(strlen(m->ns->name)+strlen(m->name)+32);
45 sprintf(mname, "<%s>\0", access2str(m->ns->access));
46 strcat(mname, m->ns->name);
48 strcat(mname, m->name);
49 } else if(m->type==0x0f || m->type==0x10) {
50 mname = strdup(m->name);
51 } else if(m->type==0x11 || m->type==0x12) {
53 } else if(m->type==0x09 || m->type==0x0e) {
54 char*s = namespace_set_to_string(m->namespace_set);
55 mname = malloc(strlen(s)+strlen(m->name)+16);
59 strcat(mname, m->name);
60 } else if(m->type==0x1b || m->type==0x1c) {
61 mname = namespace_set_to_string(m->namespace_set);
66 char* namespace_to_string(namespace_t*ns)
70 if(type==0x08) access = "";
71 else if(type==0x16) access = "Package";
72 else if(type==0x17) access = "PackageInternal";
73 else if(type==0x18) access = "Protected";
74 else if(type==0x19) access = "Explicit";
75 else if(type==0x1A) access = "StaticProtected";
76 else if(type==0x05) access = "Private";
78 fprintf(stderr, "Undefined namespace type %02x\n", type);
81 char*string = malloc(strlen(access)+strlen(ns->name)+3);
82 sprintf(string, "<%s>%s", access, ns->name);
86 char* namespace_set_to_string(namespace_set_t*set)
88 /* TODO: is the order of the namespaces important (does it
89 change the lookup order?). E.g. flex freely shuffles namespaces
91 If the order is not important, we can optimize constant pools by sorting
95 namespace_list_t*lns = set->namespaces;
97 char*s = namespace_to_string(lns->namespace);
102 char*desc = malloc(l+16);
104 lns = set->namespaces;
106 char*s = namespace_to_string(lns->namespace);
118 int pool_register_string(pool_t*pool, const char*s)
120 return array_append_if_new(pool->strings, s, 0);
123 int pool_register_namespace(pool_t*pool, namespace_t*ns)
127 char*name = namespace_to_string(ns);
128 int i = array_append_if_new(pool->namespaces, name, ns);
132 int pool_register_namespace_set(pool_t*pool, namespace_set_t*set)
134 char*name = namespace_set_to_string(set);
135 int i = array_append_if_new(pool->namespace_sets, name, set);
139 int pool_register_multiname(pool_t*pool, multiname_t*n)
143 char*name = multiname_to_string(n);
144 int i =array_append_if_new(pool->multinames, name, n);
148 int pool_register_multiname2(pool_t*pool, char*name)
150 multiname_t*n = multiname_fromstring(name);
151 int i =array_append_if_new(pool->multinames, name, n);
154 int pool_find_namespace(pool_t*pool, namespace_t*ns)
158 char*name = namespace_to_string(ns);
159 int i = array_find(pool->namespaces, name);
161 fprintf(stderr, "Couldn't find namespace \"%s\" %08x in constant pool\n", name, ns);
167 int pool_find_namespace_set(pool_t*pool, namespace_set_t*set)
169 char*name = namespace_set_to_string(set);
170 int i = array_find(pool->namespace_sets, name);
173 fprintf(stderr, "Couldn't find namespace_set \"%s\" in constant pool\n", name);
178 int pool_find_string(pool_t*pool, const char*s)
180 int i = array_find(pool->strings, s);
182 fprintf(stderr, "Couldn't find string \"%s\" in constant pool\n", s);
188 int pool_find_multiname(pool_t*pool, multiname_t*name)
190 char*n = multiname_to_string(name);
191 int i = array_find(pool->multinames, n);
193 fprintf(stderr, "Couldn't find multiname \"%s\" in constant pool\n", n);
199 multiname_t*pool_lookup_multiname(pool_t*pool, int i)
201 multiname_t*m = (multiname_t*)array_getvalue(pool->multinames, i);
205 multiname_t* multiname_fromstring(const char*name2)
209 char*n = strdup(name2);
210 char*p = strstr(n, "::");
211 char*namespace=0,*name=0;
214 fprintf(stderr, "Error: single ':' in name\n");
222 if(strchr(namespace, ':')) {
223 fprintf(stderr, "Error: single ':' in namespace\n");
225 if(strchr(name, ':')) {
226 fprintf(stderr, "Error: single ':' in qualified name\n");
230 multiname_t*m = malloc(sizeof(multiname_t));
231 memset(m, 0, sizeof(multiname_t));
233 m->namespace_set = 0;
245 p->ints = array_new();
246 array_append(p->ints, 0, (void*)(ptroff_t)0);
247 p->uints = array_new();
248 array_append(p->uints, 0, (void*)(ptroff_t)0);
249 p->floats = array_new();
250 array_append(p->floats, 0, 0);
251 p->strings = array_new();
252 array_append(p->strings, "--<UNDEFINED_STRING>--", 0);
253 p->namespaces = array_new();
254 array_append(p->namespaces, "--<UNDEFINED_NAMESPACE>--", 0);
255 p->namespace_sets = array_new();
256 array_append(p->namespace_sets, "--<UNDEFINED_NSSET>--", 0);
257 p->multinames = array_new();
258 array_append(p->multinames, "--<UNDEFINED_MULTINAME>--", 0);
265 void pool_read(pool_t*pool, TAG*tag)
267 int num_ints = swf_GetU30(tag);
268 DEBUG printf("%d ints\n", num_ints);
270 for(t=1;t<num_ints;t++) {
271 S32 v = swf_GetS30(tag);
272 DEBUG printf("int %d) %d\n", t, v);
273 array_append(pool->ints, 0, (void*)(ptroff_t)v);
276 int num_uints = swf_GetU30(tag);
277 DEBUG printf("%d uints\n", num_uints);
278 for(t=1;t<num_uints;t++) {
279 U32 v = swf_GetU30(tag);
280 DEBUG printf("uint %d) %d\n", t, v);
281 array_append(pool->uints, 0, (void*)(ptroff_t)v);
284 int num_floats = swf_GetU30(tag);
285 DEBUG printf("%d floats\n", num_floats);
286 for(t=1;t<num_floats;t++) {
287 double d = swf_GetD64(tag);
288 DEBUG printf("float %d) %f\n", t, d);
289 array_append(pool->floats, 0, 0);
292 int num_strings = swf_GetU30(tag);
293 DEBUG printf("%d strings\n", num_strings);
294 for(t=1;t<num_strings;t++) {
295 int len = swf_GetU30(tag);
296 char*s = malloc(len+1);
297 swf_GetBlock(tag, s, len);
299 array_append(pool->strings, s, 0);
300 DEBUG printf("%d) \"%s\"\n", t, pool->strings->d[t].name);
302 int num_namespaces = swf_GetU30(tag);
303 DEBUG printf("%d namespaces\n", num_namespaces);
304 for(t=1;t<num_namespaces;t++) {
305 U8 type = swf_GetU8(tag);
306 int namenr = swf_GetU30(tag);
307 const char*name = array_getkey(pool->strings, namenr);
308 NEW(namespace_t, ns);
309 memset(ns, 0, sizeof(namespace_t));
311 ns->name = strdup(name);
312 array_append(pool->namespaces, name, ns);
314 int num_sets = swf_GetU30(tag);
315 DEBUG printf("%d namespace sets\n", num_sets);
316 for(t=1;t<num_sets;t++) {
317 int count = swf_GetU30(tag);
320 NEW(namespace_set_t, nsset);
321 for(s=0;s<count;s++) {
322 int nsnr = swf_GetU30(tag);
323 namespace_t*ns = (namespace_t*)array_getvalue(pool->namespaces, nsnr);
324 list_append(nsset->namespaces, ns);
326 char*desc = namespace_set_to_string(nsset);
328 array_append(pool->namespace_sets, desc, nsset);
329 DEBUG printf("set %d) %s\n", t, desc);
332 int num_multinames = swf_GetU30(tag);
333 DEBUG printf("%d multinames\n", num_multinames);
334 for(t=1;t<num_multinames;t++) {
337 m->type = swf_GetU8(tag);
338 if(m->type==0x07 || m->type==0x0d) {
339 int namespace_index = swf_GetU30(tag); // 0 = '*' (any)
340 m->ns = (namespace_t*)array_getvalue(pool->namespaces, namespace_index);
341 int name_index = swf_GetU30(tag);
342 m->name = array_getkey(pool->strings, name_index);
343 } else if(m->type==0x0f || m->type==0x10) {
344 int name_index = swf_GetU30(tag); // 0 = '*' (any name)
345 m->name = array_getkey(pool->strings, name_index);
346 } else if(m->type==0x11 || m->type==0x12) {
347 } else if(m->type==0x09 || m->type==0x0e) {
348 int name_index = swf_GetU30(tag);
349 int namespace_set_index = swf_GetU30(tag);
350 m->name = array_getkey(pool->strings, name_index);
351 m->namespace_set = (namespace_set_t*)array_getvalue(pool->namespace_sets, namespace_set_index);
352 } else if(m->type==0x1b || m->type==0x1c) {
353 int namespace_set_index = swf_GetU30(tag);
354 m->namespace_set = (namespace_set_t*)array_getvalue(pool->namespace_sets, namespace_set_index);
356 printf("can't parse type %d multinames yet\n", m->type);
358 char*mname = multiname_to_string(m);
359 DEBUG printf("multiname %d) %s\n", t, mname);
360 array_append(pool->multinames, mname, m);
365 void pool_destroy(pool_t*pool)
368 array_free(pool->ints);
369 array_free(pool->uints);
370 array_free(pool->floats);
372 for(t=1;t<pool->strings->num;t++) {
373 free((void*)array_getkey(pool->strings, t));
375 array_free(pool->strings);
377 for(t=1;t<pool->namespaces->num;t++) {
378 free(array_getvalue(pool->namespaces, t));
380 array_free(pool->namespaces);
382 for(t=1;t<pool->namespace_sets->num;t++) {
383 namespace_set_t*set = (namespace_set_t*)array_getvalue(pool->namespace_sets, t);
384 list_free(set->namespaces);
387 array_free(pool->namespace_sets);
389 for(t=1;t<pool->multinames->num;t++) {
390 free(array_getvalue(pool->multinames, t));
392 array_free(pool->multinames);