/*
 *                 converth 
 *                 --------
 *
 *	Convert Endiannness of an H.DAT File
 *      Takes as command line input the original file
 *      and the new file.
 *
 *      This program is independent of system
 *      architecture so can be run on either the
 *      system which produced the H.DAT or the system
 *      which is going to utilise the H.DAT file.
 *
 *      Example:
 *
 *      sun> stg3r.x < dstg3
 *      sun> scp H.DAT user@linux:H.SUN
 *      sun> ssh linux
 *
 *      linux> converth H.SUN H.DAT
 *      linux> stgf.x < dstgf
 *
 *      Written: Allan Whiteford
 *               02-Jul-2007
 * 
 */
 
#include <stdio.h>

FILE *fold, *fnew;
int is_little=-1;

#define float_block(N) do_size(0,N); do_float(N); do_size(0,N);
#define integer_block(N) do_size(N,0); do_integer(N); do_size(N,0);

int get_integer()
{
	unsigned char old[4],new[4];
        unsigned int cnt;
        int a,i;
        a=fread(&old,1,4,fold);
        for (i=0;i<=3;i++)
        {
        	new[3-i]=old[i];
        }
	
        if (is_little==1) cnt = old[0]+256*old[1]+65536*old[2]+16777216*old[3];
        if (is_little==0) cnt = old[3]+256*old[2]+65536*old[1]+16777216*old[0];
	a=fwrite(&new,1,4,fnew);
	return(cnt);
}

int do_integer(int total)
{
	unsigned char old[4],new[4];
        int i,j;
        for (j=0;j<total;j++)
        {
	        fread(&old,1,4,fold);
        	for (i=0;i<=3;i++) new[3-i]=old[i];
		fwrite(&new,1,4,fnew);
	}
}


int do_float(int total)
{
	unsigned char old[8],new[8];
        int i,j;
        for (j=0;j<total;j++)
        {
        	fread(&old,1,8,fold);
        	for (i=0;i<=7;i++) new[7-i]=old[i];
		fwrite(&new,1,8,fnew);
	}
}

int get_header(int *lrange,int *lamax,int *nast)
{
	unsigned char old[4],new[4];
        unsigned int a,i;
        a=fread(&old,1,4,fold);
        for (i=0;i<=3;i++)
        {
        	new[3-i]=old[i];
        }
        a=fwrite(&new,1,4,fnew);
	
       	if (old[0] == 36) is_little=1;
 	if (old[3] == 36) is_little=0;

	if (is_little==-1)
        {	
        	printf("Cannot determine endianness of file\n");
		exit(1);
	}
        
        do_integer(2);
	*lrange=get_integer();
	*lamax=get_integer();
	*nast=get_integer();
        do_float(2);
        do_size(5,2);
}


int do_size(int iint,int iflt)
{
	unsigned char old[4],new[4];
        unsigned int cnt;
        int a,i;
        a=fread(&old,1,4,fold);
        for (i=0;i<=3;i++) new[3-i]=old[i];
        if (is_little==1) cnt = old[0]+256*old[1]+65536*old[2]+16777216*old[3];
        if (is_little==0) cnt = old[3]+256*old[2]+65536*old[1]+16777216*old[0];

	if (cnt != 4*iint+8*iflt)
        {
        	printf("File record length isn't as expected %d!\n",cnt);
                exit(1);
        }
        a=fwrite(&new,1,4,fnew);
}


int main(int argc,char **argv)
{
	char i_old[4];
	char i_new[4];
	int a,i,lrange,lamax,nast,more=1,nchan,mnp2;

	if (argc!=3)
        {
        	printf("Usage: %s OLDFILE NEWFILE\n"
                	"    OLDFILE: H.DAT file which is to have endianness converted\n"
                        "    NEWFILE: Filename for result\n",argv[0]);
                exit(1);        
        }

	fold=fopen(argv[1],"rb");
	fnew=fopen(argv[2],"wb");

	get_header(&lrange,&lamax,&nast);
        printf("File is %s endian with %d Atomic States.\n",is_little ? "little" : "big",nast);
        
        if (nast < 0)
        {
        	printf("Cannot do partitiond R-matrix file\n");
                exit(1);
        }
        
        float_block(nast);
	integer_block(nast);
        integer_block(nast);
	float_block(lrange*3)
        
        while(more)
        {
	        do_size(6,0);
        	do_integer(3);
		nchan=get_integer();                
        	mnp2=get_integer();
		more=get_integer();                
	        do_size(6,0);

		integer_block(nast);
		integer_block(nchan);
		float_block(nchan*nchan*lamax);
		float_block(mnp2);
		float_block(nchan*mnp2);
        }
        
        fclose(fold);
        fclose(fnew);
}