version 1.17, 2003/11/17 11:12:35 |
version 1.18, 2003/12/01 09:13:24 |
|
|
#define MAX_RECURSION 100 |
#define MAX_RECURSION 100 |
|
|
#define NO_ELSE -2 /* -1 is EOF */ |
#define NO_ELSE -2 /* -1 is EOF */ |
|
#define REG_ARRAY_SIZE_SMALL (UCHAR_MAX + 1) |
|
#define REG_ARRAY_SIZE_BIG (UCHAR_MAX + 1 + USHRT_MAX + 1) |
|
|
struct bmachine { |
struct bmachine { |
struct stack stack; |
struct stack stack; |
|
|
u_int obase; |
u_int obase; |
u_int ibase; |
u_int ibase; |
int readsp; |
int readsp; |
struct stack reg[UCHAR_MAX]; |
bool extended_regs; |
|
size_t reg_array_size; |
|
struct stack *reg; |
struct source readstack[MAX_RECURSION]; |
struct source readstack[MAX_RECURSION]; |
}; |
}; |
|
|
|
|
static __inline void print_tos(void); |
static __inline void print_tos(void); |
static void pop_print(void); |
static void pop_print(void); |
static void pop_printn(void); |
static void pop_printn(void); |
static __inline void print_stack(); |
static __inline void print_stack(void); |
static __inline void dup(void); |
static __inline void dup(void); |
static void swap(void); |
static void swap(void); |
static void drop(void); |
static void drop(void); |
|
|
static bool compare_numbers(enum bcode_compare, struct number *, |
static bool compare_numbers(enum bcode_compare, struct number *, |
struct number *); |
struct number *); |
static void compare(enum bcode_compare); |
static void compare(enum bcode_compare); |
|
static int readreg(void); |
static void load(void); |
static void load(void); |
static void store(void); |
static void store(void); |
static void load_stack(void); |
static void load_stack(void); |
|
|
(sizeof(jump_table_data)/sizeof(jump_table_data[0])) |
(sizeof(jump_table_data)/sizeof(jump_table_data[0])) |
|
|
void |
void |
init_bmachine(void) |
init_bmachine(bool extended_registers) |
{ |
{ |
int i; |
int i; |
|
|
|
bmachine.extended_regs = extended_registers; |
|
bmachine.reg_array_size = bmachine.extended_regs ? |
|
REG_ARRAY_SIZE_BIG : REG_ARRAY_SIZE_SMALL; |
|
|
|
bmachine.reg = malloc(bmachine.reg_array_size * |
|
sizeof(bmachine.reg[0])); |
|
if (bmachine.reg == NULL) |
|
err(1, NULL); |
|
|
for (i = 0; i < UCHAR_MAX; i++) |
for (i = 0; i < UCHAR_MAX; i++) |
jump_table[i] = unknown; |
jump_table[i] = unknown; |
for (i = 0; i < JUMP_TABLE_DATA_SIZE; i++) |
for (i = 0; i < JUMP_TABLE_DATA_SIZE; i++) |
|
|
|
|
stack_init(&bmachine.stack); |
stack_init(&bmachine.stack); |
|
|
for (i = 0; i < UCHAR_MAX; i++) |
for (i = 0; i < bmachine.reg_array_size; i++) |
stack_init(&bmachine.reg[i]); |
stack_init(&bmachine.reg[i]); |
|
|
bmachine.obase = bmachine.ibase = 10; |
bmachine.obase = bmachine.ibase = 10; |
|
|
} |
} |
} |
} |
|
|
|
static int |
|
readreg(void) |
|
{ |
|
int index, ch1, ch2; |
|
|
|
index = readch(); |
|
if (index == 0xff && bmachine.extended_regs) { |
|
ch1 = readch(); |
|
ch2 = readch(); |
|
if (ch1 == EOF || ch2 == EOF) { |
|
warnx("unexpected eof"); |
|
index = -1; |
|
} else |
|
index = (ch1 << 8) + ch2 + UCHAR_MAX + 1; |
|
} |
|
if (index < 0 || index >= bmachine.reg_array_size) { |
|
warnx("internal error: reg num = %d", index); |
|
index = -1; |
|
} |
|
return index; |
|
} |
|
|
static void |
static void |
load(void) |
load(void) |
{ |
{ |
|
|
struct value *v, copy; |
struct value *v, copy; |
struct number *n; |
struct number *n; |
|
|
index = readch(); |
index = readreg(); |
if (0 <= index && index < UCHAR_MAX) { |
if (index >= 0) { |
v = stack_tos(&bmachine.reg[index]); |
v = stack_tos(&bmachine.reg[index]); |
if (v == NULL) { |
if (v == NULL) { |
n = new_number(); |
n = new_number(); |
|
|
push_number(n); |
push_number(n); |
} else |
} else |
push(stack_dup_value(v, ©)); |
push(stack_dup_value(v, ©)); |
} else |
} |
warnx("internal error: reg num = %d", index); |
|
} |
} |
|
|
static void |
static void |
|
|
int index; |
int index; |
struct value *val; |
struct value *val; |
|
|
index = readch(); |
index = readreg(); |
if (0 <= index && index < UCHAR_MAX) { |
if (index >= 0) { |
val = pop(); |
val = pop(); |
if (val == NULL) { |
if (val == NULL) { |
return; |
return; |
} |
} |
stack_set_tos(&bmachine.reg[index], val); |
stack_set_tos(&bmachine.reg[index], val); |
} else |
} |
warnx("internal error: reg num = %d", index); |
|
} |
} |
|
|
static void |
static void |
|
|
struct stack *stack; |
struct stack *stack; |
struct value *value, copy; |
struct value *value, copy; |
|
|
index = readch(); |
index = readreg(); |
if (0 <= index && index < UCHAR_MAX) { |
if (index >= 0) { |
stack = &bmachine.reg[index]; |
stack = &bmachine.reg[index]; |
value = NULL; |
value = NULL; |
if (stack_size(stack) > 0) { |
if (stack_size(stack) > 0) { |
|
|
else |
else |
warnx("stack register '%c' (0%o) is empty", |
warnx("stack register '%c' (0%o) is empty", |
index, index); |
index, index); |
} else |
} |
warnx("internal error: reg num = %d", index); |
|
} |
} |
|
|
static void |
static void |
|
|
int index; |
int index; |
struct value *value; |
struct value *value; |
|
|
index = readch(); |
index = readreg(); |
if (0 <= index && index < UCHAR_MAX) { |
if (index >= 0) { |
value = pop(); |
value = pop(); |
if (value == NULL) |
if (value == NULL) |
return; |
return; |
stack_push(&bmachine.reg[index], value); |
stack_push(&bmachine.reg[index], value); |
} else |
} |
warnx("internal error: reg num = %d", index); |
|
} |
} |
|
|
static void |
static void |
|
|
struct stack *stack; |
struct stack *stack; |
struct value *v, copy; |
struct value *v, copy; |
|
|
reg = readch(); |
reg = readreg(); |
if (0 <= reg && reg < UCHAR_MAX) { |
if (reg >= 0) { |
inumber = pop_number(); |
inumber = pop_number(); |
if (inumber == NULL) |
if (inumber == NULL) |
return; |
return; |
|
|
push(stack_dup_value(v, ©)); |
push(stack_dup_value(v, ©)); |
} |
} |
free_number(inumber); |
free_number(inumber); |
} else |
} |
warnx("internal error: reg num = %d", reg); |
|
} |
} |
|
|
static void |
static void |
|
|
struct value *value; |
struct value *value; |
struct stack *stack; |
struct stack *stack; |
|
|
reg = readch(); |
reg = readreg(); |
if (0 <= reg && reg < UCHAR_MAX) { |
if (reg >= 0) { |
inumber = pop_number(); |
inumber = pop_number(); |
if (inumber == NULL) |
if (inumber == NULL) |
return; |
return; |
|
|
frame_assign(stack, index, value); |
frame_assign(stack, index, value); |
} |
} |
free_number(inumber); |
free_number(inumber); |
} else |
} |
warnx("internal error: reg num = %d", reg); |
|
} |
} |
|
|
static void |
static void |
|
|
struct value *v; |
struct value *v; |
|
|
elseindex = NO_ELSE; |
elseindex = NO_ELSE; |
index = readch(); |
index = readreg(); |
if (readch() == 'e') |
if (readch() == 'e') |
elseindex = readch(); |
elseindex = readreg(); |
else |
else |
unreadch(); |
unreadch(); |
|
|
|
|
if (!ok && elseindex != NO_ELSE) |
if (!ok && elseindex != NO_ELSE) |
index = elseindex; |
index = elseindex; |
|
|
if (index < 0 || index > UCHAR_MAX) |
if (index >= 0 && (ok || (!ok && elseindex != NO_ELSE))) { |
warnx("internal error: reg num = %d", index); |
|
else if (ok || (!ok && elseindex != NO_ELSE)) { |
|
v = stack_tos(&bmachine.reg[index]); |
v = stack_tos(&bmachine.reg[index]); |
if (v == NULL) |
if (v == NULL) |
warnx("register '%c' (0%o) is empty", index, index); |
warnx("register '%c' (0%o) is empty", index, index); |
|
|
case '<': |
case '<': |
case '>': |
case '>': |
case '=': |
case '=': |
readch(); |
readreg(); |
if (readch() == 'e') |
if (readch() == 'e') |
readch(); |
readreg(); |
else |
else |
unreadch(); |
unreadch(); |
break; |
break; |
|
|
case '<': |
case '<': |
case '>': |
case '>': |
case '=': |
case '=': |
readch(); |
readreg(); |
if (readch() == 'e') |
if (readch() == 'e') |
readch(); |
readreg(); |
else |
else |
unreadch(); |
unreadch(); |
break; |
break; |