From a2ce7dd42dbca39d428df8be379c00364e0b1e40 Mon Sep 17 00:00:00 2001 From: Lon Hohberger Date: Fri, 17 Oct 2008 17:27:36 -0400 Subject: [PATCH] Make console callback use split parameters (e.g. argc/argv style) --- console_args.c | 99 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ main.c | 24 +++++++++----- oglconsole.c | 18 ++++++++--- oglconsole.h | 5 ++- 4 files changed, 133 insertions(+), 13 deletions(-) create mode 100644 console_args.c diff --git a/console_args.c b/console_args.c new file mode 100644 index 0000000..8f0804a --- /dev/null +++ b/console_args.c @@ -0,0 +1,99 @@ +/** + * License - GPL + * + * Command-line splitter function. + * Lon Hohberger + */ +#include +#include +#include + +typedef enum _command_state { + STATE_QUOTE = 0x1, + STATE_LITERAL = 0x2, + STATE_COPY = 0x4 +} command_state_t; + + +/** + * Break up a command string into argv values. Rudimentary. + * Destroys the value of cmdline (inserts 0s in order to keep argv + * pointers 0-terminated in typical C-style) + */ +int +command_split(char *cmdline, int *argc, char **argv, int max) +{ + char *cmd_copy = NULL; + command_state_t state = 0; + int offset = 0, copy_offset = 0, ret = 1; + + if (max <= 0 || argv == NULL || argc == NULL) { + errno = EINVAL; + return -1; + } + + cmd_copy = strdup(cmdline); + if (!cmd_copy) + return -1; + + memset(cmdline, 0, strlen(cmdline)+1); + *argc = 0; + + while (cmd_copy[copy_offset]) { + switch(cmd_copy[copy_offset]) { + case ' ': + case '\t': + case '\r': + case '\n': + if (state & (STATE_LITERAL | STATE_QUOTE)) + break; + if (state & STATE_COPY) { + state &= ~STATE_COPY; + cmdline[offset++] = 0; + continue; + } + if (!state) { + copy_offset++; + continue; + } + break; + case '\\': + if (state & STATE_LITERAL) + break; + state |= STATE_LITERAL; + ++copy_offset; + continue; + + case '\"': + if (state & STATE_LITERAL) + break; + if (state & STATE_QUOTE) { + state &= ~STATE_QUOTE; + } else { + state |= STATE_QUOTE; + } + ++copy_offset; + continue; + } + + if (!(state & STATE_COPY)) { + if (*argc >= max) + goto out; + state |= STATE_COPY; + argv[(*argc)++] = &cmdline[offset]; + } + + state &= ~STATE_LITERAL; + + cmdline[offset] = cmd_copy[copy_offset]; + ++offset; + ++copy_offset; + } + ret = 0; + +out: + if (cmd_copy) + free(cmd_copy); + return ret; +} + diff --git a/main.c b/main.c index b3c160c..443f0d9 100644 --- a/main.c +++ b/main.c @@ -58,7 +58,7 @@ void die(int ret) } -static int parse_resolution(char *res, int *w, int *h, int *bpp) +int parse_resolution(char *res, int *w, int *h, int *bpp) { char res_copy[80]; char *p; @@ -95,17 +95,25 @@ out_err: /* TODO: rewrite parsing routines here */ /* TODO: Add 'map' command to change maps */ -static void console_input(OGLCONSOLE_Console console, char *cmd) +static void console_input(OGLCONSOLE_Console console, int argc, char **argv) { + char *cmd = argv[0]; int width, height, x; - if (!strncmp(cmd, "quit", 4) || - !strncmp(cmd, "exit", 4)) { + if (argc < 1) + return; + + if (!strcasecmp(cmd, "quit") || + !strcasecmp(cmd, "exit")) { die(0); } - if (!strncmp(cmd, "res ", 4)) { - if (parse_resolution((cmd+4), &width, &height, &x) != 0) { + if (!strcasecmp(cmd, "res")) { + if (argc < 2) { + con_printf("usage: res e.g. 640x480\n"); + return; + } + if (parse_resolution(argv[1], &width, &height, &x) != 0) { con_printf("usage: res e.g. 640x480\n"); return; } @@ -115,7 +123,7 @@ static void console_input(OGLCONSOLE_Console console, char *cmd) return; } - if (!strncmp(cmd, "score", 5)) { + if (!strcasecmp(cmd, "score")) { if (!current_game) { con_printf("Start playing, first...\n"); return; @@ -188,13 +196,13 @@ int main(int argc, char **argv) object_read_file("gfx/ghost-green-moving.3d", &last_update); object_read_file("gfx/ghost-green-dying.3d", &last_update); object_read_file("gfx/ghost-green-returning.3d", &last_update); -*/ if(argc > 1 && strcmp(argv[1], "--server") == 0) net_server_init(); if(argc > 1 && strcmp(argv[1], "--connect") == 0) net_client_init(argv[2]); +*/ OGLCONSOLE_Create(); OGLCONSOLE_EnterKey(console_input); diff --git a/oglconsole.c b/oglconsole.c index 055ec8a..66fb7db 100644 --- a/oglconsole.c +++ b/oglconsole.c @@ -101,6 +101,8 @@ OGLCONSOLE_CreateFont(void) * commands) */ #define MAX_HISTORY_COUNT 25 +#define MAX_COMMAND_ARGS 20 + /* This is the default number of lines for the console to remember (that is to * say, the user can scroll up and down to see what has been printed to the * console in the past, and this is the number of those lines, plus the number @@ -142,7 +144,7 @@ typedef struct { int visibility; /* Various callback functions defined by the user */ - void (*enterKeyCallback) (OGLCONSOLE_Console console, char *cmd); + void (*enterKeyCallback) (OGLCONSOLE_Console console, int argc, char **argv); } _OGLCONSOLE_Console; @@ -154,13 +156,13 @@ _OGLCONSOLE_Console *userConsole = NULL; /* Set the callback for a console */ void -OGLCONSOLE_EnterKey(void (*cbfun) (OGLCONSOLE_Console console, char *cmd)) +OGLCONSOLE_EnterKey(void (*cbfun) (OGLCONSOLE_Console console, int argc, char **argv)) { programConsole->enterKeyCallback = cbfun; } void -OGLCONSOLE_DefaultEnterKeyCallback(OGLCONSOLE_Console console, char __attribute__((unused)) *cmd) +OGLCONSOLE_DefaultEnterKeyCallback(OGLCONSOLE_Console console, int __attribute__((unused)) argc, char __attribute__((unused)) **argv) { OGLCONSOLE_Output(console, "No enter key callback is registered for this console!\n"); @@ -913,6 +915,9 @@ OGLCONSOLE_SDLEvent(SDL_Event * e) } else if (e->key.keysym.sym == KEY_RETURN) { + char *argv[MAX_COMMAND_ARGS]; + int argc = 0; + /* Yank the command history if necessary */ OGLCONSOLE_YankHistory(userConsole); @@ -925,8 +930,13 @@ OGLCONSOLE_SDLEvent(SDL_Event * e) userConsole->inputLine); /* Invoke console's enter-key callback function */ + if (command_split(userConsole->inputLine, &argc, argv, + MAX_COMMAND_ARGS)) { + OGLCONSOLE_Output((void *)userConsole, + "Warning: Command line too long!\n"); + } userConsole->enterKeyCallback((void *) userConsole, - userConsole->inputLine); + argc, argv); /* Erase command line */ userConsole->inputCursorPos = 0; diff --git a/oglconsole.h b/oglconsole.h index cd26910..d0c95d0 100644 --- a/oglconsole.h +++ b/oglconsole.h @@ -18,6 +18,8 @@ void OGLCONSOLE_InitText(void *console, int res_x, int res_y); void OGLCONSOLE_Destroy(OGLCONSOLE_Console console); void OGLCONSOLE_Quit(void); +int command_split(char *cmd, void **argv, int *argc, int max); + /* Set console which has PROGRAMMER focus (not application focus) */ /* This function renders the console */ @@ -35,7 +37,8 @@ do { \ } while(0) /* Register a callback with the console */ -void OGLCONSOLE_EnterKey(void(*cbfun)(OGLCONSOLE_Console console, char *cmd)); +void OGLCONSOLE_EnterKey(void(*cbfun)(OGLCONSOLE_Console console, + int argc, char **argv)); /* This function tries to handle the incoming SDL event. In the future there may * be non-SDL analogs for input systems such as GLUT. Returns true if the event -- 2.11.4.GIT