fixed bug in jpeg2000 decoding
[swftools.git] / lib / as3 / expr.c
index 25e0132..1a67594 100644 (file)
@@ -1,4 +1,4 @@
-/* ast.c
+/* expr.c
 
    Extension module for the rfxswf library.
    Part of the swftools package.
 
 static classinfo_t*join_types(classinfo_t*type1, classinfo_t*type2, nodetype_t*t)
 {
-    if(!type1 || !type2)
-        return TYPE_ANY;
-    if(TYPE_IS_ANY(type1) || TYPE_IS_ANY(type2))
-        return TYPE_ANY;
+    if(t == &node_plus) {
+        if((TYPE_IS_XMLLIST(type1) || TYPE_IS_XML(type1)) &&
+           (TYPE_IS_XMLLIST(type2) || TYPE_IS_XML(type2)))
+            return TYPE_OBJECT;
+        if(BOTH_INT(type1, type2))
+            return TYPE_INT;
+        if(IS_NUMBER_OR_INT(type1) && IS_NUMBER_OR_INT(type2))
+            return TYPE_NUMBER;
+        if(TYPE_IS_DATE(type1) || TYPE_IS_DATE(type2))
+            return TYPE_OBJECT;
+        if(TYPE_IS_STRING(type1) || TYPE_IS_STRING(type2)) {
+            /* depending on where the strings come from, the result type
+               of an "add" might be an object or a string, depending on the
+               verifier's mood. So basically we just don't know the type. */
+            return TYPE_VOID;
+        }
+        if(TYPE_IS_ANY(type1) || TYPE_IS_ANY(type2))
+            return TYPE_ANY;
+        return TYPE_OBJECT; // e.g. array+array = object
+    }
+    
     if(type1 == type2)
         return type1;
     return TYPE_ANY;
 }
-static char is_getlocal(code_t*c)
-{
-    if(!c || c->prev || c->next)
-        return 0;
-    return(c->opcode == OPCODE_GETLOCAL
-        || c->opcode == OPCODE_GETLOCAL_0
-        || c->opcode == OPCODE_GETLOCAL_1
-        || c->opcode == OPCODE_GETLOCAL_2
-        || c->opcode == OPCODE_GETLOCAL_3);
-}
 static int getlocalnr(code_t*c)
 {
     if(c->opcode == OPCODE_GETLOCAL) {return (ptroff_t)c->data[0];}
@@ -132,12 +139,14 @@ static code_t* toreadwrite(code_t*in, code_t*middlepart, char justassign, char r
         write->opcode = OPCODE_SETPROPERTY;
         multiname_t*m = (multiname_t*)r->data[0];
         write->data[0] = multiname_clone(m);
-        if(m->type == QNAME || m->type == MULTINAME) {
+        if(m->type == QNAME || m->type == MULTINAME ||
+           m->type == QNAMEA || m->type == MULTINAMEA) {
             if(!justassign) {
                 prefix = abc_dup(prefix); // we need the object, too
             }
             use_temp_var = 1;
-        } else if(m->type == MULTINAMEL) {
+        } else if(m->type == MULTINAMEL || m->type == MULTINAMELA ||
+                 m->type == RTQNAME || m->type == RTQNAMEA) {
             if(!justassign) {
                 /* dupping two values on the stack requires 5 operations and one register- 
                    couldn't adobe just have given us a dup2? */
@@ -260,6 +269,32 @@ static code_t* toreadwrite(code_t*in, code_t*middlepart, char justassign, char r
     return c;
 }
 
+typedcode_t push_constant(constant_t*v)
+{
+    typedcode_t t;
+    switch(v->type) {
+        case CONSTANT_INT: t.c = abc_pushint(0, v->i);t.t = TYPE_INT;break;
+        case CONSTANT_UINT: t.c = abc_pushuint(0, v->u);t.t = TYPE_UINT;break;
+        case CONSTANT_FLOAT: t.c = abc_pushdouble(0, v->f);t.t = TYPE_FLOAT;break;
+        case CONSTANT_TRUE: t.c = abc_pushtrue(0);t.t = TYPE_BOOLEAN;break;
+        case CONSTANT_FALSE: t.c = abc_pushfalse(0);t.t = TYPE_BOOLEAN;break;
+        case CONSTANT_STRING: t.c = abc_pushstring2(0, v->s);t.t = TYPE_STRING;break;
+        case CONSTANT_NULL: t.c = abc_pushnull(0);t.t = TYPE_NULL;break;
+        case CONSTANT_UNDEFINED: t.c = abc_pushundefined(0);t.t = TYPE_ANY;break;
+        case CONSTANT_NAMESPACE:
+        case CONSTANT_NAMESPACE_PACKAGE:
+        case CONSTANT_NAMESPACE_PACKAGEINTERNAL:
+        case CONSTANT_NAMESPACE_PROTECTED:
+        case CONSTANT_NAMESPACE_EXPLICIT:
+        case CONSTANT_NAMESPACE_STATICPROTECTED:
+        case CONSTANT_NAMESPACE_PRIVATE:
+            t.c = abc_pushnamespace(0, v->ns);t.t = TYPE_NAMESPACE;break;
+        default:
+            syntaxerror("internal error: bad constant");
+    }
+    return t;
+}
+
 code_t*converttype(code_t*c, classinfo_t*from, classinfo_t*to);
 
 int constant_to_int(constant_t*c) 
@@ -317,7 +352,6 @@ constant_t node_plus_eval(node_t*n)
     EVAL_HEADER_LEFTRIGHT;
     char left_int = left.type == CONSTANT_INT || left.type == CONSTANT_UINT;
     if(left_int && (right.type == CONSTANT_INT || right.type == CONSTANT_UINT)) { 
-        /* FIXME: what to do about signed/unsigned overflows? */
         int i = constant_to_int(&left) + constant_to_int(&right);
         r.type = CONSTANT_INT;
         r.i = i;
@@ -2058,7 +2092,7 @@ typedcode_t node_pluseq_read(node_t*n)
        c = abc_add_i(c);
     } else {
        c = abc_add(c);
-       c = converttype(c, TYPE_NUMBER, left.t);
+       c = converttype(c, join_types(left.t,right.t,&node_plus), left.t);
     }
     c = toreadwrite(left.c, c, 0, 0, 1);
     t = left.t;
@@ -2072,7 +2106,7 @@ code_t* node_pluseq_exec(node_t*n)
        c = abc_add_i(c);
     } else {
        c = abc_add(c);
-       c = converttype(c, TYPE_NUMBER, left.t);
+       c = converttype(c, join_types(left.t,right.t,&node_plus), left.t);
     }
     return toreadwrite(left.c, c, 0, 0, 0);
 }
@@ -2603,7 +2637,16 @@ exec: node_const_exec
 
 typedcode_t node_code_write(node_t*n)
 {
-    syntaxerror("not implemented yet");
+    typedcode_t t;
+    t.c = 0;
+    int tmp = gettempvar();
+    t.c = abc_setlocal(t.c, tmp);
+    code_t*w = toreadwrite(n->code.c, abc_getlocal(0,tmp), 1, 0, 0);
+    t.c = code_append(t.c, w);
+    t.c = abc_kill(t.c, tmp);
+    n->code.c=0;
+    t.t = n->code.t;
+    return t;
 }
 typedcode_t node_code_read(node_t*n)
 {
@@ -2702,6 +2745,16 @@ node_t* mkmultinode(nodetype_t*t, node_t*one)
     return n;
 }
 
+node_t* mkstringnode(const char*s)
+{
+    return mkconstnode(constant_new_string(s));
+}
+
+node_t* mkaddnode(node_t*n1, node_t*n2)
+{
+    return mknode2(&node_plus, n1, n2);
+}
+
 node_t* multinode_extend(node_t*n, node_t*add)
 {
     n->child = realloc(n->child, (n->num_children+1)*sizeof(node_t*));
@@ -2768,7 +2821,20 @@ void node_free(node_t*n)
 
 typedcode_t node_read(node_t*n)
 {
-    typedcode_t t = n->type->read(n);
+    constant_t c = n->type->eval(n);
+    if(c.type == CONSTANT_UNKNOWN) {
+        typedcode_t t = n->type->read(n);
+        node_free(n);
+        return t;
+    } else {
+        typedcode_t t = push_constant(&c);
+        node_free(n);
+        return t;
+    }
+}
+typedcode_t node_write(node_t*n)
+{
+    typedcode_t t = n->type->write(n);
     node_free(n);
     return t;
 }
@@ -2831,8 +2897,8 @@ void node_dump2(node_t*n, const char*p1, const char*p2, FILE*fi)
 
 void node_dump(node_t*n)
 {
-    printf("---------------------------VVVV\n");
+    printf("------------VVVV---------------\n");
     node_dump2(n,"","",stdout);
-    printf("---------------------------^^^^\n");
+    printf("-------------------------------\n");
 }