/* wild.c - wildcard routines */

#include "copyright.h"

#include "config.h"
#include "db.h"
#include "mudconf.h"
#include "externs.h"

int wild1(char *tstr, char *dstr, int arg, char *args[], int nargs)
{
char	*copy;
int	startarg, i;

	copy = NULL;
	startarg = arg;
	while (*tstr) {
		switch (*tstr) {
		case '\\':
			/* Escape character: Treat the next character as
			 * a literal char to match, not a potential
			 * wildcard.
			 */

			tstr++;
			if (*tstr) {
				if (ToLower(*dstr) != ToLower(*tstr)) {
					for (i=startarg; i<nargs; i++) {
						if (args[i] != NULL)
							free_lbuf(args[i]);
						args[i] = NULL;
					}
					return 0;
				}
				dstr++;
				tstr++;
			}
			break;
		case '?':
			/* Single character match.
			 * If at end of data, return FALSE.
			 * Otherwise, match the character.
			 */

			if (!*dstr) {
				for (i=startarg; i<nargs; i++) {
					if (args[i] != NULL)
						free_lbuf(args[i]);
					args[i] = NULL;
				}
				return 0;
			}
			if (arg < nargs) {
				if (args[arg] == NULL)
					args[arg] = alloc_lbuf("wild1.?");
				args[arg][0] = *dstr;
				args[arg][1] = '\0';
				arg++;
			}
			tstr++;
			dstr++;
			break;
		case '*':
			/* Multi-character match
			 * If what follows matches, return success
			 * If we are at the end of the data string,
			 *    return failure
			 * Otherwise, move a character and retry
			 */
			if (wild1(tstr+1, dstr, arg+1, args, nargs)) {
				if (copy != NULL)
					*copy = '\0';
				return 1;
			}
			if (!*dstr) {
				for (i=startarg; i<nargs; i++) {
					if (args[i] != NULL)
						free_lbuf(args[i]);
					args[i] = NULL;
				}
				return 0;
			}
			if ((copy == NULL) && (arg < nargs)) {
				if (args[arg] == NULL)
					args[arg] = alloc_lbuf("wild1.*");
				copy = args[arg];
			}
			if (copy != NULL) *copy++ = *dstr;
			dstr++;
			break;
		default:
			if (ToLower(*dstr) != ToLower(*tstr)) {
				for (i=startarg; i<nargs; i++) {
					if (args[i] != NULL)
						free_lbuf(args[i]);
					args[i] = NULL;
				}
				return 0;
			}
			dstr++;
			tstr++;
		}
	}
	if (*dstr) {
		for (i=startarg; i<nargs; i++) {
			if (args[i] != NULL)
				free_lbuf(args[i]);
			args[i] = NULL;
		}
		return 0;
	}
	return 1;
}

int wild(char *tstr, char *dstr, char *args[], int nargs)
{
int	i;

	for (i=0; i<nargs; i++) args[i] = NULL;
	return wild1(tstr, dstr, 0, args, nargs);
}

int quick_wild(char *s, char *d)
{
	while (*s) {	
		switch(*s) {
		case '?':
			if (!*d) return 0;
			s++; d++;
			break;
		case '*':
			if (quick_wild(s+1,d)) return 1;
			if (!*d) return 0;
			d++;
			break;
		default:
			if (ToLower(*s) != ToLower(*d)) return 0;
			s++; d++;
		}
	}
	if (*d) return 0;
	return 1;
}

int wild_match(char *tstr, char *dstr, char *args[], int nargs)
{
int	i;

	switch (*tstr) {
	case '>':
		for  (i=0; i<nargs; i++) args[i] = NULL;
		tstr++;
		if (isdigit(*tstr) || (*tstr == '-'))
			return (atoi(tstr) < atoi(dstr));
		else
			return (strcmp(tstr, dstr) < 0);
	case '<':
		for  (i=0; i<nargs; i++) args[i] = NULL;
		tstr++;
		if (isdigit(*tstr) || (*tstr == '-'))
			return (atoi(tstr) > atoi(dstr));
		else
			return (strcmp(tstr, dstr) > 0);
	default:
		if (nargs == 0)
			return quick_wild(tstr, dstr);
		else
			return wild(tstr, dstr, args, nargs);
	}
}