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);
184 int l = sprintf(string, "[%s]%s", access, s);
189 namespace_t* namespace_clone(namespace_t*other)
194 n->access = other->access;
195 n->name = other->name?strdup(other->name):0;
199 namespace_t* namespace_fromstring(const char*name)
201 namespace_t*ns = malloc(sizeof(namespace_t));
202 memset(ns, 0, sizeof(namespace_t));
205 char*n = strdup(name);
206 char*bracket = strchr(n, ']');
210 name += (bracket-n)+1;
211 if(!strcmp(a, "")) access=0x16;
212 else if(!strcmp(a, "undefined")) access=0x08; // public??
213 else if(!strcmp(a, "package")) access=0x16;
214 else if(!strcmp(a, "public")) access=0x16;
215 else if(!strcmp(a, "packageinternal")) access=0x17;
216 else if(!strcmp(a, "protected")) access=0x18;
217 else if(!strcmp(a, "explicit")) access=0x19;
218 else if(!strcmp(a, "staticprotected")) access=0x1a;
219 else if(!strcmp(a, "private")) access=0x05;
221 fprintf(stderr, "Undefined access level: [%s]\n", a);
227 ns->name = strdup(name);
232 ns->name = strdup(name);
237 namespace_t* namespace_new(U8 access, const char*name)
239 namespace_t*ns = malloc(sizeof(namespace_t));
241 /* not sure what namespaces with empty strings are good for, but they *do* exist */
242 ns->name = name?strdup(name):0;
245 namespace_t* namespace_new_undefined(const char*name) {
246 return namespace_new(0x08, name); // public?
248 namespace_t* namespace_new_package(const char*name) {
249 return namespace_new(0x16 , name);
251 namespace_t* namespace_new_packageinternal(const char*name) {
252 return namespace_new(0x17, name);
254 namespace_t* namespace_new_protected(const char*name) {
255 return namespace_new(0x18, name);
257 namespace_t* namespace_new_explicit(const char*name) {
258 return namespace_new(0x19, name);
260 namespace_t* namespace_new_staticprotected(const char*name) {
261 return namespace_new(0x1a, name);
263 namespace_t* namespace_new_private(const char*name) {
264 return namespace_new(0x05, name);
267 void namespace_destroy(namespace_t*n)
270 free(n->name);n->name=0;
276 type_t namespace_type = {
277 dup: (dup_func)namespace_clone,
278 hash: (hash_func)namespace_hash,
279 free: (free_func)namespace_destroy,
280 equals: (equals_func)namespace_equals
283 // ---------------------------namespace sets --------------------------------
285 unsigned int namespace_set_hash(namespace_set_t*set)
289 namespace_list_t*l = set->namespaces;
290 unsigned int hash = 0;
292 hash = crc32_add_byte(hash, l->namespace->access);
293 hash = crc32_add_string(hash, l->namespace->name);
299 int namespace_set_equals(namespace_set_t*m1, namespace_set_t*m2)
303 namespace_list_t*l1 = m1->namespaces;
304 namespace_list_t*l2 = m2->namespaces;
306 if(l1->namespace->access != l2->namespace->access)
308 if(!(l1->namespace->name) != !(l2->namespace->name))
310 if(l1->namespace->name && l2->namespace->name && strcmp(l1->namespace->name, l2->namespace->name))
320 namespace_set_t* namespace_set_clone(namespace_set_t*other)
324 NEW(namespace_set_t,set);
325 set->namespaces = list_new();
326 namespace_list_t*l = other->namespaces;
328 list_append(set->namespaces, namespace_clone(l->namespace));
333 namespace_set_t* namespace_set_new()
335 NEW(namespace_set_t,set);
336 set->namespaces = list_new();
339 char* namespace_set_tostring(namespace_set_t*set)
342 return strdup("NULL");
343 /* TODO: is the order of the namespaces important (does it
344 change the lookup order?). E.g. flex freely shuffles namespaces
346 If the order is not important, we can optimize constant pools by sorting
350 namespace_list_t*lns = set->namespaces;
352 char*s = namespace_tostring(lns->namespace);
357 char*desc = malloc(l+16);
359 lns = set->namespaces;
361 char*s = namespace_tostring(lns->namespace);
372 void namespace_set_destroy(namespace_set_t*set)
375 namespace_list_t*l = set->namespaces;
377 namespace_destroy(l->namespace);l->namespace=0;
380 list_free(set->namespaces);
385 type_t namespace_set_type = {
386 dup: (dup_func)namespace_set_clone,
387 hash: (hash_func)namespace_set_hash,
388 free: (free_func)namespace_set_destroy,
389 equals: (equals_func)namespace_set_equals
392 // ----------------------------- multiname ----------------------------------
394 unsigned int multiname_hash(multiname_t*m)
398 unsigned int hash = crc32_add_byte(0, m->type);
400 hash = crc32_add_string(hash, m->name);
403 hash = crc32_add_byte(hash, m->ns->access);
404 hash = crc32_add_string(hash, m->ns->name);
406 if(m->namespace_set) {
407 namespace_list_t*l = m->namespace_set->namespaces;
409 hash = crc32_add_byte(hash, l->namespace->access);
410 hash = crc32_add_string(hash, l->namespace->name);
417 int multiname_equals(multiname_t*m1, multiname_t*m2)
421 if(m1->type!=m2->type)
424 if((!m1->name) != (!m2->name))
426 if((!m1->ns) != (!m2->ns))
428 if((!m1->namespace_set) != (!m2->namespace_set))
431 if(m1->name && m2->name && strcmp(m1->name,m2->name))
433 if(m1->ns && m2->ns) {
434 if(!namespace_equals(m1->ns, m2->ns))
437 if(m1->namespace_set && m2->namespace_set) {
438 if(!namespace_set_equals(m1->namespace_set, m2->namespace_set))
444 multiname_t* multiname_new(namespace_t*ns, const char*name)
449 m->ns = namespace_new_packageinternal("");
451 m->ns = namespace_clone(ns);
453 m->name = strdup(name);
457 multiname_t* multiname_clone(multiname_t*other)
462 m->type = other->type;
464 m->ns = namespace_clone(other->ns);
465 if(other->namespace_set)
466 m->namespace_set = namespace_set_clone(other->namespace_set);
468 m->name = strdup(other->name);
473 char* access2str(int type)
475 if(type==0x08) return "access08";
476 else if(type==0x16) return "public";
477 else if(type==0x17) return "packageinternal";
478 else if(type==0x18) return "protected";
479 else if(type==0x19) return "explicit";
480 else if(type==0x1A) return "staticprotected";
481 else if(type==0x05) return "private";
483 fprintf(stderr, "Undefined access type %02x\n", type);
489 char multiname_late_namespace(multiname_t*m)
493 return (m->type==RTQNAME || m->type==RTQNAMEA ||
494 m->type==RTQNAMEL || m->type==RTQNAMELA);
497 char multiname_late_name(multiname_t*m)
501 return m->type==RTQNAMEL || m->type==RTQNAMELA ||
502 m->type==MULTINAMEL || m->type==MULTINAMELA;
505 char* multiname_tostring(multiname_t*m)
509 return strdup("NULL");
511 return strdup("--<MULTINAME 0xff>--");
513 char*name = m->name?escape_string(m->name):strdup("*");
514 int namelen = strlen(name);
516 if(m->type==QNAME || m->type==QNAMEA) {
517 char*nsname = escape_string(m->ns->name);
518 mname = malloc(strlen(nsname)+namelen+32);
520 if(m->type == QNAMEA)
521 strcat(mname, ",attr");
523 strcat(mname,access2str(m->ns->access));
525 strcat(mname, nsname);
529 } else if(m->type==RTQNAME || m->type==RTQNAMEA) {
530 mname = malloc(namelen+32);
531 strcpy(mname, "<rt");
532 if(m->type == RTQNAMEA)
533 strcat(mname, ",attr");
536 } else if(m->type==RTQNAMEL) {
537 mname = strdup("<rt,l>");
538 } else if(m->type==RTQNAMELA) {
539 mname = strdup("<rt,l,attr>");
540 } else if(m->type==MULTINAME || m->type==MULTINAMEA) {
541 char*s = namespace_set_tostring(m->namespace_set);
542 mname = malloc(strlen(s)+namelen+16);
543 if(m->type == MULTINAME)
544 strcpy(mname,"<multi>");
546 strcpy(mname,"<multi,attr>");
551 } else if(m->type==MULTINAMEL || m->type==MULTINAMELA) {
552 char*s = namespace_set_tostring(m->namespace_set);
553 mname = malloc(strlen(s)+16);
554 if(m->type == MULTINAMEL)
555 strcpy(mname,"<l,multi>");
557 strcpy(mname,"<l,multi,attr>");
561 fprintf(stderr, "Invalid multiname type: %02x\n", m->type);
567 multiname_t* multiname_fromstring(const char*name2)
571 char*n = strdup(name2);
572 char*p = strstr(n, "::");
573 char*namespace=0,*name=0;
576 fprintf(stderr, "Error: single ':' in name\n");
584 if(strchr(namespace, ':')) {
585 fprintf(stderr, "Error: single ':' in namespace\n");
587 if(strchr(name, ':')) {
588 fprintf(stderr, "Error: single ':' in qualified name\n");
592 multiname_t*m = malloc(sizeof(multiname_t));
593 memset(m, 0, sizeof(multiname_t));
595 m->namespace_set = 0;
596 m->ns = namespace_fromstring(namespace);
597 m->name = name?strdup(name):0;
602 void multiname_destroy(multiname_t*m)
606 free((void*)m->name);m->name = 0;
609 namespace_destroy(m->ns);m->ns = 0;
611 if(m->namespace_set) {
612 namespace_set_destroy(m->namespace_set);m->namespace_set = 0;
618 type_t multiname_type = {
619 dup: (dup_func)multiname_clone,
620 hash: (hash_func)multiname_hash,
621 free: (free_func)multiname_destroy,
622 equals: (equals_func)multiname_equals
626 // ------------------------------- constants -------------------------------------
628 #define NS_TYPE(x) ((x) == 0x08 || (x) == 0x16 || (x) == 0x17 || (x) == 0x18 || \
629 (x) == 0x19 || (x) == 0x1a || (x) == 0x05)
631 #define UNIQUE_CONSTANT(x) ((x) == CONSTANT_TRUE || (x) == CONSTANT_FALSE || (x) == CONSTANT_NULL || (x) == CONSTANT_UNDEFINED)
633 constant_t* constant_new_int(int i)
637 c->type = CONSTANT_INT;
640 constant_t* constant_new_uint(unsigned int u)
644 c->type = CONSTANT_UINT;
647 constant_t* constant_new_float(double f)
651 c->type = CONSTANT_FLOAT;
654 constant_t* constant_new_string(char*s)
658 c->type = CONSTANT_STRING;
661 constant_t* constant_new_namespace(namespace_t*ns)
664 c->ns = namespace_clone(ns);
665 c->type = ns->access;
666 assert(NS_TYPE(c->type));
669 constant_t* constant_new_true()
672 c->type = CONSTANT_TRUE;
675 constant_t* constant_new_false()
678 c->type = CONSTANT_FALSE;
681 constant_t* constant_new_null()
684 c->type = CONSTANT_NULL;
687 constant_t* constant_new_undefined()
690 c->type = CONSTANT_UNDEFINED;
693 constant_t* constant_fromindex(pool_t*pool, int index, int type)
696 /* even for nonvalued constants (like TRUE/FALSE etc.), a nonzero
697 index is present to indicate that a type is coming */
702 if(NS_TYPE(c->type)) {
703 c->ns = namespace_clone(pool_lookup_namespace(pool, index));
704 } else if(c->type == CONSTANT_INT) {
705 c->i = pool_lookup_int(pool, index);
706 } else if(c->type == CONSTANT_UINT) {
707 c->u = pool_lookup_uint(pool, index);
708 } else if(c->type == CONSTANT_FLOAT) {
709 c->f = pool_lookup_float(pool, index);
710 } else if(c->type == CONSTANT_STRING) {
711 c->s = strdup(pool_lookup_string(pool, index));
712 } else if(UNIQUE_CONSTANT(c->type)) {
715 fprintf(stderr, "invalid constant type %02x\n", c->type);
719 char* constant_tostring(constant_t*c)
724 if(NS_TYPE(c->type)) {
725 return namespace_tostring(c->ns);
726 } else if(c->type == CONSTANT_INT) {
727 sprintf(buf, "%d", c->i);
729 } else if(c->type == CONSTANT_UINT) {
730 sprintf(buf, "%u", c->u);
732 } else if(c->type == CONSTANT_FLOAT) {
733 sprintf(buf, "%f", c->f);
735 } else if(c->type == CONSTANT_STRING) {
737 } else if(c->type == CONSTANT_TRUE) {
738 return strdup("true");
739 } else if(c->type == CONSTANT_FALSE) {
740 return strdup("false");
741 } else if(c->type == CONSTANT_NULL) {
742 return strdup("null");
743 } else if(c->type == CONSTANT_UNDEFINED) {
744 return strdup("undefined");
746 fprintf(stderr, "invalid constant type %02x\n", c->type);
750 char constant_has_index(constant_t*c)
754 return !UNIQUE_CONSTANT(c->type);
756 int constant_get_index(pool_t*pool, constant_t*c)
760 if(NS_TYPE(c->type)) {
762 /*if(c->type!=c->ns->access) {
763 printf("%02x<->%02x\n", c->type, c->ns->access);
765 assert(c->type == c->ns->access);
766 return pool_register_namespace(pool, c->ns);
767 } else if(c->type == CONSTANT_INT) {
768 return pool_register_int(pool, c->i);
769 } else if(c->type == CONSTANT_UINT) {
770 return pool_register_uint(pool, c->u);
771 } else if(c->type == CONSTANT_FLOAT) {
772 return pool_register_float(pool, c->f);
773 } else if(c->type == CONSTANT_STRING) {
774 return pool_register_string(pool, c->s);
775 } else if(!constant_has_index(c)) {
778 fprintf(stderr, "invalid constant type %02x\n", c->type);
782 void constant_free(constant_t*c)
786 if(c->type == CONSTANT_STRING) {
788 } else if (NS_TYPE(c->type)) {
789 namespace_destroy(c->ns);c->ns=0;
793 // ------------------------------- pool -------------------------------------
795 int pool_register_uint(pool_t*p, unsigned int i)
797 int pos = array_append_if_new(p->x_uints, &i, 0);
801 int pool_register_int(pool_t*p, int i)
803 int pos = array_append_if_new(p->x_ints, &i, 0);
807 int pool_register_float(pool_t*p, double d)
809 int pos = array_append_if_new(p->x_floats, &d, 0);
813 int pool_register_string(pool_t*pool, const char*s)
816 ptroff_t l = strlen(s);
817 int pos = array_append_if_new(pool->x_strings, s, (void*)l);
821 int pool_register_namespace(pool_t*pool, namespace_t*ns)
824 int pos = array_append_if_new(pool->x_namespaces, ns, 0);
828 int pool_register_namespace_set(pool_t*pool, namespace_set_t*set)
831 int pos = array_append_if_new(pool->x_namespace_sets, set, 0);
835 int pool_register_multiname(pool_t*pool, multiname_t*n)
838 int pos = array_append_if_new(pool->x_multinames, n, 0);
845 int pool_register_multiname2(pool_t*pool, char*name)
848 multiname_t*n = multiname_fromstring(name);
849 int pos = array_append_if_new(pool->x_multinames, n, 0);
850 multiname_destroy(n);
856 int pool_find_uint(pool_t*pool, unsigned int x)
858 int i = array_find(pool->x_uints, &x);
860 fprintf(stderr, "Couldn't find uint \"%d\" in constant pool\n", x);
865 int pool_find_int(pool_t*pool, int x)
867 int i = array_find(pool->x_ints, &x);
869 fprintf(stderr, "Couldn't find int \"%d\" in constant pool\n", x);
874 int pool_find_float(pool_t*pool, double x)
876 int i = array_find(pool->x_ints, &x);
878 fprintf(stderr, "Couldn't find int \"%d\" in constant pool\n", x);
883 int pool_find_namespace(pool_t*pool, namespace_t*ns)
887 int i = array_find(pool->x_namespaces, ns);
889 char*s = namespace_tostring(ns);
890 fprintf(stderr, "Couldn't find namespace \"%s\" %08x in constant pool\n", s, ns);
896 int pool_find_namespace_set(pool_t*pool, namespace_set_t*set)
900 int i = array_find(pool->x_namespace_sets, set);
902 char*s = namespace_set_tostring(set);
903 fprintf(stderr, "Couldn't find namespace_set \"%s\" in constant pool\n", s);
909 int pool_find_string(pool_t*pool, const char*s)
913 int i = array_find(pool->x_strings, s);
915 fprintf(stderr, "Couldn't find string \"%s\" in constant pool\n", s);
920 int pool_find_multiname(pool_t*pool, multiname_t*name)
924 int i = array_find(pool->x_multinames, name);
926 char*s = multiname_tostring(name);
927 fprintf(stderr, "Couldn't find multiname \"%s\" in constant pool\n", s);
934 int pool_lookup_int(pool_t*pool, int i)
937 return *(int*)array_getkey(pool->x_ints, i);
939 unsigned int pool_lookup_uint(pool_t*pool, int i)
942 return *(unsigned int*)array_getkey(pool->x_uints, i);
944 double pool_lookup_float(pool_t*pool, int i)
946 if(!i) return __builtin_nan("");
947 return *(double*)array_getkey(pool->x_floats, i);
949 char*pool_lookup_string(pool_t*pool, int i)
951 return (char*)array_getkey(pool->x_strings, i);
953 string_t pool_lookup_string2(pool_t*pool, int i)
955 char*s = (char*)array_getkey(pool->x_strings, i);
956 int len = (int)(ptroff_t)array_getvalue(pool->x_strings, i);
957 return string_new(s,len);
959 namespace_t*pool_lookup_namespace(pool_t*pool, int i)
961 return (namespace_t*)array_getkey(pool->x_namespaces, i);
963 namespace_set_t*pool_lookup_namespace_set(pool_t*pool, int i)
965 return (namespace_set_t*)array_getkey(pool->x_namespace_sets, i);
967 multiname_t*pool_lookup_multiname(pool_t*pool, int i)
969 return (multiname_t*)array_getkey(pool->x_multinames, i);
976 p->x_ints = array_new2(&uint_type);
977 p->x_uints = array_new2(&uint_type);
978 p->x_floats = array_new2(&float_type);
979 p->x_strings = array_new2(&charptr_type);
980 p->x_namespaces = array_new2(&namespace_type);
981 p->x_namespace_sets = array_new2(&namespace_set_type);
982 p->x_multinames = array_new2(&multiname_type);
984 /* add a zero-index entry in each list */
986 array_append(p->x_ints, 0, 0);
987 array_append(p->x_uints, 0, 0);
988 array_append(p->x_floats, 0, 0);
989 array_append(p->x_strings, 0, 0);
990 array_append(p->x_namespaces, 0, 0);
991 array_append(p->x_namespace_sets, 0, 0);
992 array_append(p->x_multinames, 0, 0);
999 void pool_read(pool_t*pool, TAG*tag)
1001 int num_ints = swf_GetU30(tag);
1002 DEBUG printf("%d ints\n", num_ints);
1004 for(t=1;t<num_ints;t++) {
1005 S32 v = swf_GetABCS32(tag);
1006 DEBUG printf("int %d) %d\n", t, v);
1007 array_append(pool->x_ints, &v, 0);
1010 int num_uints = swf_GetU30(tag);
1011 DEBUG printf("%d uints\n", num_uints);
1012 for(t=1;t<num_uints;t++) {
1013 U32 v = swf_GetABCU32(tag);
1014 DEBUG printf("uint %d) %d\n", t, v);
1015 array_append(pool->x_uints, &v, 0);
1018 int num_floats = swf_GetU30(tag);
1019 DEBUG printf("%d floats\n", num_floats);
1020 for(t=1;t<num_floats;t++) {
1021 double d = swf_GetD64(tag);
1022 DEBUG printf("float %d) %f\n", t, d);
1023 array_append(pool->x_floats, &d, 0);
1026 int num_strings = swf_GetU30(tag);
1027 DEBUG printf("%d strings\n", num_strings);
1028 for(t=1;t<num_strings;t++) {
1029 int len = swf_GetU30(tag);
1030 char*s = malloc(len+1);
1031 swf_GetBlock(tag, s, len);
1033 array_append(pool->x_strings, s, (void*)(ptroff_t)len);
1035 DEBUG printf("%d) \"%s\"\n", t, pool->x_strings->d[t].name);
1037 int num_namespaces = swf_GetU30(tag);
1038 DEBUG printf("%d namespaces\n", num_namespaces);
1039 for(t=1;t<num_namespaces;t++) {
1040 U8 type = swf_GetU8(tag);
1041 int namenr = swf_GetU30(tag);
1042 const char*name = 0;
1044 name = array_getkey(pool->x_strings, namenr);
1045 namespace_t*ns = namespace_new(type, name);
1046 array_append(pool->x_namespaces, ns, 0);
1047 DEBUG printf("%d) %02x \"%s\"\n", t, type, namespace_tostring(ns));
1048 namespace_destroy(ns);
1050 int num_sets = swf_GetU30(tag);
1051 DEBUG printf("%d namespace sets\n", num_sets);
1052 for(t=1;t<num_sets;t++) {
1053 int count = swf_GetU30(tag);
1056 NEW(namespace_set_t, nsset);
1057 for(s=0;s<count;s++) {
1058 int nsnr = swf_GetU30(tag);
1060 fprintf(stderr, "Zero entry in namespace set\n");
1061 namespace_t*ns = (namespace_t*)array_getkey(pool->x_namespaces, nsnr);
1062 list_append(nsset->namespaces, namespace_clone(ns));
1064 array_append(pool->x_namespace_sets, nsset, 0);
1065 DEBUG printf("set %d) %s\n", t, namespace_set_tostring(nsset));
1066 namespace_set_destroy(nsset);
1069 int num_multinames = swf_GetU30(tag);
1070 DEBUG printf("%d multinames\n", num_multinames);
1071 for(t=1;t<num_multinames;t++) {
1073 memset(&m, 0, sizeof(multiname_t));
1074 m.type = swf_GetU8(tag);
1075 if(m.type==0x07 || m.type==0x0d) {
1076 int namespace_index = swf_GetU30(tag);
1077 m.ns = (namespace_t*)array_getkey(pool->x_namespaces, namespace_index);
1078 int name_index = swf_GetU30(tag);
1079 if(name_index) // 0 = '*' (any)
1080 m.name = array_getkey(pool->x_strings, name_index);
1081 } else if(m.type==0x0f || m.type==0x10) {
1082 int name_index = swf_GetU30(tag);
1083 if(name_index) // 0 = '*' (any name)
1084 m.name = array_getkey(pool->x_strings, name_index);
1085 } else if(m.type==0x11 || m.type==0x12) {
1086 } else if(m.type==0x09 || m.type==0x0e) {
1087 int name_index = swf_GetU30(tag);
1088 int namespace_set_index = swf_GetU30(tag);
1090 m.name = array_getkey(pool->x_strings, name_index);
1091 m.namespace_set = (namespace_set_t*)array_getkey(pool->x_namespace_sets, namespace_set_index);
1092 } else if(m.type==0x1b || m.type==0x1c) {
1093 int namespace_set_index = swf_GetU30(tag);
1094 m.namespace_set = (namespace_set_t*)array_getkey(pool->x_namespace_sets, namespace_set_index);
1096 printf("can't parse type %d multinames yet\n", m.type);
1098 DEBUG printf("multiname %d) %s\n", t, multiname_tostring(&m));
1099 array_append(pool->x_multinames, &m, 0);
1103 void pool_write(pool_t*pool, TAG*tag)
1107 /* make sure that all namespaces used by multinames / namespace sets
1108 and all strings used by namespaces exist */
1110 for(t=1;t<pool->x_multinames->num;t++) {
1111 multiname_t*m = (multiname_t*)array_getkey(pool->x_multinames, t);
1113 pool_register_namespace(pool, m->ns);
1115 if(m->namespace_set) {
1116 pool_register_namespace_set(pool, m->namespace_set);
1119 pool_register_string(pool, m->name);
1122 for(t=1;t<pool->x_namespace_sets->num;t++) {
1123 namespace_set_t*set = (namespace_set_t*)array_getkey(pool->x_namespace_sets, t);
1124 namespace_list_t*i = set->namespaces;
1126 pool_register_namespace(pool, i->namespace);
1130 for(t=1;t<pool->x_namespaces->num;t++) {
1131 namespace_t*ns= (namespace_t*)array_getkey(pool->x_namespaces, t);
1132 /* The spec says (page 22): "a value of zero denotes an empty string".
1133 However when actually using zero strings as empty namespaces, the
1134 flash player breaks.*/
1135 //if(ns->name && ns->name[0])
1136 pool_register_string(pool, ns->name);
1139 //pool_register_int(pool, 15);
1140 //pool_register_int(pool, 1);
1141 //pool_register_int(pool, 0);
1144 swf_SetU30(tag, pool->x_ints->num>1?pool->x_ints->num:0);
1145 for(t=1;t<pool->x_ints->num;t++) {
1146 S32 val = *(int*)array_getkey(pool->x_ints, t);
1147 swf_SetABCS32(tag, val);
1149 swf_SetU30(tag, pool->x_uints->num>1?pool->x_uints->num:0);
1150 for(t=1;t<pool->x_uints->num;t++) {
1151 swf_SetABCU32(tag, *(unsigned int*)array_getkey(pool->x_uints, t));
1153 swf_SetU30(tag, pool->x_floats->num>1?pool->x_floats->num:0);
1154 for(t=1;t<pool->x_floats->num;t++) {
1155 double d = pool_lookup_float(pool, t);
1158 swf_SetU30(tag, pool->x_strings->num>1?pool->x_strings->num:0);
1159 for(t=1;t<pool->x_strings->num;t++) {
1160 string_t str = pool_lookup_string2(pool, t);
1161 swf_SetU30String(tag, str.str, str.len);
1163 swf_SetU30(tag, pool->x_namespaces->num>1?pool->x_namespaces->num:0);
1164 for(t=1;t<pool->x_namespaces->num;t++) {
1165 namespace_t*ns= (namespace_t*)array_getkey(pool->x_namespaces, t);
1166 swf_SetU8(tag, ns->access);
1167 const char*name = ns->name;
1170 //if(name && name[0])
1171 i = pool_find_string(pool, name);
1175 swf_SetU30(tag, pool->x_namespace_sets->num>1?pool->x_namespace_sets->num:0);
1176 for(t=1;t<pool->x_namespace_sets->num;t++) {
1177 namespace_set_t*set = (namespace_set_t*)array_getkey(pool->x_namespace_sets, t);
1178 namespace_list_t*i = set->namespaces;
1179 int len = list_length(i);
1180 swf_SetU30(tag, len);
1182 int index = pool_find_namespace(pool, i->namespace);
1183 swf_SetU30(tag, index);
1188 swf_SetU30(tag, pool->x_multinames->num>1?pool->x_multinames->num:0);
1189 for(t=1;t<pool->x_multinames->num;t++) {
1190 multiname_t*m = (multiname_t*)array_getkey(pool->x_multinames, t);
1191 swf_SetU8(tag, m->type);
1194 assert(m->type==0x07 || m->type==0x0d);
1195 int i = pool_find_namespace(pool, m->ns);
1196 if(i<0) fprintf(stderr, "internal error: unregistered namespace %02x %s %s\n", m->ns->access, access2str(m->ns->access), m->ns->name);
1199 assert(m->type!=0x07 && m->type!=0x0d);
1202 assert(m->type==0x09 || m->type==0x0e || m->type==0x07 || m->type==0x0d || m->type==0x0f || m->type==0x10);
1203 int i = pool_find_string(pool, m->name);
1204 if(i<0) fprintf(stderr, "internal error: unregistered name\n");
1207 assert(m->type!=0x09 && m->type!=0x0e && m->type!=0x07 && m->type!=0x0d && m->type!=0x0f && m->type!=0x10);
1209 if(m->namespace_set) {
1210 assert(m->type==0x09 || m->type==0x0e || m->type==0x1c || m->type==0x1b);
1211 int i = pool_find_namespace_set(pool, m->namespace_set);
1212 if(i<0) fprintf(stderr, "internal error: unregistered namespace set\n");
1215 assert(m->type!=0x09 && m->type!=0x0e && m->type!=0x1c && m->type!=0x1b);
1221 void pool_destroy(pool_t*pool)
1224 array_free(pool->x_ints);
1225 array_free(pool->x_uints);
1226 array_free(pool->x_floats);
1227 array_free(pool->x_strings);
1228 array_free(pool->x_namespaces);
1229 array_free(pool->x_namespace_sets);
1230 array_free(pool->x_multinames);