static char callcode(currentstats_t*stats, int pos, int stack, int scope) { while(pos<stats->num) { if(stats->stack[pos].flags&FLAG_SEEN) { if(stats->stack[pos].stackpos != stack || stats->stack[pos].scopepos != scope) { //dumpstack(stats); stats->stack[pos].flags |= FLAG_ERROR; fprintf(stderr, "Stack mismatch at pos %d\n", pos); fprintf(stderr, "Should be: %d:%d, is: %d:%d\n", stack, scope, stats->stack[pos].stackpos, stats->stack[pos].scopepos); /* return error here if we do verification */ //return 0; } return 1; } stats->stack[pos].flags |= FLAG_SEEN; stats->stack[pos].stackpos = stack; stats->stack[pos].scopepos = scope; code_t*c = stats->stack[pos].code; opcode_t*op = opcode_get(c->opcode); //printf("Walking %s at position %d, stack=%d, scope=%d\n", op->name, pos, stack, scope); stack += stack_minus(c); if(stack<0) { stats->stack[pos].flags |= FLAG_ERROR; fprintf(stderr, "error: stack underflow at %d (%s)\n", pos, op->name); /* if we would do true verification (if we would be a vm), this is where we would return the error return 0; */ } stack += op->stack_plus; scope += op->scope_stack_plus; if(stack > stats->maxstack) stats->maxstack = stack; if(scope > stats->maxscope) stats->maxscope = scope; if(op->flags & OP_SET_DXNS) stats->flags |= FLAGS_SET_DXNS; if(op->flags & OP_NEED_ACTIVATION) stats->flags |= FLAGS_ACTIVATION; if(c->opcode == OPCODE_NEWCLASS) { abc_class_t*cls = (abc_class_t*)(c->data[0]); if(scope > cls->init_scope_depth) cls->init_scope_depth = scope; } if(c->opcode == OPCODE_NEWFUNCTION) { abc_method_t*m = (abc_method_t*)(c->data[0]); if(m->body && scope > m->body->init_scope_depth) m->body->init_scope_depth = scope; } if(op->flags & OP_REGISTER) { char*p = op->params; int pos = 0; char ok=0; while(*p) { if(*p=='r') { handleregister(stats, (ptroff_t)c->data[pos]); ok = 1; } p++; } if(!ok) { handleregister(stats, c->opcode&3); } } if(op->flags&OP_RETURN) { if(OP_RETURN==0x48/*returnvalue*/) { if(stack!=1) { stats->stack[pos].flags |= FLAG_ERROR; fprintf(stderr, "return(value) with stackposition %d\n", stack); } } else if(OP_RETURN==0x47) { if(stack!=0) { stats->stack[pos].flags |= FLAG_ERROR; fprintf(stderr, "return(void) with stackposition %d\n", stack); } } } if(op->flags & (OP_THROW|OP_RETURN)) return 1; if(op->flags & OP_JUMP) { if(!c->branch) { stats->stack[pos].flags |= FLAG_ERROR; fprintf(stderr, "Error: Invalid jump target in instruction %s at position %d.\n", op->name, pos); return 0; } c = c->branch; pos = c->pos; continue; } if(op->flags & OP_BRANCH) { if(!c->branch) { stats->stack[pos].flags |= FLAG_ERROR; fprintf(stderr, "Error: Invalid jump target in instruction %s at position %d\n", op->name, pos); return 0; } int newpos = c->branch->pos; if(!callcode(stats, newpos, stack, scope)) return 0; } if(op->flags & OP_LOOKUPSWITCH) { lookupswitch_t*l = c->data[0]; if(!l->def) { stats->stack[pos].flags |= FLAG_ERROR; fprintf(stderr, "Error: Invalid jump target in instruction %s at position %d\n", op->name, pos); return 0; } if(!callcode(stats, l->def->pos, stack, scope)) return 0; code_list_t*t = l->targets; while(t) { if(!t->code) { stats->stack[pos].flags |= FLAG_ERROR; fprintf(stderr, "Error: Invalid jump target in instruction %s at position %d\n", op->name, pos); return 0; } if(!callcode(stats, t->code->pos, stack, scope)) return 0; t = t->next; } } pos++; if(pos<stats->num) { assert(c->next == stats->stack[pos].code); } } return 1; }
void program_loop() { char *line = NULL; size_t line_size = 0; int start_from = 0; char *token = NULL; while(true) { printf("%d > ", num_stack_items()); line_size = getline(&line, &line_size, stdin); if (line_size == -1) break; while (true) { token = get_next_token(line, line_size, &start_from); if (token == NULL) { break; } else if (strcmp(token, ".s") == 0) { stack_show(); continue; } else if (strcmp(token, ".") == 0) { stack_dot(); continue; } else if (strcmp(token, ".dropall") == 0) { stack_dropall(); continue; } else if (strcmp(token, "+") == 0) { stack_plus(); continue; } else if (strcmp(token, "-") == 0) { stack_minus(); continue; } else if (strcmp(token, ".swap") == 0) { stack_swap(); continue; } else if (strcmp(token, ".dup") == 0) { stack_dup(); continue; } else if (strcmp(token, ".over") == 0) { stack_over(); continue; } else if (strcmp(token, ".drop") == 0) { stack_pop(); continue; } else if (strcmp(token, ".rot") == 0) { stack_rot(); continue; } else if (strcmp(token, ".-rot") == 0) { stack_rot(); stack_rot(); continue; } else if (strcmp(token, "!") == 0) { set_variable(); continue; } else if (strcmp(token, "$") == 0) { get_variable(); continue; } else if (token[0] == '$' && token[1] == '$') { eprintf("error: variable name can't begin with $.\n"); continue; } else if (token[0] == '$' && token[1] == '.') { /* Put literals in for stack operations. */ /* shift everything after $ over one */ for (int i = 0; i < BUFSIZE-1; ++i) { token[i] = token[i+1]; } stack_push(token); continue; } else if (token[0] == '$') { /* shift everything after $ over one */ for (int i = 0; i < BUFSIZE-1; ++i) { token[i] = token[i+1]; } stack_push(token); get_variable(); continue; } else if (strcmp(token, ";") == 0) { stack_execute(); continue; } else if (strcmp(token, ".cd") == 0) { stack_cd(); continue; } else if (token[0] == '.' && strlen(token) > 1) { /* shift everything after . over one */ for (int i = 0; i < BUFSIZE-1; ++i) { token[i] = token[i+1]; } stack_push(token); stack_execute(); continue; } stack_push(token); } start_from = 0; } }