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) {
59 if(*v1==*v2) return 1;
60 if(*v1!=*v1 && *v2!=*v2) return 1; //both values are NaN
71 // ----------------------------- uint ----------------------------------
73 unsigned int undefined_uint = 0;
75 void*uint_clone(const void*_v) {
78 const unsigned int*v1=_v;
79 unsigned int*v2 = malloc(sizeof(unsigned int));
83 unsigned int uint_hash(const void*_v) {
86 const unsigned int*v=_v;
89 void uint_destroy(void*_v) {
90 unsigned int*v = (unsigned int*)_v;
94 char uint_equals(const void*_v1, const void*_v2) {
95 const unsigned int*v1=_v1;
96 const unsigned int*v2=_v2;
103 dup: (dup_func)uint_clone,
104 hash: (hash_func)uint_hash,
105 free: (free_func)uint_destroy,
106 equals: (equals_func)uint_equals
109 // ----------------------------- namespace ----------------------------------
111 unsigned int namespace_hash(namespace_t*n)
115 unsigned int hash = 0;
116 hash = crc32_add_byte(hash, n->access);
117 hash = crc32_add_string(hash, n->name);
121 unsigned char namespace_equals(const namespace_t*n1, const namespace_t*n2)
125 if(n1->access != n2->access)
127 if(!(n1->name) != !(n2->name))
129 if(n1->name && n2->name && strcmp(n1->name, n2->name))
134 char*escape_string(const char*str)
137 return strdup("NULL");
139 unsigned const char*s=str;
152 char*newstr = malloc(len+1);
157 dest+=sprintf(dest, "\\%d", *s);
160 dest+=sprintf(dest, "\\r");
162 dest+=sprintf(dest, "\\n");
164 dest+=sprintf(dest, "\\t");
166 dest+=sprintf(dest, "\\%2o", *s);
170 dest+=sprintf(dest, "\\x%02x", *s);
178 char* namespace_tostring(namespace_t*ns)
181 return strdup("NULL");
183 U8 type = ns->access;
184 access = access2str(type);
185 char*s = escape_string(ns->name);
186 char*string = (char*)malloc(strlen(access)+strlen(s)+7);
188 sprintf(string, "[%s]NULL", access, s);
190 sprintf(string, "[%s]\"\"", access, s);
192 sprintf(string, "[%s]", access, s);
198 namespace_t* namespace_clone(namespace_t*other)
203 n->access = other->access;
204 n->name = other->name?strdup(other->name):0;
208 namespace_t* namespace_fromstring(const char*name)
210 namespace_t*ns = malloc(sizeof(namespace_t));
211 memset(ns, 0, sizeof(namespace_t));
214 char*n = strdup(name);
215 char*bracket = strchr(n, ']');
219 name += (bracket-n)+1;
220 if(!strcmp(a, "")) access=0x16;
221 else if(!strcmp(a, "undefined")) access=0x08; // public??
222 else if(!strcmp(a, "package")) access=0x16;
223 else if(!strcmp(a, "public")) access=0x16;
224 else if(!strcmp(a, "packageinternal")) access=0x17;
225 else if(!strcmp(a, "protected")) access=0x18;
226 else if(!strcmp(a, "explicit")) access=0x19;
227 else if(!strcmp(a, "staticprotected")) access=0x1a;
228 else if(!strcmp(a, "private")) access=0x05;
230 fprintf(stderr, "Undefined access level: [%s]\n", a);
236 ns->name = strdup(name);
241 ns->name = strdup(name);
246 namespace_t* namespace_new(U8 access, const char*name)
248 namespace_t*ns = malloc(sizeof(namespace_t));
250 /* not sure what namespaces with empty strings are good for, but they *do* exist */
251 ns->name = name?strdup(name):0;
254 namespace_t* namespace_new_undefined(const char*name) {
255 return namespace_new(0x08, name); // public?
257 namespace_t* namespace_new_package(const char*name) {
258 return namespace_new(0x16 , name);
260 namespace_t* namespace_new_packageinternal(const char*name) {
261 return namespace_new(0x17, name);
263 namespace_t* namespace_new_protected(const char*name) {
264 return namespace_new(0x18, name);
266 namespace_t* namespace_new_explicit(const char*name) {
267 return namespace_new(0x19, name);
269 namespace_t* namespace_new_staticprotected(const char*name) {
270 return namespace_new(0x1a, name);
272 namespace_t* namespace_new_private(const char*name) {
273 return namespace_new(0x05, name);
276 void namespace_destroy(namespace_t*n)
279 free(n->name);n->name=0;
285 type_t namespace_type = {
286 dup: (dup_func)namespace_clone,
287 hash: (hash_func)namespace_hash,
288 free: (free_func)namespace_destroy,
289 equals: (equals_func)namespace_equals
292 // ---------------------------namespace sets --------------------------------
294 unsigned int namespace_set_hash(namespace_set_t*set)
298 namespace_list_t*l = set->namespaces;
299 unsigned int hash = 0;
301 hash = crc32_add_byte(hash, l->namespace->access);
302 hash = crc32_add_string(hash, l->namespace->name);
308 int namespace_set_equals(namespace_set_t*m1, namespace_set_t*m2)
312 namespace_list_t*l1 = m1->namespaces;
313 namespace_list_t*l2 = m2->namespaces;
315 if(l1->namespace->access != l2->namespace->access)
317 if(!(l1->namespace->name) != !(l2->namespace->name))
319 if(l1->namespace->name && l2->namespace->name && strcmp(l1->namespace->name, l2->namespace->name))
329 namespace_set_t* namespace_set_clone(namespace_set_t*other)
333 NEW(namespace_set_t,set);
334 set->namespaces = list_new();
335 namespace_list_t*l = other->namespaces;
337 list_append(set->namespaces, namespace_clone(l->namespace));
342 namespace_set_t* namespace_set_new()
344 NEW(namespace_set_t,set);
345 set->namespaces = list_new();
348 char* namespace_set_tostring(namespace_set_t*set)
351 return strdup("NULL");
352 /* TODO: is the order of the namespaces important (does it
353 change the lookup order?). E.g. flex freely shuffles namespaces
355 If the order is not important, we can optimize constant pools by sorting
359 namespace_list_t*lns = set->namespaces;
361 char*s = namespace_tostring(lns->namespace);
366 char*desc = malloc(l+16);
368 lns = set->namespaces;
370 char*s = namespace_tostring(lns->namespace);
381 void namespace_set_destroy(namespace_set_t*set)
384 namespace_list_t*l = set->namespaces;
386 namespace_destroy(l->namespace);l->namespace=0;
389 list_free(set->namespaces);
394 type_t namespace_set_type = {
395 dup: (dup_func)namespace_set_clone,
396 hash: (hash_func)namespace_set_hash,
397 free: (free_func)namespace_set_destroy,
398 equals: (equals_func)namespace_set_equals
401 // ----------------------------- multiname ----------------------------------
403 unsigned int multiname_hash(multiname_t*m)
407 unsigned int hash = crc32_add_byte(0, m->type);
409 hash = crc32_add_string(hash, m->name);
412 hash = crc32_add_byte(hash, m->ns->access);
413 hash = crc32_add_string(hash, m->ns->name);
415 if(m->namespace_set) {
416 namespace_list_t*l = m->namespace_set->namespaces;
418 hash = crc32_add_byte(hash, l->namespace->access);
419 hash = crc32_add_string(hash, l->namespace->name);
426 int multiname_equals(multiname_t*m1, multiname_t*m2)
430 if(m1->type!=m2->type)
433 if((!m1->name) != (!m2->name))
435 if((!m1->ns) != (!m2->ns))
437 if((!m1->namespace_set) != (!m2->namespace_set))
440 if(m1->name && m2->name && strcmp(m1->name,m2->name))
442 if(m1->ns && m2->ns) {
443 if(!namespace_equals(m1->ns, m2->ns))
446 if(m1->namespace_set && m2->namespace_set) {
447 if(!namespace_set_equals(m1->namespace_set, m2->namespace_set))
453 multiname_t* multiname_new(namespace_t*ns, const char*name)
458 m->ns = namespace_new_packageinternal("");
460 m->ns = namespace_clone(ns);
462 m->name = strdup(name);
466 multiname_t* multiname_clone(multiname_t*other)
471 m->type = other->type;
473 m->ns = namespace_clone(other->ns);
474 if(other->namespace_set)
475 m->namespace_set = namespace_set_clone(other->namespace_set);
477 m->name = strdup(other->name);
482 char* access2str(int type)
484 if(type==0x08) return "namespace";
485 else if(type==0x16) return "public";
486 else if(type==0x17) return "packageinternal";
487 else if(type==0x18) return "protected";
488 else if(type==0x19) return "explicit";
489 else if(type==0x1A) return "staticprotected";
490 else if(type==0x05) return "private";
492 fprintf(stderr, "Undefined access type %02x\n", type);
498 char multiname_late_namespace(multiname_t*m)
502 return (m->type==RTQNAME || m->type==RTQNAMEA ||
503 m->type==RTQNAMEL || m->type==RTQNAMELA);
506 char multiname_late_name(multiname_t*m)
510 return m->type==RTQNAMEL || m->type==RTQNAMELA ||
511 m->type==MULTINAMEL || m->type==MULTINAMELA;
514 char* multiname_tostring(multiname_t*m)
518 return strdup("NULL");
520 return strdup("--<MULTINAME 0xff>--");
522 char*name = m->name?escape_string(m->name):strdup("*");
523 int namelen = strlen(name);
525 if(m->type==QNAME || m->type==QNAMEA) {
526 char*nsname = escape_string(m->ns->name);
527 mname = malloc(strlen(nsname)+namelen+32);
529 if(m->type == QNAMEA)
530 strcat(mname, ",attr");
532 strcat(mname,access2str(m->ns->access));
534 strcat(mname, nsname);
538 } else if(m->type==RTQNAME || m->type==RTQNAMEA) {
539 mname = malloc(namelen+32);
540 strcpy(mname, "<rt");
541 if(m->type == RTQNAMEA)
542 strcat(mname, ",attr");
545 } else if(m->type==RTQNAMEL) {
546 mname = strdup("<rt,l>");
547 } else if(m->type==RTQNAMELA) {
548 mname = strdup("<rt,l,attr>");
549 } else if(m->type==MULTINAME || m->type==MULTINAMEA) {
550 char*s = namespace_set_tostring(m->namespace_set);
551 mname = malloc(strlen(s)+namelen+16);
552 if(m->type == MULTINAME)
553 strcpy(mname,"<multi>");
555 strcpy(mname,"<multi,attr>");
560 } else if(m->type==MULTINAMEL || m->type==MULTINAMELA) {
561 char*s = namespace_set_tostring(m->namespace_set);
562 mname = malloc(strlen(s)+16);
563 if(m->type == MULTINAMEL)
564 strcpy(mname,"<l,multi>");
566 strcpy(mname,"<l,multi,attr>");
570 fprintf(stderr, "Invalid multiname type: %02x\n", m->type);
576 multiname_t* multiname_fromstring(const char*name2)
580 char*n = strdup(name2);
581 char*p = strstr(n, "::");
582 char*namespace=0,*name=0;
585 fprintf(stderr, "Error: single ':' in name\n");
593 if(strchr(namespace, ':')) {
594 fprintf(stderr, "Error: single ':' in namespace\n");
596 if(strchr(name, ':')) {
597 fprintf(stderr, "Error: single ':' in qualified name\n");
601 multiname_t*m = malloc(sizeof(multiname_t));
602 memset(m, 0, sizeof(multiname_t));
604 m->namespace_set = 0;
605 m->ns = namespace_fromstring(namespace);
606 m->name = name?strdup(name):0;
611 void multiname_destroy(multiname_t*m)
615 free((void*)m->name);m->name = 0;
618 namespace_destroy(m->ns);m->ns = 0;
620 if(m->namespace_set) {
621 namespace_set_destroy(m->namespace_set);m->namespace_set = 0;
628 type_t multiname_type = {
629 dup: (dup_func)multiname_clone,
630 hash: (hash_func)multiname_hash,
631 free: (free_func)multiname_destroy,
632 equals: (equals_func)multiname_equals
636 // ------------------------------- constants -------------------------------------
638 #define NS_TYPE(x) ((x) == 0x08 || (x) == 0x16 || (x) == 0x17 || (x) == 0x18 || \
639 (x) == 0x19 || (x) == 0x1a || (x) == 0x05)
641 #define UNIQUE_CONSTANT(x) ((x) == CONSTANT_TRUE || (x) == CONSTANT_FALSE || (x) == CONSTANT_NULL || (x) == CONSTANT_UNDEFINED)
643 constant_t* constant_new_int(int i)
647 c->type = CONSTANT_INT;
650 constant_t* constant_new_uint(unsigned int u)
654 c->type = CONSTANT_UINT;
657 constant_t* constant_new_float(double f)
661 c->type = CONSTANT_FLOAT;
664 constant_t* constant_new_string(char*s)
667 c->s = string_new4(s);
668 c->type = CONSTANT_STRING;
671 constant_t* constant_new_string2(const char*s, int len)
674 c->s = string_new3(s, len);
675 c->type = CONSTANT_STRING;
678 constant_t* constant_new_namespace(namespace_t*ns)
681 c->ns = namespace_clone(ns);
682 c->type = ns->access;
683 assert(NS_TYPE(c->type));
686 constant_t* constant_new_true()
689 c->type = CONSTANT_TRUE;
692 constant_t* constant_new_false()
695 c->type = CONSTANT_FALSE;
698 constant_t* constant_new_null()
701 c->type = CONSTANT_NULL;
704 constant_t* constant_new_undefined()
707 c->type = CONSTANT_UNDEFINED;
710 constant_t* constant_fromindex(pool_t*pool, int index, int type)
713 /* even for nonvalued constants (like TRUE/FALSE etc.), a nonzero
714 index is present to indicate that a type is coming */
719 if(NS_TYPE(c->type)) {
720 c->ns = namespace_clone(pool_lookup_namespace(pool, index));
721 } else if(c->type == CONSTANT_INT) {
722 c->i = pool_lookup_int(pool, index);
723 } else if(c->type == CONSTANT_UINT) {
724 c->u = pool_lookup_uint(pool, index);
725 } else if(c->type == CONSTANT_FLOAT) {
726 c->f = pool_lookup_float(pool, index);
727 } else if(c->type == CONSTANT_STRING) {
728 string_t s = pool_lookup_string2(pool, index);
729 c->s = string_dup3(&s);
730 } else if(UNIQUE_CONSTANT(c->type)) {
733 fprintf(stderr, "invalid constant type %02x\n", c->type);
737 char* constant_tostring(constant_t*c)
740 return strdup("NULL");
742 if(NS_TYPE(c->type)) {
743 return namespace_tostring(c->ns);
744 } else if(c->type == CONSTANT_INT) {
745 sprintf(buf, "%d", c->i);
747 } else if(c->type == CONSTANT_UINT) {
748 sprintf(buf, "%u", c->u);
750 } else if(c->type == CONSTANT_FLOAT) {
752 sprintf(buf, "%f", c->f);
754 } else if(c->type == CONSTANT_STRING) {
755 /* should we escape the string? \0 bytes won't be printed */
756 return strdup_n(c->s->str,c->s->len);
757 } else if(c->type == CONSTANT_TRUE) {
758 return strdup("true");
759 } else if(c->type == CONSTANT_FALSE) {
760 return strdup("false");
761 } else if(c->type == CONSTANT_NULL) {
762 return strdup("null");
763 } else if(c->type == CONSTANT_UNDEFINED) {
764 return strdup("undefined");
766 fprintf(stderr, "invalid constant type %02x\n", c->type);
770 char constant_has_index(constant_t*c)
774 return !UNIQUE_CONSTANT(c->type);
776 int constant_get_index(pool_t*pool, constant_t*c)
780 if(NS_TYPE(c->type)) {
782 /*if(c->type!=c->ns->access) {
783 printf("%02x<->%02x\n", c->type, c->ns->access);
785 assert(c->type == c->ns->access);
786 return pool_register_namespace(pool, c->ns);
787 } else if(c->type == CONSTANT_INT) {
788 return pool_register_int(pool, c->i);
789 } else if(c->type == CONSTANT_UINT) {
790 return pool_register_uint(pool, c->u);
791 } else if(c->type == CONSTANT_FLOAT) {
792 return pool_register_float(pool, c->f);
793 } else if(c->type == CONSTANT_STRING) {
794 return pool_register_string2(pool, c->s);
795 } else if(!constant_has_index(c)) {
798 fprintf(stderr, "invalid constant type %02x\n", c->type);
802 void constant_free(constant_t*c)
806 if(c->type == CONSTANT_STRING) {
808 } else if (NS_TYPE(c->type)) {
809 namespace_destroy(c->ns);c->ns=0;
813 // ------------------------------- pool -------------------------------------
815 int pool_register_uint(pool_t*p, unsigned int i)
817 int pos = array_append_if_new(p->x_uints, &i, 0);
821 int pool_register_int(pool_t*p, int i)
823 int pos = array_append_if_new(p->x_ints, &i, 0);
827 int pool_register_float(pool_t*p, double d)
829 int pos = array_append_if_new(p->x_floats, &d, 0);
833 int pool_register_string(pool_t*pool, const char*str)
836 string_t s = string_new2(str);
837 int pos = array_append_if_new(pool->x_strings, &s, 0);
841 int pool_register_string2(pool_t*pool, string_t*s)
843 if(!s || !s->str) return 0;
844 int pos = array_append_if_new(pool->x_strings, s, 0);
848 int pool_register_namespace(pool_t*pool, namespace_t*ns)
851 int pos = array_append_if_new(pool->x_namespaces, ns, 0);
855 int pool_register_namespace_set(pool_t*pool, namespace_set_t*set)
858 int pos = array_append_if_new(pool->x_namespace_sets, set, 0);
862 int pool_register_multiname(pool_t*pool, multiname_t*n)
865 int pos = array_append_if_new(pool->x_multinames, n, 0);
869 int pool_register_multiname2(pool_t*pool, char*name)
872 multiname_t*n = multiname_fromstring(name);
873 int pos = array_append_if_new(pool->x_multinames, n, 0);
874 multiname_destroy(n);
880 int pool_find_uint(pool_t*pool, unsigned int x)
882 int i = array_find(pool->x_uints, &x);
884 fprintf(stderr, "Couldn't find uint \"%d\" in constant pool\n", x);
889 int pool_find_int(pool_t*pool, int x)
891 int i = array_find(pool->x_ints, &x);
893 fprintf(stderr, "Couldn't find int \"%d\" in constant pool\n", x);
898 int pool_find_float(pool_t*pool, double x)
900 int i = array_find(pool->x_ints, &x);
902 fprintf(stderr, "Couldn't find int \"%d\" in constant pool\n", x);
907 int pool_find_namespace(pool_t*pool, namespace_t*ns)
911 int i = array_find(pool->x_namespaces, ns);
913 char*s = namespace_tostring(ns);
914 fprintf(stderr, "Couldn't find namespace \"%s\" %08x in constant pool\n", s, ns);
920 int pool_find_namespace_set(pool_t*pool, namespace_set_t*set)
924 int i = array_find(pool->x_namespace_sets, set);
926 char*s = namespace_set_tostring(set);
927 fprintf(stderr, "Couldn't find namespace_set \"%s\" in constant pool\n", s);
933 int pool_find_string(pool_t*pool, const char*str)
937 string_t s = string_new2(str);
938 int i = array_find(pool->x_strings, &s);
940 fprintf(stderr, "Couldn't find string \"%s\" in constant pool\n", s);
945 int pool_find_multiname(pool_t*pool, multiname_t*name)
949 int i = array_find(pool->x_multinames, name);
951 char*s = multiname_tostring(name);
952 fprintf(stderr, "Couldn't find multiname \"%s\" in constant pool\n", s);
959 int pool_lookup_int(pool_t*pool, int i)
962 return *(int*)array_getkey(pool->x_ints, i);
964 unsigned int pool_lookup_uint(pool_t*pool, int i)
967 return *(unsigned int*)array_getkey(pool->x_uints, i);
969 double pool_lookup_float(pool_t*pool, int i)
971 if(!i) return __builtin_nan("");
972 return *(double*)array_getkey(pool->x_floats, i);
974 const char*pool_lookup_string(pool_t*pool, int i)
976 string_t*s = array_getkey(pool->x_strings, i);
980 string_t pool_lookup_string2(pool_t*pool, int i)
982 string_t*s = array_getkey(pool->x_strings, i);
985 namespace_t*pool_lookup_namespace(pool_t*pool, int i)
987 return (namespace_t*)array_getkey(pool->x_namespaces, i);
989 namespace_set_t*pool_lookup_namespace_set(pool_t*pool, int i)
991 return (namespace_set_t*)array_getkey(pool->x_namespace_sets, i);
993 multiname_t*pool_lookup_multiname(pool_t*pool, int i)
995 return (multiname_t*)array_getkey(pool->x_multinames, i);
1002 p->x_ints = array_new2(&uint_type);
1003 p->x_uints = array_new2(&uint_type);
1004 p->x_floats = array_new2(&float_type);
1005 p->x_strings = array_new2(&stringstruct_type);
1006 p->x_namespaces = array_new2(&namespace_type);
1007 p->x_namespace_sets = array_new2(&namespace_set_type);
1008 p->x_multinames = array_new2(&multiname_type);
1010 /* add a zero-index entry in each list */
1012 array_append(p->x_ints, 0, 0);
1013 array_append(p->x_uints, 0, 0);
1014 array_append(p->x_floats, 0, 0);
1015 array_append(p->x_strings, 0, 0);
1016 array_append(p->x_namespaces, 0, 0);
1017 array_append(p->x_namespace_sets, 0, 0);
1018 array_append(p->x_multinames, 0, 0);
1025 void pool_read(pool_t*pool, TAG*tag)
1027 int num_ints = swf_GetU30(tag);
1028 DEBUG printf("%d ints\n", num_ints);
1030 for(t=1;t<num_ints;t++) {
1031 S32 v = swf_GetABCS32(tag);
1032 DEBUG printf("int %d) %d\n", t, v);
1033 array_append(pool->x_ints, &v, 0);
1036 int num_uints = swf_GetU30(tag);
1037 DEBUG printf("%d uints\n", num_uints);
1038 for(t=1;t<num_uints;t++) {
1039 U32 v = swf_GetABCU32(tag);
1040 DEBUG printf("uint %d) %d\n", t, v);
1041 array_append(pool->x_uints, &v, 0);
1044 int num_floats = swf_GetU30(tag);
1045 DEBUG printf("%d floats\n", num_floats);
1046 for(t=1;t<num_floats;t++) {
1047 double d = swf_GetD64(tag);
1048 DEBUG printf("float %d) %f\n", t, d);
1049 array_append(pool->x_floats, &d, 0);
1052 int num_strings = swf_GetU30(tag);
1053 DEBUG printf("%d strings\n", num_strings);
1054 for(t=1;t<num_strings;t++) {
1055 int len = swf_GetU30(tag);
1056 string_t s = string_new(&tag->data[tag->pos], len);
1057 swf_GetBlock(tag, 0, len);
1058 array_append(pool->x_strings, &s, 0);
1059 DEBUG printf("%d) \"%s\"\n", t, ((string_t*)array_getkey(pool->x_strings, t))->str);
1061 int num_namespaces = swf_GetU30(tag);
1062 DEBUG printf("%d namespaces\n", num_namespaces);
1063 for(t=1;t<num_namespaces;t++) {
1064 U8 type = swf_GetU8(tag);
1065 int namenr = swf_GetU30(tag);
1066 const char*name = 0;
1068 name = pool_lookup_string(pool, namenr);
1069 namespace_t*ns = namespace_new(type, name);
1070 array_append(pool->x_namespaces, ns, 0);
1071 DEBUG printf("%d) %02x \"%s\"\n", t, type, namespace_tostring(ns));
1072 namespace_destroy(ns);
1074 int num_sets = swf_GetU30(tag);
1075 DEBUG printf("%d namespace sets\n", num_sets);
1076 for(t=1;t<num_sets;t++) {
1077 int count = swf_GetU30(tag);
1080 NEW(namespace_set_t, nsset);
1081 for(s=0;s<count;s++) {
1082 int nsnr = swf_GetU30(tag);
1084 fprintf(stderr, "Zero entry in namespace set\n");
1085 namespace_t*ns = (namespace_t*)array_getkey(pool->x_namespaces, nsnr);
1086 list_append(nsset->namespaces, namespace_clone(ns));
1088 array_append(pool->x_namespace_sets, nsset, 0);
1089 DEBUG printf("set %d) %s\n", t, namespace_set_tostring(nsset));
1090 namespace_set_destroy(nsset);
1093 int num_multinames = swf_GetU30(tag);
1094 DEBUG printf("%d multinames\n", num_multinames);
1095 for(t=1;t<num_multinames;t++) {
1097 memset(&m, 0, sizeof(multiname_t));
1098 m.type = swf_GetU8(tag);
1099 if(m.type==0x07 || m.type==0x0d) {
1100 int namespace_index = swf_GetU30(tag);
1101 m.ns = (namespace_t*)array_getkey(pool->x_namespaces, namespace_index);
1102 int name_index = swf_GetU30(tag);
1103 if(name_index) // 0 = '*' (any)
1104 m.name = pool_lookup_string(pool, name_index);
1105 } else if(m.type==0x0f || m.type==0x10) {
1106 int name_index = swf_GetU30(tag);
1107 if(name_index) // 0 = '*' (any name)
1108 m.name = pool_lookup_string(pool, name_index);
1109 } else if(m.type==0x11 || m.type==0x12) {
1110 } else if(m.type==0x09 || m.type==0x0e) {
1111 int name_index = swf_GetU30(tag);
1112 int namespace_set_index = swf_GetU30(tag);
1114 m.name = pool_lookup_string(pool, name_index);
1115 m.namespace_set = (namespace_set_t*)array_getkey(pool->x_namespace_sets, namespace_set_index);
1116 } else if(m.type==0x1b || m.type==0x1c) {
1117 int namespace_set_index = swf_GetU30(tag);
1118 m.namespace_set = (namespace_set_t*)array_getkey(pool->x_namespace_sets, namespace_set_index);
1120 printf("can't parse type %d multinames yet\n", m.type);
1122 DEBUG printf("multiname %d) %s\n", t, multiname_tostring(&m));
1123 array_append(pool->x_multinames, &m, 0);
1127 void pool_dump(pool_t*pool, FILE*fo, char flags)
1130 fprintf(fo, "%d integers:\n", pool->x_ints->num);
1131 for(t=1;t<pool->x_ints->num;t++) {
1132 S32 val = *(int*)array_getkey(pool->x_ints, t);
1133 if(flags&1) fprintf(fo, "%d) %d\n", t, val);
1135 fprintf(fo, "%d unsigned integers:\n", pool->x_uints->num);
1136 for(t=1;t<pool->x_uints->num;t++) {
1137 U32 val = *(unsigned int*)array_getkey(pool->x_uints, t);
1138 if(flags&1) fprintf(fo, "%d) %d\n", t, val);
1140 fprintf(fo, "%d floats:\n", pool->x_floats->num);
1141 for(t=1;t<pool->x_floats->num;t++) {
1142 double d = pool_lookup_float(pool, t);
1143 if(flags&2) fprintf(fo, "%d) %f\n", t, d);
1145 fprintf(fo, "%d strings:\n", pool->x_strings->num);
1146 for(t=1;t<pool->x_strings->num;t++) {
1147 string_t str = pool_lookup_string2(pool, t);
1148 if(flags&1) fprintf(fo, "%d) ", t);
1149 if(flags&1) fwrite(str.str, str.len, 1, fo);
1150 if(flags&1) fprintf(fo, "\n", t);
1152 fprintf(fo, "%d namespaces:\n", pool->x_namespaces->num);
1153 for(t=1;t<pool->x_namespaces->num;t++) {
1154 namespace_t*ns= (namespace_t*)array_getkey(pool->x_namespaces, t);
1155 char*s = namespace_tostring(ns);
1156 if(flags&1) fprintf(fo, "%d) %s\n", t, s);
1159 fprintf(fo, "%d namespace sets:\n", pool->x_namespace_sets->num);
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 char*s = namespace_set_tostring(set);
1163 if(flags&1) fprintf(fo, "%d) %s\n", t, s);
1167 fprintf(fo, "%d multinames:\n", pool->x_multinames->num);
1168 for(t=1;t<pool->x_multinames->num;t++) {
1169 multiname_t*m = (multiname_t*)array_getkey(pool->x_multinames, t);
1170 char*s = multiname_tostring(m);
1171 if(flags&1) fprintf(fo, "%d) %s\n", t, s);
1176 void pool_write(pool_t*pool, TAG*tag)
1180 /* make sure that all namespaces used by multinames / namespace sets
1181 and all strings used by namespaces exist */
1183 for(t=1;t<pool->x_multinames->num;t++) {
1184 multiname_t*m = (multiname_t*)array_getkey(pool->x_multinames, t);
1186 pool_register_namespace(pool, m->ns);
1188 if(m->namespace_set) {
1189 pool_register_namespace_set(pool, m->namespace_set);
1192 pool_register_string(pool, m->name);
1195 for(t=1;t<pool->x_namespace_sets->num;t++) {
1196 namespace_set_t*set = (namespace_set_t*)array_getkey(pool->x_namespace_sets, t);
1197 namespace_list_t*i = set->namespaces;
1199 pool_register_namespace(pool, i->namespace);
1203 for(t=1;t<pool->x_namespaces->num;t++) {
1204 namespace_t*ns= (namespace_t*)array_getkey(pool->x_namespaces, t);
1205 /* The spec says (page 22): "a value of zero denotes an empty string".
1206 However when actually using zero strings as empty namespaces, the
1207 flash player breaks.*/
1208 //if(ns->name && ns->name[0])
1209 pool_register_string(pool, ns->name);
1212 //pool_register_int(pool, 15);
1213 //pool_register_int(pool, 1);
1214 //pool_register_int(pool, 0);
1217 swf_SetU30(tag, pool->x_ints->num>1?pool->x_ints->num:0);
1218 for(t=1;t<pool->x_ints->num;t++) {
1219 S32 val = *(int*)array_getkey(pool->x_ints, t);
1220 swf_SetABCS32(tag, val);
1222 swf_SetU30(tag, pool->x_uints->num>1?pool->x_uints->num:0);
1223 for(t=1;t<pool->x_uints->num;t++) {
1224 swf_SetABCU32(tag, *(unsigned int*)array_getkey(pool->x_uints, t));
1226 swf_SetU30(tag, pool->x_floats->num>1?pool->x_floats->num:0);
1227 for(t=1;t<pool->x_floats->num;t++) {
1228 double d = pool_lookup_float(pool, t);
1231 swf_SetU30(tag, pool->x_strings->num>1?pool->x_strings->num:0);
1232 for(t=1;t<pool->x_strings->num;t++) {
1233 string_t str = pool_lookup_string2(pool, t);
1234 swf_SetU30String(tag, str.str, str.len);
1236 swf_SetU30(tag, pool->x_namespaces->num>1?pool->x_namespaces->num:0);
1237 for(t=1;t<pool->x_namespaces->num;t++) {
1238 namespace_t*ns= (namespace_t*)array_getkey(pool->x_namespaces, t);
1239 swf_SetU8(tag, ns->access);
1240 const char*name = ns->name;
1243 //if(name && name[0])
1244 i = pool_find_string(pool, name);
1248 swf_SetU30(tag, pool->x_namespace_sets->num>1?pool->x_namespace_sets->num:0);
1249 for(t=1;t<pool->x_namespace_sets->num;t++) {
1250 namespace_set_t*set = (namespace_set_t*)array_getkey(pool->x_namespace_sets, t);
1251 namespace_list_t*i = set->namespaces;
1252 int len = list_length(i);
1253 swf_SetU30(tag, len);
1255 int index = pool_find_namespace(pool, i->namespace);
1256 swf_SetU30(tag, index);
1261 swf_SetU30(tag, pool->x_multinames->num>1?pool->x_multinames->num:0);
1262 for(t=1;t<pool->x_multinames->num;t++) {
1263 multiname_t*m = (multiname_t*)array_getkey(pool->x_multinames, t);
1264 swf_SetU8(tag, m->type);
1267 assert(m->type==0x07 || m->type==0x0d);
1268 int i = pool_find_namespace(pool, m->ns);
1269 if(i<0) fprintf(stderr, "internal error: unregistered namespace %02x %s %s\n", m->ns->access, access2str(m->ns->access), m->ns->name);
1272 assert(m->type!=0x07 && m->type!=0x0d);
1275 assert(m->type==0x09 || m->type==0x0e || m->type==0x07 || m->type==0x0d || m->type==0x0f || m->type==0x10);
1276 int i = pool_find_string(pool, m->name);
1277 if(i<0) fprintf(stderr, "internal error: unregistered name\n");
1280 assert(m->type!=0x09 && m->type!=0x0e && m->type!=0x07 && m->type!=0x0d && m->type!=0x0f && m->type!=0x10);
1282 if(m->namespace_set) {
1283 assert(m->type==0x09 || m->type==0x0e || m->type==0x1c || m->type==0x1b);
1284 int i = pool_find_namespace_set(pool, m->namespace_set);
1285 if(i<0) fprintf(stderr, "internal error: unregistered namespace set\n");
1288 assert(m->type!=0x09 && m->type!=0x0e && m->type!=0x1c && m->type!=0x1b);
1294 void pool_destroy(pool_t*pool)
1297 array_free(pool->x_ints);
1298 array_free(pool->x_uints);
1299 array_free(pool->x_floats);
1300 array_free(pool->x_strings);
1301 array_free(pool->x_namespaces);
1302 array_free(pool->x_namespace_sets);
1303 array_free(pool->x_multinames);