1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165
|
/* -*-c-*- -------------- mixvm_loop.c :
* Implementation of mix vm command loop.
* ------------------------------------------------------------------
* Copyright (C) 2000, 2001, 2002, 2004, 2006, 2007, 2009, 2010 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 3 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., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*
*/
#include <stdio.h>
#include <string.h>
#include <mixlib/mix.h>
#include <mixlib/mix_config.h>
#include <mixlib/mix_vm.h>
#include <mixlib/mix_device.h>
#include <mixlib/mix_vm_dump.h>
#ifdef MAKE_GUILE
#include <mixguile/mixguile.h>
#endif
#include "mixvm_command.h"
#include "mixvm_loop.h"
#ifdef HAVE_LIBHISTORY
# include <readline/history.h>
#else
# define add_history(x) ((void)0)
#endif
#ifdef HAVE_LIBREADLINE
# include <readline/readline.h>
#else /* !HAVE_LIBREADLINE */
static char *
readline (char *prompt)
{
enum {LINE_LEN = 256};
char *line = g_new (char, LINE_LEN);
printf ("%s", prompt);
if (fgets (line, LINE_LEN, stdin) == NULL)
{
g_free(line);
return (NULL);
}
return (line);
}
#endif /* HAVE_LIBREADLINE */
/* A static variable for holding the line. */
static char *line_read = (char *)NULL;
#define PROMPT_LEN 128
static char PROMPT[PROMPT_LEN + 1] = {'M', 'I', 'X', '>', ' '};
static const char *CONFIG_FILE_ = "mixvm.config";
static const char *PROMPT_KEY_ = "Prompt";
/* Read a string, and return a pointer to it. Returns NULL on EOF. */
static char *
rl_gets ()
{
/* If the buffer has already been allocated, return the memory
to the free pool. */
if (line_read)
{
g_free (line_read);
line_read = (char *)NULL;
}
/* Get a line from the user. */
line_read = readline ((char *)PROMPT);
/* If the line has any text in it, save it on the history. */
if (line_read && *line_read)
add_history (line_read);
return (line_read);
}
/* The main command loop of the virtual machine */
static mix_config_t *config_ = NULL;
static mix_vm_cmd_dispatcher_t *
init_mixvm_ (const gchar *file, gboolean use_emacs)
{
static const gchar *HISTORY_FILE = "mixvm.history";
static gint HISTORY_SIZE = 100;
config_ = mix_config_new (NULL, CONFIG_FILE_);
mix_config_set_autosave (config_, TRUE);
if (!mix_config_get_history_file (config_))
mix_config_set_history_file (config_, HISTORY_FILE);
if (mix_config_get_history_size (config_) == 0)
mix_config_set_history_size (config_, HISTORY_SIZE);
mix_vmloop_set_prompt (mix_config_get (config_, PROMPT_KEY_));
return mixvm_cmd_init (config_, (char *)file, use_emacs);
}
void
mix_vmloop_set_prompt (const gchar *prompt)
{
if (prompt)
{
g_snprintf (PROMPT, PROMPT_LEN, "%s ", prompt);
mix_config_update (config_, PROMPT_KEY_, prompt);
}
}
static void
loop_ (void *closure, int argc, char *argv[])
{
while ( mixvm_cmd_exec (rl_gets ()) )
;
mix_config_delete (config_);
}
void
mix_vmloop (int argc, char *argv[], gboolean initfile,
const gchar *file, gboolean use_emacs)
{
#ifdef MAKE_GUILE
mix_vm_cmd_dispatcher_t *dis = init_mixvm_ (file, use_emacs);
mixguile_init (argc, argv, initfile, loop_, dis);
#else
(void) init_mixvm_ (file, use_emacs);
loop_ (NULL, argc, argv);
#endif
}
/* run a program and exit */
void
mix_vmrun (const gchar *code_file, gboolean dump, gboolean ptime)
{
gchar *time_cmd = ptime? g_strdup ("stime on") : g_strdup ("stime off");
gchar *run_cmd = g_strdup ("run");
gchar *dump_cmd = dump? g_strdup ("pall") : NULL;
gboolean result;
init_mixvm_ (code_file, FALSE);
result = mixvm_cmd_exec (time_cmd) && mixvm_cmd_exec (run_cmd);
if (result && dump) mixvm_cmd_exec (dump_cmd);
mix_config_set_autosave (config_, FALSE);
mix_config_delete (config_);
g_free(time_cmd);
g_free(run_cmd);
if (dump_cmd) g_free(dump_cmd);
}
|