added param to pool_dump, fixed bug in float comparison (NaN support)
[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=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=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]", access, s);
193
194     free(s);
195     return string;
196 }
197
198 namespace_t* namespace_clone(namespace_t*other)
199 {
200     if(!other)
201         return 0;
202     NEW(namespace_t,n);
203     n->access = other->access;
204     n->name = other->name?strdup(other->name):0;
205     return n;
206 }
207
208 namespace_t* namespace_fromstring(const char*name)
209 {
210     namespace_t*ns = malloc(sizeof(namespace_t));
211     memset(ns, 0, sizeof(namespace_t));
212     if(name[0] == '[') {
213         U8 access;
214         char*n = strdup(name);
215         char*bracket = strchr(n, ']');
216         if(bracket) {
217             *bracket = 0;
218             char*a = n+1;
219             name += (bracket-n)+1;
220             if(!strcmp(a, "")) access=0x16;
221             else if(!strcmp(a, "undefined")) access=0x08; // public??
222             else if(!strcmp(a, "package")) access=0x16;
223             else if(!strcmp(a, "public")) access=0x16;
224             else if(!strcmp(a, "packageinternal")) access=0x17;
225             else if(!strcmp(a, "protected")) access=0x18;
226             else if(!strcmp(a, "explicit")) access=0x19;
227             else if(!strcmp(a, "staticprotected")) access=0x1a;
228             else if(!strcmp(a, "private")) access=0x05;
229             else {
230                 fprintf(stderr, "Undefined access level: [%s]\n", a);
231                 free(n);
232                 return 0;
233             }
234         }
235         ns->access = access;
236         ns->name = strdup(name);
237         free(n);
238         return ns;
239     } else {
240         ns->access = 0x16;
241         ns->name = strdup(name);
242         return ns;
243     }
244 }
245
246 namespace_t* namespace_new(U8 access, const char*name)
247 {
248     namespace_t*ns = malloc(sizeof(namespace_t));
249     ns->access = access;
250     /* not sure what namespaces with empty strings are good for, but they *do* exist */
251     ns->name = name?strdup(name):0;
252     return ns;
253 }
254 namespace_t* namespace_new_undefined(const char*name) {
255     return namespace_new(0x08, name); // public?
256 }
257 namespace_t* namespace_new_package(const char*name) {
258     return namespace_new(0x16 , name);
259 }
260 namespace_t* namespace_new_packageinternal(const char*name) {
261     return namespace_new(0x17, name);
262 }
263 namespace_t* namespace_new_protected(const char*name) {
264     return namespace_new(0x18, name);
265 }
266 namespace_t* namespace_new_explicit(const char*name) {
267     return namespace_new(0x19, name);
268 }
269 namespace_t* namespace_new_staticprotected(const char*name) {
270     return namespace_new(0x1a, name);
271 }
272 namespace_t* namespace_new_private(const char*name) {
273     return namespace_new(0x05, name);
274 }
275
276 void namespace_destroy(namespace_t*n)
277 {
278     if(n) {
279         free(n->name);n->name=0;
280         n->access=0x00;
281         free(n);
282     }
283 }
284
285 type_t namespace_type = {
286     dup: (dup_func)namespace_clone,
287     hash: (hash_func)namespace_hash,
288     free: (free_func)namespace_destroy,
289     equals: (equals_func)namespace_equals
290 };
291
292 // ---------------------------namespace sets --------------------------------
293
294 unsigned int namespace_set_hash(namespace_set_t*set)
295 {
296     if(!set)
297         return 0;
298     namespace_list_t*l = set->namespaces;
299     unsigned int hash = 0;
300     while(l) {
301         hash = crc32_add_byte(hash, l->namespace->access);
302         hash = crc32_add_string(hash, l->namespace->name);
303         l = l->next;
304     }
305     return hash;
306 }
307
308 int namespace_set_equals(namespace_set_t*m1, namespace_set_t*m2)
309 {
310     if(!m1 || !m2)
311         return m1==m2;
312     namespace_list_t*l1 = m1->namespaces;
313     namespace_list_t*l2 = m2->namespaces;
314     while(l1 && l2) {
315         if(l1->namespace->access != l2->namespace->access)
316             return 0;
317         if(!(l1->namespace->name) != !(l2->namespace->name))
318             return 0;
319         if(l1->namespace->name && l2->namespace->name && strcmp(l1->namespace->name, l2->namespace->name))
320             return 0;
321         l1 = l1->next;
322         l2 = l2->next;
323     }
324     if(l1||l2)
325         return 0;
326     return 1;
327 }
328
329 namespace_set_t* namespace_set_clone(namespace_set_t*other)
330 {
331     if(!other)
332         return 0;
333     NEW(namespace_set_t,set);
334     set->namespaces = list_new();
335     namespace_list_t*l = other->namespaces;
336     while(l) {
337         list_append(set->namespaces, namespace_clone(l->namespace));
338         l = l->next;
339     }
340     return set;
341 }
342 namespace_set_t* namespace_set_new()
343 {
344     NEW(namespace_set_t,set);
345     set->namespaces = list_new();
346     return set;
347 }
348 char* namespace_set_tostring(namespace_set_t*set)
349 {
350     if(!set)
351         return strdup("NULL");
352     /* TODO: is the order of the namespaces important (does it
353        change the lookup order?). E.g. flex freely shuffles namespaces
354        around.
355        If the order is not important, we can optimize constant pools by sorting
356        the namespaces.
357     */
358     int l = 0;
359     namespace_list_t*lns = set->namespaces;
360     while(lns) {
361         char*s = namespace_tostring(lns->namespace);
362         l += strlen(s)+1;
363         free(s);
364         lns = lns->next;
365     }
366     char*desc = malloc(l+16);
367     strcpy(desc, "{");
368     lns = set->namespaces;
369     while(lns) {
370         char*s = namespace_tostring(lns->namespace);
371         strcat(desc, s);
372         free(s);
373         lns = lns->next;
374         if(lns)
375             strcat(desc, ",");
376     }
377     strcat(desc, "}");
378     return desc;
379 }
380
381 void namespace_set_destroy(namespace_set_t*set)
382 {
383     if(set) {
384         namespace_list_t*l = set->namespaces;
385         while(l) {
386             namespace_destroy(l->namespace);l->namespace=0;
387             l = l->next;
388         }
389         list_free(set->namespaces);
390         free(set);
391     }
392 }
393
394 type_t namespace_set_type = {
395     dup: (dup_func)namespace_set_clone,
396     hash: (hash_func)namespace_set_hash,
397     free: (free_func)namespace_set_destroy,
398     equals: (equals_func)namespace_set_equals
399 };
400
401 // ----------------------------- multiname ----------------------------------
402
403 unsigned int multiname_hash(multiname_t*m)
404 {
405     if(!m)
406         return 0;
407     unsigned int hash = crc32_add_byte(0, m->type);
408     if(m->name) {
409         hash = crc32_add_string(hash, m->name);
410     }
411     if(m->ns) {
412         hash = crc32_add_byte(hash, m->ns->access);
413         hash = crc32_add_string(hash, m->ns->name);
414     }
415     if(m->namespace_set) {
416         namespace_list_t*l = m->namespace_set->namespaces;
417         while(l) {
418             hash = crc32_add_byte(hash, l->namespace->access);
419             hash = crc32_add_string(hash, l->namespace->name);
420             l = l->next;
421         }
422     }
423     return hash;
424 }
425
426 int multiname_equals(multiname_t*m1, multiname_t*m2)
427 {
428     if(!m1 || !m2)
429         return m1==m2;
430     if(m1->type!=m2->type)
431         return 0;
432
433     if((!m1->name) != (!m2->name))
434         return 0;
435     if((!m1->ns) != (!m2->ns))
436         return 0;
437     if((!m1->namespace_set) != (!m2->namespace_set))
438         return 0;
439
440     if(m1->name && m2->name && strcmp(m1->name,m2->name))
441         return 0;
442     if(m1->ns && m2->ns) {
443         if(!namespace_equals(m1->ns, m2->ns))
444             return 0;
445     }
446     if(m1->namespace_set && m2->namespace_set) {
447         if(!namespace_set_equals(m1->namespace_set, m2->namespace_set))
448             return 0;
449     }
450     return 1;
451 }
452
453 multiname_t* multiname_new(namespace_t*ns, const char*name)
454 {
455     NEW(multiname_t,m);
456     m->type = QNAME;
457     if(!ns) {
458         m->ns = namespace_new_packageinternal("");
459     } else {
460         m->ns = namespace_clone(ns);
461     }
462     m->name = strdup(name);
463     return m;
464 }
465
466 multiname_t* multiname_clone(multiname_t*other)
467 {
468     if(!other)
469         return 0;
470     NEW(multiname_t,m);
471     m->type = other->type;
472     if(other->ns)
473         m->ns = namespace_clone(other->ns);
474     if(other->namespace_set)
475         m->namespace_set = namespace_set_clone(other->namespace_set);
476     if(other->name)
477         m->name = strdup(other->name);
478     return m;
479 }
480
481
482 char* access2str(int type)
483 {
484     if(type==0x08) return "namespace";
485     else if(type==0x16) return "public";
486     else if(type==0x17) return "packageinternal";
487     else if(type==0x18) return "protected";
488     else if(type==0x19) return "explicit";
489     else if(type==0x1A) return "staticprotected";
490     else if(type==0x05) return "private";
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) {
526         char*nsname = escape_string(m->ns->name);
527         mname = malloc(strlen(nsname)+namelen+32);
528         strcpy(mname, "<q");
529         if(m->type == QNAMEA)
530             strcat(mname, ",attr");
531         strcat(mname, ">[");
532         strcat(mname,access2str(m->ns->access));
533         strcat(mname, "]");
534         strcat(mname, nsname);
535         free(nsname);
536         strcat(mname, "::");
537         strcat(mname, name);
538     } else if(m->type==RTQNAME || m->type==RTQNAMEA) {
539         mname = malloc(namelen+32);
540         strcpy(mname, "<rt");
541         if(m->type == RTQNAMEA) 
542             strcat(mname, ",attr");
543         strcat(mname, ">");
544         strcat(mname, name);
545     } else if(m->type==RTQNAMEL) {
546         mname = strdup("<rt,l>");
547     } else if(m->type==RTQNAMELA) {
548         mname = strdup("<rt,l,attr>");
549     } else if(m->type==MULTINAME || m->type==MULTINAMEA) {
550         char*s = namespace_set_tostring(m->namespace_set);
551         mname = malloc(strlen(s)+namelen+16);
552         if(m->type == MULTINAME)
553             strcpy(mname,"<multi>");
554         else //MULTINAMEA
555             strcpy(mname,"<multi,attr>");
556         strcat(mname, s);
557         strcat(mname, "::");
558         strcat(mname, name);
559         free(s);
560     } else if(m->type==MULTINAMEL || m->type==MULTINAMELA) {
561         char*s = namespace_set_tostring(m->namespace_set);
562         mname = malloc(strlen(s)+16);
563         if(m->type == MULTINAMEL)
564             strcpy(mname,"<l,multi>");
565         else //MULTINAMELA
566             strcpy(mname,"<l,multi,attr>");
567         strcat(mname,s);
568         free(s);
569     } else {
570         fprintf(stderr, "Invalid multiname type: %02x\n", m->type);
571     }
572     free(name);
573     return mname;
574 }
575
576 multiname_t* multiname_fromstring(const char*name2)
577 {
578     if(!name2)
579         return 0;
580     char*n = strdup(name2);
581     char*p = strstr(n, "::");
582     char*namespace=0,*name=0;
583     if(!p) {
584         if(strchr(n, ':')) {
585             fprintf(stderr, "Error: single ':' in name\n");
586         }
587         namespace = "";
588         name = n;
589     } else {
590         *p = 0;
591         namespace = n;
592         name = p+2;
593         if(strchr(namespace, ':')) {
594             fprintf(stderr, "Error: single ':' in namespace\n");
595         }
596         if(strchr(name, ':')) {
597             fprintf(stderr, "Error: single ':' in qualified name\n");
598         }
599     }
600
601     multiname_t*m = malloc(sizeof(multiname_t));
602     memset(m, 0, sizeof(multiname_t));
603     m->type = QNAME;
604     m->namespace_set = 0;
605     m->ns = namespace_fromstring(namespace);
606     m->name = name?strdup(name):0;
607     free(n);
608     return m;
609 }
610
611 void multiname_destroy(multiname_t*m)
612 {
613     if(m) {
614         if(m->name) {
615             free((void*)m->name);m->name = 0;
616         }
617         if(m->ns) {
618             namespace_destroy(m->ns);m->ns = 0;
619         }
620         if(m->namespace_set) {
621             namespace_set_destroy(m->namespace_set);m->namespace_set = 0;
622         }
623         m->type=0;
624         free(m);
625     }
626 }
627
628 type_t multiname_type = {
629     dup: (dup_func)multiname_clone,
630     hash: (hash_func)multiname_hash,
631     free: (free_func)multiname_destroy,
632     equals: (equals_func)multiname_equals
633 };
634
635
636 // ------------------------------- constants -------------------------------------
637
638 #define NS_TYPE(x) ((x) == 0x08 || (x) == 0x16 || (x) == 0x17 || (x) == 0x18 ||  \
639                                    (x) == 0x19 || (x) == 0x1a || (x) == 0x05)
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(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_fromindex(pool_t*pool, int index, int type)
711 {
712     if(!index) {
713         /* even for nonvalued constants (like TRUE/FALSE etc.), a nonzero
714            index is present to indicate that a type is coming */
715         return 0;
716     } 
717     NEW(constant_t,c);
718     c->type = type;
719     if(NS_TYPE(c->type)) {
720         c->ns = namespace_clone(pool_lookup_namespace(pool, index));
721     } else if(c->type == CONSTANT_INT) {
722         c->i = pool_lookup_int(pool, index);
723     } else if(c->type == CONSTANT_UINT) {
724         c->u = pool_lookup_uint(pool, index);
725     } else if(c->type == CONSTANT_FLOAT) {
726         c->f = pool_lookup_float(pool, index);
727     } else if(c->type == CONSTANT_STRING) {
728         string_t s = pool_lookup_string2(pool, index);
729         c->s = string_dup3(&s);
730     } else if(UNIQUE_CONSTANT(c->type)) {
731         // ok
732     } else {
733         fprintf(stderr, "invalid constant type %02x\n", c->type);
734     }
735     return c;
736 }
737 char* constant_tostring(constant_t*c)
738 {
739     if(!c)
740         return strdup("NULL");
741     char buf[32];
742     if(NS_TYPE(c->type)) {
743         return namespace_tostring(c->ns);
744     } else if(c->type == CONSTANT_INT) {
745         sprintf(buf, "%d", c->i);
746         return strdup(buf);
747     } else if(c->type == CONSTANT_UINT) {
748         sprintf(buf, "%u", c->u);
749         return strdup(buf);
750     } else if(c->type == CONSTANT_FLOAT) {
751         char buf[1024];
752         sprintf(buf, "%f", c->f);
753         return strdup(buf);
754     } else if(c->type == CONSTANT_STRING) {
755         /* should we escape the string? \0 bytes won't be printed */
756         return strdup_n(c->s->str,c->s->len);
757     } else if(c->type == CONSTANT_TRUE) {
758         return strdup("true");
759     } else if(c->type == CONSTANT_FALSE) {
760         return strdup("false");
761     } else if(c->type == CONSTANT_NULL) {
762         return strdup("null");
763     } else if(c->type == CONSTANT_UNDEFINED) {
764         return strdup("undefined");
765     } else {
766         fprintf(stderr, "invalid constant type %02x\n", c->type);
767         return 0;
768     }
769 }
770 char constant_has_index(constant_t*c) 
771 {
772     if(!c)
773         return 0;
774     return !UNIQUE_CONSTANT(c->type);
775 }
776 int constant_get_index(pool_t*pool, constant_t*c)
777 {
778     if(!c)
779         return 0;
780     if(NS_TYPE(c->type)) {
781         assert(c->ns);
782         /*if(c->type!=c->ns->access) {
783             printf("%02x<->%02x\n", c->type, c->ns->access);
784         }*/
785         assert(c->type == c->ns->access);
786         return pool_register_namespace(pool, c->ns);
787     } else if(c->type == CONSTANT_INT) {
788         return pool_register_int(pool, c->i);
789     } else if(c->type == CONSTANT_UINT) {
790         return pool_register_uint(pool, c->u);
791     } else if(c->type == CONSTANT_FLOAT) {
792         return pool_register_float(pool, c->f);
793     } else if(c->type == CONSTANT_STRING) {
794         return pool_register_string2(pool, c->s);
795     } else if(!constant_has_index(c)) {
796         return 1;
797     } else {
798         fprintf(stderr, "invalid constant type %02x\n", c->type);
799         return 0;
800     }
801 }
802 void constant_free(constant_t*c)
803 {
804     if(!c)
805         return;
806     if(c->type == CONSTANT_STRING) {
807         string_free(c->s);
808     } else if (NS_TYPE(c->type)) {
809         namespace_destroy(c->ns);c->ns=0;
810     }
811     free(c);
812 }
813 // ------------------------------- pool -------------------------------------
814
815 int pool_register_uint(pool_t*p, unsigned int i)
816 {
817     int pos = array_append_if_new(p->x_uints, &i, 0);
818     assert(pos!=0);
819     return pos;
820 }
821 int pool_register_int(pool_t*p, int i)
822 {
823     int pos = array_append_if_new(p->x_ints, &i, 0);
824     assert(pos!=0);
825     return pos;
826 }
827 int pool_register_float(pool_t*p, double d)
828 {
829     int pos = array_append_if_new(p->x_floats, &d, 0);
830     assert(pos!=0);
831     return pos;
832 }
833 int pool_register_string(pool_t*pool, const char*str)
834 {
835     if(!str) return 0;
836     string_t s = string_new2(str);
837     int pos = array_append_if_new(pool->x_strings, &s, 0);
838     assert(pos!=0);
839     return pos;
840 }
841 int pool_register_string2(pool_t*pool, string_t*s)
842 {
843     if(!s || !s->str) return 0;
844     int pos = array_append_if_new(pool->x_strings, s, 0);
845     assert(pos!=0);
846     return pos;
847 }
848 int pool_register_namespace(pool_t*pool, namespace_t*ns)
849 {
850     if(!ns) return 0;
851     int pos = array_append_if_new(pool->x_namespaces, ns, 0);
852     assert(pos!=0);
853     return pos;
854 }
855 int pool_register_namespace_set(pool_t*pool, namespace_set_t*set)
856 {
857     if(!set) return 0;
858     int pos = array_append_if_new(pool->x_namespace_sets, set, 0);
859     assert(pos!=0);
860     return pos;
861 }
862 int pool_register_multiname(pool_t*pool, multiname_t*n)
863 {
864     if(!n) return 0;
865     int pos = array_append_if_new(pool->x_multinames, n, 0);
866     assert(pos!=0);
867     return pos;
868 }
869 int pool_register_multiname2(pool_t*pool, char*name)
870 {
871     if(!name) return 0;
872     multiname_t*n = multiname_fromstring(name);
873     int pos = array_append_if_new(pool->x_multinames, n, 0);
874     multiname_destroy(n);
875     assert(pos!=0);
876     return pos;
877 }
878
879
880 int pool_find_uint(pool_t*pool, unsigned int x)
881 {
882     int i = array_find(pool->x_uints, &x);
883     if(i<=0) {
884         fprintf(stderr, "Couldn't find uint \"%d\" in constant pool\n", x);
885         return 0;
886     }
887     return i;
888 }
889 int pool_find_int(pool_t*pool, int x)
890 {
891     int i = array_find(pool->x_ints, &x);
892     if(i<=0) {
893         fprintf(stderr, "Couldn't find int \"%d\" in constant pool\n", x);
894         return 0;
895     }
896     return i;
897 }
898 int pool_find_float(pool_t*pool, double x)
899 {
900     int i = array_find(pool->x_ints, &x);
901     if(i<=0) {
902         fprintf(stderr, "Couldn't find int \"%d\" in constant pool\n", x);
903         return 0;
904     }
905     return i;
906 }
907 int pool_find_namespace(pool_t*pool, namespace_t*ns)
908 {
909     if(!ns)
910         return 0;
911     int i = array_find(pool->x_namespaces, ns);
912     if(i<=0) {
913         char*s = namespace_tostring(ns);
914         fprintf(stderr, "Couldn't find namespace \"%s\" %08x in constant pool\n", s, ns);
915         free(s);
916         return 0;
917     }
918     return i;
919 }
920 int pool_find_namespace_set(pool_t*pool, namespace_set_t*set)
921 {
922     if(!set)
923         return 0;
924     int i = array_find(pool->x_namespace_sets, set);
925     if(i<=0) {
926         char*s = namespace_set_tostring(set);
927         fprintf(stderr, "Couldn't find namespace_set \"%s\" in constant pool\n", s);
928         free(s);
929         return 0;
930     }
931     return i;
932 }
933 int pool_find_string(pool_t*pool, const char*str)
934 {
935     if(!str)
936         return 0;
937     string_t s = string_new2(str);
938     int i = array_find(pool->x_strings, &s);
939     if(i<=0) {
940         fprintf(stderr, "Couldn't find string \"%s\" in constant pool\n", s);
941         return 0;
942     }
943     return i;
944 }
945 int pool_find_multiname(pool_t*pool, multiname_t*name)
946 {
947     if(!name)
948         return 0;
949     int i = array_find(pool->x_multinames, name);
950     if(i<=0) {
951         char*s = multiname_tostring(name);
952         fprintf(stderr, "Couldn't find multiname \"%s\" in constant pool\n", s);
953         free(s);
954         return 0;
955     }
956     return i;
957 }
958
959 int pool_lookup_int(pool_t*pool, int i)
960 {
961     if(!i) return 0;
962     return *(int*)array_getkey(pool->x_ints, i);
963 }
964 unsigned int pool_lookup_uint(pool_t*pool, int i)
965 {
966     if(!i) return 0;
967     return *(unsigned int*)array_getkey(pool->x_uints, i);
968 }
969 double pool_lookup_float(pool_t*pool, int i)
970 {
971     if(!i) return __builtin_nan("");
972     return *(double*)array_getkey(pool->x_floats, i);
973 }
974 const char*pool_lookup_string(pool_t*pool, int i)
975 {
976     string_t*s = array_getkey(pool->x_strings, i);
977     if(!s) return 0;
978     return s->str;
979 }
980 string_t pool_lookup_string2(pool_t*pool, int i)
981 {
982     string_t*s = array_getkey(pool->x_strings, i);
983     return *s;
984 }
985 namespace_t*pool_lookup_namespace(pool_t*pool, int i)
986 {
987     return (namespace_t*)array_getkey(pool->x_namespaces, i);
988 }
989 namespace_set_t*pool_lookup_namespace_set(pool_t*pool, int i)
990 {
991     return (namespace_set_t*)array_getkey(pool->x_namespace_sets, i);
992 }
993 multiname_t*pool_lookup_multiname(pool_t*pool, int i)
994 {
995     return (multiname_t*)array_getkey(pool->x_multinames, i);
996 }
997
998 pool_t*pool_new()
999 {
1000     NEW(pool_t, p);
1001
1002     p->x_ints = array_new2(&uint_type);
1003     p->x_uints = array_new2(&uint_type);
1004     p->x_floats = array_new2(&float_type);
1005     p->x_strings = array_new2(&stringstruct_type);
1006     p->x_namespaces = array_new2(&namespace_type);
1007     p->x_namespace_sets = array_new2(&namespace_set_type);
1008     p->x_multinames = array_new2(&multiname_type);
1009
1010     /* add a zero-index entry in each list */
1011   
1012     array_append(p->x_ints, 0, 0);
1013     array_append(p->x_uints, 0, 0);
1014     array_append(p->x_floats, 0, 0);
1015     array_append(p->x_strings, 0, 0);
1016     array_append(p->x_namespaces, 0, 0);
1017     array_append(p->x_namespace_sets, 0, 0);
1018     array_append(p->x_multinames, 0, 0);
1019     return p;
1020 }
1021
1022 #define DEBUG if(0)
1023 //#define DEBUG
1024
1025 void pool_read(pool_t*pool, TAG*tag)
1026 {
1027     int num_ints = swf_GetU30(tag);
1028     DEBUG printf("%d ints\n", num_ints);
1029     int t;
1030     for(t=1;t<num_ints;t++) {
1031         S32 v = swf_GetABCS32(tag);
1032         DEBUG printf("int %d) %d\n", t, v);
1033         array_append(pool->x_ints, &v, 0);
1034     }
1035
1036     int num_uints = swf_GetU30(tag);
1037     DEBUG printf("%d uints\n", num_uints);
1038     for(t=1;t<num_uints;t++) {
1039         U32 v = swf_GetABCU32(tag);
1040         DEBUG printf("uint %d) %d\n", t, v);
1041         array_append(pool->x_uints, &v, 0);
1042     }
1043     
1044     int num_floats = swf_GetU30(tag);
1045     DEBUG printf("%d floats\n", num_floats);
1046     for(t=1;t<num_floats;t++) {
1047         double d = swf_GetD64(tag);
1048         DEBUG printf("float %d) %f\n", t, d);
1049         array_append(pool->x_floats, &d, 0);
1050     }
1051     
1052     int num_strings = swf_GetU30(tag);
1053     DEBUG printf("%d strings\n", num_strings);
1054     for(t=1;t<num_strings;t++) {
1055         int len = swf_GetU30(tag);
1056         string_t s = string_new(&tag->data[tag->pos], len);
1057         swf_GetBlock(tag, 0, len);
1058         array_append(pool->x_strings, &s, 0);
1059         DEBUG printf("%d) \"%s\"\n", t, ((string_t*)array_getkey(pool->x_strings, t))->str);
1060     }
1061     int num_namespaces = swf_GetU30(tag);
1062     DEBUG printf("%d namespaces\n", num_namespaces);
1063     for(t=1;t<num_namespaces;t++) {
1064         U8 type = swf_GetU8(tag);
1065         int namenr = swf_GetU30(tag);
1066         const char*name = 0; 
1067         if(namenr)
1068             name = pool_lookup_string(pool, namenr);
1069         namespace_t*ns = namespace_new(type, name);
1070         array_append(pool->x_namespaces, ns, 0);
1071         DEBUG printf("%d) %02x \"%s\"\n", t, type, namespace_tostring(ns));
1072         namespace_destroy(ns);
1073     }
1074     int num_sets = swf_GetU30(tag);
1075     DEBUG printf("%d namespace sets\n", num_sets);
1076     for(t=1;t<num_sets;t++) {
1077         int count = swf_GetU30(tag);
1078         int s;
1079         
1080         NEW(namespace_set_t, nsset);
1081         for(s=0;s<count;s++) {
1082             int nsnr = swf_GetU30(tag);
1083             if(!nsnr)
1084                 fprintf(stderr, "Zero entry in namespace set\n");
1085             namespace_t*ns = (namespace_t*)array_getkey(pool->x_namespaces, nsnr);
1086             list_append(nsset->namespaces, namespace_clone(ns));
1087         }
1088         array_append(pool->x_namespace_sets, nsset, 0);
1089         DEBUG printf("set %d) %s\n", t, namespace_set_tostring(nsset));
1090         namespace_set_destroy(nsset);
1091     }
1092
1093     int num_multinames = swf_GetU30(tag);
1094     DEBUG printf("%d multinames\n", num_multinames);
1095     for(t=1;t<num_multinames;t++) {
1096         multiname_t m;
1097         memset(&m, 0, sizeof(multiname_t));
1098         m.type = swf_GetU8(tag);
1099         if(m.type==0x07 || m.type==0x0d) {
1100             int namespace_index = swf_GetU30(tag);
1101             m.ns = (namespace_t*)array_getkey(pool->x_namespaces, namespace_index);
1102             int name_index = swf_GetU30(tag);
1103             if(name_index) // 0 = '*' (any)
1104                 m.name = pool_lookup_string(pool, name_index);
1105         } else if(m.type==0x0f || m.type==0x10) {
1106             int name_index = swf_GetU30(tag);
1107             if(name_index) // 0 = '*' (any name)
1108                 m.name = pool_lookup_string(pool, name_index);
1109         } else if(m.type==0x11 || m.type==0x12) {
1110         } else if(m.type==0x09 || m.type==0x0e) {
1111             int name_index = swf_GetU30(tag);
1112             int namespace_set_index = swf_GetU30(tag);
1113             if(name_index)
1114                 m.name = pool_lookup_string(pool, name_index);
1115             m.namespace_set = (namespace_set_t*)array_getkey(pool->x_namespace_sets, namespace_set_index);
1116         } else if(m.type==0x1b || m.type==0x1c) {
1117             int namespace_set_index = swf_GetU30(tag);
1118             m.namespace_set = (namespace_set_t*)array_getkey(pool->x_namespace_sets, namespace_set_index);
1119         } else {
1120             printf("can't parse type %d multinames yet\n", m.type);
1121         }
1122         DEBUG printf("multiname %d) %s\n", t, multiname_tostring(&m));
1123         array_append(pool->x_multinames, &m, 0);
1124     }
1125
1126
1127 void pool_dump(pool_t*pool, FILE*fo, char flags)
1128 {
1129     int t;
1130     fprintf(fo, "%d integers:\n", pool->x_ints->num);
1131     for(t=1;t<pool->x_ints->num;t++) {
1132         S32 val = *(int*)array_getkey(pool->x_ints, t);
1133         if(flags&1) fprintf(fo, "%d) %d\n", t, val);
1134     }
1135     fprintf(fo, "%d unsigned integers:\n", pool->x_uints->num);
1136     for(t=1;t<pool->x_uints->num;t++) {
1137         U32 val = *(unsigned int*)array_getkey(pool->x_uints, t);
1138         if(flags&1) fprintf(fo, "%d) %d\n", t, val);
1139     }
1140     fprintf(fo, "%d floats:\n", pool->x_floats->num);
1141     for(t=1;t<pool->x_floats->num;t++) {
1142         double d = pool_lookup_float(pool, t);
1143         if(flags&2) fprintf(fo, "%d) %f\n", t, d);
1144     }
1145     fprintf(fo, "%d strings:\n", pool->x_strings->num);
1146     for(t=1;t<pool->x_strings->num;t++) {
1147         string_t str = pool_lookup_string2(pool, t);
1148         if(flags&1) fprintf(fo, "%d) ", t);
1149         if(flags&1) fwrite(str.str, str.len, 1, fo);
1150         if(flags&1) fprintf(fo, "\n", t);
1151     }
1152     fprintf(fo, "%d namespaces:\n", pool->x_namespaces->num);
1153     for(t=1;t<pool->x_namespaces->num;t++) {
1154         namespace_t*ns= (namespace_t*)array_getkey(pool->x_namespaces, t);
1155         char*s = namespace_tostring(ns);
1156         if(flags&1) fprintf(fo, "%d) %s\n", t, s);
1157         free(s);
1158     }
1159     fprintf(fo, "%d namespace sets:\n", pool->x_namespace_sets->num);
1160     for(t=1;t<pool->x_namespace_sets->num;t++) {
1161         namespace_set_t*set = (namespace_set_t*)array_getkey(pool->x_namespace_sets, t);
1162         char*s = namespace_set_tostring(set);
1163         if(flags&1) fprintf(fo, "%d) %s\n", t, s);
1164         free(s);
1165     }
1166
1167     fprintf(fo, "%d multinames:\n", pool->x_multinames->num);
1168     for(t=1;t<pool->x_multinames->num;t++) {
1169         multiname_t*m = (multiname_t*)array_getkey(pool->x_multinames, t);
1170         char*s = multiname_tostring(m);
1171         if(flags&1) fprintf(fo, "%d) %s\n", t, s);
1172         free(s);
1173     }
1174
1175
1176 void pool_write(pool_t*pool, TAG*tag)
1177 {
1178     int t;
1179     
1180     /* make sure that all namespaces used by multinames / namespace sets
1181        and all strings used by namespaces exist */
1182
1183     for(t=1;t<pool->x_multinames->num;t++) {
1184         multiname_t*m = (multiname_t*)array_getkey(pool->x_multinames, t);
1185         if(m->ns) {
1186             pool_register_namespace(pool, m->ns);
1187         }
1188         if(m->namespace_set) {
1189             pool_register_namespace_set(pool, m->namespace_set);
1190         }
1191         if(m->name) {
1192             pool_register_string(pool, m->name);
1193         }
1194     }
1195     for(t=1;t<pool->x_namespace_sets->num;t++) {
1196         namespace_set_t*set = (namespace_set_t*)array_getkey(pool->x_namespace_sets, t);
1197         namespace_list_t*i = set->namespaces;
1198         while(i) {
1199             pool_register_namespace(pool, i->namespace);
1200             i = i->next;
1201         }
1202     }
1203     for(t=1;t<pool->x_namespaces->num;t++) {
1204         namespace_t*ns= (namespace_t*)array_getkey(pool->x_namespaces, t);
1205         /*  The spec says (page 22): "a value of zero denotes an empty string".
1206             However when actually using zero strings as empty namespaces, the
1207             flash player breaks.*/
1208         //if(ns->name && ns->name[0])
1209         pool_register_string(pool, ns->name);
1210     }
1211
1212     //pool_register_int(pool, 15);
1213     //pool_register_int(pool, 1);
1214     //pool_register_int(pool, 0);
1215     
1216     /* write data */
1217     swf_SetU30(tag, pool->x_ints->num>1?pool->x_ints->num:0);
1218     for(t=1;t<pool->x_ints->num;t++) {
1219         S32 val = *(int*)array_getkey(pool->x_ints, t);
1220         swf_SetABCS32(tag, val);
1221     }
1222     swf_SetU30(tag, pool->x_uints->num>1?pool->x_uints->num:0);
1223     for(t=1;t<pool->x_uints->num;t++) {
1224         swf_SetABCU32(tag, *(unsigned int*)array_getkey(pool->x_uints, t));
1225     }
1226     swf_SetU30(tag, pool->x_floats->num>1?pool->x_floats->num:0);
1227     for(t=1;t<pool->x_floats->num;t++) {
1228         double d = pool_lookup_float(pool, t);
1229         swf_SetD64(tag, d);
1230     }
1231     swf_SetU30(tag, pool->x_strings->num>1?pool->x_strings->num:0);
1232     for(t=1;t<pool->x_strings->num;t++) {
1233         string_t str = pool_lookup_string2(pool, t);
1234         swf_SetU30String(tag, str.str, str.len);
1235     }
1236     swf_SetU30(tag, pool->x_namespaces->num>1?pool->x_namespaces->num:0);
1237     for(t=1;t<pool->x_namespaces->num;t++) {
1238         namespace_t*ns= (namespace_t*)array_getkey(pool->x_namespaces, t);
1239         swf_SetU8(tag, ns->access);
1240         const char*name = ns->name;
1241         int i = 0;
1242         
1243         //if(name && name[0])
1244         i = pool_find_string(pool, name);
1245
1246         swf_SetU30(tag, i);
1247     }
1248     swf_SetU30(tag, pool->x_namespace_sets->num>1?pool->x_namespace_sets->num:0);
1249     for(t=1;t<pool->x_namespace_sets->num;t++) {
1250         namespace_set_t*set = (namespace_set_t*)array_getkey(pool->x_namespace_sets, t);
1251         namespace_list_t*i = set->namespaces; 
1252         int len = list_length(i);
1253         swf_SetU30(tag, len);
1254         while(i) {
1255             int index = pool_find_namespace(pool, i->namespace);
1256             swf_SetU30(tag, index);
1257             i = i->next;
1258         }
1259     }
1260
1261     swf_SetU30(tag, pool->x_multinames->num>1?pool->x_multinames->num:0);
1262     for(t=1;t<pool->x_multinames->num;t++) {
1263         multiname_t*m = (multiname_t*)array_getkey(pool->x_multinames, t);
1264         swf_SetU8(tag, m->type);
1265
1266         if(m->ns) {
1267             assert(m->type==0x07 || m->type==0x0d);
1268             int i = pool_find_namespace(pool, m->ns);
1269             if(i<0) fprintf(stderr, "internal error: unregistered namespace %02x %s %s\n", m->ns->access, access2str(m->ns->access), m->ns->name);
1270             swf_SetU30(tag, i);
1271         } else {
1272             assert(m->type!=0x07 && m->type!=0x0d);
1273         }
1274         if(m->name) {
1275             assert(m->type==0x09 || m->type==0x0e || m->type==0x07 || m->type==0x0d || m->type==0x0f || m->type==0x10);
1276             int i = pool_find_string(pool, m->name);
1277             if(i<0) fprintf(stderr, "internal error: unregistered name\n");
1278             swf_SetU30(tag, i);
1279         } else {
1280             assert(m->type!=0x09 && m->type!=0x0e && m->type!=0x07 && m->type!=0x0d && m->type!=0x0f && m->type!=0x10);
1281         }
1282         if(m->namespace_set) {
1283             assert(m->type==0x09 || m->type==0x0e || m->type==0x1c || m->type==0x1b);
1284             int i = pool_find_namespace_set(pool, m->namespace_set);
1285             if(i<0) fprintf(stderr, "internal error: unregistered namespace set\n");
1286             swf_SetU30(tag, i);
1287         } else {
1288             assert(m->type!=0x09 && m->type!=0x0e && m->type!=0x1c && m->type!=0x1b);
1289         }
1290     }
1291 }
1292
1293
1294 void pool_destroy(pool_t*pool)
1295 {
1296     int t;
1297     array_free(pool->x_ints);
1298     array_free(pool->x_uints);
1299     array_free(pool->x_floats);
1300     array_free(pool->x_strings);
1301     array_free(pool->x_namespaces);
1302     array_free(pool->x_namespace_sets);
1303     array_free(pool->x_multinames);
1304     free(pool);
1305 }