summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorJose Antonio Ortega Ruiz <jao@gnu.org>2004-06-06 19:53:13 +0000
committerJose Antonio Ortega Ruiz <jao@gnu.org>2004-06-06 19:53:13 +0000
commitc39f8e909b0fde21c586c09f2cb7c6538da1d492 (patch)
tree3fe339e6282eaeafd4680356da55ca7e7c07583e
parent4fcb279164c3bbc584b4121dfda04a393ff6e8d5 (diff)
downloadmdk-c39f8e909b0fde21c586c09f2cb7c6538da1d492.tar.gz
mdk-c39f8e909b0fde21c586c09f2cb7c6538da1d492.tar.bz2
keep track of runtime errors and correctly report them.
-rw-r--r--mixlib/xmix_vm.c123
-rw-r--r--mixlib/xmix_vm.h7
-rw-r--r--mixlib/xmix_vm_handlers.c53
3 files changed, 115 insertions, 68 deletions
diff --git a/mixlib/xmix_vm.c b/mixlib/xmix_vm.c
index 718a9d3..ecb67c9 100644
--- a/mixlib/xmix_vm.c
+++ b/mixlib/xmix_vm.c
@@ -56,6 +56,20 @@ get_dev_ (mix_vm_t *vm, mix_fspec_t type)
return vm->devices[type];
}
+/* error macro */
+#define fail_if_not_(vm,cond,error) \
+do { \
+ if (!(cond)) \
+ { \
+ set_last_error_ (vm, error); \
+ return FALSE; \
+ } \
+} while (FALSE)
+
+#define fail_(vm,error) fail_if_not_ (vm, FALSE, error)
+
+#define fail_unexpected_(vm) fail_ (vm, MIX_VM_ERROR_UNEXPECTED)
+
/* Instruction handlers */
static gboolean
@@ -136,7 +150,7 @@ spc_handler_ (mix_vm_t *vm, const mix_ins_t *ins)
mix_word_negative (num) : num);
break;
}
- default: return FALSE;
+ default: fail_ (vm, MIX_VM_ERROR_BAD_FSPEC);
}
inc_loc_ (vm);
return TRUE;
@@ -148,7 +162,8 @@ sla_handler_ (mix_vm_t *vm, const mix_ins_t *ins)
mix_short_t n = get_M_ (vm,ins);
g_assert (ins->opcode == mix_opSLx);
- g_return_val_if_fail (mix_short_is_positive (n), FALSE);
+
+ fail_if_not_ (vm, mix_short_is_positive (n), MIX_VM_ERROR_BAD_M);
switch ( mix_ins_id_from_ins (*ins) ) {
case mix_SLA:
@@ -174,7 +189,7 @@ sla_handler_ (mix_vm_t *vm, const mix_ins_t *ins)
&get_rA_ (vm), &get_rX_ (vm));
break;
default:
- return FALSE;
+ fail_unexpected_ (vm);
}
inc_loc_ (vm);
@@ -189,16 +204,19 @@ mov_handler_ (mix_vm_t *vm, const mix_ins_t *ins)
guint k, delta = ins->fspec;
g_assert (ins->opcode == mix_opMOVE);
- g_return_val_if_fail (mix_short_is_positive (from), FALSE);
- g_return_val_if_fail (mix_short_is_positive (to), FALSE);
- g_return_val_if_fail (MEMOK_ (from + delta -1), FALSE);
- g_return_val_if_fail (MEMOK_ (to + delta - 1), FALSE);
-
- for (k = 0; k < delta; ++k)
- set_cell_ (vm, to+k, get_cell_ (vm, from+k));
- set_rI_ (vm, 1, to+delta);
- inc_loc_ (vm);
- return TRUE;
+ if (mix_short_is_positive (from)
+ && mix_short_is_positive (to)
+ && MEMOK_ (from + delta -1)
+ && MEMOK_ (to + delta - 1))
+ {
+ for (k = 0; k < delta; ++k)
+ set_cell_ (vm, to+k, get_cell_ (vm, from+k));
+ set_rI_ (vm, 1, to+delta);
+ inc_loc_ (vm);
+ return TRUE;
+ }
+ else
+ return FALSE;
}
static gboolean
@@ -258,8 +276,10 @@ static gboolean
jbs_handler_ (mix_vm_t *vm, const mix_ins_t *ins)
{
g_assert (ins->opcode == mix_opJBUS);
- g_return_val_if_fail (ins->fspec < BD_NO_, TRUE);
- g_return_val_if_fail (get_dev_ (vm, ins->fspec) != NULL, TRUE);
+ fail_if_not_ (vm, ins->fspec < BD_NO_, MIX_VM_ERROR_BAD_DEVICE_NO);
+ fail_if_not_ (vm, get_dev_ (vm, ins->fspec) != NULL,
+ MIX_VM_ERROR_BAD_DEVICE_NO);
+
if ( mix_device_busy (get_dev_ (vm, ins->fspec)) ) {
set_rJ_ (vm, get_loc_ (vm));
set_loc_ (vm, get_M_ (vm, ins));
@@ -272,18 +292,19 @@ ioc_handler_ (mix_vm_t *vm, const mix_ins_t *ins)
{
mix_address_t addr;
mix_device_t *dev;
- gboolean result;
g_assert (ins->opcode == mix_opIOC);
+
addr = get_M_ (vm, ins);
- g_return_val_if_fail (ins->fspec < BD_NO_, TRUE);
+ fail_if_not_ (vm, ins->fspec < BD_NO_, MIX_VM_ERROR_BAD_DEVICE_NO);
+
dev = get_dev_ (vm, ins->fspec);
- g_return_val_if_fail (dev != NULL, TRUE);
- result =
- mix_device_ioc (dev, addr);
+ fail_if_not_ (vm, dev != NULL, MIX_VM_ERROR_BAD_DEVICE_NO);
+
+ fail_if_not_ (vm, mix_device_ioc (dev, addr), MIX_VM_ERROR_DEV_CTL);
inc_loc_ (vm);
- return result;
+ return TRUE;
}
static gboolean
@@ -291,21 +312,24 @@ inp_handler_ (mix_vm_t *vm, const mix_ins_t *ins)
{
mix_address_t addr;
mix_device_t *dev;
- gboolean result;
g_assert (ins->opcode == mix_opIN);
+ fail_if_not_ (vm, ins->fspec < BD_NO_, MIX_VM_ERROR_BAD_DEVICE_NO);
+
addr = get_M_ (vm, ins);
- g_return_val_if_fail (ins->fspec < BD_NO_, TRUE);
- g_return_val_if_fail (MEMOK_ (addr), TRUE);
+ fail_if_not_ (vm, MEMOK_ (addr), MIX_VM_ERROR_BAD_ACCESS);
+
dev = get_dev_ (vm, ins->fspec);
- g_return_val_if_fail ( dev != NULL, TRUE);
- g_return_val_if_fail (MEM_CELLS_NO_ - addr > mix_device_block_size (dev),
- TRUE);
- result =
- mix_device_read (dev, get_cell_ptr_ (vm, addr));
+ fail_if_not_ (vm, dev != NULL, MIX_VM_ERROR_BAD_DEVICE_NO);
+
+ fail_if_not_ (vm, MEM_CELLS_NO_ - addr > mix_device_block_size (dev),
+ MIX_VM_ERROR_BAD_ACCESS);
+
+ fail_if_not_ (vm, mix_device_read (dev, get_cell_ptr_ (vm, addr)),
+ MIX_VM_ERROR_DEV_READ);
inc_loc_ (vm);
- return result;
+ return TRUE;
}
static gboolean
@@ -313,29 +337,35 @@ out_handler_ (mix_vm_t *vm, const mix_ins_t *ins)
{
mix_address_t addr;
mix_device_t *dev;
- gboolean result;
g_assert (ins->opcode == mix_opOUT);
+
+ fail_if_not_ (vm, ins->fspec < BD_NO_, MIX_VM_ERROR_BAD_DEVICE_NO);
+
addr = get_M_ (vm, ins);
- g_return_val_if_fail (ins->fspec < BD_NO_, TRUE);
- g_return_val_if_fail (MEMOK_ (addr), TRUE);
+ fail_if_not_ (vm, MEMOK_ (addr), MIX_VM_ERROR_BAD_ACCESS);
+
dev = get_dev_ (vm, ins->fspec);
- g_return_val_if_fail ( dev != NULL, TRUE);
- g_return_val_if_fail (MEM_CELLS_NO_ - addr > mix_device_block_size (dev),
- TRUE);
- result =
- mix_device_write (dev, get_cell_ptr_ (vm, addr));
+ fail_if_not_ (vm, dev != NULL, MIX_VM_ERROR_BAD_DEVICE_NO);
+
+ fail_if_not_ (vm, MEM_CELLS_NO_ - addr > mix_device_block_size (dev),
+ MIX_VM_ERROR_BAD_ACCESS);
+
+ fail_if_not_ (vm, mix_device_write (dev, get_cell_ptr_ (vm, addr)),
+ MIX_VM_ERROR_DEV_WRITE);
inc_loc_ (vm);
- return result;
+ return TRUE;
}
static gboolean
jrd_handler_ (mix_vm_t *vm, const mix_ins_t *ins)
{
g_assert (ins->opcode == mix_opJRED);
- g_return_val_if_fail (ins->fspec < BD_NO_, TRUE);
- g_return_val_if_fail (get_dev_ (vm, ins->fspec) != NULL, TRUE);
+ fail_if_not_ (vm, ins->fspec < BD_NO_, MIX_VM_ERROR_BAD_DEVICE_NO);
+ fail_if_not_ (vm, get_dev_ (vm, ins->fspec) != NULL,
+ MIX_VM_ERROR_BAD_DEVICE_NO);
+
inc_loc_ (vm);
if ( !mix_device_busy (get_dev_ (vm, ins->fspec)) )
{
@@ -353,7 +383,8 @@ jmp_handler_ (mix_vm_t *vm, const mix_ins_t *ins)
mix_ins_id_t id = mix_ins_id_from_ins (*ins);
g_assert (ins->opcode == mix_opJMP);
- g_return_val_if_fail (MEMOK_ (addr), FALSE);
+ fail_if_not_ (vm, MEMOK_ (addr), MIX_VM_ERROR_BAD_ACCESS);
+
switch ( id ) {
case mix_JMP:
case mix_JSJ:
@@ -386,7 +417,7 @@ jmp_handler_ (mix_vm_t *vm, const mix_ins_t *ins)
jump = ( get_cmp_ (vm) != mix_GREAT );
break;
default:
- return FALSE;
+ fail_unexpected_ (vm);
}
inc_loc_ (vm);
@@ -406,7 +437,7 @@ jpx_handler_ (mix_vm_t *vm, const mix_ins_t *ins)
mix_word_t val;
g_assert (ins->opcode >= mix_opJAx || ins->opcode <= mix_opJXx);
- g_return_val_if_fail (MEMOK_ (addr), FALSE);
+ fail_if_not_ (vm, MEMOK_ (addr), MIX_VM_ERROR_BAD_ACCESS);
switch (ins->opcode) {
case mix_opJAx: val = get_rA_ (vm); break;
@@ -448,7 +479,7 @@ jpx_handler_ (mix_vm_t *vm, const mix_ins_t *ins)
|| mix_word_is_negative (val);
break;
default:
- return FALSE;
+ fail_unexpected_ (vm);
}
inc_loc_ (vm);
@@ -509,7 +540,7 @@ ina_handler_ (mix_vm_t *vm, const mix_ins_t *ins)
mix_word_reverse_sign (val);
break;
default:
- return FALSE;
+ fail_unexpected_ (vm);
}
set_reg_ (vm, r, val);
inc_loc_ (vm);
diff --git a/mixlib/xmix_vm.h b/mixlib/xmix_vm.h
index 45805e8..f4773eb 100644
--- a/mixlib/xmix_vm.h
+++ b/mixlib/xmix_vm.h
@@ -2,9 +2,9 @@
* This file contains internal declarations used in the implementation
* of the mix_vm_t type.
* ------------------------------------------------------------------
- * $Id: xmix_vm.h,v 1.8 2003/01/12 21:05:01 jao Exp $
+ * $Id: xmix_vm.h,v 1.9 2004/06/06 19:53:13 jao Exp $
* ------------------------------------------------------------------
- * Copyright (C) 2000, 2002, 2003 Free Software Foundation, Inc.
+ * Copyright (C) 2000, 2002, 2003, 2004 Free Software Foundation, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -50,6 +50,7 @@ struct mix_vm_t
mix_cmpflag_t cmpflag;
mix_short_t loc_count;
mix_vm_status_t status;
+ mix_vm_error_t last_error;
mix_device_t * devices[BD_NO_];
mix_address_t start_addr; /* start address of loaded file */
GTree *line_table; /* source line no -> address */
@@ -86,6 +87,8 @@ enum { A_ = 0, X_, J_, I1_, I2_, I3_, I4_, I5_, I6_ };
#define get_pred_list_(vm) (vm->pred_list)
#define get_address_list_(vm) (vm->address_list)
#define get_status_(vm) (vm->status)
+#define get_last_error_(vm) (vm->last_error)
+#define set_last_error_(vm,error) ((vm)->last_error = (error))
#define set_reg_(vm,r,x) \
do { \
diff --git a/mixlib/xmix_vm_handlers.c b/mixlib/xmix_vm_handlers.c
index 4d0285f..a778750 100644
--- a/mixlib/xmix_vm_handlers.c
+++ b/mixlib/xmix_vm_handlers.c
@@ -1,9 +1,9 @@
/* -*-c-*- -------------- xmix_vm_handlers.c :
* Implementation of the functions declared in xmix_vm_handlers.h
* ------------------------------------------------------------------
- * $Id: xmix_vm_handlers.c,v 1.7 2003/01/11 22:43:13 jao Exp $
+ * $Id: xmix_vm_handlers.c,v 1.8 2004/06/06 19:54:11 jao Exp $
* ------------------------------------------------------------------
- * Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc.
+ * Copyright (C) 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -103,31 +103,42 @@ mix_vm_command_info_t commands_[] = {
/* trace current instruction */
static void
-trace_ (mix_vm_cmd_dispatcher_t *dis)
+do_trace_ (mix_vm_cmd_dispatcher_t *dis, gboolean error)
{
enum {BUFFER_LEN = 128};
static gchar STRINS[BUFFER_LEN];
- if (wants_logs_ (dis))
+ const mix_src_file_t *file = mix_vm_get_src_file (dis->vm);
+ const gchar *line = "\n";
+ mix_address_t loc = mix_vm_get_prog_count (dis->vm);
+ mix_word_t ins = mix_vm_get_addr_contents (dis->vm, loc);
+ mix_ins_t fins;
+ mix_word_to_ins_uncheck (ins, fins);
+ mix_ins_to_string_in_buffer (&fins, STRINS, BUFFER_LEN);
+
+ if (file != NULL)
{
- const mix_src_file_t *file = mix_vm_get_src_file (dis->vm);
- const gchar *line = "\n";
- mix_address_t loc = mix_vm_get_prog_count (dis->vm);
- mix_word_t ins = mix_vm_get_addr_contents (dis->vm, loc);
- mix_ins_t fins;
- mix_word_to_ins_uncheck (ins, fins);
- mix_ins_to_string_in_buffer (&fins, STRINS, BUFFER_LEN);
+ gulong b = mix_vm_get_break_lineno (dis->vm);
+ if (b > 0) line = mix_src_file_get_line (file, b);
+ }
- if (file != NULL)
- {
- gulong b = mix_vm_get_break_lineno (dis->vm);
- if (b > 0) line = mix_src_file_get_line (file, b);
- }
+ if (!error)
+ log_message_ (dis, "%d: [%-15s]\t%s", (gint)loc, STRINS, line);
+ else
+ log_error_ (dis, "%d: [%-15s]\t%s", (gint)loc, STRINS, line);
+}
- log_message_ (dis, "%d: [%-15s]\t%s", (gint)loc, STRINS, line);
+static void
+trace_ (mix_vm_cmd_dispatcher_t *dis)
+{
+ if (wants_logs_ (dis))
+ {
+ do_trace_ (dis, FALSE);
}
}
+#define trace_error_(dis) do_trace_ (dis, TRUE)
+
/* run a program tracing executed instructions */
static int
run_and_trace_ (mix_vm_cmd_dispatcher_t *dis)
@@ -328,12 +339,14 @@ cmd_run_ (mix_vm_cmd_dispatcher_t *dis, const gchar *arg)
}
break;
case MIX_VM_ERROR:
- log_error_ (dis, _("... error executing loaded file"));
+ log_error_ (dis, _("%s:"), mix_vm_get_last_error_string (dis->vm));
+ trace_error_ (dis);
break;
default:
g_assert_not_reached ();
break;
}
+
if (wants_logs_ (dis)) print_time_ (dis);
return TRUE;
@@ -373,8 +386,8 @@ cmd_next_ (mix_vm_cmd_dispatcher_t *dis, const gchar *arg)
}
else if (k == MIX_VM_ERROR)
{
- log_error_ (dis, _("Error at address %d"),
- mix_vm_get_prog_count (dis->vm));
+ log_error_ (dis, _("%s:"), mix_vm_get_last_error_string (dis->vm));
+ trace_error_ (dis);
break;
}
}