/****************************************************************************
 *                                                                          *
 *     Loki - Programs for genetic analysis of complex traits using MCMC    *
 *                                                                          *
 *             Simon Heath - University of Washington                       *
 *                                                                          *
 *                      July 1997                                           *
 *                                                                          *
 * read_binfiles.c:                                                         *
 *                                                                          *
 * Read in the binary datafiles produced by prep                            *
 *                                                                          *
 * Copyright (C) Simon C. Heath 1997, 2000, 2002                            *
 * This is free software.  You can distribute it and/or modify it           *
 * under the terms of the Modified BSD license, see the file COPYING        *
 *                                                                          *
 ****************************************************************************/

#include <config.h>
#include <stdlib.h>
#include <string.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#ifdef USE_DMALLOC
#include <dmalloc.h>
#endif
#include <math.h>
#include <stdio.h>
#include <errno.h>
#include <signal.h>
#include <sys/wait.h>
#include <limits.h>

#include "utils.h"
#include "libhdr.h"
#include "loki.h"
#include "sparse.h"
#include "loki_peel.h"

int ped_size,n_markers,n_links,n_id_records,n_nonid_records,polygenic_flag,num_recs,max_peel_off,comp_sflag;
int *comp_start,*comp_size,*comp_ngenes,n_comp,***allele_trans,*comp_npeel,extra_allele_flag,tlocus_flag;
int family_id,n_orig_families,n_models,**founder_flag;
double total_maplength[2]={-1.0,-1.0};
lk_ulong ***all_set,**req_set[2];
struct Peelseq_Head **peelseq_head;
struct R_Func ***r_func;

struct Id_Record *id_array;
struct Id_Recode id_recode,fam_recode;
struct Marker *marker;
struct Link *linkage;
struct Variable *id_variable,*nonid_variable;
struct Model *models;
struct SparseMatRec **AIMatrix;

#define BFE(a,b) BinFileError(__FILE__,__LINE__,a,b)
static void BinFileError(const char *sfile,const int line,const char *file,const char *s)
{
	(void)fprintf(stderr,"[%s:%d] Error reading from file '%s'\n",sfile,line,file);
	if(s) (void)fprintf(stderr,"%s\n",s);
	if(errno) perror("loki");
	from_abt=1;
	exit(EXIT_FAILURE);
}

static int Check_Var(struct Model_Var *var)
{
	int er=0;
	
	if(var->var_index<0) er=1;
	else if(!(var->type&(ST_ID|ST_SIRE|ST_DAM|ST_TRAITLOCUS))) {
		if(var->type&ST_MARKER)	{
			if(var->var_index>=n_markers) er=1;
		} else if(var->type&ST_CONSTANT)	{
			if(var->var_index>=n_id_records) er=1;
		} else if(var->var_index>=n_nonid_records) er=1;
	}
	return er;
}

#ifdef FUNC_NAME
#undef FUNC_NAME
#endif
#define FUNC_NAME "open_readfile_and_check"
static FILE *open_readfile_and_check(char *fname)
{
	int i;
	FILE *fptr;
	
	errno=0;
	if(Filter) {
		i=child_open(READ,fname,Filter);
		if(!(fptr=fdopen(i,"r"))) BFE(fname,"Couldn't fdopen() stream");
		if(errno && errno!=ESPIPE) BFE(fname,0);
		errno=0;
	} else if(!(fptr=fopen(fname,"r"))) abt(__FILE__,__LINE__,"%s(): File Error.  Couldn't open '%s' for reading\n",FUNC_NAME,fname);
	return fptr;
}

#ifdef FUNC_NAME
#undef FUNC_NAME
#endif
#define FUNC_NAME "fget_line"
char *fget_line(FILE *fptr)
{
	static char *p;
	static int buf_size=256;
	int i=0;
	
	if(!fptr) {
		if(p) free(p);
		p=0;
		return 0;
	}
	if(!p) if(!(p=malloc((size_t)buf_size))) ABT_FUNC(MMsg);
	while(fgets(p+i,buf_size-i,fptr)) {
		i=(int)strlen(p);
		if((i && p[i-1]=='\n')||feof(fptr)) break;
		buf_size*=2;
		if(!(p=realloc(p,(size_t)buf_size))) ABT_FUNC(MMsg);
	} 
	if(!i) return 0;
	return p;
}

int get_str(char *p,char **p1,char c)
{
	int i=0;
	
	*p1=p;
	while(**p1) {
		if(**p1==c) break;
		i++;
		(*p1)++;
	}
	return i;
}

char *read_id_data(struct id_data *s,char *p)
{
	char *p1;
	
	if(*p++!=';') return 0;
	s->flag=strtol(p,&p1,16);
	p=p1+1;
	if(*p1=='I') s->data.value=strtol(p,&p1,16);
	else if(*p1=='R') (void)txt_get_double(p,&p1,&s->data.rvalue);
	return p1;
}

#ifdef FUNC_NAME
#undef FUNC_NAME
#endif
#define FUNC_NAME "ReadBinFiles"
void ReadBinFiles(char **lfile,int eflag)
{
	int i,j,k,k1,k2,k3,k4,a,a1,a2,*hapdata=0,comp,n_all,*mtmp;
	int v2[13],num_recs;
	lk_ulong *tl;
	unsigned int t_int;
	double **td1,*td2;
	char *fname,*tmp,*tmp1,*tmp2;
	struct id_data *iddata=0,**iddata_p=0;
	struct Model_Var *mvtmp;
	struct Peelseq_Head *pp=0;
	struct Simple_Element *simple_em;
	struct Complex_Element *complex_em;
	struct Locus *loc;
	void *tvp;
	union arg_type *rtmp=0;
	FILE *fptr;
	char *EMsg[]={
		"Bad format",
		"Bad magic number",
		"File corrupt",
		"Unexpected end of file",
	};
	
	signal(SIGCHLD,SIG_IGN);
	errno=0;
	fname=make_file_name(".opt");
	if(!(fptr=fopen(fname,"r"))) abt(__FILE__,__LINE__,"%s(): File Error.  Couldn't open '%s' for reading\n",FUNC_NAME,fname);
	(void)printf("Reading from %s\n",fname);
	if(!(tmp=fget_line(fptr))) BFE(fname,EMsg[3]);
	if(strncmp(tmp,"Loki.opt:",9)) BFE(fname,EMsg[0]);
	RunID=strtoul(tmp+9,&tmp1,16);
	if(*tmp1++!=',') BFE(fname,EMsg[2]);
	i=get_str(tmp1,&tmp,',');
	if(*tmp++!=',') BFE(fname,EMsg[2]);
	if(i) {
		if(!(*lfile=malloc((size_t)i+1))) ABT_FUNC(MMsg);
		(void)strncpy(*lfile,tmp1,(size_t)i);
		(*lfile)[i]=0;
	}
	i=get_str(tmp,&tmp1,'\n');
	if(*tmp1++!='\n') BFE(fname,EMsg[2]);
	if(i) {
		if(!(Filter=malloc((size_t)i+1))) ABT_FUNC(MMsg);
		(void)strncpy(Filter,tmp,(size_t)i);
		Filter[i]=0;
	}
	if(fclose(fptr)) BFE(fname,0);
	free(fname);
	fname=make_file_name(".dat");
	fptr=open_readfile_and_check(fname);
	(void)printf("Reading from %s\n",fname);
	if(!(tmp=fget_line(fptr))) BFE(fname,EMsg[3]);
	if(strncmp(tmp,"Loki.dat:",9)) BFE(fname,EMsg[0]);
	t_int=strtoul(tmp+9,&tmp1,16);
	if(t_int!=RunID) BFE(fname,"Binary files are from mixed runs");
	for(i=0;i<13;i++) {
		if(*tmp1++!=',') BFE(fname,EMsg[2]);
		if(*tmp1=='-') v2[i]=-(int)strtol(tmp1+1,&tmp,16);
		else v2[i]=(int)strtol(tmp1,&tmp,16);
		tmp1=tmp;
	}
	if(*tmp1++!='\n') BFE(fname,EMsg[2]);
	ped_size=v2[0];
	n_comp=v2[1];
	if(n_comp<0) {
		n_comp=-n_comp;
		comp_sflag=1;
	}
	n_markers=v2[2];
	n_links=v2[3];
	n_id_records=v2[4];
	n_nonid_records=v2[5];
	polygenic_flag=v2[6]&1;
	family_id=v2[6]&2?1:0;
	num_recs=v2[8];
	tlocus_flag=v2[10];
	n_genetic_groups=v2[11];
	n_models=v2[12];
	if(v2[11]<0 || v2[7]<0 || ped_size<1 || n_comp<1 || (n_markers && n_links<1)) BFE(fname,EMsg[2]);
	if(v2[7]) {
		if(!(iddata=malloc(sizeof(struct id_data)*v2[7]))) ABT_FUNC(MMsg);
		RemBlock=AddRemem(iddata,RemBlock);
	}
	if(num_recs) {
		if(!(iddata_p=malloc(sizeof(void *)*num_recs))) ABT_FUNC(MMsg);
		RemBlock=AddRemem(iddata_p,RemBlock);
	}
	if(n_markers) {
		if(!(hapdata=malloc(sizeof(int)*ped_size*n_markers))) ABT_FUNC(MMsg);
		RemBlock=AddRemem(hapdata,RemBlock);
	}
	if(!(comp_size=malloc(sizeof(int)*n_comp*3))) ABT_FUNC(MMsg);
	comp_ngenes=comp_size+n_comp;
	comp_start=comp_ngenes+n_comp;
	if(!(tmp=fget_line(fptr))) BFE(fname,EMsg[3]);
	for(i=0;i<n_comp;i++) {
		comp_size[i]=(int)strtol(tmp,&tmp1,16);
		tmp=tmp1;
		if(i<n_comp-1) if(*tmp++!=',') BFE(fname,EMsg[2]);
	}
	if(*tmp++!='\n') BFE(fname,EMsg[2]);
	for(i=j=0;i<n_comp;i++) {
		comp_ngenes[i]=0;
		comp_start[i]=j;
		j+=comp_size[i];
	}
	if(j!=ped_size) BFE(fname,EMsg[2]);
	if(!(id_array=malloc(sizeof(struct Id_Record)*ped_size))) ABT_FUNC(MMsg);
	if(n_markers+tlocus_flag) {
		if(!(id_array[0].pruned_flag=malloc(sizeof(int)*ped_size*(n_markers+tlocus_flag)))) ABT_FUNC(MMsg);
		RemBlock=AddRemem(id_array[0].pruned_flag,RemBlock);
		for(j=1;j<ped_size;j++) id_array[j].pruned_flag=id_array[j-1].pruned_flag+n_markers+tlocus_flag;
		if(!(founder_flag=malloc(sizeof(void *)*(n_markers+tlocus_flag)))) ABT_FUNC(MMsg);
		if(!(founder_flag[0]=malloc(sizeof(int)*ped_size*(n_markers+tlocus_flag)))) ABT_FUNC(MMsg);
 		for(j=1;j<n_markers+tlocus_flag;j++) founder_flag[j]=founder_flag[j-1]+ped_size;
	}
	if(n_markers) {
		if(!(marker=malloc(sizeof(struct Marker)*n_markers))) ABT_FUNC(MMsg);
		for(i=0;i<n_markers;i++) {
			loc=&marker[i].locus;
			loc->gt=0;
			marker[i].haplo=hapdata;
			hapdata+=ped_size;
			loc->variance=0;
			loc->seg[0]=0;
			marker[i].mterm=0;
		}
	}
	for(k=k1=j=0;j<ped_size;j++) {
		id_array[j].res=id_array[j].cens=0;
		id_array[j].bv=id_array[j].bvsum=id_array[j].bvsum2=0;
		id_array[j].data=0;
		id_array[j].data1=0;
		if(!(tmp=fget_line(fptr))) BFE(fname,EMsg[3]);
		k2=n_genetic_groups>1?7:6;
		if(family_id) k2++;
		for(i=0;i<k2;i++) {
			v2[i]=(int)strtol(tmp,&tmp1,16);
			tmp=tmp1;
			if(i<k2-1) if(*tmp++!=',') BFE(fname,EMsg[2]);
		}
		if(v2[0]>ped_size || v2[1]>ped_size) BFE(fname,EMsg[2]);
		id_array[j].sire=v2[0];
		id_array[j].dam=v2[1];
		if(family_id) {
			id_array[j].fam_code=v2[2];
			if(v2[2]>n_orig_families) n_orig_families=v2[2];
		}
		id_array[j].sex=v2[4+family_id];
		id_array[j].affected=v2[5+family_id];
		id_array[j].group=n_genetic_groups>1?v2[6+family_id]:1;
		k2=v2[2+family_id];
		id_array[j].n_rec=k2;
		if(k2>1) multiple_rec=1;
		if(v2[3+family_id]&2) {
			k2=n_genetic_groups>1?1:0;
			if(n_id_records-k2) {
				for(i=0;i<n_id_records-k2;i++) {
					tmp=read_id_data(iddata+k+i,tmp);
					if(!tmp) BFE(fname,EMsg[2]);
				}
				id_array[j].data=iddata+k;
				k+=n_id_records-k2;
			}
		}
		if(v2[2+family_id]) {
			if(!(iddata_p)) BFE(fname,EMsg[2]);
			id_array[j].data1=iddata_p+k1;
			k1+=v2[2+family_id];
			for(k2=0;k2<v2[2+family_id];k2++)	{
				id_array[j].data1[k2]=iddata+k;
				for(i=0;i<n_nonid_records;i++) {
					tmp=read_id_data(iddata+k,tmp);
					if(!tmp) BFE(fname,EMsg[2]);
					k++;
				}
			}
		}
		if(v2[3+family_id]&1)	{
			if(*tmp++!=';') BFE(fname,EMsg[2]);
			for(i=0;i<n_markers;i++) {
				k2=strtol(tmp,&tmp1,16);
				tmp=tmp1;
				if(*tmp++!=',') BFE(fname,EMsg[2]);
				k3=strtol(tmp,&tmp1,16);
				tmp=tmp1;
				if(*tmp++!=';') BFE(fname,EMsg[2]);
				if(k3>k2) {
					k4=k3;
					k3=k2;
					k2=k4;
				}
				marker[i].haplo[j]=(k2<<16)|k3;
			}
		} else for(i=0;i<n_markers;i++) marker[i].haplo[j]=0;
	}
	for(i=comp=0;comp<n_comp;comp++) for(j=0;j<comp_size[comp];j++) id_array[i++].comp=comp;
	if(!(tmp=fget_line(fptr))) BFE(fname,EMsg[3]);
	if(strncmp(tmp,"LKTR:",5)) BFE(fname,EMsg[0]);
	k=(int)strtol(tmp+5,&tmp1,16);
	if(family_id) {
		if(*tmp1++!=',') BFE(fname,EMsg[2]);
		tmp=tmp1;
		k1=(int)strtol(tmp,&tmp1,16);
	}
	if(*tmp1!='\n') BFE(fname,EMsg[2]);
	if(!(id_recode.recode=malloc(sizeof(union arg_type)*ped_size))) ABT_FUNC(MMsg);
	RemBlock=AddRemem(id_recode.recode,RemBlock);
	if(family_id && n_orig_families) {
		if(!(fam_recode.recode=malloc(sizeof(union arg_type)*n_orig_families))) ABT_FUNC(MMsg);
		RemBlock=AddRemem(fam_recode.recode,RemBlock);
	}
	if(family_id && n_orig_families) {
		if(k1) {
			fam_recode.flag=ST_STRING;
			if(!(tmp=malloc((size_t)k1))) ABT_FUNC(MMsg);
			RemBlock=AddRemem(tmp,RemBlock);
			if(fread(tmp,1,(size_t)k1,fptr)!=(size_t)k1) BFE(fname,EMsg[3]);
			for(k2=j=0;j<n_orig_families;j++) {
				fam_recode.recode[j].string=tmp+k2;
				while(k2<k1 && tmp[k2]!='\n') k2++;
				if(k2>=k1) BFE(fname,EMsg[0]);
				tmp[k2++]='\0';
			}
		} else {
			fam_recode.flag=ST_INTEGER;
			for(j=0;j<n_orig_families;j++)	{
				if(!(tmp=fget_line(fptr))) BFE(fname,EMsg[3]);
				fam_recode.recode[j].value=(int)strtol(tmp,&tmp1,16);
				if(*tmp1!='\n') BFE(fname,EMsg[2]);
			}
		}
	}
	if(k) {
		id_recode.flag=ST_STRING;
		if(!(tmp=malloc((size_t)k))) ABT_FUNC(MMsg);
		RemBlock=AddRemem(tmp,RemBlock);
		if(fread(tmp,1,(size_t)k,fptr)!=(size_t)k) BFE(fname,EMsg[3]);
		for(k1=j=0;j<ped_size;j++) {
			if(tmp[k1]!='\n') {
				id_recode.recode[j].string=tmp+k1;
				while(k1<k && tmp[k1]!='\n') k1++;
				if(k1>=k) BFE(fname,EMsg[0]);
			} else id_recode.recode[j].string=0;
			tmp[k1++]='\0';
		}
	} else {
		id_recode.flag=ST_INTEGER;
		for(j=0;j<ped_size;j++)	{
			if(!(tmp=fget_line(fptr))) BFE(fname,EMsg[3]);
			if(*tmp!='\n') {
				id_recode.recode[j].value=(int)strtol(tmp,&tmp1,16);
				if(*tmp1!='\n') BFE(fname,EMsg[2]);
			} else id_recode.recode[j].value=INT_MAX;
		}
	}
	if(n_links) {
		if(!(tmp=fget_line(fptr))) BFE(fname,EMsg[3]);
		if(strncmp(tmp,"LKLN:",5)) BFE(fname,EMsg[0]);
		k=(int)strtol(tmp+5,&tmp1,16);
		if(k<1) BFE(fname,EMsg[2]);
		if(!(linkage=malloc(sizeof(struct Link)*n_links))) ABT_FUNC(MMsg);
		for(j=0;j<n_links;j++) {
			linkage[j].n_markers=0;
			linkage[j].range_set[0]=linkage[j].range_set[1]=0;
			linkage[j].ibd_list=0;
			linkage[j].ibd_est_type=0;
			if(*tmp1++!=',') BFE(fname,EMsg[2]);
			linkage[j].type=(int)strtol(tmp1,&tmp,16);
			tmp1=tmp;
		}
		if(*tmp1!='\n') BFE(fname,EMsg[2]);
		if(!(tmp2=malloc((size_t)k))) ABT_FUNC(MMsg);
		RemBlock=AddRemem(tmp2,RemBlock);	
		if(fread(tmp2,1,(size_t)k,fptr)!=(size_t)k) BFE(fname,EMsg[3]);
		for(k1=k2=0,j=0;j<n_links;j++) {
			linkage[j].name=tmp2+k2;
			while(k2<k && tmp2[k2]!='\n') k2++;
			if(k2>=k) BFE(fname,EMsg[0]);
			tmp2[k2++]='\0';
		}
	}
	if(n_markers) {
		if(!(tmp=fget_line(fptr))) BFE(fname,EMsg[3]);
		if(strncmp(tmp,"LKMK:",5)) BFE(fname,EMsg[0]);
		k=(int)strtol(tmp+5,&tmp1,16);
		if(*tmp1++!=',') BFE(fname,EMsg[2]);
		k1=(int)strtol(tmp1,&tmp,16);
		if(k<1 || k1<0) BFE(fname,EMsg[2]);
		if(n_models) {
			if(!(marker[0].mterm=malloc(sizeof(void *)*n_markers*n_models))) ABT_FUNC(MMsg);
			for(i=0;i<n_markers*n_models;i++) marker[0].mterm[i]=0;
			for(i=1;i<n_markers;i++) marker[i].mterm=marker[i-1].mterm+n_models;
		}
		if(*tmp!='\n') BFE(fname,EMsg[2]);
		if(!(marker[0].n_all1=malloc(sizeof(int)*n_markers*n_comp))) ABT_FUNC(MMsg);
		RemBlock=AddRemem(marker[0].n_all1,RemBlock);
		for(j=1;j<n_markers;j++) marker[j].n_all1=marker[j-1].n_all1+n_comp;
		if(!(mtmp=malloc(sizeof(int)*n_markers))) ABT_FUNC(MMsg);
		RemBlock=AddRemem(mtmp,RemBlock);
		if(!(tmp2=malloc((size_t)k))) ABT_FUNC(MMsg);
		RemBlock=AddRemem(tmp2,RemBlock);
		if(k1) {
			if(!(rtmp=malloc(sizeof(union arg_type)*k1))) ABT_FUNC(MMsg);
			RemBlock=AddRemem(rtmp,RemBlock);
		}
		if(fread(tmp2,1,(size_t)k,fptr)!=(size_t)k) BFE(fname,EMsg[3]);
		for(k2=k3=j=0;j<n_markers;j++) {
			loc=&marker[j].locus;
			loc->flag=0;
			marker[j].name=tmp2+k2;
			while(k2<k && tmp2[k2]!='\n') k2++;
			if(k2>=k) BFE(fname,EMsg[0]);
			tmp2[k2++]='\0';
			if(!(tmp=fget_line(fptr))) BFE(fname,EMsg[3]);
			marker[j].index=(int)strtol(tmp,&tmp1,16);
			tmp=tmp1;
			if(n_links>1) {
				if(*tmp++!=',') BFE(fname,EMsg[2]);
				loc->link_group=(int)strtol(tmp,&tmp1,16);
				tmp=tmp1;
			} else loc->link_group=0;
		 	if(loc->link_group<0 || loc->link_group>=n_links) BFE(fname,EMsg[2]);
			linkage[loc->link_group].n_markers++;
			if(*tmp++!=',') BFE(fname,EMsg[2]);
			loc->n_alleles=(int)strtol(tmp,&tmp1,16);
			tmp=tmp1;
			if(!loc->n_alleles) {
				if(*tmp!='\n') BFE(fname,EMsg[2]);
				marker[j].rec_flag=0;
				marker[j].recode=0;
				continue;
			}
			marker[j].recode=rtmp+k3;
			k3+=loc->n_alleles;
			if(k3>k1) BFE(fname,EMsg[0]);
			if(*tmp++!=',') BFE(fname,EMsg[2]);
			a=(int)strtol(tmp,&tmp1,16);
			if(*tmp1!='\n') BFE(fname,EMsg[2]);
			if(a) {
				if(!(tmp1=malloc((size_t)a))) ABT_FUNC(MMsg);
				RemBlock=AddRemem(tmp1,RemBlock);
				marker[j].rec_flag=ST_STRING;
				if(fread(tmp1,1,(size_t)a,fptr)!=(size_t)a) BFE(fname,EMsg[3]);
				for(a1=a2=0;a1<loc->n_alleles;a1++) {
					marker[j].recode[a1].string=tmp1+a2;
					while(a2<a && tmp1[a2]!='\n') a2++;
					if(a2>=a) BFE(fname,EMsg[0]);
					tmp1[a2++]='\0';
				}
			} else {
				marker[j].rec_flag=ST_INTEGER;
				for(a1=0;a1<loc->n_alleles;a1++) {
					if(!(tmp=fget_line(fptr))) BFE(fname,EMsg[3]);
					marker[j].recode[a1].value=(int)strtol(tmp,&tmp1,16);
					if(*tmp1!='\n') BFE(fname,EMsg[2]);
				}
			}
		}
		for(k1=k2=0,j=0;j<n_links;j++) {
			linkage[j].mk_index=mtmp+k1;
			k1+=linkage[j].n_markers;
			if(k1>n_markers) BFE(fname,EMsg[0]);
			linkage[j].n_markers=0;
		}
		for(j=0;j<n_markers;j++) {
			loc=&marker[j].locus;
			linkage[loc->link_group].mk_index[linkage[loc->link_group].n_markers++]=j;
		}
	}
	if(n_id_records) {
		if(!(id_variable=malloc(sizeof(struct Variable)*(n_id_records+n_nonid_records)))) ABT_FUNC(MMsg);
		if(n_nonid_records) nonid_variable=id_variable+n_id_records;
		if(!(tmp=fget_line(fptr))) BFE(fname,EMsg[3]);
		if(strncmp(tmp,"LKIR:",5)) BFE(fname,EMsg[0]);
		k=(int)strtol(tmp+5,&tmp1,16);
		if(*tmp1++!=',' || !k) BFE(fname,EMsg[2]);
		k1=(int)strtol(tmp1,&tmp,16);
		if(*tmp!='\n') BFE(fname,EMsg[2]);
		if(!(tmp2=malloc((size_t)k))) ABT_FUNC(MMsg);
		RemBlock=AddRemem(tmp2,RemBlock);
		if(k1) {
			if(!(rtmp=malloc(sizeof(union arg_type)*k1))) ABT_FUNC(MMsg);
			RemBlock=AddRemem(rtmp,RemBlock);
		}
		if(fread(tmp2,1,(size_t)k,fptr)!=(size_t)k) BFE(fname,EMsg[3]);
		for(k2=k3=j=0;j<n_id_records;j++) {
			id_variable[j].name=tmp2+k2;
			while(k2<k && tmp2[k2]!='\n') k2++;
			if(k2>=k) BFE(fname,EMsg[0]);
			tmp2[k2++]='\0';
			if(!(tmp=fget_line(fptr))) BFE(fname,EMsg[3]);
			id_variable[j].type=(int)strtol(tmp,&tmp1,16);
			if(*tmp1++!=',') BFE(fname,EMsg[2]);
			id_variable[j].index=(int)strtol(tmp1,&tmp,16);
			if(id_variable[j].type&ST_FACTOR) {	
				if(*tmp++!=',') BFE(fname,EMsg[2]);
				id_variable[j].n_levels=(int)strtol(tmp,&tmp1,16);
				tmp=tmp1;
				if(id_variable[j].n_levels) {
					id_variable[j].recode=rtmp+k3;
					k3+=id_variable[j].n_levels;
					if(k3>k1) BFE(fname,EMsg[0]);
					if(*tmp++!=',') BFE(fname,EMsg[2]);
					a=(int)strtol(tmp,&tmp1,16);
					if(*tmp1!='\n') BFE(fname,EMsg[2]);
					if(a)	{
						id_variable[j].rec_flag=ST_STRING;
						if(!(tmp1=malloc((size_t)a))) ABT_FUNC(MMsg);
						RemBlock=AddRemem(tmp1,RemBlock);
						if(fread(tmp1,1,(size_t)a,fptr)!=(size_t)a) BFE(fname,EMsg[3]);
						for(a1=a2=0;a1<id_variable[j].n_levels;a1++)	{
							id_variable[j].recode[a1].string=tmp1+a2;
							while(a2<a && tmp1[a2]!='\n') a2++;
							if(a2>=a) BFE(fname,EMsg[0]);
							tmp1[a2++]='\0';
						}
					} else {
						id_variable[j].rec_flag=ST_INTEGER;
						for(a1=0;a1<id_variable[j].n_levels;a1++)	{
							if(!(tmp=fget_line(fptr))) BFE(fname,EMsg[3]);
							id_variable[j].recode[a1].value=(int)strtol(tmp,&tmp1,16);
							if(*tmp1!='\n') BFE(fname,EMsg[2]);
						}
					}
				} else id_variable[j].recode=0;
			} else {
				id_variable[j].n_levels=0;
				id_variable[j].recode=0;
			}
		}
	}
	if(n_nonid_records) {
		if(!n_id_records) if(!(nonid_variable=malloc(sizeof(struct Variable)*n_nonid_records))) ABT_FUNC(MMsg);
		if(!(tmp=fget_line(fptr))) BFE(fname,EMsg[3]);
		if(strncmp(tmp,"LKNR:",5)) BFE(fname,EMsg[0]);
		k=(int)strtol(tmp+5,&tmp1,16);
		if(*tmp1++!=',' || !k) BFE(fname,EMsg[2]);
		k1=(int)strtol(tmp1,&tmp,16);
		if(*tmp!='\n') BFE(fname,EMsg[2]);
		if(!(tmp2=malloc((size_t)k))) ABT_FUNC(MMsg);
		RemBlock=AddRemem(tmp2,RemBlock);
		if(k1) {
			if(!(rtmp=malloc(sizeof(union arg_type)*k1))) ABT_FUNC(MMsg);
			RemBlock=AddRemem(rtmp,RemBlock);
		}
		if(fread(tmp2,1,(size_t)k,fptr)!=(size_t)k) BFE(fname,EMsg[3]);
		for(k2=k3=j=0;j<n_nonid_records;j++) {
			nonid_variable[j].name=tmp2+k2;
			while(k2<k && tmp2[k2]!='\n') k2++;
			if(k2>=k) BFE(fname,EMsg[0]);
			tmp2[k2++]='\0';
			if(!(tmp=fget_line(fptr))) BFE(fname,EMsg[3]);
			nonid_variable[j].type=(int)strtol(tmp,&tmp1,16);
			if(*tmp1++!=',') BFE(fname,EMsg[2]);
			nonid_variable[j].index=(int)strtol(tmp1,&tmp,16);
			if(nonid_variable[j].type&ST_FACTOR) {
				if(*tmp++!=',') BFE(fname,EMsg[2]);
				nonid_variable[j].n_levels=(int)strtol(tmp,&tmp1,16);
				tmp=tmp1;
				if(nonid_variable[j].n_levels) {
					nonid_variable[j].recode=rtmp+k3;
					k3+=nonid_variable[j].n_levels;
					if(k3>k1) BFE(fname,EMsg[0]);
					if(*tmp++!=',') BFE(fname,EMsg[2]);
					a=(int)strtol(tmp,&tmp1,16);
					if(*tmp1!='\n') BFE(fname,EMsg[2]);
					if(a) {
						nonid_variable[j].rec_flag=ST_STRING;
						if(!(tmp1=malloc((size_t)a))) ABT_FUNC(MMsg);
						RemBlock=AddRemem(tmp1,RemBlock);
						if(fread(tmp1,1,(size_t)a,fptr)!=(size_t)a) BFE(fname,EMsg[3]);
						for(a1=a2=0;a1<nonid_variable[j].n_levels;a1++)	{
							nonid_variable[j].recode[a1].string=tmp1+a2;
							while(a2<a && tmp1[a2]!='\n') a2++;
							if(a2>=a) BFE(fname,EMsg[0]);
							tmp1[a2++]='\0';
						}
					} else {
						nonid_variable[j].rec_flag=ST_INTEGER;
						for(a1=0;a1<nonid_variable[j].n_levels;a1++)	{
							if(!(tmp=fget_line(fptr))) BFE(fname,EMsg[3]);
							nonid_variable[j].recode[a1].value=(int)strtol(tmp,&tmp1,16);
							if(*tmp1!='\n') BFE(fname,EMsg[2]);
						}
					}
				} else nonid_variable[j].recode=0;
			} else {
				nonid_variable[j].n_levels=0;
				nonid_variable[j].recode=0;
			}
		}
	}
	if(n_models) {
		if(!(models=malloc(sizeof(struct Model)*n_models))) ABT_FUNC(MMsg);
		k=n_models*(n_models+1)/2;
		k1=2*k+n_models*5;
		if(!(residual_var=malloc(sizeof(double)*k1))) ABT_FUNC(MMsg);
		for(k2=0;k2<k1;k2++) residual_var[k2]=0.0;
		additive_var=residual_var+k;
		residual_var_limit=additive_var+k;
		additive_var_limit=residual_var_limit+n_models;
		grand_mean=additive_var_limit+n_models;
		tau=grand_mean+n_models;
		tau_beta=tau+n_models;
		for(k2=0;k2<n_models;k2++) tau_beta[k2]=2.0;
		if(!(res_var_set=malloc(sizeof(int)*n_models*3))) ABT_FUNC(MMsg);
		for(k2=0;k2<n_models*3;k2++) res_var_set[k2]=0;
		add_var_set=res_var_set+n_models;
		grand_mean_set=add_var_set+n_models;
		for(k3=k2=0;k2<n_models;k2++) {
			models[k2].polygenic_flag=0;
			if(!(tmp=fget_line(fptr))) BFE(fname,EMsg[3]);
			if(strncmp(tmp,"LKMD:",5)) BFE(fname,EMsg[0]);
			models[k2].var.type=(int)strtol(tmp+5,&tmp1,16);
			if(models[k2].var.type&ST_CENSORED) k3=1;
			if(*tmp1++!=',') BFE(fname,EMsg[2]);
			models[k2].var.var_index=(int)strtol(tmp1,&tmp,16);
			if(*tmp++!=',') BFE(fname,EMsg[2]);
			models[k2].n_terms=(int)strtol(tmp,&tmp1,16);
			if(*tmp1++!=',') BFE(fname,EMsg[2]);
			v2[0]=(int)strtol(tmp1,&tmp,16);
			if(*tmp++!='\n') BFE(fname,EMsg[2]);
			if(Check_Var(&models[k2].var)) BFE(fname,EMsg[0]);
			if(models[k2].n_terms<1 || v2[0]<models[k2].n_terms) BFE(fname,EMsg[0]);
			if(!(models[k2].term=malloc(sizeof(struct Model_Term)*models[k2].n_terms))) ABT_FUNC(MMsg);
			if(!(mvtmp=malloc(sizeof(struct Model_Var)*v2[0]))) ABT_FUNC(MMsg);
			RemBlock=AddRemem(mvtmp,RemBlock);
			for(k1=i=0;i<models[k2].n_terms;i++)	{
				if(!(tmp=fget_line(fptr))) BFE(fname,EMsg[3]);
				k=(int)strtol(tmp,&tmp1,16);
				models[k2].term[i].n_vars=k;
				models[k2].term[i].out_flag=0;
				models[k2].term[i].vars=mvtmp+k1;
				k1+=k;
				if(k1>v2[0]) BFE(fname,EMsg[0]);
				for(j=0;j<k;j++) {
					if(*tmp1++!=',') BFE(fname,EMsg[2]);
					models[k2].term[i].vars[j].type=(int)strtol(tmp1,&tmp,16);	
					if(*tmp++!=',') BFE(fname,EMsg[2]);
					if(models[k2].term[i].vars[j].type&ST_ID) {
						if(!polygenic_flag) BFE(fname,EMsg[2]);
						models[k2].polygenic_flag=1;
					}
					models[k2].term[i].vars[j].var_index=(int)strtol(tmp,&tmp1,16);	
					if(Check_Var(models[k2].term[i].vars+j)) BFE(fname,EMsg[0]);
				}
				if(*tmp1++!='\n') BFE(fname,EMsg[2]);
			}
		}
		k=(ped_size)*(1+k3)*n_models;
		if(!(td1=calloc((size_t)k,sizeof(void *)))) ABT_FUNC(MMsg);
		RemBlock=AddRemem(td1,RemBlock);
		if(polygenic_flag) {
			if(!(td2=malloc(sizeof(double)*ped_size*3*n_models))) ABT_FUNC(MMsg);
			RemBlock=AddRemem(td2,RemBlock);
		} else td2=0;
		for(j=0;j<ped_size;j++) {
			id_array[j].res=td1;
			td1+=n_models;
			if(k3) {
				id_array[j].cens=td1;
				td1+=n_models;
			}
			if(polygenic_flag) {
				id_array[j].bv=td2;
				id_array[j].bvsum=td2+n_models;
				id_array[j].bvsum2=td2+2*n_models;
				td2+=3*n_models;
			}
		}
	}
	if(!(tmp=fget_line(fptr))) BFE(fname,EMsg[3]);
	if(strncmp(tmp,"Ldat.end",8)) BFE(fname,EMsg[0]);
	if(fclose(fptr)) BFE(fname,0);
	free(fname);
	if(polygenic_flag) {
		fname=make_file_name(".nrm");
		fptr=open_readfile_and_check(fname);
		(void)printf("Reading from %s\n",fname);
		if(!(tmp=fget_line(fptr))) BFE(fname,EMsg[3]);
		if(strncmp(tmp,"Loki.nrm:",9)) BFE(fname,EMsg[0]);
		t_int=strtoul(tmp+9,&tmp1,16);
		if(t_int!=RunID) BFE(fname,"Binary files are from mixed runs");
		if(*tmp1++!=',') BFE(fname,EMsg[2]);
		v2[0]=(int)strtol(tmp1,&tmp,16);
		if(*tmp++!=',') BFE(fname,EMsg[2]);
		v2[1]=(int)strtol(tmp,&tmp1,16);
		if(*tmp1++!='\n') BFE(fname,EMsg[2]);
		if(v2[0]!=ped_size || v2[1]!=n_comp) BFE(fname,EMsg[2]);
		if(!(AIMatrix=malloc(sizeof(void *)*n_comp))) ABT_FUNC(MMsg);
		for(i=0;i<n_comp;i++) AIMatrix[i]=0;
		for(i=0;i<n_comp;i++) {
			if(!(tmp=fget_line(fptr))) BFE(fname,EMsg[3]);
			if(strncmp(tmp,"LKNM:",5)) BFE(fname,EMsg[0]);
			v2[0]=(int)strtol(tmp+5,&tmp1,16);
			if(*tmp1++!=',') BFE(fname,EMsg[2]);
			v2[1]=(int)strtol(tmp1,&tmp,16);
			if(*tmp++!='\n') BFE(fname,EMsg[2]);
			if(v2[0]!=comp_size[i] || v2[1]<=v2[0]) BFE(fname,EMsg[2]);
			if(!(AIMatrix[i]=malloc(sizeof(struct SparseMatRec)*v2[1]))) ABT_FUNC(MMsg);
			for(j=0;j<v2[1];j++) {
				if(!(tmp=fget_line(fptr))) BFE(fname,EMsg[3]);
				AIMatrix[i][j].x=(int)strtol(tmp,&tmp1,16);
				if(*tmp1++!=',') BFE(fname,EMsg[2]);
				if(txt_get_double(tmp1,&tmp,&AIMatrix[i][j].val)) BFE(fname,EMsg[2]);
				if(*tmp++!='\n') BFE(fname,EMsg[2]);
			}
		}
		if(!(tmp=fget_line(fptr))) BFE(fname,EMsg[3]);
		if(strncmp(tmp,"Lnrm.end",8)) BFE(fname,EMsg[0]);
		if(fclose(fptr)) BFE(fname,0);
		free(fname);
	}
	if(n_markers || tlocus_flag) {
		fname=make_file_name(".gen");
		fptr=open_readfile_and_check(fname);
		(void)printf("Reading from %s\n",fname);
		if(!(tmp=fget_line(fptr))) BFE(fname,EMsg[3]);
		if(strncmp(tmp,"Loki.gen:",9)) BFE(fname,EMsg[0]);
		t_int=strtoul(tmp+9,&tmp1,16);
		if(t_int!=RunID) BFE(fname,"Binary files are from mixed runs");
		for(i=0;i<3;i++) {
			if(*tmp1++!=',') BFE(fname,EMsg[2]);
			v2[i]=(int)strtol(tmp1,&tmp,16);
			tmp1=tmp;
		}
		if(*tmp1++!='\n') BFE(fname,EMsg[2]);
		extra_allele_flag=v2[2];
		if(v2[0]!=n_markers || v2[1]!=n_comp) BFE(fname,EMsg[2]);
		for(i=0;i<n_markers;i++) {
			loc=&marker[i].locus;
			marker[i].lumped=loc->n_alleles;
			if(!extra_allele_flag && loc->n_alleles) loc->n_alleles++;
		}
		if(eflag) {
			if(n_markers) {
				if(!(allele_trans=malloc(sizeof(void *)*n_markers))) ABT_FUNC(MMsg);
				if(!(allele_trans[0]=malloc(sizeof(void *)*n_markers*n_comp))) ABT_FUNC(MMsg);
				for(i=1;i<n_markers;i++) allele_trans[i]=allele_trans[i-1]+n_comp;
				for(i=j=0;i<n_markers;i++) j+=marker[i].locus.n_alleles;
				if(j) {
					if(!(allele_trans[0][0]=malloc(sizeof(int)*n_comp*j))) ABT_FUNC(MMsg);
					for(i=1;i<n_markers;i++) allele_trans[i][0]=allele_trans[i-1][0]+n_comp*marker[i-1].locus.n_alleles;
					for(i=0;i<n_markers;i++) for(j=1;j<n_comp;j++) allele_trans[i][j]=allele_trans[i][j-1]+marker[i].locus.n_alleles;
				}
			}
		} else {
			if(!(tvp=malloc(sizeof(void *)*(n_markers*6+tlocus_flag*2)))) ABT_FUNC(MMsg);
			all_set=tvp;
			all_set[0]=0;
			peelseq_head=(struct Peelseq_Head **)tvp+n_markers;
			peelseq_head[0]=0;
			allele_trans=(int ***)tvp+2*n_markers+tlocus_flag;
			allele_trans[0]=0;
			r_func=(struct R_Func ***)tvp+3*n_markers+tlocus_flag;
			r_func[0]=0;
			req_set[0]=(lk_ulong **)tvp+4*n_markers+2*tlocus_flag;
			if(n_markers) {
				if(!(req_set[0][0]=malloc(sizeof(lk_long)*n_markers*3*ped_size))) ABT_FUNC(MMsg);
				req_set[1]=req_set[0]+n_markers;
				req_set[1][0]=req_set[0][0]+n_markers*ped_size;
				for(i=1;i<n_markers;i++) for(j=0;j<2;j++) req_set[j][i]=req_set[j][i-1]+ped_size;
				if(!(allele_trans[0]=malloc(sizeof(void *)*n_markers*n_comp))) ABT_FUNC(MMsg);
				for(i=1;i<n_markers;i++) allele_trans[i]=allele_trans[i-1]+n_comp;
				for(i=j=0;i<n_markers;i++) j+=marker[i].locus.n_alleles;
				if(j) {
					if(!(allele_trans[0][0]=malloc(sizeof(int)*n_comp*j))) ABT_FUNC(MMsg);
					for(i=1;i<n_markers;i++) allele_trans[i][0]=allele_trans[i-1][0]+n_comp*marker[i-1].locus.n_alleles;
					for(i=0;i<n_markers;i++) for(j=1;j<n_comp;j++) allele_trans[i][j]=allele_trans[i][j-1]+marker[i].locus.n_alleles;
				}
				if(!(all_set[0]=malloc(sizeof(void *)*n_markers*ped_size))) ABT_FUNC(MMsg);
			}
			if(!(r_func[0]=malloc(sizeof(void *)*(n_markers+tlocus_flag)*n_comp))) ABT_FUNC(MMsg);
			if(!(peelseq_head[0]=calloc((size_t)(n_markers+tlocus_flag)*n_comp,sizeof(struct Peelseq_Head)))) ABT_FUNC(MMsg);
			if(!(comp_npeel=calloc((size_t)n_comp,sizeof(int)))) ABT_FUNC(MMsg);
			for(i=1;i<n_markers+tlocus_flag;i++) {
				if(i<n_markers) all_set[i]=all_set[i-1]+ped_size;
				r_func[i]=r_func[i-1]+n_comp;
				peelseq_head[i]=peelseq_head[i-1]+n_comp;
			}
			for(i=0;i<n_markers+tlocus_flag;i++) for(j=0;j<n_comp;j++) r_func[i][j]=0;
		}
		for(i=0;i<n_markers+tlocus_flag;i++) {
			if(i<n_markers) {
				n_all=marker[i].locus.n_alleles;
				if(n_all<2)	{
					for(comp=0;comp<n_comp;comp++) {
						marker[i].n_all1[comp]=n_all;
						if(!eflag) r_func[i][comp]=0;
					}
					continue;
				}
			} else n_all=2;
			if(!(tmp=fget_line(fptr))) BFE(fname,EMsg[3]);
			if(strncmp(tmp,"LKMK:",5)) BFE(fname,EMsg[0]);
			v2[0]=(int)strtol(tmp+5,&tmp1,16);
			if(*tmp1!='\n' || v2[0]!=n_all) BFE(fname,EMsg[2]);
			k2=0;
			for(k=comp=0;comp<n_comp;comp++) {
				if(!eflag) {
					pp=peelseq_head[i]+comp;
					r_func[i][comp]=0;
				}
				if(!(tmp=fget_line(fptr))) BFE(fname,EMsg[3]);
				if(strncmp(tmp,"LKCM:",5)) BFE(fname,EMsg[0]);
				tmp1=tmp+5;
				for(j=0;j<5;j++) {
					if(j && *tmp1++!=',') BFE(fname,EMsg[2]);
					v2[j]=(int)strtol(tmp1,&tmp,16);
					tmp1=tmp;
				}
				if(*tmp!='\n' || v2[0]!=comp || v2[1]!=comp_size[comp] || v2[4]>v2[1]) BFE(fname,EMsg[2]);
				if(i<n_markers) marker[i].n_all1[comp]=v2[2];
				if(v2[2]<2 || !v2[4]) {
					/* Everyone in the component is pruned */
					for(j=0;j<comp_size[comp];j++) id_array[k++].pruned_flag[i]=1;
					continue;
				}
				if(i<n_markers) {
					if(!(tl=malloc(sizeof(lk_long)*v2[4]*v2[2]))) ABT_FUNC(MMsg);
					RemBlock=AddRemem(tl,RemBlock);
					if(v2[2]!=n_all) {
						if(!(tmp=fget_line(fptr))) BFE(fname,EMsg[3]);
						for(j=0;j<n_all;j++) {
							if(j && *tmp++!=',') BFE(fname,EMsg[2]);
							allele_trans[i][comp][j]=(int)strtol(tmp,&tmp1,10);
							tmp=tmp1;
						}
						if(*tmp!='\n') BFE(fname,EMsg[2]);
					} else for(j=0;j<n_all;j++) allele_trans[i][comp][j]=j;
				} else tl=0;
				for(j=0;j<comp_size[comp];j++) {
					if(!(tmp=fget_line(fptr))) BFE(fname,EMsg[3]);
					id_array[k+j].pruned_flag[i]=(int)strtol(tmp,&tmp1,16);
					if(i!=n_markers && !eflag) {
						all_set[i][k+j]=0;
						req_set[0][i][k+j]=req_set[1][i][k+j]=0;
						if(!id_array[k+j].pruned_flag[i]) {
							all_set[i][k+j]=tl;
							for(k1=0;k1<v2[2];k1++) {
								if(*tmp1++!=',') {
									if(!eflag && tmp1[-1]=='\n') BFE(fname,"File appears to be for Fenris.  Do not use prep -e to prepare datafiles for Loki");
									BFE(fname,EMsg[2]);
								}
#ifdef USE_LONGLONG
								tl[k1]=strtoll(tmp1,&tmp,16);
#else
								tl[k1]=strtol(tmp1,&tmp,16);
#endif
								tmp1=tmp;
							}
							if(v2[3]) {	
								if(*tmp1++!=',') BFE(fname,EMsg[2]);
#ifdef USE_LONGLONG
								req_set[0][i][k+j]=strtoll(tmp1,&tmp,16);
#else
								req_set[0][i][k+j]=strtol(tmp1,&tmp,16);
#endif
								if(*tmp++!=',') BFE(fname,EMsg[2]);
#ifdef USE_LONGLONG
								req_set[1][i][k+j]=strtoll(tmp,&tmp1,16);
#else
								req_set[1][i][k+j]=strtol(tmp,&tmp1,16);
#endif
							}
							tl+=v2[2];
						}
					}
					if(*tmp1!='\n') {
						if(*tmp1==',' && eflag) BFE(fname,"File appears to be for Loki.  Use prep -e to prepare datafiles for Fenris");
						BFE(fname,EMsg[2]);
					}
				}
				k+=j;
				if(!eflag) {
					if(!(tmp=fget_line(fptr))) BFE(fname,EMsg[3]);
					if(strncmp(tmp,"LKPL\n",5)) BFE(fname,EMsg[0]);
					for(;;) {
						if(!(tmp=fget_line(fptr))) BFE(fname,EMsg[3]);	
						v2[0]=(int)strtol(tmp,&tmp1,16);
						if(!v2[0]) break;
						comp_npeel[comp]++;
						if(v2[0]==PEEL_SIMPLE) {
							pp->type=PEEL_SIMPLE;
							if(!(simple_em=malloc(sizeof(struct Simple_Element)))) ABT_FUNC(MMsg);
							pp->ptr.simple=simple_em;
							if(*tmp1++!=',') BFE(fname,EMsg[2]);
							simple_em->sire=(int)strtol(tmp1,&tmp,16);
							if(*tmp++!=',') BFE(fname,EMsg[2]);
							simple_em->dam=(int)strtol(tmp,&tmp1,16);
							if(*tmp1++!=',') BFE(fname,EMsg[2]);
							simple_em->n_off=(int)strtol(tmp1,&tmp,16);
							if(*tmp++!=',') BFE(fname,EMsg[2]);
							simple_em->pivot=(int)strtol(tmp,&tmp1,10);
							if(*tmp1++!=',') BFE(fname,EMsg[2]);
							simple_em->out_index=(int)strtol(tmp1,&tmp,10);
							j=simple_em->n_off;
							if(j<1) BFE(fname,EMsg[2]);
							if(j>max_peel_off) max_peel_off=j;
							if(!(simple_em->off=malloc(sizeof(int)*j))) ABT_FUNC(MMsg);
							for(k1=0;k1<j;k1++) {
								if(*tmp++!=',') break;
								simple_em->off[k1]=(int)strtol(tmp,&tmp1,16);
								tmp=tmp1;
							}
							if(simple_em->sire<0 || simple_em->dam<0 || k1<j) BFE(fname,EMsg[2]);
							pp= &simple_em->next;
							pp->type=0;
						} else {
							pp->type=PEEL_COMPLEX;
							if(!(complex_em=malloc(sizeof(struct Complex_Element)))) ABT_FUNC(MMsg);
							pp->ptr.complex=complex_em;
							if(*tmp1++!=',') BFE(fname,EMsg[2]);
							complex_em->n_peel=(int)strtol(tmp1,&tmp,16);
							if(*tmp++!=',') BFE(fname,EMsg[2]);
							complex_em->n_involved=(int)strtol(tmp,&tmp1,16);
							if(*tmp1++!=',') BFE(fname,EMsg[2]);
							complex_em->out_index=(int)strtol(tmp1,&tmp,10);
							if(*tmp++!=',') BFE(fname,EMsg[2]);
							complex_em->n_rfuncs=(int)strtol(tmp,&tmp1,16);
							j=complex_em->n_involved*2+complex_em->n_rfuncs;
							if(!(complex_em->involved=malloc(sizeof(int)*j))) ABT_FUNC(MMsg);
							for(k1=0;k1<complex_em->n_involved;k1++) {
								tmp=tmp1;
								if(*tmp++!=',') break;
								complex_em->involved[k1]=(int)strtol(tmp,&tmp1,10);
							}
							for(;k1<j;k1++) {
								tmp=tmp1;
								if(*tmp++!=',') break;
								complex_em->involved[k1]=(int)strtol(tmp,&tmp1,16);
							}
							j=complex_em->n_involved;
							complex_em->flags=complex_em->involved+j;
							complex_em->index=complex_em->flags+j;
							pp= &complex_em->next;
							pp->type=0;
						}
						if(*tmp1!='\n') BFE(fname,EMsg[2]);
					}
					if(*tmp1++!=',') BFE(fname,EMsg[2]);
					v2[0]=(int)strtol(tmp1,&tmp,16);
					if(*tmp!='\n') BFE(fname,EMsg[2]);
					if(v2[0]) {
						if(!(r_func[i][comp]=malloc(sizeof(struct R_Func)*v2[0]))) ABT_FUNC(MMsg);
						for(j=0;j<v2[0];j++) {
							if(!(tmp=fget_line(fptr))) BFE(fname,EMsg[3]);
							r_func[i][comp][j].id_list=0;
							r_func[i][comp][j].flag=0;
							r_func[i][comp][j].n_ind=(int)strtol(tmp,&tmp1,16);
							if(*tmp1++!=',') BFE(fname,EMsg[2]);
							r_func[i][comp][j].n_terms=(int)strtol(tmp1,&tmp,16);
							r_func[i][comp][j].flag=1;
							k1=r_func[i][comp][j].n_ind;
							if(!(r_func[i][comp][j].id_list=malloc(sizeof(int)*k1))) ABT_FUNC(MMsg);
							RemBlock=AddRemem(r_func[i][comp][j].id_list,RemBlock);
							for(k2=0;k2<k1;k2++) {
								tmp1=tmp;
								if(*tmp1++!=',') BFE(fname,EMsg[2]);
								r_func[i][comp][j].id_list[k2]=(int)strtol(tmp1,&tmp,10);
							}
							if(*tmp!='\n') BFE(fname,EMsg[2]);
						}
					}
				}
			}
		}
		if(!(tmp=fget_line(fptr))) BFE(fname,EMsg[3]);
		if(strncmp(tmp,"Lgen.end",8)) BFE(fname,EMsg[0]);
		if(fclose(fptr)) BFE(fname,0);
		free(fname);
	}
	(void)fget_line(0);
	signal(SIGCHLD,SIG_DFL);
	while(waitpid(-1,&i,WNOHANG)>0);
}
