/* -*-c-*- -------------- mixguile_cmd_dispatcher.c : * Implementation of the functions declared in mixguile_cmd_dispatcher.h * ------------------------------------------------------------------ * Last change: Time-stamp: "01/08/22 02:29:34 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 #include #include #include #include #include "mixguile.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); }