19 cmd_handler_t function;
23 /* The list of cmds */
24 static cmd_t *cmd_list = NULL;
27 #define ALIAS_NAME_MAX 32
28 typedef struct cmd_alias_s
30 char name[ALIAS_NAME_MAX];
32 struct cmd_alias_s *next;
35 /* The list of aliases */
36 static cmd_alias_t *cmd_alias_list = NULL;
39 /* add a new console command */
40 void cmd_addcommand(char *cmd_name, cmd_handler_t cmd_func)
44 Assert(cmd_name != NULL);
46 for (cmd = cmd_list; cmd; cmd = cmd->next) {
47 if (!stricmp(cmd_name, cmd->name))
50 con_printf(CON_NORMAL, "command %s already exists, not adding\n", cmd_name);
55 /* create command, insert at front of list */
56 MALLOC(cmd, cmd_t, 1);
58 cmd->function = cmd_func;
60 con_printf(CON_DEBUG, "cmd_addcommand: added %s\n", cmd->name);
65 typedef struct cmd_queue_s
68 struct cmd_queue_s *next;
71 /* The list of commands to be executed */
72 static cmd_queue_t *cmd_queue_head = NULL;
73 static cmd_queue_t *cmd_queue_tail = NULL;
76 void cvar_cmd_set(int argc, char **argv);
79 /* execute a parsed command */
80 void cmd_execute(int argc, char **argv)
85 for (cmd = cmd_list; cmd; cmd = cmd->next) {
86 if (!stricmp(argv[0], cmd->name)) {
87 con_printf(CON_DEBUG, "cmd_execute: executing %s\n", argv[0]);
88 cmd->function(argc, argv);
93 for (alias = cmd_alias_list; alias; alias = alias->next) {
94 if (!stricmp(argv[0], alias->name)) {
95 con_printf(CON_DEBUG, "cmd_execute: pushing alias \"%s\": %s\n", alias->name, alias->value);
96 cmd_insert(alias->value);
102 { // set value of cvar
103 char *new_argv[argc+1];
107 for (i = 0; i < argc; i++)
108 new_argv[i+1] = argv[i];
109 cvar_cmd_set(argc + 1, new_argv);
114 /* Parse an input string */
115 void cmd_parse(char *input)
117 char buffer[CMD_MAX_LENGTH];
118 char *tokens[CMD_MAX_TOKENS];
122 Assert(input != NULL);
124 /* Strip leading spaces */
125 for (i=0; isspace(input[i]); i++) ;
126 strncpy( buffer, &input[i], CMD_MAX_LENGTH );
128 //printf("lead strip \"%s\"\n",buffer);
129 l = (int)strlen(buffer);
130 /* If command is empty, give up */
133 /* Strip trailing spaces */
134 for (i=l-1; i>0 && isspace(buffer[i]); i--) ;
136 //printf("trail strip \"%s\"\n",buffer);
138 /* Split into tokens */
139 l = (int)strlen(buffer);
143 for (i=1; i<l; i++) {
144 if (buffer[i] == '"') {
145 tokens[num_tokens - 1] = &buffer[++i];
146 while (i < l && buffer[i] != '"')
151 if (isspace(buffer[i]) || buffer[i] == '=') {
153 while (isspace(buffer[i+1]) && (i+1 < l)) i++;
154 tokens[num_tokens++] = &buffer[i+1];
158 /* Check for matching commands */
159 cmd_execute(num_tokens, tokens);
163 int cmd_queue_wait = 0;
165 int cmd_queue_process(void)
169 while (!cmd_queue_wait && cmd_queue_head) {
170 cmd = cmd_queue_head;
171 cmd_queue_head = cmd_queue_head->next;
173 cmd_queue_tail = NULL;
175 con_printf(CON_DEBUG, "cmd_queue_process: processing %s\n", cmd->command_line);
176 cmd_parse(cmd->command_line); // Note, this may change the queue
178 d_free(cmd->command_line);
182 if (cmd_queue_wait > 0) {
184 if (Function_mode == FMODE_GAME) {
185 con_printf(CON_DEBUG, "cmd_queue_process: waiting\n");
194 /* execute until there are no commands left */
195 void cmd_queue_flush(void)
197 while (cmd_queue_process()) {
202 /* Add some commands to the queue to be executed */
203 void cmd_enqueue(int insert, char *input)
205 cmd_queue_t *new, *head, *tail;
206 char output[CMD_MAX_LENGTH];
209 Assert(input != NULL);
216 /* Strip leading spaces */
217 while(isspace(*input) || *input == ';')
220 /* If command is empty, give up */
224 /* Find the end of this line (\n, ;, or nul) */
231 } else if ( *input == '\n' || (!quoted && *input == ';') ) {
235 } while ((*optr++ = *input++));
238 /* make a new queue item, add it to list */
239 MALLOC(new, cmd_queue_t, 1);
240 new->command_line = d_strdup(output);
249 con_printf(CON_DEBUG, "cmd_enqueue: adding %s\n", output);
253 /* add our list to the head of the main list */
255 tail->next = cmd_queue_head;
257 cmd_queue_tail = tail;
259 cmd_queue_head = head;
260 con_printf(CON_DEBUG, "cmd_enqueue: added to front of list\n");
262 /* add our list to the tail of the main list */
264 cmd_queue_head = head;
266 cmd_queue_tail->next = head;
268 cmd_queue_tail = tail;
269 con_printf(CON_DEBUG, "cmd_enqueue: added to back of list\n");
273 void cmd_enqueuef(int insert, char *fmt, ...)
276 char buf[CMD_MAX_LENGTH];
278 va_start (arglist, fmt);
279 vsnprintf (buf, CMD_MAX_LENGTH, fmt, arglist);
282 cmd_enqueue(insert, buf);
286 /* Attempt to autocomplete an input string */
287 char *cmd_complete(char *input)
292 int len = (int)strlen(input);
297 for (ptr = cmd_list; ptr != NULL; ptr = ptr->next)
298 if (!strnicmp(input, ptr->name, len))
301 for (aptr = cmd_alias_list; aptr != NULL; aptr = aptr->next)
302 if (!strnicmp(input, aptr->name, len))
305 return cvar_complete(input);
310 void cmd_alias(int argc, char **argv)
313 char buf[CMD_MAX_LENGTH] = "";
316 if (argc == 2 && !stricmp(argv[1], "-h")) {
317 con_printf(CON_NORMAL, "%s <name> <commands>\n", argv[0]);
318 con_printf(CON_NORMAL, " define <name> as an alias for <commands>\n");
319 con_printf(CON_NORMAL, "%s <name>\n", argv[0]);
320 con_printf(CON_NORMAL, " show the current definition of <name>\n");
321 con_printf(CON_NORMAL, "%s\n", argv[0]);
322 con_printf(CON_NORMAL, " show all defined aliases\n");
327 con_printf(CON_NORMAL, "aliases:\n");
328 for (alias = cmd_alias_list; alias; alias = alias->next)
329 con_printf(CON_NORMAL, "%s: %s\n", alias->name, alias->value);
334 for (alias = cmd_alias_list; alias; alias = alias->next)
335 if (!stricmp(argv[1], alias->name)) {
336 con_printf(CON_NORMAL, "%s: %s\n", alias->name, alias->value);
340 con_printf(CON_NORMAL, "alias: %s not found\n", argv[1]);
344 for (i = 2; i < argc; i++) {
346 strncat(buf, " ", CMD_MAX_LENGTH);
347 strncat(buf, argv[i], CMD_MAX_LENGTH);
350 for (alias = cmd_alias_list; alias; alias = alias->next) {
351 if (!stricmp(argv[1], alias->name)) {
352 d_free(alias->value);
353 alias->value = d_strdup(buf);
358 MALLOC(alias, cmd_alias_t, 1);
359 strncpy(alias->name, argv[1], ALIAS_NAME_MAX);
360 alias->value = d_strdup(buf);
361 alias->next = cmd_alias_list;
362 cmd_alias_list = alias;
367 void cmd_unalias(int argc, char **argv)
369 cmd_alias_t *alias, *prev_alias = NULL;
371 if (argc != 2 || (argc == 2 && !stricmp(argv[1], "-h"))) {
372 con_printf(CON_NORMAL, "%s <name>\n", argv[0]);
373 con_printf(CON_NORMAL, " undefine the alias <name>\n");
377 for (alias = cmd_alias_list; alias ; alias = alias->next) {
378 if (!stricmp(argv[1], alias->name))
384 con_printf(CON_NORMAL, "alias: %s not found\n", argv[1]);
389 prev_alias->next = alias->next;
391 cmd_alias_list = alias->next;
393 d_free(alias->value);
398 /* echo to console */
399 void cmd_echo(int argc, char **argv)
401 char buf[CMD_MAX_LENGTH] = "";
404 if (argc == 2 && !stricmp(argv[1], "-h")) {
405 con_printf(CON_NORMAL, "usage: %s [text]\n", argv[0]);
406 con_printf(CON_NORMAL, " write <text> to the console\n");
411 for (i = 1; i < argc; i++) {
413 strncat(buf, " ", CMD_MAX_LENGTH);
414 strncat(buf, argv[i], CMD_MAX_LENGTH);
416 con_printf(CON_NORMAL, "%s\n", buf);
420 void cmd_exec(int argc, char **argv) {
421 cmd_queue_t *new, *head, *tail;
423 char line[CMD_MAX_LENGTH] = "";
425 if (argc != 2 || (argc == 2 && !stricmp(argv[1], "-h"))) {
426 con_printf(CON_NORMAL, "usage: %s <file>\n", argv[0]);
427 con_printf(CON_NORMAL, " execute <file>\n");
434 f = PHYSFSX_openReadBuffered(argv[1]);
436 con_printf(CON_CRITICAL, "exec: %s not found\n", argv[1]);
439 while (PHYSFSX_gets(f, line)) {
440 /* make a new queue item, add it to list */
441 MALLOC(new, cmd_queue_t, 1);
442 new->command_line = d_strdup(line);
451 con_printf(CON_DEBUG, "cmd_exec: adding %s\n", line);
455 /* add our list to the head of the main list */
457 tail->next = cmd_queue_head;
459 cmd_queue_tail = tail;
461 cmd_queue_head = head;
462 con_printf(CON_DEBUG, "cmd_exec: added to front of list\n");
467 void cmd_help(int argc, char **argv)
471 if (argc > 2 || (argc == 2 && !stricmp(argv[1], "-h"))) {
472 con_printf(CON_NORMAL, "usage: %s [command]\n", argv[0]);
473 con_printf(CON_NORMAL, " get help for <command>, or list all commands if not specified.\n");
479 con_printf(CON_NORMAL, "Available commands:\n");
480 for (cmd = cmd_list; cmd; cmd = cmd->next) {
481 con_printf(CON_NORMAL, " %s\n", cmd->name);
487 cmd_insertf("%s -h", argv[1]);
492 void cmd_wait(int argc, char **argv)
494 if (argc > 2 || (argc == 2 && !stricmp(argv[1], "-h"))) {
495 con_printf(CON_NORMAL, "usage: %s [n]\n", argv[0]);
496 con_printf(CON_NORMAL, " stop processing commands, resume in <n> cycles (default 1)\n");
504 cmd_queue_wait = atoi(argv[1]);
515 p = ((cmd_t *)p)->next;
521 d_free(((cmd_alias_t *)p)->value);
523 p = ((cmd_alias_t *)p)->next;
531 cmd_addcommand("alias", cmd_alias);
532 cmd_addcommand("unalias", cmd_unalias);
533 cmd_addcommand("echo", cmd_echo);
534 cmd_addcommand("exec", cmd_exec);
535 cmd_addcommand("help", cmd_help);
536 cmd_addcommand("wait", cmd_wait);