]> git.jsancho.org Git - gacela.git/blobdiff - src/gacela.c
(no commit message)
[gacela.git] / src / gacela.c
index 12766dd1b8f41715bbd8f94e5b9652dcbdc8eb34..036b3fa9ef3075d3eae7404564495240d1a7d01c 100644 (file)
 #include "gacela_GL.h"
 #include "gacela_FTGL.h"
 
-// Generic variables
+// Global variables
 int ctrl_c = 0;
+int pid = 0;
+char *history_path = NULL;
+
 
 static int
 find_matching_paren (int k)
@@ -114,11 +117,18 @@ ctrl_c_handler (int signum)
   printf ("ERROR: User interrupt\nABORT: (signal)\n");
   ctrl_c = 1;
 }
-     
+
+void
+child_dies_handler (int signum)
+{
+  write_history (history_path);
+  exit (0);
+}
+
 static void
 init_gacela_client ()
 {
-  struct sigaction new_action;
+  struct sigaction ctrl_c_action, child_dies_action;
 
   // init bouncing parens
   rl_bind_key (')', match_paren);
@@ -126,11 +136,55 @@ init_gacela_client ()
   rl_bind_key ('}', match_paren);
 
   // SIGINT
-  new_action.sa_handler = ctrl_c_handler;
-  sigemptyset (&new_action.sa_mask);
-  new_action.sa_flags = 0;
+  ctrl_c_action.sa_handler = ctrl_c_handler;
+  sigemptyset (&ctrl_c_action.sa_mask);
+  ctrl_c_action.sa_flags = 0;
+
+  sigaction (SIGINT, &ctrl_c_action, NULL);
+
+  // SIGALRM
+  if (pid != 0) {
+    child_dies_action.sa_handler = child_dies_handler;
+    sigemptyset (&child_dies_action.sa_mask);
+    child_dies_action.sa_flags = 0;
+
+    sigaction (SIGALRM, &child_dies_action, NULL);
+  }
 
-  sigaction (SIGINT, &new_action, NULL);
+}
+
+int
+opened_parens (char *line, int k)
+{
+  int i;
+  int opened = 0;
+  char c = 0;
+
+  // Choose the corresponding opening bracket
+  if (k == ')') c = '(';
+  else if (k == ']') c = '[';
+  else if (k == '}') c = '{';
+
+  for (i = 0; i < strlen (line); i++) {
+    // Is the current character part of a character literal?
+    if (i + 2 >= strlen (line)
+       && line[i] == '#'
+       && line[i + 1] == '\\')
+      i = i + 2;
+    else if (line[i] == '"') {
+      // Skip over a string literal
+      for (i++; i < strlen (line); i++)
+       if (line[i] == '"'
+           && line[i - 1] != '\\')
+             break;
+    }
+    else if (line[i] == c)
+      opened++;
+    else if (line[i] == k)
+      opened--;
+  }
+
+  return opened;
 }
 
 void
@@ -138,8 +192,8 @@ gacela_client (SCM rec_channel, SCM send_channel)
 {
   int n;
   SCM buffer;
-  char *line;
-  char *history_path;
+  char *line = NULL, *line_for_sending = NULL;
+  int opened = 0;
 
   // Command line
   asprintf (&history_path, "%s/.gacela_history", getenv("HOME"));
@@ -148,24 +202,45 @@ gacela_client (SCM rec_channel, SCM send_channel)
   read_history (history_path);
 
   while (1) {
-    line = readline ("gacela> ");
-    ctrl_c = 0;
+    if (opened > 0)
+      line = readline ("... ");
+    else
+      line = readline ("gacela> ");
+
     if (!line) break;
+
+    opened += opened_parens (line, ')');
+    ctrl_c = 0;
+
     if (line && *line)
       {
        add_history (line);
-       scm_write (scm_from_locale_string (line), send_channel);
-       scm_force_output (send_channel);
-
-       while (scm_char_ready_p (rec_channel) == SCM_BOOL_F) {
-         if (ctrl_c) break;
-         sleep (0.5);
+       if (line_for_sending == NULL) {
+         line_for_sending = strdup (line);
        }
-       if (ctrl_c)
-         ctrl_c = 0;
        else {
-         buffer = scm_read (rec_channel);
-         printf ("%s\n", scm_to_locale_string (buffer));
+         line_for_sending = realloc (line_for_sending, strlen (line_for_sending) + strlen (line) + 2);
+         line_for_sending = strcat (line_for_sending, "\n");
+         line_for_sending = strcat (line_for_sending, line);
+       }
+
+       if (opened <= 0) {
+         scm_write (scm_from_locale_string (line_for_sending), send_channel);
+         scm_force_output (send_channel);
+         free (line_for_sending);
+         line_for_sending = NULL;
+
+         while (scm_char_ready_p (rec_channel) == SCM_BOOL_F) {
+           if (ctrl_c) break;
+           sleep (0.5);
+         }
+         if (ctrl_c)
+           ctrl_c = 0;
+         else {
+           buffer = scm_read (rec_channel);
+           if (strlen (scm_to_locale_string (buffer)) > 0)
+             printf ("%s\n", scm_to_locale_string (buffer));
+         }
        }
       }
     free (line);
@@ -176,10 +251,10 @@ gacela_client (SCM rec_channel, SCM send_channel)
 }
 
 static void*
-init_gacela (void *data, int argc, char **argv)
+init_scheme (void *data, int argc, char **argv)
 {
   // Guile configuration
-  scm_c_eval_string ("(set-repl-prompt! \"gacela>\")");
+  scm_c_eval_string ("(set-repl-prompt! \"gacela> \")");
   scm_c_eval_string ("(use-modules (ice-9 readline))");
   scm_c_eval_string ("(activate-readline)");
   scm_c_eval_string ("(use-modules (ice-9 optargs))");
@@ -204,85 +279,55 @@ load_scheme_files (char *path)
 }
 
 void
-start_single (char *working_path)
+init_gacela (char *path)
 {
-  char *argv = "guile";
-
-  scm_with_guile (&init_gacela, NULL);
-  load_scheme_files (working_path);
-  scm_shell (1, &argv);
+  scm_with_guile (&init_scheme, NULL);
+  load_scheme_files (path);
+  scm_c_eval_string ("(init-video-mode)");
 }
 
 void
-start_server (char *working_path, int port)
+start_server (int port)
 {
-  char start_server[100];
+  char *start_server;
 
-  scm_with_guile (&init_gacela, NULL);
-  load_scheme_files (working_path);
-  sprintf (start_server, "(start-server %d)", port);
+  asprintf (&start_server, "(start-server #:port %d)", port);
   scm_c_eval_string (start_server);
 }
 
 void
-start_local_server (char *working_path, SCM pipes)
+start_local_server (SCM pipes)
 {
   char start_server[100];
 
-  scm_with_guile (&init_gacela, NULL);
-  load_scheme_files (working_path);
   scm_c_define ("pipes", pipes);
-  scm_c_eval_string ("(start-server pipes)");
+  scm_c_eval_string ("(start-server #:pipes pipes)");
 }
 
-/*
 void
 start_remote_client (char *hostname, int port)
 {
-  int sockfd;
-  struct hostent *server;
-  struct sockaddr_in serv_addr;
-
-  // Connect to the server
-  sockfd = socket (AF_INET, SOCK_STREAM, 0);
-  server = gethostbyname (hostname);
-  bzero ((char *) &serv_addr, sizeof (serv_addr));
-  serv_addr.sin_family = AF_INET;
-  bcopy ((char *)server->h_addr, (char *)&serv_addr.sin_addr.s_addr, server->h_length);
-  serv_addr.sin_port = htons (port);
-  if (connect (sockfd, (struct sockaddr *) &serv_addr, sizeof (serv_addr)) == -1) {
-    printf ("%s [%d.%d.%d.%d] %d: Connection refused\n", hostname, server->h_addr[0], server->h_addr[1], server->h_addr[2], server->h_addr[3], port);
-  }
-  else {
-    gacela_client (sockfd, sockfd);
-    close (sockfd);
-  }
-}
-*/
+  SCM client_socket;
+  char *connect_to_server;
 
-void
-start_remote_client (char *hostname, int port)
-{
-  SCM sockfd;
-
-  sockfd = scm_socket (AF_INET, SOCK_STREAM);
-  scm_connect (sockfd, AF_INET, 
+  asprintf (&connect_to_server, "(let ((s (socket PF_INET SOCK_STREAM 0))) (connect s AF_INET (car (hostent:addr-list (gethost \"%s\"))) %d) s)", hostname, port);
+  client_socket = scm_c_eval_string (connect_to_server);
+  gacela_client (client_socket, client_socket);
 }
 
 int
 main (int argc, char *argv[])
 {
   char *arg;
-  int mode = 0;   // shell: 1, server: 2, client: 3
+  int mode = 0;   // dev: 1, server: 2, client: 3
   char *host;
   int port = 0;
   int i;
   SCM fd1, fd2;
-  int pid;
 
   // Checking arguments
   for (i = 1; i < argc; i++) {
-    if (strcmp (argv[i], "--shell-mode") == 0)
+    if (strcmp (argv[i], "--dev") == 0)
       mode = 1;
     else if (strncmp (argv[i], "--server", 8) == 0) {
       mode = 2;
@@ -306,13 +351,7 @@ main (int argc, char *argv[])
 
   scm_init_guile ();
 
-  if (mode == 1)
-    start_single (dirname (argv[0]));
-  else if (mode == 2 && port != 0)
-    start_server (dirname (argv[0]), port);
-  else if (mode == 3 && port != 0)
-    start_remote_client (host, port);
-  else {
+  if (mode == 1) {
     fd1 = scm_pipe ();
     fd2 = scm_pipe ();
     pid = fork ();
@@ -320,7 +359,9 @@ main (int argc, char *argv[])
     if (pid == 0) {
       scm_close (SCM_CAR (fd1));
       scm_close (SCM_CDR (fd2));
-      start_local_server (dirname (argv[0]), scm_cons (SCM_CAR (fd2), SCM_CDR (fd1)));
+      init_gacela (dirname (argv[0]));
+      start_local_server (scm_cons (SCM_CAR (fd2), SCM_CDR (fd1)));
+      kill (getppid (), SIGALRM);
     }
     else {
       scm_close (SCM_CDR (fd1));
@@ -328,21 +369,16 @@ main (int argc, char *argv[])
       gacela_client (SCM_CAR (fd1), SCM_CDR (fd2));
       kill (pid, SIGKILL);
     }
-
-    /*
-    SCM buffer;
-    if (pid == 0) {
-      printf ("Hijo: 0\n");
-      scm_write (scm_from_locale_string ("Hola mundo\n"), SCM_CDR (pipes));
-      scm_force_output (SCM_CDR (pipes));
-      printf ("Hijo: 1\n");
-    }
-    else {
-      printf ("Padre: 0\n");
-      buffer = scm_read (SCM_CAR (pipes));
-      printf ("%s\n", scm_to_locale_string (buffer));
-      printf ("Padre: 1\n");
-    }
-    */
+  }
+  else if (mode == 2 && port != 0) {
+    init_gacela (dirname (argv[0]));
+    start_server (port);
+  }
+  else if (mode == 3 && port != 0)
+    start_remote_client (host, port);
+  else {
+    init_gacela (dirname (argv[0]));
+    scm_shell (argc, argv);
+    SDL_Quit ();
   }
 }