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 */
28 // ----------------------------- float ----------------------------------
30 void* float_clone(const void*_v) {
34 double*v2 = malloc(sizeof(double));
38 unsigned int float_hash(const void*_v) {
41 const unsigned char*b=_v;
45 h = crc32_add_byte(h, b[t]);
48 void float_destroy(void*_v) {
49 double*v = (double*)_v;
53 char float_equals(const void*_v1, const void*_v2) {
68 // ----------------------------- uint ----------------------------------
70 unsigned int undefined_uint = 0;
72 void*uint_clone(const void*_v) {
75 const unsigned int*v1=_v;
76 unsigned int*v2 = malloc(sizeof(unsigned int));
80 unsigned int uint_hash(const void*_v) {
83 const unsigned int*v=_v;
86 void uint_destroy(void*_v) {
87 unsigned int*v = (unsigned int*)_v;
91 char uint_equals(const void*_v1, const void*_v2) {
92 const unsigned int*v1=_v1;
93 const unsigned int*v2=_v2;
100 dup: (dup_func)uint_clone,
101 hash: (hash_func)uint_hash,
102 free: (free_func)uint_destroy,
103 equals: (equals_func)uint_equals
106 // ----------------------------- namespace ----------------------------------
108 unsigned int namespace_hash(namespace_t*n)
112 unsigned int hash = 0;
113 hash = crc32_add_byte(hash, n->access);
114 hash = crc32_add_string(hash, n->name);
118 unsigned char namespace_equals(const namespace_t*n1, const namespace_t*n2)
122 if(n1->access != n2->access)
124 if(!(n1->name) != !(n2->name))
126 if(n1->name && n2->name && strcmp(n1->name, n2->name))
131 char*escape_string(const char*str)
134 return strdup("NULL");
136 unsigned const char*s=str;
149 char*newstr = malloc(len+1);
154 dest+=sprintf(dest, "\\%d", *s);
157 dest+=sprintf(dest, "\\r");
159 dest+=sprintf(dest, "\\n");
161 dest+=sprintf(dest, "\\t");
163 dest+=sprintf(dest, "\\%2o", *s);
167 dest+=sprintf(dest, "\\x%02x", *s);
175 char* namespace_tostring(namespace_t*ns)
178 return strdup("NULL");
180 U8 type = ns->access;
181 access = access2str(type);
182 char*s = escape_string(ns->name);
183 char*string = (char*)malloc(strlen(access)+strlen(s)+3);
185 sprintf(string, "[%s]NULL", access, s);
187 sprintf(string, "[%s]\"\"", access, s);
189 sprintf(string, "[%s]", access, s);
195 namespace_t* namespace_clone(namespace_t*other)
200 n->access = other->access;
201 n->name = other->name?strdup(other->name):0;
205 namespace_t* namespace_fromstring(const char*name)
207 namespace_t*ns = malloc(sizeof(namespace_t));
208 memset(ns, 0, sizeof(namespace_t));
211 char*n = strdup(name);
212 char*bracket = strchr(n, ']');
216 name += (bracket-n)+1;
217 if(!strcmp(a, "")) access=0x16;
218 else if(!strcmp(a, "undefined")) access=0x08; // public??
219 else if(!strcmp(a, "package")) access=0x16;
220 else if(!strcmp(a, "public")) access=0x16;
221 else if(!strcmp(a, "packageinternal")) access=0x17;
222 else if(!strcmp(a, "protected")) access=0x18;
223 else if(!strcmp(a, "explicit")) access=0x19;
224 else if(!strcmp(a, "staticprotected")) access=0x1a;
225 else if(!strcmp(a, "private")) access=0x05;
227 fprintf(stderr, "Undefined access level: [%s]\n", a);
233 ns->name = strdup(name);
238 ns->name = strdup(name);
243 namespace_t* namespace_new(U8 access, const char*name)
245 namespace_t*ns = malloc(sizeof(namespace_t));
247 /* not sure what namespaces with empty strings are good for, but they *do* exist */
248 ns->name = name?strdup(name):0;
251 namespace_t* namespace_new_undefined(const char*name) {
252 return namespace_new(0x08, name); // public?
254 namespace_t* namespace_new_package(const char*name) {
255 return namespace_new(0x16 , name);
257 namespace_t* namespace_new_packageinternal(const char*name) {
258 return namespace_new(0x17, name);
260 namespace_t* namespace_new_protected(const char*name) {
261 return namespace_new(0x18, name);
263 namespace_t* namespace_new_explicit(const char*name) {
264 return namespace_new(0x19, name);
266 namespace_t* namespace_new_staticprotected(const char*name) {
267 return namespace_new(0x1a, name);
269 namespace_t* namespace_new_private(const char*name) {
270 return namespace_new(0x05, name);
273 void namespace_destroy(namespace_t*n)
276 free(n->name);n->name=0;
282 type_t namespace_type = {
283 dup: (dup_func)namespace_clone,
284 hash: (hash_func)namespace_hash,
285 free: (free_func)namespace_destroy,
286 equals: (equals_func)namespace_equals
289 // ---------------------------namespace sets --------------------------------
291 unsigned int namespace_set_hash(namespace_set_t*set)
295 namespace_list_t*l = set->namespaces;
296 unsigned int hash = 0;
298 hash = crc32_add_byte(hash, l->namespace->access);
299 hash = crc32_add_string(hash, l->namespace->name);
305 int namespace_set_equals(namespace_set_t*m1, namespace_set_t*m2)
309 namespace_list_t*l1 = m1->namespaces;
310 namespace_list_t*l2 = m2->namespaces;
312 if(l1->namespace->access != l2->namespace->access)
314 if(!(l1->namespace->name) != !(l2->namespace->name))
316 if(l1->namespace->name && l2->namespace->name && strcmp(l1->namespace->name, l2->namespace->name))
326 namespace_set_t* namespace_set_clone(namespace_set_t*other)
330 NEW(namespace_set_t,set);
331 set->namespaces = list_new();
332 namespace_list_t*l = other->namespaces;
334 list_append(set->namespaces, namespace_clone(l->namespace));
339 namespace_set_t* namespace_set_new()
341 NEW(namespace_set_t,set);
342 set->namespaces = list_new();
345 char* namespace_set_tostring(namespace_set_t*set)
348 return strdup("NULL");
349 /* TODO: is the order of the namespaces important (does it
350 change the lookup order?). E.g. flex freely shuffles namespaces
352 If the order is not important, we can optimize constant pools by sorting
356 namespace_list_t*lns = set->namespaces;
358 char*s = namespace_tostring(lns->namespace);
363 char*desc = malloc(l+16);
365 lns = set->namespaces;
367 char*s = namespace_tostring(lns->namespace);
378 void namespace_set_destroy(namespace_set_t*set)
381 namespace_list_t*l = set->namespaces;
383 namespace_destroy(l->namespace);l->namespace=0;
386 list_free(set->namespaces);
391 type_t namespace_set_type = {
392 dup: (dup_func)namespace_set_clone,
393 hash: (hash_func)namespace_set_hash,
394 free: (free_func)namespace_set_destroy,
395 equals: (equals_func)namespace_set_equals
398 // ----------------------------- multiname ----------------------------------
400 unsigned int multiname_hash(multiname_t*m)
404 unsigned int hash = crc32_add_byte(0, m->type);
406 hash = crc32_add_string(hash, m->name);
409 hash = crc32_add_byte(hash, m->ns->access);
410 hash = crc32_add_string(hash, m->ns->name);
412 if(m->namespace_set) {
413 namespace_list_t*l = m->namespace_set->namespaces;
415 hash = crc32_add_byte(hash, l->namespace->access);
416 hash = crc32_add_string(hash, l->namespace->name);
423 int multiname_equals(multiname_t*m1, multiname_t*m2)
427 if(m1->type!=m2->type)
430 if((!m1->name) != (!m2->name))
432 if((!m1->ns) != (!m2->ns))
434 if((!m1->namespace_set) != (!m2->namespace_set))
437 if(m1->name && m2->name && strcmp(m1->name,m2->name))
439 if(m1->ns && m2->ns) {
440 if(!namespace_equals(m1->ns, m2->ns))
443 if(m1->namespace_set && m2->namespace_set) {
444 if(!namespace_set_equals(m1->namespace_set, m2->namespace_set))
450 multiname_t* multiname_new(namespace_t*ns, const char*name)
455 m->ns = namespace_new_packageinternal("");
457 m->ns = namespace_clone(ns);
459 m->name = strdup(name);
463 multiname_t* multiname_clone(multiname_t*other)
468 m->type = other->type;
470 m->ns = namespace_clone(other->ns);
471 if(other->namespace_set)
472 m->namespace_set = namespace_set_clone(other->namespace_set);
474 m->name = strdup(other->name);
479 char* access2str(int type)
481 if(type==0x08) return "access08";
482 else if(type==0x16) return "public";
483 else if(type==0x17) return "packageinternal";
484 else if(type==0x18) return "protected";
485 else if(type==0x19) return "explicit";
486 else if(type==0x1A) return "staticprotected";
487 else if(type==0x05) return "private";
489 fprintf(stderr, "Undefined access type %02x\n", type);
495 char multiname_late_namespace(multiname_t*m)
499 return (m->type==RTQNAME || m->type==RTQNAMEA ||
500 m->type==RTQNAMEL || m->type==RTQNAMELA);
503 char multiname_late_name(multiname_t*m)
507 return m->type==RTQNAMEL || m->type==RTQNAMELA ||
508 m->type==MULTINAMEL || m->type==MULTINAMELA;
511 char* multiname_tostring(multiname_t*m)
515 return strdup("NULL");
517 return strdup("--<MULTINAME 0xff>--");
519 char*name = m->name?escape_string(m->name):strdup("*");
520 int namelen = strlen(name);
522 if(m->type==QNAME || m->type==QNAMEA) {
523 char*nsname = escape_string(m->ns->name);
524 mname = malloc(strlen(nsname)+namelen+32);
526 if(m->type == QNAMEA)
527 strcat(mname, ",attr");
529 strcat(mname,access2str(m->ns->access));
531 strcat(mname, nsname);
535 } else if(m->type==RTQNAME || m->type==RTQNAMEA) {
536 mname = malloc(namelen+32);
537 strcpy(mname, "<rt");
538 if(m->type == RTQNAMEA)
539 strcat(mname, ",attr");
542 } else if(m->type==RTQNAMEL) {
543 mname = strdup("<rt,l>");
544 } else if(m->type==RTQNAMELA) {
545 mname = strdup("<rt,l,attr>");
546 } else if(m->type==MULTINAME || m->type==MULTINAMEA) {
547 char*s = namespace_set_tostring(m->namespace_set);
548 mname = malloc(strlen(s)+namelen+16);
549 if(m->type == MULTINAME)
550 strcpy(mname,"<multi>");
552 strcpy(mname,"<multi,attr>");
557 } else if(m->type==MULTINAMEL || m->type==MULTINAMELA) {
558 char*s = namespace_set_tostring(m->namespace_set);
559 mname = malloc(strlen(s)+16);
560 if(m->type == MULTINAMEL)
561 strcpy(mname,"<l,multi>");
563 strcpy(mname,"<l,multi,attr>");
567 fprintf(stderr, "Invalid multiname type: %02x\n", m->type);
573 multiname_t* multiname_fromstring(const char*name2)
577 char*n = strdup(name2);
578 char*p = strstr(n, "::");
579 char*namespace=0,*name=0;
582 fprintf(stderr, "Error: single ':' in name\n");
590 if(strchr(namespace, ':')) {
591 fprintf(stderr, "Error: single ':' in namespace\n");
593 if(strchr(name, ':')) {
594 fprintf(stderr, "Error: single ':' in qualified name\n");
598 multiname_t*m = malloc(sizeof(multiname_t));
599 memset(m, 0, sizeof(multiname_t));
601 m->namespace_set = 0;
602 m->ns = namespace_fromstring(namespace);
603 m->name = name?strdup(name):0;
608 void multiname_destroy(multiname_t*m)
612 free((void*)m->name);m->name = 0;
615 namespace_destroy(m->ns);m->ns = 0;
617 if(m->namespace_set) {
618 namespace_set_destroy(m->namespace_set);m->namespace_set = 0;
625 type_t multiname_type = {
626 dup: (dup_func)multiname_clone,
627 hash: (hash_func)multiname_hash,
628 free: (free_func)multiname_destroy,
629 equals: (equals_func)multiname_equals
633 // ------------------------------- constants -------------------------------------
635 #define NS_TYPE(x) ((x) == 0x08 || (x) == 0x16 || (x) == 0x17 || (x) == 0x18 || \
636 (x) == 0x19 || (x) == 0x1a || (x) == 0x05)
638 #define UNIQUE_CONSTANT(x) ((x) == CONSTANT_TRUE || (x) == CONSTANT_FALSE || (x) == CONSTANT_NULL || (x) == CONSTANT_UNDEFINED)
640 constant_t* constant_new_int(int i)
644 c->type = CONSTANT_INT;
647 constant_t* constant_new_uint(unsigned int u)
651 c->type = CONSTANT_UINT;
654 constant_t* constant_new_float(double f)
658 c->type = CONSTANT_FLOAT;
661 constant_t* constant_new_string(char*s)
664 c->s = string_new4(s);
665 c->type = CONSTANT_STRING;
668 constant_t* constant_new_string2(const char*s, int len)
671 c->s = string_new3(s, len);
672 c->type = CONSTANT_STRING;
675 constant_t* constant_new_namespace(namespace_t*ns)
678 c->ns = namespace_clone(ns);
679 c->type = ns->access;
680 assert(NS_TYPE(c->type));
683 constant_t* constant_new_true()
686 c->type = CONSTANT_TRUE;
689 constant_t* constant_new_false()
692 c->type = CONSTANT_FALSE;
695 constant_t* constant_new_null()
698 c->type = CONSTANT_NULL;
701 constant_t* constant_new_undefined()
704 c->type = CONSTANT_UNDEFINED;
707 constant_t* constant_fromindex(pool_t*pool, int index, int type)
710 /* even for nonvalued constants (like TRUE/FALSE etc.), a nonzero
711 index is present to indicate that a type is coming */
716 if(NS_TYPE(c->type)) {
717 c->ns = namespace_clone(pool_lookup_namespace(pool, index));
718 } else if(c->type == CONSTANT_INT) {
719 c->i = pool_lookup_int(pool, index);
720 } else if(c->type == CONSTANT_UINT) {
721 c->u = pool_lookup_uint(pool, index);
722 } else if(c->type == CONSTANT_FLOAT) {
723 c->f = pool_lookup_float(pool, index);
724 } else if(c->type == CONSTANT_STRING) {
725 string_t s = pool_lookup_string2(pool, index);
726 c->s = string_dup3(&s);
727 } else if(UNIQUE_CONSTANT(c->type)) {
730 fprintf(stderr, "invalid constant type %02x\n", c->type);
734 char* constant_tostring(constant_t*c)
739 if(NS_TYPE(c->type)) {
740 return namespace_tostring(c->ns);
741 } else if(c->type == CONSTANT_INT) {
742 sprintf(buf, "%d", c->i);
744 } else if(c->type == CONSTANT_UINT) {
745 sprintf(buf, "%u", c->u);
747 } else if(c->type == CONSTANT_FLOAT) {
749 sprintf(buf, "%f", c->f);
751 } else if(c->type == CONSTANT_STRING) {
752 /* should we escape the string? \0 bytes won't be printed */
753 return strdup_n(c->s->str,c->s->len);
754 } else if(c->type == CONSTANT_TRUE) {
755 return strdup("true");
756 } else if(c->type == CONSTANT_FALSE) {
757 return strdup("false");
758 } else if(c->type == CONSTANT_NULL) {
759 return strdup("null");
760 } else if(c->type == CONSTANT_UNDEFINED) {
761 return strdup("undefined");
763 fprintf(stderr, "invalid constant type %02x\n", c->type);
767 char constant_has_index(constant_t*c)
771 return !UNIQUE_CONSTANT(c->type);
773 int constant_get_index(pool_t*pool, constant_t*c)
777 if(NS_TYPE(c->type)) {
779 /*if(c->type!=c->ns->access) {
780 printf("%02x<->%02x\n", c->type, c->ns->access);
782 assert(c->type == c->ns->access);
783 return pool_register_namespace(pool, c->ns);
784 } else if(c->type == CONSTANT_INT) {
785 return pool_register_int(pool, c->i);
786 } else if(c->type == CONSTANT_UINT) {
787 return pool_register_uint(pool, c->u);
788 } else if(c->type == CONSTANT_FLOAT) {
789 return pool_register_float(pool, c->f);
790 } else if(c->type == CONSTANT_STRING) {
791 return pool_register_string2(pool, c->s);
792 } else if(!constant_has_index(c)) {
795 fprintf(stderr, "invalid constant type %02x\n", c->type);
799 void constant_free(constant_t*c)
803 if(c->type == CONSTANT_STRING) {
805 } else if (NS_TYPE(c->type)) {
806 namespace_destroy(c->ns);c->ns=0;
810 // ------------------------------- pool -------------------------------------
812 int pool_register_uint(pool_t*p, unsigned int i)
814 int pos = array_append_if_new(p->x_uints, &i, 0);
818 int pool_register_int(pool_t*p, int i)
820 int pos = array_append_if_new(p->x_ints, &i, 0);
824 int pool_register_float(pool_t*p, double d)
826 int pos = array_append_if_new(p->x_floats, &d, 0);
830 int pool_register_string(pool_t*pool, const char*str)
833 string_t s = string_new2(str);
834 int pos = array_append_if_new(pool->x_strings, &s, 0);
838 int pool_register_string2(pool_t*pool, string_t*s)
840 if(!s || !s->str) return 0;
841 int pos = array_append_if_new(pool->x_strings, s, 0);
845 int pool_register_namespace(pool_t*pool, namespace_t*ns)
848 int pos = array_append_if_new(pool->x_namespaces, ns, 0);
852 int pool_register_namespace_set(pool_t*pool, namespace_set_t*set)
855 int pos = array_append_if_new(pool->x_namespace_sets, set, 0);
859 int pool_register_multiname(pool_t*pool, multiname_t*n)
862 int pos = array_append_if_new(pool->x_multinames, n, 0);
866 int pool_register_multiname2(pool_t*pool, char*name)
869 multiname_t*n = multiname_fromstring(name);
870 int pos = array_append_if_new(pool->x_multinames, n, 0);
871 multiname_destroy(n);
877 int pool_find_uint(pool_t*pool, unsigned int x)
879 int i = array_find(pool->x_uints, &x);
881 fprintf(stderr, "Couldn't find uint \"%d\" in constant pool\n", x);
886 int pool_find_int(pool_t*pool, int x)
888 int i = array_find(pool->x_ints, &x);
890 fprintf(stderr, "Couldn't find int \"%d\" in constant pool\n", x);
895 int pool_find_float(pool_t*pool, double x)
897 int i = array_find(pool->x_ints, &x);
899 fprintf(stderr, "Couldn't find int \"%d\" in constant pool\n", x);
904 int pool_find_namespace(pool_t*pool, namespace_t*ns)
908 int i = array_find(pool->x_namespaces, ns);
910 char*s = namespace_tostring(ns);
911 fprintf(stderr, "Couldn't find namespace \"%s\" %08x in constant pool\n", s, ns);
917 int pool_find_namespace_set(pool_t*pool, namespace_set_t*set)
921 int i = array_find(pool->x_namespace_sets, set);
923 char*s = namespace_set_tostring(set);
924 fprintf(stderr, "Couldn't find namespace_set \"%s\" in constant pool\n", s);
930 int pool_find_string(pool_t*pool, const char*str)
934 string_t s = string_new2(str);
935 int i = array_find(pool->x_strings, &s);
937 fprintf(stderr, "Couldn't find string \"%s\" in constant pool\n", s);
942 int pool_find_multiname(pool_t*pool, multiname_t*name)
946 int i = array_find(pool->x_multinames, name);
948 char*s = multiname_tostring(name);
949 fprintf(stderr, "Couldn't find multiname \"%s\" in constant pool\n", s);
956 int pool_lookup_int(pool_t*pool, int i)
959 return *(int*)array_getkey(pool->x_ints, i);
961 unsigned int pool_lookup_uint(pool_t*pool, int i)
964 return *(unsigned int*)array_getkey(pool->x_uints, i);
966 double pool_lookup_float(pool_t*pool, int i)
968 if(!i) return __builtin_nan("");
969 return *(double*)array_getkey(pool->x_floats, i);
971 const char*pool_lookup_string(pool_t*pool, int i)
973 string_t*s = array_getkey(pool->x_strings, i);
977 string_t pool_lookup_string2(pool_t*pool, int i)
979 string_t*s = array_getkey(pool->x_strings, i);
982 namespace_t*pool_lookup_namespace(pool_t*pool, int i)
984 return (namespace_t*)array_getkey(pool->x_namespaces, i);
986 namespace_set_t*pool_lookup_namespace_set(pool_t*pool, int i)
988 return (namespace_set_t*)array_getkey(pool->x_namespace_sets, i);
990 multiname_t*pool_lookup_multiname(pool_t*pool, int i)
992 return (multiname_t*)array_getkey(pool->x_multinames, i);
999 p->x_ints = array_new2(&uint_type);
1000 p->x_uints = array_new2(&uint_type);
1001 p->x_floats = array_new2(&float_type);
1002 p->x_strings = array_new2(&stringstruct_type);
1003 p->x_namespaces = array_new2(&namespace_type);
1004 p->x_namespace_sets = array_new2(&namespace_set_type);
1005 p->x_multinames = array_new2(&multiname_type);
1007 /* add a zero-index entry in each list */
1009 array_append(p->x_ints, 0, 0);
1010 array_append(p->x_uints, 0, 0);
1011 array_append(p->x_floats, 0, 0);
1012 array_append(p->x_strings, 0, 0);
1013 array_append(p->x_namespaces, 0, 0);
1014 array_append(p->x_namespace_sets, 0, 0);
1015 array_append(p->x_multinames, 0, 0);
1022 void pool_read(pool_t*pool, TAG*tag)
1024 int num_ints = swf_GetU30(tag);
1025 DEBUG printf("%d ints\n", num_ints);
1027 for(t=1;t<num_ints;t++) {
1028 S32 v = swf_GetABCS32(tag);
1029 DEBUG printf("int %d) %d\n", t, v);
1030 array_append(pool->x_ints, &v, 0);
1033 int num_uints = swf_GetU30(tag);
1034 DEBUG printf("%d uints\n", num_uints);
1035 for(t=1;t<num_uints;t++) {
1036 U32 v = swf_GetABCU32(tag);
1037 DEBUG printf("uint %d) %d\n", t, v);
1038 array_append(pool->x_uints, &v, 0);
1041 int num_floats = swf_GetU30(tag);
1042 DEBUG printf("%d floats\n", num_floats);
1043 for(t=1;t<num_floats;t++) {
1044 double d = swf_GetD64(tag);
1045 DEBUG printf("float %d) %f\n", t, d);
1046 array_append(pool->x_floats, &d, 0);
1049 int num_strings = swf_GetU30(tag);
1050 DEBUG printf("%d strings\n", num_strings);
1051 for(t=1;t<num_strings;t++) {
1052 int len = swf_GetU30(tag);
1053 string_t s = string_new(&tag->data[tag->pos], len);
1054 swf_GetBlock(tag, 0, len);
1055 array_append(pool->x_strings, &s, 0);
1056 DEBUG printf("%d) \"%s\"\n", t, ((string_t*)array_getkey(pool->x_strings, t))->str);
1058 int num_namespaces = swf_GetU30(tag);
1059 DEBUG printf("%d namespaces\n", num_namespaces);
1060 for(t=1;t<num_namespaces;t++) {
1061 U8 type = swf_GetU8(tag);
1062 int namenr = swf_GetU30(tag);
1063 const char*name = 0;
1065 name = pool_lookup_string(pool, namenr);
1066 namespace_t*ns = namespace_new(type, name);
1067 array_append(pool->x_namespaces, ns, 0);
1068 DEBUG printf("%d) %02x \"%s\"\n", t, type, namespace_tostring(ns));
1069 namespace_destroy(ns);
1071 int num_sets = swf_GetU30(tag);
1072 DEBUG printf("%d namespace sets\n", num_sets);
1073 for(t=1;t<num_sets;t++) {
1074 int count = swf_GetU30(tag);
1077 NEW(namespace_set_t, nsset);
1078 for(s=0;s<count;s++) {
1079 int nsnr = swf_GetU30(tag);
1081 fprintf(stderr, "Zero entry in namespace set\n");
1082 namespace_t*ns = (namespace_t*)array_getkey(pool->x_namespaces, nsnr);
1083 list_append(nsset->namespaces, namespace_clone(ns));
1085 array_append(pool->x_namespace_sets, nsset, 0);
1086 DEBUG printf("set %d) %s\n", t, namespace_set_tostring(nsset));
1087 namespace_set_destroy(nsset);
1090 int num_multinames = swf_GetU30(tag);
1091 DEBUG printf("%d multinames\n", num_multinames);
1092 for(t=1;t<num_multinames;t++) {
1094 memset(&m, 0, sizeof(multiname_t));
1095 m.type = swf_GetU8(tag);
1096 if(m.type==0x07 || m.type==0x0d) {
1097 int namespace_index = swf_GetU30(tag);
1098 m.ns = (namespace_t*)array_getkey(pool->x_namespaces, namespace_index);
1099 int name_index = swf_GetU30(tag);
1100 if(name_index) // 0 = '*' (any)
1101 m.name = pool_lookup_string(pool, name_index);
1102 } else if(m.type==0x0f || m.type==0x10) {
1103 int name_index = swf_GetU30(tag);
1104 if(name_index) // 0 = '*' (any name)
1105 m.name = pool_lookup_string(pool, name_index);
1106 } else if(m.type==0x11 || m.type==0x12) {
1107 } else if(m.type==0x09 || m.type==0x0e) {
1108 int name_index = swf_GetU30(tag);
1109 int namespace_set_index = swf_GetU30(tag);
1111 m.name = pool_lookup_string(pool, name_index);
1112 m.namespace_set = (namespace_set_t*)array_getkey(pool->x_namespace_sets, namespace_set_index);
1113 } else if(m.type==0x1b || m.type==0x1c) {
1114 int namespace_set_index = swf_GetU30(tag);
1115 m.namespace_set = (namespace_set_t*)array_getkey(pool->x_namespace_sets, namespace_set_index);
1117 printf("can't parse type %d multinames yet\n", m.type);
1119 DEBUG printf("multiname %d) %s\n", t, multiname_tostring(&m));
1120 array_append(pool->x_multinames, &m, 0);
1124 void pool_write(pool_t*pool, TAG*tag)
1128 /* make sure that all namespaces used by multinames / namespace sets
1129 and all strings used by namespaces exist */
1131 for(t=1;t<pool->x_multinames->num;t++) {
1132 multiname_t*m = (multiname_t*)array_getkey(pool->x_multinames, t);
1134 pool_register_namespace(pool, m->ns);
1136 if(m->namespace_set) {
1137 pool_register_namespace_set(pool, m->namespace_set);
1140 pool_register_string(pool, m->name);
1143 for(t=1;t<pool->x_namespace_sets->num;t++) {
1144 namespace_set_t*set = (namespace_set_t*)array_getkey(pool->x_namespace_sets, t);
1145 namespace_list_t*i = set->namespaces;
1147 pool_register_namespace(pool, i->namespace);
1151 for(t=1;t<pool->x_namespaces->num;t++) {
1152 namespace_t*ns= (namespace_t*)array_getkey(pool->x_namespaces, t);
1153 /* The spec says (page 22): "a value of zero denotes an empty string".
1154 However when actually using zero strings as empty namespaces, the
1155 flash player breaks.*/
1156 //if(ns->name && ns->name[0])
1157 pool_register_string(pool, ns->name);
1160 //pool_register_int(pool, 15);
1161 //pool_register_int(pool, 1);
1162 //pool_register_int(pool, 0);
1165 swf_SetU30(tag, pool->x_ints->num>1?pool->x_ints->num:0);
1166 for(t=1;t<pool->x_ints->num;t++) {
1167 S32 val = *(int*)array_getkey(pool->x_ints, t);
1168 swf_SetABCS32(tag, val);
1170 swf_SetU30(tag, pool->x_uints->num>1?pool->x_uints->num:0);
1171 for(t=1;t<pool->x_uints->num;t++) {
1172 swf_SetABCU32(tag, *(unsigned int*)array_getkey(pool->x_uints, t));
1174 swf_SetU30(tag, pool->x_floats->num>1?pool->x_floats->num:0);
1175 for(t=1;t<pool->x_floats->num;t++) {
1176 double d = pool_lookup_float(pool, t);
1179 swf_SetU30(tag, pool->x_strings->num>1?pool->x_strings->num:0);
1180 for(t=1;t<pool->x_strings->num;t++) {
1181 string_t str = pool_lookup_string2(pool, t);
1182 swf_SetU30String(tag, str.str, str.len);
1184 swf_SetU30(tag, pool->x_namespaces->num>1?pool->x_namespaces->num:0);
1185 for(t=1;t<pool->x_namespaces->num;t++) {
1186 namespace_t*ns= (namespace_t*)array_getkey(pool->x_namespaces, t);
1187 swf_SetU8(tag, ns->access);
1188 const char*name = ns->name;
1191 //if(name && name[0])
1192 i = pool_find_string(pool, name);
1196 swf_SetU30(tag, pool->x_namespace_sets->num>1?pool->x_namespace_sets->num:0);
1197 for(t=1;t<pool->x_namespace_sets->num;t++) {
1198 namespace_set_t*set = (namespace_set_t*)array_getkey(pool->x_namespace_sets, t);
1199 namespace_list_t*i = set->namespaces;
1200 int len = list_length(i);
1201 swf_SetU30(tag, len);
1203 int index = pool_find_namespace(pool, i->namespace);
1204 swf_SetU30(tag, index);
1209 swf_SetU30(tag, pool->x_multinames->num>1?pool->x_multinames->num:0);
1210 for(t=1;t<pool->x_multinames->num;t++) {
1211 multiname_t*m = (multiname_t*)array_getkey(pool->x_multinames, t);
1212 swf_SetU8(tag, m->type);
1215 assert(m->type==0x07 || m->type==0x0d);
1216 int i = pool_find_namespace(pool, m->ns);
1217 if(i<0) fprintf(stderr, "internal error: unregistered namespace %02x %s %s\n", m->ns->access, access2str(m->ns->access), m->ns->name);
1220 assert(m->type!=0x07 && m->type!=0x0d);
1223 assert(m->type==0x09 || m->type==0x0e || m->type==0x07 || m->type==0x0d || m->type==0x0f || m->type==0x10);
1224 int i = pool_find_string(pool, m->name);
1225 if(i<0) fprintf(stderr, "internal error: unregistered name\n");
1228 assert(m->type!=0x09 && m->type!=0x0e && m->type!=0x07 && m->type!=0x0d && m->type!=0x0f && m->type!=0x10);
1230 if(m->namespace_set) {
1231 assert(m->type==0x09 || m->type==0x0e || m->type==0x1c || m->type==0x1b);
1232 int i = pool_find_namespace_set(pool, m->namespace_set);
1233 if(i<0) fprintf(stderr, "internal error: unregistered namespace set\n");
1236 assert(m->type!=0x09 && m->type!=0x0e && m->type!=0x1c && m->type!=0x1b);
1242 void pool_destroy(pool_t*pool)
1245 array_free(pool->x_ints);
1246 array_free(pool->x_uints);
1247 array_free(pool->x_floats);
1248 array_free(pool->x_strings);
1249 array_free(pool->x_namespaces);
1250 array_free(pool->x_namespace_sets);
1251 array_free(pool->x_multinames);