#include <exec/types.h>            /* BOOL etc. Type-Definitions     */
#include <dos/dos.h>               /* Definition of RETURN_FAIL etc. */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

/* Konstanten -------------------------------------------------------------------------- */

#define MISSING_BASENAME	1
#define FROM_NOT_LEGAL		2
#define UPTO_NOT_LEGAL		3
#define FROM_TOO_LOW			4
#define UPTO_TOO_LOW			5
#define WRONG_PARAMETERS	6
#define MISSING_ASNAME		7
#define MISSING_WILDCARD  8
/* --------------------- */
#define PARSE_ERROR       8
/* --------------------- */
#define FILE_EXISTS				9
#define NO_MEMORY        10


/* Funktions-Protos -------------------------------------------------------------------- */

BOOL   LetztesFile(int, char *);
char * MakeFileName(int);
void   WrongArgs(char *);
char * CutWildCard(char *);
char * Uppercase(char *);
void   PrintError(int);
BOOL   fileexist(char *);


/* Globale Variablen ------------------------------------------------------------------- */

char * basename;
char * asname = NULL;
const char * wildcard = "*";
int    from = 0;
int    upto = -1;
BOOL   nofrac = FALSE;
BOOL   doublenull = FALSE;
BOOL   quiet = FALSE;
BOOL   force = FALSE;
BOOL   add = FALSE;

/* main -------------------------------------------------------------------------------- */

int main(int ArgC, char * ArgV[])
{
	int    arg = 1;												/* Aktuelle Argumentnummer */
	int    filenr;                        /* Aktuelle Nummer des bearbeiteten Files */
	int    zeichen;                       /* Zeichen-Transfer-Puffer */
	int    WCpos = 0;                     /* Dient zum finden des Wildcards */
	int    baselen = 0;                   /* Länge des Basenames */
	BOOL   ready = FALSE;                 /* Schleifenabbruchs-Boolean */
	BOOL   error = FALSE;                 /* TRUE, falls Joining abgebrochen */
	BOOL   givenasname = FALSE;           /* TRUE, wenn AsName vom Benutzer kommt */
	FILE * Asfp = NULL;                   /* Output-FilePointer */
	FILE * Infp = NULL;                   /* Input-FilePointer */
	char * actualfilename = NULL;         /* Name des aktuellen Files */
	
	/* ------------------------ Parsing ------------------------- */
/*fs*/
	if(1 == ArgC)                        /* keine Parameter ist unzulässig */
	{
		PrintError(MISSING_BASENAME);
		WrongArgs(ArgV[0]);
	}

	/* BaseName-Parameter */
	basename = ArgV[arg];
	arg++;
	baselen = strlen(basename);
	/* WildCard finden, Stelle in WCpos */
	for(WCpos = 0; WCpos <=baselen; WCpos++)
	{
		if(wildcard[0] == basename[WCpos]) break;
	}
	if(WCpos > baselen)
	{
		PrintError(MISSING_WILDCARD);
		WrongArgs(ArgV[0]);
	}

	/* FROM-Parameter */
	if(arg+2 <= ArgC && 0 == strcmp("FROM", Uppercase(ArgV[arg]) ))
	{
		if(!isdigit(ArgV[arg+1][0]) ) 
		{
			PrintError(FROM_NOT_LEGAL);
			WrongArgs(ArgV[0]);
		}
		from = atoi(ArgV[++arg]);
		if(0 > from)
		{
			PrintError(FROM_TOO_LOW);
			WrongArgs(ArgV[0]);
		}
		arg++;
	} 

	/* UPTO-Parameter */
	if(arg+2 <= ArgC && 0 == strcmp("UPTO", Uppercase(ArgV[arg]) ))
	{
		if(!isdigit(ArgV[arg+1][0]) )
		{
			PrintError(UPTO_NOT_LEGAL);
			WrongArgs(ArgV[0]);
		}
		upto = atoi(ArgV[++arg]);
		if(-1 != upto)
		{
			if(upto <= from) 
			{
				PrintError(UPTO_TOO_LOW);
				WrongArgs(ArgV[0]);
			}
		}
		arg++;
	} 
	
	/* ASName-Parameter */
	if(arg+2 <= ArgC && 0 == strcmp("AS", Uppercase(ArgV[arg]) ))
	{
		asname = ArgV[++arg];
		arg++;
	} 

	while(!ready && arg+1 <= ArgC)          /* Abfrage der drei Booleans */
	{
		/* NOFRAC-Parameter */
		if(arg+1 <= ArgC && 0 == strcmp("NOFRAC", Uppercase(ArgV[arg]) ))
		{
			nofrac = TRUE;
			arg++;
		}

		/* NULL-Parameter */
		else if(arg+1 <= ArgC && 0 == strcmp("NULL", Uppercase(ArgV[arg]) ))
		{
			doublenull = TRUE;
			arg++;
		}

		/* QUIET-Parameter */
		else if(arg+1 <= ArgC && 0 == strcmp("QUIET", Uppercase(ArgV[arg]) ))
		{
			quiet = TRUE;
			arg++;
		}

		/* FORCE-Parameter */
		else if(arg+1 <= ArgC && 0 == strcmp("FORCE", Uppercase(ArgV[arg]) ))
		{
			force = TRUE;
			arg++;
		}

		/* ADD-Parameter */
		else if(arg+1 <= ArgC && 0 == strcmp("ADD", Uppercase(ArgV[arg]) ))
		{
			add = TRUE;
			arg++;
		}

		/* Müll-Parameter führt zum Ende */
		else 
		{
			PrintError(WRONG_PARAMETERS);
			ready = TRUE;
		}
	}
	
	if(arg != ArgC) WrongArgs(ArgV[0]);                   /* mind. ein  Parameter ungültig */

	if(0 == strcmp(wildcard, basename) && NULL == asname) /* WildCard-BaseName, aber kein AsName */
	{
		PrintError(MISSING_ASNAME);
		WrongArgs(ArgV[0]);
	}

	if(NULL == asname)
	{
		givenasname = TRUE;
		asname = CutWildCard(basename);    /* Default-AsName ist der Basename ohne WildCard*/
	}
/* --------------------------------------------------------------------------------------- */
/*fe*/

	if(!quiet) printf("\n  MJoin V1.1 by Harald Löffler\n\n");
	
	if(!fileexist(asname) || force)
	{
		filenr = from;
		do
		{
			actualfilename = MakeFileName(filenr);
			if(!quiet) printf("    %s", actualfilename);
			if(fileexist(actualfilename))
			{

				/* hier muß das Joining stattfinden */

				if(add)
				{
					if(!Asfp)	Asfp = fopen(asname, "a");
				}
				else
				{
					if(!Asfp)	Asfp = fopen(asname, "w");
				}

				Infp = fopen(actualfilename, "r");

				while(EOF != (zeichen = getc(Infp)))
				{
					putc(zeichen, Asfp);
				}

				if(Infp) fclose(Infp);

				/* Ende Joining                     */

				if(!quiet) printf("\tJoined\n");
			}
			else
			{
				if(-1 != upto && nofrac) error = TRUE;
				if(!quiet) printf("\tNot found\n");
			}
		
			ready = LetztesFile(filenr, actualfilename);
			free(actualfilename);
			filenr++;
		}
		while(!ready);
	}
	else
	{
		if(!quiet) PrintError(FILE_EXISTS);
		exit(RETURN_WARN);
	}

	/* Am Ende das EOF und Schließen des AsFiles nicht vergessen */
	if(Asfp)	fclose(Asfp);
  if(!givenasname) free(asname);
	if(!quiet) printf("\n");
	if(error)
	{
		if(!quiet) printf("  Joining aborted!\n\n");
		exit(RETURN_WARN);
	}
	else
	{
		exit(RETURN_OK);
	}
}

/* Funktionen -------------------------------------------------------------------------- */

BOOL LetztesFile(int number, char * filename)
/*fs*/
{
	if(nofrac || -1 == upto)
	{
		return((BOOL)!fileexist(filename));
	}
	else
	{
		return((BOOL)!(number < upto));
	}
}
/*fe*/

char * MakeFileName(int number)
/*fs*/
{
	char * str;
  char * frontpart;
  char * rearpart;
  int    WCpos = 0;
	int    nrlen = 1;
	int    baselen = 0;
	int    dummy = 0;
	int    step = 0;

	dummy = number;
	while(dummy > 9)
	{
		dummy /=10;
		nrlen++;
	}

	baselen = strlen(basename);

	/* WildCard finden, Stelle in WCpos */
	for(WCpos = 0; WCpos <=baselen; WCpos++)
	{
		if(wildcard[0] == basename[WCpos]) break;
	}

	frontpart = (char *) malloc(WCpos + 1);
	if(NULL == frontpart)
	{
	  printf("\n  MJoin V1.1 by Harald Löffler\n\n");
		PrintError(NO_MEMORY);
		exit(RETURN_FAIL);
	}

	rearpart = (char *) malloc(baselen - WCpos);
	if(NULL == rearpart)
	{
	  printf("\n  MJoin V1.1 by Harald Löffler\n\n");
		PrintError(NO_MEMORY);
		exit(RETURN_FAIL);
	}

	if(doublenull && number < 10) nrlen++;

	str = (char *)malloc(baselen + nrlen + 1);
	if(NULL == str)
	{
	  printf("\n  MJoin V1.1 by Harald Löffler\n\n");
		PrintError(NO_MEMORY);
		exit(RETURN_FAIL);
	}

	/* frontpart kopieren */
	for(step = 0; step < WCpos; step++)
	{
		frontpart[step] = basename[step];
	}
  frontpart[WCpos] = NULL;
	
	/* rearpart kopieren */
	for(step = WCpos+1; step < baselen; step++)
	{
		rearpart[step-WCpos-1] = basename[step];
	}
  rearpart[baselen-WCpos-1] = NULL;	

	if(doublenull && number < 10)
	{
		sprintf(str, "%s0%i%s", frontpart, number, rearpart);
	}
	else
	{
		sprintf(str, "%s%i%s", frontpart, number, rearpart);
	}
  free(rearpart);
  free(frontpart);
	return(str);
}
/*fe*/

void WrongArgs(char * progname)
/*fs*/
{
	printf("\nUSAGE: %s <basename>\t[FROM start] [UPTO end] [AS newname]\n\t\t\t[NOFRAC|NULL|QUIET|FORCE|ADD]\n\n", progname);
	exit(RETURN_WARN);
}
/*fe*/

char * CutWildCard(char *name)
/*fs*/
{
	char * retname = NULL;
	int i = 0;
	int j = 0;
	
	retname = (char *) malloc(strlen(name) + 1);
	if(NULL == retname)
	{
	  printf("\n  MJoin V1.1 by Harald Löffler\n\n");
		PrintError(NO_MEMORY);
		exit(RETURN_FAIL);
	}
	

	for(i=0, j=0 ; i < strlen(name); i++)
	{
		if(wildcard[0] != name[i])
			retname[j++] = name[i];	
	}
	retname[j] = NULL;
	return(retname);
}
/*fe*/

char * Uppercase(char * str)
/*fs*/
{
	int i = -1;
	while(str[++i] != NULL) str[i] = toupper(str[i]);
	return(str);
}
/*fe*/

void PrintError(int error)
/*fs*/
{
	if(error <= PARSE_ERROR && !quiet)
	  printf("\n  MJoin V1.1 by Harald Löffler\n");
	if(!(error > PARSE_ERROR && quiet))
	{
		switch(error)
		{
			case MISSING_BASENAME:
				printf("\n  I need at least a basename!\n");
				break;
			case FROM_NOT_LEGAL:
				printf("\n  FROM-Value is not a legal number.\n");			
				break;
			case UPTO_NOT_LEGAL:
				printf("\n  FROM-Value is not a legal number.\n");
				break;
			case FROM_TOO_LOW:
				printf("\n  FROM-Value must be greater then zero.\n");
				break;
			case UPTO_TOO_LOW:
				printf("\n  UPTO-Value must be greater then FROM-Value.\n");
				break;
			case WRONG_PARAMETERS:
				printf("\n  One or more wrong Parameter(s)!\n");
				break;
			case MISSING_ASNAME:
				printf("\n  I need an AsName!\n");
				break;
			case MISSING_WILDCARD:
				printf("\n  Where is the wildcard? :-|\n");
				break;
			case FILE_EXISTS:
				printf("  AsName allready exists. Use FORCE to overwrite.\n\n");
				break;
			case NO_MEMORY:
			  printf("  Cannot allocate new memory. Abort.\n\n");
			  break;
		}
	}
}
/*fe*/

BOOL fileexist(char * file)
/*fs*/
{
	FILE * fp = NULL;
	BOOL   ret = FALSE;

	fp = fopen(file,"r");

	if(NULL == fp)
	{
		ret = FALSE;
	}
	else
	{
		ret = TRUE;
	}

	if(fp) fclose(fp);
	return(ret);
}
/*fe*/
