⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 xmix_vm_handlers.c

📁 汇编语言编程源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
/* -*-c-*- -------------- xmix_vm_handlers.c : * Implementation of the functions declared in xmix_vm_handlers.h * ------------------------------------------------------------------ *  $Id: xmix_vm_handlers.c,v 1.4 2001/09/17 23:26:43 jao Exp $ * ------------------------------------------------------------------ * Copyright (C) 2001 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 * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. *   * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. *   * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *   */#include "xmix_vm_handlers.h"/* available commands (in the same order as the type enum) */mix_vm_command_info_t commands_[] = {  { "help", cmd_help_, N_("Display this text"), "help [COMMAND]"},  { "load", cmd_load_, N_("Load a MIX code file"), "load FILENAME"},  { "edit", cmd_edit_, N_("Edit a MIXAL source file"), "edit [FILENAME]"},  { "pedit", cmd_pedit_, N_("Print the external editor command"), "pedit"},  { "sedit", cmd_sedit_, N_("Set the external editor command"),    "sedit COMMAND (e.g. emacs %s)"},  { "compile", cmd_compile_, N_("Compile a MIXAL source file"),    "compile [FILENAME]"},  { "pasm", cmd_pasm_, N_("Print the compile command"), "pasm"},  { "sasm", cmd_sasm_, N_("Set the compile command"),    "sasm COMMAND (e.g. mixasm -g -l %s)"},  { "run", cmd_run_, N_("Run loaded or given MIX code file"),     "run [FILENAME]"},  { "next", cmd_next_, N_("Execute next instruction(s)"),     "next [NO_OF_INS]"},  { "pstat", cmd_pstat_, N_("Print current vm status"), "pstat"},  { "pc", cmd_pc_, N_("Print program counter value"), "pc" },  { "psym", cmd_psym_, N_("Print symbol value"), "psym [SYMBOLNAME]"},  { "preg", cmd_preg_, N_("Print register value"),     "preg [A | X | J | I[1-6]]"},  { "pflags", cmd_pflags_, N_("Print comparison and overflow flags"),     "pflags"},  { "pall", cmd_pall_, N_("Print all registers and flags"), "pall"},  { "pmem", cmd_pmem_, N_("Print memory contents in address range"),     "pmem FROM[-TO]"},  { "sreg", cmd_sreg_, N_("Set register value"),     "preg A | X | J | I[1-6] VALUE"},  { "scmp", cmd_scmp_, N_("Set comparison flag value"), "scmp L | E | G"},  { "sover", cmd_sover_, N_("Set overflow flag value"), "sover T | F" },  { "smem", cmd_smem_, N_("Set memory contents in given address"),     "smem ADDRESS VALUE"},  { "ssym", cmd_ssym_, N_("Set a symbol\'s value"), "ssym SYMBOL WEXPR"},  { "sbp", cmd_sbp_, N_("Set break point at given line"), "sbp LINENO"},  { "cbp", cmd_cbp_, N_("Clear break point at given line"), "cbp LINENO"},  { "sbpa", cmd_sbpa_, N_("Set break point at given address"),    "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"),    "w2d WORD"},  { "strace", cmd_strace_, N_("Turn on/off instruction tracing"),    "strace on|off"},  { "pbt", cmd_pbt_, N_("Print backtrace of executed instructions"),    "pbt [INS_NO] (e.g pbt 5)"},  { "stime", cmd_stime_, N_("Turn on/off timing statistics"),    "stime on|off"},  { "ptime", cmd_ptime_, N_("Print current time statistics"), "ptime"},  { "sddir", cmd_sddir_, N_("Set devices directory"),"sddir NEWDIR"},  { "pddir", cmd_pddir_, N_("Print current devices directory"),"pddir"},  { "slog", cmd_slog_, N_("Turn on/off message logging"), "slog on|off"},  { "pprog", cmd_pprog_, N_("Print the current program path"), "pprog"},  { "psrc", cmd_psrc_, N_("Print the current program source path"), "psrc"},  { "pline", cmd_pline_,    N_("Print the current (or a given) program source line"), "pline [LINENO]"},  { NULL, NULL, NULL, NULL},};/* trace current instruction */static voidtrace_ (mix_vm_cmd_dispatcher_t *dis){  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)	{	  gulong b = mix_vm_get_break_lineno (dis->vm);	  if (b > 0) line = mix_src_file_get_line (file, b);	}            log_message_ (dis, "%d: [%-15s]\t%s", (gint)loc, STRINS, line);    }}/* run a program tracing executed instructions */static intrun_and_trace_ (mix_vm_cmd_dispatcher_t *dis){  int k = MIX_VM_RUNNING;  if (!dis->trace)    return mix_vm_run (dis->vm);  else while (k == MIX_VM_RUNNING)    {      trace_ (dis);      k = mix_vm_exec_next (dis->vm);    }  return k;}/* print time statistics */static voidprint_time_ (mix_vm_cmd_dispatcher_t *dis){  dis->laptime = mix_vm_get_uptime (dis->vm) - dis->uptime;  dis->uptime += dis->laptime;  dis->progtime += dis->laptime;  if (dis->printtime)    fprintf      (dis->out,       _("Elapsed time: %ld /Total program time: %ld (Total uptime: %ld)\n"),       dis->laptime, dis->progtime, dis->uptime);}/* commands */static voidprint_help_ (gpointer key, gpointer val, gpointer data){  mix_vm_command_info_t *info = (mix_vm_command_info_t *)val;  if (info)    fprintf ((FILE *)data, "%-15s%s\n", info->name, info->doc);}gbooleancmd_help_ (mix_vm_cmd_dispatcher_t *dis, const gchar *arg){  if (arg && strlen (arg) > 0)    {      int i;      mix_vm_command_info_t *info =	(mix_vm_command_info_t *)g_hash_table_lookup	(dis->commands, (gpointer)arg);      for (i = 0; info == NULL && commands_[i].name; i++)	if (!strcmp (commands_[i].name, arg)) info = commands_ + i;      if (info)	{	  fprintf (dis->out , _("%-15s%s.\n%-15sUsage: %s\n"),		   info->name, info->doc, "", info->usage);	  return TRUE;	}      fprintf (dis->out, _("No commands match `%s'\n"), arg);      return FALSE;    }  else    {      int i = 0;      fprintf (dis->out, _("Possible commands are:\n"));      for (i = 0; commands_[i].name; ++i)	fprintf (dis->out, "%-15s%s\n", commands_[i].name, commands_[i].doc);      g_hash_table_foreach (dis->commands, print_help_, (gpointer)dis->out);      return TRUE;    }}gbooleancmd_load_ (mix_vm_cmd_dispatcher_t *dis, const gchar *arg){  errno = 0;  if (arg == NULL || *arg == '\0')    {      log_error_ (dis, _("Missing file name"));      return FALSE;    }  mix_eval_remove_symbols_from_table (dis->eval,				      mix_vm_get_symbol_table (dis->vm));  if (!mix_vm_load_file (dis->vm, arg) )    {      log_error_ (dis, _("Cannot load %s: "));      if ( errno == 0 )	log_error_ (dis, _("Wrong file format"));      else	log_error_ (dis, "%s", strerror (errno));      return FALSE;    }  if (dis->program != arg)    {      if (dis->program) g_free (dis->program);      dis->program = mix_file_complete_name (arg, MIX_CODE_DEFEXT);    }  mix_eval_set_symbols_from_table (dis->eval,				   mix_vm_get_symbol_table (dis->vm));  if (wants_logs_ (dis))    log_message_ (dis, _("Program loaded. Start address: %d"),		  mix_vm_get_prog_count (dis->vm));    dis->laptime = dis->progtime = 0;  return TRUE;}gbooleancmd_edit_ (mix_vm_cmd_dispatcher_t *dis, const gchar *arg){  if (dis->editor == NULL)    {      log_error_ (dis, _("Editor not specified (use sedit)"));      return FALSE;    }  if (!arg || *arg == '\0') arg = mix_vm_cmd_dispatcher_get_src_file_path (dis);  if (!arg)    {      log_error_ (dis, _("MIXAL source file path not found"));      return FALSE;    }  else    {      gchar *cmd = g_strdup_printf (dis->editor, arg);      if (wants_logs_ (dis)) log_message_ (dis, cmd);      system (cmd);      if (wants_logs_ (dis)) log_message_ (dis, _(" ...done"));      g_free (cmd);      return TRUE;    }}gbooleancmd_compile_ (mix_vm_cmd_dispatcher_t *dis, const gchar *arg){  if (dis->assembler == NULL)    {      log_error_ (dis, _("MIX assembler not specified (use sasm)"));      return FALSE;    }  if (!arg || *arg == '\0') arg = mix_vm_cmd_dispatcher_get_src_file_path (dis);  if (!arg)    {      log_error_ (dis, _("MIXAL source file path not found"));      return FALSE;    }  else    {      gchar *cmd = g_strdup_printf (dis->assembler, arg);      if (wants_logs_ (dis)) log_message_ (dis, cmd);      if (system (cmd) == EXIT_SUCCESS && wants_logs_ (dis))	log_message_ (dis, _("Successful compilation"));      g_free (cmd);      return TRUE;    }}gbooleancmd_run_ (mix_vm_cmd_dispatcher_t *dis, const gchar *arg){  if (arg != NULL && *arg != '\0' && cmd_load_ (dis, arg) != TRUE)     return FALSE;    if (mix_vm_is_halted (dis->vm)) cmd_load_ (dis, dis->program);      if (wants_logs_ (dis)) log_message_ (dis, _("Running ..."));  switch (run_and_trace_ (dis))    {    case MIX_VM_HALT:      if (wants_logs_ (dis)) log_message_ (dis, _("... done"));      break;    case MIX_VM_BREAK:      if (wants_logs_ (dis))	{	  gulong line = mix_vm_get_break_lineno (dis->vm);	  if (line != 0)	    log_message_	      (dis, _("... stopped: breakpoint at line %ld (address %d)"), 	       line, mix_vm_get_prog_count (dis->vm));	  else	    log_message_ (dis, _("... stopped: breakpoint at address %d"),			  mix_vm_get_prog_count (dis->vm));      }      break;    case MIX_VM_COND_BREAK:      if (wants_logs_ (dis))	{	  gulong line = mix_vm_get_break_lineno (dis->vm);	  if (line != 0)	    log_message_ (dis, _("... stopped: %s (line %ld, address %d)"),			  mix_vm_get_last_breakpoint_message (dis->vm),			  line, mix_vm_get_prog_count (dis->vm));	  else	    log_message_ (dis, _("... stopped: %s (address %d)"),			  mix_vm_get_last_breakpoint_message (dis->vm),			  mix_vm_get_prog_count (dis->vm));	}      break;    case MIX_VM_ERROR:      log_error_ (dis, _("... error executing loaded file"));      break;    default:      g_assert_not_reached ();      break;    }  if (wants_logs_ (dis)) print_time_ (dis);  return TRUE;}gbooleancmd_next_ (mix_vm_cmd_dispatcher_t *dis, const gchar *arg){  int ins_no = 1;  int k;  if ( strlen (arg) != 0 )    {      int k = 0;      while (isdigit (arg[k]))	k++;      if (arg[k] != '\0')	{	  log_error_ (dis, _("Invalid argument: %s"), arg);	  return FALSE;	}      ins_no = atoi (arg);    }  if (mix_vm_is_halted (dis->vm)) cmd_load_ (dis, dis->program);      while ( ins_no-- > 0 )    {      if (dis->trace) trace_ (dis);      k = mix_vm_exec_next (dis->vm);      if (k == MIX_VM_HALT)	{	  if (wants_logs_ (dis))	    log_message_(dis, _("End of program reached at address %d"),			 mix_vm_get_prog_count (dis->vm));	  break;	}      else if (k == MIX_VM_ERROR)	{	  log_error_ (dis, _("Error at address %d"),		      mix_vm_get_prog_count (dis->vm));	  break;	}    }  if (wants_logs_ (dis)) print_time_ (dis);  return TRUE;}gbooleancmd_pc_ (mix_vm_cmd_dispatcher_t *dis, const gchar *arg){  fprintf (dis->out, "Current address: %d\n", mix_vm_get_prog_count (dis->vm));  return TRUE;}gbooleancmd_psym_ (mix_vm_cmd_dispatcher_t *dis, const gchar *arg){  gboolean result = FALSE;  const mix_symbol_table_t *table = mix_eval_symbol_table (dis->eval);  if ( table == NULL )    log_error_ (dis, _("Symbol table not available"));  else if (arg != NULL && *arg != '\0')    {      if ( mix_symbol_table_is_defined (table, arg) )	{	  mix_word_print_to_file (mix_symbol_table_value (table, arg),				  NULL, dis->out);	  putc ('\n', dis->out);	  result = TRUE;	}      else	fprintf (dis->out, _("%s: symbol not defined\n"), arg);    }  else    {      mix_symbol_table_print (table, MIX_SYM_ROWS, dis->out, TRUE);      result = TRUE;    }        return result;}gbooleancmd_preg_ (mix_vm_cmd_dispatcher_t *dis, const gchar *arg){  mix_dump_context_set_opt (dis->dump, MIX_DUMP_NONE);  if ( strlen (arg) == 0 )    mix_dump_context_add_opt (dis->dump, MIX_DUMP_rALL);  else switch (*arg)    {    case 'A':      mix_dump_context_add_opt (dis->dump, MIX_DUMP_rA);      break;    case 'X':      mix_dump_context_add_opt (dis->dump, MIX_DUMP_rX);      break;    case 'J':      mix_dump_context_add_opt (dis->dump, MIX_DUMP_rJ);      break;    case 'I':      {	if ( strlen (arg) == 1 )	  mix_dump_context_add_opt (dis->dump, MIX_DUMP_rIa);	else	  {	    static gint32 opt[] = { MIX_DUMP_rI1, MIX_DUMP_rI2,				    MIX_DUMP_rI3, MIX_DUMP_rI4,				    MIX_DUMP_rI5, MIX_DUMP_rI6 	    };	    int i = arg[1] - '1';	    if ( i < 0 || i > 5 )	      {		log_error_ (dis, _("Invalid I index: %d"), i);		return FALSE;	      }	    mix_dump_context_add_opt (dis->dump, opt[i]);	  }      }      break;    default:

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -