/*

  This is a part of the Project Frontier's Source code.

  Copyright (C) 1997-98 Francis Gastellu
                    aka Lone Runner/Aegis

  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.

  You should have received a copy of the GNU General Public License
  along with this program; if not, write to the Free Software
  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

*/
/*

Boyer-moore search

*/

#include "string.h"
#include "conio.h"
#include "alloc.h"
#include "mem.h"
#include "..\com\system.h"
#include "..\lang\boymoor.h"

#define BM_AND 0
#define BM_OR 1

char far bmS[255]="";
char far bmW[25][25]={"","","","","","","","","","","","","","","","","","","","","","","","",""};
int bmCase=0;

// ---------------------------------------------------------------------------
int boyerMoore_search(char *b)
{
char word[80];
int state[50];
int depth=0;
int zapLevel[50];
int oper[50];
int not[50];
int value;
char *p, *res;

strcpy(tmpStr, bmS);
state[depth] = -1;
memset(&state, 255, sizeof(int)*50);
memset(&oper, BM_AND, sizeof(int)*50);
memset(&zapLevel, 0, sizeof(int)*50);
memset(&not, 0, sizeof(int)*50);

while (tokCount(bmS))
	{
    getToken(word, bmS);
    if (word[1] == 0)
    	{
        switch (*word)
        	{
            case '&':
            	if (state[depth] == -1)
					{strcpy(bmS, tmpStr);
                	return 0; }
            	if (!state[depth])
                	zapLevel[depth] = 1;
                oper[depth] = BM_AND;
            	break;
            case '|':
            	if (state[depth] == -1)
					{strcpy(bmS, tmpStr);
                	return 0; }
                oper[depth] = BM_OR;
                break;
            case '!':
                if (!tokCount(bmS))
					{strcpy(bmS, tmpStr);
                	return 0; }
                else
                    not[depth] = 1;
                break;
            case '(':
                if (depth == 49)
					{strcpy(bmS, tmpStr);
                	return 0; }
                else
	            	depth++;
                break;
            case ')':
            	if (depth == 0)
					{strcpy(bmS, tmpStr);
                	return 0; }
                else
                	{
                    if (state[depth] == -1) state[depth] = 1;
                	depth--;
                    if (state[depth+1] == 0)
                    	value = not[depth] ? 1 : 0;
                    else
	                    value = not[depth] ? 0 : 1;
		            if (state[depth] != -1 && oper[depth] == BM_OR)
		              	{
						state[depth] |= value;
		                oper[depth] = BM_AND;
		                }
		            else
		            	state[depth] &= value;
                    }
            default:
            	goto chkwrd; // BEURK!
            }
        }
    else
    	chkwrd:
    	if (!zapLevel[depth])
			{
            res = bmCase ? strstr(b, word) : stristr(b, word);
		    if (res)
            	{
                value = not[depth] ? 0 : 1;
//	            if (!not[depth] && wCount < 25) strncpy(bmW[wCount++], word, 25);
                }
            else
            	value = not[depth] ? 1 : 0;
            if (state[depth] != -1 && oper[depth] == BM_OR)
              	{
				state[depth] |= value;
                oper[depth] = BM_AND;
                }
            else
            	state[depth] &= value;
            }
    }

strcpy(bmS, tmpStr);
return state[0] != -1 ? state[0] : 0;
}

// ---------------------------------------------------------------------------
void boyerMoore_init(char *s, int caseSens)
{
int a;
char x[2]=".";
int wCount=0;

*tmpStr=0;
*tmpStr2=0;

bmCase = caseSens;

for (a=0;a<25;a++)
	*bmW[a] = 0;

for (a=0;s[a] && a < 255;a++)
	{
    switch (s[a])
    	{
        case '&':
        case '!':
        case '|':
        case '(':
        case ')':
        	while (a && s[a-1] == ' ') { strcpy(&s[a-1], &s[a]); a--; tmpStr[strlen(tmpStr)-1] = 0; }
        	strcat(tmpStr, "\001");
            *x = s[a];
            strcat(tmpStr, x);
        	strcat(tmpStr, "\001");
            while (s[a+1] == ' ') strcpy(&s[a], &s[a+1]);
            break;
        default:
            *x = s[a];
            strcat(tmpStr, x);
            break;
        }
    }
Ctokenize(tmpStr, '\001', bmS);
while (tokCount(bmS))
	{
    getToken(tmpStr2, bmS);
    switch (*tmpStr2)
    	{
        case '&':
        case '!':
        case '|':
        case '(':
        case ')':
        	break;
        default:
        	if (wCount == 24) break;
        	strnzcpy(bmW[wCount++], tmpStr2, 24);
            break;
        }
    }
Ctokenize(tmpStr, '\001', bmS);
}

// ---------------------------------------------------------------------------
void boyerMoore_reset(void)
{
int a;

bmCase = 0;
for (a=0;a<25;a++)
	*bmW[a] = 0;
*bmS=0;
}

