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, "packageinternal")) access=0x17;
215 else if(!strcmp(a, "protected")) access=0x18;
216 else if(!strcmp(a, "explicit")) access=0x19;
217 else if(!strcmp(a, "staticprotected")) access=0x1a;
218 else if(!strcmp(a, "private")) access=0x05;
220 fprintf(stderr, "Undefined access level: [%s]\n", a);
226 ns->name = strdup(name);
231 ns->name = strdup(name);
236 namespace_t* namespace_new(U8 access, const char*name)
238 namespace_t*ns = malloc(sizeof(namespace_t));
240 /* not sure what namespaces with empty strings are good for, but they *do* exist */
241 ns->name = name?strdup(name):0;
244 namespace_t* namespace_new_undefined(const char*name) {
245 return namespace_new(0x08, name); // public?
247 namespace_t* namespace_new_package(const char*name) {
248 return namespace_new(0x16 , name);
250 namespace_t* namespace_new_packageinternal(const char*name) {
251 return namespace_new(0x17, name);
253 namespace_t* namespace_new_protected(const char*name) {
254 return namespace_new(0x18, name);
256 namespace_t* namespace_new_explicit(const char*name) {
257 return namespace_new(0x19, name);
259 namespace_t* namespace_new_staticprotected(const char*name) {
260 return namespace_new(0x1a, name);
262 namespace_t* namespace_new_private(const char*name) {
263 return namespace_new(0x05, name);
266 void namespace_destroy(namespace_t*n)
269 free(n->name);n->name=0;
275 type_t namespace_type = {
276 dup: (dup_func)namespace_clone,
277 hash: (hash_func)namespace_hash,
278 free: (free_func)namespace_destroy,
279 equals: (equals_func)namespace_equals
282 // ---------------------------namespace sets --------------------------------
284 unsigned int namespace_set_hash(namespace_set_t*set)
288 namespace_list_t*l = set->namespaces;
289 unsigned int hash = 0;
291 hash = crc32_add_byte(hash, l->namespace->access);
292 hash = crc32_add_string(hash, l->namespace->name);
298 int namespace_set_equals(namespace_set_t*m1, namespace_set_t*m2)
302 namespace_list_t*l1 = m1->namespaces;
303 namespace_list_t*l2 = m2->namespaces;
305 if(l1->namespace->access != l2->namespace->access)
307 if(!(l1->namespace->name) != !(l2->namespace->name))
309 if(l1->namespace->name && l2->namespace->name && strcmp(l1->namespace->name, l2->namespace->name))
319 namespace_set_t* namespace_set_clone(namespace_set_t*other)
323 NEW(namespace_set_t,set);
324 set->namespaces = list_new();
325 namespace_list_t*l = other->namespaces;
327 list_append(set->namespaces, namespace_clone(l->namespace));
332 namespace_set_t* namespace_set_new()
334 NEW(namespace_set_t,set);
335 set->namespaces = list_new();
338 char* namespace_set_tostring(namespace_set_t*set)
341 return strdup("NULL");
342 /* TODO: is the order of the namespaces important (does it
343 change the lookup order?). E.g. flex freely shuffles namespaces
345 If the order is not important, we can optimize constant pools by sorting
349 namespace_list_t*lns = set->namespaces;
351 char*s = namespace_tostring(lns->namespace);
356 char*desc = malloc(l+16);
358 lns = set->namespaces;
360 char*s = namespace_tostring(lns->namespace);
371 void namespace_set_destroy(namespace_set_t*set)
374 namespace_list_t*l = set->namespaces;
376 namespace_destroy(l->namespace);l->namespace=0;
379 list_free(set->namespaces);
384 type_t namespace_set_type = {
385 dup: (dup_func)namespace_set_clone,
386 hash: (hash_func)namespace_set_hash,
387 free: (free_func)namespace_set_destroy,
388 equals: (equals_func)namespace_set_equals
391 // ----------------------------- multiname ----------------------------------
393 unsigned int multiname_hash(multiname_t*m)
397 unsigned int hash = crc32_add_byte(0, m->type);
399 hash = crc32_add_string(hash, m->name);
402 hash = crc32_add_byte(hash, m->ns->access);
403 hash = crc32_add_string(hash, m->ns->name);
405 if(m->namespace_set) {
406 namespace_list_t*l = m->namespace_set->namespaces;
408 hash = crc32_add_byte(hash, l->namespace->access);
409 hash = crc32_add_string(hash, l->namespace->name);
416 int multiname_equals(multiname_t*m1, multiname_t*m2)
420 if(m1->type!=m2->type)
423 if((!m1->name) != (!m2->name))
425 if((!m1->ns) != (!m2->ns))
427 if((!m1->namespace_set) != (!m2->namespace_set))
430 if(m1->name && m2->name && strcmp(m1->name,m2->name))
432 if(m1->ns && m2->ns) {
433 if(!namespace_equals(m1->ns, m2->ns))
436 if(m1->namespace_set && m2->namespace_set) {
437 if(!namespace_set_equals(m1->namespace_set, m2->namespace_set))
443 multiname_t* multiname_new(namespace_t*ns, const char*name)
448 m->ns = namespace_new_packageinternal("");
450 m->ns = namespace_clone(ns);
452 m->name = strdup(name);
456 multiname_t* multiname_clone(multiname_t*other)
461 m->type = other->type;
463 m->ns = namespace_clone(other->ns);
464 if(other->namespace_set)
465 m->namespace_set = namespace_set_clone(other->namespace_set);
467 m->name = strdup(other->name);
472 char* access2str(int type)
474 if(type==0x08) return "access08";
475 else if(type==0x16) return "package";
476 else if(type==0x17) return "packageinternal";
477 else if(type==0x18) return "protected";
478 else if(type==0x19) return "explicit";
479 else if(type==0x1A) return "staticprotected";
480 else if(type==0x05) return "private";
482 fprintf(stderr, "Undefined access type %02x\n", type);
488 char multiname_late_namespace(multiname_t*m)
492 return (m->type==RTQNAME || m->type==RTQNAMEA ||
493 m->type==RTQNAMEL || m->type==RTQNAMELA);
496 char multiname_late_name(multiname_t*m)
500 return m->type==RTQNAMEL || m->type==RTQNAMELA ||
501 m->type==MULTINAMEL || m->type==MULTINAMELA;
504 char* multiname_tostring(multiname_t*m)
508 return strdup("NULL");
510 return strdup("--<MULTINAME 0xff>--");
512 char*name = m->name?escape_string(m->name):strdup("*");
513 int namelen = strlen(name);
515 if(m->type==QNAME || m->type==QNAMEA) {
516 char*nsname = escape_string(m->ns->name);
517 mname = malloc(strlen(nsname)+namelen+32);
519 if(m->type == QNAMEA)
520 strcat(mname, ",attr");
522 strcat(mname,access2str(m->ns->access));
524 strcat(mname, nsname);
528 } else if(m->type==RTQNAME || m->type==RTQNAMEA) {
529 mname = malloc(namelen+32);
530 strcpy(mname, "<rt");
531 if(m->type == RTQNAMEA)
532 strcat(mname, ",attr");
535 } else if(m->type==RTQNAMEL) {
536 mname = strdup("<rt,l>");
537 } else if(m->type==RTQNAMELA) {
538 mname = strdup("<rt,l,attr>");
539 } else if(m->type==MULTINAME || m->type==MULTINAMEA) {
540 char*s = namespace_set_tostring(m->namespace_set);
541 mname = malloc(strlen(s)+namelen+16);
542 if(m->type == MULTINAME)
543 strcpy(mname,"<multi>");
545 strcpy(mname,"<multi,attr>");
550 } else if(m->type==MULTINAMEL || m->type==MULTINAMELA) {
551 char*s = namespace_set_tostring(m->namespace_set);
552 mname = malloc(strlen(s)+16);
553 if(m->type == MULTINAMEL)
554 strcpy(mname,"<l,multi>");
556 strcpy(mname,"<l,multi,attr>");
560 fprintf(stderr, "Invalid multiname type: %02x\n", m->type);
566 multiname_t* multiname_fromstring(const char*name2)
570 char*n = strdup(name2);
571 char*p = strstr(n, "::");
572 char*namespace=0,*name=0;
575 fprintf(stderr, "Error: single ':' in name\n");
583 if(strchr(namespace, ':')) {
584 fprintf(stderr, "Error: single ':' in namespace\n");
586 if(strchr(name, ':')) {
587 fprintf(stderr, "Error: single ':' in qualified name\n");
591 multiname_t*m = malloc(sizeof(multiname_t));
592 memset(m, 0, sizeof(multiname_t));
594 m->namespace_set = 0;
595 m->ns = namespace_fromstring(namespace);
596 m->name = name?strdup(name):0;
601 void multiname_destroy(multiname_t*m)
605 free((void*)m->name);m->name = 0;
608 namespace_destroy(m->ns);m->ns = 0;
610 if(m->namespace_set) {
611 namespace_set_destroy(m->namespace_set);m->namespace_set = 0;
617 type_t multiname_type = {
618 dup: (dup_func)multiname_clone,
619 hash: (hash_func)multiname_hash,
620 free: (free_func)multiname_destroy,
621 equals: (equals_func)multiname_equals
625 // ------------------------------- constants -------------------------------------
627 #define NS_TYPE(x) ((x) == 0x08 || (x) == 0x16 || (x) == 0x17 || (x) == 0x18 || \
628 (x) == 0x19 || (x) == 0x1a || (x) == 0x05)
630 #define UNIQUE_CONSTANT(x) ((x) == CONSTANT_TRUE || (x) == CONSTANT_FALSE || (x) == CONSTANT_NULL || (x) == CONSTANT_UNDEFINED)
632 constant_t* constant_new_int(int i)
636 c->type = CONSTANT_INT;
639 constant_t* constant_new_uint(unsigned int u)
643 c->type = CONSTANT_UINT;
646 constant_t* constant_new_float(double f)
650 c->type = CONSTANT_FLOAT;
653 constant_t* constant_new_string(char*s)
657 c->type = CONSTANT_STRING;
660 constant_t* constant_new_namespace(namespace_t*ns)
663 c->ns = namespace_clone(ns);
664 c->type = ns->access;
665 assert(NS_TYPE(c->type));
668 constant_t* constant_new_true()
671 c->type = CONSTANT_TRUE;
674 constant_t* constant_new_false()
677 c->type = CONSTANT_FALSE;
680 constant_t* constant_new_null()
683 c->type = CONSTANT_NULL;
686 constant_t* constant_new_undefined()
689 c->type = CONSTANT_UNDEFINED;
692 constant_t* constant_fromindex(pool_t*pool, int index, int type)
695 /* even for nonvalued constants (like TRUE/FALSE etc.), a nonzero
696 index is present to indicate that a type is coming */
701 if(NS_TYPE(c->type)) {
702 c->ns = namespace_clone(pool_lookup_namespace(pool, index));
703 } else if(c->type == CONSTANT_INT) {
704 c->i = pool_lookup_int(pool, index);
705 } else if(c->type == CONSTANT_UINT) {
706 c->u = pool_lookup_uint(pool, index);
707 } else if(c->type == CONSTANT_FLOAT) {
708 c->f = pool_lookup_float(pool, index);
709 } else if(c->type == CONSTANT_STRING) {
710 c->s = strdup(pool_lookup_string(pool, index));
711 } else if(UNIQUE_CONSTANT(c->type)) {
714 fprintf(stderr, "invalid constant type %02x\n", c->type);
718 char* constant_tostring(constant_t*c)
723 if(NS_TYPE(c->type)) {
724 return namespace_tostring(c->ns);
725 } else if(c->type == CONSTANT_INT) {
726 sprintf(buf, "%d", c->i);
728 } else if(c->type == CONSTANT_UINT) {
729 sprintf(buf, "%u", c->u);
731 } else if(c->type == CONSTANT_FLOAT) {
732 sprintf(buf, "%f", c->f);
734 } else if(c->type == CONSTANT_STRING) {
736 } else if(c->type == CONSTANT_TRUE) {
737 return strdup("true");
738 } else if(c->type == CONSTANT_FALSE) {
739 return strdup("false");
740 } else if(c->type == CONSTANT_NULL) {
741 return strdup("null");
742 } else if(c->type == CONSTANT_UNDEFINED) {
743 return strdup("undefined");
745 fprintf(stderr, "invalid constant type %02x\n", c->type);
749 char constant_has_index(constant_t*c)
753 return !UNIQUE_CONSTANT(c->type);
755 int constant_get_index(pool_t*pool, constant_t*c)
759 if(NS_TYPE(c->type)) {
761 /*if(c->type!=c->ns->access) {
762 printf("%02x<->%02x\n", c->type, c->ns->access);
764 assert(c->type == c->ns->access);
765 return pool_register_namespace(pool, c->ns);
766 } else if(c->type == CONSTANT_INT) {
767 return pool_register_int(pool, c->i);
768 } else if(c->type == CONSTANT_UINT) {
769 return pool_register_uint(pool, c->u);
770 } else if(c->type == CONSTANT_FLOAT) {
771 return pool_register_float(pool, c->f);
772 } else if(c->type == CONSTANT_STRING) {
773 return pool_register_string(pool, c->s);
774 } else if(!constant_has_index(c)) {
777 fprintf(stderr, "invalid constant type %02x\n", c->type);
781 void constant_free(constant_t*c)
785 if(c->type == CONSTANT_STRING) {
787 } else if (NS_TYPE(c->type)) {
788 namespace_destroy(c->ns);c->ns=0;
792 // ------------------------------- pool -------------------------------------
794 int pool_register_uint(pool_t*p, unsigned int i)
796 int pos = array_append_if_new(p->x_uints, &i, 0);
800 int pool_register_int(pool_t*p, int i)
802 int pos = array_append_if_new(p->x_ints, &i, 0);
806 int pool_register_float(pool_t*p, double d)
808 int pos = array_append_if_new(p->x_floats, &d, 0);
812 int pool_register_string(pool_t*pool, const char*s)
815 int pos = array_append_if_new(pool->x_strings, s, 0);
819 int pool_register_namespace(pool_t*pool, namespace_t*ns)
822 int pos = array_append_if_new(pool->x_namespaces, ns, 0);
826 int pool_register_namespace_set(pool_t*pool, namespace_set_t*set)
829 int pos = array_append_if_new(pool->x_namespace_sets, set, 0);
833 int pool_register_multiname(pool_t*pool, multiname_t*n)
836 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 namespace_t*pool_lookup_namespace(pool_t*pool, int i)
953 return (namespace_t*)array_getkey(pool->x_namespaces, i);
955 namespace_set_t*pool_lookup_namespace_set(pool_t*pool, int i)
957 return (namespace_set_t*)array_getkey(pool->x_namespace_sets, i);
959 multiname_t*pool_lookup_multiname(pool_t*pool, int i)
961 return (multiname_t*)array_getkey(pool->x_multinames, i);
968 p->x_ints = array_new2(&uint_type);
969 p->x_uints = array_new2(&uint_type);
970 p->x_floats = array_new2(&float_type);
971 p->x_strings = array_new2(&charptr_type);
972 p->x_namespaces = array_new2(&namespace_type);
973 p->x_namespace_sets = array_new2(&namespace_set_type);
974 p->x_multinames = array_new2(&multiname_type);
976 /* add a zero-index entry in each list */
978 array_append(p->x_ints, 0, 0);
979 array_append(p->x_uints, 0, 0);
980 array_append(p->x_floats, 0, 0);
981 array_append(p->x_strings, 0, 0);
982 array_append(p->x_namespaces, 0, 0);
983 array_append(p->x_namespace_sets, 0, 0);
984 array_append(p->x_multinames, 0, 0);
991 void pool_read(pool_t*pool, TAG*tag)
993 int num_ints = swf_GetU30(tag);
994 DEBUG printf("%d ints\n", num_ints);
996 for(t=1;t<num_ints;t++) {
997 S32 v = swf_GetS30(tag);
998 DEBUG printf("int %d) %d\n", t, v);
999 array_append(pool->x_ints, &v, 0);
1002 int num_uints = swf_GetU30(tag);
1003 DEBUG printf("%d uints\n", num_uints);
1004 for(t=1;t<num_uints;t++) {
1005 U32 v = swf_GetU30(tag);
1006 DEBUG printf("uint %d) %d\n", t, v);
1007 array_append(pool->x_uints, &v, 0);
1010 int num_floats = swf_GetU30(tag);
1011 DEBUG printf("%d floats\n", num_floats);
1012 for(t=1;t<num_floats;t++) {
1013 double d = swf_GetD64(tag);
1014 DEBUG printf("float %d) %f\n", t, d);
1015 array_append(pool->x_floats, &d, 0);
1018 int num_strings = swf_GetU30(tag);
1019 DEBUG printf("%d strings\n", num_strings);
1020 for(t=1;t<num_strings;t++) {
1021 int len = swf_GetU30(tag);
1022 char*s = malloc(len+1);
1023 swf_GetBlock(tag, s, len);
1025 array_append(pool->x_strings, s, 0);
1027 DEBUG printf("%d) \"%s\"\n", t, pool->x_strings->d[t].name);
1029 int num_namespaces = swf_GetU30(tag);
1030 DEBUG printf("%d namespaces\n", num_namespaces);
1031 for(t=1;t<num_namespaces;t++) {
1032 U8 type = swf_GetU8(tag);
1033 int namenr = swf_GetU30(tag);
1034 const char*name = 0;
1036 name = array_getkey(pool->x_strings, namenr);
1037 namespace_t*ns = namespace_new(type, name);
1038 array_append(pool->x_namespaces, ns, 0);
1039 DEBUG printf("%d) %02x \"%s\"\n", t, type, namespace_tostring(ns));
1040 namespace_destroy(ns);
1042 int num_sets = swf_GetU30(tag);
1043 DEBUG printf("%d namespace sets\n", num_sets);
1044 for(t=1;t<num_sets;t++) {
1045 int count = swf_GetU30(tag);
1048 NEW(namespace_set_t, nsset);
1049 for(s=0;s<count;s++) {
1050 int nsnr = swf_GetU30(tag);
1052 fprintf(stderr, "Zero entry in namespace set\n");
1053 namespace_t*ns = (namespace_t*)array_getkey(pool->x_namespaces, nsnr);
1054 list_append(nsset->namespaces, namespace_clone(ns));
1056 array_append(pool->x_namespace_sets, nsset, 0);
1057 DEBUG printf("set %d) %s\n", t, namespace_set_tostring(nsset));
1058 namespace_set_destroy(nsset);
1061 int num_multinames = swf_GetU30(tag);
1062 DEBUG printf("%d multinames\n", num_multinames);
1063 for(t=1;t<num_multinames;t++) {
1065 memset(&m, 0, sizeof(multiname_t));
1066 m.type = swf_GetU8(tag);
1067 if(m.type==0x07 || m.type==0x0d) {
1068 int namespace_index = swf_GetU30(tag);
1069 m.ns = (namespace_t*)array_getkey(pool->x_namespaces, namespace_index);
1070 int name_index = swf_GetU30(tag);
1071 if(name_index) // 0 = '*' (any)
1072 m.name = array_getkey(pool->x_strings, name_index);
1073 } else if(m.type==0x0f || m.type==0x10) {
1074 int name_index = swf_GetU30(tag);
1075 if(name_index) // 0 = '*' (any name)
1076 m.name = array_getkey(pool->x_strings, name_index);
1077 } else if(m.type==0x11 || m.type==0x12) {
1078 } else if(m.type==0x09 || m.type==0x0e) {
1079 int name_index = swf_GetU30(tag);
1080 int namespace_set_index = swf_GetU30(tag);
1082 m.name = array_getkey(pool->x_strings, name_index);
1083 m.namespace_set = (namespace_set_t*)array_getkey(pool->x_namespace_sets, namespace_set_index);
1084 } else if(m.type==0x1b || m.type==0x1c) {
1085 int namespace_set_index = swf_GetU30(tag);
1086 m.namespace_set = (namespace_set_t*)array_getkey(pool->x_namespace_sets, namespace_set_index);
1088 printf("can't parse type %d multinames yet\n", m.type);
1090 DEBUG printf("multiname %d) %s\n", t, multiname_tostring(&m));
1091 array_append(pool->x_multinames, &m, 0);
1095 void pool_write(pool_t*pool, TAG*tag)
1099 /* make sure that all namespaces used by multinames / namespace sets
1100 and all strings used by namespaces exist */
1102 for(t=1;t<pool->x_multinames->num;t++) {
1103 multiname_t*m = (multiname_t*)array_getkey(pool->x_multinames, t);
1105 pool_register_namespace(pool, m->ns);
1107 if(m->namespace_set) {
1108 pool_register_namespace_set(pool, m->namespace_set);
1111 pool_register_string(pool, m->name);
1114 for(t=1;t<pool->x_namespace_sets->num;t++) {
1115 namespace_set_t*set = (namespace_set_t*)array_getkey(pool->x_namespace_sets, t);
1116 namespace_list_t*i = set->namespaces;
1118 pool_register_namespace(pool, i->namespace);
1122 for(t=1;t<pool->x_namespaces->num;t++) {
1123 namespace_t*ns= (namespace_t*)array_getkey(pool->x_namespaces, t);
1124 /* The spec says (page 22): "a value of zero denotes an empty string".
1125 However when actually using zero strings as empty namespaces, the
1126 flash player breaks.*/
1127 //if(ns->name && ns->name[0])
1128 array_append_if_new(pool->x_strings, ns->name, 0);
1131 //pool_register_int(pool, 15);
1132 //pool_register_int(pool, 1);
1133 //pool_register_int(pool, 0);
1136 swf_SetU30(tag, pool->x_ints->num>1?pool->x_ints->num:0);
1137 for(t=1;t<pool->x_ints->num;t++) {
1138 S32 val = *(int*)array_getkey(pool->x_ints, t);
1139 swf_SetS30(tag, val);
1141 swf_SetU30(tag, pool->x_uints->num>1?pool->x_uints->num:0);
1142 for(t=1;t<pool->x_uints->num;t++) {
1143 swf_SetU30(tag, *(unsigned int*)array_getkey(pool->x_uints, t));
1145 swf_SetU30(tag, pool->x_floats->num>1?pool->x_floats->num:0);
1146 for(t=1;t<pool->x_floats->num;t++) {
1147 double d = pool_lookup_float(pool, t);
1150 swf_SetU30(tag, pool->x_strings->num>1?pool->x_strings->num:0);
1151 for(t=1;t<pool->x_strings->num;t++) {
1152 swf_SetU30String(tag, array_getkey(pool->x_strings, t));
1154 swf_SetU30(tag, pool->x_namespaces->num>1?pool->x_namespaces->num:0);
1155 for(t=1;t<pool->x_namespaces->num;t++) {
1156 namespace_t*ns= (namespace_t*)array_getkey(pool->x_namespaces, t);
1157 swf_SetU8(tag, ns->access);
1158 const char*name = ns->name;
1161 //if(name && name[0])
1162 i = pool_find_string(pool, name);
1166 swf_SetU30(tag, pool->x_namespace_sets->num>1?pool->x_namespace_sets->num:0);
1167 for(t=1;t<pool->x_namespace_sets->num;t++) {
1168 namespace_set_t*set = (namespace_set_t*)array_getkey(pool->x_namespace_sets, t);
1169 namespace_list_t*i = set->namespaces;
1170 int len = list_length(i);
1171 swf_SetU30(tag, len);
1173 int index = pool_find_namespace(pool, i->namespace);
1174 swf_SetU30(tag, index);
1179 swf_SetU30(tag, pool->x_multinames->num>1?pool->x_multinames->num:0);
1180 for(t=1;t<pool->x_multinames->num;t++) {
1181 multiname_t*m = (multiname_t*)array_getkey(pool->x_multinames, t);
1182 swf_SetU8(tag, m->type);
1185 assert(m->type==0x07 || m->type==0x0d);
1186 int i = pool_find_namespace(pool, m->ns);
1187 if(i<0) fprintf(stderr, "internal error: unregistered namespace %02x %s %s\n", m->ns->access, access2str(m->ns->access), m->ns->name);
1190 assert(m->type!=0x07 && m->type!=0x0d);
1193 assert(m->type==0x09 || m->type==0x0e || m->type==0x07 || m->type==0x0d || m->type==0x0f || m->type==0x10);
1194 int i = pool_find_string(pool, m->name);
1195 if(i<0) fprintf(stderr, "internal error: unregistered name\n");
1198 assert(m->type!=0x09 && m->type!=0x0e && m->type!=0x07 && m->type!=0x0d && m->type!=0x0f && m->type!=0x10);
1200 if(m->namespace_set) {
1201 assert(m->type==0x09 || m->type==0x0e || m->type==0x1c || m->type==0x1b);
1202 int i = pool_find_namespace_set(pool, m->namespace_set);
1203 if(i<0) fprintf(stderr, "internal error: unregistered namespace set\n");
1206 assert(m->type!=0x09 && m->type!=0x0e && m->type!=0x1c && m->type!=0x1b);
1212 void pool_destroy(pool_t*pool)
1215 array_free(pool->x_ints);
1216 array_free(pool->x_uints);
1217 array_free(pool->x_floats);
1218 array_free(pool->x_strings);
1219 array_free(pool->x_namespaces);
1220 array_free(pool->x_namespace_sets);
1221 array_free(pool->x_multinames);