fixed some compiler warnings
[swftools.git] / lib / as3 / pool.c
1 /* pool.c
2
3    Routines for handling Flash2 AVM2 ABC contantpool entries.
4
5    Extension module for the rfxswf library.
6    Part of the swftools package.
7
8    Copyright (c) 2008 Matthias Kramm <kramm@quiss.org>
9  
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.
14
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.
19
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 */
23
24 #include <assert.h>
25 #include "pool.h"
26
27
28 // ----------------------------- float ----------------------------------
29
30 void* float_clone(const void*_v) {
31     if(_v==0) 
32         return 0;
33     const double*v1=_v;
34     double*v2 = malloc(sizeof(double));
35     *v2 = *v1;
36     return v2;
37 }
38 unsigned int float_hash(const void*_v) {
39     if(!_v)
40         return 0;
41     const unsigned char*b=_v;
42     unsigned int h=0;
43     int t;
44     for(t=0;t<8;t++)
45         h = crc32_add_byte(h, b[t]);
46     return h;
47 }
48 void float_destroy(void*_v) {
49     double*v = (double*)_v;
50     if(v)
51         free(v);
52 }
53 char float_equals(const void*_v1, const void*_v2) {
54     const double*v1=_v1;
55     const double*v2=_v2;
56     if(!v1 || !v2) 
57         return v1==v2;
58     
59     if(*v1==*v2) return 1;
60     if(*v1!=*v1 && *v2!=*v2) return 1; //both values are NaN
61     return 0;
62 }
63
64 type_t float_type = {
65     dup: float_clone,
66     hash: float_hash,
67     free: float_destroy,
68     equals: float_equals
69 };
70
71 // ----------------------------- uint ----------------------------------
72
73 unsigned int undefined_uint = 0;
74
75 void*uint_clone(const void*_v) {
76     if(!_v)
77         return 0;
78     const unsigned int*v1=_v;
79     unsigned int*v2 = malloc(sizeof(unsigned int));
80     *v2 = *v1;
81     return v2;
82 }
83 unsigned int uint_hash(const void*_v) {
84     if(!_v)
85         return 0;
86     const unsigned int*v=_v;
87     return *v;
88 }
89 void uint_destroy(void*_v) {
90     unsigned int*v = (unsigned int*)_v;
91     if(v)
92         free(v);
93 }
94 char uint_equals(const void*_v1, const void*_v2) {
95     const unsigned int*v1=_v1;
96     const unsigned int*v2=_v2;
97     if(!v1 || !v2)
98         return v1==v2;
99     return *v1==*v2;
100 }
101
102 type_t uint_type = {
103     dup: (dup_func)uint_clone,
104     hash: (hash_func)uint_hash,
105     free: (free_func)uint_destroy,
106     equals: (equals_func)uint_equals
107 };
108
109 // ----------------------------- namespace ----------------------------------
110
111 unsigned int namespace_hash(namespace_t*n)
112 {
113     if(!n)
114         return 0;
115     unsigned int hash = 0;
116     hash = crc32_add_byte(hash, n->access);
117     hash = crc32_add_string(hash, n->name);
118     return hash;
119 }
120
121 unsigned char namespace_equals(const namespace_t*n1, const namespace_t*n2)
122 {
123     if(!n1 || !n2)
124         return n1==n2;
125     if(n1->access != n2->access)
126         return 0;
127     if(!(n1->name) != !(n2->name))
128         return 0;
129     if(n1->name && n2->name && strcmp(n1->name, n2->name))
130         return 0;
131     return 1;
132 }
133
134 char*escape_string(const char*str)
135 {
136     if(!str)
137         return strdup("NULL");
138     int len=0;
139     unsigned const char*s=(unsigned const char*)str;
140     while(*s) {
141         if(*s<10) {
142             len+=2; // \d
143         } else if(*s<32) {
144             len+=3; // \dd
145         } else if(*s<127) {
146             len++;
147         } else {
148             len+=4; // \xhh
149         }
150         s++;
151     }
152     char*newstr = malloc(len+1);
153     char*dest = newstr;
154     s=(unsigned const char*)str;
155     while(*s) {
156         if(*s<9) {
157             dest+=sprintf(dest, "\\%d", *s);
158         } else if(*s<32) {
159             if(*s==13)
160                 dest+=sprintf(dest, "\\r");
161             else if(*s==10) 
162                 dest+=sprintf(dest, "\\n");
163             else if(*s==9) 
164                 dest+=sprintf(dest, "\\t");
165             else 
166                 dest+=sprintf(dest, "\\%2o", *s);
167         } else if(*s<127) {
168             *dest++=*s;
169         } else {
170             dest+=sprintf(dest, "\\x%02x", *s);
171         }
172         s++;
173     }
174     *dest = 0;
175     return newstr;
176 }
177
178 char* namespace_tostring(namespace_t*ns)
179 {
180     if(!ns)
181         return strdup("NULL");
182     char*access = 0;
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);
187     if(!s)
188         sprintf(string, "[%s]NULL", access);
189     else if(!*s)
190         sprintf(string, "[%s]\"\"", access);
191     else 
192         sprintf(string, "[%s]%s", access, s);
193     free(s);
194     return string;
195 }
196
197 namespace_t* namespace_clone(namespace_t*other)
198 {
199     if(!other)
200         return 0;
201     NEW(namespace_t,n);
202     n->access = other->access;
203     n->name = other->name?strdup(other->name):0;
204     return n;
205 }
206
207 namespace_t* namespace_fromstring(const char*name)
208 {
209     namespace_t*ns = malloc(sizeof(namespace_t));
210     memset(ns, 0, sizeof(namespace_t));
211     if(name[0] == '[') {
212         U8 access = 0;
213         char*n = strdup(name);
214         char*bracket = strchr(n, ']');
215         if(bracket) {
216             *bracket = 0;
217             char*a = n+1;
218             name += (bracket-n)+1;
219             if(!strcmp(a, "")) access=0x16;
220             else if(!strcmp(a, "undefined")) access=0x08; // public??
221             else if(!strcmp(a, "package")) access=0x16;
222             else if(!strcmp(a, "public")) access=0x16;
223             else if(!strcmp(a, "packageinternal")) access=0x17;
224             else if(!strcmp(a, "protected")) access=0x18;
225             else if(!strcmp(a, "explicit")) access=0x19;
226             else if(!strcmp(a, "staticprotected")) access=0x1a;
227             else if(!strcmp(a, "private")) access=0x05;
228             else {
229                 fprintf(stderr, "Undefined access level: [%s]\n", a);
230                 free(n);
231                 return 0;
232             }
233         }
234         ns->access = access;
235         ns->name = strdup(name);
236         free(n);
237         return ns;
238     } else {
239         ns->access = 0x16;
240         ns->name = strdup(name);
241         return ns;
242     }
243 }
244
245 namespace_t* namespace_new(U8 access, const char*name)
246 {
247     namespace_t*ns = malloc(sizeof(namespace_t));
248     ns->access = access;
249     /* not sure what namespaces with empty strings are good for, but they *do* exist */
250     ns->name = name?strdup(name):0;
251     return ns;
252 }
253 namespace_t* namespace_new_namespace(const char*name) {
254     return namespace_new(0x08, name); // public?
255 }
256 namespace_t* namespace_new_package(const char*name) {
257     return namespace_new(0x16 , name);
258 }
259 namespace_t* namespace_new_packageinternal(const char*name) {
260     return namespace_new(0x17, name);
261 }
262 namespace_t* namespace_new_protected(const char*name) {
263     return namespace_new(0x18, name);
264 }
265 namespace_t* namespace_new_explicit(const char*name) {
266     return namespace_new(0x19, name);
267 }
268 namespace_t* namespace_new_staticprotected(const char*name) {
269     return namespace_new(0x1a, name);
270 }
271 namespace_t* namespace_new_private(const char*name) {
272     return namespace_new(0x05, name);
273 }
274
275 void namespace_destroy(namespace_t*n)
276 {
277     if(n) {
278         free((char*)n->name);n->name=0;
279         n->access=0x00;
280         free(n);
281     }
282 }
283
284 type_t namespace_type = {
285     dup: (dup_func)namespace_clone,
286     hash: (hash_func)namespace_hash,
287     free: (free_func)namespace_destroy,
288     equals: (equals_func)namespace_equals
289 };
290
291 // ---------------------------namespace sets --------------------------------
292
293 unsigned int namespace_set_hash(namespace_set_t*set)
294 {
295     if(!set)
296         return 0;
297     namespace_list_t*l = set->namespaces;
298     unsigned int hash = 0;
299     while(l) {
300         hash = crc32_add_byte(hash, l->namespace->access);
301         hash = crc32_add_string(hash, l->namespace->name);
302         l = l->next;
303     }
304     return hash;
305 }
306
307 int namespace_set_equals(namespace_set_t*m1, namespace_set_t*m2)
308 {
309     if(!m1 || !m2)
310         return m1==m2;
311     namespace_list_t*l1 = m1->namespaces;
312     namespace_list_t*l2 = m2->namespaces;
313     while(l1 && l2) {
314         if(l1->namespace->access != l2->namespace->access)
315             return 0;
316         if(!(l1->namespace->name) != !(l2->namespace->name))
317             return 0;
318         if(l1->namespace->name && l2->namespace->name && strcmp(l1->namespace->name, l2->namespace->name))
319             return 0;
320         l1 = l1->next;
321         l2 = l2->next;
322     }
323     if(l1||l2)
324         return 0;
325     return 1;
326 }
327
328 namespace_set_t* namespace_set_clone(namespace_set_t*other)
329 {
330     if(!other)
331         return 0;
332     NEW(namespace_set_t,set);
333     set->namespaces = list_new();
334     namespace_list_t*l = other->namespaces;
335     while(l) {
336         list_append(set->namespaces, namespace_clone(l->namespace));
337         l = l->next;
338     }
339     return set;
340 }
341 namespace_set_t* namespace_set_new()
342 {
343     NEW(namespace_set_t,set);
344     set->namespaces = list_new();
345     return set;
346 }
347 char* namespace_set_tostring(namespace_set_t*set)
348 {
349     if(!set)
350         return strdup("NULL");
351     /* TODO: is the order of the namespaces important (does it
352        change the lookup order?). E.g. flex freely shuffles namespaces
353        around.
354        If the order is not important, we can optimize constant pools by sorting
355        the namespaces.
356     */
357     int l = 0;
358     namespace_list_t*lns = set->namespaces;
359     while(lns) {
360         char*s = namespace_tostring(lns->namespace);
361         l += strlen(s)+1;
362         free(s);
363         lns = lns->next;
364     }
365     char*desc = malloc(l+16);
366     strcpy(desc, "{");
367     lns = set->namespaces;
368     while(lns) {
369         char*s = namespace_tostring(lns->namespace);
370         strcat(desc, s);
371         free(s);
372         lns = lns->next;
373         if(lns)
374             strcat(desc, ",");
375     }
376     strcat(desc, "}");
377     return desc;
378 }
379
380 void namespace_set_destroy(namespace_set_t*set)
381 {
382     if(set) {
383         namespace_list_t*l = set->namespaces;
384         while(l) {
385             namespace_destroy(l->namespace);l->namespace=0;
386             l = l->next;
387         }
388         list_free(set->namespaces);
389         free(set);
390     }
391 }
392
393 type_t namespace_set_type = {
394     dup: (dup_func)namespace_set_clone,
395     hash: (hash_func)namespace_set_hash,
396     free: (free_func)namespace_set_destroy,
397     equals: (equals_func)namespace_set_equals
398 };
399
400 // ----------------------------- multiname ----------------------------------
401
402 unsigned int multiname_hash(multiname_t*m)
403 {
404     if(!m)
405         return 0;
406     unsigned int hash = crc32_add_byte(0, m->type);
407     if(m->name) {
408         hash = crc32_add_string(hash, m->name);
409     }
410     if(m->ns) {
411         hash = crc32_add_byte(hash, m->ns->access);
412         hash = crc32_add_string(hash, m->ns->name);
413     }
414     if(m->namespace_set) {
415         namespace_list_t*l = m->namespace_set->namespaces;
416         while(l) {
417             hash = crc32_add_byte(hash, l->namespace->access);
418             hash = crc32_add_string(hash, l->namespace->name);
419             l = l->next;
420         }
421     }
422     return hash;
423 }
424
425 int multiname_equals(multiname_t*m1, multiname_t*m2)
426 {
427     if(!m1 || !m2)
428         return m1==m2;
429     if(m1->type!=m2->type)
430         return 0;
431
432     if((!m1->name) != (!m2->name))
433         return 0;
434     if((!m1->ns) != (!m2->ns))
435         return 0;
436     if((!m1->namespace_set) != (!m2->namespace_set))
437         return 0;
438
439     if(m1->name && m2->name && strcmp(m1->name,m2->name))
440         return 0;
441     if(m1->ns && m2->ns) {
442         if(!namespace_equals(m1->ns, m2->ns))
443             return 0;
444     }
445     if(m1->namespace_set && m2->namespace_set) {
446         if(!namespace_set_equals(m1->namespace_set, m2->namespace_set))
447             return 0;
448     }
449     return 1;
450 }
451
452 multiname_t* multiname_new(namespace_t*ns, const char*name)
453 {
454     NEW(multiname_t,m);
455     m->type = QNAME;
456     if(!ns) {
457         m->ns = namespace_new_packageinternal("");
458     } else {
459         m->ns = namespace_clone(ns);
460     }
461     m->name = strdup(name);
462     return m;
463 }
464
465 multiname_t* multiname_clone(multiname_t*other)
466 {
467     if(!other)
468         return 0;
469     NEW(multiname_t,m);
470     m->type = other->type;
471     if(other->ns)
472         m->ns = namespace_clone(other->ns);
473     if(other->namespace_set)
474         m->namespace_set = namespace_set_clone(other->namespace_set);
475     if(other->name)
476         m->name = strdup(other->name);
477     return m;
478 }
479
480
481 char* access2str(int type)
482 {
483     if(type==0x08) return "namespace";
484     else if(type==0x16) return "public";
485     else if(type==0x17) return "packageinternal";
486     else if(type==0x18) return "protected";
487     else if(type==0x19) return "explicit";
488     else if(type==0x1A) return "staticprotected";
489     else if(type==0x05) return "private";
490     else if(type==0x00) return "any";
491     else {
492         fprintf(stderr, "Undefined access type %02x\n", type);
493         return "undefined";
494     }
495 }
496
497
498 char multiname_late_namespace(multiname_t*m)
499 {
500     if(!m)
501         return 0;
502     return (m->type==RTQNAME || m->type==RTQNAMEA ||
503             m->type==RTQNAMEL || m->type==RTQNAMELA);
504 }
505
506 char multiname_late_name(multiname_t*m)
507 {
508     if(!m)
509         return 0;
510     return m->type==RTQNAMEL || m->type==RTQNAMELA ||
511            m->type==MULTINAMEL || m->type==MULTINAMELA;
512 }
513
514 char* multiname_tostring(multiname_t*m)
515 {
516     char*mname = 0;
517     if(!m)
518         return strdup("NULL");
519     if(m->type==0xff)
520         return strdup("--<MULTINAME 0xff>--");
521
522     char*name = m->name?escape_string(m->name):strdup("*");
523     int namelen = strlen(name);
524
525     if(m->type==QNAME || m->type==QNAMEA || m->type==POSTFIXTYPE) {
526         char*nsname = m->ns?escape_string(m->ns->name):strdup("NULL");
527         mname = malloc(strlen(nsname)+namelen+32);
528         strcpy(mname, "<q");
529         if(m->type == QNAMEA)
530             strcat(mname, ",attr");
531         strcat(mname, ">");
532         if(m->ns) {
533             strcat(mname,"[");
534             strcat(mname,access2str(m->ns->access));
535             strcat(mname, "]");
536         }
537         strcat(mname, nsname);
538         free(nsname);
539         strcat(mname, "::");
540         strcat(mname, name);
541     } else if(m->type==RTQNAME || m->type==RTQNAMEA) {
542         mname = malloc(namelen+32);
543         strcpy(mname, "<rt");
544         if(m->type == RTQNAMEA) 
545             strcat(mname, ",attr");
546         strcat(mname, ">");
547         strcat(mname, name);
548     } else if(m->type==RTQNAMEL) {
549         mname = strdup("<rt,l>");
550     } else if(m->type==RTQNAMELA) {
551         mname = strdup("<rt,l,attr>");
552     } else if(m->type==MULTINAME || m->type==MULTINAMEA) {
553         char*s = namespace_set_tostring(m->namespace_set);
554         mname = malloc(strlen(s)+namelen+16);
555         if(m->type == MULTINAME)
556             strcpy(mname,"<multi>");
557         else //MULTINAMEA
558             strcpy(mname,"<multi,attr>");
559         strcat(mname, s);
560         strcat(mname, "::");
561         strcat(mname, name);
562         free(s);
563     } else if(m->type==MULTINAMEL || m->type==MULTINAMELA) {
564         char*s = namespace_set_tostring(m->namespace_set);
565         mname = malloc(strlen(s)+16);
566         if(m->type == MULTINAMEL)
567             strcpy(mname,"<l,multi>");
568         else //MULTINAMELA
569             strcpy(mname,"<l,multi,attr>");
570         strcat(mname,s);
571         free(s);
572     } else {
573         return strdup("<invalid>");
574     }
575     free(name);
576     return mname;
577 }
578
579 multiname_t* multiname_fromstring(const char*name2)
580 {
581     if(!name2)
582         return 0;
583     char*n = strdup(name2);
584     char*p = strstr(n, "::");
585     char*namespace=0,*name=0;
586     if(!p) {
587         if(strchr(n, ':')) {
588             fprintf(stderr, "Error: single ':' in name\n");
589         }
590         namespace = "";
591         name = n;
592     } else {
593         *p = 0;
594         namespace = n;
595         name = p+2;
596         if(strchr(namespace, ':')) {
597             fprintf(stderr, "Error: single ':' in namespace\n");
598         }
599         if(strchr(name, ':')) {
600             fprintf(stderr, "Error: single ':' in qualified name\n");
601         }
602     }
603
604     multiname_t*m = malloc(sizeof(multiname_t));
605     memset(m, 0, sizeof(multiname_t));
606     m->type = QNAME;
607     m->namespace_set = 0;
608     m->ns = namespace_fromstring(namespace);
609     m->name = name?strdup(name):0;
610     free(n);
611     return m;
612 }
613
614 void multiname_destroy(multiname_t*m)
615 {
616     if(m) {
617         if(m->name) {
618             free((void*)m->name);m->name = 0;
619         }
620         if(m->ns) {
621             namespace_destroy(m->ns);m->ns = 0;
622         }
623         if(m->namespace_set) {
624             namespace_set_destroy(m->namespace_set);m->namespace_set = 0;
625         }
626         m->type=0;
627         free(m);
628     }
629 }
630
631 type_t multiname_type = {
632     dup: (dup_func)multiname_clone,
633     hash: (hash_func)multiname_hash,
634     free: (free_func)multiname_destroy,
635     equals: (equals_func)multiname_equals
636 };
637
638
639 // ------------------------------- constants -------------------------------------
640
641 #define UNIQUE_CONSTANT(x) ((x) == CONSTANT_TRUE || (x) == CONSTANT_FALSE || (x) == CONSTANT_NULL || (x) == CONSTANT_UNDEFINED)
642
643 constant_t* constant_new_int(int i) 
644 {
645     NEW(constant_t,c);
646     c->i = i;
647     c->type = CONSTANT_INT;
648     return c;
649 }
650 constant_t* constant_new_uint(unsigned int u)
651 {
652     NEW(constant_t,c);
653     c->u = u;
654     c->type = CONSTANT_UINT;
655     return c;
656 }
657 constant_t* constant_new_float(double f)
658 {
659     NEW(constant_t,c);
660     c->f = f;
661     c->type = CONSTANT_FLOAT;
662     return c;
663 }
664 constant_t* constant_new_string(const char*s)
665 {
666     NEW(constant_t,c);
667     c->s = string_new4(s);
668     c->type = CONSTANT_STRING;
669     return c;
670 }
671 constant_t* constant_new_string2(const char*s, int len)
672 {
673     NEW(constant_t,c);
674     c->s = string_new3(s, len);
675     c->type = CONSTANT_STRING;
676     return c;
677 }
678 constant_t* constant_new_namespace(namespace_t*ns)
679 {
680     NEW(constant_t,c);
681     c->ns = namespace_clone(ns);
682     c->type = ns->access;
683     assert(NS_TYPE(c->type));
684     return c;
685 }
686 constant_t* constant_new_true()
687 {
688     NEW(constant_t,c);
689     c->type = CONSTANT_TRUE;
690     return c;
691 }
692 constant_t* constant_new_false()
693 {
694     NEW(constant_t,c);
695     c->type = CONSTANT_FALSE;
696     return c;
697 }
698 constant_t* constant_new_null()
699 {
700     NEW(constant_t,c);
701     c->type = CONSTANT_NULL;
702     return c;
703 }
704 constant_t* constant_new_undefined()
705 {
706     NEW(constant_t,c);
707     c->type = CONSTANT_UNDEFINED;
708     return c;
709 }
710 constant_t* constant_clone(constant_t*other)
711 {
712     if(!other) return 0;
713     constant_t*c = malloc(sizeof(constant_t));
714     memcpy(c, other, sizeof(constant_t));
715     if(NS_TYPE(c->type)) {
716         c->ns = namespace_clone(other->ns);
717     } else if(c->type == CONSTANT_STRING) {
718         c->s = string_dup3(other->s);
719     }
720     return c;
721 }
722 constant_t* constant_fromindex(pool_t*pool, int index, int type)
723 {
724     if(!index) {
725         /* even for nonvalued constants (like TRUE/FALSE etc.), a nonzero
726            index is present to indicate that a type is coming */
727         return 0;
728     } 
729     NEW(constant_t,c);
730     c->type = type;
731     if(NS_TYPE(c->type)) {
732         c->ns = namespace_clone(pool_lookup_namespace(pool, index));
733     } else if(c->type == CONSTANT_INT) {
734         c->i = pool_lookup_int(pool, index);
735     } else if(c->type == CONSTANT_UINT) {
736         c->u = pool_lookup_uint(pool, index);
737     } else if(c->type == CONSTANT_FLOAT) {
738         c->f = pool_lookup_float(pool, index);
739     } else if(c->type == CONSTANT_STRING) {
740         string_t s = pool_lookup_string2(pool, index);
741         c->s = string_dup3(&s);
742     } else if(UNIQUE_CONSTANT(c->type)) {
743         // ok
744     } else {
745         fprintf(stderr, "invalid constant type %02x\n", c->type);
746     }
747     return c;
748 }
749 char* constant_tostring(constant_t*c)
750 {
751     if(!c)
752         return strdup("NULL");
753     char buf[32];
754     if(NS_TYPE(c->type)) {
755         return namespace_tostring(c->ns);
756     } else if(c->type == CONSTANT_INT) {
757         sprintf(buf, "%d", c->i);
758         return strdup(buf);
759     } else if(c->type == CONSTANT_UINT) {
760         sprintf(buf, "%u", c->u);
761         return strdup(buf);
762     } else if(c->type == CONSTANT_FLOAT) {
763         char buf[1024];
764         sprintf(buf, "%f", c->f);
765         return strdup(buf);
766     } else if(c->type == CONSTANT_STRING) {
767         /* should we escape the string? \0 bytes won't be printed */
768         return strdup_n(c->s->str,c->s->len);
769     } else if(c->type == CONSTANT_TRUE) {
770         return strdup("true");
771     } else if(c->type == CONSTANT_FALSE) {
772         return strdup("false");
773     } else if(c->type == CONSTANT_NULL) {
774         return strdup("null");
775     } else if(c->type == CONSTANT_UNDEFINED) {
776         return strdup("undefined");
777     } else {
778         fprintf(stderr, "invalid constant type %02x\n", c->type);
779         return 0;
780     }
781 }
782 char constant_has_index(constant_t*c) 
783 {
784     if(!c)
785         return 0;
786     return !UNIQUE_CONSTANT(c->type);
787 }
788 int constant_get_index(pool_t*pool, constant_t*c)
789 {
790     if(!c)
791         return 0;
792     if(NS_TYPE(c->type)) {
793         assert(c->ns);
794         /*if(c->type!=c->ns->access) {
795             printf("%02x<->%02x\n", c->type, c->ns->access);
796         }*/
797         assert(c->type == c->ns->access);
798         return pool_register_namespace(pool, c->ns);
799     } else if(c->type == CONSTANT_INT) {
800         return pool_register_int(pool, c->i);
801     } else if(c->type == CONSTANT_UINT) {
802         return pool_register_uint(pool, c->u);
803     } else if(c->type == CONSTANT_FLOAT) {
804         return pool_register_float(pool, c->f);
805     } else if(c->type == CONSTANT_STRING) {
806         return pool_register_string2(pool, c->s);
807     } else if(c->type == CONSTANT_UNDEFINED) {
808         /* write undefined with index 0 (and no type). Otherwise, the FlashPlayer 
809            seems to throw an "attempt to read out of bounds" exception */
810         return 0;
811     } else if(!constant_has_index(c)) {
812         return 1;
813     } else {
814         fprintf(stderr, "invalid constant type %02x\n", c->type);
815         return 0;
816     }
817 }
818 void constant_free(constant_t*c)
819 {
820     if(!c)
821         return;
822     if(c->type == CONSTANT_STRING) {
823         string_free(c->s);
824     } else if (NS_TYPE(c->type)) {
825         namespace_destroy(c->ns);c->ns=0;
826     }
827     free(c);
828 }
829 // --------------------------- optimizing -----------------------------------
830
831 static int array_append_or_increase(array_t*array, void*key)
832 {
833     int pos = array_find(array, key);
834     if(pos>=0) {
835         array->d[pos].data++;
836         return pos;
837     } else {
838         return array_append(array, key, 0);
839     }
840 }
841 static int compare_arrayentry(const void*_c1, const void*_c2)
842 {
843     const array_entry_t*c1 = _c1;
844     const array_entry_t*c2 = _c2;
845     return c2->data - c1->data;
846 }
847
848 static void* nodup(const void*o) {return (void*)o;}
849
850 static void reshuffle_array(array_t*array)
851 {
852     qsort(array->d+1, array->num-1, sizeof(array->d[0]), compare_arrayentry);
853     type_t* old_type = array->entry2pos->key_type;
854     type_t old_type_nodup = *old_type;
855     old_type_nodup.dup = nodup;
856     dict_t*d = dict_new2(&old_type_nodup);
857     dict_destroy_shallow(array->entry2pos);
858     array->entry2pos = d;
859     int t;
860     for(t=0;t<array->num;t++) {
861         dict_put(array->entry2pos, array->d[t].name, (void*)(ptroff_t)(t+1));
862     }
863     d->key_type = old_type;
864
865 }
866
867 // ------------------------------- pool -------------------------------------
868
869 int pool_register_uint(pool_t*p, unsigned int i)
870 {
871     int pos = array_append_or_increase(p->x_uints, &i);
872     assert(pos!=0);
873     return pos;
874 }
875 int pool_register_int(pool_t*p, int i)
876 {
877     int pos = array_append_or_increase(p->x_ints, &i);
878     assert(pos!=0);
879     return pos;
880 }
881 int pool_register_float(pool_t*p, double d)
882 {
883     int pos = array_append_or_increase(p->x_floats, &d);
884     assert(pos!=0);
885     return pos;
886 }
887 int pool_register_string(pool_t*pool, const char*str)
888 {
889     if(!str) return 0;
890     string_t s = string_new2(str);
891     int pos = array_append_or_increase(pool->x_strings, &s);
892     assert(pos!=0);
893     return pos;
894 }
895 int pool_register_string2(pool_t*pool, string_t*s)
896 {
897     if(!s || !s->str) return 0;
898     int pos = array_append_or_increase(pool->x_strings, s);
899     assert(pos!=0);
900     return pos;
901 }
902 int pool_register_namespace(pool_t*pool, namespace_t*ns)
903 {
904     if(!ns) return 0;
905     int pos = array_append_or_increase(pool->x_namespaces, ns);
906     assert(pos!=0 || ns->access==ZERONAMESPACE);
907     return pos;
908 }
909 int pool_register_namespace_set(pool_t*pool, namespace_set_t*set)
910 {
911     if(!set) return 0;
912     int pos = array_append_or_increase(pool->x_namespace_sets, set);
913     assert(pos!=0);
914     return pos;
915 }
916 int pool_register_multiname(pool_t*pool, multiname_t*n)
917 {
918     if(!n) return 0;
919     int pos = array_append_or_increase(pool->x_multinames, n);
920     assert(pos!=0);
921     return pos;
922 }
923 int pool_register_multiname2(pool_t*pool, char*name)
924 {
925     if(!name) return 0;
926     multiname_t*n = multiname_fromstring(name);
927     int pos = array_append_or_increase(pool->x_multinames, n);
928     multiname_destroy(n);
929     assert(pos!=0);
930     return pos;
931 }
932
933
934 int pool_find_uint(pool_t*pool, unsigned int x)
935 {
936     int i = array_find(pool->x_uints, &x);
937     if(i<=0) {
938         fprintf(stderr, "Couldn't find uint \"%d\" in constant pool\n", x);
939         return 0;
940     }
941     return i;
942 }
943 int pool_find_int(pool_t*pool, int x)
944 {
945     int i = array_find(pool->x_ints, &x);
946     if(i<=0) {
947         fprintf(stderr, "Couldn't find int \"%d\" in constant pool\n", x);
948         return 0;
949     }
950     return i;
951 }
952 int pool_find_float(pool_t*pool, double x)
953 {
954     int i = array_find(pool->x_ints, &x);
955     if(i<=0) {
956         fprintf(stderr, "Couldn't find int \"%f\" in constant pool\n", x);
957         return 0;
958     }
959     return i;
960 }
961 int pool_find_namespace(pool_t*pool, namespace_t*ns)
962 {
963     if(!ns)
964         return 0;
965     int i = array_find(pool->x_namespaces, ns);
966     if(i<0) {
967         char*s = namespace_tostring(ns);
968         fprintf(stderr, "Couldn't find namespace \"%s\" %08x in constant pool\n", s, (int)ns);
969         free(s);
970         return 0;
971     }
972     return i;
973 }
974 int pool_find_namespace_set(pool_t*pool, namespace_set_t*set)
975 {
976     if(!set)
977         return 0;
978     int i = array_find(pool->x_namespace_sets, set);
979     if(i<=0) {
980         char*s = namespace_set_tostring(set);
981         fprintf(stderr, "Couldn't find namespace_set \"%s\" in constant pool\n", s);
982         free(s);
983         return 0;
984     }
985     return i;
986 }
987 int pool_find_string(pool_t*pool, const char*str)
988 {
989     if(!str)
990         return 0;
991     string_t s = string_new2(str);
992     int i = array_find(pool->x_strings, &s);
993     if(i<=0) {
994         fprintf(stderr, "Couldn't find string \"%s\" in constant pool\n", str);
995         return 0;
996     }
997     return i;
998 }
999 int pool_find_multiname(pool_t*pool, multiname_t*name)
1000 {
1001     if(!name)
1002         return 0;
1003     int i = array_find(pool->x_multinames, name);
1004     if(i<=0) {
1005         char*s = multiname_tostring(name);
1006         fprintf(stderr, "Couldn't find multiname \"%s\" in constant pool\n", s);
1007         free(s);
1008         return 0;
1009     }
1010     return i;
1011 }
1012
1013 int pool_lookup_int(pool_t*pool, int i)
1014 {
1015     if(!i) return 0;
1016     return *(int*)array_getkey(pool->x_ints, i);
1017 }
1018 unsigned int pool_lookup_uint(pool_t*pool, int i)
1019 {
1020     if(!i) return 0;
1021     return *(unsigned int*)array_getkey(pool->x_uints, i);
1022 }
1023 double pool_lookup_float(pool_t*pool, int i)
1024 {
1025     if(!i) return __builtin_nan("");
1026     return *(double*)array_getkey(pool->x_floats, i);
1027 }
1028 const char*pool_lookup_string(pool_t*pool, int i)
1029 {
1030     string_t*s = array_getkey(pool->x_strings, i);
1031     if(!s) return 0;
1032     return s->str;
1033 }
1034 string_t pool_lookup_string2(pool_t*pool, int i)
1035 {
1036     string_t*s = array_getkey(pool->x_strings, i);
1037     return *s;
1038 }
1039 namespace_t*pool_lookup_namespace(pool_t*pool, int i)
1040 {
1041     return (namespace_t*)array_getkey(pool->x_namespaces, i);
1042 }
1043 namespace_set_t*pool_lookup_namespace_set(pool_t*pool, int i)
1044 {
1045     return (namespace_set_t*)array_getkey(pool->x_namespace_sets, i);
1046 }
1047 multiname_t*pool_lookup_multiname(pool_t*pool, int i)
1048 {
1049     return (multiname_t*)array_getkey(pool->x_multinames, i);
1050 }
1051
1052 static namespace_t zeronamespace={ZERONAMESPACE,"*"};
1053 pool_t*pool_new()
1054 {
1055     NEW(pool_t, p);
1056
1057     p->x_ints = array_new2(&uint_type);
1058     p->x_uints = array_new2(&uint_type);
1059     p->x_floats = array_new2(&float_type);
1060     p->x_strings = array_new2(&stringstruct_type);
1061     p->x_namespaces = array_new2(&namespace_type);
1062     p->x_namespace_sets = array_new2(&namespace_set_type);
1063     p->x_multinames = array_new2(&multiname_type);
1064
1065     /* add a zero-index entry in each list */
1066   
1067     array_append(p->x_ints, 0, 0);
1068     array_append(p->x_uints, 0, 0);
1069     array_append(p->x_floats, 0, 0);
1070     array_append(p->x_strings, 0, 0);
1071     array_append(p->x_namespaces, &zeronamespace, 0);
1072     array_append(p->x_namespace_sets, 0, 0);
1073     array_append(p->x_multinames, 0, 0);
1074     return p;
1075 }
1076
1077 void pool_optimize(pool_t*p)
1078 {
1079     reshuffle_array(p->x_ints);
1080     reshuffle_array(p->x_uints);
1081     reshuffle_array(p->x_floats);
1082     reshuffle_array(p->x_strings);
1083     reshuffle_array(p->x_namespaces);
1084     reshuffle_array(p->x_namespace_sets);
1085     reshuffle_array(p->x_multinames);
1086 }
1087
1088 #define DEBUG if(0)
1089 //#define DEBUG
1090
1091 void pool_read(pool_t*pool, TAG*tag)
1092 {
1093     int num_ints = swf_GetU30(tag);
1094     DEBUG printf("%d ints\n", num_ints);
1095     int t;
1096     for(t=1;t<num_ints;t++) {
1097         S32 v = swf_GetABCS32(tag);
1098         DEBUG printf("int %d) %d\n", t, v);
1099         array_append(pool->x_ints, &v, 0);
1100     }
1101
1102     int num_uints = swf_GetU30(tag);
1103     DEBUG printf("%d uints\n", num_uints);
1104     for(t=1;t<num_uints;t++) {
1105         U32 v = swf_GetABCU32(tag);
1106         DEBUG printf("uint %d) %d\n", t, v);
1107         array_append(pool->x_uints, &v, 0);
1108     }
1109     
1110     int num_floats = swf_GetU30(tag);
1111     DEBUG printf("%d floats\n", num_floats);
1112     for(t=1;t<num_floats;t++) {
1113         double d = swf_GetD64(tag);
1114         DEBUG printf("float %d) %f\n", t, d);
1115         array_append(pool->x_floats, &d, 0);
1116     }
1117     
1118     int num_strings = swf_GetU30(tag);
1119     DEBUG printf("%d strings\n", num_strings);
1120     for(t=1;t<num_strings;t++) {
1121         int len = swf_GetU30(tag);
1122         string_t s = string_new((char*)&tag->data[tag->pos], len);
1123         swf_GetBlock(tag, 0, len);
1124         array_append(pool->x_strings, &s, 0);
1125         DEBUG printf("%d) \"%s\"\n", t, ((string_t*)array_getkey(pool->x_strings, t))->str);
1126     }
1127     int num_namespaces = swf_GetU30(tag);
1128     DEBUG printf("%d namespaces\n", num_namespaces);
1129     for(t=1;t<num_namespaces;t++) {
1130         U8 type = swf_GetU8(tag);
1131         int namenr = swf_GetU30(tag);
1132         const char*name = 0; 
1133         if(namenr)
1134             name = pool_lookup_string(pool, namenr);
1135         namespace_t*ns = namespace_new(type, name);
1136         array_append(pool->x_namespaces, ns, 0);
1137         DEBUG printf("%d) %02x \"%s\"\n", t, type, namespace_tostring(ns));
1138         namespace_destroy(ns);
1139     }
1140     int num_sets = swf_GetU30(tag);
1141     DEBUG printf("%d namespace sets\n", num_sets);
1142     for(t=1;t<num_sets;t++) {
1143         int count = swf_GetU30(tag);
1144         int s;
1145         
1146         NEW(namespace_set_t, nsset);
1147         for(s=0;s<count;s++) {
1148             int nsnr = swf_GetU30(tag);
1149             if(!nsnr)
1150                 fprintf(stderr, "Zero entry in namespace set\n");
1151             namespace_t*ns = (namespace_t*)array_getkey(pool->x_namespaces, nsnr);
1152             list_append(nsset->namespaces, namespace_clone(ns));
1153         }
1154         array_append(pool->x_namespace_sets, nsset, 0);
1155         DEBUG printf("set %d) %s\n", t, namespace_set_tostring(nsset));
1156         namespace_set_destroy(nsset);
1157     }
1158
1159     int num_multinames = swf_GetU30(tag);
1160     DEBUG printf("%d multinames\n", num_multinames);
1161     for(t=1;t<num_multinames;t++) {
1162         multiname_t m;
1163         memset(&m, 0, sizeof(multiname_t));
1164         
1165         /*int s;
1166         for(s=0;s<8;s++)
1167             printf("0x%02x ", tag->data[tag->pos+s]);
1168         printf("\n");*/
1169
1170         m.type = swf_GetU8(tag);
1171         if(m.type==0x07 || m.type==0x0d) {
1172             int namespace_index = swf_GetU30(tag);
1173             m.ns = (namespace_t*)array_getkey(pool->x_namespaces, namespace_index);
1174             if(!m.ns) {
1175                 fprintf(stderr, "Error: Illegal reference to namespace #%d in constant pool.\n", namespace_index);
1176             }
1177             int name_index = swf_GetU30(tag);
1178             if(name_index) // 0 = '*' (any)
1179                 m.name = pool_lookup_string(pool, name_index);
1180         } else if(m.type==0x0f || m.type==0x10) {
1181             int name_index = swf_GetU30(tag);
1182             if(name_index) // 0 = '*' (any name)
1183                 m.name = pool_lookup_string(pool, name_index);
1184         } else if(m.type==0x11 || m.type==0x12) {
1185         } else if(m.type==0x09 || m.type==0x0e) {
1186             int name_index = swf_GetU30(tag);
1187             int namespace_set_index = swf_GetU30(tag);
1188             if(name_index)
1189                 m.name = pool_lookup_string(pool, name_index);
1190             m.namespace_set = (namespace_set_t*)array_getkey(pool->x_namespace_sets, namespace_set_index);
1191         } else if(m.type==0x1b || m.type==0x1c) {
1192             int namespace_set_index = swf_GetU30(tag);
1193             m.namespace_set = (namespace_set_t*)array_getkey(pool->x_namespace_sets, namespace_set_index);
1194         } else if(m.type==0x1d) {
1195             int v1 = swf_GetU30(tag); //multiname
1196             int v2 = swf_GetU30(tag); //counter?
1197             int v3 = swf_GetU30(tag); //multiname
1198             // e.g. Vector<int> ... we only store the parent object
1199             m = *(multiname_t*)array_getkey(pool->x_multinames, v1);
1200         } else {
1201             printf("can't parse type %d multinames yet\n", m.type);
1202         }
1203         DEBUG printf("multiname %d) %s\n", t, multiname_tostring(&m));
1204         array_append(pool->x_multinames, &m, 0);
1205     }
1206
1207
1208 void pool_dump(pool_t*pool, FILE*fo, char flags)
1209 {
1210     int t;
1211     fprintf(fo, "%d integers\n", pool->x_ints->num);
1212     for(t=1;t<pool->x_ints->num;t++) {
1213         S32 val = *(int*)array_getkey(pool->x_ints, t);
1214         int freq = (int)(ptroff_t)array_getvalue(pool->x_ints, t);
1215         if(flags&1) fprintf(fo, "%5d %d) %d\n", freq, t, val);
1216     }
1217     fprintf(fo, "%d unsigned integers\n", pool->x_uints->num);
1218     for(t=1;t<pool->x_uints->num;t++) {
1219         U32 val = *(unsigned int*)array_getkey(pool->x_uints, t);
1220         int freq = (int)(ptroff_t)array_getvalue(pool->x_uints, t);
1221         if(flags&1) fprintf(fo, "%5d %d) %d\n", freq, t, val);
1222     }
1223     fprintf(fo, "%d floats\n", pool->x_floats->num);
1224     for(t=1;t<pool->x_floats->num;t++) {
1225         double d = pool_lookup_float(pool, t);
1226         int freq = (int)(ptroff_t)array_getvalue(pool->x_floats, t);
1227         if(flags&2) fprintf(fo, "%5d %d) %f\n", freq, t, d);
1228     }
1229     fprintf(fo, "%d strings\n", pool->x_strings->num);
1230     for(t=1;t<pool->x_strings->num;t++) {
1231         string_t str = pool_lookup_string2(pool, t);
1232         int freq = (int)(ptroff_t)array_getvalue(pool->x_strings, t);
1233         if(flags&1) fprintf(fo, "%5d %d) ", freq, t);
1234         if(flags&1) fwrite(str.str, str.len, 1, fo);
1235         if(flags&1) fprintf(fo, "\n");
1236     }
1237     fprintf(fo, "%d namespaces\n", pool->x_namespaces->num);
1238     for(t=1;t<pool->x_namespaces->num;t++) {
1239         namespace_t*ns= (namespace_t*)array_getkey(pool->x_namespaces, t);
1240         char*s = namespace_tostring(ns);
1241         int freq = (int)(ptroff_t)array_getvalue(pool->x_namespaces, t);
1242         if(flags&1) fprintf(fo, "%5d %d) %s\n", freq, t, s);
1243         free(s);
1244     }
1245     fprintf(fo, "%d namespace sets\n", pool->x_namespace_sets->num);
1246     for(t=1;t<pool->x_namespace_sets->num;t++) {
1247         namespace_set_t*set = (namespace_set_t*)array_getkey(pool->x_namespace_sets, t);
1248         char*s = namespace_set_tostring(set);
1249         int freq = (int)(ptroff_t)array_getvalue(pool->x_namespace_sets, t);
1250         if(flags&1) fprintf(fo, "%5d %d) %s\n", freq, t, s);
1251         free(s);
1252     }
1253
1254     fprintf(fo, "%d multinames\n", pool->x_multinames->num);
1255     for(t=1;t<pool->x_multinames->num;t++) {
1256         multiname_t*m = (multiname_t*)array_getkey(pool->x_multinames, t);
1257         char*s = multiname_tostring(m);
1258         int freq = (int)(ptroff_t)array_getvalue(pool->x_multinames, t);
1259         if(flags&1) fprintf(fo, "%5d %d) %s\n", freq, t, s);
1260         free(s);
1261     }
1262
1263
1264 void pool_write(pool_t*pool, TAG*tag)
1265 {
1266     int t;
1267     
1268     /* make sure that all namespaces used by multinames / namespace sets
1269        and all strings used by namespaces exist */
1270
1271     for(t=1;t<pool->x_multinames->num;t++) {
1272         multiname_t*m = (multiname_t*)array_getkey(pool->x_multinames, t);
1273         if(m->ns) {
1274             pool_register_namespace(pool, m->ns);
1275         }
1276         if(m->namespace_set) {
1277             pool_register_namespace_set(pool, m->namespace_set);
1278         }
1279         if(m->name) {
1280             pool_register_string(pool, m->name);
1281         }
1282     }
1283     for(t=1;t<pool->x_namespace_sets->num;t++) {
1284         namespace_set_t*set = (namespace_set_t*)array_getkey(pool->x_namespace_sets, t);
1285         namespace_list_t*i = set->namespaces;
1286         while(i) {
1287             pool_register_namespace(pool, i->namespace);
1288             i = i->next;
1289         }
1290     }
1291     for(t=1;t<pool->x_namespaces->num;t++) {
1292         namespace_t*ns= (namespace_t*)array_getkey(pool->x_namespaces, t);
1293         /*  The spec says (page 22): "a value of zero denotes an empty string".
1294             However when actually using zero strings as empty namespaces, the
1295             flash player breaks.*/
1296         //if(ns->name && ns->name[0])
1297         pool_register_string(pool, ns->name);
1298     }
1299
1300     //pool_register_int(pool, 15);
1301     //pool_register_int(pool, 1);
1302     //pool_register_int(pool, 0);
1303     
1304     /* write data */
1305     swf_SetU30(tag, pool->x_ints->num>1?pool->x_ints->num:0);
1306     for(t=1;t<pool->x_ints->num;t++) {
1307         S32 val = *(int*)array_getkey(pool->x_ints, t);
1308         swf_SetABCS32(tag, val);
1309     }
1310     swf_SetU30(tag, pool->x_uints->num>1?pool->x_uints->num:0);
1311     for(t=1;t<pool->x_uints->num;t++) {
1312         swf_SetABCU32(tag, *(unsigned int*)array_getkey(pool->x_uints, t));
1313     }
1314     swf_SetU30(tag, pool->x_floats->num>1?pool->x_floats->num:0);
1315     for(t=1;t<pool->x_floats->num;t++) {
1316         double d = pool_lookup_float(pool, t);
1317         swf_SetD64(tag, d);
1318     }
1319     swf_SetU30(tag, pool->x_strings->num>1?pool->x_strings->num:0);
1320     for(t=1;t<pool->x_strings->num;t++) {
1321         string_t str = pool_lookup_string2(pool, t);
1322         swf_SetU30String(tag, str.str, str.len);
1323     }
1324     swf_SetU30(tag, pool->x_namespaces->num>1?pool->x_namespaces->num:0);
1325     for(t=1;t<pool->x_namespaces->num;t++) {
1326         namespace_t*ns= (namespace_t*)array_getkey(pool->x_namespaces, t);
1327         swf_SetU8(tag, ns->access);
1328         const char*name = ns->name;
1329         int i = 0;
1330         
1331         //if(name && name[0])
1332         i = pool_find_string(pool, name);
1333
1334         swf_SetU30(tag, i);
1335     }
1336     swf_SetU30(tag, pool->x_namespace_sets->num>1?pool->x_namespace_sets->num:0);
1337     for(t=1;t<pool->x_namespace_sets->num;t++) {
1338         namespace_set_t*set = (namespace_set_t*)array_getkey(pool->x_namespace_sets, t);
1339         namespace_list_t*i = set->namespaces; 
1340         int len = list_length(i);
1341         swf_SetU30(tag, len);
1342         while(i) {
1343             int index = pool_find_namespace(pool, i->namespace);
1344             swf_SetU30(tag, index);
1345             i = i->next;
1346         }
1347     }
1348
1349     swf_SetU30(tag, pool->x_multinames->num>1?pool->x_multinames->num:0);
1350     for(t=1;t<pool->x_multinames->num;t++) {
1351         multiname_t*m = (multiname_t*)array_getkey(pool->x_multinames, t);
1352         swf_SetU8(tag, m->type);
1353
1354         if(m->ns) {
1355             assert(m->type==0x07 || m->type==0x0d);
1356             int i = pool_find_namespace(pool, m->ns);
1357             if(i<0) fprintf(stderr, "internal error: unregistered namespace %02x %s %s\n", m->ns->access, access2str(m->ns->access), m->ns->name);
1358             swf_SetU30(tag, i);
1359         } else {
1360             assert(m->type!=0x07 && m->type!=0x0d);
1361         }
1362         
1363         if(m->name) {
1364             assert(m->type==0x09 || m->type==0x0e || m->type==0x07 || m->type==0x0d || m->type==0x0f || m->type==0x10);
1365             int i = pool_find_string(pool, m->name);
1366             if(i<0) fprintf(stderr, "internal error: unregistered name\n");
1367             swf_SetU30(tag, i);
1368         } else {
1369             if(m->type == 0x09) {
1370                 swf_SetU30(tag, 0);
1371             }
1372             assert(m->type!=0x0e && m->type!=0x07 && m->type!=0x0d && m->type!=0x0f && m->type!=0x10);
1373         }
1374         if(m->namespace_set) {
1375             assert(m->type==0x09 || m->type==0x0e || m->type==0x1c || m->type==0x1b);
1376             int i = pool_find_namespace_set(pool, m->namespace_set);
1377             if(i<0) fprintf(stderr, "internal error: unregistered namespace set\n");
1378             swf_SetU30(tag, i);
1379         } else {
1380             assert(m->type!=0x09 && m->type!=0x0e && m->type!=0x1c && m->type!=0x1b);
1381         }
1382     }
1383 }
1384
1385
1386 void pool_destroy(pool_t*pool)
1387 {
1388     int t;
1389     array_free(pool->x_ints);
1390     array_free(pool->x_uints);
1391     array_free(pool->x_floats);
1392     array_free(pool->x_strings);
1393     array_free(pool->x_namespaces);
1394     array_free(pool->x_namespace_sets);
1395     array_free(pool->x_multinames);
1396     free(pool);
1397 }