355 lines · 6.1 KB · C
RawDownload
#include "quakedef.h" static bool cmd_wait;static sizebuf_t cmd_text;static int cmd_argc;static char *cmd_argv[80];static const char *cmd_args = nil; cmd_source_t cmd_source; /* * Causes execution of the remainder of the command buffer to be delayed until * next frame.  This allows commands like: * bind g "impulse 5 ; +attack ; wait ; -attack ; impulse 2" */static voidCmd_Wait_f(cmd_t *c){	USED(c);	cmd_wait = true;} voidCbuf_Init(void){	SZ_Alloc(&cmd_text, 65536); // space for commands and script files} /* Adds command text at the end of the buffer */voidCbuf_AddText(const char *text){	int l; 	l = strlen(text); 	if(cmd_text.cursize + l >= cmd_text.maxsize) {		Con_Printf("Cbuf_AddText: overflow\n");		return;	} 	SZ_Write(&cmd_text, text, strlen(text));} /* * Adds command text immediately after the current command * Adds a \n to the text * FIXME: actually change the command buffer to do less copying */voidCbuf_InsertText(const char *text){	char *temp = nil;	int templen; 	// copy off any commands still remaining in the exec buffer	templen = cmd_text.cursize;	if(templen) {		temp = Z_Malloc(templen);		memmove(temp, cmd_text.data, templen);		SZ_Clear(&cmd_text);	} 	// add the entire text of the file	Cbuf_AddText(text); 	// add the copied off data	if(templen) {		SZ_Write(&cmd_text, temp, templen);		Z_Free(temp);	}} voidCbuf_Execute(void){	int i, quotes;	char *text, line[1024]; 	while(cmd_text.cursize) {		// find a \n or ; line break		text = (char *)cmd_text.data; 		quotes = 0;		for(i = 0; i < cmd_text.cursize; i++) {			if(text[i] == '"')				quotes++;			if(!(quotes & 1) && text[i] == ';')				break; // don't break if inside a quoted string			if(text[i] == '\n')				break;		} 		memmove(line, text, i);		line[i] = 0; 		// delete the text from the command buffer and move remaining commands down		// this is necessary because commands (exec, alias) can insert data at the		// beginning of the text buffer 		if(i == cmd_text.cursize)			cmd_text.cursize = 0;		else {			i++;			cmd_text.cursize -= i;			memmove(text, text + i, cmd_text.cursize);		} 		// execute the command line		Cmd_ExecuteString(line, src_command); 		if(cmd_wait) { // skip out while text still remains in buffer, leaving it			// for next frame			cmd_wait = false;			break;		}	}} static voidCmd_Exec_f(cmd_t *c){	char *f;	void *mark; 	USED(c);	if(Cmd_Argc() != 2) {		Con_Printf("exec <filename> : execute a script file\n");		return;	} 	mark = Hunk_Mark();	f = loadhunklmp(Cmd_Argv(1), nil);	if(f == nil) {		Con_Printf("exec: %s\n", lerr());		return;	}	Con_Printf("execing %s\n", Cmd_Argv(1)); 	Cbuf_InsertText(f);	Hunk_FreeToMark(mark);} static voidCmd_Echo_f(cmd_t *c){	int i; 	USED(c);	for(i = 1; i < Cmd_Argc(); i++)		Con_Printf("%s ", Cmd_Argv(i));	Con_Printf("\n");} static char *CopyString(const char *in){	char *out; 	out = Z_Malloc(strlen(in) + 1);	strcpy(out, in);	return out;} static voidCmd_AliasList(const char *name, void *v, void *aux){	cmd_t *a; 	USED(aux);	a = v;	if(iscmd(a) && a->alias != nil)		Con_Printf("  %s : %s\n", name, a->alias);} static voidCmd_ExecAlias_f(cmd_t *a){	Cbuf_InsertText(a->alias);} static voidCmd_Alias_f(cmd_t *t){	const char *s;	char cmd[1024];	cmd_t *a;	int i, c; 	USED(t);	if(Cmd_Argc() == 1) {		Con_Printf("Current alias commands:\n");		Con_SearchObject("", 0, Cmd_AliasList, nil);		return;	} 	s = Cmd_Argv(1);	if(strlen(Cmd_Args()) - strlen(s) >= sizeof(cmd)) {		Con_Printf("Alias commands are too long\n");		return;	} 	if((a = Con_FindObject(s)) != nil) {		if(!iscmd(a) || a->alias == nil) {			Con_Printf("Can't register alias %s, already defined\n", s);			return;		}		Z_Free(a->alias);	} 	if(a == nil)		a = Cmd_AddCommand(CopyString(s), Cmd_ExecAlias_f); 	// copy the rest of the command line	cmd[0] = 0; // start out with a null string	c = Cmd_Argc();	for(i = 2; i < c; i++) {		strcat(cmd, Cmd_Argv(i));		if(i != c)			strcat(cmd, " ");	}	strcat(cmd, "\n"); 	a->alias = CopyString(cmd);} voidCmd_Init(void){	Cmd_AddCommand("exec", Cmd_Exec_f);	Cmd_AddCommand("echo", Cmd_Echo_f);	Cmd_AddCommand("alias", Cmd_Alias_f);	Cmd_AddCommand("cmd", Cmd_ForwardToServer);	Cmd_AddCommand("wait", Cmd_Wait_f);} intCmd_Argc(void){	return cmd_argc;} const char *Cmd_Argv(int arg){	if(arg >= cmd_argc)		return "";	return cmd_argv[arg];} const char *Cmd_Args(void){	return cmd_args;} static voidCmd_TokenizeString(const char *s){	int i; 	// clear the args from the last string	for(i = 0; i < cmd_argc; i++) {		Z_Free(cmd_argv[i]);		cmd_argv[i] = nil;	} 	cmd_argc = 0;	cmd_args = nil; 	while(1) {		// skip whitespace up to a /n		while(*s != 0 && *s <= ' ' && *s != '\n')			s++; 		if(*s == '\n') // a newline seperates commands in the buffer			return; 		if(*s == 0)			return; 		if(cmd_argc == 1)			cmd_args = s; 		s = COM_Parse(s);		if(!s)			return; 		if(cmd_argc < nelem(cmd_argv)) {			cmd_argv[cmd_argc] = Z_Malloc(strlen(com_token) + 1);			strcpy(cmd_argv[cmd_argc], com_token);			cmd_argc++;		}	}} cmd_t *Cmd_AddCommand(char *name, cmdfun_t f){	cmd_t *cmd; 	if(Con_FindObject(name) != nil) {		Con_Printf("Cmd_AddCommand: %s already defined\n", name);		return nil;	} 	cmd = Z_Malloc(sizeof(*cmd));	cmd->name = name;	cmd->f = f;	Con_AddObject(name, cmd);	return cmd;} voidCmd_ExecuteString(const char *text, cmd_source_t src){	cmd_t *cmd; 	cmd_source = src;	Cmd_TokenizeString(text); 	// execute the command line	if(!Cmd_Argc())		return; // no tokens 	cmd = Con_FindObject(cmd_argv[0]);	if(cmd != nil && iscmd(cmd)) {		cmd->f(cmd);		return;	} 	// check cvars	if(!Cvar_Command())		Con_Printf("Unknown command \"%s\": %s\n", Cmd_Argv(0), text);} voidCmd_ForwardToServer(cmd_t *c){	USED(c);	if(cls.state != ca_connected) {		Con_Printf("Can't \"%s\", not connected\n", Cmd_Argv(0));		return;	} 	if(cls.demoplayback)		return; // not really connected 	MSG_WriteByte(&cls.message, clc_stringcmd);	if(cistrcmp(Cmd_Argv(0), "cmd") != 0) {		SZ_Print(&cls.message, Cmd_Argv(0));		SZ_Print(&cls.message, " ");	}	SZ_Print(&cls.message, Cmd_Argc() > 1 ? Cmd_Args() : "\n");}

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t