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 = namespace_clone(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 = strdup(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 /*if(c->type!=c->ns->access) {
758 printf("%02x<->%02x\n", c->type, c->ns->access);
760 assert(c->type == c->ns->access);
761 return pool_register_namespace(pool, c->ns);
762 } else if(c->type == CONSTANT_INT) {
763 return pool_register_int(pool, c->i);
764 } else if(c->type == CONSTANT_UINT) {
765 return pool_register_uint(pool, c->u);
766 } else if(c->type == CONSTANT_FLOAT) {
767 return pool_register_float(pool, c->f);
768 } else if(c->type == CONSTANT_STRING) {
769 return pool_register_string(pool, c->s);
770 } else if(!constant_has_index(c)) {
773 fprintf(stderr, "invalid constant type %02x\n", c->type);
777 void constant_free(constant_t*c)
781 if(c->type == CONSTANT_STRING) {
783 } else if (NS_TYPE(c->type)) {
784 namespace_destroy(c->ns);c->ns=0;
788 // ------------------------------- pool -------------------------------------
790 int pool_register_uint(pool_t*p, unsigned int i)
792 int pos = array_append_if_new(p->x_uints, &i, 0);
796 int pool_register_int(pool_t*p, int i)
798 int pos = array_append_if_new(p->x_ints, &i, 0);
802 int pool_register_float(pool_t*p, double d)
804 int pos = array_append_if_new(p->x_floats, &d, 0);
808 int pool_register_string(pool_t*pool, const char*s)
811 int pos = array_append_if_new(pool->x_strings, s, 0);
815 int pool_register_namespace(pool_t*pool, namespace_t*ns)
818 int pos = array_append_if_new(pool->x_namespaces, ns, 0);
822 int pool_register_namespace_set(pool_t*pool, namespace_set_t*set)
825 int pos = array_append_if_new(pool->x_namespace_sets, set, 0);
829 int pool_register_multiname(pool_t*pool, multiname_t*n)
832 int pos = array_append_if_new(pool->x_multinames, n, 0);
839 int pool_register_multiname2(pool_t*pool, char*name)
842 multiname_t*n = multiname_fromstring(name);
843 int pos = array_append_if_new(pool->x_multinames, n, 0);
844 multiname_destroy(n);
850 int pool_find_uint(pool_t*pool, unsigned int x)
852 int i = array_find(pool->x_uints, &x);
854 fprintf(stderr, "Couldn't find uint \"%d\" in constant pool\n", x);
859 int pool_find_int(pool_t*pool, int x)
861 int i = array_find(pool->x_ints, &x);
863 fprintf(stderr, "Couldn't find int \"%d\" in constant pool\n", x);
868 int pool_find_float(pool_t*pool, double x)
870 int i = array_find(pool->x_ints, &x);
872 fprintf(stderr, "Couldn't find int \"%d\" in constant pool\n", x);
877 int pool_find_namespace(pool_t*pool, namespace_t*ns)
881 int i = array_find(pool->x_namespaces, ns);
883 char*s = namespace_to_string(ns);
884 fprintf(stderr, "Couldn't find namespace \"%s\" %08x in constant pool\n", s, ns);
890 int pool_find_namespace_set(pool_t*pool, namespace_set_t*set)
894 int i = array_find(pool->x_namespace_sets, set);
896 char*s = namespace_set_to_string(set);
897 fprintf(stderr, "Couldn't find namespace_set \"%s\" in constant pool\n", s);
903 int pool_find_string(pool_t*pool, const char*s)
907 int i = array_find(pool->x_strings, s);
909 fprintf(stderr, "Couldn't find string \"%s\" in constant pool\n", s);
914 int pool_find_multiname(pool_t*pool, multiname_t*name)
918 int i = array_find(pool->x_multinames, name);
920 char*s = multiname_to_string(name);
921 fprintf(stderr, "Couldn't find multiname \"%s\" in constant pool\n", s);
928 int pool_lookup_int(pool_t*pool, int i)
931 return *(int*)array_getkey(pool->x_ints, i);
933 unsigned int pool_lookup_uint(pool_t*pool, int i)
936 return *(unsigned int*)array_getkey(pool->x_uints, i);
938 double pool_lookup_float(pool_t*pool, int i)
940 if(!i) return __builtin_nan("");
941 return *(double*)array_getkey(pool->x_floats, i);
943 char*pool_lookup_string(pool_t*pool, int i)
945 return (char*)array_getkey(pool->x_strings, i);
947 namespace_t*pool_lookup_namespace(pool_t*pool, int i)
949 return (namespace_t*)array_getkey(pool->x_namespaces, i);
951 namespace_set_t*pool_lookup_namespace_set(pool_t*pool, int i)
953 return (namespace_set_t*)array_getkey(pool->x_namespace_sets, i);
955 multiname_t*pool_lookup_multiname(pool_t*pool, int i)
957 return (multiname_t*)array_getkey(pool->x_multinames, i);
964 p->x_ints = array_new2(&uint_type);
965 p->x_uints = array_new2(&uint_type);
966 p->x_floats = array_new2(&float_type);
967 p->x_strings = array_new2(&charptr_type);
968 p->x_namespaces = array_new2(&namespace_type);
969 p->x_namespace_sets = array_new2(&namespace_set_type);
970 p->x_multinames = array_new2(&multiname_type);
972 /* add a zero-index entry in each list */
974 array_append(p->x_ints, 0, 0);
975 array_append(p->x_uints, 0, 0);
976 array_append(p->x_floats, 0, 0);
977 array_append(p->x_strings, 0, 0);
978 array_append(p->x_namespaces, 0, 0);
979 array_append(p->x_namespace_sets, 0, 0);
980 array_append(p->x_multinames, 0, 0);
987 void pool_read(pool_t*pool, TAG*tag)
989 int num_ints = swf_GetU30(tag);
990 DEBUG printf("%d ints\n", num_ints);
992 for(t=1;t<num_ints;t++) {
993 S32 v = swf_GetS30(tag);
994 DEBUG printf("int %d) %d\n", t, v);
995 array_append(pool->x_ints, &v, 0);
998 int num_uints = swf_GetU30(tag);
999 DEBUG printf("%d uints\n", num_uints);
1000 for(t=1;t<num_uints;t++) {
1001 U32 v = swf_GetU30(tag);
1002 DEBUG printf("uint %d) %d\n", t, v);
1003 array_append(pool->x_uints, &v, 0);
1006 int num_floats = swf_GetU30(tag);
1007 DEBUG printf("%d floats\n", num_floats);
1008 for(t=1;t<num_floats;t++) {
1009 double d = swf_GetD64(tag);
1010 DEBUG printf("float %d) %f\n", t, d);
1011 array_append(pool->x_floats, &d, 0);
1014 int num_strings = swf_GetU30(tag);
1015 DEBUG printf("%d strings\n", num_strings);
1016 for(t=1;t<num_strings;t++) {
1017 int len = swf_GetU30(tag);
1018 char*s = malloc(len+1);
1019 swf_GetBlock(tag, s, len);
1021 array_append(pool->x_strings, s, 0);
1023 DEBUG printf("%d) \"%s\"\n", t, pool->x_strings->d[t].name);
1025 int num_namespaces = swf_GetU30(tag);
1026 DEBUG printf("%d namespaces\n", num_namespaces);
1027 for(t=1;t<num_namespaces;t++) {
1028 U8 type = swf_GetU8(tag);
1029 int namenr = swf_GetU30(tag);
1030 const char*name = 0;
1032 name = array_getkey(pool->x_strings, namenr);
1033 namespace_t*ns = namespace_new(type, name);
1034 array_append(pool->x_namespaces, ns, 0);
1035 DEBUG printf("%d) %02x \"%s\"\n", t, type, namespace_to_string(ns));
1036 namespace_destroy(ns);
1038 int num_sets = swf_GetU30(tag);
1039 DEBUG printf("%d namespace sets\n", num_sets);
1040 for(t=1;t<num_sets;t++) {
1041 int count = swf_GetU30(tag);
1044 NEW(namespace_set_t, nsset);
1045 for(s=0;s<count;s++) {
1046 int nsnr = swf_GetU30(tag);
1048 fprintf(stderr, "Zero entry in namespace set\n");
1049 namespace_t*ns = (namespace_t*)array_getkey(pool->x_namespaces, nsnr);
1050 list_append(nsset->namespaces, namespace_clone(ns));
1052 array_append(pool->x_namespace_sets, nsset, 0);
1053 DEBUG printf("set %d) %s\n", t, namespace_set_to_string(nsset));
1054 namespace_set_destroy(nsset);
1057 int num_multinames = swf_GetU30(tag);
1058 DEBUG printf("%d multinames\n", num_multinames);
1059 for(t=1;t<num_multinames;t++) {
1061 memset(&m, 0, sizeof(multiname_t));
1062 m.type = swf_GetU8(tag);
1063 if(m.type==0x07 || m.type==0x0d) {
1064 int namespace_index = swf_GetU30(tag);
1065 m.ns = (namespace_t*)array_getkey(pool->x_namespaces, namespace_index);
1066 int name_index = swf_GetU30(tag);
1067 if(name_index) // 0 = '*' (any)
1068 m.name = array_getkey(pool->x_strings, name_index);
1069 } else if(m.type==0x0f || m.type==0x10) {
1070 int name_index = swf_GetU30(tag);
1071 if(name_index) // 0 = '*' (any name)
1072 m.name = array_getkey(pool->x_strings, name_index);
1073 } else if(m.type==0x11 || m.type==0x12) {
1074 } else if(m.type==0x09 || m.type==0x0e) {
1075 int name_index = swf_GetU30(tag);
1076 int namespace_set_index = swf_GetU30(tag);
1078 m.name = array_getkey(pool->x_strings, name_index);
1079 m.namespace_set = (namespace_set_t*)array_getkey(pool->x_namespace_sets, namespace_set_index);
1080 } else if(m.type==0x1b || m.type==0x1c) {
1081 int namespace_set_index = swf_GetU30(tag);
1082 m.namespace_set = (namespace_set_t*)array_getkey(pool->x_namespace_sets, namespace_set_index);
1084 printf("can't parse type %d multinames yet\n", m.type);
1086 DEBUG printf("multiname %d) %s\n", t, multiname_to_string(&m));
1087 array_append(pool->x_multinames, &m, 0);
1091 void pool_write(pool_t*pool, TAG*tag)
1095 /* make sure that all namespaces used by multinames / namespace sets
1096 and all strings used by namespaces exist */
1098 for(t=1;t<pool->x_multinames->num;t++) {
1099 multiname_t*m = (multiname_t*)array_getkey(pool->x_multinames, t);
1101 pool_register_namespace(pool, m->ns);
1103 if(m->namespace_set) {
1104 pool_register_namespace_set(pool, m->namespace_set);
1107 pool_register_string(pool, m->name);
1110 for(t=1;t<pool->x_namespace_sets->num;t++) {
1111 namespace_set_t*set = (namespace_set_t*)array_getkey(pool->x_namespace_sets, t);
1112 namespace_list_t*i = set->namespaces;
1114 pool_register_namespace(pool, i->namespace);
1118 for(t=1;t<pool->x_namespaces->num;t++) {
1119 namespace_t*ns= (namespace_t*)array_getkey(pool->x_namespaces, t);
1120 /* The spec says (page 22): "a value of zero denotes an empty string".
1121 However when actually using zero strings as empty namespaces, the
1122 flash player breaks.*/
1123 //if(ns->name && ns->name[0])
1124 array_append_if_new(pool->x_strings, ns->name, 0);
1127 //pool_register_int(pool, 15);
1128 //pool_register_int(pool, 1);
1129 //pool_register_int(pool, 0);
1132 swf_SetU30(tag, pool->x_ints->num>1?pool->x_ints->num:0);
1133 for(t=1;t<pool->x_ints->num;t++) {
1134 S32 val = *(int*)array_getkey(pool->x_ints, t);
1135 swf_SetS30(tag, val);
1137 swf_SetU30(tag, pool->x_uints->num>1?pool->x_uints->num:0);
1138 for(t=1;t<pool->x_uints->num;t++) {
1139 swf_SetU30(tag, *(unsigned int*)array_getkey(pool->x_uints, t));
1141 swf_SetU30(tag, pool->x_floats->num>1?pool->x_floats->num:0);
1142 for(t=1;t<pool->x_floats->num;t++) {
1143 double d = pool_lookup_float(pool, t);
1146 swf_SetU30(tag, pool->x_strings->num>1?pool->x_strings->num:0);
1147 for(t=1;t<pool->x_strings->num;t++) {
1148 swf_SetU30String(tag, array_getkey(pool->x_strings, t));
1150 swf_SetU30(tag, pool->x_namespaces->num>1?pool->x_namespaces->num:0);
1151 for(t=1;t<pool->x_namespaces->num;t++) {
1152 namespace_t*ns= (namespace_t*)array_getkey(pool->x_namespaces, t);
1153 swf_SetU8(tag, ns->access);
1154 const char*name = ns->name;
1157 //if(name && name[0])
1158 i = pool_find_string(pool, name);
1162 swf_SetU30(tag, pool->x_namespace_sets->num>1?pool->x_namespace_sets->num:0);
1163 for(t=1;t<pool->x_namespace_sets->num;t++) {
1164 namespace_set_t*set = (namespace_set_t*)array_getkey(pool->x_namespace_sets, t);
1165 namespace_list_t*i = set->namespaces;
1166 int len = list_length(i);
1167 swf_SetU30(tag, len);
1169 int index = pool_find_namespace(pool, i->namespace);
1170 swf_SetU30(tag, index);
1175 swf_SetU30(tag, pool->x_multinames->num>1?pool->x_multinames->num:0);
1176 for(t=1;t<pool->x_multinames->num;t++) {
1177 multiname_t*m = (multiname_t*)array_getkey(pool->x_multinames, t);
1178 swf_SetU8(tag, m->type);
1181 assert(m->type==0x07 || m->type==0x0d);
1182 int i = pool_find_namespace(pool, m->ns);
1183 if(i<0) fprintf(stderr, "internal error: unregistered namespace %02x %s %s\n", m->ns->access, access2str(m->ns->access), m->ns->name);
1186 assert(m->type!=0x07 && m->type!=0x0d);
1189 assert(m->type==0x09 || m->type==0x0e || m->type==0x07 || m->type==0x0d || m->type==0x0f || m->type==0x10);
1190 int i = pool_find_string(pool, m->name);
1191 if(i<0) fprintf(stderr, "internal error: unregistered name\n");
1194 assert(m->type!=0x09 && m->type!=0x0e && m->type!=0x07 && m->type!=0x0d && m->type!=0x0f && m->type!=0x10);
1196 if(m->namespace_set) {
1197 assert(m->type==0x09 || m->type==0x0e || m->type==0x1c || m->type==0x1b);
1198 int i = pool_find_namespace_set(pool, m->namespace_set);
1199 if(i<0) fprintf(stderr, "internal error: unregistered namespace set\n");
1202 assert(m->type!=0x09 && m->type!=0x0e && m->type!=0x1c && m->type!=0x1b);
1208 void pool_destroy(pool_t*pool)
1211 array_free(pool->x_ints);
1212 array_free(pool->x_uints);
1213 array_free(pool->x_floats);
1214 array_free(pool->x_strings);
1215 array_free(pool->x_namespaces);
1216 array_free(pool->x_namespace_sets);
1217 array_free(pool->x_multinames);