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_to_string(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_to_string(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_to_string(lns->namespace);
356 char*desc = malloc(l+16);
358 lns = set->namespaces;
360 char*s = namespace_to_string(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)
447 m->ns = namespace_clone(ns);
448 m->name = strdup(name);
452 multiname_t* multiname_clone(multiname_t*other)
457 m->type = other->type;
459 m->ns = namespace_clone(other->ns);
460 if(other->namespace_set)
461 m->namespace_set = namespace_set_clone(other->namespace_set);
463 m->name = strdup(other->name);
468 char* access2str(int type)
470 if(type==0x08) return "access08";
471 else if(type==0x16) return "package";
472 else if(type==0x17) return "packageinternal";
473 else if(type==0x18) return "protected";
474 else if(type==0x19) return "explicit";
475 else if(type==0x1A) return "staticprotected";
476 else if(type==0x05) return "private";
478 fprintf(stderr, "Undefined access type %02x\n", type);
484 char multiname_late_namespace(multiname_t*m)
488 return (m->type==RTQNAME || m->type==RTQNAMEA ||
489 m->type==RTQNAMEL || m->type==RTQNAMELA);
492 char multiname_late_name(multiname_t*m)
496 return m->type==RTQNAMEL || m->type==RTQNAMELA ||
497 m->type==MULTINAMEL || m->type==MULTINAMELA;
500 char* multiname_to_string(multiname_t*m)
504 return strdup("NULL");
506 return strdup("--<MULTINAME 0xff>--");
508 char*name = m->name?escape_string(m->name):strdup("*");
509 int namelen = strlen(name);
511 if(m->type==QNAME || m->type==QNAMEA) {
512 char*nsname = escape_string(m->ns->name);
513 mname = malloc(strlen(nsname)+namelen+32);
515 if(m->type == QNAMEA)
516 strcat(mname, ",attr");
518 strcat(mname,access2str(m->ns->access));
520 strcat(mname, nsname);
524 } else if(m->type==RTQNAME || m->type==RTQNAMEA) {
525 mname = malloc(namelen+32);
526 strcpy(mname, "<rt");
527 if(m->type == RTQNAMEA)
528 strcat(mname, ",attr");
531 } else if(m->type==RTQNAMEL) {
532 mname = strdup("<rt,l>");
533 } else if(m->type==RTQNAMELA) {
534 mname = strdup("<rt,l,attr>");
535 } else if(m->type==MULTINAME || m->type==MULTINAMEA) {
536 char*s = namespace_set_to_string(m->namespace_set);
537 mname = malloc(strlen(s)+namelen+16);
538 if(m->type == MULTINAME)
539 strcpy(mname,"<multi>");
541 strcpy(mname,"<multi,attr>");
546 } else if(m->type==MULTINAMEL || m->type==MULTINAMELA) {
547 char*s = namespace_set_to_string(m->namespace_set);
548 mname = malloc(strlen(s)+16);
549 if(m->type == MULTINAMEL)
550 strcpy(mname,"<l,multi>");
552 strcpy(mname,"<l,multi,attr>");
556 fprintf(stderr, "Invalid multiname type: %02x\n", m->type);
562 multiname_t* multiname_fromstring(const char*name2)
566 char*n = strdup(name2);
567 char*p = strstr(n, "::");
568 char*namespace=0,*name=0;
571 fprintf(stderr, "Error: single ':' in name\n");
579 if(strchr(namespace, ':')) {
580 fprintf(stderr, "Error: single ':' in namespace\n");
582 if(strchr(name, ':')) {
583 fprintf(stderr, "Error: single ':' in qualified name\n");
587 multiname_t*m = malloc(sizeof(multiname_t));
588 memset(m, 0, sizeof(multiname_t));
590 m->namespace_set = 0;
591 m->ns = namespace_fromstring(namespace);
592 m->name = name?strdup(name):0;
597 void multiname_destroy(multiname_t*m)
601 free((void*)m->name);m->name = 0;
604 namespace_destroy(m->ns);m->ns = 0;
606 if(m->namespace_set) {
607 namespace_set_destroy(m->namespace_set);m->namespace_set = 0;
613 type_t multiname_type = {
614 dup: (dup_func)multiname_clone,
615 hash: (hash_func)multiname_hash,
616 free: (free_func)multiname_destroy,
617 equals: (equals_func)multiname_equals
621 // ------------------------------- constants -------------------------------------
623 #define NS_TYPE(x) ((x) == 0x08 || (x) == 0x16 || (x) == 0x17 || (x) == 0x18 || \
624 (x) == 0x19 || (x) == 0x1a || (x) == 0x05)
626 #define UNIQUE_CONSTANT(x) ((x) == CONSTANT_TRUE || (x) == CONSTANT_FALSE || (x) == CONSTANT_NULL || (x) == CONSTANT_UNDEFINED)
628 constant_t* constant_new_int(int i)
632 c->type = CONSTANT_INT;
635 constant_t* constant_new_uint(unsigned int u)
639 c->type = CONSTANT_UINT;
642 constant_t* constant_new_float(double f)
646 c->type = CONSTANT_FLOAT;
649 constant_t* constant_new_string(char*s)
653 c->type = CONSTANT_STRING;
656 constant_t* constant_new_namespace(namespace_t*ns)
659 c->ns = namespace_clone(ns);
660 c->type = ns->access;
661 assert(NS_TYPE(c->type));
664 constant_t* constant_new_true()
667 c->type = CONSTANT_TRUE;
670 constant_t* constant_new_false()
673 c->type = CONSTANT_FALSE;
676 constant_t* constant_new_null()
679 c->type = CONSTANT_NULL;
682 constant_t* constant_new_undefined()
685 c->type = CONSTANT_UNDEFINED;
688 constant_t* constant_fromindex(pool_t*pool, int index, int type)
691 /* even for nonvalued constants (like TRUE/FALSE etc.), a nonzero
692 index is present to indicate that a type is coming */
697 if(NS_TYPE(c->type)) {
698 c->ns = pool_lookup_namespace(pool, index);
699 } else if(c->type == CONSTANT_INT) {
700 c->i = pool_lookup_int(pool, index);
701 } else if(c->type == CONSTANT_UINT) {
702 c->u = pool_lookup_uint(pool, index);
703 } else if(c->type == CONSTANT_FLOAT) {
704 c->f = pool_lookup_float(pool, index);
705 } else if(c->type == CONSTANT_STRING) {
706 c->s = pool_lookup_string(pool, index);
707 } else if(UNIQUE_CONSTANT(c->type)) {
710 fprintf(stderr, "invalid constant type %02x\n", c->type);
714 char* constant_to_string(constant_t*c)
719 if(NS_TYPE(c->type)) {
720 return namespace_to_string(c->ns);
721 } else if(c->type == CONSTANT_INT) {
722 sprintf(buf, "%d", c->i);
724 } else if(c->type == CONSTANT_UINT) {
725 sprintf(buf, "%u", c->u);
727 } else if(c->type == CONSTANT_FLOAT) {
728 sprintf(buf, "%f", c->f);
730 } else if(c->type == CONSTANT_STRING) {
732 } else if(c->type == CONSTANT_TRUE) {
733 return strdup("true");
734 } else if(c->type == CONSTANT_FALSE) {
735 return strdup("false");
736 } else if(c->type == CONSTANT_NULL) {
737 return strdup("null");
738 } else if(c->type == CONSTANT_UNDEFINED) {
739 return strdup("undefined");
741 fprintf(stderr, "invalid constant type %02x\n", c->type);
745 char constant_has_index(constant_t*c)
749 return !UNIQUE_CONSTANT(c->type);
751 int constant_get_index(pool_t*pool, constant_t*c)
755 if(NS_TYPE(c->type)) {
757 assert(c->type == c->ns->access);
758 return pool_register_namespace(pool, c->ns);
759 } else if(c->type == CONSTANT_INT) {
760 return pool_register_int(pool, c->i);
761 } else if(c->type == CONSTANT_UINT) {
762 return pool_register_uint(pool, c->u);
763 } else if(c->type == CONSTANT_FLOAT) {
764 return pool_register_float(pool, c->f);
765 } else if(c->type == CONSTANT_STRING) {
766 return pool_register_string(pool, c->s);
767 } else if(!constant_has_index(c)) {
770 fprintf(stderr, "invalid constant type %02x\n", c->type);
774 void constant_free(constant_t*c)
778 if(c->type == CONSTANT_STRING) {
780 } else if (NS_TYPE(c->type)) {
781 namespace_destroy(c->ns);c->ns=0;
785 // ------------------------------- pool -------------------------------------
787 int pool_register_uint(pool_t*p, unsigned int i)
789 int pos = array_append_if_new(p->x_uints, &i, 0);
793 int pool_register_int(pool_t*p, int i)
795 int pos = array_append_if_new(p->x_ints, &i, 0);
799 int pool_register_float(pool_t*p, double d)
801 int pos = array_append_if_new(p->x_floats, &d, 0);
805 int pool_register_string(pool_t*pool, const char*s)
808 int pos = array_append_if_new(pool->x_strings, s, 0);
812 int pool_register_namespace(pool_t*pool, namespace_t*ns)
815 int pos = array_append_if_new(pool->x_namespaces, ns, 0);
819 int pool_register_namespace_set(pool_t*pool, namespace_set_t*set)
822 int pos = array_append_if_new(pool->x_namespace_sets, set, 0);
826 int pool_register_multiname(pool_t*pool, multiname_t*n)
829 int pos = array_append_if_new(pool->x_multinames, n, 0);
836 int pool_register_multiname2(pool_t*pool, char*name)
839 multiname_t*n = multiname_fromstring(name);
840 int pos = array_append_if_new(pool->x_multinames, n, 0);
841 multiname_destroy(n);
847 int pool_find_uint(pool_t*pool, unsigned int x)
849 int i = array_find(pool->x_uints, &x);
851 fprintf(stderr, "Couldn't find uint \"%d\" in constant pool\n", x);
856 int pool_find_int(pool_t*pool, int x)
858 int i = array_find(pool->x_ints, &x);
860 fprintf(stderr, "Couldn't find int \"%d\" in constant pool\n", x);
865 int pool_find_float(pool_t*pool, double x)
867 int i = array_find(pool->x_ints, &x);
869 fprintf(stderr, "Couldn't find int \"%d\" in constant pool\n", x);
874 int pool_find_namespace(pool_t*pool, namespace_t*ns)
878 int i = array_find(pool->x_namespaces, ns);
880 char*s = namespace_to_string(ns);
881 fprintf(stderr, "Couldn't find namespace \"%s\" %08x in constant pool\n", s, ns);
887 int pool_find_namespace_set(pool_t*pool, namespace_set_t*set)
891 int i = array_find(pool->x_namespace_sets, set);
893 char*s = namespace_set_to_string(set);
894 fprintf(stderr, "Couldn't find namespace_set \"%s\" in constant pool\n", s);
900 int pool_find_string(pool_t*pool, const char*s)
904 int i = array_find(pool->x_strings, s);
906 fprintf(stderr, "Couldn't find string \"%s\" in constant pool\n", s);
911 int pool_find_multiname(pool_t*pool, multiname_t*name)
915 int i = array_find(pool->x_multinames, name);
917 char*s = multiname_to_string(name);
918 fprintf(stderr, "Couldn't find multiname \"%s\" in constant pool\n", s);
925 int pool_lookup_int(pool_t*pool, int i)
928 return *(int*)array_getkey(pool->x_ints, i);
930 unsigned int pool_lookup_uint(pool_t*pool, int i)
933 return *(unsigned int*)array_getkey(pool->x_uints, i);
935 double pool_lookup_float(pool_t*pool, int i)
937 if(!i) return __builtin_nan("");
938 return *(double*)array_getkey(pool->x_floats, i);
940 char*pool_lookup_string(pool_t*pool, int i)
942 return (char*)array_getkey(pool->x_strings, i);
944 namespace_t*pool_lookup_namespace(pool_t*pool, int i)
946 return (namespace_t*)array_getkey(pool->x_namespaces, i);
948 namespace_set_t*pool_lookup_namespace_set(pool_t*pool, int i)
950 return (namespace_set_t*)array_getkey(pool->x_namespace_sets, i);
952 multiname_t*pool_lookup_multiname(pool_t*pool, int i)
954 return (multiname_t*)array_getkey(pool->x_multinames, i);
961 p->x_ints = array_new2(&uint_type);
962 p->x_uints = array_new2(&uint_type);
963 p->x_floats = array_new2(&float_type);
964 p->x_strings = array_new2(&charptr_type);
965 p->x_namespaces = array_new2(&namespace_type);
966 p->x_namespace_sets = array_new2(&namespace_set_type);
967 p->x_multinames = array_new2(&multiname_type);
969 /* add a zero-index entry in each list */
971 array_append(p->x_ints, 0, 0);
972 array_append(p->x_uints, 0, 0);
973 array_append(p->x_floats, 0, 0);
974 array_append(p->x_strings, 0, 0);
975 array_append(p->x_namespaces, 0, 0);
976 array_append(p->x_namespace_sets, 0, 0);
977 array_append(p->x_multinames, 0, 0);
984 void pool_read(pool_t*pool, TAG*tag)
986 int num_ints = swf_GetU30(tag);
987 DEBUG printf("%d ints\n", num_ints);
989 for(t=1;t<num_ints;t++) {
990 S32 v = swf_GetS30(tag);
991 DEBUG printf("int %d) %d\n", t, v);
992 array_append(pool->x_ints, &v, 0);
995 int num_uints = swf_GetU30(tag);
996 DEBUG printf("%d uints\n", num_uints);
997 for(t=1;t<num_uints;t++) {
998 U32 v = swf_GetU30(tag);
999 DEBUG printf("uint %d) %d\n", t, v);
1000 array_append(pool->x_uints, &v, 0);
1003 int num_floats = swf_GetU30(tag);
1004 DEBUG printf("%d floats\n", num_floats);
1005 for(t=1;t<num_floats;t++) {
1006 double d = swf_GetD64(tag);
1007 DEBUG printf("float %d) %f\n", t, d);
1008 array_append(pool->x_floats, &d, 0);
1011 int num_strings = swf_GetU30(tag);
1012 DEBUG printf("%d strings\n", num_strings);
1013 for(t=1;t<num_strings;t++) {
1014 int len = swf_GetU30(tag);
1015 char*s = malloc(len+1);
1016 swf_GetBlock(tag, s, len);
1018 array_append(pool->x_strings, s, 0);
1020 DEBUG printf("%d) \"%s\"\n", t, pool->x_strings->d[t].name);
1022 int num_namespaces = swf_GetU30(tag);
1023 DEBUG printf("%d namespaces\n", num_namespaces);
1024 for(t=1;t<num_namespaces;t++) {
1025 U8 type = swf_GetU8(tag);
1026 int namenr = swf_GetU30(tag);
1027 const char*name = 0;
1029 name = array_getkey(pool->x_strings, namenr);
1030 namespace_t*ns = namespace_new(type, name);
1031 array_append(pool->x_namespaces, ns, 0);
1032 DEBUG printf("%d) %02x \"%s\"\n", t, type, namespace_to_string(ns));
1033 namespace_destroy(ns);
1035 int num_sets = swf_GetU30(tag);
1036 DEBUG printf("%d namespace sets\n", num_sets);
1037 for(t=1;t<num_sets;t++) {
1038 int count = swf_GetU30(tag);
1041 NEW(namespace_set_t, nsset);
1042 for(s=0;s<count;s++) {
1043 int nsnr = swf_GetU30(tag);
1045 fprintf(stderr, "Zero entry in namespace set\n");
1046 namespace_t*ns = (namespace_t*)array_getkey(pool->x_namespaces, nsnr);
1047 list_append(nsset->namespaces, namespace_clone(ns));
1049 array_append(pool->x_namespace_sets, nsset, 0);
1050 DEBUG printf("set %d) %s\n", t, namespace_set_to_string(nsset));
1051 namespace_set_destroy(nsset);
1054 int num_multinames = swf_GetU30(tag);
1055 DEBUG printf("%d multinames\n", num_multinames);
1056 for(t=1;t<num_multinames;t++) {
1058 memset(&m, 0, sizeof(multiname_t));
1059 m.type = swf_GetU8(tag);
1060 if(m.type==0x07 || m.type==0x0d) {
1061 int namespace_index = swf_GetU30(tag);
1062 m.ns = (namespace_t*)array_getkey(pool->x_namespaces, namespace_index);
1063 int name_index = swf_GetU30(tag);
1064 if(name_index) // 0 = '*' (any)
1065 m.name = array_getkey(pool->x_strings, name_index);
1066 } else if(m.type==0x0f || m.type==0x10) {
1067 int name_index = swf_GetU30(tag);
1068 if(name_index) // 0 = '*' (any name)
1069 m.name = array_getkey(pool->x_strings, name_index);
1070 } else if(m.type==0x11 || m.type==0x12) {
1071 } else if(m.type==0x09 || m.type==0x0e) {
1072 int name_index = swf_GetU30(tag);
1073 int namespace_set_index = swf_GetU30(tag);
1075 m.name = array_getkey(pool->x_strings, name_index);
1076 m.namespace_set = (namespace_set_t*)array_getkey(pool->x_namespace_sets, namespace_set_index);
1077 } else if(m.type==0x1b || m.type==0x1c) {
1078 int namespace_set_index = swf_GetU30(tag);
1079 m.namespace_set = (namespace_set_t*)array_getkey(pool->x_namespace_sets, namespace_set_index);
1081 printf("can't parse type %d multinames yet\n", m.type);
1083 DEBUG printf("multiname %d) %s\n", t, multiname_to_string(&m));
1084 array_append(pool->x_multinames, &m, 0);
1088 void pool_write(pool_t*pool, TAG*tag)
1092 /* make sure that all namespaces used by multinames / namespace sets
1093 and all strings used by namespaces exist */
1095 for(t=1;t<pool->x_multinames->num;t++) {
1096 multiname_t*m = (multiname_t*)array_getkey(pool->x_multinames, t);
1098 pool_register_namespace(pool, m->ns);
1100 if(m->namespace_set) {
1101 pool_register_namespace_set(pool, m->namespace_set);
1104 pool_register_string(pool, m->name);
1107 for(t=1;t<pool->x_namespace_sets->num;t++) {
1108 namespace_set_t*set = (namespace_set_t*)array_getkey(pool->x_namespace_sets, t);
1109 namespace_list_t*i = set->namespaces;
1111 pool_register_namespace(pool, i->namespace);
1115 for(t=1;t<pool->x_namespaces->num;t++) {
1116 namespace_t*ns= (namespace_t*)array_getkey(pool->x_namespaces, t);
1117 /* The spec says (page 22): "a value of zero denotes an empty string".
1118 However when actually using zero strings as empty namespaces, the
1119 flash player breaks.*/
1120 //if(ns->name && ns->name[0])
1121 array_append_if_new(pool->x_strings, ns->name, 0);
1124 //pool_register_int(pool, 15);
1125 //pool_register_int(pool, 1);
1126 //pool_register_int(pool, 0);
1129 swf_SetU30(tag, pool->x_ints->num>1?pool->x_ints->num:0);
1130 for(t=1;t<pool->x_ints->num;t++) {
1131 S32 val = *(int*)array_getkey(pool->x_ints, t);
1132 swf_SetS30(tag, val);
1134 swf_SetU30(tag, pool->x_uints->num>1?pool->x_uints->num:0);
1135 for(t=1;t<pool->x_uints->num;t++) {
1136 swf_SetU30(tag, *(unsigned int*)array_getkey(pool->x_uints, t));
1138 swf_SetU30(tag, pool->x_floats->num>1?pool->x_floats->num:0);
1139 for(t=1;t<pool->x_floats->num;t++) {
1140 double d = pool_lookup_float(pool, t);
1143 swf_SetU30(tag, pool->x_strings->num>1?pool->x_strings->num:0);
1144 for(t=1;t<pool->x_strings->num;t++) {
1145 swf_SetU30String(tag, array_getkey(pool->x_strings, t));
1147 swf_SetU30(tag, pool->x_namespaces->num>1?pool->x_namespaces->num:0);
1148 for(t=1;t<pool->x_namespaces->num;t++) {
1149 namespace_t*ns= (namespace_t*)array_getkey(pool->x_namespaces, t);
1150 swf_SetU8(tag, ns->access);
1151 const char*name = ns->name;
1154 //if(name && name[0])
1155 i = pool_find_string(pool, name);
1159 swf_SetU30(tag, pool->x_namespace_sets->num>1?pool->x_namespace_sets->num:0);
1160 for(t=1;t<pool->x_namespace_sets->num;t++) {
1161 namespace_set_t*set = (namespace_set_t*)array_getkey(pool->x_namespace_sets, t);
1162 namespace_list_t*i = set->namespaces;
1163 int len = list_length(i);
1164 swf_SetU30(tag, len);
1166 int index = pool_find_namespace(pool, i->namespace);
1167 swf_SetU30(tag, index);
1172 swf_SetU30(tag, pool->x_multinames->num>1?pool->x_multinames->num:0);
1173 for(t=1;t<pool->x_multinames->num;t++) {
1174 multiname_t*m = (multiname_t*)array_getkey(pool->x_multinames, t);
1175 swf_SetU8(tag, m->type);
1178 assert(m->type==0x07 || m->type==0x0d);
1179 int i = pool_find_namespace(pool, m->ns);
1180 if(i<0) fprintf(stderr, "internal error: unregistered namespace %02x %s %s\n", m->ns->access, access2str(m->ns->access), m->ns->name);
1183 assert(m->type!=0x07 && m->type!=0x0d);
1186 assert(m->type==0x09 || m->type==0x0e || m->type==0x07 || m->type==0x0d || m->type==0x0f || m->type==0x10);
1187 int i = pool_find_string(pool, m->name);
1188 if(i<0) fprintf(stderr, "internal error: unregistered name\n");
1191 assert(m->type!=0x09 && m->type!=0x0e && m->type!=0x07 && m->type!=0x0d && m->type!=0x0f && m->type!=0x10);
1193 if(m->namespace_set) {
1194 assert(m->type==0x09 || m->type==0x0e || m->type==0x1c || m->type==0x1b);
1195 int i = pool_find_namespace_set(pool, m->namespace_set);
1196 if(i<0) fprintf(stderr, "internal error: unregistered namespace set\n");
1199 assert(m->type!=0x09 && m->type!=0x0e && m->type!=0x1c && m->type!=0x1b);
1205 void pool_destroy(pool_t*pool)
1208 array_free(pool->x_ints);
1209 array_free(pool->x_uints);
1210 array_free(pool->x_floats);
1211 array_free(pool->x_strings);
1212 array_free(pool->x_namespaces);
1213 array_free(pool->x_namespace_sets);
1214 array_free(pool->x_multinames);