From af62622d69d19c801da2a804569fc0d69654ff6e Mon Sep 17 00:00:00 2001 From: kramm Date: Sun, 23 Nov 2008 13:57:20 +0000 Subject: [PATCH] abc constant pool implementation --- lib/as3/pool.c | 390 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ lib/as3/pool.h | 106 +++++++++++++++ 2 files changed, 496 insertions(+) create mode 100644 lib/as3/pool.c create mode 100644 lib/as3/pool.h diff --git a/lib/as3/pool.c b/lib/as3/pool.c new file mode 100644 index 0000000..65e7793 --- /dev/null +++ b/lib/as3/pool.c @@ -0,0 +1,390 @@ +/* pool.c + + Routines for handling Flash2 AVM2 ABC contantpool entries. + + Extension module for the rfxswf library. + Part of the swftools package. + + Copyright (c) 2008 Matthias Kramm + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +#include "pool.h" + +char* access2str(int type) +{ + if(type==0x08) return ""; + else if(type==0x16) return "package"; + else if(type==0x17) return "packageinternal"; + else if(type==0x18) return "protected"; + else if(type==0x19) return "explicit"; + else if(type==0x1A) return "staticprotected"; + else if(type==0x05) return "private"; + else return "undefined"; +} + +char* multiname_to_string(multiname_t*m) +{ + char*mname = 0; + if(m->type==0x07 || m->type==0x0d) { + mname = malloc(strlen(m->ns->name)+strlen(m->name)+32); + sprintf(mname, "<%s>\0", access2str(m->ns->access)); + strcat(mname, m->ns->name); + strcat(mname, "::"); + strcat(mname, m->name); + } else if(m->type==0x0f || m->type==0x10) { + mname = strdup(m->name); + } else if(m->type==0x11 || m->type==0x12) { + mname = strdup(""); + } else if(m->type==0x09 || m->type==0x0e) { + char*s = namespace_set_to_string(m->namespace_set); + mname = malloc(strlen(s)+strlen(m->name)+16); + strcpy(mname, s); + free(s); + strcat(mname, "::"); + strcat(mname, m->name); + } else if(m->type==0x1b || m->type==0x1c) { + mname = namespace_set_to_string(m->namespace_set); + } + return mname; +} + +char* namespace_to_string(namespace_t*ns) +{ + char*access = 0; + U8 type = ns->access; + if(type==0x08) access = ""; + else if(type==0x16) access = "Package"; + else if(type==0x17) access = "PackageInternal"; + else if(type==0x18) access = "Protected"; + else if(type==0x19) access = "Explicit"; + else if(type==0x1A) access = "StaticProtected"; + else if(type==0x05) access = "Private"; + else { + fprintf(stderr, "Undefined namespace type %02x\n", type); + access = "UnknownNS"; + } + char*string = malloc(strlen(access)+strlen(ns->name)+3); + sprintf(string, "<%s>%s", access, ns->name); + return string; +} + +char* namespace_set_to_string(namespace_set_t*set) +{ + /* TODO: is the order of the namespaces important (does it + change the lookup order?). E.g. flex freely shuffles namespaces + around. + If the order is not important, we can optimize constant pools by sorting + the namespaces. + */ + int l = 0; + namespace_list_t*lns = set->namespaces; + while(lns) { + char*s = namespace_to_string(lns->namespace); + l += strlen(s)+1; + free(s); + lns = lns->next; + } + char*desc = malloc(l+16); + strcpy(desc, "{"); + lns = set->namespaces; + while(lns) { + char*s = namespace_to_string(lns->namespace); + strcat(desc, s); + free(s); + strcat(desc, ","); + lns = lns->next; + } + strcat(desc, "}"); + return desc; +} + + +int pool_register_string(pool_t*pool, const char*s) +{ + return array_append_if_new(pool->strings, s, 0); +} + +int pool_register_namespace(pool_t*pool, namespace_t*ns) +{ + if(!ns) + return 0; + char*name = namespace_to_string(ns); + int i = array_append_if_new(pool->namespaces, name, ns); + free(name); + return i; +} +int pool_register_namespace_set(pool_t*pool, namespace_set_t*set) +{ + char*name = namespace_set_to_string(set); + int i = array_append_if_new(pool->namespace_sets, name, set); + free(name); + return i; +} +int pool_register_multiname(pool_t*pool, multiname_t*n) +{ + if(!n) + return 0; + char*name = multiname_to_string(n); + int i =array_append_if_new(pool->multinames, name, n); + free(name); + return i; +} +int pool_register_multiname2(pool_t*pool, char*name) +{ + multiname_t*n = multiname_fromstring(name); + int i =array_append_if_new(pool->multinames, name, n); + return i; +} +int pool_find_namespace(pool_t*pool, namespace_t*ns) +{ + if(!ns) + return 0; + char*name = namespace_to_string(ns); + int i = array_find(pool->namespaces, name); + if(i<0) { + fprintf(stderr, "Couldn't find namespace \"%s\" %08x in constant pool\n", name, ns); + return 0; + } + free(name); + return i; +} +int pool_find_namespace_set(pool_t*pool, namespace_set_t*set) +{ + char*name = namespace_set_to_string(set); + int i = array_find(pool->namespace_sets, name); + free(name); + if(i<0) { + fprintf(stderr, "Couldn't find namespace_set \"%s\" in constant pool\n", name); + return 0; + } + return i; +} +int pool_find_string(pool_t*pool, const char*s) +{ + int i = array_find(pool->strings, s); + if(i<0) { + fprintf(stderr, "Couldn't find string \"%s\" in constant pool\n", s); + *(int*)0=0; + return 0; + } + return i; +} +int pool_find_multiname(pool_t*pool, multiname_t*name) +{ + char*n = multiname_to_string(name); + int i = array_find(pool->multinames, n); + if(i<0) { + fprintf(stderr, "Couldn't find multiname \"%s\" in constant pool\n", n); + return 0; + } + return i; +} + +multiname_t*pool_lookup_multiname(pool_t*pool, int i) +{ + multiname_t*m = (multiname_t*)array_getvalue(pool->multinames, i); + return m; +} + +multiname_t* multiname_fromstring(const char*name2) +{ + if(!name2) + name2 = "::"; + char*n = strdup(name2); + char*p = strstr(n, "::"); + char*namespace=0,*name=0; + if(!p) { + if(strchr(n, ':')) { + fprintf(stderr, "Error: single ':' in name\n"); + } + namespace = ""; + name = n; + } else { + *p = 0; + namespace = n; + name = p+2; + if(strchr(namespace, ':')) { + fprintf(stderr, "Error: single ':' in namespace\n"); + } + if(strchr(name, ':')) { + fprintf(stderr, "Error: single ':' in qualified name\n"); + } + } + + multiname_t*m = malloc(sizeof(multiname_t)); + memset(m, 0, sizeof(multiname_t)); + m->type = QNAME; + m->namespace_set = 0; + NEW(namespace_t,ns); + ns->name= namespace; + m->ns = ns; + m->name = name; + return m; +} + +pool_t*pool_new() +{ + NEW(pool_t, p); + + p->ints = array_new(); + array_append(p->ints, 0, (void*)(ptroff_t)0); + p->uints = array_new(); + array_append(p->uints, 0, (void*)(ptroff_t)0); + p->floats = array_new(); + array_append(p->floats, 0, 0); + p->strings = array_new(); + array_append(p->strings, "----", 0); + p->namespaces = array_new(); + array_append(p->namespaces, "----", 0); + p->namespace_sets = array_new(); + array_append(p->namespace_sets, "----", 0); + p->multinames = array_new(); + array_append(p->multinames, "----", 0); + + return p; +} + +#define DEBUG if(0) + +void pool_read(pool_t*pool, TAG*tag) +{ + int num_ints = swf_GetU30(tag); + DEBUG printf("%d ints\n", num_ints); + int t; + for(t=1;tints, 0, (void*)(ptroff_t)v); + } + + int num_uints = swf_GetU30(tag); + DEBUG printf("%d uints\n", num_uints); + for(t=1;tuints, 0, (void*)(ptroff_t)v); + } + + int num_floats = swf_GetU30(tag); + DEBUG printf("%d floats\n", num_floats); + for(t=1;tfloats, 0, 0); + } + + int num_strings = swf_GetU30(tag); + DEBUG printf("%d strings\n", num_strings); + for(t=1;tstrings, s, 0); + DEBUG printf("%d) \"%s\"\n", t, pool->strings->d[t].name); + } + int num_namespaces = swf_GetU30(tag); + DEBUG printf("%d namespaces\n", num_namespaces); + for(t=1;tstrings, namenr); + NEW(namespace_t, ns); + memset(ns, 0, sizeof(namespace_t)); + ns->access = type; + ns->name = strdup(name); + array_append(pool->namespaces, name, ns); + } + int num_sets = swf_GetU30(tag); + DEBUG printf("%d namespace sets\n", num_sets); + for(t=1;tnamespaces, nsnr); + list_append(nsset->namespaces, ns); + } + char*desc = namespace_set_to_string(nsset); + + array_append(pool->namespace_sets, desc, nsset); + DEBUG printf("set %d) %s\n", t, desc); + } + + int num_multinames = swf_GetU30(tag); + DEBUG printf("%d multinames\n", num_multinames); + for(t=1;ttype = swf_GetU8(tag); + if(m->type==0x07 || m->type==0x0d) { + int namespace_index = swf_GetU30(tag); + m->ns = (namespace_t*)array_getvalue(pool->namespaces, namespace_index); + int name_index = swf_GetU30(tag); + m->name = array_getkey(pool->strings, name_index); + } else if(m->type==0x0f || m->type==0x10) { + int name_index = swf_GetU30(tag); + m->name = array_getkey(pool->strings, name_index); + } else if(m->type==0x11 || m->type==0x12) { + } else if(m->type==0x09 || m->type==0x0e) { + int name_index = swf_GetU30(tag); + int namespace_set_index = swf_GetU30(tag); + m->name = array_getkey(pool->strings, name_index); + m->namespace_set = (namespace_set_t*)array_getvalue(pool->namespace_sets, namespace_set_index); + } else if(m->type==0x1b || m->type==0x1c) { + int namespace_set_index = swf_GetU30(tag); + m->namespace_set = (namespace_set_t*)array_getvalue(pool->namespace_sets, namespace_set_index); + } else { + printf("can't parse type %d multinames yet\n", m->type); + } + char*mname = multiname_to_string(m); + DEBUG printf("multiname %d) %s\n", t, mname); + array_append(pool->multinames, mname, m); + free(mname); + } +} + +void pool_destroy(pool_t*pool) +{ + int t; + array_free(pool->ints); + array_free(pool->uints); + array_free(pool->floats); + + for(t=1;tstrings->num;t++) { + free((void*)array_getkey(pool->strings, t)); + } + array_free(pool->strings); + + for(t=1;tnamespaces->num;t++) { + free(array_getvalue(pool->namespaces, t)); + } + array_free(pool->namespaces); + + for(t=1;tnamespace_sets->num;t++) { + namespace_set_t*set = (namespace_set_t*)array_getvalue(pool->namespace_sets, t); + list_free(set->namespaces); + free(set); + } + array_free(pool->namespace_sets); + + for(t=1;tmultinames->num;t++) { + free(array_getvalue(pool->multinames, t)); + } + array_free(pool->multinames); +} diff --git a/lib/as3/pool.h b/lib/as3/pool.h new file mode 100644 index 0000000..db91e70 --- /dev/null +++ b/lib/as3/pool.h @@ -0,0 +1,106 @@ +/* pool.h + + Routines for handling Flash2 AVM2 ABC contantpool entries. + + Extension module for the rfxswf library. + Part of the swftools package. + + Copyright (c) 2008 Matthias Kramm + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +#ifndef __pool_h__ +#define __pool_h__ + +#include "../q.h" +#include "../rfxswf.h" + +DECLARE(pool); +DECLARE(multiname); +DECLARE(namespace); +DECLARE(namespace_set); +DECLARE_LIST(multiname); +DECLARE_LIST(namespace); +DECLARE_LIST(trait); + +/* abc file constant pool */ +struct _pool { + array_t*ints; + array_t*uints; + array_t*floats; + array_t*strings; + array_t*namespaces; + array_t*namespace_sets; + array_t*multinames; +}; + +typedef enum multiname_type +{QNAME=0x07, + QNAMEA=0x0D, + RTQNAME=0x0F, + RTQNAMEA=0x10, + RTQNAMEL=0x11, + RTQNAMELA=0x12, + MULTINAME=0x09, + MULTINAMEA=0x0E, + MULTINAMEL=0x1B, + MULTINAMELA=0x1C +} multiname_type_t; + +char* access2str(int type); + +struct _namespace { + U8 access; + char*name; +}; +struct _namespace_set { + namespace_list_t*namespaces; +}; +struct _multiname { + multiname_type_t type; + namespace_t*ns; + namespace_set_t*namespace_set; + const char*name; +}; + +/* object -> string */ +char* namespace_set_to_string(namespace_set_t*set); +char* multiname_to_string(multiname_t*m); +char* namespace_to_string(namespace_t*ns); + +/* integer -> object */ +multiname_t*pool_lookup_multiname(pool_t*pool, int i); + +/* object -> integer (lookup) */ +int pool_find_namespace(pool_t*pool, namespace_t*ns); +int pool_find_namespace_set(pool_t*pool, namespace_set_t*set); +int pool_find_string(pool_t*pool, const char*s); +int pool_find_multiname(pool_t*pool, multiname_t*name); + +/* object -> integer (lookup/creation) */ +int pool_register_string(pool_t*pool, const char*s); +int pool_register_namespace(pool_t*pool, namespace_t*ns); +int pool_register_namespace_set(pool_t*pool, namespace_set_t*set); +int pool_register_multiname(pool_t*pool, multiname_t*n); +int pool_register_multiname2(pool_t*pool, char*name); + +/* creation */ +multiname_t* multiname_fromstring(const char*name); + +pool_t*pool_new(); +void pool_read(pool_t*pool, TAG*tag); +void pool_destroy(pool_t*pool); + +#endif -- 1.7.10.4