diff options
Diffstat (limited to 'mixguile')
| -rw-r--r-- | mixguile/Makefile.am | 3 | ||||
| -rw-r--r-- | mixguile/mixguile.c | 46 | ||||
| -rw-r--r-- | mixguile/mixguile.h | 13 | ||||
| -rw-r--r-- | mixguile/mixguile_cmd_dispatcher.c | 91 | ||||
| -rw-r--r-- | mixguile/mixguile_main.c | 23 | ||||
| -rw-r--r-- | mixguile/xmixguile_cmd_dispatcher.c | 163 | 
6 files changed, 295 insertions, 44 deletions
| diff --git a/mixguile/Makefile.am b/mixguile/Makefile.am index 392b08d..fed3371 100644 --- a/mixguile/Makefile.am +++ b/mixguile/Makefile.am @@ -22,14 +22,13 @@ SCM_PATHS = -DSCM_FILE=\""$(pkgdatadir)/mixguile.scm"\"\              -DLOCAL_SCM_FILE=\"mixguile.scm\"  pkgdata_DATA = $(SCM_FILES) - +INCLUDES = -I$(includedir) $(SCM_PATHS)  libmixguile_a_INCLUDES = -I$(includedir) -DG_LOG_DOMAIN=\"libmixguile\"  libmixguile_a_SOURCES = mixguile.h mixguile.c \                          mixguile_cmd_dispatcher.h mixguile_cmd_dispatcher.c \                          xmixguile_cmd_dispatcher.h xmixguile_cmd_dispatcher.c  bin_PROGRAMS = mixguile -mixguile_INCLUDES = -I$(includedir) $(SCM_PATHS)  mixguile_LDADD = $(top_builddir)/mixlib/libmix.a \                   $(top_builddir)/lib/libreplace.a \                   $(top_builddir)/mixguile/libmixguile.a $(INTLLIBS) diff --git a/mixguile/mixguile.c b/mixguile/mixguile.c index 52321ca..4072869 100644 --- a/mixguile/mixguile.c +++ b/mixguile/mixguile.c @@ -21,31 +21,70 @@   *     */ +#include <mixlib/mix_config.h>  #include "mixguile_cmd_dispatcher.h"  #include "mixguile.h"  static mixguile_cmd_dispatcher_t *dispatcher_ = NULL; +static mix_vm_cmd_dispatcher_t *vm_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[])  { +  if (vm_dispatcher_) +    { +      mixguile_set_cmd_dispatcher (vm_dispatcher_); +      mixguile_load_bootstrap (); +    }    (*main_fun_)(argc, argv);  }  /*    initialise the guile command dispatcher and enter the provided -  main function. the mixlib is also initialised. +  main function.  */  void -mixguile_init (int argc, char *argv[], main_func_t main_fun) +mixguile_init (int argc, char *argv[], main_func_t main_fun, +	       mix_vm_cmd_dispatcher_t *dis)  { -  mix_init_lib ();    main_fun_ = main_fun; +  vm_dispatcher_ = dis;    gh_enter (argc, argv, real_main_);  } +/* load bootstrap file */ +void +mixguile_load_bootstrap (void) +{ +  FILE *scm = NULL; +  const gchar *scmfile = SCM_FILE; +  gchar *lscmfile = +    g_strconcat (g_get_home_dir (), G_DIR_SEPARATOR_S, MIX_CONFIG_DIR, +		 G_DIR_SEPARATOR_S, LOCAL_SCM_FILE, NULL); +   +  if (!(scm = fopen (scmfile, "r")) +      && !(scm = fopen ((scmfile = LOCAL_SCM_FILE), "r"))) +    { +      g_warning ("mixguile bootstrap file %s not found\n", SCM_FILE); +      scmfile = NULL; +    } +  else +    fclose (scm); + +  if (scmfile) mixguile_interpret_file (scmfile); + +  if ((scm = fopen (lscmfile, "r")) != NULL) +    { +      fclose (scm); +      mixguile_interpret_file (lscmfile); +    } + +  g_free (lscmfile); +} +  /* enter the guile repl */  void  mixguile_enter_repl (int argc, char *argv[]) @@ -60,6 +99,7 @@ mixguile_set_cmd_dispatcher (mix_vm_cmd_dispatcher_t *dis)  {    g_return_if_fail (dis != NULL);    if (dispatcher_) mixguile_cmd_dispatcher_delete (dispatcher_); +  vm_dispatcher_ = dis;    dispatcher_ = mixguile_cmd_dispatcher_new (dis);    g_assert (dispatcher_);  } diff --git a/mixguile/mixguile.h b/mixguile/mixguile.h index 8897d29..6cc7918 100644 --- a/mixguile/mixguile.h +++ b/mixguile/mixguile.h @@ -32,12 +32,21 @@  /* the main function type */  typedef void (*main_func_t) (int argc, char *argv[]); + +/* enter and do the initialisation manually inside the guile world */ +#define mixguile_enter(argc,argv,main_fun) gh_enter (argc, argv, main_fun) + +/* load mixguile startup file */ +extern void +mixguile_load_bootstrap (); +  /*    initialise the guile command dispatcher and enter the provided -  main function. the mixlib is also initialised. +  main function.  */  extern void -mixguile_init (int argc, char *argv[], main_func_t main_fun); +mixguile_init (int argc, char *argv[], main_func_t main_fun, +	       mix_vm_cmd_dispatcher_t *dis);  /* set the command dispatcher */  extern void diff --git a/mixguile/mixguile_cmd_dispatcher.c b/mixguile/mixguile_cmd_dispatcher.c index 4676c43..b55d0ed 100644 --- a/mixguile/mixguile_cmd_dispatcher.c +++ b/mixguile/mixguile_cmd_dispatcher.c @@ -30,14 +30,56 @@  #include "mixguile.h"  #include "xmixguile_cmd_dispatcher.h" +#define SCM_CMD  "scm" +#define SCMF_CMD "scmf" + +/*local commands */ +static gboolean +cmd_scm_ (mix_vm_cmd_dispatcher_t *dis, const gchar *arg) +{ +  (void) gh_eval_str_with_catch ((char *)arg, scm_handle_by_message_noexit); +  return TRUE; +} + +static gboolean +cmd_scmf_ (mix_vm_cmd_dispatcher_t *dis, const gchar *arg) +{ +  (void) gh_eval_file_with_catch ((char *)arg, scm_handle_by_message_noexit); +  return TRUE; +} + +static mix_vm_command_info_t commands_[] = { +  { SCM_CMD, cmd_scm_, N_("Eval Scheme command using Guile"), "scm COMMAND"}, +  { SCMF_CMD, cmd_scmf_, N_("Eval Scheme file using Guile"), "scm PATH"}, +  {NULL} +}; +    /* create/destroy cmd dispatcher */ +static void +make_pipe_ (mixguile_cmd_dispatcher_t *dis) +{ +  int fildes[2], r; +  FILE *out; +  r = pipe (fildes); +  g_return_if_fail (r == 0); +  out = fdopen (fildes[1], "w"); +  g_return_if_fail (out != NULL); +  r = fcntl (fildes[0], F_GETFL, 0); +  g_return_if_fail (r != -1); +  r = fcntl (fildes[0], F_SETFL, r | O_NONBLOCK); +  g_return_if_fail (r != -1); + +  dis->guile_out = out; +  dis->fildes[0] = fildes[0]; +  dis->fildes[1] = fildes[1]; +} +  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; +  int k = 0;    g_return_val_if_fail (dis != NULL, NULL); @@ -46,23 +88,19 @@ mixguile_cmd_dispatcher_new (mix_vm_cmd_dispatcher_t *dis)        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; +  result->fildes[0] = result->fildes[1] = -1; +  result->guile_out = NULL; +   +  while (commands_[k].name) +    { +      mix_vm_cmd_dispatcher_register_new (dis, commands_ + k); +      ++k; +    }    register_cmd_dispatcher_ (result); @@ -74,9 +112,12 @@ 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]); +  if (dis->guile_out) +    { +      fclose (dis->guile_out); +      close (dis->fildes[0]); +      close (dis->fildes[1]); +    }    mix_vm_cmd_dispatcher_delete (dis->dispatcher);  } @@ -99,6 +140,7 @@ mixguile_cmd_dispatcher_last_result (mixguile_cmd_dispatcher_t *dis)    gchar *tmp = NULL;    g_return_val_if_fail (dis != NULL, NULL); +  if (!dis->guile_out) return NULL;    if (dis->result) g_free (dis->result);    dis->result = NULL;    fflush (dis->guile_out); @@ -124,6 +166,7 @@ mixguile_cmd_dispatcher_last_result (mixguile_cmd_dispatcher_t *dis)  static void  prepare_dispatcher_ (mixguile_cmd_dispatcher_t *dis)  { +  if (!dis->guile_out) make_pipe_ (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, @@ -137,14 +180,14 @@ mixguile_cmd_dispatcher_prepare (mixguile_cmd_dispatcher_t *dis)    prepare_dispatcher_ (dis);  } -/* interpret commands from file or string */ +/* 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, @@ -152,9 +195,8 @@ mixguile_cmd_dispatcher_interpret_file (mixguile_cmd_dispatcher_t *dis,  {    g_return_if_fail (dis != NULL);    g_return_if_fail (path != NULL); -  prepare_dispatcher_ (dis); -  (void) gh_eval_file ((char *)path); -  reset_dispatcher_ (dis); +  mix_vm_cmd_dispatcher_dispatch_split_text (dis->dispatcher, +					     SCMF_CMD, path);  }  void @@ -163,8 +205,7 @@ mixguile_cmd_dispatcher_interpret_command (mixguile_cmd_dispatcher_t *dis,  {    g_return_if_fail (dis != NULL);    g_return_if_fail (command != NULL); -  prepare_dispatcher_ (dis); -  (void) gh_eval_str ((char *)command); -  reset_dispatcher_ (dis); +  mix_vm_cmd_dispatcher_dispatch_split_text (dis->dispatcher, +					     SCM_CMD, command);  } diff --git a/mixguile/mixguile_main.c b/mixguile/mixguile_main.c index de9bfa4..183dfaf 100644 --- a/mixguile/mixguile_main.c +++ b/mixguile/mixguile_main.c @@ -25,20 +25,19 @@  #include <stdio.h>  #include "mixguile.h" -static void -inner_main_ (int argc, char *argv[]) -{ -  mix_vm_cmd_dispatcher_t *dis = mix_vm_cmd_dispatcher_new (stdout, stderr); -  mixguile_set_cmd_dispatcher (dis); -  mixguile_enter_repl (argc, argv); -} -  int  main (int argc, char *argv[])  { -  mixguile_init (argc, argv, inner_main_); -  return EXIT_SUCCESS; /* never reached */ -} - +  const gchar *CONFIG_FILE = "mixvm.config"; +  mix_config_t *config; +  mix_vm_cmd_dispatcher_t *dis; +   +   +  mix_init_lib (); +  config = mix_config_new (NULL, CONFIG_FILE); +  dis = mix_vm_cmd_dispatcher_new_with_config (stdout, stderr, config); +  mixguile_init (argc, argv, mixguile_enter_repl, dis); +  return EXIT_SUCCESS; /* never reached */ +} diff --git a/mixguile/xmixguile_cmd_dispatcher.c b/mixguile/xmixguile_cmd_dispatcher.c index 711bc52..744b76b 100644 --- a/mixguile/xmixguile_cmd_dispatcher.c +++ b/mixguile/xmixguile_cmd_dispatcher.c @@ -219,6 +219,12 @@ mix_set_over_ (SCM over)  }  static SCM +mix_loc_ (void) +{ +  return gh_long2scm (mix_vm_get_prog_count (vm_)); +} + +static SCM  mix_cmp_ (void)  {    gchar *result = NULL; @@ -261,6 +267,158 @@ mix_set_cmp_ (SCM value)    return gh_symbol2scm ("ok");  } +/* ----- hook functions ---- */ +/* auxiliar arg list maker */ +static SCM +make_arg_list_ (const gchar *arg) +{ +  gchar **arglist = g_strsplit (arg, " ", -1); +  SCM argument = gh_list (SCM_UNDEFINED); +  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 SCM +hook_error_handler_ (void *data, SCM tag, SCM args) +{ +  int len; +  mix_vm_cmd_dispatcher_t *dis = (mix_vm_cmd_dispatcher_t *)dis; +  gchar *argstr = gh_scm2newstr (args, &len); +  fprintf (mix_vm_cmd_dispatcher_get_err_stream (dis), "Error in hook: %s\n", +	   argstr); +  g_free (argstr); +  return SCM_BOOL_T; +} +*/ + +typedef struct +{ +  SCM function; +  SCM args; +} hook_data_t; + +static SCM +hook_catch_body_ (void *data) +{ +  hook_data_t *h = (hook_data_t *)data; +  return gh_call1 (h->function, h->args); +} + +static void +scm_hook_ (mix_vm_cmd_dispatcher_t *dis, const gchar *arg, gpointer data) +{ +  hook_data_t h; +  h.function = (SCM) data; +  h.args = make_arg_list_ (arg); +  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 SCM +global_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 void +scm_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 SCM +mix_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) function); +  else +    mix_vm_cmd_dispatcher_post_hook (vm_dispatcher_, command, +				     scm_hook_, (gpointer) function); +  SCM_ALLOW_INTS; +  return gh_symbol2scm ("ok"); +} + +static SCM +mix_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) function); +  else +    mix_vm_cmd_dispatcher_global_post_hook (vm_dispatcher_, scm_global_hook_, +					    (gpointer) function); +  SCM_ALLOW_INTS; +  return gh_symbol2scm ("ok"); +} + +static SCM +mix_add_pre_hook_ (SCM cmd, SCM function) +{ +  return mix_add_hook_ (cmd, function, TRUE); +} + +static SCM +mix_add_post_hook_ (SCM cmd, SCM function) +{ +  return mix_add_hook_ (cmd, function, FALSE); +} + +static SCM +mix_add_global_pre_hook_ (SCM function) +{ +  return mix_add_global_hook_ (function, TRUE); +} + +static SCM +mix_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}, @@ -269,8 +427,13 @@ const scm_command_t DEFAULT_SCM_COMMANDS_[] = {    {"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-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}  }; | 
