/*	mark saeger,	msaeger@cse.unl.edu				*/
/*	memory.c							*/
/*	Copyright 1995 Mark Saeger.					*/
/*									*/
/*	Permission is granted to any individual or instituition to use,	*/
/*	copy, or redistribute this executable so long as it is not	*/
/*	modified and that it is not sold for profit.			*/
/*									*/
/*	LIKE ANYTHING THAT IS FREE, MORE IS PROVIDED AS IS AND COMES	*/
/*	WITH NO	WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED.	*/
/*	IN NO EVENT WILL THE COPYRIGHT HOLDER BE LIABLE FOR ANY DAMAGES	*/
/*	RESULTING FROM THE USE OF THIS SOFTWARE.			*/
#include "more.h"

#define HIT 20	/*this many hits and we have a duplicate*/

rgx *newr(void)
{
	rgx *temp;

	if((temp=(rgx *)malloc(sizeof(rgx)))==NULL)
	{
		fprintf(stderr,"Out of MEMORY...abort\n");
		exit(-1);
	}
	temp->link=NULL;
	return(temp);
}

void destroy_globrgx(void)
{
	extern rgx *globrgx;
	rgx *p, *tmp;

	if(globrgx!=NULL)
		for(p=globrgx;p!=NULL;p=tmp)	/*walk the list*/
		{
			tmp=p->link;
			free(p);	/*free memory*/
		}
}

node *newn(void)
{
	node *temp;

	if((temp=(node *)malloc(sizeof(node)))==NULL)
	{
		fprintf(stderr,"Out of MEMORY...abort\n");
		exit(-1);
	}
	temp->link=NULL;

	return(temp);
}

rgx *fillrother(rgx *grgx, char **loptreg)
{
	rgx *walk;
	rgx *prev;

	if(grgx != NULL)
	{
		for(walk=grgx;walk->link != NULL;walk=walk->link);
		walk->link=newr();
		prev=walk;	/*save it for later*/
		walk=walk->link;
	}
	else
	{
		grgx=newr();
		walk=grgx;
		prev=NULL;
	}
	walk->rdata[0]='\0';
	switch(**loptreg)
	{
		case '.':
			walk->type=RGXDOT;
			(*loptreg)++;
			break;
		case '*':
			walk->type=RGXSTAR;
			(*loptreg)++;
			break;
		case '^':
			if(!prev)	/*should be NULL since must be first*/
/*only do this when it is first position*/
				walk->type=RGXBOL;
			(*loptreg)++;	/*move around the ^ */
			break;
		case '$':
			walk->type=RGXEOL;
			(*loptreg)++;
			break;
		case '\\':
			(*loptreg)++;	/* get character after slash*/
			switch(**loptreg)
			{
				case '<':	/*beg of word*/
					walk->type=RGXBOW;
					break;
				case '>':	/*end of word*/
					walk->type=RGXEOW;
					break;
				default:
					walk->type=RGXCHAR;
					walk->rdata[0]=(**loptreg);
/*	didnt do NULL below		walk->rdata[1]='\0';*/
					break;					
			}
			(*loptreg)++;
			break;
		case '[':
			{
				int xz=0, negflag=FALSE;

				(*loptreg)++;	/*get ^ else 1st char*/
topr:
				walk->type=-1;
				while(**loptreg!=']')
				{
					switch(**loptreg)
					{
						case '^':
							negflag=TRUE;
							break;
						case '-':
							if(negflag)
								walk->type=RGXNRNG;
							else
								walk->type=RGXRNG;
							(*loptreg)++;
				/*no break, just fall through*/
						default:
							walk->rdata[xz++]=(**loptreg);
							break;
					}
					(*loptreg)++;	/*next char*/
					walk->rdata[xz]='\0';	/*keep adding NULL*/
					if(((walk->type==RGXRNG)||(walk->type==RGXNRNG)) && (**loptreg!=']'))
					{
						walk->link=newr();
						prev=walk;
						walk=walk->link;
						xz=0;
						goto topr;
					}
				}
				if(walk->type==-1)
					if(negflag)
						walk->type=RGXNVAL;
					else
						walk->type=RGXVAL;
				(*loptreg)++;	/*around the ]*/
			}
			break;
		default:
			break;
	}
	return(grgx);
}

rgx *fillr(rgx *grgx,char r_d)
{
	rgx *walk;

	if(grgx != NULL)
	{
		for(walk=grgx;walk->link != NULL;walk=walk->link);

		walk->link=newr();
		walk=walk->link;
		walk->type=RGXCHAR;
		walk->rdata[0]=r_d;
	}
	else
	{
		grgx=newr();
		grgx->type=RGXCHAR;
		grgx->rdata[0]=r_d;
	}
	return(grgx);
}
node *fill(node *llist,node *bufferstdin,int max_to_read,unsigned char bigbuf[])
{
	int x;
	node *walk;

	if(llist != NULL)
	{
		for(walk=llist;walk->link != NULL;walk=walk->link)
			walk->dirty=FALSE;
		walk->dirty=FALSE;
		walk->link=bufferstdin;
		bufferstdin->position=(walk->position)+1;
	}
	else
	{
		llist=bufferstdin;	/*first node*/
		bufferstdin->position=1;
	}

	bufferstdin->size=max_to_read;
	for(x=0;x<max_to_read;x++)
		bufferstdin->nbuf[x]=bigbuf[x];
	bufferstdin->link=NULL;
	bufferstdin->dirty=TRUE;	/*still set dirty*/
	return(llist);
}

int findprev(node *llist, unsigned char bigbuf[], int *max_to_read)
{
	node *walk;
	node *prev=NULL;
	int foundit=FALSE;
	int x;
	int never=TRUE;

	prev=llist;	/*set to first node*/
	for(walk=llist;walk!=NULL;walk=walk->link)
	{
		if(walk->dirty==TRUE)
		{
			walk->dirty=FALSE;
			foundit=TRUE;
		}
		if(!foundit)
		{
			never=FALSE;
			prev=walk;
		}
	}
	for(x=0;x<prev->size;x++)
		bigbuf[x]=prev->nbuf[x];
	*max_to_read=prev->size;
	prev->dirty=TRUE;	/*set flag*/
	return(never);
}
