-/* 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];}
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) {
if(!justassign) {
/* dupping two values on the stack requires 5 operations and one register-
couldn't adobe just have given us a dup2? */
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)
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;
r.s = malloc(sizeof(string_t));
r.s->str = s;
r.s->len = l1+l2;
+ free(add);
} else {
r.type = CONSTANT_UNKNOWN;
}
READ_HEADER_LEFTRIGHT;
c = code_append(left.c, right.c);
c = abc_astypelate(c);
- t = TYPE_ANY;
+ if(TYPE_IS_CLASS(right.t) && right.t->data) {
+ t = (classinfo_t*)right.t->data;
+ } else {
+ t = TYPE_ANY;
+ }
RET;
}
code_t* node_as_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);
}
c = toreadwrite(left.c, c, 0, 0, 1);
t = left.t;
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);
}
case CONSTANT_NAMESPACE_PRIVATE:
c = abc_pushnamespace(0, v->ns);
break;
- default: syntaxerror("invalid constant");
+ case CONSTANT_UNKNOWN:
+ syntaxerror("internal error: invalid constant");
+ default:
+ *(int*)0=0;
+ syntaxerror("invalid constant (%d)", v->type);
+
}
RET;
}
}
typedcode_t node_code_read(node_t*n)
{
- /* TODO: this dup might be unnecessary- n->code.c is only read out once */
typedcode_t t;
- t.c = code_dup(n->code.c);
+ t.c = n->code.c;
+ n->code.c=0;
t.t = n->code.t;
return t;
}
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*));
void node_free(node_t*n)
{
int t;
- if(n->type == &node_const) {
- constant_free(n->value);n->value = 0;
- }
- else if(n->type == &node_code) {
- code_free(n->code.c);n->code.c = 0;
- }
- else for(t=0;t<n->num_children;t++) {
+ if(n->type == &node_code) {
+ if(n->code.c) {
+ code_free(n->code.c);n->code.c = 0;
+ }
+ } else if(n->type == &node_const) {
+ /* keep, this is not our reference */
+ } else for(t=0;t<n->num_children;t++) {
node_free(n->child[t]);n->child[t] = 0;
}
free(n);
typedcode_t node_read(node_t*n)
{
- typedcode_t t = n->type->read(n);
- node_free(n);
- return t;
+ 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;
+ }
}
code_t* node_exec(node_t*n)
{
fprintf(fi, "%s%s (%s)\n", p1, n->type->name, s);
free(s);
} else if(n->type == &node_code) {
- fprintf(fi, "%s%s\n", p1, n->type->name);
+ fprintf(fi, "%s%s (%s)\n", p1, n->type->name, n->code.t?n->code.t->name:"*");
code_dump2(n->code.c, 0, 0, (char*)p2, fi);
} else {
fprintf(fi, "%s%s\n", p1, n->type->name);
void node_dump(node_t*n)
{
- printf("---------------------------VVVV\n");
+ printf("------------VVVV---------------\n");
node_dump2(n,"","",stdout);
- printf("---------------------------^^^^\n");
+ printf("-------------------------------\n");
}