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 // --------------------------- optimizing -----------------------------------
815 static int array_append_or_increase(array_t*array, void*key)
817 int pos = array_find(array, key);
819 array->d[pos].data++;
822 return array_append(array, key, 0);
825 static int compare_arrayentry(const void*_c1, const void*_c2)
827 const array_entry_t*c1 = _c1;
828 const array_entry_t*c2 = _c2;
829 return c1->data - c2->data;
831 static void reshuffle_array(array_t*array)
833 qsort(array->d, array->num, sizeof(array->d[0]), compare_arrayentry);
834 dict_destroy(array->entry2pos);
835 array->entry2pos = dict_new();
837 for(t=0;t<array->num;t++) {
838 dict_put(array->entry2pos, array->d[t].name, (void*)(ptroff_t)(t+1));
842 // ------------------------------- pool -------------------------------------
844 int pool_register_uint(pool_t*p, unsigned int i)
846 int pos = array_append_or_increase(p->x_uints, &i);
850 int pool_register_int(pool_t*p, int i)
852 int pos = array_append_or_increase(p->x_ints, &i);
856 int pool_register_float(pool_t*p, double d)
858 int pos = array_append_or_increase(p->x_floats, &d);
862 int pool_register_string(pool_t*pool, const char*str)
865 string_t s = string_new2(str);
866 int pos = array_append_or_increase(pool->x_strings, &s);
870 int pool_register_string2(pool_t*pool, string_t*s)
872 if(!s || !s->str) return 0;
873 int pos = array_append_or_increase(pool->x_strings, s);
877 int pool_register_namespace(pool_t*pool, namespace_t*ns)
880 int pos = array_append_or_increase(pool->x_namespaces, ns);
884 int pool_register_namespace_set(pool_t*pool, namespace_set_t*set)
887 int pos = array_append_or_increase(pool->x_namespace_sets, set);
891 int pool_register_multiname(pool_t*pool, multiname_t*n)
894 int pos = array_append_or_increase(pool->x_multinames, n);
898 int pool_register_multiname2(pool_t*pool, char*name)
901 multiname_t*n = multiname_fromstring(name);
902 int pos = array_append_or_increase(pool->x_multinames, n);
903 multiname_destroy(n);
909 int pool_find_uint(pool_t*pool, unsigned int x)
911 int i = array_find(pool->x_uints, &x);
913 fprintf(stderr, "Couldn't find uint \"%d\" in constant pool\n", x);
918 int pool_find_int(pool_t*pool, int x)
920 int i = array_find(pool->x_ints, &x);
922 fprintf(stderr, "Couldn't find int \"%d\" in constant pool\n", x);
927 int pool_find_float(pool_t*pool, double x)
929 int i = array_find(pool->x_ints, &x);
931 fprintf(stderr, "Couldn't find int \"%d\" in constant pool\n", x);
936 int pool_find_namespace(pool_t*pool, namespace_t*ns)
940 int i = array_find(pool->x_namespaces, ns);
942 char*s = namespace_tostring(ns);
943 fprintf(stderr, "Couldn't find namespace \"%s\" %08x in constant pool\n", s, ns);
949 int pool_find_namespace_set(pool_t*pool, namespace_set_t*set)
953 int i = array_find(pool->x_namespace_sets, set);
955 char*s = namespace_set_tostring(set);
956 fprintf(stderr, "Couldn't find namespace_set \"%s\" in constant pool\n", s);
962 int pool_find_string(pool_t*pool, const char*str)
966 string_t s = string_new2(str);
967 int i = array_find(pool->x_strings, &s);
969 fprintf(stderr, "Couldn't find string \"%s\" in constant pool\n", s);
974 int pool_find_multiname(pool_t*pool, multiname_t*name)
978 int i = array_find(pool->x_multinames, name);
980 char*s = multiname_tostring(name);
981 fprintf(stderr, "Couldn't find multiname \"%s\" in constant pool\n", s);
988 int pool_lookup_int(pool_t*pool, int i)
991 return *(int*)array_getkey(pool->x_ints, i);
993 unsigned int pool_lookup_uint(pool_t*pool, int i)
996 return *(unsigned int*)array_getkey(pool->x_uints, i);
998 double pool_lookup_float(pool_t*pool, int i)
1000 if(!i) return __builtin_nan("");
1001 return *(double*)array_getkey(pool->x_floats, i);
1003 const char*pool_lookup_string(pool_t*pool, int i)
1005 string_t*s = array_getkey(pool->x_strings, i);
1009 string_t pool_lookup_string2(pool_t*pool, int i)
1011 string_t*s = array_getkey(pool->x_strings, i);
1014 namespace_t*pool_lookup_namespace(pool_t*pool, int i)
1016 return (namespace_t*)array_getkey(pool->x_namespaces, i);
1018 namespace_set_t*pool_lookup_namespace_set(pool_t*pool, int i)
1020 return (namespace_set_t*)array_getkey(pool->x_namespace_sets, i);
1022 multiname_t*pool_lookup_multiname(pool_t*pool, int i)
1024 return (multiname_t*)array_getkey(pool->x_multinames, i);
1031 p->x_ints = array_new2(&uint_type);
1032 p->x_uints = array_new2(&uint_type);
1033 p->x_floats = array_new2(&float_type);
1034 p->x_strings = array_new2(&stringstruct_type);
1035 p->x_namespaces = array_new2(&namespace_type);
1036 p->x_namespace_sets = array_new2(&namespace_set_type);
1037 p->x_multinames = array_new2(&multiname_type);
1039 /* add a zero-index entry in each list */
1041 array_append(p->x_ints, 0, 0);
1042 array_append(p->x_uints, 0, 0);
1043 array_append(p->x_floats, 0, 0);
1044 array_append(p->x_strings, 0, 0);
1045 array_append(p->x_namespaces, 0, 0);
1046 array_append(p->x_namespace_sets, 0, 0);
1047 array_append(p->x_multinames, 0, 0);
1051 void pool_optimize(pool_t*p)
1053 reshuffle_array(p->x_ints);
1054 reshuffle_array(p->x_uints);
1055 reshuffle_array(p->x_floats);
1056 reshuffle_array(p->x_strings);
1057 reshuffle_array(p->x_namespaces);
1058 reshuffle_array(p->x_namespace_sets);
1059 reshuffle_array(p->x_multinames);
1065 void pool_read(pool_t*pool, TAG*tag)
1067 int num_ints = swf_GetU30(tag);
1068 DEBUG printf("%d ints\n", num_ints);
1070 for(t=1;t<num_ints;t++) {
1071 S32 v = swf_GetABCS32(tag);
1072 DEBUG printf("int %d) %d\n", t, v);
1073 array_append(pool->x_ints, &v, 0);
1076 int num_uints = swf_GetU30(tag);
1077 DEBUG printf("%d uints\n", num_uints);
1078 for(t=1;t<num_uints;t++) {
1079 U32 v = swf_GetABCU32(tag);
1080 DEBUG printf("uint %d) %d\n", t, v);
1081 array_append(pool->x_uints, &v, 0);
1084 int num_floats = swf_GetU30(tag);
1085 DEBUG printf("%d floats\n", num_floats);
1086 for(t=1;t<num_floats;t++) {
1087 double d = swf_GetD64(tag);
1088 DEBUG printf("float %d) %f\n", t, d);
1089 array_append(pool->x_floats, &d, 0);
1092 int num_strings = swf_GetU30(tag);
1093 DEBUG printf("%d strings\n", num_strings);
1094 for(t=1;t<num_strings;t++) {
1095 int len = swf_GetU30(tag);
1096 string_t s = string_new(&tag->data[tag->pos], len);
1097 swf_GetBlock(tag, 0, len);
1098 array_append(pool->x_strings, &s, 0);
1099 DEBUG printf("%d) \"%s\"\n", t, ((string_t*)array_getkey(pool->x_strings, t))->str);
1101 int num_namespaces = swf_GetU30(tag);
1102 DEBUG printf("%d namespaces\n", num_namespaces);
1103 for(t=1;t<num_namespaces;t++) {
1104 U8 type = swf_GetU8(tag);
1105 int namenr = swf_GetU30(tag);
1106 const char*name = 0;
1108 name = pool_lookup_string(pool, namenr);
1109 namespace_t*ns = namespace_new(type, name);
1110 array_append(pool->x_namespaces, ns, 0);
1111 DEBUG printf("%d) %02x \"%s\"\n", t, type, namespace_tostring(ns));
1112 namespace_destroy(ns);
1114 int num_sets = swf_GetU30(tag);
1115 DEBUG printf("%d namespace sets\n", num_sets);
1116 for(t=1;t<num_sets;t++) {
1117 int count = swf_GetU30(tag);
1120 NEW(namespace_set_t, nsset);
1121 for(s=0;s<count;s++) {
1122 int nsnr = swf_GetU30(tag);
1124 fprintf(stderr, "Zero entry in namespace set\n");
1125 namespace_t*ns = (namespace_t*)array_getkey(pool->x_namespaces, nsnr);
1126 list_append(nsset->namespaces, namespace_clone(ns));
1128 array_append(pool->x_namespace_sets, nsset, 0);
1129 DEBUG printf("set %d) %s\n", t, namespace_set_tostring(nsset));
1130 namespace_set_destroy(nsset);
1133 int num_multinames = swf_GetU30(tag);
1134 DEBUG printf("%d multinames\n", num_multinames);
1135 for(t=1;t<num_multinames;t++) {
1137 memset(&m, 0, sizeof(multiname_t));
1138 m.type = swf_GetU8(tag);
1139 if(m.type==0x07 || m.type==0x0d) {
1140 int namespace_index = swf_GetU30(tag);
1141 m.ns = (namespace_t*)array_getkey(pool->x_namespaces, namespace_index);
1142 int name_index = swf_GetU30(tag);
1143 if(name_index) // 0 = '*' (any)
1144 m.name = pool_lookup_string(pool, name_index);
1145 } else if(m.type==0x0f || m.type==0x10) {
1146 int name_index = swf_GetU30(tag);
1147 if(name_index) // 0 = '*' (any name)
1148 m.name = pool_lookup_string(pool, name_index);
1149 } else if(m.type==0x11 || m.type==0x12) {
1150 } else if(m.type==0x09 || m.type==0x0e) {
1151 int name_index = swf_GetU30(tag);
1152 int namespace_set_index = swf_GetU30(tag);
1154 m.name = pool_lookup_string(pool, name_index);
1155 m.namespace_set = (namespace_set_t*)array_getkey(pool->x_namespace_sets, namespace_set_index);
1156 } else if(m.type==0x1b || m.type==0x1c) {
1157 int namespace_set_index = swf_GetU30(tag);
1158 m.namespace_set = (namespace_set_t*)array_getkey(pool->x_namespace_sets, namespace_set_index);
1160 printf("can't parse type %d multinames yet\n", m.type);
1162 DEBUG printf("multiname %d) %s\n", t, multiname_tostring(&m));
1163 array_append(pool->x_multinames, &m, 0);
1167 void pool_dump(pool_t*pool, FILE*fo, char flags)
1170 fprintf(fo, "%d integers:\n", pool->x_ints->num);
1171 for(t=1;t<pool->x_ints->num;t++) {
1172 S32 val = *(int*)array_getkey(pool->x_ints, t);
1173 if(flags&1) fprintf(fo, "%d) %d\n", t, val);
1175 fprintf(fo, "%d unsigned integers:\n", pool->x_uints->num);
1176 for(t=1;t<pool->x_uints->num;t++) {
1177 U32 val = *(unsigned int*)array_getkey(pool->x_uints, t);
1178 if(flags&1) fprintf(fo, "%d) %d\n", t, val);
1180 fprintf(fo, "%d floats:\n", pool->x_floats->num);
1181 for(t=1;t<pool->x_floats->num;t++) {
1182 double d = pool_lookup_float(pool, t);
1183 if(flags&2) fprintf(fo, "%d) %f\n", t, d);
1185 fprintf(fo, "%d strings:\n", pool->x_strings->num);
1186 for(t=1;t<pool->x_strings->num;t++) {
1187 string_t str = pool_lookup_string2(pool, t);
1188 if(flags&1) fprintf(fo, "%d) ", t);
1189 if(flags&1) fwrite(str.str, str.len, 1, fo);
1190 if(flags&1) fprintf(fo, "\n", t);
1192 fprintf(fo, "%d namespaces:\n", pool->x_namespaces->num);
1193 for(t=1;t<pool->x_namespaces->num;t++) {
1194 namespace_t*ns= (namespace_t*)array_getkey(pool->x_namespaces, t);
1195 char*s = namespace_tostring(ns);
1196 if(flags&1) fprintf(fo, "%d) %s\n", t, s);
1199 fprintf(fo, "%d namespace sets:\n", pool->x_namespace_sets->num);
1200 for(t=1;t<pool->x_namespace_sets->num;t++) {
1201 namespace_set_t*set = (namespace_set_t*)array_getkey(pool->x_namespace_sets, t);
1202 char*s = namespace_set_tostring(set);
1203 if(flags&1) fprintf(fo, "%d) %s\n", t, s);
1207 fprintf(fo, "%d multinames:\n", pool->x_multinames->num);
1208 for(t=1;t<pool->x_multinames->num;t++) {
1209 multiname_t*m = (multiname_t*)array_getkey(pool->x_multinames, t);
1210 char*s = multiname_tostring(m);
1211 if(flags&1) fprintf(fo, "%d) %s\n", t, s);
1216 void pool_write(pool_t*pool, TAG*tag)
1220 /* make sure that all namespaces used by multinames / namespace sets
1221 and all strings used by namespaces exist */
1223 for(t=1;t<pool->x_multinames->num;t++) {
1224 multiname_t*m = (multiname_t*)array_getkey(pool->x_multinames, t);
1226 pool_register_namespace(pool, m->ns);
1228 if(m->namespace_set) {
1229 pool_register_namespace_set(pool, m->namespace_set);
1232 pool_register_string(pool, m->name);
1235 for(t=1;t<pool->x_namespace_sets->num;t++) {
1236 namespace_set_t*set = (namespace_set_t*)array_getkey(pool->x_namespace_sets, t);
1237 namespace_list_t*i = set->namespaces;
1239 pool_register_namespace(pool, i->namespace);
1243 for(t=1;t<pool->x_namespaces->num;t++) {
1244 namespace_t*ns= (namespace_t*)array_getkey(pool->x_namespaces, t);
1245 /* The spec says (page 22): "a value of zero denotes an empty string".
1246 However when actually using zero strings as empty namespaces, the
1247 flash player breaks.*/
1248 //if(ns->name && ns->name[0])
1249 pool_register_string(pool, ns->name);
1252 //pool_register_int(pool, 15);
1253 //pool_register_int(pool, 1);
1254 //pool_register_int(pool, 0);
1257 swf_SetU30(tag, pool->x_ints->num>1?pool->x_ints->num:0);
1258 for(t=1;t<pool->x_ints->num;t++) {
1259 S32 val = *(int*)array_getkey(pool->x_ints, t);
1260 swf_SetABCS32(tag, val);
1262 swf_SetU30(tag, pool->x_uints->num>1?pool->x_uints->num:0);
1263 for(t=1;t<pool->x_uints->num;t++) {
1264 swf_SetABCU32(tag, *(unsigned int*)array_getkey(pool->x_uints, t));
1266 swf_SetU30(tag, pool->x_floats->num>1?pool->x_floats->num:0);
1267 for(t=1;t<pool->x_floats->num;t++) {
1268 double d = pool_lookup_float(pool, t);
1271 swf_SetU30(tag, pool->x_strings->num>1?pool->x_strings->num:0);
1272 for(t=1;t<pool->x_strings->num;t++) {
1273 string_t str = pool_lookup_string2(pool, t);
1274 swf_SetU30String(tag, str.str, str.len);
1276 swf_SetU30(tag, pool->x_namespaces->num>1?pool->x_namespaces->num:0);
1277 for(t=1;t<pool->x_namespaces->num;t++) {
1278 namespace_t*ns= (namespace_t*)array_getkey(pool->x_namespaces, t);
1279 swf_SetU8(tag, ns->access);
1280 const char*name = ns->name;
1283 //if(name && name[0])
1284 i = pool_find_string(pool, name);
1288 swf_SetU30(tag, pool->x_namespace_sets->num>1?pool->x_namespace_sets->num:0);
1289 for(t=1;t<pool->x_namespace_sets->num;t++) {
1290 namespace_set_t*set = (namespace_set_t*)array_getkey(pool->x_namespace_sets, t);
1291 namespace_list_t*i = set->namespaces;
1292 int len = list_length(i);
1293 swf_SetU30(tag, len);
1295 int index = pool_find_namespace(pool, i->namespace);
1296 swf_SetU30(tag, index);
1301 swf_SetU30(tag, pool->x_multinames->num>1?pool->x_multinames->num:0);
1302 for(t=1;t<pool->x_multinames->num;t++) {
1303 multiname_t*m = (multiname_t*)array_getkey(pool->x_multinames, t);
1304 swf_SetU8(tag, m->type);
1307 assert(m->type==0x07 || m->type==0x0d);
1308 int i = pool_find_namespace(pool, m->ns);
1309 if(i<0) fprintf(stderr, "internal error: unregistered namespace %02x %s %s\n", m->ns->access, access2str(m->ns->access), m->ns->name);
1312 assert(m->type!=0x07 && m->type!=0x0d);
1315 assert(m->type==0x09 || m->type==0x0e || m->type==0x07 || m->type==0x0d || m->type==0x0f || m->type==0x10);
1316 int i = pool_find_string(pool, m->name);
1317 if(i<0) fprintf(stderr, "internal error: unregistered name\n");
1320 assert(m->type!=0x09 && m->type!=0x0e && m->type!=0x07 && m->type!=0x0d && m->type!=0x0f && m->type!=0x10);
1322 if(m->namespace_set) {
1323 assert(m->type==0x09 || m->type==0x0e || m->type==0x1c || m->type==0x1b);
1324 int i = pool_find_namespace_set(pool, m->namespace_set);
1325 if(i<0) fprintf(stderr, "internal error: unregistered namespace set\n");
1328 assert(m->type!=0x09 && m->type!=0x0e && m->type!=0x1c && m->type!=0x1b);
1334 void pool_destroy(pool_t*pool)
1337 array_free(pool->x_ints);
1338 array_free(pool->x_uints);
1339 array_free(pool->x_floats);
1340 array_free(pool->x_strings);
1341 array_free(pool->x_namespaces);
1342 array_free(pool->x_namespace_sets);
1343 array_free(pool->x_multinames);