📄 xmixguile_cmd_dispatcher.c
字号:
/* -*-c-*- -------------- xmixguile_cmd_dispatcher.c : * Implementation of the functions declared in xmixguile_cmd_dispatcher.h * ------------------------------------------------------------------ * $Id: xmixguile_cmd_dispatcher.c,v 1.8 2001/09/25 21:41:11 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 <mixlib/mix.h>#include <guile/gh.h>#include "xmixguile_cmd_dispatcher.h"/* cmd dispatcher for use within the scm commands */static mixguile_cmd_dispatcher_t *dispatcher_;static mix_vm_cmd_dispatcher_t *vm_dispatcher_;static mix_vm_t *vm_;/* register a NULL-terminated list of scm commands */voidregister_scm_commands_ (const scm_command_t *commands){ int k = 0; g_return_if_fail (commands != NULL); while (commands[k].name) { gh_new_procedure (commands[k].name, commands[k].func, commands[k].argno, commands[k].opt_argno, commands[k].restp); ++k; }}/* register the mixvm cmd dispatcher to use with commands */voidregister_cmd_dispatcher_ (mixguile_cmd_dispatcher_t *dis){ g_return_if_fail (dis != NULL); dispatcher_ = dis; vm_dispatcher_ = mixguile_cmd_dispatcher_get_vm_dispatcher (dis); vm_ = (mix_vm_t *) mix_vm_cmd_dispatcher_get_vm (vm_dispatcher_);}/* commands */static SCMmixvm_cmd_ (SCM cmd, SCM arg){ char *com = NULL, *argu = NULL; int len; gboolean result; SCM_ASSERT (SCM_STRINGP (cmd) || SCM_SYMBOLP (cmd), cmd, SCM_ARG1, "mixvm-cmd"); SCM_ASSERT (SCM_STRINGP (arg) || SCM_SYMBOLP (arg), arg, SCM_ARG2, "mixvm-cmd"); SCM_DEFER_INTS; com = gh_scm2newstr (cmd, &len); argu = gh_scm2newstr (arg, &len); result = mix_vm_cmd_dispatcher_dispatch (vm_dispatcher_, mix_vm_command_from_string (com), argu); g_free (com); g_free (argu); SCM_ALLOW_INTS; return SCM_UNSPECIFIED;}static SCMmixvm_status_ (void){ return gh_long2scm (mix_vm_get_run_status (vm_));}static SCMmix_last_result_ (void){ return gh_bool2scm (mix_vm_cmd_dispatcher_get_last_result (vm_dispatcher_));}static longword_to_long_ (mix_word_t word){ long result = mix_word_magnitude (word); return mix_word_is_negative (word) ? -result : result;}static longshort_to_long_ (mix_short_t s){ long result = mix_short_magnitude (s); return mix_short_is_negative (s) ? -result : result;}static SCMmix_reg_ (SCM reg){ char *regis; int len; long val = MIX_WORD_MAX + 1; SCM_ASSERT (SCM_STRINGP (reg) || SCM_SYMBOLP (reg), reg, SCM_ARG1, "mix-reg"); SCM_DEFER_INTS; regis = gh_scm2newstr (reg, &len); switch (regis[0]) { case 'A': val = word_to_long_ (mix_vm_get_rA (vm_)); break; case 'X': val = word_to_long_ (mix_vm_get_rX (vm_)); break; case 'J': val = short_to_long_ (mix_vm_get_rJ (vm_)); break; case 'I': { int i = regis[1] - '0'; if (i > 0 && i < 7) val = short_to_long_ (mix_vm_get_rI (vm_, i)); } break; default: break; } g_free (regis); SCM_ALLOW_INTS; SCM_ASSERT (val <= MIX_WORD_MAX, reg, SCM_ARG1, "mix-reg"); return gh_long2scm (val);}static SCMmix_set_reg_ (SCM reg, SCM value){ char *regis; int len; long val; gboolean result = TRUE; SCM_ASSERT (SCM_STRINGP (reg) || SCM_SYMBOLP (reg), reg, SCM_ARG1, "mix-set-reg!"); SCM_ASSERT (SCM_NUMBERP (value), value, SCM_ARG2, "mix-set-reg!"); SCM_DEFER_INTS; regis = gh_scm2newstr (reg, &len); val = gh_scm2long (value); switch (regis[0]) { case 'A': mix_vm_set_rA (vm_, mix_word_new (val)); break; case 'X': mix_vm_set_rX (vm_, mix_word_new (val)); break; case 'J': mix_vm_set_rJ (vm_, mix_short_new (val)); break; case 'I': { int i = regis[1] - '0'; if (i > 0 && i < 7) mix_vm_set_rI (vm_, i, mix_short_new (val)); else result = FALSE; } break; default: result = FALSE; break; } g_free (regis); SCM_ALLOW_INTS; SCM_ASSERT (result, reg, SCM_ARG1, "mix-set-reg!"); return gh_symbol2scm ("ok");}static SCMmix_cell_ (SCM no){ int cell; long result; SCM_ASSERT (SCM_NUMBERP (no), no, SCM_ARG1, "mix-cell"); cell = gh_scm2int (no); SCM_ASSERT (cell < MIX_VM_CELL_NO, no, SCM_ARG1, "mix-cell"); result = word_to_long_ (mix_vm_get_addr_contents (vm_, cell)); return gh_long2scm (result);}static SCMmix_set_cell_ (SCM no, SCM val){ int cell; long result; SCM_ASSERT (SCM_NUMBERP (no), no, SCM_ARG1, "mix-set-cell!"); SCM_ASSERT (SCM_NUMBERP (val), no, SCM_ARG2, "mix-set-cell!"); cell = gh_scm2int (no); SCM_ASSERT (cell < MIX_VM_CELL_NO, no, SCM_ARG1, "mix-set-cell!"); result = gh_scm2long (val); mix_vm_set_addr_contents (vm_, cell, mix_word_new (result)); return gh_symbol2scm ("ok");}static SCMmix_over_ (void){ return gh_bool2scm (mix_vm_get_overflow (vm_));}static SCMmix_set_over_ (SCM over){ mix_vm_set_overflow (vm_, gh_scm2bool (over)); return gh_symbol2scm ("ok");}static SCMmix_loc_ (void){ return gh_long2scm (mix_vm_get_prog_count (vm_));}static SCMmix_cmp_ (void){ gchar *result = NULL; switch (mix_vm_get_cmpflag (vm_)) { case mix_LESS: result = "L"; break; case mix_EQ: result = "E"; break; case mix_GREAT: result = "G"; break; default: g_assert_not_reached (); } return gh_symbol2scm (result);}static SCMmix_set_cmp_ (SCM value){ gchar *val = NULL; int len; mix_cmpflag_t result = -1; SCM_ASSERT (SCM_STRINGP (value) || SCM_SYMBOLP (value), value, SCM_ARG1, "mix-set-cmp!"); SCM_DEFER_INTS; val = gh_scm2newstr (value, &len); if (strlen (val) == 1) { switch (val[0]) { case 'L': result = mix_LESS; break; case 'E': result = mix_EQ; break; case 'G': result = mix_GREAT; break; default: break; } } g_free (val); SCM_ALLOW_INTS; SCM_ASSERT (result != -1, value, SCM_ARG1, "mix-set-cmp!"); mix_vm_set_cmpflag (vm_, result); return gh_symbol2scm ("ok");}static SCMmix_src_name_ (void){ const gchar *path = mix_vm_cmd_dispatcher_get_src_file_path (vm_dispatcher_); return gh_str02scm (path? g_basename (path) : "");}static SCMmix_src_path_ (void){ const gchar *path = mix_vm_cmd_dispatcher_get_src_file_path (vm_dispatcher_); return gh_str02scm (path? (char *)path : "");}static SCMmix_prog_name_ (void){ const gchar *path = mix_vm_cmd_dispatcher_get_program_path (vm_dispatcher_); return gh_str02scm (path? g_basename (path) : "");}static SCMmix_prog_path_ (void){ const gchar *path = mix_vm_cmd_dispatcher_get_program_path (vm_dispatcher_); return gh_str02scm (path? (char *)path : "");}static SCMmix_ddir_ (void){ return gh_str02scm ((char *)mix_device_get_dir ());}static SCMmix_uptime_ (void){ return gh_long2scm (mix_vm_cmd_dispatcher_get_uptime (vm_dispatcher_));}static SCMmix_progtime_ (void){ return gh_long2scm (mix_vm_cmd_dispatcher_get_progtime (vm_dispatcher_));}static SCMmix_laptime_ (void){ return gh_long2scm (mix_vm_cmd_dispatcher_get_laptime (vm_dispatcher_));}static SCMmix_src_line_ (SCM opt){ gulong no = 0; const gchar *line = ""; if (opt != SCM_UNDEFINED) { SCM_ASSERT (SCM_NUMBERP (opt), opt, SCM_ARG1, "mix-src-line"); no = gh_scm2long (opt); } else no = mix_vm_cmd_dispatcher_get_src_file_lineno (vm_dispatcher_); SCM_ASSERT (line >= 0, opt, SCM_ARG1, "mix-src-line"); if (no > 0) line = mix_vm_cmd_dispatcher_get_src_file_line (vm_dispatcher_, no, FALSE); return gh_str02scm ((char *)line);}static SCMmix_src_line_no_ (void){ return gh_long2scm (mix_vm_cmd_dispatcher_get_src_file_lineno (vm_dispatcher_));}/* ----- hook functions ---- *//* auxiliar arg list maker */static SCMmake_arg_list_ (const gchar *arg){ gchar **arglist = g_strsplit (arg, " ", -1); SCM argument = gh_list (SCM_UNDEFINED, SCM_EOL); if (arglist && arglist[0]) { int k = 0; while (arglist[k]) argument = gh_cons (gh_str02scm (arglist[k++]), argument); argument = gh_reverse (argument); } g_strfreev (arglist); return argument;}/* command hook auxiliar functions and types *//*static SCMhook_error_handler_ (void *data, SCM tag, SCM args){}*/typedef struct{ SCM function; SCM args;} hook_data_t;static SCMhook_catch_body_ (void *data){ hook_data_t *h = (hook_data_t *)data; return gh_call1 (h->function, h->args);}static voidscm_hook_ (mix_vm_cmd_dispatcher_t *dis, const gchar *arg, gpointer data){ hook_data_t h; h.function = (SCM) data; g_assert (gh_procedure_p (h.function)); h.args = make_arg_list_ (arg); g_assert (gh_list_p (h.args)); gh_catch (SCM_BOOL_T, hook_catch_body_, &h, scm_handle_by_message_noexit, dis);}/* global hook auxiliar functions and types */typedef struct{ SCM function; SCM cmd; SCM args;} global_hook_data_t;static SCMglobal_hook_catch_body_ (void *data){ global_hook_data_t *h = (global_hook_data_t *)data; return gh_call2 (h->function, h->cmd, h->args);}static voidscm_global_hook_ (mix_vm_cmd_dispatcher_t *dis, mix_vm_command_t cmd, const gchar *arg, gpointer data){ global_hook_data_t h; h.function = (SCM) data; h.cmd = gh_str02scm ((char *)mix_vm_command_to_string (cmd)); h.args = make_arg_list_ (arg); gh_catch (SCM_BOOL_T, global_hook_catch_body_, &h, scm_handle_by_message_noexit, NULL);}static SCMdefine_hook_procedure_ (SCM function){ enum {BUFF_SIZE = 128}; static gchar BUFFER[BUFF_SIZE]; static const gchar *PATTERN = "____mix__hook__%d____"; static int K = 0; snprintf (BUFFER, BUFF_SIZE, PATTERN, K++); /* gh_define (name, val) returns a pair: (symbol . symbol-value) */ return gh_cdr (gh_define ((char *)BUFFER, function));}static SCMmix_add_hook_ (SCM cmd, SCM function, gboolean pre){ gchar *cmdstr = NULL; mix_vm_command_t command; int len; const gchar *fun = pre? "mix-add-pre-hook" : "mix-add-post-hook"; SCM_ASSERT (SCM_STRINGP (cmd) || SCM_SYMBOLP (cmd), cmd, SCM_ARG1, fun); SCM_ASSERT (gh_procedure_p (function), function, SCM_ARG2, fun); SCM_DEFER_INTS; cmdstr = gh_scm2newstr (cmd, &len); command = mix_vm_command_from_string (cmdstr); g_free (cmdstr); SCM_ALLOW_INTS; SCM_ASSERT (command != MIX_CMD_INVALID, cmd, SCM_ARG1, fun); SCM_DEFER_INTS; if (pre) mix_vm_cmd_dispatcher_pre_hook (vm_dispatcher_, command, scm_hook_, (gpointer) define_hook_procedure_ (function)); else mix_vm_cmd_dispatcher_post_hook (vm_dispatcher_, command, scm_hook_, (gpointer) define_hook_procedure_ (function)); SCM_ALLOW_INTS; return gh_symbol2scm ("ok");}static SCMmix_add_global_hook_ (SCM function, gboolean pre){ const gchar *fun = pre? "mix-add-global-pre-hook" : "mix-add-global-post-hook"; SCM_ASSERT (gh_procedure_p (function), function, SCM_ARG1, fun); SCM_DEFER_INTS; if (pre) mix_vm_cmd_dispatcher_global_pre_hook (vm_dispatcher_, scm_global_hook_, (gpointer) define_hook_procedure_ (function)); else mix_vm_cmd_dispatcher_global_post_hook (vm_dispatcher_, scm_global_hook_, (gpointer) define_hook_procedure_ (function)); SCM_ALLOW_INTS; return gh_symbol2scm ("ok");}static SCMmix_add_pre_hook_ (SCM cmd, SCM function){ return mix_add_hook_ (cmd, function, TRUE);}static SCMmix_add_post_hook_ (SCM cmd, SCM function){ return mix_add_hook_ (cmd, function, FALSE);}static SCMmix_add_global_pre_hook_ (SCM function){ return mix_add_global_hook_ (function, TRUE);}static SCMmix_add_global_post_hook_ (SCM function){ return mix_add_global_hook_ (function, FALSE);}/* NULL-terminated list of available scm commands */const scm_command_t DEFAULT_SCM_COMMANDS_[] = { {"mixvm-cmd", mixvm_cmd_, 2, 0, 0}, {"mixvm-status", mixvm_status_, 0, 0, 0}, {"mix-last-result", mix_last_result_, 0, 0, 0}, {"mix-reg", mix_reg_, 1, 0, 0}, {"mix-set-reg!", mix_set_reg_, 2, 0, 0}, {"mix-cell", mix_cell_, 1, 0, 0}, {"mix-set-cell!", mix_set_cell_, 2, 0, 0}, {"mix-over", mix_over_, 0, 0, 0}, {"mix-loc", mix_loc_, 0, 0, 0}, {"mix-set-over!", mix_set_over_, 1, 0, 0}, {"mix-cmp", mix_cmp_, 0, 0, 0}, {"mix-up-time", mix_uptime_, 0, 0, 0}, {"mix-lap-time", mix_laptime_, 0, 0, 0}, {"mix-prog-time", mix_progtime_, 0, 0, 0}, {"mix-prog-name", mix_prog_name_, 0, 0, 0}, {"mix-prog-path", mix_prog_path_, 0, 0, 0}, {"mix-src-name", mix_src_name_, 0, 0, 0}, {"mix-src-path", mix_src_path_, 0, 0, 0}, {"mix-src-line-no", mix_src_line_no_, 0, 0, 0}, {"mix-src-line", mix_src_line_, 0, 1, 0}, {"mix-ddir", mix_ddir_, 0, 0, 0}, {"mix-set-cmp!", mix_set_cmp_, 1, 0, 0}, {"mix-add-pre-hook", mix_add_pre_hook_, 2, 0, 0}, {"mix-add-post-hook", mix_add_post_hook_, 2, 0, 0}, {"mix-add-global-pre-hook", mix_add_global_pre_hook_, 1, 0, 0}, {"mix-add-global-post-hook", mix_add_global_post_hook_, 1, 0, 0}, {NULL}};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -