diff options
Diffstat (limited to 'mixutils')
-rw-r--r-- | mixutils/Makefile.am | 27 | ||||
-rw-r--r-- | mixutils/mixasm.c | 136 | ||||
-rw-r--r-- | mixutils/mixasm_comp.c | 72 | ||||
-rw-r--r-- | mixutils/mixasm_comp.h | 35 | ||||
-rw-r--r-- | mixutils/mixvm.c | 150 | ||||
-rw-r--r-- | mixutils/mixvm_command.c | 270 | ||||
-rw-r--r-- | mixutils/mixvm_command.h | 38 | ||||
-rw-r--r-- | mixutils/mixvm_loop.c | 160 | ||||
-rw-r--r-- | mixutils/mixvm_loop.h | 38 |
9 files changed, 926 insertions, 0 deletions
diff --git a/mixutils/Makefile.am b/mixutils/Makefile.am new file mode 100644 index 0000000..7d899d6 --- /dev/null +++ b/mixutils/Makefile.am @@ -0,0 +1,27 @@ +## Process this file with automake to produce Makefile.in + +# Copyright (C) 2000, 2001, 2002 Free Software Foundation, Inc. +# +# This file is free software; as a special exception the author gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY, to the extent permitted by law; without even the +# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +# $Id: Makefile.am,v 1.9 2002/04/08 00:30:34 jao Exp $ + +if MAKE_GUILE +INCLUDES = -I$(includedir) -I$(top_srcdir) -DMAKE_GUILE +else +INCLUDES = -I$(includedir) -I$(top_srcdir) +endif + +LDADD = $(top_builddir)/mixlib/libmix.a $(top_builddir)/lib/libreplace.a \ + $(top_builddir)/mixguile/libmixguile.a $(INTLLIBS) + +bin_PROGRAMS = mixasm mixvm +mixasm_SOURCES = mixasm.c mixasm_comp.h mixasm_comp.c +mixvm_SOURCES = mixvm.c mixvm_loop.h mixvm_loop.c mixvm_command.h \ + mixvm_command.c diff --git a/mixutils/mixasm.c b/mixutils/mixasm.c new file mode 100644 index 0000000..78f9f1f --- /dev/null +++ b/mixutils/mixasm.c @@ -0,0 +1,136 @@ +/* -*-c-*- -------------- mixasm.c: + * Main function of mixasm, the mix assembler + * ------------------------------------------------------------------ + * $Id: mixasm.c,v 1.9 2005/09/20 19:43:13 jao Exp $ + * ------------------------------------------------------------------ + * Copyright (C) 2000, 2001, 2002, 2004, 2005 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include <mixlib/mix.h> + +#include <stdlib.h> +#include <stdio.h> + +#ifdef HAVE_GETOPT_LONG +# include <getopt.h> +#else +# include <lib/getopt.h> +#endif /* HAVE_GETOPT_LONG */ + +#include "mixasm_comp.h" + +enum { + VER_OPT = 'v', + HELP_OPT = 'h', + USAGE_OPT = 'u', + OUT_OPT = 'o', + LIST_OPT = 'l', + NDEBUG_OPT = 'O' +}; + + +static struct option long_options_[] = +{ + {"version", no_argument, 0, VER_OPT}, + {"help", no_argument, 0, HELP_OPT}, + {"usage", no_argument, 0, USAGE_OPT}, + {"output", required_argument, 0, OUT_OPT}, + {"list", optional_argument, 0, VER_OPT}, + {"ndebug", no_argument, 0, NDEBUG_OPT}, + {0, 0, 0, 0} +}; + +static const gchar *USAGE_ = +N_("Usage: %s [-vhulO] [-o OUTPUT_FILE] [--version] [--help]\n" + "\t[--usage] [--ndebug] [--output=OUTPUT_FILE] [--list[=LIST_FILE]] file\n"); + + +int +main (int argc, char **argv) +{ + int c; + const char *prog_name = argv[0]; + const char *src = NULL, *out = NULL, *list = NULL; + gboolean use_list = FALSE, debug = TRUE; + + setlocale (LC_ALL, ""); + bindtextdomain (PACKAGE, LOCALEDIR); + textdomain (PACKAGE); + + while (1) + { + /* -g option is still available, but is no longer used */ + c = getopt_long (argc, argv, "vhuo:lOg", long_options_, (int*)0); + + /* Detect the end of the options. */ + if (c == -1) + break; + + switch (c) + { + case HELP_OPT: case USAGE_OPT: + fprintf (stderr, _(USAGE_), prog_name); + return EXIT_SUCCESS; + case VER_OPT: + mix_print_license ("mixasm, MIX assembler"); + return EXIT_SUCCESS; + case OUT_OPT: + out = optarg; + break; + case LIST_OPT: + use_list = TRUE; + list = optarg; + break; + case NDEBUG_OPT: + debug = FALSE; + break; + case 'g': + /* used to be the switch to create debug version, not needed anymore */ + break; + case '?': + /* getopt already handles the output of a warning message */ + fprintf (stderr, _("(Try: %s -h)\n"), prog_name); + return EXIT_FAILURE; + default: + g_assert_not_reached (); + } + } + + if ( optind == argc ) + { + fprintf (stderr, _("*** Error: Missing source file.\n")); + return EXIT_FAILURE; + } + if ( optind < argc-1 ) + { + fprintf (stderr, _("*** Error: Too many input files.\n")); + return EXIT_FAILURE; + } + src = argv[optind]; + + + mix_init_lib (); + + c = mix_asm_compile (src, out, use_list, list, debug); + + mix_release_lib (); + + return c; + +} + diff --git a/mixutils/mixasm_comp.c b/mixutils/mixasm_comp.c new file mode 100644 index 0000000..0bbf8a0 --- /dev/null +++ b/mixutils/mixasm_comp.c @@ -0,0 +1,72 @@ +/* -*-c-*- -------------- mixasm_comp.c : + * Implementation of the functions declared in mixasm_comp.h + * ------------------------------------------------------------------ + * Copyright (C) 2000 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include <mixlib/mix.h> +#include <stdlib.h> +#include <stdio.h> +#include <mixlib/mix_parser.h> +#include "mixasm_comp.h" + +int +mix_asm_compile(const gchar *src, const gchar *out, gboolean use_list, + const gchar *list, gboolean debug) +{ + int result = EXIT_SUCCESS; + mix_parser_t *parser; + mix_parser_err_t error; + + if ( (parser = mix_parser_new(src)) == NULL ) + { + fprintf(stderr, _("*** Unable to open source file %s\n"), src); + return EXIT_FAILURE; + } + if ( mix_parser_compile(parser) == MIX_PERR_OK ) + { + guint k; + if ( ( k = mix_parser_warning_count(parser) ) != 0 ) + fprintf(stderr, _("(%d warning(s))\n"), k); + if ( (error = mix_parser_write_code(parser, out, debug)) != MIX_PERR_OK ) + { + fprintf(stderr, _("*** Error writing output code file: %s\n"), + mix_parser_err_string(error)); + result = EXIT_FAILURE; + } + else if ( use_list + && (error = mix_parser_write_listing(parser, list)) != + MIX_PERR_OK) + { + fprintf(stderr, _("*** Error writing listing file: %s\n"), + mix_parser_err_string(error)); + result = EXIT_FAILURE; + } + } + else + { + fprintf(stderr, _("(%d warning(s), %d error(s))\n"), + mix_parser_warning_count(parser), mix_parser_err_count(parser)); + result = EXIT_FAILURE; + } + + mix_parser_delete(parser); + return result; +} + + diff --git a/mixutils/mixasm_comp.h b/mixutils/mixasm_comp.h new file mode 100644 index 0000000..f6537f4 --- /dev/null +++ b/mixutils/mixasm_comp.h @@ -0,0 +1,35 @@ +/* -*-c-*- ---------------- mixasm_comp.h : + * Declarations of functions used to compile mix source files. + * ------------------------------------------------------------------ + * Copyright (C) 2000 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + + +#ifndef MIXASM_COMP_H +#define MIXASM_COMP_H + +#include <glib.h> + +extern int +mix_asm_compile(const gchar *src, const gchar *out, gboolean use_list, + const gchar *list, gboolean debug); + + + +#endif /* MIXASM_COMP_H */ + diff --git a/mixutils/mixvm.c b/mixutils/mixvm.c new file mode 100644 index 0000000..a0ae443 --- /dev/null +++ b/mixutils/mixvm.c @@ -0,0 +1,150 @@ +/* -*-c-*- -------------- mixvm.c : + * Main function for mixvm, the mix vm simulator + * ------------------------------------------------------------------ + * $Id: mixvm.c,v 1.10 2005/09/20 19:43:13 jao Exp $ + * ------------------------------------------------------------------ + * Copyright (C) 2000, 2001, 2002, 2004 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + + + +#include <mixlib/mix.h> +#include <mixlib/mix_vm.h> +#include <mixlib/mix_vm_dump.h> + +#include <stdlib.h> +#include <stdio.h> + +#ifdef HAVE_GETOPT_LONG +# include <getopt.h> +#else +# include <lib/getopt.h> +#endif /* HAVE_GETOPT_LONG */ + +#include "mixvm_loop.h" + +enum { + VER_OPT = 'v', + HELP_OPT = 'h', + USAGE_OPT = 'u', + RUN_OPT = 'r', + DUMP_OPT = 'd', + TIME_OPT = 't', + EMACS_OPT = 'e', /* used by mixvm-gud only */ + NOINIT_OPT = 'q' +}; + +static const char *options_ = "vhurdt"; /* no short opt for --emacs */ + +static struct option long_options_[] = +{ + {"version", no_argument, 0, VER_OPT}, + {"help", no_argument, 0, HELP_OPT}, + {"usage", no_argument, 0, USAGE_OPT}, + {"run", required_argument, 0, RUN_OPT}, + {"dump", no_argument, 0, DUMP_OPT}, + {"time", no_argument, 0, TIME_OPT}, + /* pek: yo! */ + {"emacs", no_argument, 0, EMACS_OPT}, + {"noinit", no_argument, 0, NOINIT_OPT}, + {0, 0, 0, 0} +}; + +static const gchar *USAGE_ = +N_("Usage: %s [-vhurdqt] [--version] [--help] [--noinit] [--usage]" + "\n\t[--run] [--dump] [--time] [MIX_FILE]\n"); + +int +main (int argc, char **argv) +{ + int c; + const char *prog_name = argv[0]; + const char *in = NULL; + gboolean run = FALSE; + gboolean dump = FALSE; + gboolean emacs = FALSE; + gboolean initfile = TRUE; + gboolean ptime = FALSE; + + setlocale (LC_ALL, ""); + bindtextdomain (PACKAGE, LOCALEDIR); + textdomain (PACKAGE); + + while (1) + { + c = getopt_long (argc, argv, options_, long_options_, (int*)0); + + /* Detect the end of the options. */ + if (c == -1) + break; + + switch (c) + { + case HELP_OPT: case USAGE_OPT: + fprintf (stderr, _(USAGE_), prog_name); + return EXIT_SUCCESS; + case VER_OPT: + mix_print_license ("mixvm, MIX virtual machine"); + return EXIT_SUCCESS; + case RUN_OPT: + in = optarg; + run = TRUE; + break; + case DUMP_OPT: + dump = TRUE; + break; + case TIME_OPT: + ptime = TRUE; + break; + case '?': + /* getopt already handles the output of a warning message */ + fprintf (stderr, _("(Try: %s -h)\n"), prog_name); + return EXIT_FAILURE; + case EMACS_OPT: + emacs = TRUE; + break; + case NOINIT_OPT: + initfile = FALSE; + break; + default: + g_assert_not_reached (); + } + } + + if ( optind < argc-1 ) + { + fprintf (stderr, _("*** Error: Too many input files.\n")); + return EXIT_FAILURE; + } + + if (!in) in = argv[optind]; + + mix_init_lib (); + + if (run) mix_vmrun (in, dump, ptime); + else mix_vmloop (argc, argv, initfile, in, emacs); + + mix_release_lib (); + + return EXIT_SUCCESS; + +} + + + + diff --git a/mixutils/mixvm_command.c b/mixutils/mixvm_command.c new file mode 100644 index 0000000..0fbe1ce --- /dev/null +++ b/mixutils/mixvm_command.c @@ -0,0 +1,270 @@ +/* -*-c-*- -------------- mixvm_command.c : + * Implementation of the functions declared in mixvm_command.h + * ------------------------------------------------------------------ + * $Id: mixvm_command.c,v 1.12 2005/09/20 19:43:13 jao Exp $ + * ------------------------------------------------------------------ + * Copyright (C) 2000, 2001, 2002, 2004 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include <mixlib/mix.h> + +#include <stdio.h> +#include <stdlib.h> +#include <ctype.h> + +#include <mixlib/mix.h> + +#ifdef HAVE_LIBREADLINE +# include <readline/readline.h> +# include <readline/history.h> +# ifndef HAVE_RL_COMPLETION_MATCHES /* old versions of rl don't use rl_ */ +# define rl_completion_matches completion_matches +# endif +#else /* ! HAVE_LIBREADLINE */ + typedef int Function (); +#endif /* HAVE_LIBREADLINE */ + +#include <mixlib/mix_vm.h> +#include <mixlib/mix_vm_dump.h> +#include <mixlib/mix_eval.h> +#include <mixlib/mix_src_file.h> +#include <mixlib/mix_vm_command.h> + +#ifdef MAKE_GUILE +# include <mixguile/mixguile.h> +static gboolean +try_guile_ (char *line) +{ + if (line[0] == '(') + { + if (line[strlen (line) -1] != ')') return FALSE; + mixguile_interpret_command (line); + return TRUE; + } + return FALSE; +} +#else /* !MAKE_GUILE */ +# define try_guile_(ignored) FALSE +#endif /* MAKE_GUILE */ + +#include "mixvm_loop.h" +#include "mixvm_command.h" + +/* mixvm dispatcher */ +static mix_vm_cmd_dispatcher_t *dis_ = NULL; +static mix_config_t *config_ = NULL; + +/* The names of functions that actually do the manipulation. */ +#define DEC_FUN(name) \ +static gboolean cmd_##name (mix_vm_cmd_dispatcher_t *dis, const char *arg) + +DEC_FUN (shell_); +DEC_FUN (quit_); +DEC_FUN (prompt_); + +mix_vm_command_info_t commands[] = { + { "prompt", cmd_prompt_, N_("Set command prompt"), "prompt PROMPT" }, + { "shell", cmd_shell_, N_("Execute shell command"), "shell COMMAND" }, + { "quit", cmd_quit_, N_("Quit the program"), "quit" }, + { (char *)NULL, (Function *)NULL, (char *)NULL } +}; + + +#ifdef HAVE_LIBREADLINE +/* readline functions */ +static char * +mixvm_cmd_generator_ (const char *text, int state); + + +/* Attempt to complete on the contents of TEXT. START and END bound the + region of rl_line_buffer that contains the word to complete. TEXT is + the word to complete. We can use the entire contents of rl_line_buffer + in case we want to do some simple parsing. Return the array of matches, + or NULL if there aren't any. */ +static char ** +mixvm_cmd_completion_ (char *text, int start, int end) +{ + char **matches; + + matches = (char **)NULL; + + /* If this word is at the start of the line, then it is a command + to complete. Otherwise it is the name of a file in the current + directory. */ + if (start == 0) + matches = rl_completion_matches (text, mixvm_cmd_generator_); + + return (matches); +} + +/* Generator function for command completion. STATE lets us know whether + 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_ (const char *text, int state) +{ + static const GList *comp = NULL; + char *prefix = NULL; + char *name = NULL; + + /* If this is a new word to complete, initialize now. */ + if (!state) + { + if (prefix) g_free (prefix); + comp = mix_vm_cmd_dispatcher_complete (dis_, text, &prefix); + } + + /* Return the next name which partially matches from the command list. */ + if (comp) + { + name = g_strdup ((const gchar *)comp->data); + comp = comp->next; + } + + return name; +} +#endif /* HAVE_LIBREADLINE */ + + +/* emacs interface */ +static void +emacs_output_ (mix_vm_cmd_dispatcher_t *dis, const gchar *arg, gpointer data) +{ + /* pek: probably bad that we snag the src w/every emacs_output_, + however when multiple files are supported then this will + have to be done each time (but the info will be snagged + from elsewhere...) */ + const mix_vm_t *vm = mix_vm_cmd_dispatcher_get_vm (dis); + const mix_src_file_t *src = mix_vm_get_src_file (vm); + const gchar *path = mix_src_file_get_path (src); + + mix_address_t loc = mix_vm_get_prog_count (vm); + guint lineno = mix_vm_get_address_lineno (vm, loc); + + printf ("\032\032mixvm:%s%s:%d\n", path, MIX_SRC_DEFEXT, lineno); + return; +} + +static int +cmd_quit_ (mix_vm_cmd_dispatcher_t *dis, const char *arg) +{ + puts (_("Quitting ...")); + if (dis_) mix_vm_cmd_dispatcher_delete (dis_); + if (config_) mix_config_delete (config_); + exit (0); + + /* pek: anything needed here to make the marker disappear??? */ + return FALSE; +} + +static int +cmd_shell_ (mix_vm_cmd_dispatcher_t *dis, const char *arg) +{ + system (arg); + return TRUE; +} + +static int +cmd_prompt_ (mix_vm_cmd_dispatcher_t *dis, const char *arg) +{ + if (arg && strlen (arg)) mix_vmloop_set_prompt (arg); + return TRUE; +} + + +/* external interface */ +static void +init_dis_ (mix_vm_cmd_dispatcher_t *dis) +{ + static const gchar * envars[] = { "MDK_EDITOR", "X_EDITOR", "EDITOR", + "VISUAL" }; + + static const guint s = sizeof (envars) / sizeof (envars[0]); + static const gchar *editor = NULL; + gchar *edit = NULL; + + if (!editor) + { + int k; + for (k = 0; k < s; k++) + if ( (editor = getenv (envars[k])) != NULL ) break; + } + if (!editor) editor = "vi"; + edit = g_strconcat (editor, " %s", NULL); + mix_vm_cmd_dispatcher_set_editor (dis, edit); + g_free (edit); + mix_vm_cmd_dispatcher_set_assembler (dis, "mixasm %s"); +} + +mix_vm_cmd_dispatcher_t * +mixvm_cmd_init (mix_config_t *config, char *arg, gboolean use_emacs) +{ + int k; + +#ifdef HAVE_LIBREADLINE + /* Tell the completer that we want a crack first. */ + rl_attempted_completion_function = (CPPFunction *)mixvm_cmd_completion_; +#endif /* HAVE_LIBREADLINE */ + + /* initialise the dispatcher */ + config_ = config; + dis_ = mix_vm_cmd_dispatcher_new_with_config (stdout, stderr, config_); + + if ( dis_ == NULL) + g_error (_("Failed initialisation (no memory resources)")); + + init_dis_ (dis_); + + /* add local commands */ + k = 0; + while (commands[k].name) + { + mix_vm_cmd_dispatcher_register_new (dis_, commands + k); + ++k; + } + + /* install post hook for emacs interaction */ + if (use_emacs) + { + mix_vm_cmd_dispatcher_post_hook (dis_, MIX_CMD_LOAD, emacs_output_, NULL); + mix_vm_cmd_dispatcher_post_hook (dis_, MIX_CMD_RUN, emacs_output_, NULL); + mix_vm_cmd_dispatcher_post_hook (dis_, MIX_CMD_NEXT, emacs_output_, NULL); + } + + if (arg) + mix_vm_cmd_dispatcher_dispatch (dis_, MIX_CMD_LOAD, arg); + + return dis_; +} + +gboolean +mixvm_cmd_exec (char *line) +{ + if (!line) return cmd_quit_(dis_, NULL); + + /* strip white space */ + line = g_strstrip(line); + + if (strlen (line) == 0) return TRUE; + + if (try_guile_ (line)) return TRUE; + + (void)mix_vm_cmd_dispatcher_dispatch_text (dis_, line); + + return TRUE; +} diff --git a/mixutils/mixvm_command.h b/mixutils/mixvm_command.h new file mode 100644 index 0000000..28ff877 --- /dev/null +++ b/mixutils/mixvm_command.h @@ -0,0 +1,38 @@ +/* -*-c-*- ---------------- mixvm_command.h : + * Declarations for commands accepted by the mix virtual machine + * ------------------------------------------------------------------ + * $Id: mixvm_command.h,v 1.5 2005/09/20 19:43:13 jao Exp $ + * ------------------------------------------------------------------ + * Copyright (C) 2000, 2001, 2002 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + + +#ifndef MIXVM_COMMAND_H +#define MIXVM_COMMAND_H + +#include <mixlib/mix_config.h> +#include <mixlib/mix_vm_command.h> + +extern mix_vm_cmd_dispatcher_t * +mixvm_cmd_init (mix_config_t *config, char *arg, gboolean use_emacs); + +extern gboolean +mixvm_cmd_exec (char *line); + +#endif /* MIXVM_COMMAND_H */ + diff --git a/mixutils/mixvm_loop.c b/mixutils/mixvm_loop.c new file mode 100644 index 0000000..ef84444 --- /dev/null +++ b/mixutils/mixvm_loop.c @@ -0,0 +1,160 @@ +/* -*-c-*- -------------- mixvm_loop.c : + * Implementation of mix vm command loop. + * ------------------------------------------------------------------ + * $Id: mixvm_loop.c,v 1.15 2005/09/20 19:43:13 jao Exp $ + * ------------------------------------------------------------------ + * Copyright (C) 2000, 2001, 2002, 2004 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., 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); + return fgets (line, LINE_LEN, stdin); +} +#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_ (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_ (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); +} diff --git a/mixutils/mixvm_loop.h b/mixutils/mixvm_loop.h new file mode 100644 index 0000000..2dabfcd --- /dev/null +++ b/mixutils/mixvm_loop.h @@ -0,0 +1,38 @@ +/* -*-c-*- ---------------- mixvm_loop.h : + * Declarations for functions controlling the mixvm loop. + * ------------------------------------------------------------------ + * $Id: mixvm_loop.h,v 1.2 2005/09/20 19:43:13 jao Exp $ + * ------------------------------------------------------------------ + * Copyright (C) 2000, 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + + +#ifndef MIXVM_LOOP_H +#define MIXVM_LOOP_H + +extern void +mix_vmloop (int argc, char *argv[], gboolean initfile, + const gchar *code_file, gboolean use_emacs); + +extern void +mix_vmrun (const gchar *code_file, gboolean dump, gboolean ptime); + +extern void +mix_vmloop_set_prompt (const gchar *prompt); + +#endif /* MIXVM_LOOP_H */ |