diff options
Diffstat (limited to 'mixlib/mix_vm_command.c')
-rw-r--r-- | mixlib/mix_vm_command.c | 243 |
1 files changed, 239 insertions, 4 deletions
diff --git a/mixlib/mix_vm_command.c b/mixlib/mix_vm_command.c index 9344618..0dc56c5 100644 --- a/mixlib/mix_vm_command.c +++ b/mixlib/mix_vm_command.c @@ -31,6 +31,7 @@ #include "mix_vm.h" #include "mix_vm_dump.h" #include "mix_eval.h" +#include "mix_predicate.h" #include "mix_vm_command.h" #ifdef HAVE_LIBHISTORY @@ -54,6 +55,8 @@ typedef struct gpointer data; } global_hook_; +#define PRNO_ MIX_PRED_MEM + struct mix_vm_cmd_dispatcher_t { mix_vm_t *vm; /* the virtual machine */ @@ -75,6 +78,8 @@ struct mix_vm_cmd_dispatcher_t global_hook_ global_pre; /* global pre-command hook */ global_hook_ global_post; /* global post-command hook */ mix_config_t *config; /* externally provided configuration */ + mix_predicate_t *preds[PRNO_]; /* predicates for conditional breakpoints */ + GHashTable *mem_preds; /* predicates for memory conditional bps */ }; /* command handlers */ @@ -113,6 +118,15 @@ DEC_FUN (sedit_); DEC_FUN (pasm_); DEC_FUN (sasm_); DEC_FUN (devdir_); +DEC_FUN (sbpr_); +DEC_FUN (sbpm_); +DEC_FUN (sbpc_); +DEC_FUN (sbpo_); +DEC_FUN (cbpr_); +DEC_FUN (cbpm_); +DEC_FUN (cbpc_); +DEC_FUN (cbpo_); + /* internal command info struct */ typedef struct { @@ -162,6 +176,22 @@ command_ commands_[] = { "sbpa ADDRESS"}, { "cbpa", cmd_cbpa_, N_("Clear break point at given address"), "cbpa ADDRESS"}, + { "sbpr", cmd_sbpr_, N_("Set conditional breakpoint on register change"), + "sbpr A | X | J | I[1-6]"}, + { "cbpr", cmd_cbpr_, N_("Clear conditional breakpoint on register change"), + "sbpr A | X | J | I[1-6]"}, + { "sbpm", cmd_sbpm_, N_("Set conditional breakpoint on mem cell change"), + "sbpm ADDRESS"}, + { "cbpm", cmd_cbpm_, N_("Clear conditional breakpoint on mem cell change"), + "cbpm ADDRESS"}, + { "sbpc", cmd_sbpc_, + N_("Set conditional breakpoint on comparison flag change"), "sbpc"}, + { "cbpc", cmd_cbpc_, + N_("Clear conditional breakpoint on comparison flag change"), "cbpc"}, + { "sbpo", cmd_sbpo_, + N_("Set conditional breakpoint on overflow toggled"), "sbpo"}, + { "cbpo", cmd_cbpo_, + N_("Set conditional breakpoint on overflow toggled"), "cbpo"}, { "cabp", cmd_cabp_, N_("Clear all breakpoints"), "cabp"}, { "weval", cmd_weval_, N_("Evaluate a given W-expression"), "weval WEXPR"}, { "w2d", cmd_w2d_, N_("Convert a MIX word to its decimal value"), @@ -251,6 +281,11 @@ mix_vm_cmd_dispatcher_new (FILE *out_fd, /* output messages file */ } result->config = NULL; + for (k = 0; k < PRNO_; ++k) + result->preds[k] = mix_predicate_new (k); + + result->mem_preds = g_hash_table_new (NULL, NULL); + return result; } @@ -296,10 +331,19 @@ mix_vm_cmd_dispatcher_new_with_config (FILE *out, FILE *err, /* delete (does not close the fds in the constructor) */ +static gboolean +del_pred_ (gpointer key, gpointer val, gpointer data) +{ + if (val) mix_predicate_delete ((mix_predicate_t *)val); + return TRUE; +} + void mix_vm_cmd_dispatcher_delete (mix_vm_cmd_dispatcher_t *dis) { const gchar *hfile = NULL; + gint k; + g_return_if_fail (dis != NULL); mix_eval_delete (dis->eval); mix_dump_context_delete (dis->dump); @@ -311,6 +355,8 @@ mix_vm_cmd_dispatcher_delete (mix_vm_cmd_dispatcher_t *dis) (dis->config))) write_history ((char *)hfile); #endif + for (k = 0; k < PRNO_; ++k) mix_predicate_delete (dis->preds[k]); + g_hash_table_foreach_remove (dis->mem_preds, del_pred_, NULL); g_free (dis); } @@ -734,10 +780,23 @@ cmd_run_ (mix_vm_cmd_dispatcher_t *dis, const gchar *arg) if (line != 0) fprintf (dis->out, _("... stopped: breakpoint at line %ld (address %d)\n"), - line, mix_vm_get_prog_count (dis->vm)); + line, mix_vm_get_prog_count (dis->vm)); else fprintf (dis->out, _("... stopped: breakpoint at address %d\n"), - mix_vm_get_prog_count (dis->vm)); + mix_vm_get_prog_count (dis->vm)); + } + break; + case MIX_VM_COND_BREAK: + { + gulong line = mix_vm_get_break_lineno (dis->vm); + if (line != 0) + fprintf (dis->out, _("... stopped: %s (line %ld, address %d)\n"), + mix_vm_get_last_breakpoint_message (dis->vm), + line, mix_vm_get_prog_count (dis->vm)); + else + fprintf (dis->out, _("... stopped: %s (address %d)\n"), + mix_vm_get_last_breakpoint_message (dis->vm), + mix_vm_get_prog_count (dis->vm)); } break; case MIX_VM_ERROR: @@ -861,7 +920,7 @@ cmd_preg_ (mix_vm_cmd_dispatcher_t *dis, const gchar *arg) int i = arg[1] - '1'; if ( i < 0 || i > 5 ) { - fprintf (dis->err, _("Invalid I index: %d"), i); + fprintf (dis->err, _("Invalid I index: %d\n"), i); return FALSE; } mix_dump_context_add_opt (dis->dump, opt[i]); @@ -1454,5 +1513,181 @@ cmd_devdir_ (mix_vm_cmd_dispatcher_t *dis, const gchar *arg) return TRUE; } - + +static const gint INVALID_REG_ = -2; + +static mix_predicate_type_t +get_reg_pred_ (const gchar *arg) +{ + mix_predicate_type_t pred = INVALID_REG_; + + switch (*arg) + { + case 'A': + pred = MIX_PRED_REG_A; + break; + case 'X': + pred = MIX_PRED_REG_X; + break; + case 'J': + pred = MIX_PRED_REG_J; + break; + case 'I': + { + if ( strlen (arg) == 2 ) + { + int i = arg[1] - '1'; + if ( i > 0 && i < 7 ) + pred = MIX_PRED_REG_I1 - 1 + i; + } + } + break; + default: + break; + } + return pred; +} + +static gboolean +cmd_sbpr_ (mix_vm_cmd_dispatcher_t *dis, const gchar *arg) +{ + mix_predicate_type_t pred = get_reg_pred_ (arg); + if (pred != INVALID_REG_) + { + mix_vm_set_conditional_breakpoint (dis->vm, dis->preds[pred]); + fprintf (dis->out, _("Conditional breakpoint on r%s change set\n"), arg); + return TRUE; + } + else + { + fprintf (dis->err, "Invalid argument %s\n", arg); + return FALSE; + } +} + +static gboolean +cmd_cbpr_ (mix_vm_cmd_dispatcher_t *dis, const gchar *arg) +{ + mix_predicate_type_t pred = get_reg_pred_ (arg); + if (pred != INVALID_REG_) + { + mix_vm_clear_conditional_breakpoint (dis->vm, dis->preds[pred]); + fprintf (dis->out, + _("Conditional breakpoint on r%s change removed\n"), + arg); + return TRUE; + } + else + { + fprintf (dis->err, _("Invalid argument %s\n"), arg); + return FALSE; + } +} + +static gboolean +cmd_sbpm_ (mix_vm_cmd_dispatcher_t *dis, const gchar *arg) +{ + gint add = atoi (arg); + gpointer key, value; + if (add < 0 || add > MIX_VM_CELL_NO) + { + fprintf (dis->out, _("Invalid memory address: %s\n"), arg); + return FALSE; + } + if (!g_hash_table_lookup_extended (dis->mem_preds, GINT_TO_POINTER (add), + &key, &value)) + { + mix_predicate_t *new_pred = mix_predicate_new (MIX_PRED_MEM); + mix_predicate_set_mem_address (new_pred, add); + g_hash_table_insert (dis->mem_preds, + GINT_TO_POINTER (add), (gpointer)new_pred); + mix_vm_set_conditional_breakpoint (dis->vm, new_pred); + } + fprintf (dis->out, _("Conditional breakpoint on mem cell no. %d set\n"), add); + return TRUE; +} + +static gboolean +cmd_cbpm_ (mix_vm_cmd_dispatcher_t *dis, const gchar *arg) +{ + gint add = atoi (arg); + gpointer key, value; + if (add < 0 || add > MIX_VM_CELL_NO) + { + fprintf (dis->out, _("Invalid memory address: %s\n"), arg); + return FALSE; + } + if (g_hash_table_lookup_extended (dis->mem_preds, GINT_TO_POINTER (add), + &key, &value)) + { + g_hash_table_remove (dis->mem_preds, key); + mix_vm_clear_conditional_breakpoint (dis->vm, (mix_predicate_t *)value); + mix_predicate_delete ((mix_predicate_t *)value); + fprintf (dis->out, + _("Conditional breakpoint on mem cell no. %d removed\n"), add); + } + else + { + fprintf (dis->out, _("No conditional breakpoint set at address %d\n"), + add); + } + return TRUE; +} + +static gboolean +cmd_sbpo_ (mix_vm_cmd_dispatcher_t *dis, const gchar *arg) +{ + if (arg && strlen (arg)) + fprintf (dis->err, _("Unexpected argument: %s\n"), arg); + else + { + mix_vm_set_conditional_breakpoint (dis->vm, dis->preds[MIX_PRED_OVER]); + fprintf (dis->out, + _("Conditional breakpoint on overflow toggled set.\n")); + } + return TRUE; +} + +static gboolean +cmd_cbpo_ (mix_vm_cmd_dispatcher_t *dis, const gchar *arg) +{ + if (arg && strlen (arg)) + fprintf (dis->err, _("Unexpected argument: %s\n"), arg); + else + { + mix_vm_clear_conditional_breakpoint (dis->vm, dis->preds[MIX_PRED_OVER]); + fprintf (dis->out, + _("Conditional breakpoint on overflow toggled removed.\n")); + } + return TRUE; +} + +static gboolean +cmd_sbpc_ (mix_vm_cmd_dispatcher_t *dis, const gchar *arg) +{ + if (arg && strlen (arg)) + fprintf (dis->err, _("Unexpected argument: %s\n"), arg); + else + { + mix_vm_set_conditional_breakpoint (dis->vm, dis->preds[MIX_PRED_CMP]); + fprintf (dis->out, + _("Conditional breakpoint on comparison flag changed set.\n")); + } + return TRUE; +} + +static gboolean +cmd_cbpc_ (mix_vm_cmd_dispatcher_t *dis, const gchar *arg) +{ + if (arg && strlen (arg)) + fprintf (dis->err, _("Unexpected argument: %s\n"), arg); + else + { + mix_vm_clear_conditional_breakpoint (dis->vm, dis->preds[MIX_PRED_CMP]); + fprintf (dis->out, + _("Conditional breakpoint on comparison flag changed removed.\n")); + } + return TRUE; +} + |