📄 mix_vm_command.c
字号:
/* -*-c-*- -------------- mix_vm_command.c : * Implementation of the functions declared in mix_vm_command.h * ------------------------------------------------------------------ * $Id: mix_vm_command.c,v 1.26 2001/09/16 22:32:12 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_command.h"#include "xmix_vm_handlers.h"#ifdef HAVE_LIBHISTORY# include <readline/history.h>#endif#ifdef HAVE_LIBREADLINE# include <readline/readline.h>#endif/* hook execution */static voidexec_hook_list_ (GSList *list, mix_vm_cmd_dispatcher_t *dis, const gchar *arg){ while (list) { hook_ *hook = (hook_ *)list->data; if (hook) (hook->func)(dis, arg, hook->data); list = list->next; }}static voidexec_global_hook_list_ (GSList *list, mix_vm_cmd_dispatcher_t *dis, mix_vm_command_t cmd, const gchar *arg){ while (list) { global_hook_ *hook = (global_hook_ *)list->data; if (hook) (hook->func)(dis, cmd, arg, hook->data); list = list->next; }}/* conversion from/to commands to strings */const gchar *mix_vm_command_to_string (mix_vm_command_t cmd){ if (cmd < MIX_CMD_INVALID) return commands_[cmd].name; else return NULL;}mix_vm_command_tmix_vm_command_from_string (const gchar *name){ gint cmd = 0; while (cmd < MIX_CMD_INVALID && strcmp (name, commands_[cmd].name)) ++cmd; return cmd;}/* get help string about a command */const gchar *mix_vm_command_help (mix_vm_command_t cmd){ if (cmd < MIX_CMD_INVALID) return commands_[cmd].doc; else return NULL;}const gchar *mix_vm_command_usage (mix_vm_command_t cmd){ if (cmd < MIX_CMD_INVALID) return commands_[cmd].usage; else return NULL;}/* create a new command dispatcher */static GCompletion *make_completions_ (void){ GList *cmds = NULL; gint k; GCompletion *completions = g_completion_new (NULL); for (k = 0; k < MIX_CMD_INVALID; ++k) cmds = g_list_append (cmds, (gpointer) mix_vm_command_to_string (k)); g_completion_add_items (completions, cmds); return completions;}mix_vm_cmd_dispatcher_t *mix_vm_cmd_dispatcher_new (FILE *out_fd, /* output messages file */ FILE *err_fd /* error messages file */){ mix_vm_cmd_dispatcher_t *result = NULL; int k; /* g_return_val_if_fail (out_fd && err_fd, NULL); */ result = g_new (mix_vm_cmd_dispatcher_t, 1); result->result = TRUE; result->out = out_fd; result->err = err_fd; result->log_msg = TRUE; result->uptime = result->laptime = result->progtime = 0; result->printtime = TRUE; result->trace = FALSE; result->program = NULL; result->editor = NULL; result->assembler = NULL; result->eval = mix_eval_new (); result->dump = mix_dump_context_new (out_fd, MIX_SHORT_ZERO, MIX_SHORT_ZERO, MIX_DUMP_ALL); result->vm = mix_vm_new (); result->global_pre = result->global_post = NULL; for (k =0; k < MIX_CMD_INVALID; ++k) result->pre_hooks[k] = result->post_hooks[k] = NULL; 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); result->commands = g_hash_table_new (g_str_hash, g_str_equal); result->completions = make_completions_ (); return result;}mix_vm_cmd_dispatcher_t *mix_vm_cmd_dispatcher_new_with_config (FILE *out, FILE *err, mix_config_t *config){ mix_vm_cmd_dispatcher_t *result = mix_vm_cmd_dispatcher_new (out, err); if (result != NULL && (result->config = config) != NULL) { gint hsize = 0; const gchar *val = mix_config_get (result->config, TRACING_KEY_); if (val) cmd_strace_ (result, val); val = mix_config_get (result->config, EDITOR_KEY_); if (val) mix_vm_cmd_dispatcher_set_editor (result, val); val = mix_config_get (result->config, ASM_KEY_); if (val) mix_vm_cmd_dispatcher_set_assembler (result, val); val = mix_config_get (result->config, TIMING_KEY_); if (val) cmd_stime_ (result, val); val = mix_config_get_devices_dir (result->config); if (!val || !mix_stat_dir (val, "devices")) { gchar *dirname = g_dirname (mix_config_get_filename (config)); cmd_sddir_ (result, dirname); g_free (dirname); } else mix_device_set_dir (val); val = mix_config_get (result->config, LOGGING_KEY_); if (val) cmd_slog_ (result, val);#ifdef HAVE_LIBHISTORY val = mix_config_get_history_file (result->config); hsize = mix_config_get_history_size (result->config); using_history (); stifle_history (hsize); if (val) { read_history ((char *)val); history_set_pos (history_base + history_length - 1); }#endif } return result;} /* delete (does not close the fds in the constructor) */static gbooleandel_pred_ (gpointer key, gpointer val, gpointer data){ if (val) mix_predicate_delete ((mix_predicate_t *)val); return TRUE;}static voiddel_hook_ (gpointer data, gpointer ignored){ if (data) g_free (data);}static voiddel_hook_list_ (GSList *s){ if (s) { g_slist_foreach (s, del_hook_, NULL); g_slist_free (s); }}voidmix_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); mix_vm_delete (dis->vm); if (dis->editor) g_free (dis->editor); if (dis->editor) g_free (dis->assembler);#ifdef HAVE_LIBHISTORY if (dis->config && (hfile = mix_config_get_history_file (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_hash_table_destroy (dis->mem_preds); g_hash_table_destroy (dis->commands); g_completion_free (dis->completions); for (k = 0; k < MIX_CMD_INVALID; ++k) { del_hook_list_ (dis->pre_hooks[k]); del_hook_list_ (dis->post_hooks[k]); } del_hook_list_ (dis->global_pre); del_hook_list_ (dis->global_post); g_free (dis);}/* register new commands for a dispatcher */voidmix_vm_cmd_dispatcher_register_new (mix_vm_cmd_dispatcher_t *dis, mix_vm_command_info_t *cmd){ GList *list = NULL; g_return_if_fail (dis != NULL); g_return_if_fail (cmd != NULL); g_hash_table_insert (dis->commands, (gpointer)cmd->name, (gpointer)cmd); list = g_list_append (list, (gpointer)cmd->name); g_completion_add_items (dis->completions, list);}const GList *mix_vm_cmd_dispatcher_complete (const mix_vm_cmd_dispatcher_t *dis, const gchar *cmd, gchar **prefix){ char *cp; GList *result; g_return_val_if_fail (dis != NULL, NULL); g_return_val_if_fail (cmd != NULL, NULL); cp = g_strdup (cmd); result = g_completion_complete (dis->completions, cp, prefix); g_free (cp); return result;}/* set/get out/error streams */FILE *mix_vm_cmd_dispatcher_get_out_stream (const mix_vm_cmd_dispatcher_t *dis){ g_return_val_if_fail (dis, NULL); return dis->out;}FILE *mix_vm_cmd_dispatcher_get_err_stream (const mix_vm_cmd_dispatcher_t *dis){ g_return_val_if_fail (dis, NULL); return dis->err;}FILE * /* old output stream */mix_vm_cmd_dispatcher_set_out_stream (mix_vm_cmd_dispatcher_t *dis, FILE *out){ FILE *old = NULL; g_return_val_if_fail (dis != NULL, old); old = dis->out; dis->out = out; dis->dump->channel = out; return old;}FILE * /* old error stream */mix_vm_cmd_dispatcher_set_error_stream (mix_vm_cmd_dispatcher_t *dis, FILE *err){ FILE *old = NULL; g_return_val_if_fail (dis != NULL, old); old = dis->err; dis->err = err; return old;}/* set editor and compiler templates */voidmix_vm_cmd_dispatcher_set_editor (mix_vm_cmd_dispatcher_t *dis, const gchar *edit_tplt){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -