renamed to_string to tostring
[swftools.git] / lib / as3 / pool.c
index 77f401e..ffea0e6 100644 (file)
@@ -172,7 +172,7 @@ char*escape_string(const char*str)
     return newstr;
 }
 
-char* namespace_to_string(namespace_t*ns)
+char* namespace_tostring(namespace_t*ns)
 {
     if(!ns)
         return strdup("NULL");
@@ -335,7 +335,7 @@ namespace_set_t* namespace_set_new()
     set->namespaces = list_new();
     return set;
 }
-char* namespace_set_to_string(namespace_set_t*set)
+char* namespace_set_tostring(namespace_set_t*set)
 {
     if(!set)
         return strdup("NULL");
@@ -348,7 +348,7 @@ char* namespace_set_to_string(namespace_set_t*set)
     int l = 0;
     namespace_list_t*lns = set->namespaces;
     while(lns) {
-        char*s = namespace_to_string(lns->namespace);
+        char*s = namespace_tostring(lns->namespace);
         l += strlen(s)+1;
         free(s);
         lns = lns->next;
@@ -357,7 +357,7 @@ char* namespace_set_to_string(namespace_set_t*set)
     strcpy(desc, "{");
     lns = set->namespaces;
     while(lns) {
-        char*s = namespace_to_string(lns->namespace);
+        char*s = namespace_tostring(lns->namespace);
         strcat(desc, s);
         free(s);
         lns = lns->next;
@@ -444,7 +444,11 @@ multiname_t* multiname_new(namespace_t*ns, const char*name)
 {
     NEW(multiname_t,m);
     m->type = QNAME;
-    m->ns = namespace_clone(ns);
+    if(!ns) {
+        m->ns = namespace_new_packageinternal("");
+    } else {
+        m->ns = namespace_clone(ns);
+    }
     m->name = strdup(name);
     return m;
 }
@@ -497,7 +501,7 @@ char multiname_late_name(multiname_t*m)
            m->type==MULTINAMEL || m->type==MULTINAMELA;
 }
 
-char* multiname_to_string(multiname_t*m)
+char* multiname_tostring(multiname_t*m)
 {
     char*mname = 0;
     if(!m)
@@ -533,7 +537,7 @@ char* multiname_to_string(multiname_t*m)
     } else if(m->type==RTQNAMELA) {
         mname = strdup("<rt,l,attr>");
     } else if(m->type==MULTINAME || m->type==MULTINAMEA) {
-        char*s = namespace_set_to_string(m->namespace_set);
+        char*s = namespace_set_tostring(m->namespace_set);
         mname = malloc(strlen(s)+namelen+16);
         if(m->type == MULTINAME)
             strcpy(mname,"<multi>");
@@ -544,7 +548,7 @@ char* multiname_to_string(multiname_t*m)
         strcat(mname, name);
         free(s);
     } else if(m->type==MULTINAMEL || m->type==MULTINAMELA) {
-        char*s = namespace_set_to_string(m->namespace_set);
+        char*s = namespace_set_tostring(m->namespace_set);
         mname = malloc(strlen(s)+16);
         if(m->type == MULTINAMEL)
             strcpy(mname,"<l,multi>");
@@ -617,6 +621,174 @@ type_t multiname_type = {
     equals: (equals_func)multiname_equals
 };
 
+
+// ------------------------------- constants -------------------------------------
+
+#define NS_TYPE(x) ((x) == 0x08 || (x) == 0x16 || (x) == 0x17 || (x) == 0x18 ||  \
+                                   (x) == 0x19 || (x) == 0x1a || (x) == 0x05)
+
+#define UNIQUE_CONSTANT(x) ((x) == CONSTANT_TRUE || (x) == CONSTANT_FALSE || (x) == CONSTANT_NULL || (x) == CONSTANT_UNDEFINED)
+
+constant_t* constant_new_int(int i) 
+{
+    NEW(constant_t,c);
+    c->i = i;
+    c->type = CONSTANT_INT;
+    return c;
+}
+constant_t* constant_new_uint(unsigned int u)
+{
+    NEW(constant_t,c);
+    c->u = u;
+    c->type = CONSTANT_UINT;
+    return c;
+}
+constant_t* constant_new_float(double f)
+{
+    NEW(constant_t,c);
+    c->f = f;
+    c->type = CONSTANT_FLOAT;
+    return c;
+}
+constant_t* constant_new_string(char*s)
+{
+    NEW(constant_t,c);
+    c->s = strdup(s);
+    c->type = CONSTANT_STRING;
+    return c;
+}
+constant_t* constant_new_namespace(namespace_t*ns)
+{
+    NEW(constant_t,c);
+    c->ns = namespace_clone(ns);
+    c->type = ns->access;
+    assert(NS_TYPE(c->type));
+    return c;
+}
+constant_t* constant_new_true()
+{
+    NEW(constant_t,c);
+    c->type = CONSTANT_TRUE;
+    return c;
+}
+constant_t* constant_new_false()
+{
+    NEW(constant_t,c);
+    c->type = CONSTANT_FALSE;
+    return c;
+}
+constant_t* constant_new_null()
+{
+    NEW(constant_t,c);
+    c->type = CONSTANT_NULL;
+    return c;
+}
+constant_t* constant_new_undefined()
+{
+    NEW(constant_t,c);
+    c->type = CONSTANT_UNDEFINED;
+    return c;
+}
+constant_t* constant_fromindex(pool_t*pool, int index, int type)
+{
+    if(!index) {
+        /* even for nonvalued constants (like TRUE/FALSE etc.), a nonzero
+           index is present to indicate that a type is coming */
+        return 0;
+    } 
+    NEW(constant_t,c);
+    c->type = type;
+    if(NS_TYPE(c->type)) {
+        c->ns = namespace_clone(pool_lookup_namespace(pool, index));
+    } else if(c->type == CONSTANT_INT) {
+        c->i = pool_lookup_int(pool, index);
+    } else if(c->type == CONSTANT_UINT) {
+        c->u = pool_lookup_uint(pool, index);
+    } else if(c->type == CONSTANT_FLOAT) {
+        c->f = pool_lookup_float(pool, index);
+    } else if(c->type == CONSTANT_STRING) {
+        c->s = strdup(pool_lookup_string(pool, index));
+    } else if(UNIQUE_CONSTANT(c->type)) {
+        // ok
+    } else {
+        fprintf(stderr, "invalid constant type %02x\n", c->type);
+    }
+    return c;
+}
+char* constant_tostring(constant_t*c)
+{
+    if(!c)
+        return 0;
+    char buf[30];
+    if(NS_TYPE(c->type)) {
+        return namespace_tostring(c->ns);
+    } else if(c->type == CONSTANT_INT) {
+        sprintf(buf, "%d", c->i);
+        return strdup(buf);
+    } else if(c->type == CONSTANT_UINT) {
+        sprintf(buf, "%u", c->u);
+        return strdup(buf);
+    } else if(c->type == CONSTANT_FLOAT) {
+        sprintf(buf, "%f", c->f);
+        return strdup(buf);
+    } else if(c->type == CONSTANT_STRING) {
+        return strdup(c->s);
+    } else if(c->type == CONSTANT_TRUE) {
+        return strdup("true");
+    } else if(c->type == CONSTANT_FALSE) {
+        return strdup("false");
+    } else if(c->type == CONSTANT_NULL) {
+        return strdup("null");
+    } else if(c->type == CONSTANT_UNDEFINED) {
+        return strdup("undefined");
+    } else {
+        fprintf(stderr, "invalid constant type %02x\n", c->type);
+        return 0;
+    }
+}
+char constant_has_index(constant_t*c) 
+{
+    if(!c)
+        return 0;
+    return !UNIQUE_CONSTANT(c->type);
+}
+int constant_get_index(pool_t*pool, constant_t*c)
+{
+    if(!c)
+        return 0;
+    if(NS_TYPE(c->type)) {
+        assert(c->ns);
+        /*if(c->type!=c->ns->access) {
+            printf("%02x<->%02x\n", c->type, c->ns->access);
+        }*/
+        assert(c->type == c->ns->access);
+        return pool_register_namespace(pool, c->ns);
+    } else if(c->type == CONSTANT_INT) {
+        return pool_register_int(pool, c->i);
+    } else if(c->type == CONSTANT_UINT) {
+        return pool_register_uint(pool, c->u);
+    } else if(c->type == CONSTANT_FLOAT) {
+        return pool_register_float(pool, c->f);
+    } else if(c->type == CONSTANT_STRING) {
+        return pool_register_string(pool, c->s);
+    } else if(!constant_has_index(c)) {
+        return 1;
+    } else {
+        fprintf(stderr, "invalid constant type %02x\n", c->type);
+        return 0;
+    }
+}
+void constant_free(constant_t*c)
+{
+    if(!c)
+        return;
+    if(c->type == CONSTANT_STRING) {
+        free(c->s);c->s=0;
+    } else if (NS_TYPE(c->type)) {
+        namespace_destroy(c->ns);c->ns=0;
+    }
+    free(c);
+}
 // ------------------------------- pool -------------------------------------
 
 int pool_register_uint(pool_t*p, unsigned int i)
@@ -712,7 +884,7 @@ int pool_find_namespace(pool_t*pool, namespace_t*ns)
         return 0;
     int i = array_find(pool->x_namespaces, ns);
     if(i<=0) {
-        char*s = namespace_to_string(ns);
+        char*s = namespace_tostring(ns);
         fprintf(stderr, "Couldn't find namespace \"%s\" %08x in constant pool\n", s, ns);
         free(s);
         return 0;
@@ -725,7 +897,7 @@ int pool_find_namespace_set(pool_t*pool, namespace_set_t*set)
         return 0;
     int i = array_find(pool->x_namespace_sets, set);
     if(i<=0) {
-        char*s = namespace_set_to_string(set);
+        char*s = namespace_set_tostring(set);
         fprintf(stderr, "Couldn't find namespace_set \"%s\" in constant pool\n", s);
         free(s);
         return 0;
@@ -749,7 +921,7 @@ int pool_find_multiname(pool_t*pool, multiname_t*name)
         return 0;
     int i = array_find(pool->x_multinames, name);
     if(i<=0) {
-        char*s = multiname_to_string(name);
+        char*s = multiname_tostring(name);
         fprintf(stderr, "Couldn't find multiname \"%s\" in constant pool\n", s);
         free(s);
         return 0;
@@ -859,12 +1031,12 @@ void pool_read(pool_t*pool, TAG*tag)
     for(t=1;t<num_namespaces;t++) {
        U8 type = swf_GetU8(tag);
        int namenr = swf_GetU30(tag);
-       const char*name = ""; 
-        if(namenr) //spec page 22: "a value of zero denotes an empty string"
+       const char*name = 0; 
+        if(namenr)
             name = array_getkey(pool->x_strings, namenr);
         namespace_t*ns = namespace_new(type, name);
        array_append(pool->x_namespaces, ns, 0);
-       DEBUG printf("%d) %02x \"%s\"\n", t, type, namespace_to_string(ns));
+       DEBUG printf("%d) %02x \"%s\"\n", t, type, namespace_tostring(ns));
         namespace_destroy(ns);
     }
     int num_sets = swf_GetU30(tag);
@@ -882,7 +1054,7 @@ void pool_read(pool_t*pool, TAG*tag)
             list_append(nsset->namespaces, namespace_clone(ns));
         }
         array_append(pool->x_namespace_sets, nsset, 0);
-        DEBUG printf("set %d) %s\n", t, namespace_set_to_string(nsset));
+        DEBUG printf("set %d) %s\n", t, namespace_set_tostring(nsset));
         namespace_set_destroy(nsset);
     }
 
@@ -915,15 +1087,9 @@ void pool_read(pool_t*pool, TAG*tag)
        } else {
            printf("can't parse type %d multinames yet\n", m.type);
        }
-        DEBUG printf("multiname %d) %s\n", t, multiname_to_string(&m));
+        DEBUG printf("multiname %d) %s\n", t, multiname_tostring(&m));
        array_append(pool->x_multinames, &m, 0);
     }
-    printf("%d ints\n", num_ints);
-    printf("%d uints\n", num_uints);
-    printf("%d strings\n", num_strings);
-    printf("%d namespaces\n", num_namespaces);
-    printf("%d namespace sets\n", num_sets);
-    printf("%d multinames\n", num_multinames);
 } 
 
 void pool_write(pool_t*pool, TAG*tag)
@@ -955,10 +1121,17 @@ void pool_write(pool_t*pool, TAG*tag)
     }
     for(t=1;t<pool->x_namespaces->num;t++) {
        namespace_t*ns= (namespace_t*)array_getkey(pool->x_namespaces, t);
-        if(ns->name && ns->name[0])
-            array_append_if_new(pool->x_strings, ns->name, 0);
+        /*  The spec says (page 22): "a value of zero denotes an empty string".
+            However when actually using zero strings as empty namespaces, the
+            flash player breaks.*/
+        //if(ns->name && ns->name[0])
+        array_append_if_new(pool->x_strings, ns->name, 0);
     }
 
+    //pool_register_int(pool, 15);
+    //pool_register_int(pool, 1);
+    //pool_register_int(pool, 0);
+    
     /* write data */
     swf_SetU30(tag, pool->x_ints->num>1?pool->x_ints->num:0);
     for(t=1;t<pool->x_ints->num;t++) {
@@ -971,8 +1144,8 @@ void pool_write(pool_t*pool, TAG*tag)
     }
     swf_SetU30(tag, pool->x_floats->num>1?pool->x_floats->num:0);
     for(t=1;t<pool->x_floats->num;t++) {
-        array_getvalue(pool->x_floats, t);
-        swf_SetD64(tag, 0.0); // fixme
+        double d = pool_lookup_float(pool, t);
+        swf_SetD64(tag, d);
     }
     swf_SetU30(tag, pool->x_strings->num>1?pool->x_strings->num:0);
     for(t=1;t<pool->x_strings->num;t++) {
@@ -984,8 +1157,10 @@ void pool_write(pool_t*pool, TAG*tag)
        swf_SetU8(tag, ns->access);
        const char*name = ns->name;
        int i = 0;
-        if(name && name[0])
-            i = pool_find_string(pool, name);
+        
+        //if(name && name[0])
+        i = pool_find_string(pool, name);
+
        swf_SetU30(tag, i);
     }
     swf_SetU30(tag, pool->x_namespace_sets->num>1?pool->x_namespace_sets->num:0);