#include #include #include #include "cmd.h" #include "mem.h" #include "q2defines.h" static int cmd_argc = 0; static char *cmd_argv[MAX_STRING_TOKENS]; static char *cmd_args = NULL; #define ISSPACE(x) ((x) == ' ' || (x) == '\t') void Cmd_ResetArgs() { while (cmd_argc) { cmd_argc--; Z_Free(cmd_argv[cmd_argc]); cmd_argv[cmd_argc] = NULL; } if (cmd_args) { Z_Free(cmd_args); cmd_args = NULL; } } void Cmd_SetArg(int arg, const char *s) { if ( (unsigned)arg >= MAX_STRING_TOKENS) return; if ( (unsigned)arg >= (unsigned)cmd_argc) cmd_argc = arg + 1; if (cmd_argv[arg]) Z_Free(cmd_argv[arg]); cmd_argv[arg] = Z_Strdup(s); } void Cmd_AddArg(const char *s) { assert(cmd_argv[cmd_argc] == NULL); cmd_argv[cmd_argc] = Z_Strdup(s); cmd_argc++; } int Cmd_Argc() { return cmd_argc; } const char *Cmd_Argv(int arg) { if ((unsigned)arg >= (unsigned)cmd_argc) return ""; return cmd_argv[arg]; } const char *Cmd_Args() { if (cmd_args) return cmd_args; return ""; } const char *Cmd_TokenizeString(const char *s) { const char *start, *arg1; Cmd_ResetArgs(); arg1 = NULL; for (cmd_argc = 0; ; cmd_argc++) { // skip leading whitespace while (ISSPACE(*s)) s++; // reached the end of the command? if (!*s || *s == '\n' || *s == ';' || cmd_argc >= MAX_STRING_TOKENS) { if (arg1) { cmd_args = Z_Malloc(s - arg1 + 1); memcpy(cmd_args, arg1, s - arg1); cmd_args[s - arg1] = 0; } if (*s) return s + 1; else return NULL; } if (cmd_argc == 1) arg1 = s; // handle quoted strings specially if (*s == '\"') { s++; start = s; while (*s != '\"') { if (!*s || *s == '\n') { Cmd_ResetArgs(); return NULL; } s++; } cmd_argv[cmd_argc] = Z_Malloc(s - start + 1); memcpy(cmd_argv[cmd_argc], start, s - start); cmd_argv[cmd_argc][s - start] = 0; s++; } else if (s[0] == '/' && s[1] == '/') { while (*s && *s != '\n') s++; } else { start = s; while (*s && !ISSPACE(*s) && *s != '\n' && *s != ';') s++; cmd_argv[cmd_argc] = Z_Malloc(s - start + 1); memcpy(cmd_argv[cmd_argc], start, s - start); cmd_argv[cmd_argc][s - start] = 0; } } } // Cmd_AddText // adds command(s) to the end of the commandstring void Cmd_AddText(char **commandstring, const char *s) { char *temp; size_t len; if (!s) return; len = strlen(s); if (*commandstring) len += strlen(*commandstring); temp = Z_Malloc(len + 1); if (*commandstring) { strcpy(temp, *commandstring); Z_Free(*commandstring); strcat(temp, s); } else strcpy(temp, s); *commandstring = temp; } // Cmd_InsertText // adds command(s) to the beginning of the commandstring void Cmd_InsertText(char **commandstring, const char *s) { char *temp; size_t len; if (!s) return; len = strlen(s); if (*commandstring) len += strlen(*commandstring); temp = Z_Malloc(len + 1); strcpy(temp, s); if (*commandstring) { strcat(temp, *commandstring); Z_Free(*commandstring); } *commandstring = temp; } int Cmd_RunCommands(char **commandstring, qboolean (*Execute)()) { const char *s; if (!*commandstring) return 0; for (;;) { s = Cmd_TokenizeString(*commandstring); if (s) { memmove(*commandstring, s, strlen(s)+1); } else { Z_Free(*commandstring); *commandstring = NULL; } if (!Execute()) break; if (!*commandstring) break; } return 0; } void Cmd_ParseCommandLine(int argc, char *const *argv, qboolean (*Execute)()) { int i; i = 1; while (i < argc) { if (!argv[i] || argv[i][0] != '+') { i++; continue; } Cmd_ResetArgs(); Cmd_AddArg(argv[i++] + 1); while (i < argc) { if (!argv[i] || argv[i][0] == '+') break; Cmd_AddArg(argv[i++]); } Execute(); } }