X-Git-Url: http://git.subgeniuskitty.com/vvhitespace/.git/blobdiff_plain/8d17aa4158cb8dade01d69aa015a1b3fb159995d..4fba07dca7fb9275b51e5095a774fe69eeab4660:/vv_interpreter.c diff --git a/vv_interpreter.c b/vv_interpreter.c index 1d5d906..b548a50 100644 --- a/vv_interpreter.c +++ b/vv_interpreter.c @@ -126,7 +126,10 @@ parse_label(uint8_t * code, size_t * pc) uint16_t check_label(size_t * labels, uint16_t label, size_t * pc) { - if(!labels[label]) ws_die(pc, "uninitialized label (forgot an include?)"); + if (!labels[label]) { + fprintf(stderr, "Trying to process label 0x%X.\n", label); + ws_die(pc, "uninitialized label (forgot an include?)"); + } return label; } @@ -159,14 +162,26 @@ process_imp_stack(uint8_t * code, size_t * pc, int64_t ** sp) /* Now, construct the number and push to TOS. */ /* I'm assuming the numbers are read MSb first. */ - int64_t number = 0; + uint64_t number = 0; /* Unsigned to accomodate magnitude of most negative number. */ uint8_t temp; while ((temp = next_code_byte(code,pc)) != '\n') { if (temp == '\v') ws_die(pc, "non-binary digit in number"); number <<= 1; if (temp == '\t') number++; } - stack_push(sp, number*sign); + /* Without temporarily casting to something >64-bit, the most negative */ + /* number will overflow when performing 'number*sign'. Instead, we */ + /* pick off the most negative number as a special case. */ + if (number == (1ULL << 63) && sign == -1) { + /* C parses negative integer literals first as signed positive */ + /* integer literals, then applying a unary negation operator. */ + /* Thus, the most negative value is unreachable directly. */ + int64_t number_temp = -9223372036854775807LL; /* First store -((2^63)-1) */ + number_temp--; /* Now turn it into -(2^63) */ + stack_push(sp, number_temp); + } else { + stack_push(sp, number*sign); + } } break; case '\n': @@ -238,7 +253,7 @@ process_imp_arithmetic(uint8_t * code, size_t * pc, int64_t ** sp) case '\t': /* Modulo */ temp = stack_pop(sp); - stack_push(sp, stack_pop(sp)%temp); + stack_push(sp, llabs(stack_pop(sp) % llabs(temp))); break; default: ws_die(pc, "malformed arithmetic IMP"); break; }