fixed some compiler warnings, fixed as3compile spec for-in.as
[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, s);
189     else if(!*s)
190         sprintf(string, "[%s]\"\"", access, s);
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;
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 {
491         fprintf(stderr, "Undefined access type %02x\n", type);
492         return "undefined";
493     }
494 }
495
496
497 char multiname_late_namespace(multiname_t*m)
498 {
499     if(!m)
500         return 0;
501     return (m->type==RTQNAME || m->type==RTQNAMEA ||
502             m->type==RTQNAMEL || m->type==RTQNAMELA);
503 }
504
505 char multiname_late_name(multiname_t*m)
506 {
507     if(!m)
508         return 0;
509     return m->type==RTQNAMEL || m->type==RTQNAMELA ||
510            m->type==MULTINAMEL || m->type==MULTINAMELA;
511 }
512
513 char* multiname_tostring(multiname_t*m)
514 {
515     char*mname = 0;
516     if(!m)
517         return strdup("NULL");
518     if(m->type==0xff)
519         return strdup("--<MULTINAME 0xff>--");
520
521     char*name = m->name?escape_string(m->name):strdup("*");
522     int namelen = strlen(name);
523
524     if(m->type==QNAME || m->type==QNAMEA || m->type==POSTFIXTYPE) {
525         char*nsname = m->ns?escape_string(m->ns->name):strdup("NULL");
526         mname = malloc(strlen(nsname)+namelen+32);
527         strcpy(mname, "<q");
528         if(m->type == QNAMEA)
529             strcat(mname, ",attr");
530         strcat(mname, ">");
531         if(m->ns) {
532             strcat(mname,"[");
533             strcat(mname,access2str(m->ns->access));
534             strcat(mname, "]");
535         }
536         strcat(mname, nsname);
537         free(nsname);
538         strcat(mname, "::");
539         strcat(mname, name);
540     } else if(m->type==RTQNAME || m->type==RTQNAMEA) {
541         mname = malloc(namelen+32);
542         strcpy(mname, "<rt");
543         if(m->type == RTQNAMEA) 
544             strcat(mname, ",attr");
545         strcat(mname, ">");
546         strcat(mname, name);
547     } else if(m->type==RTQNAMEL) {
548         mname = strdup("<rt,l>");
549     } else if(m->type==RTQNAMELA) {
550         mname = strdup("<rt,l,attr>");
551     } else if(m->type==MULTINAME || m->type==MULTINAMEA) {
552         char*s = namespace_set_tostring(m->namespace_set);
553         mname = malloc(strlen(s)+namelen+16);
554         if(m->type == MULTINAME)
555             strcpy(mname,"<multi>");
556         else //MULTINAMEA
557             strcpy(mname,"<multi,attr>");
558         strcat(mname, s);
559         strcat(mname, "::");
560         strcat(mname, name);
561         free(s);
562     } else if(m->type==MULTINAMEL || m->type==MULTINAMELA) {
563         char*s = namespace_set_tostring(m->namespace_set);
564         mname = malloc(strlen(s)+16);
565         if(m->type == MULTINAMEL)
566             strcpy(mname,"<l,multi>");
567         else //MULTINAMELA
568             strcpy(mname,"<l,multi,attr>");
569         strcat(mname,s);
570         free(s);
571     } else {
572         return strdup("<invalid>");
573     }
574     free(name);
575     return mname;
576 }
577
578 multiname_t* multiname_fromstring(const char*name2)
579 {
580     if(!name2)
581         return 0;
582     char*n = strdup(name2);
583     char*p = strstr(n, "::");
584     char*namespace=0,*name=0;
585     if(!p) {
586         if(strchr(n, ':')) {
587             fprintf(stderr, "Error: single ':' in name\n");
588         }
589         namespace = "";
590         name = n;
591     } else {
592         *p = 0;
593         namespace = n;
594         name = p+2;
595         if(strchr(namespace, ':')) {
596             fprintf(stderr, "Error: single ':' in namespace\n");
597         }
598         if(strchr(name, ':')) {
599             fprintf(stderr, "Error: single ':' in qualified name\n");
600         }
601     }
602
603     multiname_t*m = malloc(sizeof(multiname_t));
604     memset(m, 0, sizeof(multiname_t));
605     m->type = QNAME;
606     m->namespace_set = 0;
607     m->ns = namespace_fromstring(namespace);
608     m->name = name?strdup(name):0;
609     free(n);
610     return m;
611 }
612
613 void multiname_destroy(multiname_t*m)
614 {
615     if(m) {
616         if(m->name) {
617             free((void*)m->name);m->name = 0;
618         }
619         if(m->ns) {
620             namespace_destroy(m->ns);m->ns = 0;
621         }
622         if(m->namespace_set) {
623             namespace_set_destroy(m->namespace_set);m->namespace_set = 0;
624         }
625         m->type=0;
626         free(m);
627     }
628 }
629
630 type_t multiname_type = {
631     dup: (dup_func)multiname_clone,
632     hash: (hash_func)multiname_hash,
633     free: (free_func)multiname_destroy,
634     equals: (equals_func)multiname_equals
635 };
636
637
638 // ------------------------------- constants -------------------------------------
639
640 #define UNIQUE_CONSTANT(x) ((x) == CONSTANT_TRUE || (x) == CONSTANT_FALSE || (x) == CONSTANT_NULL || (x) == CONSTANT_UNDEFINED)
641
642 constant_t* constant_new_int(int i) 
643 {
644     NEW(constant_t,c);
645     c->i = i;
646     c->type = CONSTANT_INT;
647     return c;
648 }
649 constant_t* constant_new_uint(unsigned int u)
650 {
651     NEW(constant_t,c);
652     c->u = u;
653     c->type = CONSTANT_UINT;
654     return c;
655 }
656 constant_t* constant_new_float(double f)
657 {
658     NEW(constant_t,c);
659     c->f = f;
660     c->type = CONSTANT_FLOAT;
661     return c;
662 }
663 constant_t* constant_new_string(const char*s)
664 {
665     NEW(constant_t,c);
666     c->s = string_new4(s);
667     c->type = CONSTANT_STRING;
668     return c;
669 }
670 constant_t* constant_new_string2(const char*s, int len)
671 {
672     NEW(constant_t,c);
673     c->s = string_new3(s, len);
674     c->type = CONSTANT_STRING;
675     return c;
676 }
677 constant_t* constant_new_namespace(namespace_t*ns)
678 {
679     NEW(constant_t,c);
680     c->ns = namespace_clone(ns);
681     c->type = ns->access;
682     assert(NS_TYPE(c->type));
683     return c;
684 }
685 constant_t* constant_new_true()
686 {
687     NEW(constant_t,c);
688     c->type = CONSTANT_TRUE;
689     return c;
690 }
691 constant_t* constant_new_false()
692 {
693     NEW(constant_t,c);
694     c->type = CONSTANT_FALSE;
695     return c;
696 }
697 constant_t* constant_new_null()
698 {
699     NEW(constant_t,c);
700     c->type = CONSTANT_NULL;
701     return c;
702 }
703 constant_t* constant_new_undefined()
704 {
705     NEW(constant_t,c);
706     c->type = CONSTANT_UNDEFINED;
707     return c;
708 }
709 constant_t* constant_clone(constant_t*other)
710 {
711     if(!other) return 0;
712     constant_t*c = malloc(sizeof(constant_t));
713     memcpy(c, other, sizeof(constant_t));
714     if(NS_TYPE(c->type)) {
715         c->ns = namespace_clone(other->ns);
716     } else if(c->type == CONSTANT_STRING) {
717         c->s = string_dup3(other->s);
718     }
719     return c;
720 }
721 constant_t* constant_fromindex(pool_t*pool, int index, int type)
722 {
723     if(!index) {
724         /* even for nonvalued constants (like TRUE/FALSE etc.), a nonzero
725            index is present to indicate that a type is coming */
726         return 0;
727     } 
728     NEW(constant_t,c);
729     c->type = type;
730     if(NS_TYPE(c->type)) {
731         c->ns = namespace_clone(pool_lookup_namespace(pool, index));
732     } else if(c->type == CONSTANT_INT) {
733         c->i = pool_lookup_int(pool, index);
734     } else if(c->type == CONSTANT_UINT) {
735         c->u = pool_lookup_uint(pool, index);
736     } else if(c->type == CONSTANT_FLOAT) {
737         c->f = pool_lookup_float(pool, index);
738     } else if(c->type == CONSTANT_STRING) {
739         string_t s = pool_lookup_string2(pool, index);
740         c->s = string_dup3(&s);
741     } else if(UNIQUE_CONSTANT(c->type)) {
742         // ok
743     } else {
744         fprintf(stderr, "invalid constant type %02x\n", c->type);
745     }
746     return c;
747 }
748 char* constant_tostring(constant_t*c)
749 {
750     if(!c)
751         return strdup("NULL");
752     char buf[32];
753     if(NS_TYPE(c->type)) {
754         return namespace_tostring(c->ns);
755     } else if(c->type == CONSTANT_INT) {
756         sprintf(buf, "%d", c->i);
757         return strdup(buf);
758     } else if(c->type == CONSTANT_UINT) {
759         sprintf(buf, "%u", c->u);
760         return strdup(buf);
761     } else if(c->type == CONSTANT_FLOAT) {
762         char buf[1024];
763         sprintf(buf, "%f", c->f);
764         return strdup(buf);
765     } else if(c->type == CONSTANT_STRING) {
766         /* should we escape the string? \0 bytes won't be printed */
767         return strdup_n(c->s->str,c->s->len);
768     } else if(c->type == CONSTANT_TRUE) {
769         return strdup("true");
770     } else if(c->type == CONSTANT_FALSE) {
771         return strdup("false");
772     } else if(c->type == CONSTANT_NULL) {
773         return strdup("null");
774     } else if(c->type == CONSTANT_UNDEFINED) {
775         return strdup("undefined");
776     } else {
777         fprintf(stderr, "invalid constant type %02x\n", c->type);
778         return 0;
779     }
780 }
781 char constant_has_index(constant_t*c) 
782 {
783     if(!c)
784         return 0;
785     return !UNIQUE_CONSTANT(c->type);
786 }
787 int constant_get_index(pool_t*pool, constant_t*c)
788 {
789     if(!c)
790         return 0;
791     if(NS_TYPE(c->type)) {
792         assert(c->ns);
793         /*if(c->type!=c->ns->access) {
794             printf("%02x<->%02x\n", c->type, c->ns->access);
795         }*/
796         assert(c->type == c->ns->access);
797         return pool_register_namespace(pool, c->ns);
798     } else if(c->type == CONSTANT_INT) {
799         return pool_register_int(pool, c->i);
800     } else if(c->type == CONSTANT_UINT) {
801         return pool_register_uint(pool, c->u);
802     } else if(c->type == CONSTANT_FLOAT) {
803         return pool_register_float(pool, c->f);
804     } else if(c->type == CONSTANT_STRING) {
805         return pool_register_string2(pool, c->s);
806     } else if(c->type == CONSTANT_UNDEFINED) {
807         /* write undefined with index 0 (and no type). Otherwise, the FlashPlayer 
808            seems to throw an "attempt to read out of bounds" exception */
809         return 0;
810     } else if(!constant_has_index(c)) {
811         return 1;
812     } else {
813         fprintf(stderr, "invalid constant type %02x\n", c->type);
814         return 0;
815     }
816 }
817 void constant_free(constant_t*c)
818 {
819     if(!c)
820         return;
821     if(c->type == CONSTANT_STRING) {
822         string_free(c->s);
823     } else if (NS_TYPE(c->type)) {
824         namespace_destroy(c->ns);c->ns=0;
825     }
826     free(c);
827 }
828 // --------------------------- optimizing -----------------------------------
829
830 static int array_append_or_increase(array_t*array, void*key)
831 {
832     int pos = array_find(array, key);
833     if(pos>=0) {
834         array->d[pos].data++;
835         return pos;
836     } else {
837         return array_append(array, key, 0);
838     }
839 }
840 static int compare_arrayentry(const void*_c1, const void*_c2)
841 {
842     const array_entry_t*c1 = _c1;
843     const array_entry_t*c2 = _c2;
844     return c2->data - c1->data;
845 }
846
847 static void* nodup(const void*o) {return (void*)o;}
848
849 static void reshuffle_array(array_t*array)
850 {
851     qsort(array->d+1, array->num-1, sizeof(array->d[0]), compare_arrayentry);
852     type_t* old_type = array->entry2pos->key_type;
853     type_t old_type_nodup = *old_type;
854     old_type_nodup.dup = nodup;
855     dict_t*d = dict_new2(&old_type_nodup);
856     dict_destroy_shallow(array->entry2pos);
857     array->entry2pos = d;
858     int t;
859     for(t=0;t<array->num;t++) {
860         dict_put(array->entry2pos, array->d[t].name, (void*)(ptroff_t)(t+1));
861     }
862     d->key_type = old_type;
863
864 }
865
866 // ------------------------------- pool -------------------------------------
867
868 int pool_register_uint(pool_t*p, unsigned int i)
869 {
870     int pos = array_append_or_increase(p->x_uints, &i);
871     assert(pos!=0);
872     return pos;
873 }
874 int pool_register_int(pool_t*p, int i)
875 {
876     int pos = array_append_or_increase(p->x_ints, &i);
877     assert(pos!=0);
878     return pos;
879 }
880 int pool_register_float(pool_t*p, double d)
881 {
882     int pos = array_append_or_increase(p->x_floats, &d);
883     assert(pos!=0);
884     return pos;
885 }
886 int pool_register_string(pool_t*pool, const char*str)
887 {
888     if(!str) return 0;
889     string_t s = string_new2(str);
890     int pos = array_append_or_increase(pool->x_strings, &s);
891     assert(pos!=0);
892     return pos;
893 }
894 int pool_register_string2(pool_t*pool, string_t*s)
895 {
896     if(!s || !s->str) return 0;
897     int pos = array_append_or_increase(pool->x_strings, s);
898     assert(pos!=0);
899     return pos;
900 }
901 int pool_register_namespace(pool_t*pool, namespace_t*ns)
902 {
903     if(!ns) return 0;
904     int pos = array_append_or_increase(pool->x_namespaces, ns);
905     assert(pos!=0);
906     return pos;
907 }
908 int pool_register_namespace_set(pool_t*pool, namespace_set_t*set)
909 {
910     if(!set) return 0;
911     int pos = array_append_or_increase(pool->x_namespace_sets, set);
912     assert(pos!=0);
913     return pos;
914 }
915 int pool_register_multiname(pool_t*pool, multiname_t*n)
916 {
917     if(!n) return 0;
918     int pos = array_append_or_increase(pool->x_multinames, n);
919     assert(pos!=0);
920     return pos;
921 }
922 int pool_register_multiname2(pool_t*pool, char*name)
923 {
924     if(!name) return 0;
925     multiname_t*n = multiname_fromstring(name);
926     int pos = array_append_or_increase(pool->x_multinames, n);
927     multiname_destroy(n);
928     assert(pos!=0);
929     return pos;
930 }
931
932
933 int pool_find_uint(pool_t*pool, unsigned int x)
934 {
935     int i = array_find(pool->x_uints, &x);
936     if(i<=0) {
937         fprintf(stderr, "Couldn't find uint \"%d\" in constant pool\n", x);
938         return 0;
939     }
940     return i;
941 }
942 int pool_find_int(pool_t*pool, int x)
943 {
944     int i = array_find(pool->x_ints, &x);
945     if(i<=0) {
946         fprintf(stderr, "Couldn't find int \"%d\" in constant pool\n", x);
947         return 0;
948     }
949     return i;
950 }
951 int pool_find_float(pool_t*pool, double x)
952 {
953     int i = array_find(pool->x_ints, &x);
954     if(i<=0) {
955         fprintf(stderr, "Couldn't find int \"%d\" in constant pool\n", x);
956         return 0;
957     }
958     return i;
959 }
960 int pool_find_namespace(pool_t*pool, namespace_t*ns)
961 {
962     if(!ns)
963         return 0;
964     int i = array_find(pool->x_namespaces, ns);
965     if(i<=0) {
966         char*s = namespace_tostring(ns);
967         fprintf(stderr, "Couldn't find namespace \"%s\" %08x in constant pool\n", s, ns);
968         free(s);
969         return 0;
970     }
971     return i;
972 }
973 int pool_find_namespace_set(pool_t*pool, namespace_set_t*set)
974 {
975     if(!set)
976         return 0;
977     int i = array_find(pool->x_namespace_sets, set);
978     if(i<=0) {
979         char*s = namespace_set_tostring(set);
980         fprintf(stderr, "Couldn't find namespace_set \"%s\" in constant pool\n", s);
981         free(s);
982         return 0;
983     }
984     return i;
985 }
986 int pool_find_string(pool_t*pool, const char*str)
987 {
988     if(!str)
989         return 0;
990     string_t s = string_new2(str);
991     int i = array_find(pool->x_strings, &s);
992     if(i<=0) {
993         fprintf(stderr, "Couldn't find string \"%s\" in constant pool\n", s);
994         return 0;
995     }
996     return i;
997 }
998 int pool_find_multiname(pool_t*pool, multiname_t*name)
999 {
1000     if(!name)
1001         return 0;
1002     int i = array_find(pool->x_multinames, name);
1003     if(i<=0) {
1004         char*s = multiname_tostring(name);
1005         fprintf(stderr, "Couldn't find multiname \"%s\" in constant pool\n", s);
1006         free(s);
1007         return 0;
1008     }
1009     return i;
1010 }
1011
1012 int pool_lookup_int(pool_t*pool, int i)
1013 {
1014     if(!i) return 0;
1015     return *(int*)array_getkey(pool->x_ints, i);
1016 }
1017 unsigned int pool_lookup_uint(pool_t*pool, int i)
1018 {
1019     if(!i) return 0;
1020     return *(unsigned int*)array_getkey(pool->x_uints, i);
1021 }
1022 double pool_lookup_float(pool_t*pool, int i)
1023 {
1024     if(!i) return __builtin_nan("");
1025     return *(double*)array_getkey(pool->x_floats, i);
1026 }
1027 const char*pool_lookup_string(pool_t*pool, int i)
1028 {
1029     string_t*s = array_getkey(pool->x_strings, i);
1030     if(!s) return 0;
1031     return s->str;
1032 }
1033 string_t pool_lookup_string2(pool_t*pool, int i)
1034 {
1035     string_t*s = array_getkey(pool->x_strings, i);
1036     return *s;
1037 }
1038 namespace_t*pool_lookup_namespace(pool_t*pool, int i)
1039 {
1040     return (namespace_t*)array_getkey(pool->x_namespaces, i);
1041 }
1042 namespace_set_t*pool_lookup_namespace_set(pool_t*pool, int i)
1043 {
1044     return (namespace_set_t*)array_getkey(pool->x_namespace_sets, i);
1045 }
1046 multiname_t*pool_lookup_multiname(pool_t*pool, int i)
1047 {
1048     return (multiname_t*)array_getkey(pool->x_multinames, i);
1049 }
1050
1051 pool_t*pool_new()
1052 {
1053     NEW(pool_t, p);
1054
1055     p->x_ints = array_new2(&uint_type);
1056     p->x_uints = array_new2(&uint_type);
1057     p->x_floats = array_new2(&float_type);
1058     p->x_strings = array_new2(&stringstruct_type);
1059     p->x_namespaces = array_new2(&namespace_type);
1060     p->x_namespace_sets = array_new2(&namespace_set_type);
1061     p->x_multinames = array_new2(&multiname_type);
1062
1063     /* add a zero-index entry in each list */
1064   
1065     array_append(p->x_ints, 0, 0);
1066     array_append(p->x_uints, 0, 0);
1067     array_append(p->x_floats, 0, 0);
1068     array_append(p->x_strings, 0, 0);
1069     array_append(p->x_namespaces, 0, 0);
1070     array_append(p->x_namespace_sets, 0, 0);
1071     array_append(p->x_multinames, 0, 0);
1072     return p;
1073 }
1074
1075 void pool_optimize(pool_t*p)
1076 {
1077     reshuffle_array(p->x_ints);
1078     reshuffle_array(p->x_uints);
1079     reshuffle_array(p->x_floats);
1080     reshuffle_array(p->x_strings);
1081     reshuffle_array(p->x_namespaces);
1082     reshuffle_array(p->x_namespace_sets);
1083     reshuffle_array(p->x_multinames);
1084 }
1085
1086 #define DEBUG if(0)
1087 //#define DEBUG
1088
1089 void pool_read(pool_t*pool, TAG*tag)
1090 {
1091     int num_ints = swf_GetU30(tag);
1092     DEBUG printf("%d ints\n", num_ints);
1093     int t;
1094     for(t=1;t<num_ints;t++) {
1095         S32 v = swf_GetABCS32(tag);
1096         DEBUG printf("int %d) %d\n", t, v);
1097         array_append(pool->x_ints, &v, 0);
1098     }
1099
1100     int num_uints = swf_GetU30(tag);
1101     DEBUG printf("%d uints\n", num_uints);
1102     for(t=1;t<num_uints;t++) {
1103         U32 v = swf_GetABCU32(tag);
1104         DEBUG printf("uint %d) %d\n", t, v);
1105         array_append(pool->x_uints, &v, 0);
1106     }
1107     
1108     int num_floats = swf_GetU30(tag);
1109     DEBUG printf("%d floats\n", num_floats);
1110     for(t=1;t<num_floats;t++) {
1111         double d = swf_GetD64(tag);
1112         DEBUG printf("float %d) %f\n", t, d);
1113         array_append(pool->x_floats, &d, 0);
1114     }
1115     
1116     int num_strings = swf_GetU30(tag);
1117     DEBUG printf("%d strings\n", num_strings);
1118     for(t=1;t<num_strings;t++) {
1119         int len = swf_GetU30(tag);
1120         string_t s = string_new((char*)&tag->data[tag->pos], len);
1121         swf_GetBlock(tag, 0, len);
1122         array_append(pool->x_strings, &s, 0);
1123         DEBUG printf("%d) \"%s\"\n", t, ((string_t*)array_getkey(pool->x_strings, t))->str);
1124     }
1125     int num_namespaces = swf_GetU30(tag);
1126     DEBUG printf("%d namespaces\n", num_namespaces);
1127     for(t=1;t<num_namespaces;t++) {
1128         U8 type = swf_GetU8(tag);
1129         int namenr = swf_GetU30(tag);
1130         const char*name = 0; 
1131         if(namenr)
1132             name = pool_lookup_string(pool, namenr);
1133         namespace_t*ns = namespace_new(type, name);
1134         array_append(pool->x_namespaces, ns, 0);
1135         DEBUG printf("%d) %02x \"%s\"\n", t, type, namespace_tostring(ns));
1136         namespace_destroy(ns);
1137     }
1138     int num_sets = swf_GetU30(tag);
1139     DEBUG printf("%d namespace sets\n", num_sets);
1140     for(t=1;t<num_sets;t++) {
1141         int count = swf_GetU30(tag);
1142         int s;
1143         
1144         NEW(namespace_set_t, nsset);
1145         for(s=0;s<count;s++) {
1146             int nsnr = swf_GetU30(tag);
1147             if(!nsnr)
1148                 fprintf(stderr, "Zero entry in namespace set\n");
1149             namespace_t*ns = (namespace_t*)array_getkey(pool->x_namespaces, nsnr);
1150             list_append(nsset->namespaces, namespace_clone(ns));
1151         }
1152         array_append(pool->x_namespace_sets, nsset, 0);
1153         DEBUG printf("set %d) %s\n", t, namespace_set_tostring(nsset));
1154         namespace_set_destroy(nsset);
1155     }
1156
1157     int num_multinames = swf_GetU30(tag);
1158     DEBUG printf("%d multinames\n", num_multinames);
1159     for(t=1;t<num_multinames;t++) {
1160         multiname_t m;
1161         memset(&m, 0, sizeof(multiname_t));
1162         
1163         /*int s;
1164         for(s=0;s<8;s++)
1165             printf("0x%02x ", tag->data[tag->pos+s]);
1166         printf("\n");*/
1167
1168         m.type = swf_GetU8(tag);
1169         if(m.type==0x07 || m.type==0x0d) {
1170             int namespace_index = swf_GetU30(tag);
1171             m.ns = (namespace_t*)array_getkey(pool->x_namespaces, namespace_index);
1172             if(!m.ns) {
1173                 fprintf(stderr, "Error: Illegal reference to namespace #%d in constant pool.\n", namespace_index);
1174             }
1175             int name_index = swf_GetU30(tag);
1176             if(name_index) // 0 = '*' (any)
1177                 m.name = pool_lookup_string(pool, name_index);
1178         } else if(m.type==0x0f || m.type==0x10) {
1179             int name_index = swf_GetU30(tag);
1180             if(name_index) // 0 = '*' (any name)
1181                 m.name = pool_lookup_string(pool, name_index);
1182         } else if(m.type==0x11 || m.type==0x12) {
1183         } else if(m.type==0x09 || m.type==0x0e) {
1184             int name_index = swf_GetU30(tag);
1185             int namespace_set_index = swf_GetU30(tag);
1186             if(name_index)
1187                 m.name = pool_lookup_string(pool, name_index);
1188             m.namespace_set = (namespace_set_t*)array_getkey(pool->x_namespace_sets, namespace_set_index);
1189         } else if(m.type==0x1b || m.type==0x1c) {
1190             int namespace_set_index = swf_GetU30(tag);
1191             m.namespace_set = (namespace_set_t*)array_getkey(pool->x_namespace_sets, namespace_set_index);
1192         } else if(m.type==0x1d) {
1193             int v1 = swf_GetU30(tag); //multiname
1194             int v2 = swf_GetU30(tag); //counter?
1195             int v3 = swf_GetU30(tag); //multiname
1196             // e.g. Vector<int> ... we only store the parent object
1197             m = *(multiname_t*)array_getkey(pool->x_multinames, v1);
1198         } else {
1199             printf("can't parse type %d multinames yet\n", m.type);
1200         }
1201         DEBUG printf("multiname %d) %s\n", t, multiname_tostring(&m));
1202         array_append(pool->x_multinames, &m, 0);
1203     }
1204
1205
1206 void pool_dump(pool_t*pool, FILE*fo, char flags)
1207 {
1208     int t;
1209     fprintf(fo, "%d integers\n", pool->x_ints->num);
1210     for(t=1;t<pool->x_ints->num;t++) {
1211         S32 val = *(int*)array_getkey(pool->x_ints, t);
1212         int freq = (int)(ptroff_t)array_getvalue(pool->x_ints, t);
1213         if(flags&1) fprintf(fo, "%5d %d) %d\n", freq, t, val);
1214     }
1215     fprintf(fo, "%d unsigned integers\n", pool->x_uints->num);
1216     for(t=1;t<pool->x_uints->num;t++) {
1217         U32 val = *(unsigned int*)array_getkey(pool->x_uints, t);
1218         int freq = (int)(ptroff_t)array_getvalue(pool->x_uints, t);
1219         if(flags&1) fprintf(fo, "%5d %d) %d\n", freq, t, val);
1220     }
1221     fprintf(fo, "%d floats\n", pool->x_floats->num);
1222     for(t=1;t<pool->x_floats->num;t++) {
1223         double d = pool_lookup_float(pool, t);
1224         int freq = (int)(ptroff_t)array_getvalue(pool->x_floats, t);
1225         if(flags&2) fprintf(fo, "%5d %d) %f\n", freq, t, d);
1226     }
1227     fprintf(fo, "%d strings\n", pool->x_strings->num);
1228     for(t=1;t<pool->x_strings->num;t++) {
1229         string_t str = pool_lookup_string2(pool, t);
1230         int freq = (int)(ptroff_t)array_getvalue(pool->x_strings, t);
1231         if(flags&1) fprintf(fo, "%5d %d) ", freq, t);
1232         if(flags&1) fwrite(str.str, str.len, 1, fo);
1233         if(flags&1) fprintf(fo, "\n", t);
1234     }
1235     fprintf(fo, "%d namespaces\n", pool->x_namespaces->num);
1236     for(t=1;t<pool->x_namespaces->num;t++) {
1237         namespace_t*ns= (namespace_t*)array_getkey(pool->x_namespaces, t);
1238         char*s = namespace_tostring(ns);
1239         int freq = (int)(ptroff_t)array_getvalue(pool->x_namespaces, t);
1240         if(flags&1) fprintf(fo, "%5d %d) %s\n", freq, t, s);
1241         free(s);
1242     }
1243     fprintf(fo, "%d namespace sets\n", pool->x_namespace_sets->num);
1244     for(t=1;t<pool->x_namespace_sets->num;t++) {
1245         namespace_set_t*set = (namespace_set_t*)array_getkey(pool->x_namespace_sets, t);
1246         char*s = namespace_set_tostring(set);
1247         int freq = (int)(ptroff_t)array_getvalue(pool->x_namespace_sets, t);
1248         if(flags&1) fprintf(fo, "%5d %d) %s\n", freq, t, s);
1249         free(s);
1250     }
1251
1252     fprintf(fo, "%d multinames\n", pool->x_multinames->num);
1253     for(t=1;t<pool->x_multinames->num;t++) {
1254         multiname_t*m = (multiname_t*)array_getkey(pool->x_multinames, t);
1255         char*s = multiname_tostring(m);
1256         int freq = (int)(ptroff_t)array_getvalue(pool->x_multinames, t);
1257         if(flags&1) fprintf(fo, "%5d %d) %s\n", freq, t, s);
1258         free(s);
1259     }
1260
1261
1262 void pool_write(pool_t*pool, TAG*tag)
1263 {
1264     int t;
1265     
1266     /* make sure that all namespaces used by multinames / namespace sets
1267        and all strings used by namespaces exist */
1268
1269     for(t=1;t<pool->x_multinames->num;t++) {
1270         multiname_t*m = (multiname_t*)array_getkey(pool->x_multinames, t);
1271         if(m->ns) {
1272             pool_register_namespace(pool, m->ns);
1273         }
1274         if(m->namespace_set) {
1275             pool_register_namespace_set(pool, m->namespace_set);
1276         }
1277         if(m->name) {
1278             pool_register_string(pool, m->name);
1279         }
1280     }
1281     for(t=1;t<pool->x_namespace_sets->num;t++) {
1282         namespace_set_t*set = (namespace_set_t*)array_getkey(pool->x_namespace_sets, t);
1283         namespace_list_t*i = set->namespaces;
1284         while(i) {
1285             pool_register_namespace(pool, i->namespace);
1286             i = i->next;
1287         }
1288     }
1289     for(t=1;t<pool->x_namespaces->num;t++) {
1290         namespace_t*ns= (namespace_t*)array_getkey(pool->x_namespaces, t);
1291         /*  The spec says (page 22): "a value of zero denotes an empty string".
1292             However when actually using zero strings as empty namespaces, the
1293             flash player breaks.*/
1294         //if(ns->name && ns->name[0])
1295         pool_register_string(pool, ns->name);
1296     }
1297
1298     //pool_register_int(pool, 15);
1299     //pool_register_int(pool, 1);
1300     //pool_register_int(pool, 0);
1301     
1302     /* write data */
1303     swf_SetU30(tag, pool->x_ints->num>1?pool->x_ints->num:0);
1304     for(t=1;t<pool->x_ints->num;t++) {
1305         S32 val = *(int*)array_getkey(pool->x_ints, t);
1306         swf_SetABCS32(tag, val);
1307     }
1308     swf_SetU30(tag, pool->x_uints->num>1?pool->x_uints->num:0);
1309     for(t=1;t<pool->x_uints->num;t++) {
1310         swf_SetABCU32(tag, *(unsigned int*)array_getkey(pool->x_uints, t));
1311     }
1312     swf_SetU30(tag, pool->x_floats->num>1?pool->x_floats->num:0);
1313     for(t=1;t<pool->x_floats->num;t++) {
1314         double d = pool_lookup_float(pool, t);
1315         swf_SetD64(tag, d);
1316     }
1317     swf_SetU30(tag, pool->x_strings->num>1?pool->x_strings->num:0);
1318     for(t=1;t<pool->x_strings->num;t++) {
1319         string_t str = pool_lookup_string2(pool, t);
1320         swf_SetU30String(tag, str.str, str.len);
1321     }
1322     swf_SetU30(tag, pool->x_namespaces->num>1?pool->x_namespaces->num:0);
1323     for(t=1;t<pool->x_namespaces->num;t++) {
1324         namespace_t*ns= (namespace_t*)array_getkey(pool->x_namespaces, t);
1325         swf_SetU8(tag, ns->access);
1326         const char*name = ns->name;
1327         int i = 0;
1328         
1329         //if(name && name[0])
1330         i = pool_find_string(pool, name);
1331
1332         swf_SetU30(tag, i);
1333     }
1334     swf_SetU30(tag, pool->x_namespace_sets->num>1?pool->x_namespace_sets->num:0);
1335     for(t=1;t<pool->x_namespace_sets->num;t++) {
1336         namespace_set_t*set = (namespace_set_t*)array_getkey(pool->x_namespace_sets, t);
1337         namespace_list_t*i = set->namespaces; 
1338         int len = list_length(i);
1339         swf_SetU30(tag, len);
1340         while(i) {
1341             int index = pool_find_namespace(pool, i->namespace);
1342             swf_SetU30(tag, index);
1343             i = i->next;
1344         }
1345     }
1346
1347     swf_SetU30(tag, pool->x_multinames->num>1?pool->x_multinames->num:0);
1348     for(t=1;t<pool->x_multinames->num;t++) {
1349         multiname_t*m = (multiname_t*)array_getkey(pool->x_multinames, t);
1350         swf_SetU8(tag, m->type);
1351
1352         if(m->ns) {
1353             assert(m->type==0x07 || m->type==0x0d);
1354             int i = pool_find_namespace(pool, m->ns);
1355             if(i<0) fprintf(stderr, "internal error: unregistered namespace %02x %s %s\n", m->ns->access, access2str(m->ns->access), m->ns->name);
1356             swf_SetU30(tag, i);
1357         } else {
1358             assert(m->type!=0x07 && m->type!=0x0d);
1359         }
1360         if(m->name) {
1361             assert(m->type==0x09 || m->type==0x0e || m->type==0x07 || m->type==0x0d || m->type==0x0f || m->type==0x10);
1362             int i = pool_find_string(pool, m->name);
1363             if(i<0) fprintf(stderr, "internal error: unregistered name\n");
1364             swf_SetU30(tag, i);
1365         } else {
1366             assert(m->type!=0x09 && m->type!=0x0e && m->type!=0x07 && m->type!=0x0d && m->type!=0x0f && m->type!=0x10);
1367         }
1368         if(m->namespace_set) {
1369             assert(m->type==0x09 || m->type==0x0e || m->type==0x1c || m->type==0x1b);
1370             int i = pool_find_namespace_set(pool, m->namespace_set);
1371             if(i<0) fprintf(stderr, "internal error: unregistered namespace set\n");
1372             swf_SetU30(tag, i);
1373         } else {
1374             assert(m->type!=0x09 && m->type!=0x0e && m->type!=0x1c && m->type!=0x1b);
1375         }
1376     }
1377 }
1378
1379
1380 void pool_destroy(pool_t*pool)
1381 {
1382     int t;
1383     array_free(pool->x_ints);
1384     array_free(pool->x_uints);
1385     array_free(pool->x_floats);
1386     array_free(pool->x_strings);
1387     array_free(pool->x_namespaces);
1388     array_free(pool->x_namespace_sets);
1389     array_free(pool->x_multinames);
1390     free(pool);
1391 }