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;
619 type_t multiname_type = {
620 dup: (dup_func)multiname_clone,
621 hash: (hash_func)multiname_hash,
622 free: (free_func)multiname_destroy,
623 equals: (equals_func)multiname_equals
627 // ------------------------------- constants -------------------------------------
629 #define NS_TYPE(x) ((x) == 0x08 || (x) == 0x16 || (x) == 0x17 || (x) == 0x18 || \
630 (x) == 0x19 || (x) == 0x1a || (x) == 0x05)
632 #define UNIQUE_CONSTANT(x) ((x) == CONSTANT_TRUE || (x) == CONSTANT_FALSE || (x) == CONSTANT_NULL || (x) == CONSTANT_UNDEFINED)
634 constant_t* constant_new_int(int i)
638 c->type = CONSTANT_INT;
641 constant_t* constant_new_uint(unsigned int u)
645 c->type = CONSTANT_UINT;
648 constant_t* constant_new_float(double f)
652 c->type = CONSTANT_FLOAT;
655 constant_t* constant_new_string(char*s)
659 c->type = CONSTANT_STRING;
662 constant_t* constant_new_namespace(namespace_t*ns)
665 c->ns = namespace_clone(ns);
666 c->type = ns->access;
667 assert(NS_TYPE(c->type));
670 constant_t* constant_new_true()
673 c->type = CONSTANT_TRUE;
676 constant_t* constant_new_false()
679 c->type = CONSTANT_FALSE;
682 constant_t* constant_new_null()
685 c->type = CONSTANT_NULL;
688 constant_t* constant_new_undefined()
691 c->type = CONSTANT_UNDEFINED;
694 constant_t* constant_fromindex(pool_t*pool, int index, int type)
697 /* even for nonvalued constants (like TRUE/FALSE etc.), a nonzero
698 index is present to indicate that a type is coming */
703 if(NS_TYPE(c->type)) {
704 c->ns = namespace_clone(pool_lookup_namespace(pool, index));
705 } else if(c->type == CONSTANT_INT) {
706 c->i = pool_lookup_int(pool, index);
707 } else if(c->type == CONSTANT_UINT) {
708 c->u = pool_lookup_uint(pool, index);
709 } else if(c->type == CONSTANT_FLOAT) {
710 c->f = pool_lookup_float(pool, index);
711 } else if(c->type == CONSTANT_STRING) {
712 c->s = strdup(pool_lookup_string(pool, index));
713 } else if(UNIQUE_CONSTANT(c->type)) {
716 fprintf(stderr, "invalid constant type %02x\n", c->type);
720 char* constant_tostring(constant_t*c)
725 if(NS_TYPE(c->type)) {
726 return namespace_tostring(c->ns);
727 } else if(c->type == CONSTANT_INT) {
728 sprintf(buf, "%d", c->i);
730 } else if(c->type == CONSTANT_UINT) {
731 sprintf(buf, "%u", c->u);
733 } else if(c->type == CONSTANT_FLOAT) {
735 sprintf(buf, "%f", c->f);
737 } else if(c->type == CONSTANT_STRING) {
739 } else if(c->type == CONSTANT_TRUE) {
740 return strdup("true");
741 } else if(c->type == CONSTANT_FALSE) {
742 return strdup("false");
743 } else if(c->type == CONSTANT_NULL) {
744 return strdup("null");
745 } else if(c->type == CONSTANT_UNDEFINED) {
746 return strdup("undefined");
748 fprintf(stderr, "invalid constant type %02x\n", c->type);
752 char constant_has_index(constant_t*c)
756 return !UNIQUE_CONSTANT(c->type);
758 int constant_get_index(pool_t*pool, constant_t*c)
762 if(NS_TYPE(c->type)) {
764 /*if(c->type!=c->ns->access) {
765 printf("%02x<->%02x\n", c->type, c->ns->access);
767 assert(c->type == c->ns->access);
768 return pool_register_namespace(pool, c->ns);
769 } else if(c->type == CONSTANT_INT) {
770 return pool_register_int(pool, c->i);
771 } else if(c->type == CONSTANT_UINT) {
772 return pool_register_uint(pool, c->u);
773 } else if(c->type == CONSTANT_FLOAT) {
774 return pool_register_float(pool, c->f);
775 } else if(c->type == CONSTANT_STRING) {
776 return pool_register_string(pool, c->s);
777 } else if(!constant_has_index(c)) {
780 fprintf(stderr, "invalid constant type %02x\n", c->type);
784 void constant_free(constant_t*c)
788 if(c->type == CONSTANT_STRING) {
790 } else if (NS_TYPE(c->type)) {
791 namespace_destroy(c->ns);c->ns=0;
795 // ------------------------------- pool -------------------------------------
797 int pool_register_uint(pool_t*p, unsigned int i)
799 int pos = array_append_if_new(p->x_uints, &i, 0);
803 int pool_register_int(pool_t*p, int i)
805 int pos = array_append_if_new(p->x_ints, &i, 0);
809 int pool_register_float(pool_t*p, double d)
811 int pos = array_append_if_new(p->x_floats, &d, 0);
815 int pool_register_string(pool_t*pool, const char*s)
818 ptroff_t l = strlen(s);
819 int pos = array_append_if_new(pool->x_strings, s, (void*)l);
823 int pool_register_namespace(pool_t*pool, namespace_t*ns)
826 int pos = array_append_if_new(pool->x_namespaces, ns, 0);
830 int pool_register_namespace_set(pool_t*pool, namespace_set_t*set)
833 int pos = array_append_if_new(pool->x_namespace_sets, set, 0);
837 int pool_register_multiname(pool_t*pool, multiname_t*n)
840 int pos = array_append_if_new(pool->x_multinames, n, 0);
844 int pool_register_multiname2(pool_t*pool, char*name)
847 multiname_t*n = multiname_fromstring(name);
848 int pos = array_append_if_new(pool->x_multinames, n, 0);
849 multiname_destroy(n);
855 int pool_find_uint(pool_t*pool, unsigned int x)
857 int i = array_find(pool->x_uints, &x);
859 fprintf(stderr, "Couldn't find uint \"%d\" in constant pool\n", x);
864 int pool_find_int(pool_t*pool, int x)
866 int i = array_find(pool->x_ints, &x);
868 fprintf(stderr, "Couldn't find int \"%d\" in constant pool\n", x);
873 int pool_find_float(pool_t*pool, double x)
875 int i = array_find(pool->x_ints, &x);
877 fprintf(stderr, "Couldn't find int \"%d\" in constant pool\n", x);
882 int pool_find_namespace(pool_t*pool, namespace_t*ns)
886 int i = array_find(pool->x_namespaces, ns);
888 char*s = namespace_tostring(ns);
889 fprintf(stderr, "Couldn't find namespace \"%s\" %08x in constant pool\n", s, ns);
895 int pool_find_namespace_set(pool_t*pool, namespace_set_t*set)
899 int i = array_find(pool->x_namespace_sets, set);
901 char*s = namespace_set_tostring(set);
902 fprintf(stderr, "Couldn't find namespace_set \"%s\" in constant pool\n", s);
908 int pool_find_string(pool_t*pool, const char*s)
912 int i = array_find(pool->x_strings, s);
914 fprintf(stderr, "Couldn't find string \"%s\" in constant pool\n", s);
919 int pool_find_multiname(pool_t*pool, multiname_t*name)
923 int i = array_find(pool->x_multinames, name);
925 char*s = multiname_tostring(name);
926 fprintf(stderr, "Couldn't find multiname \"%s\" in constant pool\n", s);
933 int pool_lookup_int(pool_t*pool, int i)
936 return *(int*)array_getkey(pool->x_ints, i);
938 unsigned int pool_lookup_uint(pool_t*pool, int i)
941 return *(unsigned int*)array_getkey(pool->x_uints, i);
943 double pool_lookup_float(pool_t*pool, int i)
945 if(!i) return __builtin_nan("");
946 return *(double*)array_getkey(pool->x_floats, i);
948 char*pool_lookup_string(pool_t*pool, int i)
950 return (char*)array_getkey(pool->x_strings, i);
952 string_t pool_lookup_string2(pool_t*pool, int i)
954 char*s = (char*)array_getkey(pool->x_strings, i);
955 int len = (int)(ptroff_t)array_getvalue(pool->x_strings, i);
956 return string_new(s,len);
958 namespace_t*pool_lookup_namespace(pool_t*pool, int i)
960 return (namespace_t*)array_getkey(pool->x_namespaces, i);
962 namespace_set_t*pool_lookup_namespace_set(pool_t*pool, int i)
964 return (namespace_set_t*)array_getkey(pool->x_namespace_sets, i);
966 multiname_t*pool_lookup_multiname(pool_t*pool, int i)
968 return (multiname_t*)array_getkey(pool->x_multinames, i);
975 p->x_ints = array_new2(&uint_type);
976 p->x_uints = array_new2(&uint_type);
977 p->x_floats = array_new2(&float_type);
978 p->x_strings = array_new2(&charptr_type);
979 p->x_namespaces = array_new2(&namespace_type);
980 p->x_namespace_sets = array_new2(&namespace_set_type);
981 p->x_multinames = array_new2(&multiname_type);
983 /* add a zero-index entry in each list */
985 array_append(p->x_ints, 0, 0);
986 array_append(p->x_uints, 0, 0);
987 array_append(p->x_floats, 0, 0);
988 array_append(p->x_strings, 0, 0);
989 array_append(p->x_namespaces, 0, 0);
990 array_append(p->x_namespace_sets, 0, 0);
991 array_append(p->x_multinames, 0, 0);
998 void pool_read(pool_t*pool, TAG*tag)
1000 int num_ints = swf_GetU30(tag);
1001 DEBUG printf("%d ints\n", num_ints);
1003 for(t=1;t<num_ints;t++) {
1004 S32 v = swf_GetABCS32(tag);
1005 DEBUG printf("int %d) %d\n", t, v);
1006 array_append(pool->x_ints, &v, 0);
1009 int num_uints = swf_GetU30(tag);
1010 DEBUG printf("%d uints\n", num_uints);
1011 for(t=1;t<num_uints;t++) {
1012 U32 v = swf_GetABCU32(tag);
1013 DEBUG printf("uint %d) %d\n", t, v);
1014 array_append(pool->x_uints, &v, 0);
1017 int num_floats = swf_GetU30(tag);
1018 DEBUG printf("%d floats\n", num_floats);
1019 for(t=1;t<num_floats;t++) {
1020 double d = swf_GetD64(tag);
1021 DEBUG printf("float %d) %f\n", t, d);
1022 array_append(pool->x_floats, &d, 0);
1025 int num_strings = swf_GetU30(tag);
1026 DEBUG printf("%d strings\n", num_strings);
1027 for(t=1;t<num_strings;t++) {
1028 int len = swf_GetU30(tag);
1029 char*s = malloc(len+1);
1030 swf_GetBlock(tag, s, len);
1032 array_append(pool->x_strings, s, (void*)(ptroff_t)len);
1034 DEBUG printf("%d) \"%s\"\n", t, pool->x_strings->d[t].name);
1036 int num_namespaces = swf_GetU30(tag);
1037 DEBUG printf("%d namespaces\n", num_namespaces);
1038 for(t=1;t<num_namespaces;t++) {
1039 U8 type = swf_GetU8(tag);
1040 int namenr = swf_GetU30(tag);
1041 const char*name = 0;
1043 name = array_getkey(pool->x_strings, namenr);
1044 namespace_t*ns = namespace_new(type, name);
1045 array_append(pool->x_namespaces, ns, 0);
1046 DEBUG printf("%d) %02x \"%s\"\n", t, type, namespace_tostring(ns));
1047 namespace_destroy(ns);
1049 int num_sets = swf_GetU30(tag);
1050 DEBUG printf("%d namespace sets\n", num_sets);
1051 for(t=1;t<num_sets;t++) {
1052 int count = swf_GetU30(tag);
1055 NEW(namespace_set_t, nsset);
1056 for(s=0;s<count;s++) {
1057 int nsnr = swf_GetU30(tag);
1059 fprintf(stderr, "Zero entry in namespace set\n");
1060 namespace_t*ns = (namespace_t*)array_getkey(pool->x_namespaces, nsnr);
1061 list_append(nsset->namespaces, namespace_clone(ns));
1063 array_append(pool->x_namespace_sets, nsset, 0);
1064 DEBUG printf("set %d) %s\n", t, namespace_set_tostring(nsset));
1065 namespace_set_destroy(nsset);
1068 int num_multinames = swf_GetU30(tag);
1069 DEBUG printf("%d multinames\n", num_multinames);
1070 for(t=1;t<num_multinames;t++) {
1072 memset(&m, 0, sizeof(multiname_t));
1073 m.type = swf_GetU8(tag);
1074 if(m.type==0x07 || m.type==0x0d) {
1075 int namespace_index = swf_GetU30(tag);
1076 m.ns = (namespace_t*)array_getkey(pool->x_namespaces, namespace_index);
1077 int name_index = swf_GetU30(tag);
1078 if(name_index) // 0 = '*' (any)
1079 m.name = array_getkey(pool->x_strings, name_index);
1080 } else if(m.type==0x0f || m.type==0x10) {
1081 int name_index = swf_GetU30(tag);
1082 if(name_index) // 0 = '*' (any name)
1083 m.name = array_getkey(pool->x_strings, name_index);
1084 } else if(m.type==0x11 || m.type==0x12) {
1085 } else if(m.type==0x09 || m.type==0x0e) {
1086 int name_index = swf_GetU30(tag);
1087 int namespace_set_index = swf_GetU30(tag);
1089 m.name = array_getkey(pool->x_strings, name_index);
1090 m.namespace_set = (namespace_set_t*)array_getkey(pool->x_namespace_sets, namespace_set_index);
1091 } else if(m.type==0x1b || m.type==0x1c) {
1092 int namespace_set_index = swf_GetU30(tag);
1093 m.namespace_set = (namespace_set_t*)array_getkey(pool->x_namespace_sets, namespace_set_index);
1095 printf("can't parse type %d multinames yet\n", m.type);
1097 DEBUG printf("multiname %d) %s\n", t, multiname_tostring(&m));
1098 array_append(pool->x_multinames, &m, 0);
1102 void pool_write(pool_t*pool, TAG*tag)
1106 /* make sure that all namespaces used by multinames / namespace sets
1107 and all strings used by namespaces exist */
1109 for(t=1;t<pool->x_multinames->num;t++) {
1110 multiname_t*m = (multiname_t*)array_getkey(pool->x_multinames, t);
1112 pool_register_namespace(pool, m->ns);
1114 if(m->namespace_set) {
1115 pool_register_namespace_set(pool, m->namespace_set);
1118 pool_register_string(pool, m->name);
1121 for(t=1;t<pool->x_namespace_sets->num;t++) {
1122 namespace_set_t*set = (namespace_set_t*)array_getkey(pool->x_namespace_sets, t);
1123 namespace_list_t*i = set->namespaces;
1125 pool_register_namespace(pool, i->namespace);
1129 for(t=1;t<pool->x_namespaces->num;t++) {
1130 namespace_t*ns= (namespace_t*)array_getkey(pool->x_namespaces, t);
1131 /* The spec says (page 22): "a value of zero denotes an empty string".
1132 However when actually using zero strings as empty namespaces, the
1133 flash player breaks.*/
1134 //if(ns->name && ns->name[0])
1135 pool_register_string(pool, ns->name);
1138 //pool_register_int(pool, 15);
1139 //pool_register_int(pool, 1);
1140 //pool_register_int(pool, 0);
1143 swf_SetU30(tag, pool->x_ints->num>1?pool->x_ints->num:0);
1144 for(t=1;t<pool->x_ints->num;t++) {
1145 S32 val = *(int*)array_getkey(pool->x_ints, t);
1146 swf_SetABCS32(tag, val);
1148 swf_SetU30(tag, pool->x_uints->num>1?pool->x_uints->num:0);
1149 for(t=1;t<pool->x_uints->num;t++) {
1150 swf_SetABCU32(tag, *(unsigned int*)array_getkey(pool->x_uints, t));
1152 swf_SetU30(tag, pool->x_floats->num>1?pool->x_floats->num:0);
1153 for(t=1;t<pool->x_floats->num;t++) {
1154 double d = pool_lookup_float(pool, t);
1157 swf_SetU30(tag, pool->x_strings->num>1?pool->x_strings->num:0);
1158 for(t=1;t<pool->x_strings->num;t++) {
1159 string_t str = pool_lookup_string2(pool, t);
1160 swf_SetU30String(tag, str.str, str.len);
1162 swf_SetU30(tag, pool->x_namespaces->num>1?pool->x_namespaces->num:0);
1163 for(t=1;t<pool->x_namespaces->num;t++) {
1164 namespace_t*ns= (namespace_t*)array_getkey(pool->x_namespaces, t);
1165 swf_SetU8(tag, ns->access);
1166 const char*name = ns->name;
1169 //if(name && name[0])
1170 i = pool_find_string(pool, name);
1174 swf_SetU30(tag, pool->x_namespace_sets->num>1?pool->x_namespace_sets->num:0);
1175 for(t=1;t<pool->x_namespace_sets->num;t++) {
1176 namespace_set_t*set = (namespace_set_t*)array_getkey(pool->x_namespace_sets, t);
1177 namespace_list_t*i = set->namespaces;
1178 int len = list_length(i);
1179 swf_SetU30(tag, len);
1181 int index = pool_find_namespace(pool, i->namespace);
1182 swf_SetU30(tag, index);
1187 swf_SetU30(tag, pool->x_multinames->num>1?pool->x_multinames->num:0);
1188 for(t=1;t<pool->x_multinames->num;t++) {
1189 multiname_t*m = (multiname_t*)array_getkey(pool->x_multinames, t);
1190 swf_SetU8(tag, m->type);
1193 assert(m->type==0x07 || m->type==0x0d);
1194 int i = pool_find_namespace(pool, m->ns);
1195 if(i<0) fprintf(stderr, "internal error: unregistered namespace %02x %s %s\n", m->ns->access, access2str(m->ns->access), m->ns->name);
1198 assert(m->type!=0x07 && m->type!=0x0d);
1201 assert(m->type==0x09 || m->type==0x0e || m->type==0x07 || m->type==0x0d || m->type==0x0f || m->type==0x10);
1202 int i = pool_find_string(pool, m->name);
1203 if(i<0) fprintf(stderr, "internal error: unregistered name\n");
1206 assert(m->type!=0x09 && m->type!=0x0e && m->type!=0x07 && m->type!=0x0d && m->type!=0x0f && m->type!=0x10);
1208 if(m->namespace_set) {
1209 assert(m->type==0x09 || m->type==0x0e || m->type==0x1c || m->type==0x1b);
1210 int i = pool_find_namespace_set(pool, m->namespace_set);
1211 if(i<0) fprintf(stderr, "internal error: unregistered namespace set\n");
1214 assert(m->type!=0x09 && m->type!=0x0e && m->type!=0x1c && m->type!=0x1b);
1220 void pool_destroy(pool_t*pool)
1223 array_free(pool->x_ints);
1224 array_free(pool->x_uints);
1225 array_free(pool->x_floats);
1226 array_free(pool->x_strings);
1227 array_free(pool->x_namespaces);
1228 array_free(pool->x_namespace_sets);
1229 array_free(pool->x_multinames);