summaryrefslogtreecommitdiffhomepage
path: root/mixguile/mixguile_cmd_dispatcher.c
diff options
context:
space:
mode:
Diffstat (limited to 'mixguile/mixguile_cmd_dispatcher.c')
-rw-r--r--mixguile/mixguile_cmd_dispatcher.c148
1 files changed, 146 insertions, 2 deletions
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);
+}