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) {
734 sprintf(buf, "%f", c->f);
736 } else if(c->type == CONSTANT_STRING) {
738 } else if(c->type == CONSTANT_TRUE) {
739 return strdup("true");
740 } else if(c->type == CONSTANT_FALSE) {
741 return strdup("false");
742 } else if(c->type == CONSTANT_NULL) {
743 return strdup("null");
744 } else if(c->type == CONSTANT_UNDEFINED) {
745 return strdup("undefined");
747 fprintf(stderr, "invalid constant type %02x\n", c->type);
751 char constant_has_index(constant_t*c)
755 return !UNIQUE_CONSTANT(c->type);
757 int constant_get_index(pool_t*pool, constant_t*c)
761 if(NS_TYPE(c->type)) {
763 /*if(c->type!=c->ns->access) {
764 printf("%02x<->%02x\n", c->type, c->ns->access);
766 assert(c->type == c->ns->access);
767 return pool_register_namespace(pool, c->ns);
768 } else if(c->type == CONSTANT_INT) {
769 return pool_register_int(pool, c->i);
770 } else if(c->type == CONSTANT_UINT) {
771 return pool_register_uint(pool, c->u);
772 } else if(c->type == CONSTANT_FLOAT) {
773 return pool_register_float(pool, c->f);
774 } else if(c->type == CONSTANT_STRING) {
775 return pool_register_string(pool, c->s);
776 } else if(!constant_has_index(c)) {
779 fprintf(stderr, "invalid constant type %02x\n", c->type);
783 void constant_free(constant_t*c)
787 if(c->type == CONSTANT_STRING) {
789 } else if (NS_TYPE(c->type)) {
790 namespace_destroy(c->ns);c->ns=0;
794 // ------------------------------- pool -------------------------------------
796 int pool_register_uint(pool_t*p, unsigned int i)
798 int pos = array_append_if_new(p->x_uints, &i, 0);
802 int pool_register_int(pool_t*p, int i)
804 int pos = array_append_if_new(p->x_ints, &i, 0);
808 int pool_register_float(pool_t*p, double d)
810 int pos = array_append_if_new(p->x_floats, &d, 0);
814 int pool_register_string(pool_t*pool, const char*s)
817 ptroff_t l = strlen(s);
818 int pos = array_append_if_new(pool->x_strings, s, (void*)l);
822 int pool_register_namespace(pool_t*pool, namespace_t*ns)
825 int pos = array_append_if_new(pool->x_namespaces, ns, 0);
829 int pool_register_namespace_set(pool_t*pool, namespace_set_t*set)
832 int pos = array_append_if_new(pool->x_namespace_sets, set, 0);
836 int pool_register_multiname(pool_t*pool, multiname_t*n)
839 int pos = array_append_if_new(pool->x_multinames, n, 0);
843 int pool_register_multiname2(pool_t*pool, char*name)
846 multiname_t*n = multiname_fromstring(name);
847 int pos = array_append_if_new(pool->x_multinames, n, 0);
848 multiname_destroy(n);
854 int pool_find_uint(pool_t*pool, unsigned int x)
856 int i = array_find(pool->x_uints, &x);
858 fprintf(stderr, "Couldn't find uint \"%d\" in constant pool\n", x);
863 int pool_find_int(pool_t*pool, int x)
865 int i = array_find(pool->x_ints, &x);
867 fprintf(stderr, "Couldn't find int \"%d\" in constant pool\n", x);
872 int pool_find_float(pool_t*pool, double x)
874 int i = array_find(pool->x_ints, &x);
876 fprintf(stderr, "Couldn't find int \"%d\" in constant pool\n", x);
881 int pool_find_namespace(pool_t*pool, namespace_t*ns)
885 int i = array_find(pool->x_namespaces, ns);
887 char*s = namespace_tostring(ns);
888 fprintf(stderr, "Couldn't find namespace \"%s\" %08x in constant pool\n", s, ns);
894 int pool_find_namespace_set(pool_t*pool, namespace_set_t*set)
898 int i = array_find(pool->x_namespace_sets, set);
900 char*s = namespace_set_tostring(set);
901 fprintf(stderr, "Couldn't find namespace_set \"%s\" in constant pool\n", s);
907 int pool_find_string(pool_t*pool, const char*s)
911 int i = array_find(pool->x_strings, s);
913 fprintf(stderr, "Couldn't find string \"%s\" in constant pool\n", s);
918 int pool_find_multiname(pool_t*pool, multiname_t*name)
922 int i = array_find(pool->x_multinames, name);
924 char*s = multiname_tostring(name);
925 fprintf(stderr, "Couldn't find multiname \"%s\" in constant pool\n", s);
932 int pool_lookup_int(pool_t*pool, int i)
935 return *(int*)array_getkey(pool->x_ints, i);
937 unsigned int pool_lookup_uint(pool_t*pool, int i)
940 return *(unsigned int*)array_getkey(pool->x_uints, i);
942 double pool_lookup_float(pool_t*pool, int i)
944 if(!i) return __builtin_nan("");
945 return *(double*)array_getkey(pool->x_floats, i);
947 char*pool_lookup_string(pool_t*pool, int i)
949 return (char*)array_getkey(pool->x_strings, i);
951 string_t pool_lookup_string2(pool_t*pool, int i)
953 char*s = (char*)array_getkey(pool->x_strings, i);
954 int len = (int)(ptroff_t)array_getvalue(pool->x_strings, i);
955 return string_new(s,len);
957 namespace_t*pool_lookup_namespace(pool_t*pool, int i)
959 return (namespace_t*)array_getkey(pool->x_namespaces, i);
961 namespace_set_t*pool_lookup_namespace_set(pool_t*pool, int i)
963 return (namespace_set_t*)array_getkey(pool->x_namespace_sets, i);
965 multiname_t*pool_lookup_multiname(pool_t*pool, int i)
967 return (multiname_t*)array_getkey(pool->x_multinames, i);
974 p->x_ints = array_new2(&uint_type);
975 p->x_uints = array_new2(&uint_type);
976 p->x_floats = array_new2(&float_type);
977 p->x_strings = array_new2(&charptr_type);
978 p->x_namespaces = array_new2(&namespace_type);
979 p->x_namespace_sets = array_new2(&namespace_set_type);
980 p->x_multinames = array_new2(&multiname_type);
982 /* add a zero-index entry in each list */
984 array_append(p->x_ints, 0, 0);
985 array_append(p->x_uints, 0, 0);
986 array_append(p->x_floats, 0, 0);
987 array_append(p->x_strings, 0, 0);
988 array_append(p->x_namespaces, 0, 0);
989 array_append(p->x_namespace_sets, 0, 0);
990 array_append(p->x_multinames, 0, 0);
997 void pool_read(pool_t*pool, TAG*tag)
999 int num_ints = swf_GetU30(tag);
1000 DEBUG printf("%d ints\n", num_ints);
1002 for(t=1;t<num_ints;t++) {
1003 S32 v = swf_GetABCS32(tag);
1004 DEBUG printf("int %d) %d\n", t, v);
1005 array_append(pool->x_ints, &v, 0);
1008 int num_uints = swf_GetU30(tag);
1009 DEBUG printf("%d uints\n", num_uints);
1010 for(t=1;t<num_uints;t++) {
1011 U32 v = swf_GetABCU32(tag);
1012 DEBUG printf("uint %d) %d\n", t, v);
1013 array_append(pool->x_uints, &v, 0);
1016 int num_floats = swf_GetU30(tag);
1017 DEBUG printf("%d floats\n", num_floats);
1018 for(t=1;t<num_floats;t++) {
1019 double d = swf_GetD64(tag);
1020 DEBUG printf("float %d) %f\n", t, d);
1021 array_append(pool->x_floats, &d, 0);
1024 int num_strings = swf_GetU30(tag);
1025 DEBUG printf("%d strings\n", num_strings);
1026 for(t=1;t<num_strings;t++) {
1027 int len = swf_GetU30(tag);
1028 char*s = malloc(len+1);
1029 swf_GetBlock(tag, s, len);
1031 array_append(pool->x_strings, s, (void*)(ptroff_t)len);
1033 DEBUG printf("%d) \"%s\"\n", t, pool->x_strings->d[t].name);
1035 int num_namespaces = swf_GetU30(tag);
1036 DEBUG printf("%d namespaces\n", num_namespaces);
1037 for(t=1;t<num_namespaces;t++) {
1038 U8 type = swf_GetU8(tag);
1039 int namenr = swf_GetU30(tag);
1040 const char*name = 0;
1042 name = array_getkey(pool->x_strings, namenr);
1043 namespace_t*ns = namespace_new(type, name);
1044 array_append(pool->x_namespaces, ns, 0);
1045 DEBUG printf("%d) %02x \"%s\"\n", t, type, namespace_tostring(ns));
1046 namespace_destroy(ns);
1048 int num_sets = swf_GetU30(tag);
1049 DEBUG printf("%d namespace sets\n", num_sets);
1050 for(t=1;t<num_sets;t++) {
1051 int count = swf_GetU30(tag);
1054 NEW(namespace_set_t, nsset);
1055 for(s=0;s<count;s++) {
1056 int nsnr = swf_GetU30(tag);
1058 fprintf(stderr, "Zero entry in namespace set\n");
1059 namespace_t*ns = (namespace_t*)array_getkey(pool->x_namespaces, nsnr);
1060 list_append(nsset->namespaces, namespace_clone(ns));
1062 array_append(pool->x_namespace_sets, nsset, 0);
1063 DEBUG printf("set %d) %s\n", t, namespace_set_tostring(nsset));
1064 namespace_set_destroy(nsset);
1067 int num_multinames = swf_GetU30(tag);
1068 DEBUG printf("%d multinames\n", num_multinames);
1069 for(t=1;t<num_multinames;t++) {
1071 memset(&m, 0, sizeof(multiname_t));
1072 m.type = swf_GetU8(tag);
1073 if(m.type==0x07 || m.type==0x0d) {
1074 int namespace_index = swf_GetU30(tag);
1075 m.ns = (namespace_t*)array_getkey(pool->x_namespaces, namespace_index);
1076 int name_index = swf_GetU30(tag);
1077 if(name_index) // 0 = '*' (any)
1078 m.name = array_getkey(pool->x_strings, name_index);
1079 } else if(m.type==0x0f || m.type==0x10) {
1080 int name_index = swf_GetU30(tag);
1081 if(name_index) // 0 = '*' (any name)
1082 m.name = array_getkey(pool->x_strings, name_index);
1083 } else if(m.type==0x11 || m.type==0x12) {
1084 } else if(m.type==0x09 || m.type==0x0e) {
1085 int name_index = swf_GetU30(tag);
1086 int namespace_set_index = swf_GetU30(tag);
1088 m.name = array_getkey(pool->x_strings, name_index);
1089 m.namespace_set = (namespace_set_t*)array_getkey(pool->x_namespace_sets, namespace_set_index);
1090 } else if(m.type==0x1b || m.type==0x1c) {
1091 int namespace_set_index = swf_GetU30(tag);
1092 m.namespace_set = (namespace_set_t*)array_getkey(pool->x_namespace_sets, namespace_set_index);
1094 printf("can't parse type %d multinames yet\n", m.type);
1096 DEBUG printf("multiname %d) %s\n", t, multiname_tostring(&m));
1097 array_append(pool->x_multinames, &m, 0);
1101 void pool_write(pool_t*pool, TAG*tag)
1105 /* make sure that all namespaces used by multinames / namespace sets
1106 and all strings used by namespaces exist */
1108 for(t=1;t<pool->x_multinames->num;t++) {
1109 multiname_t*m = (multiname_t*)array_getkey(pool->x_multinames, t);
1111 pool_register_namespace(pool, m->ns);
1113 if(m->namespace_set) {
1114 pool_register_namespace_set(pool, m->namespace_set);
1117 pool_register_string(pool, m->name);
1120 for(t=1;t<pool->x_namespace_sets->num;t++) {
1121 namespace_set_t*set = (namespace_set_t*)array_getkey(pool->x_namespace_sets, t);
1122 namespace_list_t*i = set->namespaces;
1124 pool_register_namespace(pool, i->namespace);
1128 for(t=1;t<pool->x_namespaces->num;t++) {
1129 namespace_t*ns= (namespace_t*)array_getkey(pool->x_namespaces, t);
1130 /* The spec says (page 22): "a value of zero denotes an empty string".
1131 However when actually using zero strings as empty namespaces, the
1132 flash player breaks.*/
1133 //if(ns->name && ns->name[0])
1134 pool_register_string(pool, ns->name);
1137 //pool_register_int(pool, 15);
1138 //pool_register_int(pool, 1);
1139 //pool_register_int(pool, 0);
1142 swf_SetU30(tag, pool->x_ints->num>1?pool->x_ints->num:0);
1143 for(t=1;t<pool->x_ints->num;t++) {
1144 S32 val = *(int*)array_getkey(pool->x_ints, t);
1145 swf_SetABCS32(tag, val);
1147 swf_SetU30(tag, pool->x_uints->num>1?pool->x_uints->num:0);
1148 for(t=1;t<pool->x_uints->num;t++) {
1149 swf_SetABCU32(tag, *(unsigned int*)array_getkey(pool->x_uints, t));
1151 swf_SetU30(tag, pool->x_floats->num>1?pool->x_floats->num:0);
1152 for(t=1;t<pool->x_floats->num;t++) {
1153 double d = pool_lookup_float(pool, t);
1156 swf_SetU30(tag, pool->x_strings->num>1?pool->x_strings->num:0);
1157 for(t=1;t<pool->x_strings->num;t++) {
1158 string_t str = pool_lookup_string2(pool, t);
1159 swf_SetU30String(tag, str.str, str.len);
1161 swf_SetU30(tag, pool->x_namespaces->num>1?pool->x_namespaces->num:0);
1162 for(t=1;t<pool->x_namespaces->num;t++) {
1163 namespace_t*ns= (namespace_t*)array_getkey(pool->x_namespaces, t);
1164 swf_SetU8(tag, ns->access);
1165 const char*name = ns->name;
1168 //if(name && name[0])
1169 i = pool_find_string(pool, name);
1173 swf_SetU30(tag, pool->x_namespace_sets->num>1?pool->x_namespace_sets->num:0);
1174 for(t=1;t<pool->x_namespace_sets->num;t++) {
1175 namespace_set_t*set = (namespace_set_t*)array_getkey(pool->x_namespace_sets, t);
1176 namespace_list_t*i = set->namespaces;
1177 int len = list_length(i);
1178 swf_SetU30(tag, len);
1180 int index = pool_find_namespace(pool, i->namespace);
1181 swf_SetU30(tag, index);
1186 swf_SetU30(tag, pool->x_multinames->num>1?pool->x_multinames->num:0);
1187 for(t=1;t<pool->x_multinames->num;t++) {
1188 multiname_t*m = (multiname_t*)array_getkey(pool->x_multinames, t);
1189 swf_SetU8(tag, m->type);
1192 assert(m->type==0x07 || m->type==0x0d);
1193 int i = pool_find_namespace(pool, m->ns);
1194 if(i<0) fprintf(stderr, "internal error: unregistered namespace %02x %s %s\n", m->ns->access, access2str(m->ns->access), m->ns->name);
1197 assert(m->type!=0x07 && m->type!=0x0d);
1200 assert(m->type==0x09 || m->type==0x0e || m->type==0x07 || m->type==0x0d || m->type==0x0f || m->type==0x10);
1201 int i = pool_find_string(pool, m->name);
1202 if(i<0) fprintf(stderr, "internal error: unregistered name\n");
1205 assert(m->type!=0x09 && m->type!=0x0e && m->type!=0x07 && m->type!=0x0d && m->type!=0x0f && m->type!=0x10);
1207 if(m->namespace_set) {
1208 assert(m->type==0x09 || m->type==0x0e || m->type==0x1c || m->type==0x1b);
1209 int i = pool_find_namespace_set(pool, m->namespace_set);
1210 if(i<0) fprintf(stderr, "internal error: unregistered namespace set\n");
1213 assert(m->type!=0x09 && m->type!=0x0e && m->type!=0x1c && m->type!=0x1b);
1219 void pool_destroy(pool_t*pool)
1222 array_free(pool->x_ints);
1223 array_free(pool->x_uints);
1224 array_free(pool->x_floats);
1225 array_free(pool->x_strings);
1226 array_free(pool->x_namespaces);
1227 array_free(pool->x_namespace_sets);
1228 array_free(pool->x_multinames);