]> git.cworth.org Git - ttt/commitdiff
2005-12-01 Richard D. Worth <richard@theworths.org>
authorRichard Worth <richard@theworths.org>
Fri, 2 Dec 2005 01:38:34 +0000 (01:38 +0000)
committerRichard Worth <richard@theworths.org>
Fri, 2 Dec 2005 01:38:34 +0000 (01:38 +0000)
        * TODO: Check off NOTICE MESSAGE, ERROR NONAMESET.

        * PROTOCOL: Add NONAMESET error in possible errors where
        applicable. Add description for MESSAGE.

        * src/ttt-token.h: Add token typedef. Rename token type enum.

        * src/ttt-lex.l: Add support for quoted string as single token.
        * src/ttt-lex.h: Autogenerated.

        * src/ttt-client.c: (_ttt_client_execute_helo),
        (_ttt_client_execute_who), (_ttt_client_execute_message),
        (_ttt_client_execute_help), (_ttt_client_execute_version),
        (_ttt_client_execute_quit), (_ttt_client_init), (_read_request),
        (_execute_request): Whitespace changes. Implement VERSION,
        HELP. Change args_required back to args_min and args_max (see
        PROTOCOL\HELP). Modify MESSAGE to accept one token arg and quote
        output. Return NONAMESET error where applicable.

ChangeLog
PROTOCOL
TODO
src/ttt-client.c
src/ttt-lex.h
src/ttt-lex.l
src/ttt-token.h

index 27e0d4bb1894aa23844e751a30463bd06526a022..23619261d0816f38f4c121952bfee8e90d97e39b 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,24 @@
+2005-12-01  Richard D. Worth  <richard@theworths.org>
+
+       * TODO: Check off NOTICE MESSAGE, ERROR NONAMESET.
+
+       * PROTOCOL: Add NONAMESET error in possible errors where
+       applicable. Add description for MESSAGE.
+       
+       * src/ttt-token.h: Add token typedef. Rename token type enum.
+
+       * src/ttt-lex.l: Add support for quoted string as single token.
+       * src/ttt-lex.h: Autogenerated.
+
+       * src/ttt-client.c: (_ttt_client_execute_helo),
+       (_ttt_client_execute_who), (_ttt_client_execute_message),
+       (_ttt_client_execute_help), (_ttt_client_execute_version),
+       (_ttt_client_execute_quit), (_ttt_client_init), (_read_request),
+       (_execute_request): Whitespace changes. Implement VERSION,
+       HELP. Change args_required back to args_min and args_max (see
+       PROTOCOL\HELP). Modify MESSAGE to accept one token arg and quote
+       output. Return NONAMESET error where applicable.
+
 2005-11-29  Carl Worth  <cworth@cworth.org>
 
        * src/ttt-socket.h:
index c507ffeb27ca47eaa9c9098c301486b22916ffd3..d855cdf348780bc1edecce3e10e5ddb93d36d471 100644 (file)
--- a/PROTOCOL
+++ b/PROTOCOL
@@ -59,7 +59,9 @@ Document Conventions
 
        WHO <username1> <games1> <username2> <games2> ...
 
-       lists connected users and the number of games they've won.
+       Lists connected users and the number of games they've won.
+
+       Possible errors: NONAMESET
 
     1.2.2. Message
 
@@ -69,6 +71,12 @@ Document Conventions
        
        MESSAGE
 
+       Sends a message to all connected users. The text must be a
+       single token. Use a quoted-string to include spaces in the
+       message text.
+
+       Possible errors: NONAMESET
+
     1.2.3. Help
 
        HELP { <command> }
@@ -111,7 +119,7 @@ Document Conventions
 
        INVITE
 
-       Possible errors: NOUSER, BUSY
+       Possible errors: NOUSER, BUSY, NONAMESET
 
     1.3.2. Accepting an invitation
 
@@ -121,6 +129,8 @@ Document Conventions
 
        ACCEPT
 
+       Possible errors: NONAMESET
+
 1.4. In-game commands
 
     1.4.1. Get the game contents
@@ -148,7 +158,7 @@ Document Conventions
         _|X|_
         X|O|O"
     
-       Possible errors: NOTINGAME
+       Possible errors: NOTINGAME, NONAMESET
     
     1.4.2. Part
     
@@ -160,7 +170,7 @@ Document Conventions
     
        Departs the current game
 
-       Possible errors: NOTINGAME
+       Possible errors: NOTINGAME, NONAMESET
     
     1.4.3. Making a move
 
@@ -177,7 +187,7 @@ Document Conventions
        3|4|5
        6|7|8
     
-       Possible errors: NOTINGAME, NOTYOURMOVE, NOTGRID
+       Possible errors: NOTINGAME, NOTYOURMOVE, NOTGRID, NONAMESET
     
 2. Asynchronous notification.  
 
@@ -254,7 +264,10 @@ Document Conventions
     
        ERROR NONAMESET
     
-       'helo' must be sent before any command other than 'quit'.
+       'helo' must be sent before any command other than 'help',
+       'version', 'quit'.
+
+       Possibly returned by: WHO MESSAGE INVITE ACCEPT SHOW PART MOVE
     
     3.1.2. Invalid name
     
diff --git a/TODO b/TODO
index c55f890e370dfd677ff61cb5380f3f89a0b146d0..ec6630fb10f8e08c13cbef8f3200345dd878244f 100644 (file)
--- a/TODO
+++ b/TODO
@@ -25,7 +25,7 @@ S C
 ✓   2.1.2. NOTICE QUIT <username>
     2.1.3. NOTICE INVITE <username>
     2.1.4. NOTICE DISPOSE <game>
-    2.1.5. NOTICE MESSAGE <username> <text>
+   2.1.5. NOTICE MESSAGE <username> <text>
     2.2. Game notices
     2.2.1. Global game notices
     2.2.1.1. NOTICE NEWGAME <username> <username>
@@ -34,7 +34,7 @@ S C
     2.2.2.1. NOTICE MOVE <username> <number>
     3. Errors
     3.1. Connection setup errors
-    3.1.1. ERROR NONAMESET
+   3.1.1. ERROR NONAMESET
 ✓   3.1.2. ERROR INVALIDNAME
     3.2. Command format errors
     3.2.1. ERROR COMMAND
index 5f2a193179a0c644c410ed534549a186b06fd4cc..81f6e13e14268227e23a640f8288d933e7e66e15 100644 (file)
@@ -21,6 +21,8 @@
 
 #include "ttt-client.h"
 
+#define YY_DECL int yylex (yyscan_t yyscanner, ttt_token_t *token)
+
 #include "ttt-error.h"
 #include "ttt-lex.h"
 #include "ttt-server.h"
 struct _ttt_client {
     pthread_mutex_t mutex;
     pthread_t       thread;
-
+    
     ttt_server_t    *server;
     int             socket;
     yyscan_t        scanner;
-
+    
     char            **request_strings;
     int             num_request_strings;
-
+    
     char            *name;
     ttt_bool_t      registered;
     int             num_wins;
@@ -57,29 +59,40 @@ _ttt_client_execute_who (ttt_client_t *client,
                         char         **args,
                         int          num_args);
 
-static ttt_error_t
-_ttt_client_execute_quit (ttt_client_t *client,
-                         char         **args,
-                         int          num_args);
-
 static ttt_error_t
 _ttt_client_execute_message (ttt_client_t *client,
                             char         **args,
                             int          num_args);
 
+static ttt_error_t
+_ttt_client_execute_help (ttt_client_t  *client,
+                         char     **args,
+                         int      num_args);
+
+static ttt_error_t
+_ttt_client_execute_version (ttt_client_t  *client,
+                            char          **args,
+                            int           num_args);
 
+static ttt_error_t
+_ttt_client_execute_quit (ttt_client_t *client,
+                         char         **args,
+                         int          num_args);
 
 typedef struct _ttt_command_description {
     const char         *command;
-    int                args_required;
+    int                args_min;
+    int                args_max;
     ttt_command_func_t execute;
 } ttt_command_description_t;
 
 ttt_command_description_t command_descriptions[] = {
-    {"HELO",    1, _ttt_client_execute_helo},
-    {"WHO",     0, _ttt_client_execute_who },
-    {"QUIT",    0, _ttt_client_execute_quit},
-    {"MESSAGE", 1, _ttt_client_execute_message}
+    {"HELO",    1, 1, _ttt_client_execute_helo   },
+    {"WHO",     0, 0, _ttt_client_execute_who    },
+    {"MESSAGE", 1, 1, _ttt_client_execute_message},
+    {"HELP",    0, 1, _ttt_client_execute_help   },
+    {"VERSION", 1, 1, _ttt_client_execute_version},
+    {"QUIT",    0, 0, _ttt_client_execute_quit   }
 };
 
 #define ARRAY_SIZE(arr) (sizeof(arr)/sizeof(arr[0]))
@@ -91,6 +104,7 @@ _ttt_client_execute_helo (ttt_client_t *client,
 {
     ttt_error_t error;
     char *response;
+    char *notice;
 
     assert (num_args == 1);
 
@@ -99,19 +113,19 @@ _ttt_client_execute_helo (ttt_client_t *client,
     error = ttt_server_register_client (client->server, client);
     if (error)
        return error;
-
     client->registered = TRUE;
 
     xasprintf (&response, "HELO %s %s %s\r\n",
               client->name,
               ttt_server_get_host (client->server),
               ttt_server_get_port (client->server));
-
     ttt_client_send (client, response);
 
-    xasprintf (&response, "NOTICE USER %s\r\n",client->name);
-    ttt_server_broadcast(client->server,response);
+    xasprintf (&notice, "NOTICE USER %s\r\n",
+              client->name);
+    ttt_server_broadcast (client->server, notice);
 
+    free (notice);
     free (response);
 
     return TTT_ERROR_NONE;
@@ -126,8 +140,10 @@ _ttt_client_execute_who (ttt_client_t *client,
 
     assert (num_args == 0);
 
-    response = ttt_server_who (client->server);
+    if (!client->registered)
+       return TTT_ERROR_NO_NAME_SET;
 
+    response = xstrdup (ttt_server_who (client->server));
     ttt_client_send (client, response);
 
     free (response);
@@ -136,44 +152,86 @@ _ttt_client_execute_who (ttt_client_t *client,
 }
 
 static ttt_error_t
-_ttt_client_execute_quit (ttt_client_t *client,
-                         char         **args,
-                         int          num_args)
+_ttt_client_execute_message (ttt_client_t  *client,
+                            char          **args,
+                            int           num_args)
 {
+    char *response;
     char *notice;
 
-    assert (num_args == 0);
-    xasprintf (&notice,"NOTICE QUIT %s\r\n",client->name);
-    ttt_server_broadcast(client->server,notice);
+    assert (num_args == 1);
+
+    if (!client->registered)
+       return TTT_ERROR_NO_NAME_SET;
+
+    xasprintf(&response, "MESSAGE\r\n");
+    ttt_client_send (client, response);
+
+    xasprintf(&notice, "NOTICE MESSAGE %s \"%s\"\r\n",
+             client->name,
+             args[0]);
+    ttt_server_broadcast (client->server, notice);
+
     free (notice);
-    return TTT_ERROR_QUIT_REQUESTED;
+    free (response);
+
+    return TTT_ERROR_NONE;
 }
 
 static ttt_error_t
-_ttt_client_execute_message (ttt_client_t  *client,
+_ttt_client_execute_help (ttt_client_t  *client,
+                         char     **args,
+                         int      num_args)
+{
+    char *response;
+
+    /* XXX: NYI */
+
+    xasprintf(&response, "HELP - NYI\r\n");
+    ttt_client_send (client, response);
+
+    free (response);
+    return TTT_ERROR_NONE;
+}
+
+static ttt_error_t
+_ttt_client_execute_version (ttt_client_t  *client,
                             char          **args,
                             int           num_args)
 {
     char *response;
-    int i;
 
-    assert (num_args > 0);
+    assert (num_args == 1);
 
-    xasprintf(&response, "MESSAGE\r\n");
-    ttt_client_send (client, response);
-    
-    xasprintf(&response, "NOTICE MESSAGE %s", client->name);
-    for (i=0; i<num_args; i++){
-       xasprintf(&response, "%s %s",response,args[i]);
+    /* XXX: Argument is being ignored.
+       This is not completely implemented. */
 
-    }
-    xasprintf(&response, "%s\r\n",response);
-    ttt_server_broadcast (client->server,response);
+    xasprintf (&response, "VERSION 1\r\n");
+    ttt_client_send (client, response);
 
     free (response);
     return TTT_ERROR_NONE;
+}
 
+static ttt_error_t
+_ttt_client_execute_quit (ttt_client_t *client,
+                         char         **args,
+                         int          num_args)
+{
+    char *notice;
 
+    assert (num_args == 0);
+
+    if (!client->registered)
+       return TTT_ERROR_QUIT_REQUESTED;
+    
+    xasprintf (&notice, "NOTICE QUIT %s\r\n",
+              client->name);
+    ttt_server_broadcast (client->server, notice);
+    
+    free (notice);
+
+    return TTT_ERROR_QUIT_REQUESTED;
 }
 
 static void
@@ -192,7 +250,7 @@ _ttt_client_init (ttt_client_t      *client,
     client->socket = socket;
 
     file = xfdopen (socket, "r");
-    yylex_init(&client->scanner);
+    yylex_init (&client->scanner);
     yyset_in (file, client->scanner);
 
     client->request_strings = NULL;
@@ -255,25 +313,28 @@ static ttt_status_t
 _read_request (ttt_client_t *client)
 {
     ttt_token_t token;
+    ttt_token_type_t token_type;
 
     _free_request (client);
 
     while (1) {
-       token = yylex (client->scanner);
+       token_type = yylex (client->scanner, &token);
        /* Yes, EOF in two different enums is pretty ugly. */
-       if (token == TTT_TOKEN_EOF)
+       if (token_type == TTT_TOKEN_TYPE_EOF)
            return TTT_STATUS_EOF;
 
-       if (token == TTT_TOKEN_NEWLINE) {
+       if (token_type == TTT_TOKEN_TYPE_NEWLINE) {
            if (client->num_request_strings)
                return TTT_STATUS_SUCCESS;
            else
                continue;
        }
 
-       assert (token == TTT_TOKEN_STRING);
-
-       _append_to_request (client, yyget_text (client->scanner));
+       assert (token_type == TTT_TOKEN_TYPE_STRING);
+        
+       _append_to_request (client, token.u.string);
+       
+       free (token.u.string);
     }
 }
 
@@ -292,11 +353,11 @@ _execute_request (ttt_client_t *client)
     for (i=0; i < ARRAY_SIZE(command_descriptions); i++) {
        desc = &command_descriptions[i];
        if (strcmp(command, desc->command) == 0) {
-           if (num_args < desc->args_required)
+           if ((num_args < desc->args_min) || (num_args > desc->args_max))
                return TTT_ERROR_SYNTAX;
            return (desc->execute) (client, &client->request_strings[1], num_args);
-           }
        }
+    }
 
     return TTT_ERROR_COMMAND;
 }
index d70d5d89ce9ca4134965a7b6a2f5565daa8566a1..1f98457329073f87ded04933ecf3816ee575e940 100644 (file)
@@ -209,6 +209,7 @@ void yyfree (void * ,yyscan_t yyscanner );
 
 #ifdef YY_HEADER_EXPORT_START_CONDITIONS
 #define INITIAL 0
+#define STRING 1
 
 #endif
 
@@ -314,8 +315,8 @@ extern int yylex (yyscan_t yyscanner);
 #undef YY_DECL_IS_OURS
 #undef YY_DECL
 #endif
-#line 17 "ttt-lex.l"
+#line 65 "ttt-lex.l"
 
-#line 320 "ttt-lex.h"
+#line 321 "ttt-lex.h"
 #undef yyIN_HEADER
 #endif /* yyHEADER_H */
index 2a9d8e247908e33e5754a850492d9f52c3243ded..06685c4a178565ed9d969a2dad82296a6ba24f4e 100644 (file)
@@ -5,12 +5,60 @@
 
 %{
 #include "ttt-token.h"
+
+#define YY_DECL int yylex (yyscan_t yyscanner, ttt_token_t *token)
+
+#define STRING_BUF_SIZE 8000
 %}
 
+%x STRING
+
 %%
 
+       char string_buf[STRING_BUF_SIZE];
+       char *string_buf_ptr;
+
   /* Rules */
 
-\r\n                   return TTT_TOKEN_NEWLINE;
-[^ \t\r\n][^ \t\r\n]*  return TTT_TOKEN_STRING;
-[ \t\r\n]              ;
+\r\n           {
+                       token->type = TTT_TOKEN_TYPE_NEWLINE;
+                       return token->type;
+               }
+
+\"             {
+                       string_buf_ptr = string_buf;
+                       BEGIN (STRING);
+               }
+
+<STRING>{
+               \\\"            {
+                                       *string_buf_ptr++ = '"';
+                               }
+
+               \\              {
+                                       *string_buf_ptr++ = '\\';
+                               }
+
+               [^\\\"\\]+      {
+                                       char *s = yytext;
+                                       
+                                       while (*s)
+                                             *string_buf_ptr++ = *s++;
+                               }
+
+               \"              {
+                                       BEGIN (INITIAL);
+                                       *string_buf_ptr = '\0';
+                                       token->type = TTT_TOKEN_TYPE_STRING;
+                                       token->u.string = xstrdup (string_buf);
+                                       return token->type;
+                               }
+}
+
+[^ \t\r\n\"][^ \t\r\n\"]*      {
+                       token->type = TTT_TOKEN_TYPE_STRING;
+                       token->u.string = xstrdup (yytext);
+                       return token->type;
+               }
+
+[ \t\r\n]      ;
index f063d6094dd8e3483a07e889e8c71af33c8fa9c2..a927b05db236b94141379267b41b553dc337da58 100644 (file)
 #define _TTT_TOKEN_H_
 
 typedef enum {
-    TTT_TOKEN_EOF = 0,
-    TTT_TOKEN_STRING,
-    TTT_TOKEN_NEWLINE
+    TTT_TOKEN_TYPE_EOF = 0,
+    TTT_TOKEN_TYPE_COMMAND,
+    TTT_TOKEN_TYPE_STRING,
+    TTT_TOKEN_TYPE_NEWLINE
+} ttt_token_type_t;
+
+typedef struct _ttt_token {
+    ttt_token_type_t   type;
+    union {
+       char *string;
+    } u;
 } ttt_token_t;
 
 #endif /* _TTT_TOKEN_H_ */