/* * Unescape XML string * * input and output may be the same buffers * return len of output * * "<" -> "<" * ">" -> "<" * "'" -> "'" * """ -> "\"" * "&" -> "&" */ int unescape_xml_r( const char *input, int input_len, char *output){ int output_len=0; while(input_len){ if(*input=='&'){ if(IS_LT(input, input_len)){ *output='<'; input+=LT_LEN; input_len-=LT_LEN; }else if(IS_GT(input, input_len)){ *output='>'; input+=GT_LEN; input_len-=GT_LEN; }else if(IS_APOS(input, input_len)){ *output='\''; input+=APOS_LEN; input_len-=APOS_LEN; }else if(IS_QUOT(input, input_len)){ *output='"'; input+=QUOT_LEN; input_len-=QUOT_LEN; }else if(IS_AMP(input, input_len)){ *output='&'; input+=AMP_LEN; input_len-=AMP_LEN; }else{ *output='&'; input++; input_len--; } }else{ *output=*input++; input_len--; } output_len++; output++; } return output_len; }
/* Executes a program in a BVM instance until termination. * Returns a non-zero error code if an error occurred. */ int bvm_run(struct bvm *vm, const uint8_t *code, size_t code_size) { /* Code size must fit into BVM's memory. */ if (code_size > sizeof(vm->mem)) return BVM_PROGRAM_TOO_LARGE; /* Zero register file and memory. */ memset(vm->reg, 0, sizeof(vm->reg)); memset(vm->mem, 0, sizeof(vm->mem)); /* Load program code into memory. */ memcpy(vm->mem, code, code_size); /* Reset the clock. */ vm->clk = 0; while (1) { uint8_t op; uint8_t src, dst; int c; usleep(BVM_CYCLE); vm->clk++; op = pc_next(vm); switch (op) { case HALT: return 0; case MOV: src = pc_next(vm); dst = pc_next(vm); if (!IS_REGISTER_VALID(src) || !IS_REGISTER_VALID(dst)) return BVM_BAD_INSTRUCTION; vm->reg[dst] = vm->reg[src]; continue; case MOVN: src = pc_next(vm); dst = pc_next(vm); if (!IS_REGISTER_VALID(dst)) return BVM_BAD_INSTRUCTION; vm->reg[dst] = src; continue; case LOAD: src = pc_next(vm); dst = pc_next(vm); if (!IS_REGISTER_VALID(src) || !IS_REGISTER_VALID(dst)) return BVM_BAD_INSTRUCTION; vm->reg[dst] = vm->mem[vm->reg[src]]; continue; case LOADA: src = pc_next(vm); dst = pc_next(vm); if (!IS_REGISTER_VALID(src) || !IS_REGISTER_VALID(dst)) return BVM_BAD_INSTRUCTION; vm->reg[dst] = vm->mem[src]; continue; case PUT: src = pc_next(vm); dst = pc_next(vm); if (!IS_REGISTER_VALID(src) || !IS_REGISTER_VALID(dst)) return BVM_BAD_INSTRUCTION; vm->mem[vm->reg[dst]] = vm->reg[src]; continue; case PUTN: src = pc_next(vm); dst = pc_next(vm); if (!IS_REGISTER_VALID(dst)) return BVM_BAD_INSTRUCTION; vm->mem[vm->reg[dst]] = src; continue; case PUTA: src = pc_next(vm); dst = pc_next(vm); if (!IS_REGISTER_VALID(src)) return BVM_BAD_INSTRUCTION; vm->mem[dst] = vm->reg[src]; continue; case PUTNA: src = pc_next(vm); dst = pc_next(vm); vm->mem[dst] = src; continue; case PUSH: src = pc_next(vm); if (!IS_REGISTER_VALID(src)) return BVM_BAD_INSTRUCTION; vm->reg[SP]--; vm->mem[vm->reg[SP]] = vm->reg[src]; continue; case PUSHN: src = pc_next(vm); vm->reg[SP]--; vm->mem[vm->reg[SP]] = src; continue; case POP: src = pc_next(vm); if (!IS_REGISTER_VALID(src)) return BVM_BAD_INSTRUCTION; vm->reg[src] = vm->mem[vm->reg[SP]]; vm->reg[SP]++; continue; case INC: src = pc_next(vm); if (!IS_REGISTER_VALID(src)) return BVM_BAD_INSTRUCTION; vm->reg[src]++; continue; case DEC: src = pc_next(vm); if (!IS_REGISTER_VALID(src)) return BVM_BAD_INSTRUCTION; vm->reg[src]--; continue; case ADD: src = pc_next(vm); dst = pc_next(vm); if (!IS_REGISTER_VALID(src) || !IS_REGISTER_VALID(dst)) return BVM_BAD_INSTRUCTION; vm->reg[dst] += vm->reg[src]; continue; case ADDN: src = pc_next(vm); dst = pc_next(vm); if (!IS_REGISTER_VALID(dst)) return BVM_BAD_INSTRUCTION; vm->reg[dst] += src; continue; case SUB: src = pc_next(vm); dst = pc_next(vm); if (!IS_REGISTER_VALID(src) || !IS_REGISTER_VALID(dst)) return BVM_BAD_INSTRUCTION; vm->reg[dst] -= vm->reg[src]; continue; case SUBN: src = pc_next(vm); dst = pc_next(vm); if (!IS_REGISTER_VALID(dst)) return BVM_BAD_INSTRUCTION; vm->reg[dst] -= src; continue; case AND: src = pc_next(vm); dst = pc_next(vm); if (!IS_REGISTER_VALID(src) || !IS_REGISTER_VALID(dst)) return BVM_BAD_INSTRUCTION; vm->reg[dst] &= vm->reg[src]; continue; case ANDN: src = pc_next(vm); dst = pc_next(vm); if (!IS_REGISTER_VALID(src) || !IS_REGISTER_VALID(dst)) return BVM_BAD_INSTRUCTION; vm->reg[dst] &= src; continue; case OR: src = pc_next(vm); dst = pc_next(vm); if (!IS_REGISTER_VALID(src) || !IS_REGISTER_VALID(dst)) return BVM_BAD_INSTRUCTION; vm->reg[dst] |= vm->reg[src]; continue; case ORN: src = pc_next(vm); dst = pc_next(vm); if (!IS_REGISTER_VALID(src) || !IS_REGISTER_VALID(dst)) return BVM_BAD_INSTRUCTION; vm->reg[dst] |= src; continue; case XOR: src = pc_next(vm); dst = pc_next(vm); if (!IS_REGISTER_VALID(src) || !IS_REGISTER_VALID(dst)) return BVM_BAD_INSTRUCTION; vm->reg[dst] ^= vm->reg[src]; continue; case XORN: src = pc_next(vm); dst = pc_next(vm); if (!IS_REGISTER_VALID(src) || !IS_REGISTER_VALID(dst)) return BVM_BAD_INSTRUCTION; vm->reg[dst] ^= src; continue; case NEG: src = pc_next(vm); if (!IS_REGISTER_VALID(src)) return BVM_BAD_INSTRUCTION; vm->reg[src] = ~vm->reg[src]; continue; case CMP: src = pc_next(vm); dst = pc_next(vm); if (!IS_REGISTER_VALID(src) || !IS_REGISTER_VALID(dst)) return BVM_BAD_INSTRUCTION; vm->reg[CC] = 0; vm->reg[CC] |= (vm->reg[src] == vm->reg[dst]) << CC_EQ_SHIFT; vm->reg[CC] |= (vm->reg[src] < vm->reg[dst]) << CC_OF_SHIFT; continue; case CMPN: src = pc_next(vm); dst = pc_next(vm); if (!IS_REGISTER_VALID(src)) return BVM_BAD_INSTRUCTION; vm->reg[CC] = 0; vm->reg[CC] |= (vm->reg[src] == dst) << CC_EQ_SHIFT; vm->reg[CC] |= (vm->reg[src] < dst) << CC_OF_SHIFT; continue; case TEST: src = pc_next(vm); if (!IS_REGISTER_VALID(src)) return BVM_BAD_INSTRUCTION; vm->reg[CC] = 0; vm->reg[CC] |= (vm->reg[src] == 0) << CC_EQ_SHIFT; continue; case JMP: vm->reg[PC] = pc_next(vm); continue; case JE: src = pc_next(vm); if (IS_EQ(vm->reg[CC])) vm->reg[PC] = src; continue; case JNE: src = pc_next(vm); if (!IS_EQ(vm->reg[CC])) vm->reg[PC] = src; continue; case JL: src = pc_next(vm); if (IS_LT(vm->reg[CC])) vm->reg[PC] = src; continue; case JLE: src = pc_next(vm); if (IS_LT(vm->reg[CC]) || IS_EQ(vm->reg[CC])) vm->reg[PC] = src; continue; case JG: src = pc_next(vm); if (!IS_LT(vm->reg[CC]) && !IS_EQ(vm->reg[CC])) vm->reg[PC] = src; continue; case JGE: src = pc_next(vm); if (!IS_LT(vm->reg[CC]) || IS_EQ(vm->reg[CC])) vm->reg[PC] = src; continue; case JEOF: src = pc_next(vm); if (IS_EOF(vm->reg[CC])) vm->reg[PC] = src; continue; case JNEOF: src = pc_next(vm); if (!IS_EOF(vm->reg[CC])) vm->reg[PC] = src; continue; case CALL: vm->reg[SP]--; vm->mem[vm->reg[SP]] = vm->reg[PC] + 1; vm->reg[PC] = pc_next(vm); continue; case RET: vm->reg[PC] = vm->mem[vm->reg[SP]]; vm->reg[SP]++; continue; case NOP: continue; case IN: src = pc_next(vm); if (!IS_REGISTER_VALID(src)) return BVM_BAD_INSTRUCTION; if ((c = fgetc(stdin)) == EOF) vm->reg[CC] = CC_EOF; vm->reg[src] = c; continue; case OUT: src = pc_next(vm); if (!IS_REGISTER_VALID(src)) return BVM_BAD_INSTRUCTION; if (fputc(vm->reg[src], stdout) == EOF) vm->reg[CC] = CC_EOF; continue; case OUTN: src = pc_next(vm); if (fputc(src, stdout) == EOF) vm->reg[CC] = CC_EOF; continue; default: return BVM_BAD_INSTRUCTION; } } }