1 /*
2 Copyright (C) 1997-2001 Id Software, Inc.
3 
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8 
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12 
13 See the GNU General Public License for more details.
14 
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 */
19 
20 //
21 // alias.c
22 //
23 
24 #include "common.h"
25 
26 #define MAX_ALIAS_HASH	32
27 
28 aliasCmd_t	*com_aliasList;
29 aliasCmd_t	*com_aliasHashTree[MAX_ALIAS_HASH];
30 
31 int			com_aliasCount;
32 
33 /*
34 =============================================================================
35 
36 	ALIASES
37 
38 =============================================================================
39 */
40 
41 /*
42 ============
43 Alias_Exists
44 ============
45 */
Alias_Exists(char * aliasName)46 aliasCmd_t *Alias_Exists (char *aliasName)
47 {
48 	aliasCmd_t	*alias;
49 	uint32		hash;
50 
51 	if (!aliasName)
52 		return NULL;
53 
54 	hash = Com_HashGeneric (aliasName, MAX_ALIAS_HASH);
55 	for (alias=com_aliasHashTree[hash] ; alias ; alias=alias->hashNext) {
56 		if (!Q_stricmp (aliasName, alias->name))
57 			return alias;
58 	}
59 
60 	return NULL;
61 }
62 
63 
64 /*
65 ============
66 Alias_CallBack
67 ============
68 */
Alias_CallBack(void (* callBack)(const char * name))69 void Alias_CallBack (void (*callBack) (const char *name))
70 {
71 	aliasCmd_t	*alias;
72 
73 	for (alias=com_aliasList ; alias ; alias=alias->next)
74 		callBack (alias->name);
75 }
76 
77 
78 /*
79 ============
80 Alias_AddAlias
81 ============
82 */
Alias_AddAlias(char * aliasName)83 static void Alias_AddAlias (char *aliasName)
84 {
85 	aliasCmd_t	*alias;
86 	char		cmd[2048];
87 	int			i, c;
88 
89 	// Check if it's already a command
90 	if (Cmd_Exists (aliasName)) {
91 		Com_Printf (PRNT_WARNING, "Alias_AddAlias: \"%s\" already defined as a command\n", aliasName);
92 		return;
93 	}
94 
95 	// Check if it's already a cvar
96 	if (Cvar_Exists (aliasName)) {
97 		Com_Printf (PRNT_WARNING, "Alias_AddAlias: \"%s\" already defined as a cvar\n", aliasName);
98 		return;
99 	}
100 
101 	// Check name length
102 	if (strlen(aliasName)+1 >= MAX_ALIAS_NAME) {
103 		Com_Printf (PRNT_WARNING, "Alias_AddAlias: name \"%s\" too long\n", aliasName);
104 		return;
105 	}
106 
107 	// See if it's actually getting a value
108 	if (Cmd_Argc () < 3) {
109 		Com_Printf (PRNT_WARNING, "Alias_AddAlias: no commands for \"%s\" alias\n", aliasName);
110 		return;
111 	}
112 
113 	// If the alias already exists, reuse it
114 	alias = Alias_Exists (aliasName);
115 	if (alias) {
116 		Mem_Free (alias->value);
117 	}
118 	else {
119 		alias = Mem_PoolAlloc (sizeof (aliasCmd_t), com_aliasSysPool, 0);
120 		alias->hashValue = Com_HashGeneric (aliasName, MAX_ALIAS_HASH);
121 
122 		// Link it in
123 		alias->next = com_aliasList;
124 		com_aliasList = alias;
125 
126 		// Link it into the hash tree
127 		alias->hashNext = com_aliasHashTree[alias->hashValue];
128 		com_aliasHashTree[alias->hashValue] = alias;
129 	}
130 	Q_strncpyz (alias->name, aliasName, sizeof (alias->name));
131 
132 	// Copy the rest of the command line
133 	cmd[0] = 0;		// Start out with a null string
134 	c = Cmd_Argc ();
135 	for (i=2 ; i<c ; i++) {
136 		Q_strcatz (cmd, Cmd_Argv (i), sizeof (cmd));
137 		if (i != (c - 1))
138 			Q_strcatz (cmd, " ", sizeof (cmd));
139 	}
140 	Q_strcatz (cmd, "\n", sizeof (cmd));
141 
142 	alias->value = Mem_PoolStrDup (cmd, com_aliasSysPool, 0);
143 }
144 
145 
146 /*
147 ============
148 Alias_RemoveAlias
149 ============
150 */
Alias_RemoveAlias(char * aliasName)151 void Alias_RemoveAlias (char *aliasName)
152 {
153 	aliasCmd_t	*alias, **prev;
154 
155 	if (!aliasName || !aliasName[0]) {
156 		Com_Printf (PRNT_WARNING, "Alias_RemoveAlias: NULL aliasName\n");
157 		return;
158 	}
159 
160 	// de-link it from alias list
161 	prev = &com_aliasList;
162 	for ( ; ; ) {
163 		alias = *prev;
164 		if (!alias) {
165 			Com_Printf (PRNT_WARNING, "Alias_RemoveAlias: %s not added\n", aliasName);
166 			return;
167 		}
168 
169 		if (!Q_stricmp (aliasName, alias->name)) {
170 			*prev = alias->next;
171 			break;
172 		}
173 		prev = &alias->next;
174 	}
175 
176 	// de-link it from hash list
177 	prev = &com_aliasHashTree[alias->hashValue];
178 	for ( ; ; ) {
179 		alias = *prev;
180 		if (!alias) {
181 			Com_Printf (PRNT_WARNING, "Alias_RemoveAlias: %s not added to hash list\n", aliasName);
182 			return;
183 		}
184 
185 		if (!Q_stricmp (aliasName, alias->name)) {
186 			*prev = alias->hashNext;
187 			if (alias->value)
188 				Mem_Free (alias->value);
189 			Mem_Free (alias);
190 			return;
191 		}
192 		prev = &alias->hashNext;
193 	}
194 }
195 
196 /*
197 ==============================================================================
198 
199 	CONSOLE COMMANDS
200 
201 ==============================================================================
202 */
203 
204 /*
205 ===============
206 Cmd_Alias_f
207 
208 Creates a new command that executes a command string (possibly ; seperated)
209 ===============
210 */
Cmd_Alias_f(void)211 static void Cmd_Alias_f (void)
212 {
213 	if (Cmd_Argc () == 1) {
214 		Com_Printf (0, "syntax: alias <name> <value>; 'aliaslist' to see a list\n");
215 		return;
216 	}
217 
218 	Alias_AddAlias (Cmd_Argv (1));
219 }
220 
221 
222 /*
223 ===============
224 Cmd_Unalias_f
225 
226 Kills an alias
227 ===============
228 */
Cmd_Unalias_f(void)229 static void Cmd_Unalias_f (void)
230 {
231 	if (Cmd_Argc () != 2) {
232 		Com_Printf (0, "syntax: unalias <name>; 'aliaslist' to see a list\n");
233 		return;
234 	}
235 
236 	Alias_RemoveAlias (Cmd_Argv (1));
237 }
238 
239 
240 /*
241 ============
242 Cmd_AliasList_f
243 ============
244 */
alphaSortCmp(const void * _a,const void * _b)245 static int alphaSortCmp (const void *_a, const void *_b) {
246 	const aliasCmd_t *a = (const aliasCmd_t *) _a;
247 	const aliasCmd_t *b = (const aliasCmd_t *) _b;
248 
249 	return Q_stricmp (a->name, b->name);
250 }
Cmd_AliasList_f(void)251 static void Cmd_AliasList_f (void)
252 {
253 	aliasCmd_t	*alias, *sortedList;
254 	int			i, j;
255 	int			matching;
256 	int			longest;
257 	int			total;
258 	char		*wildCard;
259 
260 	if ((Cmd_Argc () != 1) && (Cmd_Argc () != 2)) {
261 		Com_Printf (0, "usage: aliaslist [wildcard]\n");
262 		return;
263 	}
264 
265 	if (Cmd_Argc () == 2)
266 		wildCard = Cmd_Argv (1);
267 	else
268 		wildCard = "*";
269 
270 	// create a list
271 	for (matching=0, total=0, alias=com_aliasList ; alias ; alias=alias->next, total++) {
272 		if (!Q_WildcardMatch (wildCard, alias->name, 1))
273 			continue;
274 		matching++;
275 	}
276 
277 	if (!matching) {
278 		Com_Printf (0, "%i aliases total, %i matching\n", total, matching);
279 		return;
280 	}
281 
282 	sortedList = Mem_PoolAlloc (matching * sizeof (aliasCmd_t), com_aliasSysPool, 0);
283 	for (matching=0, longest=0, alias=com_aliasList ; alias ; alias=alias->next) {
284 		if (!Q_WildcardMatch (wildCard, alias->name, 1))
285 			continue;
286 
287 		if ((int)strlen (alias->name) > longest)
288 			longest = strlen (alias->name);
289 
290 		sortedList[matching++] = *alias;
291 	}
292 
293 	// sort it
294 	qsort (sortedList, matching, sizeof (sortedList[0]), alphaSortCmp);
295 
296 	// print it
297 	longest++;
298 	for (i=0 ; i<matching ;  i++) {
299 		alias = &sortedList[i];
300 
301 		Com_Printf (0, alias->name);
302 		for (j=0 ; j<longest-(int)strlen(alias->name) ; j++)
303 			Com_Printf (0, " ");
304 		Com_Printf (0, "\"%s\"\n", alias->value);
305 	}
306 
307 	if (matching)
308 		Mem_Free (sortedList);
309 	Com_Printf (0, "%i aliases total, %i matching\n", total, matching);
310 }
311 
312 /*
313 =============================================================================
314 
315 	INITIALIZATION
316 
317 =============================================================================
318 */
319 
320 /*
321 ============
322 Alias_Init
323 ============
324 */
Alias_Init(void)325 void Alias_Init (void)
326 {
327 	memset (com_aliasHashTree, 0, sizeof (com_aliasHashTree));
328 
329 	Cmd_AddCommand ("alias",		Cmd_Alias_f,		"Adds an alias command");
330 	Cmd_AddCommand ("unalias",		Cmd_Unalias_f,		"Removes an alias command");
331 	Cmd_AddCommand ("aliaslist",	Cmd_AliasList_f,	"Prints out a list of alias commands");
332 }
333