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 int pos = array_append_if_new(pool->x_strings, s, 0);
820 int pool_register_namespace(pool_t*pool, namespace_t*ns)
823 int pos = array_append_if_new(pool->x_namespaces, ns, 0);
827 int pool_register_namespace_set(pool_t*pool, namespace_set_t*set)
830 int pos = array_append_if_new(pool->x_namespace_sets, set, 0);
834 int pool_register_multiname(pool_t*pool, multiname_t*n)
837 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 namespace_t*pool_lookup_namespace(pool_t*pool, int i)
954 return (namespace_t*)array_getkey(pool->x_namespaces, i);
956 namespace_set_t*pool_lookup_namespace_set(pool_t*pool, int i)
958 return (namespace_set_t*)array_getkey(pool->x_namespace_sets, i);
960 multiname_t*pool_lookup_multiname(pool_t*pool, int i)
962 return (multiname_t*)array_getkey(pool->x_multinames, i);
969 p->x_ints = array_new2(&uint_type);
970 p->x_uints = array_new2(&uint_type);
971 p->x_floats = array_new2(&float_type);
972 p->x_strings = array_new2(&charptr_type);
973 p->x_namespaces = array_new2(&namespace_type);
974 p->x_namespace_sets = array_new2(&namespace_set_type);
975 p->x_multinames = array_new2(&multiname_type);
977 /* add a zero-index entry in each list */
979 array_append(p->x_ints, 0, 0);
980 array_append(p->x_uints, 0, 0);
981 array_append(p->x_floats, 0, 0);
982 array_append(p->x_strings, 0, 0);
983 array_append(p->x_namespaces, 0, 0);
984 array_append(p->x_namespace_sets, 0, 0);
985 array_append(p->x_multinames, 0, 0);
992 void pool_read(pool_t*pool, TAG*tag)
994 int num_ints = swf_GetU30(tag);
995 DEBUG printf("%d ints\n", num_ints);
997 for(t=1;t<num_ints;t++) {
998 S32 v = swf_GetABCS32(tag);
999 DEBUG printf("int %d) %d\n", t, v);
1000 array_append(pool->x_ints, &v, 0);
1003 int num_uints = swf_GetU30(tag);
1004 DEBUG printf("%d uints\n", num_uints);
1005 for(t=1;t<num_uints;t++) {
1006 U32 v = swf_GetABCU32(tag);
1007 DEBUG printf("uint %d) %d\n", t, v);
1008 array_append(pool->x_uints, &v, 0);
1011 int num_floats = swf_GetU30(tag);
1012 DEBUG printf("%d floats\n", num_floats);
1013 for(t=1;t<num_floats;t++) {
1014 double d = swf_GetD64(tag);
1015 DEBUG printf("float %d) %f\n", t, d);
1016 array_append(pool->x_floats, &d, 0);
1019 int num_strings = swf_GetU30(tag);
1020 DEBUG printf("%d strings\n", num_strings);
1021 for(t=1;t<num_strings;t++) {
1022 int len = swf_GetU30(tag);
1023 char*s = malloc(len+1);
1024 swf_GetBlock(tag, s, len);
1026 array_append(pool->x_strings, s, 0);
1028 DEBUG printf("%d) \"%s\"\n", t, pool->x_strings->d[t].name);
1030 int num_namespaces = swf_GetU30(tag);
1031 DEBUG printf("%d namespaces\n", num_namespaces);
1032 for(t=1;t<num_namespaces;t++) {
1033 U8 type = swf_GetU8(tag);
1034 int namenr = swf_GetU30(tag);
1035 const char*name = 0;
1037 name = array_getkey(pool->x_strings, namenr);
1038 namespace_t*ns = namespace_new(type, name);
1039 array_append(pool->x_namespaces, ns, 0);
1040 DEBUG printf("%d) %02x \"%s\"\n", t, type, namespace_tostring(ns));
1041 namespace_destroy(ns);
1043 int num_sets = swf_GetU30(tag);
1044 DEBUG printf("%d namespace sets\n", num_sets);
1045 for(t=1;t<num_sets;t++) {
1046 int count = swf_GetU30(tag);
1049 NEW(namespace_set_t, nsset);
1050 for(s=0;s<count;s++) {
1051 int nsnr = swf_GetU30(tag);
1053 fprintf(stderr, "Zero entry in namespace set\n");
1054 namespace_t*ns = (namespace_t*)array_getkey(pool->x_namespaces, nsnr);
1055 list_append(nsset->namespaces, namespace_clone(ns));
1057 array_append(pool->x_namespace_sets, nsset, 0);
1058 DEBUG printf("set %d) %s\n", t, namespace_set_tostring(nsset));
1059 namespace_set_destroy(nsset);
1062 int num_multinames = swf_GetU30(tag);
1063 DEBUG printf("%d multinames\n", num_multinames);
1064 for(t=1;t<num_multinames;t++) {
1066 memset(&m, 0, sizeof(multiname_t));
1067 m.type = swf_GetU8(tag);
1068 if(m.type==0x07 || m.type==0x0d) {
1069 int namespace_index = swf_GetU30(tag);
1070 m.ns = (namespace_t*)array_getkey(pool->x_namespaces, namespace_index);
1071 int name_index = swf_GetU30(tag);
1072 if(name_index) // 0 = '*' (any)
1073 m.name = array_getkey(pool->x_strings, name_index);
1074 } else if(m.type==0x0f || m.type==0x10) {
1075 int name_index = swf_GetU30(tag);
1076 if(name_index) // 0 = '*' (any name)
1077 m.name = array_getkey(pool->x_strings, name_index);
1078 } else if(m.type==0x11 || m.type==0x12) {
1079 } else if(m.type==0x09 || m.type==0x0e) {
1080 int name_index = swf_GetU30(tag);
1081 int namespace_set_index = swf_GetU30(tag);
1083 m.name = array_getkey(pool->x_strings, name_index);
1084 m.namespace_set = (namespace_set_t*)array_getkey(pool->x_namespace_sets, namespace_set_index);
1085 } else if(m.type==0x1b || m.type==0x1c) {
1086 int namespace_set_index = swf_GetU30(tag);
1087 m.namespace_set = (namespace_set_t*)array_getkey(pool->x_namespace_sets, namespace_set_index);
1089 printf("can't parse type %d multinames yet\n", m.type);
1091 DEBUG printf("multiname %d) %s\n", t, multiname_tostring(&m));
1092 array_append(pool->x_multinames, &m, 0);
1096 void pool_write(pool_t*pool, TAG*tag)
1100 /* make sure that all namespaces used by multinames / namespace sets
1101 and all strings used by namespaces exist */
1103 for(t=1;t<pool->x_multinames->num;t++) {
1104 multiname_t*m = (multiname_t*)array_getkey(pool->x_multinames, t);
1106 pool_register_namespace(pool, m->ns);
1108 if(m->namespace_set) {
1109 pool_register_namespace_set(pool, m->namespace_set);
1112 pool_register_string(pool, m->name);
1115 for(t=1;t<pool->x_namespace_sets->num;t++) {
1116 namespace_set_t*set = (namespace_set_t*)array_getkey(pool->x_namespace_sets, t);
1117 namespace_list_t*i = set->namespaces;
1119 pool_register_namespace(pool, i->namespace);
1123 for(t=1;t<pool->x_namespaces->num;t++) {
1124 namespace_t*ns= (namespace_t*)array_getkey(pool->x_namespaces, t);
1125 /* The spec says (page 22): "a value of zero denotes an empty string".
1126 However when actually using zero strings as empty namespaces, the
1127 flash player breaks.*/
1128 //if(ns->name && ns->name[0])
1129 array_append_if_new(pool->x_strings, ns->name, 0);
1132 //pool_register_int(pool, 15);
1133 //pool_register_int(pool, 1);
1134 //pool_register_int(pool, 0);
1137 swf_SetU30(tag, pool->x_ints->num>1?pool->x_ints->num:0);
1138 for(t=1;t<pool->x_ints->num;t++) {
1139 S32 val = *(int*)array_getkey(pool->x_ints, t);
1140 swf_SetABCS32(tag, val);
1142 swf_SetU30(tag, pool->x_uints->num>1?pool->x_uints->num:0);
1143 for(t=1;t<pool->x_uints->num;t++) {
1144 swf_SetABCU32(tag, *(unsigned int*)array_getkey(pool->x_uints, t));
1146 swf_SetU30(tag, pool->x_floats->num>1?pool->x_floats->num:0);
1147 for(t=1;t<pool->x_floats->num;t++) {
1148 double d = pool_lookup_float(pool, t);
1151 swf_SetU30(tag, pool->x_strings->num>1?pool->x_strings->num:0);
1152 for(t=1;t<pool->x_strings->num;t++) {
1153 swf_SetU30String(tag, array_getkey(pool->x_strings, t));
1155 swf_SetU30(tag, pool->x_namespaces->num>1?pool->x_namespaces->num:0);
1156 for(t=1;t<pool->x_namespaces->num;t++) {
1157 namespace_t*ns= (namespace_t*)array_getkey(pool->x_namespaces, t);
1158 swf_SetU8(tag, ns->access);
1159 const char*name = ns->name;
1162 //if(name && name[0])
1163 i = pool_find_string(pool, name);
1167 swf_SetU30(tag, pool->x_namespace_sets->num>1?pool->x_namespace_sets->num:0);
1168 for(t=1;t<pool->x_namespace_sets->num;t++) {
1169 namespace_set_t*set = (namespace_set_t*)array_getkey(pool->x_namespace_sets, t);
1170 namespace_list_t*i = set->namespaces;
1171 int len = list_length(i);
1172 swf_SetU30(tag, len);
1174 int index = pool_find_namespace(pool, i->namespace);
1175 swf_SetU30(tag, index);
1180 swf_SetU30(tag, pool->x_multinames->num>1?pool->x_multinames->num:0);
1181 for(t=1;t<pool->x_multinames->num;t++) {
1182 multiname_t*m = (multiname_t*)array_getkey(pool->x_multinames, t);
1183 swf_SetU8(tag, m->type);
1186 assert(m->type==0x07 || m->type==0x0d);
1187 int i = pool_find_namespace(pool, m->ns);
1188 if(i<0) fprintf(stderr, "internal error: unregistered namespace %02x %s %s\n", m->ns->access, access2str(m->ns->access), m->ns->name);
1191 assert(m->type!=0x07 && m->type!=0x0d);
1194 assert(m->type==0x09 || m->type==0x0e || m->type==0x07 || m->type==0x0d || m->type==0x0f || m->type==0x10);
1195 int i = pool_find_string(pool, m->name);
1196 if(i<0) fprintf(stderr, "internal error: unregistered name\n");
1199 assert(m->type!=0x09 && m->type!=0x0e && m->type!=0x07 && m->type!=0x0d && m->type!=0x0f && m->type!=0x10);
1201 if(m->namespace_set) {
1202 assert(m->type==0x09 || m->type==0x0e || m->type==0x1c || m->type==0x1b);
1203 int i = pool_find_namespace_set(pool, m->namespace_set);
1204 if(i<0) fprintf(stderr, "internal error: unregistered namespace set\n");
1207 assert(m->type!=0x09 && m->type!=0x0e && m->type!=0x1c && m->type!=0x1b);
1213 void pool_destroy(pool_t*pool)
1216 array_free(pool->x_ints);
1217 array_free(pool->x_uints);
1218 array_free(pool->x_floats);
1219 array_free(pool->x_strings);
1220 array_free(pool->x_namespaces);
1221 array_free(pool->x_namespace_sets);
1222 array_free(pool->x_multinames);