/****************************************************************************
*
*	Copyright (C) 2001 Steffi Gebauer-Jung
*				  Max-Planck-Institute of Chemical Ecology
*				  Jena, Germany															
*                 All rights reserved.
*
* Language:     ANSI C
*
* Description:  Module to translate MUMmer output files or sim output files into an gff formatted output.
*				
*				MUMmer files
*				============
*					prefix.gaps 		resp.
*					prefix.errorsgaps   resp.
*                   prefix.align
*
*				ATTENTION:
*				- gff output contains always strand "+:+",
*					  even if MUMmer output file contains header "> .. reverse Consistent matches"
*					  because these files do not contain the length of the given (reverse complemented) sequence,
*					  so it is not possible to retrieve the positions on forward strand
*					  BE SURE TO USE OUTPUT FILES resulting from such files only together with the reverse complemented original sequence!  	
*				- there will be no seqbounds line as the same cause as above
*
* 				
*				sim input files
*               ===============
*				 	first 	#:lav: forward strand
*					second 	#:lav: reverse complemented strand
*					third:  error
*				  	normal a-block:
*								a {
*								  s 258
*								  b 1297 1302
*								  e 1329 1333
* 								  l 1297 1302 1303 1308 100
* 								  l 1305 1309 1329 1333 100
* 								}
*				  	a-block with identical alignment of full sequence (to skip with given option -i):
*								a {
*								  s 27000					score = length * sim-parameter M (look for it within d-block)
*								  b 1 1
*								  e 2700 2700
* 								  l 1 1 2700 2700 100
* 								}
*				  	or:
*								a {
*								  s 0
*								  b 1 1
*								  e 2700 2700
*								  f 0						f-line
* 								  l 1 1 2700 2700           l-line without score-value
* 								}
*				gff files
*				=========
* 				identical alignment of full sequence (to skip with given option -i):
*						   - is followed by a fragment of length of at least (length - 4)	
*							 (on head and tail at most 2 bases which do not belong to a complete triplett - tblastx looks on each frame separately)
*
* $Id: ali2gff.c,v 1.3 2001/09/26 16:01:50 steffi Exp $
*
****************************************************************************/
#include "ali2gff.h"
#include "time.h"

#define DEBUG 0

static char prgCall[MAXSTRING];								/*----- program call					-----*/	
static char infile[MAXSTRING];								/*----- name of the input file 			-----*/
static char outfile[MAXSTRING];								/*----- name of the output file 		-----*/
static int opt_x, opt_y, opt_f;								/*----- argument line options on/off 	-----*/
static int opt_r = 0;										
static int opt_t = 0;										
static int opt_i = 0;										
static char frameChar = '.';								/*----- frame to put in output 			-----*/
static char xName[MAXSTRING] = "SEQ1";						/*----- species name for species 1 		-----*/
static char yName[MAXSTRING] = "SEQ2";						/*----- species name for species 2 		-----*/
static FILE *stdoutCopy;
static long int counta = 0;
static float nmp;
static float avlen;


/*----------------------------- Implementation ----------------------------*/
int main(int argc,  char *argv[]) {

	char *ptr;
	
	start_time();
	
	/*----- standard command line parsing ---------------------------------*/
	strcpy(prgCall,argv[0]);
	if (argc < 2) printUsage();
	
	while (argv[1][0] == '-') {
		switch (argv[1][1]) {
			case 't':
				opt_t = 1;
				if (strcmp(argv[1],"-t")) printUsage();
				argc--;
				argv++;
				if ((sscanf(argv[1],"%c",&frameChar) < 1) || ((frameChar != '0') && (frameChar != '1') && (frameChar != '2') && (frameChar != '.'))) printUsage();
				break;
			case 'x':
				opt_x = 1;
				if (strcmp(argv[1],"-x")) printUsage();
				argc--;
				argv++;
				if (sscanf(argv[1],"%s",xName) < 1) printUsage();
				ptr = xName;
				break;
			case 'y':
				opt_y = 1;
				if (strcmp(argv[1],"-y")) printUsage();
				argc--;
				argv++;
				if (sscanf(argv[1],"%s",yName) < 1) printUsage();
				ptr = yName;
				break;
			case 'r': opt_r = 1; break;
			case 'i': opt_i = 1; break;
			case 'f': opt_f = 1; break;
			case 'h': printUsage(); break;
			default:  printUsage(); break;
		}
		argc--;	/* count of left arguments */
		argv++;	/* move the pointer to the right */
	}
	if (argc > 2) printUsage();
	strcpy(infile,argv[1]);

	/*----- choose output channel ----*/
	if (opt_f) {
		/*
		fileptr = strrchr(infile,'/');
		if (fileptr == NULL)
		*/	
			strcpy(outfile,infile);
		/*
		else strcpy(outfile,++fileptr);
		*/
		strcat(outfile,".gff");
		if (!(stdoutCopy = fopen(outfile, "w"))) {fprintf(stderr,"Error: Unable to write file %s\n",outfile); exit(4);}	
	}
	else stdoutCopy = stdout;

	doit();
	
	if (DEBUG) print_time();
	return 0;
}



/****************************************************************************
*
* Function:     doit
*
* Parameters:	---   
*
* Returns:		---			      
*
* Description:  decide between MUMmer output file, sim output file and gff file
*
****************************************************************************/
void doit() {

	FILE *alifile;

	char line[MAXSTRING];							/*----- read line 		-----*/
	char *ptr;										/*----- pointer to line -----*/
	
	
	/*----- open alignment file -----*/
	if ((alifile = fopen(infile, "r")) == NULL) {fprintf(stderr,"Error: Unable to input file %s\n",infile);exit(2);}	
	
	/*----- read first line to decide whether it is a SIM -----*/
	if ((ptr = fgets(line,sizeof(line),alifile)) == NULL) wrongFormatError(infile);
	
 	/* input file sim formatted */
 	if (strstr(line,"#:lav") == ptr) {
 		processSimfile();
 	}	
	/* input file in MUMmer output format */
	else if (strstr(line,"Consistent matches")) {
		processMumfile();
	}
	/* input file already gff formatted */
	else { 	
		if (!strcmp(xName,"SEQ1")) {
			while (((ptr = fgets(line,sizeof(line),alifile)) != NULL) && *ptr == '#');
			if (sscanf(line,"%[^: \t\n\r]:%[^: \t\n\r]", xName,yName) < 2) wrongFormatError(infile);
		}
		if (fclose(alifile)) fprintf(stderr,"Error: Unable to close file %s\n%s\n",infile,line);
		processGFFfile();
	}
	
	return;
}



/****************************************************************************
*
* Function:     processGFFfile
*
* Parameters:	---
*
* Returns:     	---
*
* Description:  read alignment data from gff file
*
****************************************************************************/
void processGFFfile() {

	FILE *GFFfile;

	char line[MAXSTRING];							/*----- read line 		-----*/
	char *ptr;										/*----- pointer to line -----*/
	char *cptr;										// pointer to comment
	char waste[MAXSTRING];
	char waste2[MAXSTRING];
	
	char feature[MAXSTRING];
	char source[MAXSTRING] = "GFF";
	
	unsigned long int xb, xe, yb, ye;
	unsigned long int xseqLen_4 = LONG_MAX;
	unsigned long int yseqLen_4 = LONG_MAX;
	
	float score;
	char scores[MAXSTRING];
	
	char strand1;
	char strand2;
	
	char strands[4];

	char frameChar1;								
	char frameChar2;
	
	char frames[4];
	
	time_t now;
	char nowString[100];
	
	unsigned short int aliPrinted = 1;
	char aliPrintString[MAXSTRING];
	
		
	
	/*----- open alignment file -----*/
	GFFfile = fopen(infile, "r");
	if (GFFfile == NULL) {fprintf(stderr,"Error: Unable to input file %s\n%s\n",infile,line);exit(2);}	
	
	fprintf (stdoutCopy,"##gff-version 2\n");
	fprintf (stdoutCopy,"##source-version %s\n",prgCall);

	now = time(NULL);
	strftime(nowString,100,"%b/%d/%Y %X",localtime(&now));
	fprintf (stdoutCopy,"##date %s\n##\n##%s ",nowString,prgCall);
	if (opt_r) fprintf (stdoutCopy," -r");
	if (opt_t) fprintf (stdoutCopy," -t %c",frameChar);
	fprintf (stdoutCopy," -x %s -y %s",xName,yName);
	if (opt_i) fprintf (stdoutCopy," -i");
	if (opt_f) fprintf (stdoutCopy," -f");
	fprintf (stdoutCopy," %s\n#name1:name2\t\tsource\t\tfeature\t\tbeg1:beg2\tend1:end2\tscore\tstrand\tframe\tgroup\tcomment\n",infile);
	
	if (opt_r) {
		while ((ptr = fgets(line,sizeof(line),GFFfile)) != NULL) {
			if (*ptr == '#') fprintf(stdoutCopy,"%s",line);
			else {
				if ((sscanf(line,"%*s %s %s %lu:%lu %lu:%lu %s %s %s",source,feature,&xb,&yb,&xe,&ye,scores,strands,frames)) < 9) wrongFormatError(infile);
				cptr = strchr(line,'#');
				
				if (!strcmp(feature,"seqbounds")) {
					if ((sscanf(scores,"%[^:]:%s",waste,waste2)) == 2) sprintf(scores,"%s:%s",waste2,waste);
					if ((sscanf(strands,"%c:%c",&strand1,&strand2)) == 2) sprintf(strands,"%c:%c",strand2,strand1);
					if ((sscanf(frames,"%c:%c",&frameChar1,&frameChar2)) == 2) sprintf(frames,"%c:%c",frameChar2,frameChar1);
					if (cptr) fprintf(stdoutCopy,"%s:%s\t%s\tseqbounds\t%lu:%lu\t%lu:%lu\t%s\t%s\t%s\t%s",yName,xName,source,yb,xb,ye,xe,scores,strands,frames,cptr);
					else      fprintf(stdoutCopy,"%s:%s\t%s\tseqbounds\t%lu:%lu\t%lu:%lu\t%s\t%s\t%s\n",yName,xName,source,yb,xb,ye,xe,scores,strands,frames);
					xseqLen_4 = xe - xb - 4;
					yseqLen_4 = ye - yb - 4;
				}
				else if (!strcmp(feature,"alignment")) {	
					/* print previous alignment line, if neccessary */
					if (!aliPrinted) fprintf (stdoutCopy,"%s",aliPrintString);
					aliPrinted = 0;
					if (cptr) {	
						if (sscanf(scores,"%f",&score) == 1) sprintf(aliPrintString,"%s:%s\t%s\talignment\t%lu:%lu\t%lu:%lu\t%5.3f\t%s\t%s\t%s",yName,xName,source,yb,xb,ye,xe,score,strands,frames,cptr);
						else                                 sprintf(aliPrintString,"%s:%s\t%s\talignment\t%lu:%lu\t%lu:%lu\t%s\t%s\t%s\t%s",   yName,xName,source,yb,xb,ye,xe,scores,strands,frames,cptr);
					}
					else {	
						if (sscanf(scores,"%f",&score) == 1) sprintf(aliPrintString,"%s:%s\t%s\talignment\t%lu:%lu\t%lu:%lu\t%5.3f\t%s\t%s\n",yName,xName,source,yb,xb,ye,xe,score,strands,frames);
						else                                 sprintf(aliPrintString,"%s:%s\t%s\talignment\t%lu:%lu\t%lu:%lu\t%s\t%s\t%s\n",   yName,xName,source,yb,xb,ye,xe,scores,strands,frames);
					}
				}
				else if (!strcmp(feature,"fragment")) {	
				    if (!opt_i || (xe - xb < xseqLen_4) || (ye - yb < yseqLen_4)) { 				
						if (cptr) {		
							if (sscanf(scores,"%f",&score) == 1) {
								if (aliPrinted) fprintf(stdoutCopy,"%s:%s\t%s\tfragment\t%lu:%lu\t%lu:%lu\t%5.3f\t%s\t%s\t%s",                 yName,xName,source,yb,xb,ye,xe,score,strands,frames,cptr);
								else            fprintf(stdoutCopy,"%s%s:%s\t%s\tfragment\t%lu:%lu\t%lu:%lu\t%5.3f\t%s\t%s\t%s",aliPrintString,yName,xName,source,yb,xb,ye,xe,score,strands,frames,cptr);
							}
							else {
								if (aliPrinted) fprintf(stdoutCopy,"%s:%s\t%s\tfragment\t%lu:%lu\t%lu:%lu\t%s\t%s\t%s\t%s",                 yName,xName,source,yb,xb,ye,xe,scores,strands,frames,cptr);
								else            fprintf(stdoutCopy,"%s%s:%s\t%s\tfragment\t%lu:%lu\t%lu:%lu\t%s\t%s\t%s\t%s",aliPrintString,yName,xName,source,yb,xb,ye,xe,scores,strands,frames,cptr);
							}
						}
						else {	
							if (sscanf(scores,"%f",&score) == 1) {
								if (aliPrinted) fprintf(stdoutCopy,"%s:%s\t%s\tfragment\t%lu:%lu\t%lu:%lu\t%5.3f\t%s\t%s\n",                 yName,xName,source,yb,xb,ye,xe,score,strands,frames);
								else            fprintf(stdoutCopy,"%s%s:%s\t%s\tfragment\t%lu:%lu\t%lu:%lu\t%5.3f\t%s\t%s\n",aliPrintString,yName,xName,source,yb,xb,ye,xe,score,strands,frames);
							}
							else {
								if (aliPrinted) fprintf(stdoutCopy,"%s:%s\t%s\tfragment\t%lu:%lu\t%lu:%lu\t%s\t%s\t%s\n",                 yName,xName,source,yb,xb,ye,xe,scores,strands,frames);
								else            fprintf(stdoutCopy,"%s%s:%s\t%s\tfragment\t%lu:%lu\t%lu:%lu\t%s\t%s\t%s\n",aliPrintString,yName,xName,source,yb,xb,ye,xe,scores,strands,frames);
							}
						}	
					}
					else fprintf(stderr,"%s: Warning: Skipped fragment (probably a self alignment of full sequence):\n%s",prgCall,line);
					aliPrinted = 1; /* if not printed already, then previous alignment line must not be printed because of skipped fragment */
				}
			}
		}
	}
	else {
		while ((ptr = fgets(line,sizeof(line),GFFfile)) != NULL) {
			if (*ptr == '#') fprintf(stdoutCopy,"%s",line);
			else {
				if ((sscanf(line,"%*s %s %s %lu:%lu %lu:%lu %s %s %s",source,feature,&xb,&yb,&xe,&ye,scores,strands,frames)) < 9) wrongFormatError(infile);
				cptr = strchr(line,'#');
				
				if (!strcmp(feature,"seqbounds")) {
					if (cptr) fprintf(stdoutCopy,"%s:%s\t%s\tseqbounds\t%lu:%lu\t%lu:%lu\t%s\t%s\t%s\t%s",xName,yName,source,xb,yb,xe,ye,scores,strands,frames,cptr);
					else      fprintf(stdoutCopy,"%s:%s\t%s\tseqbounds\t%lu:%lu\t%lu:%lu\t%s\t%s\t%s\n",xName,yName,source,xb,yb,xe,ye,scores,strands,frames);
					xseqLen_4 = xe - xb - 4;
					yseqLen_4 = ye - yb - 4;
				}
				else if (!strcmp(feature,"alignment")) {	
					/* print previous alignment line, if neccessary */
					if (!aliPrinted) fprintf (stdoutCopy,"%s",aliPrintString);
					aliPrinted = 0;
					if (cptr) {
						if (sscanf(scores,"%f",&score) == 1) sprintf(aliPrintString,"%s:%s\t%s\talignment\t%lu:%lu\t%lu:%lu\t%5.3f\t%s\t%s\t%s",xName,yName,source,xb,yb,xe,ye,score ,strands,frames,cptr);
						else                                 sprintf(aliPrintString,"%s:%s\t%s\talignment\t%lu:%lu\t%lu:%lu\t%s\t%s\t%s\t%s",   xName,yName,source,xb,yb,xe,ye,scores,strands,frames,cptr);
					}
					else {
						if (sscanf(scores,"%f",&score) == 1) sprintf(aliPrintString,"%s:%s\t%s\talignment\t%lu:%lu\t%lu:%lu\t%5.3f\t%s\t%s\n",xName,yName,source,xb,yb,xe,ye,score ,strands,frames);
						else                                 sprintf(aliPrintString,"%s:%s\t%s\talignment\t%lu:%lu\t%lu:%lu\t%s\t%s\t%s\n",   xName,yName,source,xb,yb,xe,ye,scores,strands,frames);
					}
				}
				else if (!strcmp(feature,"fragment")) {	
					if (!opt_i || (xe - xb < xseqLen_4) || (ye - yb < yseqLen_4)) { 				
						if (cptr) {
							if (sscanf(scores,"%f",&score) == 1) {
								if (aliPrinted) fprintf(stdoutCopy,"%s:%s\t%s\tfragment\t%lu:%lu\t%lu:%lu\t%5.3f\t%s\t%s\t%s",                 xName,yName,source,xb,yb,xe,ye,score,strands,frames,cptr);
								else            fprintf(stdoutCopy,"%s%s:%s\t%s\tfragment\t%lu:%lu\t%lu:%lu\t%5.3f\t%s\t%s\t%s",aliPrintString,xName,yName,source,xb,yb,xe,ye,score,strands,frames,cptr);
							}
							else {
								if (aliPrinted) fprintf(stdoutCopy,"%s:%s\t%s\tfragment\t%lu:%lu\t%lu:%lu\t%s\t%s\t%s\t%s",                    xName,yName,source,xb,yb,xe,ye,scores,strands,frames,cptr);
								else            fprintf(stdoutCopy,"%s%s:%s\t%s\tfragment\t%lu:%lu\t%lu:%lu\t%s\t%s\t%s\t%s",aliPrintString,xName,yName,source,xb,yb,xe,ye,scores,strands,frames,cptr);
							}
						}
						else {	
							if (sscanf(scores,"%f",&score) == 1) {
								if (aliPrinted) fprintf(stdoutCopy,"%s:%s\t%s\tfragment\t%lu:%lu\t%lu:%lu\t%5.3f\t%s\t%s\n",                 xName,yName,source,xb,yb,xe,ye,score,strands,frames);
								else            fprintf(stdoutCopy,"%s%s:%s\t%s\tfragment\t%lu:%lu\t%lu:%lu\t%5.3f\t%s\t%s\n",aliPrintString,xName,yName,source,xb,yb,xe,ye,score,strands,frames);
							}
							else {
								if (aliPrinted) fprintf(stdoutCopy,"%s:%s\t%s\tfragment\t%lu:%lu\t%lu:%lu\t%s\t%s\t%s\n",                    xName,yName,source,xb,yb,xe,ye,scores,strands,frames);
								else            fprintf(stdoutCopy,"%s%s:%s\t%s\tfragment\t%lu:%lu\t%lu:%lu\t%s\t%s\t%s\n",aliPrintString,xName,yName,source,xb,yb,xe,ye,scores,strands,frames);
							}
						}	
					}	
					else fprintf(stderr,"%s: Warning: Skipped fragment (probably a self alignment of full sequence):\n%s",prgCall,line);	
					aliPrinted = 1; /* if not printed already, then previous alignment line must not be printed because of skipped fragment */
				}
			}
		}
	}
	if (!aliPrinted) fprintf (stdoutCopy,"%s",aliPrintString); /* print alignment if there is no following fragment */
	
	if (fclose(GFFfile)) fprintf(stderr,"Error: Unable to close file %s\n",infile);
	if (opt_f && fclose(stdoutCopy)) fprintf(stderr,"Error: Unable to close file %s\n",outfile);
	
	return;
}


/****************************************************************************
*
* Function:     processMumfile
*
* Parameters:	---
*
* Returns:     	---
*
* Description:  read alignment data from MUMmer output file
*
****************************************************************************/
void processMumfile() {

	FILE *MUMfile;

	char line[MAXSTRING];							/*----- read line 		-----*/
	char *ptr;										/*----- pointer to line -----*/
	
	unsigned long int xb, xe, yb, ye;    			// start and end positions of MUM
	unsigned long int nextxb, nextyb;    			// start and end positions of next MUM
	unsigned long int mumlen;  /* length of MUM */
	unsigned long int overlap;
	
	unsigned long int errCount;
	float score;
	unsigned long int fxb, fxe, fyb, fye;           // start and end positions of gaps resp. fragments of gaps
    unsigned long int flen;							// fragment length
		
	char frames[4];
	
	time_t now;
	char nowString[100];
	
	char nextMUM[MAXSTRING] = "";
	char nextGAP[MAXSTRING] = "";
	
	
	char seq1[MAX_SEQUENCE_LENGTH];
	char seq2[MAX_SEQUENCE_LENGTH];
	char err[MAX_SEQUENCE_LENGTH];
	unsigned long int gaplen;
	
	char *ptr11;
	char *ptr12;
	char *ptr21;
	char *ptr22;
	char *ptre1;
	char *ptre2;
	
	unsigned long int i;
	
	unsigned short int other = 0;	// flag, whethr already "Other matches" are to be read
	
	frames[0] = frames[2] = frameChar;
	frames[1] = ':';
	frames[3] = '\0';	
		
	/*----- open alignment file -----*/
	MUMfile = fopen(infile, "r");
	if (MUMfile == NULL) {fprintf(stderr,"Error: Unable to input file %s\n%s\n",infile,line);exit(2);}	
	
	fprintf (stdoutCopy,"##gff-version 2\n");
	fprintf (stdoutCopy,"##source-version %s\n",prgCall);

	now = time(NULL);
	strftime(nowString,100,"%b/%d/%Y %X",localtime(&now));
	fprintf (stdoutCopy,"##date %s\n##\n##%s ",nowString,prgCall);
	if (opt_r) fprintf (stdoutCopy," -r");
	if (opt_t) fprintf (stdoutCopy," -t %c",frameChar);
	fprintf (stdoutCopy," -x %s -y %s",xName,yName);
	if (opt_i) fprintf (stdoutCopy," -i");
	if (opt_f) fprintf (stdoutCopy," -f");
	fprintf (stdoutCopy," %s\n#name1:name2\t\tsource\t\tfeature\t\tbeg1:beg2\tend1:end2\tscore\tstrand\tframe\tgroup\tcomment\n",infile);
	
	if (opt_r) {
		// read first line "> name [reverse ]Consistent matches"
		if (!(ptr = fgets(line,sizeof(line),MUMfile))) wrongFormatError(infile);
		if (*ptr != '>') wrongFormatError(infile);
		fprintf(stdoutCopy,"#%s",line);
		
		// read first MUM
		if(!(ptr = fgets(line,sizeof(line),MUMfile))) wrongFormatError(infile);
		if (sscanf(line," %ld %ld %ld",&xb,&yb,&mumlen) < 3) wrongFormatError(infile);
		xe = xb + mumlen - 1;
		ye = yb + mumlen - 1;
		sprintf(nextMUM,"%s:%s\tMUMmer\talignment\t%lu:%lu\t%lu:%lu\t1.000\t+:+\t%s\t# MUM\n%s:%s\tMUMmer\tfragment\t%lu:%lu\t%lu:%lu\t1.000\t+:+\t%s\n",yName,xName,yb,xb,ye,xe,frames,yName,xName,yb,xb,ye,xe,frames);
		
		while ((ptr = fgets(line,sizeof(line),MUMfile)) != NULL) {
			// Errors line of MUMmer output
			// immediately after (next) MUM
			// so we can print the GAP-alignment now using data from previous and next MUM as the number of errors within the alignment
			if (strstr(line,"Errors =") && !other) {
				 if (sscanf(line,"    Errors = %ld",&errCount) < 1) wrongFormatError(infile);
				
				 if (DEBUG) fprintf(stderr,"avlen: %f \n",score);
				 score = (score - errCount)/score; // match percentage
				
				 fprintf(stdoutCopy,"%s%5.3f\t+:+\t%s\t# GAP\n",nextGAP,score,frames);	
			}	
			
			// read GAP-alignment data
			else if (*ptr == 'T') {
				if (!other) {
					strcat(seq1,line+4);     	  // read part of first sequence
					gaplen = strlen(seq1)-1;
					seq1[gaplen] = '\0';
				
					// read part of second sequence
					if (*(ptr = fgets(line,sizeof(line),MUMfile)) != 'S') {fprintf(stderr,"%s",line);wrongFormatError(infile);}
					strcat(seq2,line+4);
					seq2[gaplen] = '\0';
				
					// read error markers				
					ptr = fgets(line,sizeof(line),MUMfile);
	        		if (*(line+strspn(line," ^")+1) != '\0') wrongFormatError(infile);
					strcat(err,line+4);
					err[gaplen] = '\0';
	        	}
	        	else {
					// read part of second sequence
					if (*(ptr = fgets(line,sizeof(line),MUMfile)) != 'S') {fprintf(stderr,"%s",line);wrongFormatError(infile);}
					// read error markers				
					ptr = fgets(line,sizeof(line),MUMfile);
	        	}
	        }	
	
	        // next MUM
			else if ((*ptr == '>') || (sscanf(line," %ld %ld %ld",&nextxb,&nextyb,&mumlen) == 3)) {
				
				// there are GAP-alignment data of the GAP before this MUM which should be interpreted and printed
				if (strcmp(err,"")) {
					if (DEBUG) fprintf(stderr,"gap data: length %d-20=%d\n%s\n%s\n%s\n",strlen(seq1),strlen(seq1)-20,seq1,seq2,err);	
				
					// generate fragments from gap data
					
					// cut start of next MUM from gap sequences
					ptre2 = strrchr(err,'^');
					ptre2++;
					*ptre2 = '\0';
					flen = ptre2 - err;
					*(seq1+flen) = '\0';
					*(seq2+flen) = '\0';
					
					// cut end of previous MUM from gap sequences
					ptre1 = strchr(err,'^');
					flen = ptre1 - err;
					ptr11 = seq1 + flen;
					ptr21 = seq2 + flen;

					// while there is something else to do
					while (*ptre1 != '\0') {
					
						// get end of (now) first gap-free fragment					
						ptr12 = strchr(ptr11,'.');
						ptr22 = strchr(ptr21,'.');
				
						// no gaps within the remaining GAP-alignment
						if (!ptr12 && !ptr22) {
							// get length
							flen = strlen(ptr11);
							// count errors (mismatches)
							ptre2 = ptre1 - 1;
							errCount = 0;
							for (i = 0; i < flen; i++) {
								ptre2++;
								if (*ptre2 == '^') errCount++;
							}
							// get score
							score = (float)(flen-errCount)/flen;
							if (DEBUG) fprintf(stderr,"flen %ld   errCount %ld   score %3.5f\n",flen,errCount,score);
							// print fragment record
							fprintf (stdoutCopy,"%s:%s\tMUMmer\tfragment\t%lu:%lu\t%lu:%lu\t%5.3f\t+:+\t%s\n",yName,xName,fyb,fxb,fyb+flen-1,fxb+flen-1,score,frames);
							// stop - there is nothing more to do
							*ptre1 = '\0';
						}
						
						// gap found
						else {
							if (DEBUG) fprintf(stderr,"%s\n%s\n%s\n",ptr11,ptr21,ptre1);						
							
							// extract the front fragment
							if (ptr12) {
								if (ptr22) {
									if (ptr12 - ptr11 < ptr22 - ptr21) {
										flen =  ptr12 - ptr11;
										ptr22 = ptr21 + flen;
									}
									else {
										flen = ptr22 - ptr21;
										ptr12 = ptr11 + flen;
									}
								}
								else {
									flen =  ptr12 - ptr11;
									ptr22 = ptr21 + flen;
								}
							}
							else {
								flen =  ptr22 - ptr21;
								ptr12 = ptr11 + flen;
							}
							
							// get fragment end positions on both sequences
							fxe = fxb + flen - 1;
							fye = fyb + flen - 1;
							
							ptre2 = ptre1 - 1;
							

							//------------------------------------------------------------------------------------------------------------------------								
							// ATTENTION: This is a workaround for inconsistent MUMmer output:
							//            Sometimes the MUM-gap alignment consumes the first positions of the following MUM
							//			  (possibly the Smith-Waterman-alignment does not penalize end gaps???)				
							// So we have to cut the fragment end, if they consume MUM-positions.
							//            Question: Are these positions always used for matches (only seen until now), or for mismatches (errors) too?
							if (DEBUG) fprintf(stderr,"(real) fragment end positions %ld %ld ------ (MUM start positions) %ld %ld \n",fye,fxe,yb,xb);
							overlap = 0;
							if (fxe >= xb) overlap = fxe - xb + 1;
							if (fye - overlap >= yb) overlap = fye - yb + 1;
							flen -= overlap;
							fxe -= overlap;
							fye -= overlap;
							//------------------------------------------------------------------------------------------------------------------------								
								
							// real fragment
							if (flen) {
								// count errors (mismatches)
								errCount = 0;
								for (i = 0; i < flen; i++) {
									ptre2++;
									if (*ptre2 == '^') errCount++;
								}
								
								// get score
								score = (float)(flen-errCount)/flen;
								if (DEBUG) fprintf(stderr,"flen %ld   errCount %ld   score %3.5f\n",flen,errCount,score);
								
								// print fragment record
								fprintf (stdoutCopy,"%s:%s\tMUMmer\tfragment\t%lu:%lu\t%lu:%lu\t%5.3f\t+:+\t%s\n",yName,xName,fyb,fxb,fye,fxe,score,frames);
							}
							
							// correction:
							//fxe += overlap;  //overlap != 0 only if end of gap reached, that means if ptre1 = '\0' in the following
							//fye += overlap;  //-> hence correct values of fxe and fye no more used
							//
							//ptre2 += overlap; // only used to calculate ptre1 - see below
							
							// keep positions
							fxb = fxe;
							fyb = fye;
							
							// get first position after the current gap (possibly a gap on the other strand)
							// xxxxxx[xxxxx]........  => strspn() = 0
							// ......[xxxxx]xxxxxxxx  => strspn() > 0   => hence use the larger value
							ptr11 = ptr12 + strspn(ptr12,".");
							ptr21 = ptr22 + strspn(ptr22,".");
						
							if (ptr11 - ptr12 < ptr21 - ptr22) {
								// get gap length (ca.)
								flen = ptr21 - ptr22;
								// adjust the other sequence
								ptr11 = ptr12 + flen;
								// adjust start positions of the next fragment
								fxb = fxb + flen + 1;
								fyb++;
							}
							else {
								// get gap length (ca.)
								flen = ptr11 - ptr12;
								// adjust the other sequence
								ptr21 = ptr22 + flen;
								// adjust start positions of the next fragment
								fxb++;
								fyb = fyb + flen + 1;
							}
							// get new start position on error marker string
							ptre1 = ptre2 + overlap + flen + 1;     // add overlap to complete workaround
						}	
					}
				}
				
				// ready - now reset sequences to avoid to use it repeatedly
				*seq1 = *seq2 = *err = '\0'; // reset sequences
				
				// now output earlier read MUM
				fprintf(stdoutCopy,"%s",nextMUM); // print MUM
				*nextMUM = '\0';
				
				if (*ptr == '>') {
					other = 1;
					fprintf(stdoutCopy,"#%s",line);
				}
				else {
					xb = nextxb;
					yb = nextyb;
					
					if (!other) {
						// prepare GAP-alignment print string and average MUM-gap length
						fxb = xe + 1;
						fyb = ye + 1;
						fxe = xb - 1;
						fye = yb - 1;
						sprintf(nextGAP,"%s:%s\tMUMmer\talignment\t%lu:%lu\t%lu:%lu\t",yName,xName,fyb,fxb,fye,fxe);
						score = (fxe - fxb  + fye - fyb)/2. + 1; // average gap length
				    }
				
					// calculate data for next MUM (to be printed after data of gap before it (in MUMmer output after this MUM))
					xe = xb + mumlen - 1;
					ye = yb + mumlen - 1;
					sprintf(nextMUM,"%s:%s\tMUMmer\talignment\t%lu:%lu\t%lu:%lu\t1.000\t+:+\t%s\t# MUM\n%s:%s\tMUMmer\tfragment\t%lu:%lu\t%lu:%lu\t1.000\t+:+\t%s\n",yName,xName,yb,xb,ye,xe,frames,yName,xName,yb,xb,ye,xe,frames);
	        	}
	        }
	        //else wrongFormatError(infile);
		}
	}
	else {
		// read first line "> name [reverse ]Consistent matches"
		if (!(ptr = fgets(line,sizeof(line),MUMfile))) wrongFormatError(infile);
		if (*ptr != '>') wrongFormatError(infile);
		fprintf(stdoutCopy,"#%s",line);
		
		// read first MUM
		if(!(ptr = fgets(line,sizeof(line),MUMfile))) wrongFormatError(infile);
		if (sscanf(line," %ld %ld %ld",&xb,&yb,&mumlen) < 3) wrongFormatError(infile);
		xe = xb + mumlen - 1;
		ye = yb + mumlen - 1;
		sprintf(nextMUM,"%s:%s\tMUMmer\talignment\t%lu:%lu\t%lu:%lu\t1.000\t+:+\t%s\t# MUM\n%s:%s\tMUMmer\tfragment\t%lu:%lu\t%lu:%lu\t1.000\t+:+\t%s\n",xName,yName,xb,yb,xe,ye,frames,xName,yName,xb,yb,xe,ye,frames);
		
		while ((ptr = fgets(line,sizeof(line),MUMfile)) != NULL) {
			// Errors line of MUMmer output
			// immediately after (next) MUM
			// so we can print the GAP-alignment now using data from previous and next MUM as the number of errors within the alignment
			if (strstr(line,"Errors =") && !other) {
				 if (sscanf(line,"    Errors = %ld",&errCount) < 1) wrongFormatError(infile);
				
				 if (DEBUG) fprintf(stderr,"avlen: %f \n",score);
				 score = (score - errCount)/score; // match percentage
				
				 fprintf(stdoutCopy,"%s%5.3f\t+:+\t%s\t# GAP\n",nextGAP,score,frames);	
			}	
			
			// read GAP-alignment data
			else if (*ptr == 'T') {
				if (!other) {
					strcat(seq1,line+4);     	  // read part of first sequence
					gaplen = strlen(seq1)-1;
					seq1[gaplen] = '\0';
				
					// read part of second sequence
					if (*(ptr = fgets(line,sizeof(line),MUMfile)) != 'S') {fprintf(stderr,"%s",line);wrongFormatError(infile);}
					strcat(seq2,line+4);
					seq2[gaplen] = '\0';
				
					// read error markers				
					ptr = fgets(line,sizeof(line),MUMfile);
	        		if (*(line+strspn(line," ^")+1) != '\0') wrongFormatError(infile);
					strcat(err,line+4);
					err[gaplen] = '\0';
	        	}
	        	else {
					// read part of second sequence
					if (*(ptr = fgets(line,sizeof(line),MUMfile)) != 'S') {fprintf(stderr,"%s",line);wrongFormatError(infile);}
					// read error markers				
					ptr = fgets(line,sizeof(line),MUMfile);
	        	}
	        }	
	
	        // next MUM
			else if ((*ptr == '>') || (sscanf(line," %ld %ld %ld",&nextxb,&nextyb,&mumlen) == 3)) {
				
				// there are GAP-alignment data of the GAP before this MUM which should be interpreted and printed
				if (strcmp(err,"")) {
					if (DEBUG) fprintf(stderr,"gap data: length %d-20=%d\n%s\n%s\n%s\n",strlen(seq1),strlen(seq1)-20,seq1,seq2,err);	
				
					// generate fragments from gap data
					
					// cut start of next MUM from gap sequences
					ptre2 = strrchr(err,'^');
					ptre2++;
					*ptre2 = '\0';
					flen = ptre2 - err;
					*(seq1+flen) = '\0';
					*(seq2+flen) = '\0';
					
					// cut end of previous MUM from gap sequences
					ptre1 = strchr(err,'^');
					flen = ptre1 - err;
					ptr11 = seq1 + flen;
					ptr21 = seq2 + flen;

					// while there is something else to do
					while (*ptre1 != '\0') {
					
						// get end of (now) first gap-free fragment					
						ptr12 = strchr(ptr11,'.');
						ptr22 = strchr(ptr21,'.');
				
						// no gaps within the remaining GAP-alignment
						if (!ptr12 && !ptr22) {
							// get length
							flen = strlen(ptr11);
							// count errors (mismatches)
							ptre2 = ptre1 - 1;
							errCount = 0;
							for (i = 0; i < flen; i++) {
								ptre2++;
								if (*ptre2 == '^') errCount++;
							}
							// get score
							score = (float)(flen-errCount)/flen;
							if (DEBUG) fprintf(stderr,"flen %ld   errCount %ld   score %3.5f\n",flen,errCount,score);
							// print fragment record
							fprintf (stdoutCopy,"%s:%s\tMUMmer\tfragment\t%lu:%lu\t%lu:%lu\t%5.3f\t+:+\t%s\n",xName,yName,fxb,fyb,fxb+flen-1,fyb+flen-1,score,frames);
							// stop - there is nothing more to do
							*ptre1 = '\0';
						}
						
						// gap found
						else {
							if (DEBUG) fprintf(stderr,"%s\n%s\n%s\n",ptr11,ptr21,ptre1);						
							
							// extract the front fragment
							if (ptr12) {
								if (ptr22) {
									if (ptr12 - ptr11 < ptr22 - ptr21) {
										flen =  ptr12 - ptr11;
										ptr22 = ptr21 + flen;
									}
									else {
										flen = ptr22 - ptr21;
										ptr12 = ptr11 + flen;
									}
								}
								else {
									flen =  ptr12 - ptr11;
									ptr22 = ptr21 + flen;
								}
							}
							else {
								flen =  ptr22 - ptr21;
								ptr12 = ptr11 + flen;
							}
							
							// get fragment end positions on both sequences
							fxe = fxb + flen - 1;
							fye = fyb + flen - 1;
							
							ptre2 = ptre1 - 1;
							

							//------------------------------------------------------------------------------------------------------------------------								
							// ATTENTION: This is a workaround for inconsistent MUMmer output:
							//            Sometimes the MUM-gap alignment consumes the first positions of the following MUM
							//			  (possibly the Smith-Waterman-alignment does not penalize end gaps???)				
							// So we have to cut the fragment end, if they consume MUM-positions.
							//            Question: Are these positions always used for matches (only seen until now), or for mismatches (errors) too?
							if (DEBUG) fprintf(stderr,"(real) fragment end positions %ld %ld ------ (MUM start positions) %ld %ld \n",fxe,fye,xb,yb);
							overlap = 0;
							if (fxe >= xb) overlap = fxe - xb + 1;
							if (fye - overlap >= yb) overlap = fye - yb + 1;
							flen -= overlap;
							fxe -= overlap;
							fye -= overlap;
							//------------------------------------------------------------------------------------------------------------------------								
								
							// real fragment
							if (flen) {
								// count errors (mismatches)
								errCount = 0;
								for (i = 0; i < flen; i++) {
									ptre2++;
									if (*ptre2 == '^') errCount++;
								}
								
								// get score
								score = (float)(flen-errCount)/flen;
								if (DEBUG) fprintf(stderr,"flen %ld   errCount %ld   score %3.5f\n",flen,errCount,score);
								
								// print fragment record
								fprintf (stdoutCopy,"%s:%s\tMUMmer\tfragment\t%lu:%lu\t%lu:%lu\t%5.3f\t+:+\t%s\n",xName,yName,fxb,fyb,fxe,fye,score,frames);
							}
							
							// correction:
							//fxe += overlap;  //overlap != 0 only if end of gap reached, that means if ptre1 = '\0' in the following
							//fye += overlap;  //-> hence correct values of fxe and fye no more used
							//
							//ptre2 += overlap; // only used to calculate ptre1 - see below
							
							// keep positions
							fxb = fxe;
							fyb = fye;
							
							// get first position after the current gap (possibly a gap on the other strand)
							// xxxxxx[xxxxx]........  => strspn() = 0
							// ......[xxxxx]xxxxxxxx  => strspn() > 0   => hence use the larger value
							ptr11 = ptr12 + strspn(ptr12,".");
							ptr21 = ptr22 + strspn(ptr22,".");
						
							if (ptr11 - ptr12 < ptr21 - ptr22) {
								// get gap length (ca.)
								flen = ptr21 - ptr22;
								// adjust the other sequence
								ptr11 = ptr12 + flen;
								// adjust start positions of the next fragment
								fxb = fxb + flen + 1;
								fyb++;
							}
							else {
								// get gap length (ca.)
								flen = ptr11 - ptr12;
								// adjust the other sequence
								ptr21 = ptr22 + flen;
								// adjust start positions of the next fragment
								fxb++;
								fyb = fyb + flen + 1;
							}
							// get new start position on error marker string
							ptre1 = ptre2 + overlap + flen + 1;     // add overlap to complete workaround
						}	
					}
				}
				
				// ready - now reset sequences to avoid to use it repeatedly
				*seq1 = *seq2 = *err = '\0'; // reset sequences
				
				// now output earlier read MUM
				fprintf(stdoutCopy,"%s",nextMUM); // print MUM
				*nextMUM = '\0';
				
				if (*ptr == '>') {
					other = 1;
					fprintf(stdoutCopy,"#%s",line);
				}
				else {
					xb = nextxb;
					yb = nextyb;
					
					if (!other) {
						// prepare GAP-alignment print string and average MUM-gap length
						fxb = xe + 1;
						fyb = ye + 1;
						fxe = xb - 1;
						fye = yb - 1;
						sprintf(nextGAP,"%s:%s\tMUMmer\talignment\t%lu:%lu\t%lu:%lu\t",xName,yName,fxb,fyb,fxe,fye);
						score = (fxe - fxb  + fye - fyb)/2. + 1; // average gap length
				    }
				
					// calculate data for next MUM (to be printed after data of gap before it (in MUMmer output after this MUM))
					xe = xb + mumlen - 1;
					ye = yb + mumlen - 1;
					sprintf(nextMUM,"%s:%s\tMUMmer\talignment\t%lu:%lu\t%lu:%lu\t1.000\t+:+\t%s\t# MUM\n%s:%s\tMUMmer\tfragment\t%lu:%lu\t%lu:%lu\t1.000\t+:+\t%s\n",xName,yName,xb,yb,xe,ye,frames,xName,yName,xb,yb,xe,ye,frames);
	        	}
	        }
	        //else wrongFormatError(infile);
		}
	}
	if (*nextMUM != '\0') fprintf(stdoutCopy,"%s",nextMUM);
	if (fclose(MUMfile)) fprintf(stderr,"Error: Unable to close file %s\n",infile);
	if (opt_f && fclose(stdoutCopy)) fprintf(stderr,"Error: Unable to close file %s\n",outfile);
	
	return;
}



/****************************************************************************
*
* Function:     processSimfile
*
* Parameters:	---
*
* Returns:     	---
*
* Description:  read alignment data from sim file
*
****************************************************************************/
void processSimfile() {

	FILE *simfile;

	char line[MAXSTRING];							/*----- read line 		-----*/
	char seqboundsline[MAXSTRING];
	char *ptr;										/*----- pointer to line -----*/
	char waste[MAXSTRING];
	
	char source[MAXSTRING];
	
	float score;
	
	unsigned short int lavCount = 1;
	unsigned long int xb, xe, yb, ye;
	unsigned long int yh;
	
	char strand1;
	char strand2;
	
	time_t now;
	char nowString[100];
		
	int scancount;
	
	unsigned long int xseqLen_4;	/* length of x sequence -5 */
	unsigned long int yseqLen_4;	/* length of y sequence -5 */

	unsigned long int yrev; 			/* start position + end position of y sequence --- this term is used to calculate positions of rev. compl. fragments on forward strand */   			
	
	unsigned short int aliPrinted = 0;
	char aliPrintString[MAXSTRING];

		
	/*----- open alignment file -----*/
	simfile = fopen(infile, "r");
	if (simfile == NULL) {fprintf(stderr,"Error: Unable to input file %s\n%s\n",infile,line);exit(2);}	
	
	/*----- read lav-line --- it is a SIM file because of previous test in calling subroutine doit -----*/
	ptr = fgets(line,sizeof(line),simfile);
	
	fprintf (stdoutCopy,"##gff-version 2\n");
	fprintf (stdoutCopy,"##source-version %s\n",prgCall);

	now = time(NULL);
	strftime(nowString,100,"%b/%d/%Y %X",localtime(&now));
	fprintf (stdoutCopy,"##date %s\n##\n##%s ",nowString,prgCall);
	if (opt_r) fprintf (stdoutCopy," -r");
	if (opt_t) fprintf (stdoutCopy," -t %c",frameChar);
	fprintf (stdoutCopy," -x %s -y %s",xName,yName);
	if (opt_i) fprintf (stdoutCopy," -i");
	if (opt_f) fprintf (stdoutCopy," -f");
	fprintf (stdoutCopy," %s\n#name1:name2\t\tsource\t\tfeature\t\tbeg1:beg2\tend1:end2\tscore\tstrand\tframe\tgroup\tcomment\n",infile);
	
	
	
	while ((ptr = fgets(line,sizeof(line),simfile)) != NULL) {
		if (strstr(line,"#:lav") == ptr) {
			lavCount++;
			if (lavCount > 2) wrongFormatError(infile);
		}
		else if (strstr(line,"d {") == ptr) {
			if (fgets(line,sizeof(line),simfile) != NULL) {
				if (sscanf(line,"  \"%s ",waste) < 1) wrongFormatError(infile);
				ptr = strrchr(waste,'/');
				if (ptr != NULL) strcpy(source,ptr+1);
				else             strcpy(source,waste);
			}
			
			while (((ptr = fgets(line,sizeof(line),simfile)) != NULL) && (*ptr != '}')) {}
			if (ptr == NULL) wrongFormatError(infile);
		}
		else if (strstr(line,"s {") == ptr) {
			if ((fgets(line,sizeof(line),simfile) != NULL) && (sscanf(line,"%*s %lu %lu ", &xb, &xe) < 2)) wrongFormatError(infile);
			if ((fgets(line,sizeof(line),simfile) != NULL) && (sscanf(line,"%*s %lu %lu ", &yb, &ye) < 2)) wrongFormatError(infile);
			
			xseqLen_4 = xe - xb - 4;
			yseqLen_4 = ye - yb - 4;
			yrev = yb + ye;
				
			if (opt_r) sprintf (seqboundsline,"\t%s\tseqbounds\t%lu:%lu\t%lu:%lu\t.\t.\t.\n",source,yb,xb,ye,xe);
			else       sprintf (seqboundsline,"\t%s\tseqbounds\t%lu:%lu\t%lu:%lu\t.\t.\t.\n",source,xb,yb,xe,ye);
			
			while (((ptr = fgets(line,sizeof(line),simfile)) != NULL) && (*ptr != '}')) {}
			if (ptr == NULL) wrongFormatError(infile);
		}
		else if (strstr(line,"a {") == ptr) {
			if ((fgets(line,sizeof(line),simfile) == NULL) || (sscanf(line,"  s %f",&score) < 1)) wrongFormatError(infile);
			/*----- start point -----*/
			if ((fgets(line,sizeof(line),simfile) == NULL) || (sscanf(line,"  b %lu %lu",&xb,&yb) < 2)) wrongFormatError(infile);
			/*----- end point -----*/
			if ((fgets(line,sizeof(line),simfile) == NULL) || (sscanf(line,"  e %lu %lu",&xe,&ye) < 2)) wrongFormatError(infile);
			if (!opt_i || ((xe - xb < xseqLen_4) && (ye - yb < yseqLen_4))) {
				counta++;
				nmp = 0.;
				aliPrinted = 0;
				
				avlen = (abs(xe-xb) + abs(ye-yb))/2 + 1;				
				if (lavCount > 1) {
					/* y-values need to be converted */
					yb = yrev-yb;
					ye = yrev-ye;
				}
					
				if (xe < xb) {
					yh = xb;
					xb = xe;
					xe = yh;
					strand1 = '-';
				}
				else strand1 = '+';
				
				if (ye < yb) {
					yh = yb;
					yb = ye;
					ye = yh;
					strand2 = '-';
				}
				else strand2 = '+';
				
				if (opt_r) sprintf (aliPrintString,"%s:%s\t%s\talignment\t%lu:%lu\t%lu:%lu\t%5.3f\t%c:%c\t%c:%c\n",yName,xName,source,yb,xb,ye,xe,score,strand2,strand1,frameChar,frameChar);
				else       sprintf (aliPrintString,"%s:%s\t%s\talignment\t%lu:%lu\t%lu:%lu\t%5.3f\t%c:%c\t%c:%c\n",xName,yName,source,xb,yb,xe,ye,score,strand1,strand2,frameChar,frameChar);
			}
			else {
				fprintf(stderr,"%s: Warning: Skipped alignment with score %f (probably a self alignment of full sequence)\n",prgCall,score);
				while (((ptr = fgets(line,sizeof(line),simfile)) != NULL) && (*ptr != '}')) {}
				if (ptr == NULL) wrongFormatError(infile);
			}
		}
		else if (strstr(line,"  l") == ptr) {
			if ((scancount = sscanf(line,"%*s %ld %ld %ld %ld %f",&xb,&yb,&xe,&ye,&score)) < 4) wrongFormatError(infile);
			if ((scancount == 4)) score = 100.;
							
			nmp += (abs(xe - xb)+1) * score/(avlen*100.);
				
			if (lavCount > 1) {
				/* y-values need to be converted */
				yb = yrev-yb;
				ye = yrev-ye;
			}
				
			if (xe < xb) {
				yh = xb;
				xb = xe;
				xe = yh;
				strand1 = '-';
			}
			else strand1 = '+';
			
			if (ye < yb) {
				yh = yb;
				yb = ye;
				ye = yh;
				strand2 = '-';
			}
			else strand2 = '+';
				
			if (aliPrinted) {
				if (opt_r) fprintf (stdoutCopy,"%s:%s\t%s\tfragment\t%lu:%lu\t%lu:%lu\t%5.3f\t%c:%c\t%c:%c\t## cumulative nmp: %.3f\n",yName,xName,source,yb,xb,ye,xe,score/100.,strand2,strand1,frameChar,frameChar,nmp);
				else       fprintf (stdoutCopy,"%s:%s\t%s\tfragment\t%lu:%lu\t%lu:%lu\t%5.3f\t%c:%c\t%c:%c\t## cumulative nmp: %.3f\n",xName,yName,source,xb,yb,xe,ye,score/100.,strand1,strand2,frameChar,frameChar,nmp);
			}
			else {
				if (counta == 1) {	
					if (opt_r) fprintf (stdoutCopy,"%s:%s%s",yName,xName,seqboundsline);
					else       fprintf (stdoutCopy,"%s:%s%s",xName,yName,seqboundsline);
				}
				if (opt_r) fprintf (stdoutCopy,"%s%s:%s\t%s\tfragment\t%lu:%lu\t%lu:%lu\t%5.3f\t%c:%c\t%c:%c\t## cumulative nmp: %.3f\n",aliPrintString,yName,xName,source,yb,xb,ye,xe,score/100.,strand2,strand1,frameChar,frameChar,nmp);
				else       fprintf (stdoutCopy,"%s%s:%s\t%s\tfragment\t%lu:%lu\t%lu:%lu\t%5.3f\t%c:%c\t%c:%c\t## cumulative nmp: %.3f\n",aliPrintString,xName,yName,source,xb,yb,xe,ye,score/100.,strand1,strand2,frameChar,frameChar,nmp);
				aliPrinted = 1;
			}
		}
		else if ((strstr(line,"  f") == ptr) && opt_i) {
			counta--;
			/* read to end of block - skip all l line without score data */
			while (((ptr = fgets(line,sizeof(line),simfile)) != NULL) && (*ptr != '}')) {}
			if (ptr == NULL) wrongFormatError(infile);
		}
	}
	
	if (fclose(simfile)) fprintf(stderr,"Error: Unable to close file %s\n",infile);
	if (opt_f && fclose(stdoutCopy)) fprintf(stderr,"Error: Unable to close file %s\n",outfile);
	
	return;
}



/****************************************************************************
*
* Function:     start_time
* Parameters:   ---
* Returns:      ---
*
* Description:  get current time 
*
****************************************************************************/
void start_time(void) {
	timer.begin_clock = clock();
	timer.begin_time = time(NULL);
	return;
}



/****************************************************************************
*
* Function:     print_time
* Parameters:   ---
* Returns:      ---
*
* Description:  print left time 
*
****************************************************************************/
void print_time(void) {
	double user_time, real_time;
	char s1[MAXSTRING], s2[MAXSTRING];
	int n1, n2, width;
	
	user_time = (clock()-timer.begin_clock)/((double) CLOCKS_PER_SEC);
	real_time = difftime(time(NULL),timer.begin_time);
	
	n1 = sprintf(s1,"%.2f",user_time);
	n2 = sprintf(s2,"%.2f",real_time);
	
	width = (n1 > n2) ? n1 : n2;	
	
	fprintf(stderr,"User time: %*.2f seconds\nReal time: %*.2f seconds\n\n",width,user_time,width,real_time);
	
	return;
}



/****************************************************************************
*
* Function:     printUsage
* Parameters:   ---
* Returns:      ---
*
* Description:  print usage to screen 
*
****************************************************************************/
void printUsage(void) {
	fprintf (stderr,
	"\n\n\n"
	"NAME\n"
	"            %s - Module to translate a MUMmer output files into gff formatted output.\n\n"
	"SYNOPSIS\n"
	"            %s [-r] [-t <.|0|1|2>] [-x <name>] [-y <name>] [-H] [-f] [-h] <MUMmer_output_file>\n\n"
	"DESCRIPTION\n"
	"				\n\n"
	"OPTIONS\n"
	"\n-r               interchange the order of sequences (sequence 1 on y-axis, sequence 2 on x-axis)"
	"\n-t <.|0|1|2>     put label 'frame' in gff output"
	"\n-x <name>        specify the species name for species 1 (default: Seq1)"
	"\n-y <name>        specify the species name for species 2 (default: Seq2)"
	"\n-i               ignore full sequence identities"
	"\n-f               write output to file"
	"\n-h               print this help text\n\n\n",prgCall,prgCall);
	exit(1);
}



/****************************************************************************
*
* Function:     wrongFormatError
* Parameters:	char*	filename
* Returns:		-
* Description:  output error message and exit
*
****************************************************************************/
void wrongFormatError(const char* filename) {
	fprintf(stderr,"File %s is not in proper format!\n",filename);
	exit(3);
}



/****************************************************************************
*
* Function:     allocationError
* Parameters:	-
* Returns:		-
* Description:  output error message and exit
*
****************************************************************************/
void allocationError() {
	fprintf(stderr,"Allocation failure!\n");
	exit(9);									
}
