diff options
| -rw-r--r-- | mixlib/mix_vm_command.c | 243 | ||||
| -rw-r--r-- | mixlib/mix_vm_command.h | 8 | ||||
| -rw-r--r-- | mixutils/mixvm_command.c | 6 | ||||
| -rw-r--r-- | samples/.cvsignore | 1 | ||||
| -rw-r--r-- | samples/cbp.mixal | 13 | 
5 files changed, 264 insertions, 7 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; +} + diff --git a/mixlib/mix_vm_command.h b/mixlib/mix_vm_command.h index 45e2c8c..6c60264 100644 --- a/mixlib/mix_vm_command.h +++ b/mixlib/mix_vm_command.h @@ -63,6 +63,14 @@ typedef enum {    MIX_CMD_CBP,			/* clear breakpoint at lineno */    MIX_CMD_SBPA,			/* set breakpoint at address */    MIX_CMD_CBPA,			/* clear breakpoint at address */ +  MIX_CMD_SBPR,			/* set breakpoint on register changed */ +  MIX_CMD_CBPR,			/* clear breakpoint on register changed */ +  MIX_CMD_SBPM,			/* set breakpoint on mem cell changed */ +  MIX_CMD_CBPM,			/* clear breakpoint on mem cell changed */ +  MIX_CMD_SBPC,			/* set breakpoint on comp flag changed */ +  MIX_CMD_CBPC,			/* clear breakpoint on comp flag changed */ +  MIX_CMD_SBPO,			/* set breakpoint on overflow toggled */ +  MIX_CMD_CBPO,			/* clear breakpoint on overflow toggled */    MIX_CMD_CABP,			/* clear all breakpoints */    MIX_CMD_WEVAL,		/* evaluate a w-expression */    MIX_CMD_W2D,			/* print word in decimal notation */ diff --git a/mixutils/mixvm_command.c b/mixutils/mixvm_command.c index b8bef53..d13e5ac 100644 --- a/mixutils/mixvm_command.c +++ b/mixutils/mixvm_command.c @@ -76,7 +76,7 @@ static const char *mix_commands_[ALL_COMMANDS_NO_] = {NULL};  #ifdef HAVE_LIBREADLINE  /* readline functions */  static char * -mixvm_cmd_generator_ (char *text, int state); +mixvm_cmd_generator_ (const char *text, int state);  /* Attempt to complete on the contents of TEXT.  START and END bound the @@ -95,7 +95,7 @@ mixvm_cmd_completion_ (char *text, int start, int end)       to complete.  Otherwise it is the name of a file in the current       directory. */    if (start == 0) -    matches = completion_matches (text, mixvm_cmd_generator_); +    matches = rl_completion_matches (text, mixvm_cmd_generator_);    return (matches);  } @@ -104,7 +104,7 @@ mixvm_cmd_completion_ (char *text, int start, int end)     to start from scratch; without any state (i.e. STATE == 0), then we     start at the top of the list. */  static char * -mixvm_cmd_generator_ (char *text, int state) +mixvm_cmd_generator_ (const char *text, int state)  {    static int list_index, len;    const char *name; diff --git a/samples/.cvsignore b/samples/.cvsignore index 18ddd94..bebe302 100644 --- a/samples/.cvsignore +++ b/samples/.cvsignore @@ -1,6 +1,7 @@  Makefile  Makefile.in  cardwr.dev +cbp.mix  disk0.dev  disk1.dev  disk2.dev diff --git a/samples/cbp.mixal b/samples/cbp.mixal new file mode 100644 index 0000000..b436c8c --- /dev/null +++ b/samples/cbp.mixal @@ -0,0 +1,13 @@ +* testing conditional breakpoints +	ORIG	2000 +START	ENTA	100 +	STA	1000 +	ENTX	200 +	STX     1001 +	CMPA	1001 	* cmp flag changed +	CMPX	1000    * cmp flag changed +	DIV	1002    * over toggle +	END	START + +	 +	 | 
