19 cmd_handler_t function;
20 const char *help_text;
24 /* The list of cmds */
25 static cmd_t *cmd_list;
28 #define ALIAS_NAME_MAX 32
29 typedef struct cmd_alias_s
31 char name[ALIAS_NAME_MAX];
33 struct cmd_alias_s *next;
36 /* The list of aliases */
37 static cmd_alias_t *cmd_alias_list;
40 typedef struct cmd_queue_s
43 struct cmd_queue_s *next;
46 /* The list of commands to be executed */
47 static cmd_queue_t *cmd_queue_head;
48 static cmd_queue_t *cmd_queue_tail;
51 /* number of cycles to wait before processing any commands */
52 static int cmd_queue_wait;
55 /* add a new console command */
56 void cmd_addcommand(const char *cmd_name, cmd_handler_t cmd_func, const char *cmd_help_text)
60 Assert(cmd_name != NULL);
62 for (cmd = cmd_list; cmd; cmd = cmd->next) {
63 if (!stricmp(cmd_name, cmd->name))
66 con_printf(CON_NORMAL, "command %s already exists, not adding\n", cmd_name);
71 /* create command, insert at front of list */
72 MALLOC(cmd, cmd_t, 1);
74 cmd->function = cmd_func;
75 cmd->help_text = cmd_help_text;
77 con_printf(CON_DEBUG, "cmd_addcommand: added %s\n", cmd->name);
82 void cvar_cmd_set(int argc, char **argv);
85 /* execute a parsed command */
86 void cmd_execute(int argc, char **argv)
91 for (cmd = cmd_list; cmd; cmd = cmd->next) {
92 if (!stricmp(argv[0], cmd->name)) {
93 con_printf(CON_DEBUG, "cmd_execute: executing %s\n", argv[0]);
94 cmd->function(argc, argv);
99 for (alias = cmd_alias_list; alias; alias = alias->next) {
100 if (!stricmp(argv[0], alias->name)) {
101 con_printf(CON_DEBUG, "cmd_execute: pushing alias \"%s\": %s\n", alias->name, alias->value);
102 cmd_insert(alias->value);
108 { // set value of cvar
109 char *new_argv[argc+1];
113 for (i = 0; i < argc; i++)
114 new_argv[i+1] = argv[i];
115 cvar_cmd_set(argc + 1, new_argv);
120 /* Parse an input string */
121 void cmd_parse(char *input)
123 char buffer[CMD_MAX_LENGTH];
124 char *tokens[CMD_MAX_TOKENS];
128 Assert(input != NULL);
130 /* Strip leading spaces */
131 while( isspace(*input) ) { ++input; }
132 strncpy( buffer, input, CMD_MAX_LENGTH );
134 //printf("lead strip \"%s\"\n",buffer);
135 l = (int)strlen(buffer);
136 /* If command is empty, give up */
139 /* Strip trailing spaces */
140 for (i=l-1; i>0 && isspace(buffer[i]); i--) ;
142 //printf("trail strip \"%s\"\n",buffer);
144 /* Split into tokens */
145 l = (int)strlen(buffer);
149 for (i=1; i<l; i++) {
150 if (buffer[i] == '"') {
151 tokens[num_tokens - 1] = &buffer[++i];
152 while (i < l && buffer[i] != '"')
157 if (isspace(buffer[i]) || buffer[i] == '=') {
159 while (isspace(buffer[i+1]) && (i+1 < l)) i++;
160 tokens[num_tokens++] = &buffer[i+1];
164 /* Check for matching commands */
165 cmd_execute(num_tokens, tokens);
169 int cmd_queue_process(void)
173 while (!cmd_queue_wait && cmd_queue_head) {
174 cmd = cmd_queue_head;
175 cmd_queue_head = cmd_queue_head->next;
177 cmd_queue_tail = NULL;
179 con_printf(CON_DEBUG, "cmd_queue_process: processing %s\n", cmd->command_line);
180 cmd_parse(cmd->command_line); // Note, this may change the queue
182 d_free(cmd->command_line);
186 if (cmd_queue_wait > 0) {
188 if (Function_mode == FMODE_GAME) {
189 con_printf(CON_DEBUG, "cmd_queue_process: waiting\n");
198 /* execute until there are no commands left */
199 void cmd_queue_flush(void)
201 while (cmd_queue_process()) {
206 /* Add some commands to the queue to be executed */
207 void cmd_enqueue(int insert, char *input)
209 cmd_queue_t *new, *head, *tail;
210 char output[CMD_MAX_LENGTH];
213 Assert(input != NULL);
220 /* Strip leading spaces */
221 while(isspace(*input) || *input == ';')
224 /* If command is empty, give up */
228 /* Find the end of this line (\n, ;, or nul) */
235 } else if ( *input == '\n' || (!quoted && *input == ';') ) {
239 } while ((*optr++ = *input++));
242 /* make a new queue item, add it to list */
243 MALLOC(new, cmd_queue_t, 1);
244 new->command_line = d_strdup(output);
253 con_printf(CON_DEBUG, "cmd_enqueue: adding %s\n", output);
257 /* add our list to the head of the main list */
259 tail->next = cmd_queue_head;
261 cmd_queue_tail = tail;
263 cmd_queue_head = head;
264 con_printf(CON_DEBUG, "cmd_enqueue: added to front of list\n");
266 /* add our list to the tail of the main list */
268 cmd_queue_head = head;
270 cmd_queue_tail->next = head;
272 cmd_queue_tail = tail;
273 con_printf(CON_DEBUG, "cmd_enqueue: added to back of list\n");
277 void cmd_enqueuef(int insert, const char *fmt, ...)
280 char buf[CMD_MAX_LENGTH];
282 va_start (arglist, fmt);
283 vsnprintf (buf, CMD_MAX_LENGTH, fmt, arglist);
286 cmd_enqueue(insert, buf);
290 /* Attempt to autocomplete an input string */
291 const char *cmd_complete(char *input)
296 int len = (int)strlen(input);
301 for (ptr = cmd_list; ptr != NULL; ptr = ptr->next)
302 if (!strnicmp(input, ptr->name, len))
305 for (aptr = cmd_alias_list; aptr != NULL; aptr = aptr->next)
306 if (!strnicmp(input, aptr->name, len))
309 return cvar_complete(input);
314 void cmd_alias(int argc, char **argv)
317 char buf[CMD_MAX_LENGTH] = "";
321 con_printf(CON_NORMAL, "aliases:\n");
322 for (alias = cmd_alias_list; alias; alias = alias->next)
323 con_printf(CON_NORMAL, "%s: %s\n", alias->name, alias->value);
328 for (alias = cmd_alias_list; alias; alias = alias->next)
329 if (!stricmp(argv[1], alias->name)) {
330 con_printf(CON_NORMAL, "%s: %s\n", alias->name, alias->value);
334 con_printf(CON_NORMAL, "alias: %s not found\n", argv[1]);
338 for (i = 2; i < argc; i++) {
340 strncat(buf, " ", CMD_MAX_LENGTH);
341 strncat(buf, argv[i], CMD_MAX_LENGTH);
344 for (alias = cmd_alias_list; alias; alias = alias->next) {
345 if (!stricmp(argv[1], alias->name)) {
346 d_free(alias->value);
347 alias->value = d_strdup(buf);
352 MALLOC(alias, cmd_alias_t, 1);
353 strncpy(alias->name, argv[1], ALIAS_NAME_MAX);
354 alias->value = d_strdup(buf);
355 alias->next = cmd_alias_list;
356 cmd_alias_list = alias;
361 void cmd_unalias(int argc, char **argv)
363 cmd_alias_t *alias, *prev_alias = NULL;
365 if (argc < 2 || argc > 2) {
366 cmd_insertf("help %s", argv[0]);
370 for (alias = cmd_alias_list; alias ; alias = alias->next) {
371 if (!stricmp(argv[1], alias->name))
377 con_printf(CON_NORMAL, "unalias: %s not found\n", argv[1]);
382 prev_alias->next = alias->next;
384 cmd_alias_list = alias->next;
386 d_free(alias->value);
391 /* echo to console */
392 void cmd_echo(int argc, char **argv)
394 char buf[CMD_MAX_LENGTH] = "";
397 for (i = 1; i < argc; i++) {
399 strncat(buf, " ", CMD_MAX_LENGTH);
400 strncat(buf, argv[i], CMD_MAX_LENGTH);
402 con_printf(CON_NORMAL, "%s\n", buf);
406 void cmd_exec(int argc, char **argv) {
407 cmd_queue_t *new, *head, *tail;
409 char line[CMD_MAX_LENGTH] = "";
411 if (argc < 2 || argc > 2) {
412 cmd_insertf("help %s", argv[0]);
418 f = PHYSFSX_openReadBuffered(argv[1]);
420 con_printf(CON_CRITICAL, "exec: %s not found\n", argv[1]);
423 while (PHYSFSX_gets(f, line)) {
424 /* make a new queue item, add it to list */
425 MALLOC(new, cmd_queue_t, 1);
426 new->command_line = d_strdup(line);
435 con_printf(CON_DEBUG, "cmd_exec: adding %s\n", line);
439 /* add our list to the head of the main list */
441 tail->next = cmd_queue_head;
443 cmd_queue_tail = tail;
445 cmd_queue_head = head;
446 con_printf(CON_DEBUG, "cmd_exec: added to front of list\n");
451 void cmd_help(int argc, char **argv)
456 cmd_insertf("help %s", argv[0]);
461 con_printf(CON_NORMAL, "Available commands:\n");
462 for (cmd = cmd_list; cmd; cmd = cmd->next) {
463 con_printf(CON_NORMAL, " %s\n", cmd->name);
469 for (cmd = cmd_list; cmd != NULL; cmd = cmd->next)
470 if (!stricmp(argv[1], cmd->name))
474 con_printf(CON_URGENT, "Command %s not found\n", argv[1]);
478 if (!cmd->help_text) {
479 con_printf(CON_NORMAL, "%s: no help found\n", argv[1]);
483 con_printf(CON_NORMAL, "%s\n", cmd->help_text);
488 void cmd_wait(int argc, char **argv)
491 cmd_insertf("help %s", argv[0]);
498 cmd_queue_wait = atoi(argv[1]);
505 cmd_alias_t *alias_p;
514 alias_p = cmd_alias_list;
516 cmd_alias_t *temp = alias_p;
517 d_free(alias_p->value);
518 alias_p = alias_p->next;
526 cmd_addcommand("alias", cmd_alias, "alias <name> <commands>\n" " define <name> as an alias for <commands>\n"
527 "alias <name>\n" " show the current definition of <name>\n"
528 "alias\n" " show all defined aliases");
529 cmd_addcommand("unalias", cmd_unalias, "unalias <name>\n" " undefine the alias <name>");
530 cmd_addcommand("echo", cmd_echo, "echo [text]\n" " write <text> to the console");
531 cmd_addcommand("exec", cmd_exec, "exec <file>\n" " execute <file>");
532 cmd_addcommand("help", cmd_help, "help [command]\n" " get help for <command>, or list all commands if not specified.");
533 cmd_addcommand("wait", cmd_wait, "usage: wait [n]\n" " stop processing commands, resume in <n> cycles (default 1)");