/* $Id: commands.c 295 2005-12-16 19:44:24Z tsaviran $
 * -------------------------------------------------------
 * Copyright (C) 2003-2005 Tommi Saviranta <wnd@iki.fi>
 *	(C) 2002 Lee Hardy <lee@leeh.co.uk>
 * -------------------------------------------------------
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 */

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif /* ifdef HAVE_CONFIG_H */

#include "commands.h"
#include "common.h"



static struct commandhash *cmd_hash[MAX_CMD];
static int command_hash(const char *p);
void command_add(const char *p, int cmdvalue);



/* The struct for the command hash table. */
struct commandhash {
	const char		*cmd;
	int			cmdvalue;
	struct commandhash	*next;
};



/* The struct for the table below. */
struct commandaddstruct {
	char	*cmd;
	int	mask;
};



/*
 * The table of commands that we need to add at startup, and their relevant
 * bitmasks, as defined in commands.h.
 */
static struct commandaddstruct cmd_add_table[] =
{
	/* command,		bitmask,	*/
	{"PING",		CMD_PING,	},
	{"PONG",		CMD_PONG,	},
	{"MODE",		CMD_MODE,	},
	{"NICK",		CMD_NICK,	},
	{"NOTICE",		CMD_NOTICE,	},
	{"KICK",		CMD_KICK,	},
	{"JOIN",		CMD_JOIN,	},
	{"PART",		CMD_PART,	},
	{"TOPIC",		CMD_TOPIC,	},
	{"KILL",		CMD_KILL,	},
	{"PRIVMSG",		CMD_PRIVMSG,	},
	{"QUIT",		CMD_QUIT,	},
	{NULL,			CMD_NONE,	}
};



/*
 * Hashes a command to a value.
 */
static int
command_hash(const char *p)
{
	int	hash_val = 0;

	while (*p) {
		hash_val += ((int) (*p) & 0xDF);
		p++;
	}

	return (hash_val % MAX_CMD);
} /* static int command_hash(const char *p) */



/*
 * Searches for a command in the command hash table.
 */
int
command_find(char *p)
{
	struct commandhash	*ptr;
	int			cmdindex;
	
	cmdindex = command_hash(p);
	
	for (ptr = cmd_hash[cmdindex]; ptr; ptr = ptr->next) {
		if (xstrcasecmp(p, ptr->cmd) == 0) {
			return ptr->cmdvalue;
		}
	}

	return 0;
} /* int command_find(char *p) */



/*
 * Adds a command to the command hash table.
 */
void
command_add(const char *cmd, int cmdvalue)
{
	struct commandhash	*ptr;
	struct commandhash	*temp_ptr;
	struct commandhash	*last_ptr = NULL;
	int			cmdindex;

	cmdindex = command_hash(cmd);

	/* command exists */
	for (temp_ptr = cmd_hash[cmdindex]; temp_ptr;
			temp_ptr = temp_ptr->next) {
		if (xstrcasecmp(cmd, temp_ptr->cmd) == 0) {
			return;
		}

		last_ptr = temp_ptr;
	}

	ptr = (struct commandhash *) xcalloc(1, sizeof(struct commandhash));

	ptr->cmd = cmd;
	ptr->cmdvalue = cmdvalue;

	if (last_ptr) {
		last_ptr->next = ptr;
	} else {
		cmd_hash[cmdindex] = ptr;
	}
} /* void command_add(const char *cmd, int cmdvalue) */



/*
 * Walks the commandsadd table and adds all the entries.
 */
void
command_setup(void)
{
	int	i;

	for (i = 0; i < MAX_CMD; i++) {
		cmd_hash[i] = NULL;
	}
	
	for (i = 0; cmd_add_table[i].cmd; i++) {
		command_add(cmd_add_table[i].cmd, cmd_add_table[i].mask);
	}
} /* void command_setup(void) */



/*
 * Free memore allocated by command-hash.
 */
void
command_free(void)
{
	int	i;
	struct commandhash	*ptr;
	struct commandhash	*next = NULL;

	for (i = 0; i < MAX_CMD; i++) {
		for (ptr = cmd_hash[i]; ptr != NULL; ptr = next) {
			next = ptr->next;
			xfree(ptr);
		}
	}
} /* void command_free(void) */


syntax highlighted by Code2HTML, v. 0.9.1