diff options
Diffstat (limited to 'mixguile')
-rw-r--r-- | mixguile/Makefile.am | 3 | ||||
-rw-r--r-- | mixguile/mixguile.c | 41 | ||||
-rw-r--r-- | mixguile/mixguile.h | 22 | ||||
-rw-r--r-- | mixguile/mixguile_cmd_dispatcher.c | 148 | ||||
-rw-r--r-- | mixguile/mixguile_cmd_dispatcher.h | 24 | ||||
-rw-r--r-- | mixguile/xmixguile_cmd_dispatcher.c | 90 | ||||
-rw-r--r-- | mixguile/xmixguile_cmd_dispatcher.h | 72 |
7 files changed, 384 insertions, 16 deletions
diff --git a/mixguile/Makefile.am b/mixguile/Makefile.am index 15d6308..664c7cd 100644 --- a/mixguile/Makefile.am +++ b/mixguile/Makefile.am @@ -16,7 +16,8 @@ noinst_LIBRARIES = libmixguile.a if MAKE_GUILE libmixguile_a_SOURCES = mixguile.h mixguile.c \ - mixguile_cmd_dispatcher.h mixguile_cmd_dispatcher.c + mixguile_cmd_dispatcher.h mixguile_cmd_dispatcher.c \ + xmixguile_cmd_dispatcher.h xmixguile_cmd_dispatcher.c else libmixguile_a_SOURCES = diff --git a/mixguile/mixguile.c b/mixguile/mixguile.c index 478c3d8..52321ca 100644 --- a/mixguile/mixguile.c +++ b/mixguile/mixguile.c @@ -1,7 +1,7 @@ /* -*-c-*- -------------- mixguile.c : * Implementation of the functions declared in mixguile.h * ------------------------------------------------------------------ - * Last change: Time-stamp: "01/08/21 02:26:10 jao" + * Last change: Time-stamp: "01/08/22 01:10:33 jao" * ------------------------------------------------------------------ * Copyright (C) 2001 Free Software Foundation, Inc. * @@ -21,17 +21,16 @@ * */ - +#include "mixguile_cmd_dispatcher.h" #include "mixguile.h" -static mixguile_cmd_dispatcher_t *dispatcher_; +static mixguile_cmd_dispatcher_t *dispatcher_ = NULL; static main_func_t main_fun_; /* do local initialisation and enter the user provided main */ static void real_main_ (int argc, char *argv[]) { - dispatcher_ = mixguile_cmd_dispatcher_new (); (*main_fun_)(argc, argv); } @@ -47,10 +46,40 @@ mixguile_init (int argc, char *argv[], main_func_t main_fun) gh_enter (argc, argv, real_main_); } +/* enter the guile repl */ +void +mixguile_enter_repl (int argc, char *argv[]) +{ + mixguile_cmd_dispatcher_prepare (dispatcher_); + gh_repl (argc, argv); +} + +/* set the command dispatcher */ +void +mixguile_set_cmd_dispatcher (mix_vm_cmd_dispatcher_t *dis) +{ + g_return_if_fail (dis != NULL); + if (dispatcher_) mixguile_cmd_dispatcher_delete (dispatcher_); + dispatcher_ = mixguile_cmd_dispatcher_new (dis); + g_assert (dispatcher_); +} + /* access the mixguile comand dispatcher */ -mixguile_cmd_dispatcher_t * +mix_vm_cmd_dispatcher_t * mixguile_get_cmd_dispatcher (void) { - return dispatcher_; + return mixguile_cmd_dispatcher_get_vm_dispatcher (dispatcher_); +} + +/* execute a string or file using the guile interpreter */ +void +mixguile_interpret_file (const gchar *path) +{ + mixguile_cmd_dispatcher_interpret_file (dispatcher_, path); } +void +mixguile_interpret_command (const gchar *command) +{ + mixguile_cmd_dispatcher_interpret_command (dispatcher_, command); +} diff --git a/mixguile/mixguile.h b/mixguile/mixguile.h index 319eb36..8897d29 100644 --- a/mixguile/mixguile.h +++ b/mixguile/mixguile.h @@ -1,7 +1,7 @@ /* -*-c-*- ---------------- mixguile.h : * Interface to the mixguile interpreter. * ------------------------------------------------------------------ - * Last change: Time-stamp: <01/08/21 02:26:18 jao> + * Last change: Time-stamp: <01/08/21 23:48:15 jao> * ------------------------------------------------------------------ * Copyright (C) 2001 Free Software Foundation, Inc. * @@ -26,8 +26,8 @@ #define MIXGUILE_H #include <mixlib/mix.h> +#include <mixlib/mix_vm_command.h> #include <guile/gh.h> -#include "mixguile_cmd_dispatcher.h" /* the main function type */ typedef void (*main_func_t) (int argc, char *argv[]); @@ -39,10 +39,24 @@ typedef void (*main_func_t) (int argc, char *argv[]); extern void mixguile_init (int argc, char *argv[], main_func_t main_fun); -/* access the mixguile comand dispatcher */ -extern mixguile_cmd_dispatcher_t * +/* set the command dispatcher */ +extern void +mixguile_set_cmd_dispatcher (mix_vm_cmd_dispatcher_t *dis); + +/* enter the guile repl */ +extern void +mixguile_enter_repl (int argc, char *argv[]); + +/* access the comand dispatcher */ +extern mix_vm_cmd_dispatcher_t * mixguile_get_cmd_dispatcher (void); +/* execute a string or file using the guile interpreter */ +extern void +mixguile_interpret_file (const gchar *path); + +extern void +mixguile_interpret_command (const gchar *command); #endif /* MIXGUILE_H */ diff --git a/mixguile/mixguile_cmd_dispatcher.c b/mixguile/mixguile_cmd_dispatcher.c index 2d7161a..4676c43 100644 --- a/mixguile/mixguile_cmd_dispatcher.c +++ b/mixguile/mixguile_cmd_dispatcher.c @@ -1,7 +1,7 @@ /* -*-c-*- -------------- mixguile_cmd_dispatcher.c : * Implementation of the functions declared in mixguile_cmd_dispatcher.h * ------------------------------------------------------------------ - * Last change: Time-stamp: "01/08/21 02:27:50 jao" + * Last change: Time-stamp: "01/08/22 02:29:34 jao" * ------------------------------------------------------------------ * Copyright (C) 2001 Free Software Foundation, Inc. * @@ -21,6 +21,150 @@ * */ +#include <stdio.h> +#include <unistd.h> +#include <fcntl.h> +#include <errno.h> + +#include <guile/gh.h> #include "mixguile.h" -#include "mixguile_cmd_dispatcher.h" +#include "xmixguile_cmd_dispatcher.h" + +/* create/destroy cmd dispatcher */ +mixguile_cmd_dispatcher_t * +mixguile_cmd_dispatcher_new (mix_vm_cmd_dispatcher_t *dis) +{ + static gboolean REGISTERED = FALSE; + mixguile_cmd_dispatcher_t *result = NULL; + int fildes[2], r; + FILE *out; + + g_return_val_if_fail (dis != NULL, NULL); + + if (!REGISTERED) + { + register_scm_commands_ (DEFAULT_SCM_COMMANDS_); + REGISTERED = TRUE; + } + + r = pipe (fildes); + g_return_val_if_fail (r == 0, NULL); + out = fdopen (fildes[1], "w"); + g_return_val_if_fail (out != NULL, NULL); + r = fcntl (fildes[0], F_GETFL, 0); + g_return_val_if_fail (r != -1, NULL); + r = fcntl (fildes[0], F_SETFL, r | O_NONBLOCK); + g_return_val_if_fail (r != -1, NULL); + + result = g_new (mixguile_cmd_dispatcher_t, 1); + result->dispatcher = dis; + result->err = result->out = NULL; + result->guile_out = out; + result->fildes[0] = fildes[0]; + result->fildes[1] = fildes[1]; + result->result = NULL; + + register_cmd_dispatcher_ (result); + + return result; +} + + +void +mixguile_cmd_dispatcher_delete (mixguile_cmd_dispatcher_t *dis) +{ + g_return_if_fail (dis != NULL); + fclose (dis->guile_out); + close (dis->fildes[0]); + close (dis->fildes[1]); + mix_vm_cmd_dispatcher_delete (dis->dispatcher); +} + +/* get the underlying vm dispatcher */ +mix_vm_cmd_dispatcher_t * +mixguile_cmd_dispatcher_get_vm_dispatcher (const mixguile_cmd_dispatcher_t *dis) +{ + g_return_val_if_fail (dis != NULL, NULL); + return dis->dispatcher; +} + +/* get the result string of last executed command */ +const gchar * +mixguile_cmd_dispatcher_last_result (mixguile_cmd_dispatcher_t *dis) +{ + enum {BLKSIZE = 256}; + static gchar BUFFER[BLKSIZE + 1]; + + ssize_t k; + gchar *tmp = NULL; + + g_return_val_if_fail (dis != NULL, NULL); + if (dis->result) g_free (dis->result); + dis->result = NULL; + fflush (dis->guile_out); + while ((k = read (dis->fildes[0], BUFFER, BLKSIZE)) != 0) + { + if (k == -1 && errno != EINTR) break; + if (k != -1) + { + tmp = dis->result; + BUFFER[k] = '\0'; + dis->result = g_strconcat (tmp ? tmp : "", BUFFER, NULL); + g_free (tmp); + } + } + + if (dis->result && dis->result[strlen (dis->result) - 1] == '\n') + dis->result[strlen (dis->result) - 1] = '\0'; + + return dis->result; +} + +/* prepare dispatcher for repl */ +static void +prepare_dispatcher_ (mixguile_cmd_dispatcher_t *dis) +{ + dis->out = mix_vm_cmd_dispatcher_set_out_stream (dis->dispatcher, + dis->guile_out); + dis->err = mix_vm_cmd_dispatcher_set_error_stream (dis->dispatcher, + dis->guile_out); +} + +void +mixguile_cmd_dispatcher_prepare (mixguile_cmd_dispatcher_t *dis) +{ + g_return_if_fail (dis != NULL); + prepare_dispatcher_ (dis); +} + +/* interpret commands from file or string */ +static void +reset_dispatcher_ (mixguile_cmd_dispatcher_t *dis) +{ + (void) mix_vm_cmd_dispatcher_set_out_stream (dis->dispatcher, dis->out); + (void) mix_vm_cmd_dispatcher_set_error_stream (dis->dispatcher, dis->err); +} + + +void +mixguile_cmd_dispatcher_interpret_file (mixguile_cmd_dispatcher_t *dis, + const gchar *path) +{ + g_return_if_fail (dis != NULL); + g_return_if_fail (path != NULL); + prepare_dispatcher_ (dis); + (void) gh_eval_file ((char *)path); + reset_dispatcher_ (dis); +} + +void +mixguile_cmd_dispatcher_interpret_command (mixguile_cmd_dispatcher_t *dis, + const gchar *command) +{ + g_return_if_fail (dis != NULL); + g_return_if_fail (command != NULL); + prepare_dispatcher_ (dis); + (void) gh_eval_str ((char *)command); + reset_dispatcher_ (dis); +} diff --git a/mixguile/mixguile_cmd_dispatcher.h b/mixguile/mixguile_cmd_dispatcher.h index 5be1d13..4dba9d0 100644 --- a/mixguile/mixguile_cmd_dispatcher.h +++ b/mixguile/mixguile_cmd_dispatcher.h @@ -1,7 +1,7 @@ /* -*-c-*- ---------------- mixguile_cmd_dispatcher.h : * Command dispatcher with guile support * ------------------------------------------------------------------ - * Last change: Time-stamp: <01/08/21 02:24:45 jao> + * Last change: Time-stamp: <01/08/22 01:15:23 jao> * ------------------------------------------------------------------ * Copyright (C) 2001 Free Software Foundation, Inc. * @@ -33,14 +33,32 @@ typedef struct mixguile_cmd_dispatcher_t mixguile_cmd_dispatcher_t; /* create/destroy cmd dispatcher */ extern mixguile_cmd_dispatcher_t * -mixguile_cmd_dispatcher_new (void); +mixguile_cmd_dispatcher_new (mix_vm_cmd_dispatcher_t *dis); extern void mixguile_cmd_dispatcher_delete (mixguile_cmd_dispatcher_t *dis); /* get the underlying vm dispatcher */ extern mix_vm_cmd_dispatcher_t * -mixguile_cmd_dispatcher_get_vm_dispatcher (const mix_vm_cmd_dispatcher_t *disp); +mixguile_cmd_dispatcher_get_vm_dispatcher (const + mixguile_cmd_dispatcher_t *disp); + +/* get the result string of last executed command */ +extern const gchar * +mixguile_cmd_dispatcher_last_result (mixguile_cmd_dispatcher_t *disp); + +/* prepare dispatcher for repl */ +extern void +mixguile_cmd_dispatcher_prepare (mixguile_cmd_dispatcher_t *dis); + +/* interpret commands from file or string */ +extern void +mixguile_cmd_dispatcher_interpret_file (mixguile_cmd_dispatcher_t *dis, + const gchar *path); + +extern void +mixguile_cmd_dispatcher_interpret_command (mixguile_cmd_dispatcher_t *dis, + const gchar *command); #endif /* MIXGUILE_CMD_DISPATCHER_H */ diff --git a/mixguile/xmixguile_cmd_dispatcher.c b/mixguile/xmixguile_cmd_dispatcher.c new file mode 100644 index 0000000..38a1200 --- /dev/null +++ b/mixguile/xmixguile_cmd_dispatcher.c @@ -0,0 +1,90 @@ +/* -*-c-*- -------------- xmixguile_cmd_dispatcher.c : + * Implementation of the functions declared in xmixguile_cmd_dispatcher.h + * ------------------------------------------------------------------ + * Last change: Time-stamp: "01/08/21 23:55:06 jao" + * ------------------------------------------------------------------ + * 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_; + +/* register a NULL-terminated list of scm commands */ +void +register_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 */ +void +register_cmd_dispatcher_ (mixguile_cmd_dispatcher_t *dis) +{ + g_return_if_fail (dis != NULL); + dispatcher_ = dis; + vm_dispatcher_ = mixguile_cmd_dispatcher_get_vm_dispatcher (dis); +} + +/* commands */ +static SCM +mix_command_ (SCM cmd, SCM arg) +{ + char *com, *argu; + int len; + gboolean result; + + SCM_DEFER_INTS; + SCM_ASSERT (SCM_STRINGP (cmd), cmd, SCM_ARG1, "mix-command"); + SCM_ASSERT (SCM_STRINGP (arg), arg, SCM_ARG2, "mix-command"); + 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; + com = (char *) mixguile_cmd_dispatcher_last_result (dispatcher_); + if (!com || strlen (com) == 0) + com = result? "ok" : "fail"; + return gh_str02scm (com); +} + +/* NULL-terminated list of available scm commands */ +const scm_command_t DEFAULT_SCM_COMMANDS_[] = { + {"mix-command", mix_command_, 2, 0, 0}, + {NULL} +}; + + + + + diff --git a/mixguile/xmixguile_cmd_dispatcher.h b/mixguile/xmixguile_cmd_dispatcher.h new file mode 100644 index 0000000..c399632 --- /dev/null +++ b/mixguile/xmixguile_cmd_dispatcher.h @@ -0,0 +1,72 @@ +/* -*-c-*- ---------------- xmixguile_cmd_dispatcher.h : + * Internal declarations for mixguile_cmd_dispatcher_t + * ------------------------------------------------------------------ + * Last change: Time-stamp: <01/08/22 01:11:20 jao> + * ------------------------------------------------------------------ + * 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. + * + */ + + +#ifndef XMIXGUILE_CMD_DISPATCHER_H +#define XMIXGUILE_CMD_DISPATCHER_H + +#include <stdlib.h> +#include <stdio.h> + +#include <guile/gh.h> +#include "mixguile_cmd_dispatcher.h" + +/* the cmd dispatcher type */ +struct mixguile_cmd_dispatcher_t +{ + mix_vm_cmd_dispatcher_t *dispatcher; + FILE *err; /* the vm dispatcher err stream */ + FILE *out; /* the vm dispatcher out stream */ + FILE *guile_out; /* output file of the dispatcher */ + int fildes[2]; /* pipe for communication with dispatcher */ + gchar *result; /* last result string */ +}; + +/* scm commands types */ +/* prototype of a function implementing a new scm function */ +typedef SCM (*scm_func_t) (); + +/* record for a new scm command */ +typedef struct scm_command_t +{ + gchar *name; /* name of the scheme command */ + scm_func_t func; /* implementation of the command */ + int argno; /* no. of arguments */ + int opt_argno; /* no. of optional arguments */ + int restp; /* if 1, receive a list of remaining args */ +} scm_command_t; + +/* NULL-terminated list of available scm commands */ +extern const scm_command_t DEFAULT_SCM_COMMANDS_[]; + +/* register a NULL-terminated list of scm commands */ +extern void +register_scm_commands_ (const scm_command_t *commands); + +/* register the mixvm cmd dispatcher to use with commands */ +extern void +register_cmd_dispatcher_ (mixguile_cmd_dispatcher_t *dis); + + +#endif /* XMIXGUILE_CMD_DISPATCHER_H */ + |