[Commit] librr/src rr.h,1.5,1.6 rr_board.c,1.6,1.7 rr_client.c,1.2,1.3 rr_strbuf.c,1.1,1.2 rr_string.c,1.1,1.2 rrint.h,1.4,1.5

Keith Packard commit at keithp.com
Thu Jun 12 01:09:11 PDT 2003


Committed by: keithp

Update of /local/src/CVS/librr/src
In directory home.keithp.com:/tmp/cvs-serv3291/src

Modified Files:
	rr.h rr_board.c rr_client.c rr_strbuf.c rr_string.c rrint.h 
Log Message:
added notices, eliminate threads

Index: rr.h
===================================================================
RCS file: /local/src/CVS/librr/src/rr.h,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -d -r1.5 -r1.6
--- rr.h	11 Jun 2003 23:26:14 -0000	1.5
+++ rr.h	12 Jun 2003 07:09:09 -0000	1.6
@@ -143,6 +143,89 @@
     RR_DIRECTION_SOUTH = RR_DIRECTION_DOWN
 } rr_direction_t;
 
+typedef enum {
+    /* global game notices */
+    RR_NOTICE_USER,
+    RR_NOTICE_QUIT,
+    RR_NOTICE_GAME,
+    RR_NOTICE_DISPOSE,
+    RR_NOTICE_MESSAGE,
+    RR_NOTICE_GAMESTATE,
+    RR_NOTICE_TURN,
+    RR_NOTICE_JOIN,
+    RR_NOTICE_WATCH,
+    RR_NOTICE_PART,
+    /* bid notices */
+    RR_NOTICE_BID,
+    RR_NOTICE_REVOKE,
+    RR_NOTICE_TIMER,
+    RR_NOTICE_ABANDON,
+    RR_NOTICE_NOBID,
+    /* solving notices */
+    RR_NOTICE_ACTIVE,
+    RR_NOTICE_MOVE,
+    RR_NOTICE_UNDO,
+    RR_NOTICE_RESET,
+    RR_NOTICE_POSITION,
+    RR_NOTICE_SCORE,
+    /* user notices */
+    RR_NOTICE_ACTIVATE
+} rr_notice_type_t;
+
+typedef enum {
+    RR_GAMESTATE_NEW,
+    RR_GAMESTATE_BID,
+    RR_GAMESTATE_SHOW,
+    RR_GAMESTATE_DONE,
+} rr_gamestate_t;
+
+typedef struct {
+    rr_notice_type_t	type;
+    union {
+	
+	/*
+	 * USER,  QUIT, JOIN, WATCH, PART, REVOKE, 
+	 * ABANDON, NOBID, GAME, DISPOSE
+	 */
+	char *string;
+	
+	/* MESSAGE */
+	struct {
+	    char    *username;
+	    char    *text;
+	} message;
+	
+	/* GAMESTATE */
+	rr_gamestate_t	gamestate;
+
+	/* TURN */
+	rr_target_t	target;
+
+	/* BID, ACTIVE, SCORE */
+	struct {
+	    char    *username;
+	    int	    number;
+	} bid;
+
+	/* TIME, ACTIVATE */
+	int number;
+
+	/* MOVE */
+	struct {
+	    int		    count;
+	    rr_robot_t	    robot;
+	    rr_direction_t  direction;
+	} move;
+
+	/* POSITION */
+	struct {
+	    rr_robot_t	    robot;
+	    int		    x, y;
+	} position;
+
+    } u;
+} rr_notice_t;
+    
 /* rr_board.c */
 
 rr_board_t *
@@ -240,6 +323,9 @@
 #define RR_CELL_GET_ROBOT(cell) ((cell) & RR_ROBOT_ANY)
 #define RR_CELL_GET_TARGET(cell) ((cell) & RR_TARGET_ANY)
 
+int
+rr_board_notice (rr_board_t *board, const char **notify);
+
 /* rr_cell.c */
 
 int
@@ -267,32 +353,29 @@
 		  const char *port,
 		  const char *user);
 
-rr_board_t *
-rr_client_get_board (rr_client_t *client);
+int
+rr_client_fd (rr_client_t *client);
 
 rr_status_t
 rr_client_helo (rr_client_t *client, const char *user);
 
 rr_status_t
-rr_client_games (rr_client_t *client, char **games);
+rr_client_games (rr_client_t *client, char ***games);
 
 rr_status_t
 rr_client_message (rr_client_t *client, const char *text);
 
 rr_status_t
-rr_client_help (rr_client_t *client, char **help);
-
-rr_status_t
 rr_client_quit (rr_client_t *client);
 
 rr_status_t
-rr_client_players (rr_client_t *client, char **players);
+rr_client_players (rr_client_t *client, char ***players);
 
 rr_status_t
-rr_client_watchers (rr_client_t *client, char **watchers);
+rr_client_watchers (rr_client_t *client, char ***watchers);
 
 rr_status_t
-rr_client_gameinfo (rr_client_t *client, const char *game, char **info);
+rr_client_gameinfo (rr_client_t *client, const char *game, char ***info);
 
 rr_status_t
 rr_client_new (rr_client_t *client, const char *game);
@@ -307,10 +390,7 @@
 rr_client_dispose (rr_client_t *client, const char *game);
 
 rr_status_t
-rr_client_userinfo (rr_client_t *client, const char *user, char **info);
-
-rr_status_t
-rr_client_update_board (rr_client_t *client);
+rr_client_userinfo (rr_client_t *client, const char *user, char ***info);
 
 rr_status_t
 rr_client_show (rr_client_t *client, char **diagram);
@@ -342,6 +422,14 @@
 void
 rr_client_destroy (rr_client_t *client);
 
+int
+rr_client_notice_pending (rr_client_t *client);
+
+rr_status_t
+rr_client_next_notice (rr_client_t *client, char ***notice);
+
+rr_notice_t *
+rr_client_parse_notice (rr_client_t *client, char **notice);
 /* rr.c */
 
 const char *

Index: rr_board.c
===================================================================
RCS file: /local/src/CVS/librr/src/rr_board.c,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -d -r1.6 -r1.7
--- rr_board.c	11 Jun 2003 23:26:14 -0000	1.6
+++ rr_board.c	12 Jun 2003 07:09:09 -0000	1.7
@@ -544,5 +544,3 @@
 
     return RR_STATUS_SUCCESS;
 }
-
-

Index: rr_client.c
===================================================================
RCS file: /local/src/CVS/librr/src/rr_client.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- rr_client.c	11 Jun 2003 23:26:14 -0000	1.2
+++ rr_client.c	12 Jun 2003 07:09:09 -0000	1.3
@@ -26,9 +26,11 @@
 
 #include <unistd.h>
 #include <sys/socket.h>
+#include <sys/poll.h>
 #include <netdb.h>
 #include <errno.h>
 #include <ctype.h>
+#include <fcntl.h>
 
 #include "rrint.h"
 
@@ -53,7 +55,7 @@
 static rr_status_t
 _rr_client_request (rr_client_t *client,
 		    rr_cmd_t cmd, const char *arg,
-		    char **response);
+		    char ***response);
 
 static rr_status_t
 _rr_client_send (rr_client_t *client, const char *fmt, ...);
@@ -62,7 +64,7 @@
 _rr_client_send_va (rr_client_t *client, const char *fmt, va_list va);
 
 static rr_status_t
-_rr_client_recv (rr_client_t *client, rr_cmd_t cmd, char **arg);
+_rr_client_recv (rr_client_t *client, rr_cmd_t cmd, char ***arg);
 
 static rr_status_t
 _rr_client_error_to_status (const char *error);
@@ -124,20 +126,10 @@
 {
     rr_status_t status;
 
-    pthread_mutex_init (&client->mutex, NULL);
-    pthread_cond_init (&client->response_cond, NULL);
-
-    status = _rr_board_init (&client->board, 0, 0);
-    if (status)
-	return status;
-
     status = _rr_client_connect (client, host, port);
     if (status)
 	return status;
 
-    pthread_create (&client->response_thread, NULL,
-		    _rr_client_response_thread_start, client);
-
     status = rr_client_helo (client, user);
     if (status) {
 	char *user_uniq;
@@ -166,18 +158,17 @@
 static rr_status_t
 _rr_client_fini (rr_client_t *client)
 {
-    pthread_mutex_lock (&client->mutex);
-
-    _rr_board_fini (&client->board);
-
     _rr_client_disconnect (client);
 
-    pthread_cond_destroy (&client->response_cond);
-    pthread_mutex_unlock (&client->mutex);
-
     return RR_STATUS_SUCCESS;
 }
 
+int
+rr_client_fd (rr_client_t *client)
+{
+    return client->sock;
+}
+
 void
 rr_client_destroy (rr_client_t *client)
 {
@@ -212,6 +203,8 @@
     if (err) {
 	return RR_STATUS_CONNECT_ERROR;
     }
+    fcntl (client->sock, F_SETFL,
+	   fcntl (client->sock, F_GETFL, 0) | O_NONBLOCK);
 
     freeaddrinfo (addr);
 
@@ -229,25 +222,90 @@
     return RR_STATUS_SUCCESS;
 }
 
-/* XXX: Might want to add a realistically sized buffered read here */
 static rr_status_t
-_rr_client_read_char (rr_client_t *client, char *c)
+_rr_client_fill (rr_client_t *client)
 {
-    char buf[1];
-    int cnt;
+    int	r = read (client->sock, client->buf, RR_BUF_SIZE);
+    if (r > 0)
+    {
+	client->end = r;
+	client->ptr = 0;
+	return RR_STATUS_SUCCESS;
+    }
+    if (r == 0)
+	return RR_STATUS_EOF;
+    if (errno == EWOULDBLOCK)
+    {
+	client->end = 0;
+	client->ptr = 0;
+	return RR_STATUS_SUCCESS;
+    }
+    return RR_STATUS_IO_ERROR;
+}
 
-    while (1) {
-	cnt = read (client->sock, &buf, 1);
-	if (cnt == 1) {
-	    *c = buf[0];
-	    return RR_STATUS_SUCCESS;
-	} else if (cnt == 0)
-	    return RR_STATUS_EOF;
-	else if (errno == EINTR || errno == EAGAIN)
-	    continue;
-	else
-	    return RR_STATUS_IO_ERROR;
+static int
+_rr_client_poll (rr_client_t *client, int events, int timeout)
+{
+    struct pollfd   p;
+    int r;
+
+    p.fd = client->sock;
+    p.events = events;
+    p.revents = 0;
+    for (;;)
+    {
+	r = poll (&p, 1, timeout);
+	if (r >= 0)
+	    return r;
+	if (errno != EINTR && errno != EAGAIN)
+	    return r;
+    }
+}
+
+static rr_status_t
+_rr_client_read_block (rr_client_t *client)
+{
+    if (_rr_client_poll (client, POLLIN, -1) < 0)
+	return RR_STATUS_IO_ERROR;
+    return RR_STATUS_SUCCESS;
+}
+
+static rr_status_t
+_rr_client_write_block (rr_client_t *client)
+{
+    if (_rr_client_poll (client, POLLOUT, -1) < 0)
+	return RR_STATUS_IO_ERROR;
+    return RR_STATUS_SUCCESS;
+}
+
+static int
+_rr_client_readable (rr_client_t *client)
+{
+    if (client->ptr < client->end)
+	return 1;
+    if (_rr_client_poll (client, POLLIN, 0) != 0)
+	return 1;
+    return 0;
+}
+    
+static rr_status_t
+_rr_client_read_char (rr_client_t *client, char *c)
+{
+    rr_status_t status;
+    while (client->ptr >= client->end)
+    {
+	status = _rr_client_fill (client);
+	if (status != RR_STATUS_SUCCESS)
+	    return status;
+	if (client->ptr >= client->end)
+	{
+	    status = _rr_client_read_block (client);
+	    if (status != RR_STATUS_SUCCESS)
+		return status;
+	}
     }
+    *c = client->buf[client->ptr++];
+    return RR_STATUS_SUCCESS;
 }
 
 static rr_status_t
@@ -313,87 +371,63 @@
 }
 
 static rr_status_t
-_rr_client_read_word (rr_client_t *client, char **str, char *delimiter)
-{
-    rr_status_t status = RR_STATUS_SUCCESS;
-    rr_strbuf_t strbuf;
-
-    _rr_strbuf_init (&strbuf);
-
-    status = _rr_client_read_word_strbuf (client, &strbuf, delimiter);
-
-    *str = _rr_strbuf_fini (&strbuf);
-
-    return status;
-}
-
-static rr_status_t
-_rr_client_read_line (rr_client_t *client, char **str)
+_rr_client_read_line (rr_client_t *client, char ***strstr)
 {
     rr_status_t status = RR_STATUS_SUCCESS;
-    rr_strbuf_t strbuf;
+    rr_strstrbuf_t strstrbuf;
     char delimiter;
 
-    _rr_strbuf_init (&strbuf);
+    _rr_strstrbuf_init (&strstrbuf);
 
     while (1) {
+	rr_strbuf_t strbuf;
+	_rr_strbuf_init (&strbuf);
 	status = _rr_client_read_word_strbuf (client,
 					      &strbuf,
 					      &delimiter);
+	_rr_strstrbuf_append (&strstrbuf, _rr_strbuf_str (&strbuf));
+	_rr_strbuf_fini (&strbuf);
 	if (status || delimiter == '\n')
 	    break;
-	_rr_strbuf_append (&strbuf, ' ');
     };
 
-    *str = _rr_strbuf_fini (&strbuf);
+    *strstr = _rr_strstrbuf_fini (&strstrbuf);
 
     return status;
 }
 
-static void *
-_rr_client_response_thread_start (void *closure)
+/* return a reply */
+static rr_status_t
+_rr_client_queue_notice (rr_client_t *client, char **arg)
 {
-    rr_status_t status;
-    rr_client_t *client = closure;
-    char *response, *arg;
-    char delimiter;
-    
-    while (1) {
-	status = _rr_client_read_word (client, &response, &delimiter);
-	if (status)
-	    break;
-	if (delimiter == '\n') {
-	    arg = strdup("");
-	    if (arg == NULL)
-		return (void *) RR_STATUS_NO_MEMORY;
-	} else {
-	    status = _rr_client_read_line (client, &arg);
-	    if (status)
-		break;
-	}
-
-	if (strcmp (response, "NOTICE") == 0) {
-	    /* XXX: Need to handle these. */
-	    fprintf (stderr, "Not handling response: %s %s\n", response, arg);
-	    free (response);
-	    free (arg);
-	    continue;
-	}
-
-	pthread_mutex_lock (&client->mutex);
-	client->response = response;
-	client->arg = arg;
-	pthread_mutex_unlock (&client->mutex);
-	pthread_cond_signal (&client->response_cond);
+    rr_notice_elt_t *e = malloc (sizeof (rr_notice_elt_t)), **p;
+    if (!e) {
+	free (arg);
+	return RR_STATUS_NO_MEMORY;
     }
-
-    return (void *) RR_STATUS_SUCCESS;
+    for (p = &client->notice_queue; *p; p = &(*p)->next);
+    e->notice = arg;
+    e->next = 0;
+    *p = e;
 }
 
-rr_board_t *
-rr_client_get_board (rr_client_t *client)
+static rr_status_t
+_rr_client_reply (rr_client_t *client, char ***response)
 {
-    return &client->board;
+    while (1) {
+	char **arg;
+	rr_status_t status = _rr_client_read_line (client, &arg);
+	if (status != RR_STATUS_SUCCESS)
+	    return status;
+	
+	if (arg[0] && strcmp (arg[0], "NOTICE") == 0) {
+	    _rr_strings_cdr (arg);
+	    _rr_client_queue_notice (client, arg);
+	} else {
+	    *response = arg;
+	    return RR_STATUS_SUCCESS;
+	}
+    }
 }
 
 rr_status_t
@@ -403,7 +437,7 @@
 }
 
 rr_status_t
-rr_client_games (rr_client_t *client, char **games)
+rr_client_games (rr_client_t *client, char ***games)
 {
     return _rr_client_request (client, RR_CMD_GAMES, NULL, games);
 }
@@ -415,31 +449,25 @@
 }
 
 rr_status_t
-rr_client_help (rr_client_t *client, char **help)
-{
-    return _rr_client_request (client, RR_CMD_HELP, NULL, help);
-}   
-
-rr_status_t
 rr_client_quit (rr_client_t *client)
 {
     return _rr_client_request (client, RR_CMD_QUIT, NULL, NULL);
 }
 
 rr_status_t
-rr_client_players (rr_client_t *client, char **players)
+rr_client_players (rr_client_t *client, char ***players)
 {
     return _rr_client_request (client, RR_CMD_PLAYERS, NULL, players);
 }
 
 rr_status_t
-rr_client_watchers (rr_client_t *client, char **watchers)
+rr_client_watchers (rr_client_t *client, char ***watchers)
 {
     return _rr_client_request (client, RR_CMD_WATCHERS, NULL, watchers);
 }
 
 rr_status_t
-rr_client_gameinfo (rr_client_t *client, const char *game, char **info)
+rr_client_gameinfo (rr_client_t *client, const char *game, char ***info)
 {
     return _rr_client_request (client, RR_CMD_GAMEINFO, game, info);
 }
@@ -469,39 +497,23 @@
 }
 
 rr_status_t
-rr_client_userinfo (rr_client_t *client, const char *user, char **info)
+rr_client_userinfo (rr_client_t *client, const char *user, char ***info)
 {
     return _rr_client_request (client, RR_CMD_USERINFO, user, info);
 }
 
 rr_status_t
-rr_client_update_board (rr_client_t *client)
-{
-    rr_status_t status;
-    char *diagram;
-
-    status = rr_client_show (client, &diagram);
-    if (diagram)
-	free (diagram);
-    if (status)
-	return status;
-
-    return RR_STATUS_SUCCESS;
-}
-
-rr_status_t
 rr_client_show (rr_client_t *client, char **diagram)
 {
     rr_status_t status;
+    char **args;
 
-    status = _rr_client_request (client, RR_CMD_SHOW, NULL, diagram);
-    if (status)
-	return status;
-
-    status = rr_board_parse (&client->board, *diagram);
+    status = _rr_client_request (client, RR_CMD_SHOW, NULL, &args);
     if (status)
 	return status;
 
+    *diagram = _rr_string_dup (args[0]);
+    free (args);
     return RR_STATUS_SUCCESS;
 }
 
@@ -556,13 +568,11 @@
 static rr_status_t
 _rr_client_request (rr_client_t *client,
 		    rr_cmd_t cmd, const char *arg,
-		    char **response)
+		    char ***response)
 {
     rr_status_t status = RR_STATUS_SUCCESS;
     char *cmd_str;
-    char *recv;
-
-    pthread_mutex_lock (&client->mutex);
+    char **recv;
 
     cmd_str = RR_CLIENT_COMMAND[cmd].arg;
 
@@ -583,7 +593,6 @@
 	free (recv);
 
   DONE:
-    pthread_mutex_unlock (&client->mutex);
 
     return status;
 }
@@ -606,7 +615,9 @@
 static rr_status_t
 _rr_client_send_va (rr_client_t *client, const char *fmt, va_list va)
 {
-    char *msg;
+    char *msg, *m;
+    int len, r;
+    rr_status_t status = RR_STATUS_SUCCESS;
 
     if (client->sock == -1)
 	return RR_STATUS_NOT_CONNECTED;
@@ -615,10 +626,29 @@
     if (msg == NULL)
 	return RR_STATUS_NO_MEMORY;
 
-    write (client->sock, msg, strlen (msg));
+    len = strlen (msg);
+    m = msg;
+    while (len)
+    {
+	r = write (client->sock, m, len);
+	if (r > 0)
+	{
+	    m += r;
+	    len -= r;
+	}
+	else if (r == 0 || 
+	    (errno == EWOULDBLOCK && errno != EAGAIN))
+	{
+	    status = RR_STATUS_IO_ERROR;
+	    break;
+	}
+	else
+	    _rr_client_write_block (client);
+    }
+    
     free (msg);
 
-    return RR_STATUS_SUCCESS;
+    return status;
 }
 
 static rr_status_t
@@ -667,29 +697,323 @@
 }
 /* NOTE: Called with client->mutex held */
 static rr_status_t
-_rr_client_recv (rr_client_t *client, rr_cmd_t cmd, char **arg)
+_rr_client_recv (rr_client_t *client, rr_cmd_t cmd, char ***argp)
 {
-    rr_status_t status;
-
-    pthread_cond_wait (&client->response_cond, &client->mutex);
-
-    if (strcmp (client->response, RR_CLIENT_COMMAND[cmd].arg) == 0) {
-	*arg = client->arg;
+    char **arg;
+    rr_status_t status = _rr_client_reply (client, &arg);
+    
+    if (arg[0] && strcmp (arg[0], RR_CLIENT_COMMAND[cmd].arg) == 0) {
 	status = RR_STATUS_SUCCESS;
-    } else if (strcmp (client->response, "ERROR") == 0) {
-	*arg = NULL;
-	status = _rr_client_error_to_status (client->arg);
-	free (client->arg);
-	client->arg = NULL;
+	_rr_strings_cdr (arg);
+	*argp = arg;
+    } else if (arg[0] && strcmp (arg[0], "ERROR") == 0) {
+	status = _rr_client_error_to_status (arg[1]);
+	free (arg);
+	*argp = 0;
     } else {
-	fprintf (stderr, "Unexpected response: %s %s\n",
-		 client->response, client->arg);
 	status = RR_STATUS_PROTOCOL_ERROR;
+	fprintf (stderr, "Unexpected response: %s\n",
+		 arg[0]);
+	free (arg);
+	*argp = 0;
     }
+    return status;
+}
 
-    free (client->response);
-    client->response = NULL;
+int
+rr_client_notice_pending (rr_client_t *client)
+{
+    if (client->notice_queue)
+	return 1;
+    if (_rr_client_readable (client))
+	return 1;
+    return 0;
+}
 
-    return status;
+rr_status_t
+rr_client_next_notice (rr_client_t *client, char ***notice)
+{
+    rr_notice_elt_t *elt = client->notice_queue;
+    rr_status_t status;
+    char **arg;
+    if (elt)
+    {
+	client->notice_queue = elt->next;
+	*notice = elt->notice;
+	free (elt);
+	return RR_STATUS_SUCCESS;
+    }
+    status = _rr_client_read_line (client, &arg);
+    if (status != RR_STATUS_SUCCESS)
+	return status;
+    _rr_strings_cdr (arg);
+    *notice = arg;
+    return RR_STATUS_SUCCESS;
+}
+
+static rr_notice_t *
+_rr_notice_create (rr_notice_type_t type, int extra)
+{
+    rr_notice_t	*n = malloc (sizeof (rr_notice_t) + extra);
+    if (!n)
+	return 0;
+    memset (n, '\0', sizeof (rr_notice_t) + extra);
+    n->type = type;
+    return n;
+}
+
+static rr_robot_t
+_rr_parse_robot (char *name)
+{
+    static struct {
+	char		    *name;
+	rr_robot_t   robot;
+    } robots[] = {
+	{ "red",    RR_ROBOT_RED },
+	{ "yellow", RR_ROBOT_YELLOW },
+	{ "green",  RR_ROBOT_GREEN },
+	{ "blue",   RR_ROBOT_BLUE },
+    };
+#define RR_NUM_ROBOTS	(sizeof (robots) / sizeof (robots[0]))
+    int	i;
+
+    for (i = 0; i < RR_NUM_ROBOTS; i++)
+	if (!strcmp (robots[i].name, name))
+	    return robots[i].robot;
+    return robots[0].robot;
+}
+
+static rr_target_color_t
+_rr_parse_color (char *name)
+{
+    static struct {
+	char		    *name;
+	rr_target_color_t   color;
+    } colors[] = {
+	{ "red",    RR_TARGET_RED },
+	{ "yellow", RR_TARGET_YELLOW },
+	{ "green",  RR_TARGET_GREEN },
+	{ "blue",   RR_TARGET_BLUE },
+	{ "whirl",  RR_TARGET_MULTI },
+    };
+#define RR_NUM_COLORS	(sizeof (colors) / sizeof (colors[0]))
+    int	i;
+
+    for (i = 0; i < RR_NUM_COLORS; i++)
+	if (!strcmp (colors[i].name, name))
+	    return colors[i].color;
+    return colors[0].color;
+}
+
+static rr_target_shape_t
+_rr_parse_shape (char *name)
+{
+    static struct {
+	char		    *name;
+	rr_target_shape_t   shape;
+    } shapes[] = {
+	{ "circle",	RR_TARGET_CIRCLE },
+	{ "octagon",	RR_TARGET_OCTAGON },
+	{ "square",	RR_TARGET_SQUARE },
+	{ "triangle",   RR_TARGET_TRIANGLE },
+	{ "whirl",	RR_TARGET_SHAPE_WHIRL },
+    };
+#define RR_NUM_SHAPES	(sizeof (shapes) / sizeof (shapes[0]))
+    int	i;
+
+    for (i = 0; i < RR_NUM_SHAPES; i++)
+	if (!strcmp (shapes[i].name, name))
+	    return shapes[i].shape;
+    return shapes[0].shape;
 }
 
+static rr_direction_t
+_rr_parse_direction (char *name)
+{
+    static struct {
+	char		*name;
+	rr_direction_t	direction;
+    } directions[] = {
+	{ "north",  RR_DIRECTION_NORTH },
+	{ "east",   RR_DIRECTION_EAST },
+	{ "south",  RR_DIRECTION_SOUTH },
+	{ "west",   RR_DIRECTION_WEST },
+    };
+#define RR_NUM_DIRECTIONS	(sizeof (directions) / sizeof (directions[0]))
+    int	i;
+
+    for (i = 0; i < RR_NUM_DIRECTIONS; i++)
+	if (!strcmp (directions[i].name, name))
+	    return directions[i].direction;
+    return directions[0].direction;
+}
+
+static int
+_rr_parse_int (char *n)
+{
+    return atoi (n);
+}
+
+static rr_notice_t *
+_rr_notice_void (rr_notice_type_t type, char **notice)
+{
+    return _rr_notice_create (type, 0);
+}
+
+static rr_notice_t *
+_rr_notice_string (rr_notice_type_t type, char **notice)
+{
+    rr_notice_t	*n = _rr_notice_create (type, strlen (notice[1]) + 1);
+    if (!n)
+	return 0;
+    n->u.string = (char *) (n + 1);
+    strcpy (n->u.string, notice[1]);
+    return n;
+}
+
+static rr_notice_t *
+_rr_notice_message (rr_notice_type_t type, char **notice)
+{
+    rr_notice_t	*n = _rr_notice_create (type, 
+					strlen (notice[1]) + 1 +
+					strlen (notice[2]) + 1);
+    if (!n)
+	return 0;
+    n->u.message.username = (char *) (n + 1);
+    n->u.message.text = n->u.message.username + strlen (notice[1]) + 1;
+    strcpy (n->u.message.username, notice[1]);
+    strcpy (n->u.message.text, notice[2]);
+    return n;
+}
+
+static rr_notice_t *
+_rr_notice_gamestate (rr_notice_type_t type, char **notice)
+{
+    rr_notice_t	*n = _rr_notice_create (type, 0);
+    static struct {
+	char		*name;
+	rr_gamestate_t	gamestate;
+    } gamestates[] = {
+	"NEW",	RR_GAMESTATE_NEW,
+	"BID",	RR_GAMESTATE_BID,
+	"SHOW",	RR_GAMESTATE_SHOW,
+	"DONE",	RR_GAMESTATE_DONE
+    };
+
+#define RR_NUM_GAMESTATES   (sizeof (gamestates) / sizeof (gamestates[0]))
+    int	i;
+
+    if (!n)
+	return 0;
+    for (i = 0; i < RR_NUM_GAMESTATES; i++)
+	if (!strcmp (notice[1], gamestates[i].name))
+	{
+	    n->u.gamestate = gamestates[i].gamestate;
+	    return n;
+	}
+    free (n);
+    return 0;
+}
+
+static rr_notice_t *
+_rr_notice_target (rr_notice_type_t type, char **notice)
+{
+    rr_notice_t	*n = _rr_notice_create (type, 0);
+    if (!n)
+	return 0;
+    n->u.target = _rr_parse_color (notice[1]) | _rr_parse_shape (notice[2]);
+    return n;
+}
+
+static rr_notice_t *
+_rr_notice_bid (rr_notice_type_t type, char **notice)
+{
+    rr_notice_t	*n = _rr_notice_create (type, strlen (notice[1]) + 1);
+    if (!n)
+	return 0;
+    n->u.bid.username = (char *) (n + 1);
+    strcpy (n->u.bid.username, notice[1]);
+    n->u.bid.number = _rr_parse_int(notice[2]);
+    return n;
+}
+
+static rr_notice_t *
+_rr_notice_number (rr_notice_type_t type, char **notice)
+{
+    rr_notice_t	*n = _rr_notice_create (type, 0);
+    if (!n)
+	return 0;
+    n->u.number = _rr_parse_int(notice[1]);
+    return n;
+}
+
+static rr_notice_t *
+_rr_notice_move (rr_notice_type_t type, char **notice)
+{
+    rr_notice_t	*n = _rr_notice_create (type, 0);
+    if (!n)
+	return 0;
+    n->u.move.count = _rr_parse_int(notice[1]);
+    n->u.move.robot = _rr_parse_robot(notice[2]);
+    n->u.move.direction = _rr_parse_direction (notice[3]);
+    return n;
+}
+
+static rr_notice_t *
+_rr_notice_position (rr_notice_type_t type, char **notice)
+{
+    rr_notice_t	*n = _rr_notice_create (type, 0);
+    if (!n)
+	return 0;
+    n->u.position.robot = _rr_parse_robot (notice[1]);
+    n->u.position.x = _rr_parse_int (notice[2]);
+    n->u.position.y = _rr_parse_int (notice[3]);
+    return n;
+}
+
+static struct {
+    char		*name;
+    rr_notice_type_t	type;
+    rr_notice_t		*(*func) (rr_notice_type_t, char **);
+} notices[] = {
+    /* global game notices */
+    { "USER",		RR_NOTICE_USER, 	_rr_notice_string },
+    { "QUIT",		RR_NOTICE_QUIT, 	_rr_notice_void },
+    { "GAME",		RR_NOTICE_GAME, 	_rr_notice_string },
+    { "DISPOSE",	RR_NOTICE_DISPOSE,	_rr_notice_void},
+    { "MESSAGE",	RR_NOTICE_MESSAGE,	_rr_notice_message },
+    { "GAMESTATE",	RR_NOTICE_GAMESTATE,	_rr_notice_gamestate },
+    { "TURN",		RR_NOTICE_TURN,		_rr_notice_target },
+    { "GAME",		RR_NOTICE_GAME,		_rr_notice_string },
+    { "JOIN",		RR_NOTICE_JOIN,		_rr_notice_string },
+    { "WATCH",		RR_NOTICE_WATCH,	_rr_notice_string },
+    { "PART",		RR_NOTICE_PART,		_rr_notice_string },
+    /* bid notices */
+    { "BID",		RR_NOTICE_BID,		_rr_notice_bid },
+    { "REVOKE",		RR_NOTICE_REVOKE,	_rr_notice_string },
+    { "TIMER",		RR_NOTICE_TIMER,	_rr_notice_number },
+    { "ABANDON",	RR_NOTICE_ABANDON,	_rr_notice_string },
+    { "NOBID",		RR_NOTICE_NOBID,	_rr_notice_string },
+    /* solving notices */
+    { "ACTIVE",		RR_NOTICE_ACTIVE,	_rr_notice_bid },
+    { "MOVE",		RR_NOTICE_MOVE,		_rr_notice_move },
+    { "UNDO",		RR_NOTICE_UNDO,		_rr_notice_void },
+    { "RESET",		RR_NOTICE_RESET,	_rr_notice_void },
+    { "POSITION",	RR_NOTICE_POSITION,	_rr_notice_position },
+    { "SCORE",		RR_NOTICE_SCORE,	_rr_notice_bid },
+    /* user notices */
+    { "ACTIVATE",	RR_NOTICE_ACTIVATE,	_rr_notice_number }
+};
+
+#define NUM_NOTICES (sizeof (notices) / sizeof (notices[0]))
+
+rr_notice_t *
+rr_client_parse_notice (rr_client_t *client, char **notice)
+{
+    int	i;
+
+    for (i = 0; i < NUM_NOTICES; i++)
+	if (!strcmp (notice[0], notices[i].name))
+	    return (*notices[i].func) (notices[i].type, notice);
+    return 0;
+}

Index: rr_strbuf.c
===================================================================
RCS file: /local/src/CVS/librr/src/rr_strbuf.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- rr_strbuf.c	5 Jun 2003 14:32:42 -0000	1.1
+++ rr_strbuf.c	12 Jun 2003 07:09:09 -0000	1.2
@@ -37,7 +37,7 @@
 }
 
 char *
-_rr_strbuf_fini (rr_strbuf_t *buf)
+_rr_strbuf_str (rr_strbuf_t *buf)
 {
     char *str;
 
@@ -52,6 +52,16 @@
     return str;
 }
 
+void
+_rr_strbuf_fini (rr_strbuf_t *buf)
+{
+    if (buf->str)
+	free (buf->str);
+    buf->str = 0;
+    buf->size = 0;
+    buf->len = 0;
+}
+
 #define RR_STRBUF_GROWTH 48
 rr_status_t
 _rr_strbuf_append (rr_strbuf_t *buf, char c)
@@ -72,3 +82,50 @@
     return RR_STATUS_SUCCESS;
 }
 
+rr_status_t
+_rr_strstrbuf_init (rr_strstrbuf_t *buf)
+{
+    _rr_strbuf_init (&buf->str);
+    buf->len = 0;
+    return RR_STATUS_SUCCESS;
+}
+
+char **
+_rr_strstrbuf_fini (rr_strstrbuf_t *buf)
+{
+    char    **ret, *d, *s;
+    int	    i;
+
+    ret = (char **) malloc ((buf->len + 1) * (sizeof (char *)) +
+			    buf->str.len + 1);
+    if (!ret)
+	return 0;
+    d = (char *) (ret + buf->len + 1);
+    s = buf->str.str;
+    for (i = 0; i < buf->len; i++)
+    {
+	int l;
+	ret[i] = d;
+	strcpy (d, s);
+	l = strlen (s);
+	d += l + 1;
+	s += l + 1;
+    }
+    ret[i] = 0;
+    _rr_strbuf_fini (&buf->str);
+    buf->len = 0;
+    return ret;
+}
+
+rr_status_t
+_rr_strstrbuf_append (rr_strstrbuf_t *buf, char *s)
+{
+    char c;
+    buf->len++;
+    do {
+	rr_status_t status = _rr_strbuf_append (&buf->str, c = *s++);
+	if (status != RR_STATUS_SUCCESS)
+	    return status;
+    } while (c);
+    return RR_STATUS_SUCCESS;
+}

Index: rr_string.c
===================================================================
RCS file: /local/src/CVS/librr/src/rr_string.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- rr_string.c	5 Jun 2003 14:32:42 -0000	1.1
+++ rr_string.c	12 Jun 2003 07:09:09 -0000	1.2
@@ -69,3 +69,22 @@
 	*str = new_str;
     }
 }
+
+void
+_rr_strings_cdr (char **args)
+{
+    int	l;
+
+    for (l = 0; args[l]; l++);
+    memmove (args, args + 1, l * sizeof (char *));
+}
+
+char *
+_rr_string_dup (char *s)
+{
+    char    *r = malloc (strlen (s) + 1);
+    if (!r)
+	return 0;
+    strcpy (r, s);
+    return r;
+}

Index: rrint.h
===================================================================
RCS file: /local/src/CVS/librr/src/rrint.h,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -d -r1.4 -r1.5
--- rrint.h	11 Jun 2003 23:26:14 -0000	1.4
+++ rrint.h	12 Jun 2003 07:09:09 -0000	1.5
@@ -32,7 +32,6 @@
 #include <stdint.h>
 #include <stdarg.h>
 #include <string.h>
-#include <pthread.h>
 
 #include "rr.h"
 
@@ -101,17 +100,19 @@
     char *arg;
 } rr_command_t, rr_request_t, rr_response_t;
 
-struct rr_client {
-    pthread_mutex_t mutex;
-    pthread_t response_thread;
-
-    char *response;
-    char *arg;
-    pthread_cond_t response_cond;
+typedef struct rr_notice_elt {
+    struct rr_notice_elt *next;
+    char **notice;
+} rr_notice_elt_t;
 
-    rr_board_t board;
+#define RR_BUF_SIZE 1024
 
+struct rr_client {
     int sock;
+    char buf[RR_BUF_SIZE];
+    int ptr;
+    int end;
+    rr_notice_elt_t *notice_queue;
 };
 
 typedef struct rr_strbuf {
@@ -120,6 +121,11 @@
     int len;
 } rr_strbuf_t;
 
+typedef struct rr_strstrbuf {
+    rr_strbuf_t str;
+    int	len;
+} rr_strstrbuf_t;
+
 /* rr.c */
 char
 _rr_robot_to_char (rr_robot_t robot);
@@ -176,11 +182,23 @@
 _rr_strbuf_init (rr_strbuf_t *buf);
 
 char *
+_rr_strbuf_str (rr_strbuf_t *buf);
+
+void
 _rr_strbuf_fini (rr_strbuf_t *buf);
 
 rr_status_t
 _rr_strbuf_append (rr_strbuf_t *buf, char c);
 
+rr_status_t
+_rr_strstrbuf_init (rr_strstrbuf_t *buf);
+
+char **
+_rr_strstrbuf_fini (rr_strstrbuf_t *buf);
+
+rr_status_t
+_rr_strstrbuf_append (rr_strstrbuf_t *buf, char *s);
+
 /* rr_string.c */
 
 int
@@ -188,5 +206,11 @@
 
 int
 _rr_string_sprintf_alloc_va (char **str, const char *fmt, va_list ap);
+
+void
+_rr_strings_cdr (char **args);
+
+char *
+_rr_string_dup (char *str);
 
 #endif




More information about the Commit mailing list