#ifdef DEMO
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#ifdef  __STDC__
#define x      x
#else
#define x      ()
#endif
#else
#include "global.h"
#include "commands.h"
#include "hardware.h"
#ifndef MSDOS
#include "proc.h"
#endif
#endif

#ifdef __MSDOS__
#undef MSDOS
#define MSDOS 1
#endif

#if !defined(_lint)
static char rcsid[] OPTIONAL = "$Id: sort.c,v 1.19 1997/07/31 00:44:20 root Exp $";
#endif

#define ENDING ((size_t) -1)

int expired;

struct entries {
	char *name;
	long theindex;
	size_t nextindex;
};

void sortit (const char *fname,int entrysize, int searchsize, int strsize,time_t age);

static struct entries *e = ((struct entries *)0);
static int count;
static size_t current;
static char name[16];
static int result, same;
static size_t theindex;
static long currentindex;
static int sortdups = 0, wassorted = 0;
static size_t sorthead;
static size_t lastindex;

static struct entries *temp = (struct entries *) 0;
static struct entries *temp2 = (struct entries *) 0;


static void search (void);
static void insert (void);
static void makesortname (char *buf, const char *origname);


static void
search ()
{
	same = 0;
	lastindex = ENDING;
	for (theindex = sorthead; theindex != ENDING; theindex = e[theindex].nextindex)		{
		result = strnicmp (name, e[theindex].name, strlen(name));
		if (!result)	{
			same = 1;
			sortdups++;
			return;
		}
		if (result < 0)
			return;
		lastindex = theindex;
	}
	return;
}


static void
insert ()
{
	temp = &e[current];
	if (lastindex == ENDING)	{	/* at head of list */
		temp->nextindex = sorthead;
		sorthead = current;
	} else 	{	/* in the midst or tail of file */
		temp2 = &e[lastindex];
		if (theindex)		/* in midst of list */
			temp->nextindex = temp2->nextindex;
		temp2->nextindex = current;
		if (!wassorted && !same && !theindex)
			wassorted = 1;
	}

	strcpy (temp->name, name);
#ifdef DEMO
	if (count)	{
		if (temp->nextindex == ENDING)
			printf ("inserting last record %s\n", temp->name);
		else	{
			temp2 = &e[e[current].nextindex];
			printf ("inserting - %s -> %s\n", temp->name, temp2->name);
		}
	} else
		printf ("inserting 1st record %s\n", temp->name);
#endif
	if (!same)
		temp->theindex = currentindex;
	else
		temp->theindex = -1;
	current++;
	count++;
}


static void
makesortname (buf, origname)
char *buf;
const char *origname;
{
char *cp;

	strcpy (buf, origname);
	cp = strchr (buf, '.');
	if (!cp)
		cp = &buf[strlen(buf)];
	strcpy (cp, ".srt");
}


void
sortit (fname, entrysize, searchsize, strsize, date)
const char *fname;
int entrysize, searchsize, strsize;
time_t date;
{
char *cp;
unsigned k;
FILE *fp, *out;
char buf[128];
long size0, size;
#if 0
int num;
#endif
time_t now, stamptime;
int newnum = 0;

#ifdef DEMO
	printf ("Filename: '%s', Entrysize=%d, Searchsize=%d\n", fname, entrysize, searchsize);
#endif
	if ((fp = fopen (fname, "rt")) == 0)	{
#ifdef DEMO
		printf ("can't open input file: %s\n", fname);
#endif
		return;
	}
	makesortname (buf, fname);
	if ((out = fopen (buf, "wt")) == 0)	{
#ifdef DEMO
		printf ("can't open output file: %s\n", buf);
#endif
		(void) fclose (fp);
		return;
	}
	size0 = (long) filelength(fileno(fp));
	size = size0 / (long) entrysize;
	size += 1;
#ifdef DEMO
	printf ("File length = %ld\n", size0);
	printf ("%ld Entries found - Allocating structure...\n", size - 1);
#else
	log(-1,"Sort '%s' - %ld Entries originally", fname, size - 1);
#endif
	e = (struct entries *) mallocw ((unsigned)((unsigned long)size * sizeof(struct entries)));
	for (current = 0; current < (size_t) size; current++)	{
		e[current].name = (char *)mallocw ((unsigned)(searchsize + 1));
		e[current].name[0] = 0;
		e[current].nextindex = ENDING;
		e[current].theindex = -1;
		kwait (NULL);
	}

	sorthead = ENDING;
	current = count = 0;
	expired = sortdups = wassorted = 0;
	now = time(&now);
	while (!feof (fp))	{
		kwait (NULL);
		currentindex = ftell(fp);
		if ((long)current == size)
			break;
		(void) fgets (buf, entrysize, fp);
#ifdef DEMO
		printf ("Reading Entry %d/%d - ", current, count);
#endif
		if (feof (fp))	{
#ifdef DEMO
			putchar ('\n');
#endif
			continue;
		}
		kwait (NULL);
		if (*buf > ' ' && ((int) strlen(buf) > (entrysize - 2)) && (*buf != '#'))	{
			strncpy (name, buf, (unsigned)searchsize);
			name[searchsize] = 0;
			if ((cp = strpbrk (name, ".@ \t")) != 0)
				*cp = 0;
			search();
			kwait (NULL);
			insert ();
			kwait (NULL);
		} else	{	/* skip it! */
#ifdef DEMO
			putchar ('\n');
#endif
			current++;
			count++;
			continue;
		}
		/* now check for expired date stamp, if used */
		if (date)	{
			cp = strchr (buf, ' ');
			if (!cp)	{
				stamptime = 0;
			} else {
				cp = skipwhite (cp);
				stamptime = atol(cp);
			}
			if ((stamptime == 0) || (now - stamptime >= date))	{
#ifdef DEMO
				printf ("Expiring: now=%ld, age=%ld, stamptime=%ld\n", now, date, stamptime);
#endif
				expired++;
				e[current].theindex = -2;
			}
		}
	}
#ifdef DEMO
	putchar ('\n');
#endif
	(void) fflush (stdout);
	if (expired || wassorted || sortdups)		{
		for (theindex = sorthead,k=0; k < (unsigned)count && theindex != ENDING; k++,theindex = temp->nextindex)	{
			temp = &e[theindex];
			if (temp->theindex >= 0)	{
#ifdef DEMO
				printf ("Outputing record %d/%d\n", k, count);
#endif
				kwait (NULL);
				fseek (fp, (long) temp->theindex, 0);
				(void) fgets (buf, entrysize, fp);

				if (strsize)	{
					/* we now re-format it, just in case it is bad */
					if ((cp = strpbrk (buf, " \t")) == 0)	{
#ifdef DEMO
						printf ("Skipping malformed entry,,,,\n");
#endif
						continue;
					}
					*cp++ = 0;
					cp = skipwhite (cp);
					stamptime = atol(cp);
					buf[strsize] = 0;	/* just in case */
					cp = buf;
					while (*cp)	{
						if (*cp & 0x80)	{
							*cp = 0;
							break;
						}
						cp++;
					}
					if (stamptime && *buf)
				                fprintf(out,"%-*s %-14ld\n",strsize,buf,stamptime);
			        } else
					fputs (buf, out);
				newnum++;
			}
#ifdef DEMO
			else 	{
				if (temp->theindex == -2)
					printf ("Expiring record %d/%d\n", k, count);
				else printf ("Skipping record %d/%d\n", k, count);
			}
#endif
			
		}
	}
#ifndef DEMO
	log(-1,"Sort '%s' - %d Entries at end", fname, newnum);
#else
	printf ("Sort '%s' - %d Entries at end\n", fname, newnum);
#endif	
	(void) fclose (fp);
	(void) fclose (out);
	for (current = 0; (long)current < size; current++)
		free(e[current].name);
	if (e != ((struct entries *)0))	{
		free (e);
		e = ((struct entries *)0);
	}

	makesortname (buf, fname);
	if (expired || wassorted || sortdups)	{
		(void) remove (fname);
		(void) rename (buf, fname);
	} else
		(void) remove (buf);
}



#ifdef DEMO
#define ENTRYSIZE 49

int
kwait (i)
int i;
{
	return i;
}


char *
skipwhite (cp)
char *cp;
{
	while (*cp && (*cp == ' ' || *cp == '\t'))
		cp++;
	return (cp);
}


void
main (argc, argv)
int argc;
char *argv[];
{
unsigned long begincore;

	begincore = coreleft();
	if (argc == 1)
		sortit ("c:/nos/spool/wpagebbs", ENTRYSIZE, 6, 32, (time_t)0);
	else
		sortit (argv[1], atoi (argv[2]), atoi(argv[3]), atoi(argv[2]) - 17, (time_t) 0);
	printf ("\nBeginning coreleft was %ld - Now is %ld\n", begincore, (long) coreleft());
	if (!wassorted && !sortdups)
		printf ("File was already sorted with no duplicates...\nNo further action needed\n");
	else if (sortdups)
		printf ("%d duplicates removed\n", sortdups);
}
#endif
