+ if(!callcode(current, 0, 0, 0)) {
+ free(current);
+ return 0;
+ }
+ abc_exception_list_t*e = exceptions;
+ while(e) {
+ if(e->abc_exception->target)
+ callcode(current, e->abc_exception->target->pos, 1, 0);
+ e = e->next;
+ }
+
+ return current;
+}
+
+void stats_free(currentstats_t*stats)
+{
+ if(stats) {
+ free(stats->stack);stats->stack=0;
+ free(stats);
+ }
+}
+
+int code_dump(code_t*c)
+{
+ return code_dump2(c, 0, 0, "", stdout);
+}
+int code_dump2(code_t*c, abc_exception_list_t*exceptions, abc_file_t*file, char*prefix, FILE*fo)
+{
+ abc_exception_list_t*e = exceptions;
+ c = code_start(c);
+ currentstats_t*stats = code_get_stats(c, exceptions);
+
+ int pos = 0;
+ while(c) {
+ U8 opcode = c->opcode;
+ char found = 0;
+ opcode_t*op = opcode_get(opcode);
+
+ e = exceptions;
+ while(e) {
+ if(c==e->abc_exception->from)
+ fprintf(fo, "%s TRY {\n", prefix);
+ if(c==e->abc_exception->target) {
+ char*s1 = multiname_tostring(e->abc_exception->exc_type);
+ char*s2 = multiname_tostring(e->abc_exception->var_name);
+ fprintf(fo, "%s CATCH(%s %s)\n", prefix, s1, s2);
+ free(s1);
+ free(s2);
+ }
+ e = e->next;
+ }
+
+ if(!op) {
+ fprintf(stderr, "Can't parse opcode %02x.\n", opcode);
+ return 0;
+ } else {
+ char*p = op->params;
+ char first = 1;
+ int i=0;
+
+ if(stats) {
+ int f = stats->stack[c->pos].flags;
+ fprintf(fo, "%s%5d) %c %d:%d %s ", prefix, c->pos,
+ (f&FLAG_ERROR)?'E':((f&FLAG_SEEN)?'+':'|'),
+ stats->stack[c->pos].stackpos,
+ stats->stack[c->pos].scopepos,
+ op->name);
+ } else {
+ fprintf(fo, "%s%5d) ? ?:? %s ", prefix, c->pos, op->name);
+ }
+
+ while(*p) {
+ void*data = c->data[i];
+ if(i>0)
+ printf(", ");
+
+ if(*p == 'n') {
+ int n = (ptroff_t)data;
+ fprintf(fo, "%d params", n);
+ } else if(*p == '2') {
+ multiname_t*n = (multiname_t*)data;
+ char* m = multiname_tostring(n);
+ fprintf(fo, "%s", m);
+ free(m);
+ } else if(*p == 'm') {
+ abc_method_t*m = (abc_method_t*)data;
+ fprintf(fo, "[method %08x %s]", m->index, m->name);
+ } else if(*p == 'c') {
+ abc_class_t*cls = (abc_class_t*)data;
+ char*classname = multiname_tostring(cls->classname);
+ fprintf(fo, "[classinfo %08x %s]", cls->index, classname);
+ free(classname);
+ } else if(*p == 'i') {
+ abc_method_body_t*b = (abc_method_body_t*)data;
+ fprintf(fo, "[methodbody]");
+ } else if(*p == 'u' || *p == 'I' || *p == 'U') {
+ int n = (ptroff_t)data;
+ fprintf(fo, "%d", n);
+ } else if(*p == 'f') {
+ double f = *(double*)data;
+ fprintf(fo, "%f", f);
+ } else if(*p == 'r') {
+ int n = (ptroff_t)data;
+ fprintf(fo, "r%d", n);
+ } else if(*p == 'b') {
+ int b = (signed char)(ptroff_t)data;
+ fprintf(fo, "%d", b);
+ } else if(*p == 'j') {
+ if(c->branch)
+ fprintf(fo, "->%d", c->branch->pos);
+ else
+ fprintf(fo, "%08x", c->branch);
+ } else if(*p == 's') {
+ char*s = string_escape((string_t*)data);
+ fprintf(fo, "\"%s\"", s);
+ free(s);
+ } else if(*p == 'D') {
+ fprintf(fo, "[register %02x=%s]", (ptroff_t)c->data[1], (char*)c->data[0]);
+ } else if(*p == 'S') {
+ lookupswitch_t*l = c->data[0];
+ fprintf(fo, "[");
+ if(l->def)
+ fprintf(fo, "default->%d", l->def->pos);
+ else
+ fprintf(fo, "default->00000000");
+ code_list_t*t = l->targets;
+ while(t) {
+ if(t->code)
+ fprintf(fo, ",->%d", t->code->pos);
+ else
+ fprintf(fo, ",->00000000");
+ t = t->next;
+ }
+ fprintf(fo, "]");
+ } else {
+ fprintf(stderr, "Can't parse opcode param type \"%c\"\n", *p);
+ return 0;
+ }
+ p++;
+ i++;
+ first = 0;
+ }
+ fprintf(fo, "\n");
+ }
+
+ e = exceptions;
+ while(e) {
+ if(c==e->abc_exception->to) {
+ if(e->abc_exception->target)
+ fprintf(fo, "%s } // END TRY (HANDLER: %d)\n", prefix, e->abc_exception->target->pos);
+ else
+ fprintf(fo, "%s } // END TRY (HANDLER: 00000000)\n", prefix);
+ }
+ e = e->next;
+ }
+
+ pos++;
+ c = c->next;
+ }
+ stats_free(stats);
+ return 1;
+}
+
+codestats_t* code_get_statistics(code_t*code, abc_exception_list_t*exceptions)
+{
+ currentstats_t*current = code_get_stats(code, exceptions);
+ if(!current)
+ return 0;
+ codestats_t*stats = rfx_calloc(sizeof(codestats_t));
+ stats->local_count = current->maxlocal;
+ stats->max_stack = current->maxstack;
+ stats->max_scope_depth = current->maxscope;
+ stats->flags = current->flags;