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);
185 sprintf(string, "[%s]NULL", access, s);
187 sprintf(string, "[%s]\"\"", access, s);
189 sprintf(string, "[%s]", access, s);
195 namespace_t* namespace_clone(namespace_t*other)
200 n->access = other->access;
201 n->name = other->name?strdup(other->name):0;
205 namespace_t* namespace_fromstring(const char*name)
207 namespace_t*ns = malloc(sizeof(namespace_t));
208 memset(ns, 0, sizeof(namespace_t));
211 char*n = strdup(name);
212 char*bracket = strchr(n, ']');
216 name += (bracket-n)+1;
217 if(!strcmp(a, "")) access=0x16;
218 else if(!strcmp(a, "undefined")) access=0x08; // public??
219 else if(!strcmp(a, "package")) access=0x16;
220 else if(!strcmp(a, "public")) access=0x16;
221 else if(!strcmp(a, "packageinternal")) access=0x17;
222 else if(!strcmp(a, "protected")) access=0x18;
223 else if(!strcmp(a, "explicit")) access=0x19;
224 else if(!strcmp(a, "staticprotected")) access=0x1a;
225 else if(!strcmp(a, "private")) access=0x05;
227 fprintf(stderr, "Undefined access level: [%s]\n", a);
233 ns->name = strdup(name);
238 ns->name = strdup(name);
243 namespace_t* namespace_new(U8 access, const char*name)
245 namespace_t*ns = malloc(sizeof(namespace_t));
247 /* not sure what namespaces with empty strings are good for, but they *do* exist */
248 ns->name = name?strdup(name):0;
251 namespace_t* namespace_new_undefined(const char*name) {
252 return namespace_new(0x08, name); // public?
254 namespace_t* namespace_new_package(const char*name) {
255 return namespace_new(0x16 , name);
257 namespace_t* namespace_new_packageinternal(const char*name) {
258 return namespace_new(0x17, name);
260 namespace_t* namespace_new_protected(const char*name) {
261 return namespace_new(0x18, name);
263 namespace_t* namespace_new_explicit(const char*name) {
264 return namespace_new(0x19, name);
266 namespace_t* namespace_new_staticprotected(const char*name) {
267 return namespace_new(0x1a, name);
269 namespace_t* namespace_new_private(const char*name) {
270 return namespace_new(0x05, name);
273 void namespace_destroy(namespace_t*n)
276 free(n->name);n->name=0;
282 type_t namespace_type = {
283 dup: (dup_func)namespace_clone,
284 hash: (hash_func)namespace_hash,
285 free: (free_func)namespace_destroy,
286 equals: (equals_func)namespace_equals
289 // ---------------------------namespace sets --------------------------------
291 unsigned int namespace_set_hash(namespace_set_t*set)
295 namespace_list_t*l = set->namespaces;
296 unsigned int hash = 0;
298 hash = crc32_add_byte(hash, l->namespace->access);
299 hash = crc32_add_string(hash, l->namespace->name);
305 int namespace_set_equals(namespace_set_t*m1, namespace_set_t*m2)
309 namespace_list_t*l1 = m1->namespaces;
310 namespace_list_t*l2 = m2->namespaces;
312 if(l1->namespace->access != l2->namespace->access)
314 if(!(l1->namespace->name) != !(l2->namespace->name))
316 if(l1->namespace->name && l2->namespace->name && strcmp(l1->namespace->name, l2->namespace->name))
326 namespace_set_t* namespace_set_clone(namespace_set_t*other)
330 NEW(namespace_set_t,set);
331 set->namespaces = list_new();
332 namespace_list_t*l = other->namespaces;
334 list_append(set->namespaces, namespace_clone(l->namespace));
339 namespace_set_t* namespace_set_new()
341 NEW(namespace_set_t,set);
342 set->namespaces = list_new();
345 char* namespace_set_tostring(namespace_set_t*set)
348 return strdup("NULL");
349 /* TODO: is the order of the namespaces important (does it
350 change the lookup order?). E.g. flex freely shuffles namespaces
352 If the order is not important, we can optimize constant pools by sorting
356 namespace_list_t*lns = set->namespaces;
358 char*s = namespace_tostring(lns->namespace);
363 char*desc = malloc(l+16);
365 lns = set->namespaces;
367 char*s = namespace_tostring(lns->namespace);
378 void namespace_set_destroy(namespace_set_t*set)
381 namespace_list_t*l = set->namespaces;
383 namespace_destroy(l->namespace);l->namespace=0;
386 list_free(set->namespaces);
391 type_t namespace_set_type = {
392 dup: (dup_func)namespace_set_clone,
393 hash: (hash_func)namespace_set_hash,
394 free: (free_func)namespace_set_destroy,
395 equals: (equals_func)namespace_set_equals
398 // ----------------------------- multiname ----------------------------------
400 unsigned int multiname_hash(multiname_t*m)
404 unsigned int hash = crc32_add_byte(0, m->type);
406 hash = crc32_add_string(hash, m->name);
409 hash = crc32_add_byte(hash, m->ns->access);
410 hash = crc32_add_string(hash, m->ns->name);
412 if(m->namespace_set) {
413 namespace_list_t*l = m->namespace_set->namespaces;
415 hash = crc32_add_byte(hash, l->namespace->access);
416 hash = crc32_add_string(hash, l->namespace->name);
423 int multiname_equals(multiname_t*m1, multiname_t*m2)
427 if(m1->type!=m2->type)
430 if((!m1->name) != (!m2->name))
432 if((!m1->ns) != (!m2->ns))
434 if((!m1->namespace_set) != (!m2->namespace_set))
437 if(m1->name && m2->name && strcmp(m1->name,m2->name))
439 if(m1->ns && m2->ns) {
440 if(!namespace_equals(m1->ns, m2->ns))
443 if(m1->namespace_set && m2->namespace_set) {
444 if(!namespace_set_equals(m1->namespace_set, m2->namespace_set))
450 multiname_t* multiname_new(namespace_t*ns, const char*name)
455 m->ns = namespace_new_packageinternal("");
457 m->ns = namespace_clone(ns);
459 m->name = strdup(name);
463 multiname_t* multiname_clone(multiname_t*other)
468 m->type = other->type;
470 m->ns = namespace_clone(other->ns);
471 if(other->namespace_set)
472 m->namespace_set = namespace_set_clone(other->namespace_set);
474 m->name = strdup(other->name);
479 char* access2str(int type)
481 if(type==0x08) return "access08";
482 else if(type==0x16) return "public";
483 else if(type==0x17) return "packageinternal";
484 else if(type==0x18) return "protected";
485 else if(type==0x19) return "explicit";
486 else if(type==0x1A) return "staticprotected";
487 else if(type==0x05) return "private";
489 fprintf(stderr, "Undefined access type %02x\n", type);
495 char multiname_late_namespace(multiname_t*m)
499 return (m->type==RTQNAME || m->type==RTQNAMEA ||
500 m->type==RTQNAMEL || m->type==RTQNAMELA);
503 char multiname_late_name(multiname_t*m)
507 return m->type==RTQNAMEL || m->type==RTQNAMELA ||
508 m->type==MULTINAMEL || m->type==MULTINAMELA;
511 char* multiname_tostring(multiname_t*m)
515 return strdup("NULL");
517 return strdup("--<MULTINAME 0xff>--");
519 char*name = m->name?escape_string(m->name):strdup("*");
520 int namelen = strlen(name);
522 if(m->type==QNAME || m->type==QNAMEA) {
523 char*nsname = escape_string(m->ns->name);
524 mname = malloc(strlen(nsname)+namelen+32);
526 if(m->type == QNAMEA)
527 strcat(mname, ",attr");
529 strcat(mname,access2str(m->ns->access));
531 strcat(mname, nsname);
535 } else if(m->type==RTQNAME || m->type==RTQNAMEA) {
536 mname = malloc(namelen+32);
537 strcpy(mname, "<rt");
538 if(m->type == RTQNAMEA)
539 strcat(mname, ",attr");
542 } else if(m->type==RTQNAMEL) {
543 mname = strdup("<rt,l>");
544 } else if(m->type==RTQNAMELA) {
545 mname = strdup("<rt,l,attr>");
546 } else if(m->type==MULTINAME || m->type==MULTINAMEA) {
547 char*s = namespace_set_tostring(m->namespace_set);
548 mname = malloc(strlen(s)+namelen+16);
549 if(m->type == MULTINAME)
550 strcpy(mname,"<multi>");
552 strcpy(mname,"<multi,attr>");
557 } else if(m->type==MULTINAMEL || m->type==MULTINAMELA) {
558 char*s = namespace_set_tostring(m->namespace_set);
559 mname = malloc(strlen(s)+16);
560 if(m->type == MULTINAMEL)
561 strcpy(mname,"<l,multi>");
563 strcpy(mname,"<l,multi,attr>");
567 fprintf(stderr, "Invalid multiname type: %02x\n", m->type);
573 multiname_t* multiname_fromstring(const char*name2)
577 char*n = strdup(name2);
578 char*p = strstr(n, "::");
579 char*namespace=0,*name=0;
582 fprintf(stderr, "Error: single ':' in name\n");
590 if(strchr(namespace, ':')) {
591 fprintf(stderr, "Error: single ':' in namespace\n");
593 if(strchr(name, ':')) {
594 fprintf(stderr, "Error: single ':' in qualified name\n");
598 multiname_t*m = malloc(sizeof(multiname_t));
599 memset(m, 0, sizeof(multiname_t));
601 m->namespace_set = 0;
602 m->ns = namespace_fromstring(namespace);
603 m->name = name?strdup(name):0;
608 void multiname_destroy(multiname_t*m)
612 free((void*)m->name);m->name = 0;
615 namespace_destroy(m->ns);m->ns = 0;
617 if(m->namespace_set) {
618 namespace_set_destroy(m->namespace_set);m->namespace_set = 0;
625 type_t multiname_type = {
626 dup: (dup_func)multiname_clone,
627 hash: (hash_func)multiname_hash,
628 free: (free_func)multiname_destroy,
629 equals: (equals_func)multiname_equals
633 // ------------------------------- constants -------------------------------------
635 #define NS_TYPE(x) ((x) == 0x08 || (x) == 0x16 || (x) == 0x17 || (x) == 0x18 || \
636 (x) == 0x19 || (x) == 0x1a || (x) == 0x05)
638 #define UNIQUE_CONSTANT(x) ((x) == CONSTANT_TRUE || (x) == CONSTANT_FALSE || (x) == CONSTANT_NULL || (x) == CONSTANT_UNDEFINED)
640 constant_t* constant_new_int(int i)
644 c->type = CONSTANT_INT;
647 constant_t* constant_new_uint(unsigned int u)
651 c->type = CONSTANT_UINT;
654 constant_t* constant_new_float(double f)
658 c->type = CONSTANT_FLOAT;
661 constant_t* constant_new_string(char*s)
665 c->type = CONSTANT_STRING;
668 constant_t* constant_new_namespace(namespace_t*ns)
671 c->ns = namespace_clone(ns);
672 c->type = ns->access;
673 assert(NS_TYPE(c->type));
676 constant_t* constant_new_true()
679 c->type = CONSTANT_TRUE;
682 constant_t* constant_new_false()
685 c->type = CONSTANT_FALSE;
688 constant_t* constant_new_null()
691 c->type = CONSTANT_NULL;
694 constant_t* constant_new_undefined()
697 c->type = CONSTANT_UNDEFINED;
700 constant_t* constant_fromindex(pool_t*pool, int index, int type)
703 /* even for nonvalued constants (like TRUE/FALSE etc.), a nonzero
704 index is present to indicate that a type is coming */
709 if(NS_TYPE(c->type)) {
710 c->ns = namespace_clone(pool_lookup_namespace(pool, index));
711 } else if(c->type == CONSTANT_INT) {
712 c->i = pool_lookup_int(pool, index);
713 } else if(c->type == CONSTANT_UINT) {
714 c->u = pool_lookup_uint(pool, index);
715 } else if(c->type == CONSTANT_FLOAT) {
716 c->f = pool_lookup_float(pool, index);
717 } else if(c->type == CONSTANT_STRING) {
718 c->s = strdup(pool_lookup_string(pool, index));
719 } else if(UNIQUE_CONSTANT(c->type)) {
722 fprintf(stderr, "invalid constant type %02x\n", c->type);
726 char* constant_tostring(constant_t*c)
731 if(NS_TYPE(c->type)) {
732 return namespace_tostring(c->ns);
733 } else if(c->type == CONSTANT_INT) {
734 sprintf(buf, "%d", c->i);
736 } else if(c->type == CONSTANT_UINT) {
737 sprintf(buf, "%u", c->u);
739 } else if(c->type == CONSTANT_FLOAT) {
741 sprintf(buf, "%f", c->f);
743 } else if(c->type == CONSTANT_STRING) {
745 } else if(c->type == CONSTANT_TRUE) {
746 return strdup("true");
747 } else if(c->type == CONSTANT_FALSE) {
748 return strdup("false");
749 } else if(c->type == CONSTANT_NULL) {
750 return strdup("null");
751 } else if(c->type == CONSTANT_UNDEFINED) {
752 return strdup("undefined");
754 fprintf(stderr, "invalid constant type %02x\n", c->type);
758 char constant_has_index(constant_t*c)
762 return !UNIQUE_CONSTANT(c->type);
764 int constant_get_index(pool_t*pool, constant_t*c)
768 if(NS_TYPE(c->type)) {
770 /*if(c->type!=c->ns->access) {
771 printf("%02x<->%02x\n", c->type, c->ns->access);
773 assert(c->type == c->ns->access);
774 return pool_register_namespace(pool, c->ns);
775 } else if(c->type == CONSTANT_INT) {
776 return pool_register_int(pool, c->i);
777 } else if(c->type == CONSTANT_UINT) {
778 return pool_register_uint(pool, c->u);
779 } else if(c->type == CONSTANT_FLOAT) {
780 return pool_register_float(pool, c->f);
781 } else if(c->type == CONSTANT_STRING) {
782 return pool_register_string(pool, c->s);
783 } else if(!constant_has_index(c)) {
786 fprintf(stderr, "invalid constant type %02x\n", c->type);
790 void constant_free(constant_t*c)
794 if(c->type == CONSTANT_STRING) {
796 } else if (NS_TYPE(c->type)) {
797 namespace_destroy(c->ns);c->ns=0;
801 // ------------------------------- pool -------------------------------------
803 int pool_register_uint(pool_t*p, unsigned int i)
805 int pos = array_append_if_new(p->x_uints, &i, 0);
809 int pool_register_int(pool_t*p, int i)
811 int pos = array_append_if_new(p->x_ints, &i, 0);
815 int pool_register_float(pool_t*p, double d)
817 int pos = array_append_if_new(p->x_floats, &d, 0);
821 int pool_register_string(pool_t*pool, const char*s)
824 ptroff_t l = strlen(s);
825 int pos = array_append_if_new(pool->x_strings, s, (void*)l);
829 int pool_register_namespace(pool_t*pool, namespace_t*ns)
832 int pos = array_append_if_new(pool->x_namespaces, ns, 0);
836 int pool_register_namespace_set(pool_t*pool, namespace_set_t*set)
839 int pos = array_append_if_new(pool->x_namespace_sets, set, 0);
843 int pool_register_multiname(pool_t*pool, multiname_t*n)
846 int pos = array_append_if_new(pool->x_multinames, n, 0);
850 int pool_register_multiname2(pool_t*pool, char*name)
853 multiname_t*n = multiname_fromstring(name);
854 int pos = array_append_if_new(pool->x_multinames, n, 0);
855 multiname_destroy(n);
861 int pool_find_uint(pool_t*pool, unsigned int x)
863 int i = array_find(pool->x_uints, &x);
865 fprintf(stderr, "Couldn't find uint \"%d\" in constant pool\n", x);
870 int pool_find_int(pool_t*pool, int x)
872 int i = array_find(pool->x_ints, &x);
874 fprintf(stderr, "Couldn't find int \"%d\" in constant pool\n", x);
879 int pool_find_float(pool_t*pool, double x)
881 int i = array_find(pool->x_ints, &x);
883 fprintf(stderr, "Couldn't find int \"%d\" in constant pool\n", x);
888 int pool_find_namespace(pool_t*pool, namespace_t*ns)
892 int i = array_find(pool->x_namespaces, ns);
894 char*s = namespace_tostring(ns);
895 fprintf(stderr, "Couldn't find namespace \"%s\" %08x in constant pool\n", s, ns);
901 int pool_find_namespace_set(pool_t*pool, namespace_set_t*set)
905 int i = array_find(pool->x_namespace_sets, set);
907 char*s = namespace_set_tostring(set);
908 fprintf(stderr, "Couldn't find namespace_set \"%s\" in constant pool\n", s);
914 int pool_find_string(pool_t*pool, const char*s)
918 int i = array_find(pool->x_strings, s);
920 fprintf(stderr, "Couldn't find string \"%s\" in constant pool\n", s);
925 int pool_find_multiname(pool_t*pool, multiname_t*name)
929 int i = array_find(pool->x_multinames, name);
931 char*s = multiname_tostring(name);
932 fprintf(stderr, "Couldn't find multiname \"%s\" in constant pool\n", s);
939 int pool_lookup_int(pool_t*pool, int i)
942 return *(int*)array_getkey(pool->x_ints, i);
944 unsigned int pool_lookup_uint(pool_t*pool, int i)
947 return *(unsigned int*)array_getkey(pool->x_uints, i);
949 double pool_lookup_float(pool_t*pool, int i)
951 if(!i) return __builtin_nan("");
952 return *(double*)array_getkey(pool->x_floats, i);
954 char*pool_lookup_string(pool_t*pool, int i)
956 return (char*)array_getkey(pool->x_strings, i);
958 string_t pool_lookup_string2(pool_t*pool, int i)
960 char*s = (char*)array_getkey(pool->x_strings, i);
961 int len = (int)(ptroff_t)array_getvalue(pool->x_strings, i);
962 return string_new(s,len);
964 namespace_t*pool_lookup_namespace(pool_t*pool, int i)
966 return (namespace_t*)array_getkey(pool->x_namespaces, i);
968 namespace_set_t*pool_lookup_namespace_set(pool_t*pool, int i)
970 return (namespace_set_t*)array_getkey(pool->x_namespace_sets, i);
972 multiname_t*pool_lookup_multiname(pool_t*pool, int i)
974 return (multiname_t*)array_getkey(pool->x_multinames, i);
981 p->x_ints = array_new2(&uint_type);
982 p->x_uints = array_new2(&uint_type);
983 p->x_floats = array_new2(&float_type);
984 p->x_strings = array_new2(&charptr_type);
985 p->x_namespaces = array_new2(&namespace_type);
986 p->x_namespace_sets = array_new2(&namespace_set_type);
987 p->x_multinames = array_new2(&multiname_type);
989 /* add a zero-index entry in each list */
991 array_append(p->x_ints, 0, 0);
992 array_append(p->x_uints, 0, 0);
993 array_append(p->x_floats, 0, 0);
994 array_append(p->x_strings, 0, 0);
995 array_append(p->x_namespaces, 0, 0);
996 array_append(p->x_namespace_sets, 0, 0);
997 array_append(p->x_multinames, 0, 0);
1004 void pool_read(pool_t*pool, TAG*tag)
1006 int num_ints = swf_GetU30(tag);
1007 DEBUG printf("%d ints\n", num_ints);
1009 for(t=1;t<num_ints;t++) {
1010 S32 v = swf_GetABCS32(tag);
1011 DEBUG printf("int %d) %d\n", t, v);
1012 array_append(pool->x_ints, &v, 0);
1015 int num_uints = swf_GetU30(tag);
1016 DEBUG printf("%d uints\n", num_uints);
1017 for(t=1;t<num_uints;t++) {
1018 U32 v = swf_GetABCU32(tag);
1019 DEBUG printf("uint %d) %d\n", t, v);
1020 array_append(pool->x_uints, &v, 0);
1023 int num_floats = swf_GetU30(tag);
1024 DEBUG printf("%d floats\n", num_floats);
1025 for(t=1;t<num_floats;t++) {
1026 double d = swf_GetD64(tag);
1027 DEBUG printf("float %d) %f\n", t, d);
1028 array_append(pool->x_floats, &d, 0);
1031 int num_strings = swf_GetU30(tag);
1032 DEBUG printf("%d strings\n", num_strings);
1033 for(t=1;t<num_strings;t++) {
1034 int len = swf_GetU30(tag);
1035 char*s = malloc(len+1);
1036 swf_GetBlock(tag, s, len);
1038 array_append(pool->x_strings, s, (void*)(ptroff_t)len);
1040 DEBUG printf("%d) \"%s\"\n", t, pool->x_strings->d[t].name);
1042 int num_namespaces = swf_GetU30(tag);
1043 DEBUG printf("%d namespaces\n", num_namespaces);
1044 for(t=1;t<num_namespaces;t++) {
1045 U8 type = swf_GetU8(tag);
1046 int namenr = swf_GetU30(tag);
1047 const char*name = 0;
1049 name = array_getkey(pool->x_strings, namenr);
1050 namespace_t*ns = namespace_new(type, name);
1051 array_append(pool->x_namespaces, ns, 0);
1052 DEBUG printf("%d) %02x \"%s\"\n", t, type, namespace_tostring(ns));
1053 namespace_destroy(ns);
1055 int num_sets = swf_GetU30(tag);
1056 DEBUG printf("%d namespace sets\n", num_sets);
1057 for(t=1;t<num_sets;t++) {
1058 int count = swf_GetU30(tag);
1061 NEW(namespace_set_t, nsset);
1062 for(s=0;s<count;s++) {
1063 int nsnr = swf_GetU30(tag);
1065 fprintf(stderr, "Zero entry in namespace set\n");
1066 namespace_t*ns = (namespace_t*)array_getkey(pool->x_namespaces, nsnr);
1067 list_append(nsset->namespaces, namespace_clone(ns));
1069 array_append(pool->x_namespace_sets, nsset, 0);
1070 DEBUG printf("set %d) %s\n", t, namespace_set_tostring(nsset));
1071 namespace_set_destroy(nsset);
1074 int num_multinames = swf_GetU30(tag);
1075 DEBUG printf("%d multinames\n", num_multinames);
1076 for(t=1;t<num_multinames;t++) {
1078 memset(&m, 0, sizeof(multiname_t));
1079 m.type = swf_GetU8(tag);
1080 if(m.type==0x07 || m.type==0x0d) {
1081 int namespace_index = swf_GetU30(tag);
1082 m.ns = (namespace_t*)array_getkey(pool->x_namespaces, namespace_index);
1083 int name_index = swf_GetU30(tag);
1084 if(name_index) // 0 = '*' (any)
1085 m.name = array_getkey(pool->x_strings, name_index);
1086 } else if(m.type==0x0f || m.type==0x10) {
1087 int name_index = swf_GetU30(tag);
1088 if(name_index) // 0 = '*' (any name)
1089 m.name = array_getkey(pool->x_strings, name_index);
1090 } else if(m.type==0x11 || m.type==0x12) {
1091 } else if(m.type==0x09 || m.type==0x0e) {
1092 int name_index = swf_GetU30(tag);
1093 int namespace_set_index = swf_GetU30(tag);
1095 m.name = array_getkey(pool->x_strings, name_index);
1096 m.namespace_set = (namespace_set_t*)array_getkey(pool->x_namespace_sets, namespace_set_index);
1097 } else if(m.type==0x1b || m.type==0x1c) {
1098 int namespace_set_index = swf_GetU30(tag);
1099 m.namespace_set = (namespace_set_t*)array_getkey(pool->x_namespace_sets, namespace_set_index);
1101 printf("can't parse type %d multinames yet\n", m.type);
1103 DEBUG printf("multiname %d) %s\n", t, multiname_tostring(&m));
1104 array_append(pool->x_multinames, &m, 0);
1108 void pool_write(pool_t*pool, TAG*tag)
1112 /* make sure that all namespaces used by multinames / namespace sets
1113 and all strings used by namespaces exist */
1115 for(t=1;t<pool->x_multinames->num;t++) {
1116 multiname_t*m = (multiname_t*)array_getkey(pool->x_multinames, t);
1118 pool_register_namespace(pool, m->ns);
1120 if(m->namespace_set) {
1121 pool_register_namespace_set(pool, m->namespace_set);
1124 pool_register_string(pool, m->name);
1127 for(t=1;t<pool->x_namespace_sets->num;t++) {
1128 namespace_set_t*set = (namespace_set_t*)array_getkey(pool->x_namespace_sets, t);
1129 namespace_list_t*i = set->namespaces;
1131 pool_register_namespace(pool, i->namespace);
1135 for(t=1;t<pool->x_namespaces->num;t++) {
1136 namespace_t*ns= (namespace_t*)array_getkey(pool->x_namespaces, t);
1137 /* The spec says (page 22): "a value of zero denotes an empty string".
1138 However when actually using zero strings as empty namespaces, the
1139 flash player breaks.*/
1140 //if(ns->name && ns->name[0])
1141 pool_register_string(pool, ns->name);
1144 //pool_register_int(pool, 15);
1145 //pool_register_int(pool, 1);
1146 //pool_register_int(pool, 0);
1149 swf_SetU30(tag, pool->x_ints->num>1?pool->x_ints->num:0);
1150 for(t=1;t<pool->x_ints->num;t++) {
1151 S32 val = *(int*)array_getkey(pool->x_ints, t);
1152 swf_SetABCS32(tag, val);
1154 swf_SetU30(tag, pool->x_uints->num>1?pool->x_uints->num:0);
1155 for(t=1;t<pool->x_uints->num;t++) {
1156 swf_SetABCU32(tag, *(unsigned int*)array_getkey(pool->x_uints, t));
1158 swf_SetU30(tag, pool->x_floats->num>1?pool->x_floats->num:0);
1159 for(t=1;t<pool->x_floats->num;t++) {
1160 double d = pool_lookup_float(pool, t);
1163 swf_SetU30(tag, pool->x_strings->num>1?pool->x_strings->num:0);
1164 for(t=1;t<pool->x_strings->num;t++) {
1165 string_t str = pool_lookup_string2(pool, t);
1166 swf_SetU30String(tag, str.str, str.len);
1168 swf_SetU30(tag, pool->x_namespaces->num>1?pool->x_namespaces->num:0);
1169 for(t=1;t<pool->x_namespaces->num;t++) {
1170 namespace_t*ns= (namespace_t*)array_getkey(pool->x_namespaces, t);
1171 swf_SetU8(tag, ns->access);
1172 const char*name = ns->name;
1175 //if(name && name[0])
1176 i = pool_find_string(pool, name);
1180 swf_SetU30(tag, pool->x_namespace_sets->num>1?pool->x_namespace_sets->num:0);
1181 for(t=1;t<pool->x_namespace_sets->num;t++) {
1182 namespace_set_t*set = (namespace_set_t*)array_getkey(pool->x_namespace_sets, t);
1183 namespace_list_t*i = set->namespaces;
1184 int len = list_length(i);
1185 swf_SetU30(tag, len);
1187 int index = pool_find_namespace(pool, i->namespace);
1188 swf_SetU30(tag, index);
1193 swf_SetU30(tag, pool->x_multinames->num>1?pool->x_multinames->num:0);
1194 for(t=1;t<pool->x_multinames->num;t++) {
1195 multiname_t*m = (multiname_t*)array_getkey(pool->x_multinames, t);
1196 swf_SetU8(tag, m->type);
1199 assert(m->type==0x07 || m->type==0x0d);
1200 int i = pool_find_namespace(pool, m->ns);
1201 if(i<0) fprintf(stderr, "internal error: unregistered namespace %02x %s %s\n", m->ns->access, access2str(m->ns->access), m->ns->name);
1204 assert(m->type!=0x07 && m->type!=0x0d);
1207 assert(m->type==0x09 || m->type==0x0e || m->type==0x07 || m->type==0x0d || m->type==0x0f || m->type==0x10);
1208 int i = pool_find_string(pool, m->name);
1209 if(i<0) fprintf(stderr, "internal error: unregistered name\n");
1212 assert(m->type!=0x09 && m->type!=0x0e && m->type!=0x07 && m->type!=0x0d && m->type!=0x0f && m->type!=0x10);
1214 if(m->namespace_set) {
1215 assert(m->type==0x09 || m->type==0x0e || m->type==0x1c || m->type==0x1b);
1216 int i = pool_find_namespace_set(pool, m->namespace_set);
1217 if(i<0) fprintf(stderr, "internal error: unregistered namespace set\n");
1220 assert(m->type!=0x09 && m->type!=0x0e && m->type!=0x1c && m->type!=0x1b);
1226 void pool_destroy(pool_t*pool)
1229 array_free(pool->x_ints);
1230 array_free(pool->x_uints);
1231 array_free(pool->x_floats);
1232 array_free(pool->x_strings);
1233 array_free(pool->x_namespaces);
1234 array_free(pool->x_namespace_sets);
1235 array_free(pool->x_multinames);