/* This file contains input code for  a */
/* modified version of the LODSCORE program */
/* described in the papers: */
/* R. W. Cottingham Jr., R. M. idury, and A. A. Schaffer */
/* Faster Sequential Genetic Linkage Computations */
/* American Journal of Human Gentics, 53(1993), pp. 252-263 */
/* and A. A. Schaffer, S. K. Gupta, K. Shriram, and R. W. Cottingham, Jr., */
/* Avoiding Recomputation in Genetic Linkage Analysis, */
/* Human Heredity 44(1994), pp. 225-237. */

#include "commondefs.h"
#if !defined(DOS)
#include "checkpointdefs.h"
#endif
#include "gemdefs.h"
#include "lodefs.h"


Void setparam()
{
  long i, j, k, l, m;
  thetavalues *WITH;
  long FORLIM;
  locusvalues *WITH1;
  thisarray *WITH2;
  long FORLIM1, FORLIM2;

  penalty = false;
  k = 0;
  WITH = maletheta;
  FORLIM = mlocus - 2;
  for (i = 0; i <= FORLIM; i++) {
    k++;
    WITH->theta[i] = xall[k - 1];
  }
  if (sexdif) {
    if (readfemale) {
      WITH = femaletheta;
      FORLIM = mlocus - 2;
      for (i = 0; i <= FORLIM; i++) {
	k++;
	WITH->theta[i] = xall[k - 1];
      }
    } else {
      k++;
      distratio = xall[k - 1];
    }
  }
  if (itsys == 0)
    return;
  WITH1 = thislocus[itsys - 1];
  if (disequi) {
    WITH2 = hapfreq;
    FORLIM = nuhap;
    for (i = 0; i < FORLIM; i++)
      WITH2->genarray[i] = xall[i + k];
    WITH2->genarray[nuhap - 1] = 1.0;
    FORLIM = nuhap - 2;
    for (i = 0; i <= FORLIM; i++)
      WITH2->genarray[nuhap - 1] -= WITH2->genarray[i];
    penalty = (WITH2->genarray[nuhap - 1] < 0.0);
    k += nuhap - 1;
  } else {
    FORLIM = WITH1->nallele - 2;
    for (i = 0; i <= FORLIM; i++)
      WITH1->freq[i] = xall[i + k];
    WITH1->freq[WITH1->nallele - 1] = 1.0;
    FORLIM = WITH1->nallele - 2;
    for (i = 0; i <= FORLIM; i++)
      WITH1->freq[WITH1->nallele - 1] -= WITH1->freq[i];
    penalty = (WITH1->freq[WITH1->nallele - 1] < 0.0);
    k += WITH1->nallele - 1;
  }
  if (WITH1->which == affection) {
    FORLIM = WITH1->UU.U0.nclass;
    for (l = 0; l < FORLIM; l++) {
      FORLIM1 = WITH1->nallele;
      for (i = 1; i <= FORLIM1; i++) {
	FORLIM2 = WITH1->nallele;
	for (j = i; j <= FORLIM2; j++) {
	  k++;
	  WITH1->UU.U0.pen[i][j - 1][2][l] = xall[k - 1];
	  WITH1->UU.U0.pen[i][j - 1][1][l] = 1.0 - xall[k - 1];
	  for (m = 0; m <= 2; m++)
	    WITH1->UU.U0.pen[j][i - 1][m][l] = WITH1->UU.U0.pen[i][j - 1][m]
	      [l];
	}
      }
      if (sexlink) {
	FORLIM1 = WITH1->nallele;
	for (i = 0; i < FORLIM1; i++) {
	  k++;
	  WITH1->UU.U0.pen[0][i][2][l] = xall[k - 1];
	  WITH1->UU.U0.pen[0][i][1][l] = 1.0 - xall[k - 1];
	}
      }
    }
    return;
  }
  if (WITH1->which != quantitative)
    return;
  FORLIM = WITH1->UU.U1.ntrait;
  /*USER MUST CHANGE FOR SYSTEMS WITH MORE THAN 2 ALLELES*/
  for (i = 0; i < FORLIM; i++) {
    WITH1->UU.U1.pm[1][0][i] = xall[k];
    WITH1->UU.U1.pm[2][1][i] = xall[k + 1] + xall[k];
    WITH1->UU.U1.pm[1][1][i] = xall[k + 2] * xall[k + 1] + xall[k];
    WITH1->UU.U1.pm[0][0][i] = xall[k];
    WITH1->UU.U1.pm[0][1][i] = WITH1->UU.U1.pm[1][1][i];
    WITH1->UU.U1.pm[2][0][i] = WITH1->UU.U1.pm[1][1][i];
    k += 3;
  }
  FORLIM = WITH1->UU.U1.ntrait;
  for (i = 0; i < FORLIM; i++) {
    FORLIM1 = WITH1->UU.U1.ntrait;
    for (j = i; j < FORLIM1; j++) {
      k++;
      WITH1->UU.U1.vmat[i][j] = xall[k - 1];
      WITH1->UU.U1.vmat[j][i] = xall[k - 1];
    }
  }
  invert(WITH1->UU.U1.vmat, WITH1->UU.U1.ntrait, &WITH1->UU.U1.det);
  WITH1->UU.U1.det = 1 / sqrt(WITH1->UU.U1.det);
}


/* Local variables for getlocations: */
struct LOC_getlocations {
  long ngene, nseg, here, there, start, nhet, thisseg;
  boolean rarepresent, riskhom, riskhet;
  hapvector hap1, hap2;
  boolean thishet[maxlocus];
} ;

Local boolean checkrare(LINK)
struct LOC_getlocations *LINK;
{
  long i;
  boolean check;
  locusvalues *WITH;

  check = false;
  for (i = 0; i < mlocus; i++) {
    if (nohom[i]) {
      WITH = thislocus[i];
      if (WITH->freq[LINK->hap1[i] - 1] < minfreq ||
	  WITH->freq[LINK->hap2[i] - 1] < minfreq)
	check = true;
    }
  }
  return check;
}

Local Void checkrisk(riskhet, riskhom, LINK)
boolean *riskhet, *riskhom;
struct LOC_getlocations *LINK;
{
  *riskhet = false;
  *riskhom = false;
  if (LINK->hap1[risksys - 1] == riskall && LINK->hap2[risksys - 1] == riskall)
    *riskhom = true;
  else {
    if ((LINK->hap1[risksys - 1] != riskall &&
	 LINK->hap2[risksys - 1]  == riskall) ||
	(LINK->hap2[risksys - 1] != riskall &&
	 LINK->hap1[risksys - 1] == riskall))
      *riskhet = true;
  }
}

Local long gethapn(hap, LINK)
hapvector hap;
struct LOC_getlocations *LINK;
{
  long i, n;

  n = 1;
  for (i = 0; i < mlocus; i++)
    n += increment[i] * (hap[i] - 1);
  return n;
}

/* Local variables for domalerisk: */
struct LOC_domalerisk {
  struct LOC_getlocations *LINK;
} ;

Local Void setrisk(LINK)
struct LOC_domalerisk *LINK;
{
  long n;

  n = gethapn(LINK->LINK->hap1, LINK->LINK);
  if (LINK->LINK->hap1[risksys - 1] == riskall)
    riskmale[n - 1] = true;
  else
    riskmale[n - 1] = false;
}

Local Void getriskhap(system, LINK)
long system;
struct LOC_domalerisk *LINK;
{
  long i;
  locusvalues *WITH;
  long FORLIM;

  WITH = thislocus[system - 1];
  FORLIM = WITH->nallele;
  for (i = 1; i <= FORLIM; i++) {
    LINK->LINK->hap1[system - 1] = i;
    if (system != mlocus)
      getriskhap(system + 1, LINK);
    else
      setrisk(LINK);
  }
}

Local Void domalerisk(LINK)
struct LOC_getlocations *LINK;
{
  struct LOC_domalerisk V;

  V.LINK = LINK;
  getriskhap(1L, &V);
}

/* Local variables for domutation: */
struct LOC_domutation {
  struct LOC_getlocations *LINK;
} ;

Local Void setmutation(LINK)
struct LOC_domutation *LINK;
{
  long i, n;

  n = gethapn(LINK->LINK->hap1, LINK->LINK);
  if (LINK->LINK->hap1[mutsys - 1] ==
      thislocus[mutsys - 1]->nallele) {
    muthap[n - 1] = n;
    return;
  }
  i = LINK->LINK->hap1[mutsys - 1];
  LINK->LINK->hap1[mutsys - 1] = thislocus[mutsys - 1]->nallele;
  muthap[n - 1] = gethapn(LINK->LINK->hap1, LINK->LINK);
  LINK->LINK->hap1[mutsys - 1] = i;
}

Local Void getmuthap(system, LINK)
long system;
struct LOC_domutation *LINK;
{
  long i;
  locusvalues *WITH;
  long FORLIM;

  WITH = thislocus[system - 1];
  FORLIM = WITH->nallele;
  for (i = 1; i <= FORLIM; i++) {
    LINK->LINK->hap1[system - 1] = i;
    if (system != mlocus)
      getmuthap(system + 1, LINK);
    else
      setmutation(LINK);
  }
}

Local Void domutation(LINK)
struct LOC_getlocations *LINK;
{
  struct LOC_domutation V;

  V.LINK = LINK;
  getmuthap(1L, &V);
}

Local Void setnumbers(LINK)
struct LOC_getlocations *LINK;
{
  long nhap1, nhap2;

  LINK->ngene++;

  segstart[LINK->ngene - 1] = LINK->here + 1;
  probstart[LINK->ngene - 1] = LINK->there + 1;
  probend[LINK->ngene - 1] = LINK->there + LINK->nseg;

  LINK->there += LINK->nseg;

  nhap1 = gethapn(LINK->hap1, LINK);
  nhap2 = gethapn(LINK->hap2, LINK);
  genenumber[nhap1 - 1][nhap2 - 1] = LINK->ngene;
  genenumber[nhap2 - 1][nhap1 - 1] = LINK->ngene;

  if (minfreq != 0.0) {
    if (LINK->rarepresent)
      rare[LINK->ngene - 1] = true;
    else
      rare[LINK->ngene - 1] = false;
  } else
    rare[LINK->ngene - 1] = false;
  if (risk) {
    risk1[LINK->ngene - 1] = LINK->riskhet;
    risk2[LINK->ngene - 1] = LINK->riskhom;
  }

  LINK->thisseg++;
  invgenenum1[LINK->thisseg - 1] = nhap1;
  invgenenum2[LINK->thisseg - 1] = nhap2;
}

Local Void hapscr(system, nscramble, LINK)
long system, nscramble;
struct LOC_getlocations *LINK;
{
  long i, j;

  if (LINK->thishet[system - 1])
    nscramble++;
  if (system != mlocus)
    hapscr(system + 1, nscramble, LINK);
  else
    setnumbers(LINK);
  if (nscramble <= 1)
    return;
  if (LINK->hap1[system - 1] == LINK->hap2[system - 1])
    return;
  i = LINK->hap1[system - 1];
  j = LINK->hap2[system - 1];
  LINK->hap1[system - 1] = j;
  LINK->hap2[system - 1] = i;
  if (system != mlocus)
    hapscr(system + 1, nscramble, LINK);
  else
    setnumbers(LINK);
  LINK->hap1[system - 1] = i;
  LINK->hap2[system - 1] = j;
}

Local Void sethap(system, LINK)
long system;
struct LOC_getlocations *LINK;
{
  long i, j;
  locusvalues *WITH;
  long FORLIM, FORLIM1;

  WITH = thislocus[system - 1];
  if (LINK->thishet[system - 1]) {
    FORLIM = WITH->nallele;
    for (i = 1; i < FORLIM; i++) {
      LINK->hap1[system - 1] = i;
      FORLIM1 = WITH->nallele;
      for (j = i + 1; j <= FORLIM1; j++) {
	LINK->hap2[system - 1] = j;
	if (system != mlocus)
	  sethap(system + 1, LINK);
	else {
	  LINK->rarepresent = checkrare(LINK);
	  if (risk)
	    checkrisk(&LINK->riskhet, &LINK->riskhom, LINK);
	  LINK->there = LINK->start;
	  LINK->thisseg = LINK->here;
	  hapscr(1L, 0L, LINK);
	  LINK->here += LINK->nseg;
	}
      }
    }
    return;
  }
  FORLIM = WITH->nallele;
  for (i = 1; i <= FORLIM; i++) {
    LINK->hap1[system - 1] = i;
    LINK->hap2[system - 1] = i;
    if (system != mlocus)
      sethap(system + 1, LINK);
    else {
      LINK->rarepresent = checkrare(LINK);
      if (risk)
	checkrisk(&LINK->riskhet, &LINK->riskhom, LINK);
      LINK->thisseg = LINK->here;
      LINK->there = LINK->start;
      hapscr(1L, 0L, LINK);
      LINK->here += LINK->nseg;
    }
  }
}

Local Void starthap(LINK)
struct LOC_getlocations *LINK;
{
  long i, FORLIM;

  LINK->nseg = 1;
  FORLIM = LINK->nhet;
  for (i = 2; i <= FORLIM; i++)
    LINK->nseg *= 2;
  sethap(1L, LINK);
  LINK->start = LINK->there;
}

Local Void gethet1(system, LINK)
long system;
struct LOC_getlocations *LINK;
{
  LINK->thishet[system - 1] = false;
  if (system != mlocus)
    gethet1(system + 1, LINK);
  else
    starthap(LINK);
  LINK->thishet[system - 1] = true;
  LINK->nhet++;
  if (system != mlocus)
    gethet1(system + 1, LINK);
  else
    starthap(LINK);
  LINK->nhet--;
}


Void getlocations()
{
  struct LOC_getlocations V;

  V.nhet = 0;
  V.here = 0;
  V.there = 0;
  V.ngene = 0;
  V.start = 0;
  gethet1(1L, &V);
  if (mutsys != 0)
    domutation(&V);
  if (sexlink && risk)
    domalerisk(&V);
}


typedef enum {
  nobnd, probnd, zerobnd, logbnd
} boundary;


Void setiterate()
{
  boundary bndtype[maxn];
  long i, j, k, l;
  thetavalues *WITH;
  long FORLIM;
  locusvalues *WITH1;
  long FORLIM1, FORLIM2;

  k = 0;
  WITH = maletheta;
  FORLIM = nlocus - 2;
  for (i = 0; i <= FORLIM; i++) {
    k++;
    xall[k - 1] = WITH->theta[i];
    if (interfer && !mapping)
      bndtype[k - 1] = logbnd;
    else
      bndtype[k - 1] = probnd;
  }
  if (sexdif) {
    if (readfemale) {
      WITH = femaletheta;
      FORLIM = nlocus - 2;
      for (i = 0; i <= FORLIM; i++) {
	k++;
	xall[k - 1] = WITH->theta[i];
	bndtype[k - 1] = probnd;
      }
    } else {
      k++;
      xall[k - 1] = distratio;
      bndtype[k - 1] = zerobnd;
    }
  }
  nall = k;
  if (itsys != 0) {
   /*AAS, if we are estimating allele frequencies, then the
     improvements under the guise of ALLELE_SPEED cannot be applied*/
    if (ALLELE_SPEED) {
      fprintf(stderr,"\nYou are attempting to estimate allele frequencies.");
      fprintf(stderr,"\nYou must have ALLELE_SPEED set to  0 in");
      fprintf(stderr,"\ncommondefs.h, so that your alleles");
      fprintf(stderr,"\nare not mutated, then recompile LODSCORE.");
      fprintf(stderr,"\nFASTLINK will exit politely to allow you to change ALLELE_SPEED");
      exit(EXIT_FAILURE);
    }

    WITH1 = thislocus[itsys - 1];
    if (disequi) {
      FORLIM = nuhap - 2;
      for (i = 0; i <= FORLIM; i++)
	xall[i + k] = hapfreq->genarray[i];
      nall = nuhap + k - 1;
    } else {
      FORLIM = WITH1->nallele - 2;
      for (i = 0; i <= FORLIM; i++)
	xall[i + k] = WITH1->freq[i];
      nall = WITH1->nallele + k - 1;
    }
    FORLIM = nall;
    for (i = k; i < FORLIM; i++)
      bndtype[i] = probnd;
    k = nall;

    if (WITH1->which == quantitative) {
      nall += WITH1->UU.U1.ntrait * (WITH1->UU.U1.ntrait + 1) / 2 +
	      WITH1->UU.U1.ntrait * 3;

    } else {
      if (WITH1->which == affection) {
	nall += WITH1->UU.U0.nclass * WITH1->nallele * (WITH1->nallele + 1) / 2;
	if (sexlink)
	  nall += WITH1->nallele;
      }
    }

    if (WITH1->which == affection) {
      FORLIM = WITH1->UU.U0.nclass;
      for (l = 0; l < FORLIM; l++) {
	FORLIM1 = WITH1->nallele;
	for (i = 1; i <= FORLIM1; i++) {
	  FORLIM2 = WITH1->nallele;
	  for (j = i - 1; j < FORLIM2; j++) {
	    k++;
	    xall[k - 1] = WITH1->UU.U0.pen[i][j][2][l];
	    bndtype[k - 1] = probnd;
	  }
	}
	if (sexlink) {
	  FORLIM1 = WITH1->nallele;
	  for (i = 0; i < FORLIM1; i++) {
	    k++;
	    xall[k - 1] = WITH1->UU.U0.pen[0][i][2][l];
	    bndtype[k - 1] = probnd;
	  }
	}
      }
    } else {
      if (WITH1->which == quantitative) {
	invert(WITH1->UU.U1.vmat, WITH1->UU.U1.ntrait, &WITH1->UU.U1.det);
	FORLIM = WITH1->UU.U1.ntrait;
	/*USER MUST MODIFY FOR A SYSTEM WILL MORE THAN 2 ALLELES */
	for (l = 0; l < FORLIM; l++) {
	  FORLIM1 = WITH1->nallele;
	  for (i = 1; i <= FORLIM1; i++) {
	    FORLIM2 = WITH1->nallele;
	    for (j = i; j <= FORLIM2; j++) {
	      k++;
	      if (i == 1 && j == 1)
		xall[k - 1] = WITH1->UU.U1.pm[i][j - 1][l];
	      else {
		if (i == 1)
		  xall[k - 1] = WITH1->UU.U1.pm[j][j - 1][l] - xall[k - 2];
		else
		  xall[k - 1] = (WITH1->UU.U1.pm[i - 1][j - 1]
				 [l] - xall[k - 3]) / xall[k - 2];
	      }
	      bndtype[k - 1] = nobnd;
	    }
	  }
	}
	FORLIM = WITH1->UU.U1.ntrait;
	for (i = 1; i <= FORLIM; i++) {
	  FORLIM1 = WITH1->UU.U1.ntrait;
	  for (j = i; j <= FORLIM1; j++) {
	    k++;
	    xall[k - 1] = WITH1->UU.U1.vmat[i - 1][j - 1];
	    if (i == j)
	      bndtype[k - 1] = zerobnd;
	    else
	      bndtype[k - 1] = nobnd;
	  }
	}
      }
    }

  }
  nall = k;
  n = 0;
  for (i = 0; i < nall; i++) {
    if (itp[i] == 1) {
      n++;
      x[n - 1] = xall[i];
    }
  }
  for (i = 0; i < nall; i++) {
    bnd[i][0] = -1000.0;
    bnd[i][1] = 1000.0;
    if (bndtype[i] == probnd) {
      bnd[i][0] = 0.0;
      bnd[i][1] = 1.0;
    } else {
      if (bndtype[i] == logbnd) {
	bnd[i][0] = -20.0;
	bnd[i][1] = 20.0;
      } else {
	if (bndtype[i] == zerobnd)
	  bnd[i][0] = 0.0;
      }
    }
  }
}


Void inputerror(nerror, par1, par2, LINK)
long nerror, par1, par2;
struct LOC_inputdata *LINK;
{
  printf("Fatal error detected in procedure inputdata\n");
  switch (nerror) {

  case 0:
    printf("Number of loci %2ld exceeds the constant maxsys\n", par1);
    break;

  case 1:
    printf("Number of loci read %2ld. Less than minimum of 1\n", par1);
    break;

  case 2:
    printf(
      "Error detected reading loci order. Locus number %2ld in position %2ld exceeds number of loci\n",
      par2, par1);
    break;

  case 3:
    printf(
      "Error detected reading loci order. Illegal locus number %2ld in position %2ld\n",
      par2, par1);
    break;

  case 4:
    printf(
      "Error detected reading loci order. Locus number repeated in positions %2ld and %2ld\n",
      par1, par2);
    break;

  case 5:
    printf(
      "Error detected reading locus description. Illegal locus type %2ld for locus %2ld\n",
      par2, par1);
    break;

  case 6:
    printf(
      "Error detected reading locus description for system %2ld. Number of alleles  %2ld exceeds maxall\n",
      par1, par1);
    break;

  case 7:
    printf(
      "Error detected reading locus description for system %2ld. Illegal number of alleles  %2ld\n",
      par1, par2);
    break;

  case 8:
    printf(
      "Error detected reading locus description for system %2ld.\n Number of factors  %2ld exceeds maxfact or length of a long int\n",
      par1, par2);
    break;

  case 9:
    printf(
      "Error detected reading locus description for system %2ld. Illegal number of factors  %2ld\n",
      par1, par2);
    break;

  case 10:
    printf(
      "Error detected reading locus description for system %2ld. Alleles not codominant\n",
      par1);
    break;

  case 11:
    printf("Error detected reading pedigree record %2ld. Illegal code for sex %2ld\n",
	   par1, par2);
    break;

  case 12:
    printf(
      "Error detected reading pedigree record at pedigree%2ld. Maximum number of pedigree records exceeded\n",
      par1);
    break;

  case 13:
    printf(
      "Error detected reading pedigree record %2ld. Maximum number of individuals exceeded\n",
      par1);
    break;

  case 14:
    printf(
      "Error detected reading pedigree record %2ld. Illegal binary factor code %2ld\n",
      par1, par2);
    break;

  case 15:
    printf(
      "Error detected reading pedigree record %2ld. No allelic pair for genotype\n",
      par1);
    break;

  case 16:
    printf(
      "Error detected reading pedigree record %2ld. Allele number %2ld exceeds maxall\n",
      par1, par2);
    break;

  case 17:
    printf(
      "Error detected reading pedigree record %2ld. Illegal allele number %2ld\n",
      par1, par2);
    break;

  case 18:
    printf("Number of systems after factorization (%3ld) exceeds maxsystem\n",
	   par1);
    break;

  case 19:
    printf("Number of systems after factorization (%3ld) less than minimum of 1\n",
	   par1);
    break;

  case 20:
    printf("Number of recombination types (%3ld) exceeds maxrectype\n", par1);
    break;

  case 21:
    printf("Number of recombination types (%3ld) less than minimum of 1\n",
	   par1);
    break;

  case 22:
    printf(
      "End of file detected in tempdat by procedure readthg before all data found\n");
    break;

  case 23:
    printf(
      "Error detected reading iterated locus in datafile. Value (%3ld) greater than nlocus\n",
      par1);
    break;

  case 24:
    printf(
      "Error detected reading iterated locus in datafile. Illegal value (%3ld)\n",
      par1);
    break;

  case 25:
    printf("Number of iterated parameters greater then maxn\n");
    break;

  case 26:
    printf(
      "Error detected reading pedigree record %2ld. Liability class (%2ld) exceeds nclass\n",
      par1, par2);
    break;

  case 27:
    printf(
      "Error detected reading pedigree record %2ld. Illegal liability class (%2ld)\n",
      par1, par2);
    break;

  case 28:
    printf(
      "Error detected reading locus description for system%2ld. Liability classes (%3ld) exceed maxliab\n",
      par1, par2);
    break;

  case 29:
    printf(
      "Error detected reading locus description for system%2ld. Illegal number of liability classes (%3ld)\n",
      par1, par2);
    break;

  case 30:
    printf(
      "Error detected reading locus description for system%2ld. Penetrance out of range\n",
      par1);
    break;

  case 31:
    printf(
      "Error detected reading locus description for system%2ld. Number of traits (%3ld) exceeds maxtrait\n",
      par1, par2);
    break;

  case 32:
    printf(
      "Error detected reading locus description for system%2ld. Number of traits out of range (%3ld)\n",
      par1, par2);
    break;

  case 33:
    printf(
      "Error detected reading locus description for system%2ld. Variance must be positive\n",
      par1);
    break;

  case 34:
    printf(
      "Error detected reading locus description for system%2ld. Variance multiplier must be positive\n",
      par1);
    break;

  case 35:
    printf(
      "Error detected reading locus description for system%2ld. Risk allele %3ld) exceeds nallele\n",
      par1, par2);
    break;

  case 36:
    printf(
      "Error detected reading locus description for system%2ld. Illegal risk allele (%3ld)\n",
      par1, par2);
    break;

  case 37:
    printf("Error detected reading datafile. Risk locus %3ld) exceeds nlocus\n",
	   par2);
    break;

  case 38:
    printf("Error detected reading datafile. Illegal value for risk locus %3ld)\n",
	   par2);
    break;

  case 39:
    printf("Error detected reading datafile. Mutation locus %3ld) exceeds nlocus\n",
	   par2);
    break;

  case 40:
    printf(
      "Error detected reading datafile. Illegal value for mutation locus %3ld)\n",
      par2);
    break;

  case 41:
    printf(
      "Error detected reading datafile. Linkage disequilbirium is not allowed with this program\n");
    break;

  case 42:
    printf("Locus %5ld in lod score list exceeds mlocus %5ld\n", par1, par2);
    break;

  case 43:
    printf("Illegal locus number %5ld in lod score list\n", par1);
    break;
  }
  exit(EXIT_FAILURE);
}

Void inputwarning(nwarning, par1, par2, LINK)
long nwarning, par1, par2;
struct LOC_inputdata *LINK;
{
  printf("Warning number from procedure inputdata\n");
  switch (nwarning) {

  case 0:
    printf("Illegal sex difference parameter %2ld Parameter should be 0, 1, or 2\n",
	   par1);
    break;

  case 1:
    printf("Illegal interference parameter %2ld Lack of interference assumed\n",
	   par1);
    break;

  case 2:
    printf(
      "Illegal sex difference parameter %2ld Parameter must be 0 with sex-linked data\n",
      par1);
    break;

  case 3:
    printf(
      "Non-standard affection status%4ld interpreted as normal in pedigree record%5ld\n",
      par2, par1);
    break;
  }
}

/* Local variables for readped: */
struct LOC_readped {
  struct LOC_inputdata *LINK;
  long sequence;
} ;

/* Local variables for getphenotype: */
struct LOC_getphenotype {
  struct LOC_readped *LINK;
  thisperson **p;
  long system;
} ;

Local Void readbin(phen, ourlocus, LINK)
phenotype **phen;
locusvalues *ourlocus;
struct LOC_getphenotype *LINK;
{
  long i, j;
  phenotype *WITH;
  long FORLIM;

  WITH = *phen;
  WITH->which = binary_;
  WITH->phenf = 0;
  FORLIM = LINK->LINK->LINK->nfactor[LINK->system - 1];
  for (i = 1; i <= FORLIM; i++) {
    fscanf(pedfile, "%ld", &j);
    if (j != 0 && j != 1)
      inputerror(14L, (*LINK->p)->id, j, LINK->LINK->LINK);
    if (j == 1)
      WITH->phenf = ((long)WITH->phenf) | (1 << ((long)i));
  }
}

Local Void readnumber(phen, ourlocus, LINK)
phenotype **phen;
locusvalues *ourlocus;
struct LOC_getphenotype *LINK;
{
  long i, j, l;
  phenotype *WITH;

  /* dwix: begin */
  static int pedidx = 0;
  static int pednum = -1;
  int locidx, allidx;
  /* dwix: end */
  int allfirst, allsecond;

  WITH = *phen;
  WITH->which = binary_;
  WITH->phenf = 0;
  for (i = 1; i <= 2; i++) {
    fscanf(pedfile, "%ld", &j);
    if (j > maxall)
      inputerror(16L, (*LINK->p)->id, j, LINK->LINK->LINK);
    if ((j < 0) || (j > ourlocus->nallele))
      inputerror(17L, (*LINK->p)->id, j, LINK->LINK->LINK);
    if (j != 0)
#if ALLELE_SPEED
      WITH->phenf = 1;
#else
      WITH->phenf = ((long)WITH->phenf) | (1L << ((int)j));
#endif
    if (1==i)
      allfirst = j;
    else
      allsecond = j;

    /* dwix: begin */
    allidx = j;
    /*Note: lodscore uses holdlocus; other programs use thislocus*/
    locidx = -1;
    for(l=0; l < mlocus; l++)
      if(ourlocus == holdlocus[l])
	locidx = l;
    if (pednum != (*LINK->p)->ped) {
      pedidx++;
      pednum = (*LINK->p)->ped;
    }
    ped_loc_all[pedidx - 1][locidx][allidx].present = true;
    /* dwix: end */
  }
  if (allfirst <= allsecond) {
   WITH->allele1 = allfirst;
   WITH->allele2 = allsecond;
  }
  else {
   WITH->allele1 = allsecond;
   WITH->allele2 = allfirst;
  }
}

Local Void readaff(phen, thislocus, LINK)
phenotype **phen;
locusvalues *thislocus;
struct LOC_getphenotype *LINK;
{
  long thisval;
  phenotype *WITH;

  WITH = *phen;
  fscanf(pedfile, "%ld", &thisval);
  if (thisval == missaff)
    WITH->aff = 0;
  else {
    if (thisval == affval)
      WITH->aff = 2;
    else {
      if (thisval != 1)
	inputwarning(3L, (*LINK->p)->id, thisval, LINK->LINK->LINK);
      WITH->aff = 1;
    }
  }
  if (thislocus->UU.U0.nclass == 1)
    WITH->liability = 1;
  else
    fscanf(pedfile, "%ld", &(*phen)->liability);
  if (WITH->liability > thislocus->UU.U0.nclass)
    inputerror(26L, (*LINK->p)->id, WITH->liability, LINK->LINK->LINK);
  if (WITH->liability <= 0)
    inputerror(27L, (*LINK->p)->id, WITH->liability, LINK->LINK->LINK);
}

Local Void readquan(phen, thislocus, LINK)
phenotype **phen;
locusvalues *thislocus;
struct LOC_getphenotype *LINK;
{
  long i;
  double xval;
  phenotype *WITH;
  long FORLIM;

  WITH = *phen;
  if (!sexlink || !(*LINK->p)->male) {
    FORLIM = thislocus->UU.U1.ntrait;
    for (i = 0; i < FORLIM; i++)
      fscanf(pedfile, "%lf", &(*phen)->x[i]);
    WITH->missing = true;
    FORLIM = thislocus->UU.U1.ntrait;
    for (i = 0; i < FORLIM; i++) {
      if (WITH->x[i] != missval)
	WITH->missing = false;
    }
    return;
  }
  fscanf(pedfile, "%lf", &xval);
  if (xval == missval)
    WITH->aff = missaff;
  else {
    if (xval == affall)
      WITH->aff = affall;
    else
      WITH->aff = -11;
  }
  WITH->liability = 1;
  FORLIM = thislocus->UU.U1.ntrait;
  for (i = 2; i <= FORLIM; i++)
    fscanf(pedfile, "%lf", &xval);
}

Local Void getphenotype(p_, LINK)
thisperson **p_;
struct LOC_readped *LINK;
{
  struct LOC_getphenotype V;
  long thisread;
  thisperson *WITH;

  V.LINK = LINK;
  V.p = p_;
  WITH = *V.p;
  for (thisread = 1; thisread <= mlocus; thisread++) {
    V.system = thisread;
    WITH->holdphen[V.system - 1] = NULL;
    if (holdlocus[V.system - 1]->which != null_) {
      WITH->holdphen[V.system - 1] = (phenotype *)Malloc(sizeof(phenotype));
      if (WITH->holdphen[V.system - 1] == NULL)
        malloc_err("holdphen entry");
    }
    switch (holdlocus[V.system - 1]->which) {

    case quantitative:
      readquan(&WITH->holdphen[V.system - 1], holdlocus[V.system - 1], &V);
      break;

    case affection:
      readaff(&WITH->holdphen[V.system - 1], holdlocus[V.system - 1], &V);
      break;

    case binary_:
      if (holdlocus[V.system - 1]->format == allformat)
	readnumber(&WITH->holdphen[V.system - 1], holdlocus[V.system - 1], &V);
      else
	readbin(&WITH->holdphen[V.system - 1], holdlocus[V.system - 1], &V);
      break;
    /* cgh -- make gcc happy */
    case null_:
    default:
      break;
    }
    if (lastpriv == V.system) {
      WITH->privphen = (phenotype *)Malloc(sizeof(phenotype));
      if (WITH->privphen == NULL)
        malloc_err("privphen field");
      switch (holdlocus[V.system - 1]->privlocus->which) {

      case quantitative:
	readquan(&WITH->privphen, holdlocus[V.system - 1]->privlocus, &V);
	break;

      case affection:
	readaff(&WITH->privphen, holdlocus[V.system - 1]->privlocus, &V);
	break;
      /* cgh -- gcc */
      case binary_:
      case null_:
      default:
	break;
      }
    }
  }
}

Local Void getind(id, LINK)
long *id;
struct LOC_readped *LINK;
{
  fscanf(pedfile, "%ld", id);
  if (*id == 0)
    return;
  *id += LINK->sequence;
  if (*id > maxind)
    inputerror(13L, *id, *id, LINK->LINK);
  if (person[*id] == NULL) {
    person[*id] = (thisperson *)Malloc(sizeof(thisperson));
    if (person[*id] == NULL)
      malloc_err("person entry");
  }
}  /*getind*/


Local Void multimarriage(p, LINK)
thisperson **p;
struct LOC_readped *LINK;
{
  thisperson *q, *child, *WITH;

  if ((*p)->foff == NULL) {
    (*p)->multi = false;
    return;
  }
  WITH = *p;
  if (WITH->male)
    q = WITH->foff->ma;
  else
    q = WITH->foff->pa;
  child = WITH->foff;
  (*p)->multi = false;
  do {
    if (WITH->male) {
      WITH->multi = (q == child->ma); 
      child = child->nextpa;
    } else {
      WITH->multi = (q == child->pa); 
      child = child->nextma;
    }
  } while (!(child == NULL || WITH->multi));
}  /*multimarriage*/


Void readped(LINK)
struct LOC_inputdata *LINK;
{
  struct LOC_readped V;
  long i, newid, sex_, profield, newped, nuperson, thisone, thisped;
  thisperson *holdloop;
  thisperson *WITH;

  V.LINK = LINK;
  for (i = 0; i <= maxind; i++)
    person[i] = NULL;
  V.sequence = 0;
  nuperson = 0;
  nuped = 1;
  for (i = 0; i < maxloop; i++) {
    looppers[nuped - 1][i][0] = NULL;
    looppers[nuped - 1][i][1] = NULL;
  }
  proband[nuped - 1] = NULL;
  fscanf(pedfile, "%ld", &newped);
  thisped = newped;
  startped[0] = 1;
  while (!P_eof(pedfile)) {
    nuperson++;
    getind(&thisone, &V);
    if (proband[nuped - 1] == NULL)
      proband[nuped - 1] = person[thisone];
    WITH = person[thisone];
    WITH->ped = thisped;
    WITH->id = thisone;
    getind(&newid, &V);
    WITH->pa = person[newid];
    getind(&newid, &V);
    WITH->ma = person[newid];
    getind(&newid, &V);
    WITH->foff = person[newid];
    getind(&newid, &V);
    WITH->nextpa = person[newid];
    getind(&newid, &V);
    WITH->nextma = person[newid];
    fscanf(pedfile, "%ld", &sex_);
    if (sex_ != 1 && sex_ != 2)
      inputerror(11L, WITH->id, sex_, LINK);
    if (sex_ == 1)
      WITH->male = true;
    else
      WITH->male = false;
    WITH->unknown = false;
    WITH->inloop = 0;
    WITH->loopdepend = false; /*A. A. Schaffer*/
    WITH->loopneeded = false;
    fscanf(pedfile, "%ld", &profield);
    /* Diagnostic added by A. A. Schaffer 7/25/94 */
    if ((profield - 1) > maxloop) {
      fprintf(stderr, "\nYour pedigree has more loops than allowed by the constant maxloop ");
      fprintf(stderr, "\nYou must increase the constant maxloop defined in commondefs.h and recompile ");
      fprintf(stderr, "\nYou are encouraged to read the loops.ps document distributed with FASTLINK ");
      fprintf(stderr, "\nThe program will exit politely to allow you to correct the problem ");
      exit(EXIT_FAILURE);
    }
    if (profield == 1)
      proband[nuped - 1] = person[thisone];
    else if (profield > 1 && profield - 1 <= maxloop) {
      if (looppers[nuped - 1][profield - 2][1] == NULL)
	looppers[nuped - 1][profield - 2][1] = person[thisone];
      else
	looppers[nuped - 1][profield - 2][0] = person[thisone];
    }
    getphenotype(&person[thisone], &V);
    fscanf(pedfile, "%*[^\n]");
    getc(pedfile);
    if (!P_eof(pedfile))
      fscanf(pedfile, "%ld", &newped);
    if (newped == thisped)
      continue;
    V.sequence += nuperson;
    endped[nuped - 1] = V.sequence;
    nuperson = 0;
    nuped++;
    if (nuped > maxped)
      inputerror(12L, newped, nuped, LINK);
    startped[nuped - 1] = V.sequence + 1;
    for (i = 0; i < maxloop; i++) {
      looppers[nuped - 1][i][0] = NULL;
      looppers[nuped - 1][i][1] = NULL;
    }
    proband[nuped - 1] = NULL;
    thisped = newped;
  }
  totperson = V.sequence + nuperson;
  endped[nuped - 1] = totperson;
  for (newped = 0; newped < nuped; newped++) {
    if (looppers[newped][0][1] != NULL && looppers[newped][0][0] == NULL)
      looppers[newped][0][0] = proband[newped];
    for (i = 0; i < maxloop; i++) {
      if (looppers[newped][i][0] == NULL)
	looppers[newped][i][1] = NULL;
      else {
	looppers[newped][i][0]->inloop = i + 1;
	looppers[newped][i][1]->inloop = i + 1;
	if (looppers[newped][i][0]->pa == NULL &&
	    looppers[newped][i][1]->pa != NULL) {
	  holdloop = looppers[newped][i][0];
	  looppers[newped][i][0] = looppers[newped][i][1];
	  looppers[newped][i][1] = holdloop;
	}
      }
    }
  }
  for (thisone = 1; thisone <= totperson; thisone++) {
    multimarriage(&person[thisone], &V);
  }
}


/* Local variables for getlocus: */
struct LOC_getlocus {
  struct LOC_readloci *LINK;
  long system;
} ;

Local Void getbin(locus, system, LINK)
locusvalues **locus;
long *system;
struct LOC_getlocus *LINK;
{
  long i, j, k;
  locusvalues *WITH;
  long FORLIM, FORLIM1;

  fscanf(datafile, "%ld%*[^\n]", &LINK->LINK->LINK->nfactor[*system - 1]);
  getc(datafile);
  if ((LINK->LINK->LINK->nfactor[*system - 1] > maxfact) ||
      (LINK->LINK->LINK->nfactor[*system - 1] > (sizeof(long) * 8 - 1)))
    inputerror(8L, *system, LINK->LINK->LINK->nfactor[*system - 1],
	       LINK->LINK->LINK);
  if (LINK->LINK->LINK->nfactor[*system - 1] <= 0)
    inputerror(9L, *system, LINK->LINK->LINK->nfactor[*system - 1],
	       LINK->LINK->LINK);
  WITH = *locus;
  FORLIM = WITH->nallele;
  for (i = 0; i < FORLIM; i++)
    WITH->UU.allele[i] = 0;
  FORLIM = WITH->nallele;
  for (i = 0; i < FORLIM; i++) {
    FORLIM1 = LINK->LINK->LINK->nfactor[*system - 1];
    for (j = 1; j <= FORLIM1; j++) {
      fscanf(datafile, "%ld", &k);
      if (k == 1)
	WITH->UU.allele[i] = ((long)WITH->UU.allele[i]) | (1L << ((int)j));
    }
  }
  fscanf(datafile, "%*[^\n]");
  getc(datafile);
}

Local Void getnumber(locus, system, LINK)
locusvalues **locus;
long *system;
struct LOC_getlocus *LINK;
{
  long i;
  locusvalues *WITH;
  long FORLIM;

  WITH = *locus;
  FORLIM = WITH->nallele;
  for (i = 1; i <= FORLIM; i++)
    WITH->UU.allele[i - 1] = 1;
}


Local Void getpen(locus, LINK)
locusvalues **locus;
struct LOC_getlocus *LINK;
{
  long i, j, k, l;
  locusvalues *WITH;
  long FORLIM, FORLIM1, FORLIM2;

  WITH = *locus;
  fscanf(datafile, "%ld%*[^\n]", &(*locus)->UU.U0.nclass);
  getc(datafile);
  if (WITH->UU.U0.nclass > maxliab)
    inputerror(28L, LINK->system, WITH->UU.U0.nclass, LINK->LINK->LINK);
  if (WITH->UU.U0.nclass <= 0)
    inputerror(29L, LINK->system, WITH->UU.U0.nclass, LINK->LINK->LINK);
  FORLIM = WITH->UU.U0.nclass;
  for (l = 0; l < FORLIM; l++) {
    FORLIM1 = WITH->nallele;
    for (i = 1; i <= FORLIM1; i++) {
      FORLIM2 = WITH->nallele;
      for (j = i - 1; j < FORLIM2; j++) {
	fscanf(datafile, "%lf", &(*locus)->UU.U0.pen[i][j][2][l]);
	if ((unsigned)WITH->UU.U0.pen[i][j][2][l] > 1.0)
	  inputerror(30L, LINK->system, LINK->system, LINK->LINK->LINK);
	WITH->UU.U0.pen[i][j][1][l] = 1 - WITH->UU.U0.pen[i][j][2][l];
	WITH->UU.U0.pen[i][j][0][l] = 1.0;
	for (k = 0; k <= 2; k++)
	  WITH->UU.U0.pen[j + 1][i - 1][k][l] = WITH->UU.U0.pen[i][j][k][l];
      }
    }
    fscanf(datafile, "%*[^\n]");
    getc(datafile);
    FORLIM1 = WITH->nallele;
    for (i = 0; i < FORLIM1; i++)
      WITH->UU.U0.pen[0][i][0][l] = 1.0;
    if (sexlink) {
/* This code was an error in LINKAGE 5.1. It tries to read an extra
   penetrance line on sexlinked data. -Bob Cottingham 8/18/93
      FORLIM1 = WITH->nallele;
      for (i = 0; i < FORLIM1; i++)
	fscanf(datafile, "%lf", &(*locus)->UU.U0.pen[0][i][2][l]);
*/
      FORLIM1 = WITH->nallele;
      for (i = 0; i < FORLIM1; i++) {
	fscanf(datafile, "%lf", &(*locus)->UU.U0.pen[0][i][2][l]);
	if ((unsigned)WITH->UU.U0.pen[0][i][2][l] > 1.0)
	  inputerror(30L, LINK->system, LINK->system, LINK->LINK->LINK);
      }
      FORLIM1 = WITH->nallele;
      for (i = 0; i < FORLIM1; i++)
	WITH->UU.U0.pen[0][i][1][l] = 1.0 - WITH->UU.U0.pen[0][i][2][l];
      fscanf(datafile, "%*[^\n]");
      getc(datafile);
    }
  }
}


Local Void getquan(locus, privelege, LINK)
locusvalues **locus;
boolInt privelege;
struct LOC_getlocus *LINK;
{
  /*Get information of a quantitative locus. Privelege says whether it is
    a priveleged locus or not*/
  long i, j, k;
  locusvalues *WITH;
  long FORLIM, FORLIM1, FORLIM2;

  WITH = *locus;
  fscanf(datafile, "%ld%*[^\n]", &(*locus)->UU.U1.ntrait);
  getc(datafile);
  if (WITH->UU.U1.ntrait > maxtrait)
    inputerror(31L, LINK->system, WITH->UU.U1.ntrait, LINK->LINK->LINK);
  if (WITH->UU.U1.ntrait <= 0)
    inputerror(32L, LINK->system, WITH->UU.U0.nclass, LINK->LINK->LINK);
  FORLIM = WITH->UU.U1.ntrait;
  for (i = 0; i < FORLIM; i++) {
    FORLIM1 = WITH->nallele;
    for (j = 1; j <= FORLIM1; j++) {
      FORLIM2 = WITH->nallele;
      for (k = j; k <= FORLIM2; k++) {
	fscanf(datafile, "%lf", &(*locus)->UU.U1.pm[j][k - 1][i]);
	WITH->UU.U1.pm[k][j - 1][i] = WITH->UU.U1.pm[j][k - 1][i];
      }
    }
  }
  fscanf(datafile, "%*[^\n]");
  getc(datafile);
  if (privelege && LINK->LINK->nupriv != lastpriv)
    return;
  FORLIM = WITH->UU.U1.ntrait;
  for (i = 0; i < FORLIM; i++) {
    FORLIM1 = WITH->UU.U1.ntrait;
    for (j = i; j < FORLIM1; j++) {
      fscanf(datafile, "%lf", &(*locus)->UU.U1.vmat[i][j]);
      if (i + 1 == j + 1 && WITH->UU.U1.vmat[i][j] <= 0.0)
	inputerror(33L, LINK->system, LINK->system, LINK->LINK->LINK);
      WITH->UU.U1.vmat[j][i] = WITH->UU.U1.vmat[i][j];
    }
  }
  fscanf(datafile, "%*[^\n]");
  getc(datafile);
  invert(WITH->UU.U1.vmat, WITH->UU.U1.ntrait, &WITH->UU.U1.det);
  WITH->UU.U1.det = 1 / sqrt(WITH->UU.U1.det);
  fscanf(datafile, "%lf%*[^\n]", &(*locus)->UU.U1.conmat);
  getc(datafile);
  if (WITH->UU.U1.conmat <= 0)
    inputerror(34L, LINK->system, LINK->system, LINK->LINK->LINK);
  WITH->UU.U1.conmat = 1 / WITH->UU.U1.conmat;
  WITH->UU.U1.contrait = 1.0;
  FORLIM = WITH->UU.U1.ntrait;
  for (i = 1; i <= FORLIM; i++)
    WITH->UU.U1.contrait *= WITH->UU.U1.conmat;
  WITH->UU.U1.contrait = sqrt(WITH->UU.U1.contrait);
}

Void getlocus(system_, LINK)
long system_;
struct LOC_readloci *LINK;
{
  struct LOC_getlocus V;
  long j;
  locusvalues *WITH, *WITH1;
  long FORLIM;
  int TEMP;

  V.LINK = LINK;
  V.system = system_;
  holdlocus[V.system - 1] = (locusvalues *)Malloc(sizeof(locusvalues));
  if (holdlocus[V.system - 1] == NULL)
    malloc_err("holdlocus entry");
  WITH = holdlocus[V.system - 1];
  WITH->privlocus = NULL;
  fscanf(datafile, "%ld%d", &LINK->whichtype,
	 &holdlocus[V.system - 1]->nallele);
  if (LINK->whichtype < 0 && LINK->whichtype > 4)
    inputerror(5L, V.system, LINK->whichtype, LINK->LINK);
  if (WITH->nallele > maxall)
    inputerror(6L, V.system, WITH->nallele, LINK->LINK);
  if (WITH->nallele <= 0)
    inputerror(7L, V.system, WITH->nallele, LINK->LINK);
  switch (LINK->whichtype) {

  case 0:
    WITH->which = quantitative;
    break;

  case 1:
    WITH->which = affection;
    break;

  case 2:
    WITH->which = binary_;
    break;

  case 3:
    WITH->which = binary_;
    break;
  }
  WITH->format = LINK->whichtype;
  if (lastpriv == 0) {
    fscanf(datafile, "%*[^\n]");
    getc(datafile);
  } else {
    fscanf(datafile, "%ld%*[^\n]", &LINK->whichtype);
    getc(datafile);
    if (LINK->whichtype == 0 || LINK->whichtype == 1) {
      LINK->nupriv++;
      WITH->privlocus = (locusvalues *)Malloc(sizeof(locusvalues));
      if (WITH->privlocus == NULL)
        malloc_err("privlocus field");
      WITH->privlocus->nallele = WITH->nallele;
      WITH1 = WITH->privlocus;
      switch (LINK->whichtype) {

      case 0:
	WITH1->which = quantitative;
	break;

      case 1:
	WITH1->which = affection;
	break;
      }
    }
  }
  if (!disequi) {
    FORLIM = WITH->nallele;
    for (j = 0; j < FORLIM; j++) {
      fscanf(datafile, "%lf", &holdlocus[V.system - 1]->freq[j]);
      if (holdlocus[V.system - 1]->freq[j] <= minfreq)
        fprintf(stderr, "\nWarning: one of your allele frequencies is dangerously low");
    }
    fscanf(datafile, "%*[^\n]");
    getc(datafile);
  }
  switch (WITH->which) {

  case binary_:
    if (WITH->format == allformat)
      getnumber(&holdlocus[V.system - 1], &V.system, &V);
    else
      getbin(&holdlocus[V.system - 1], &V.system, &V);
    break;

  case affection:
    getpen(&holdlocus[V.system - 1], &V);
    break;

  case quantitative:
    getquan(&holdlocus[V.system - 1], false, &V);
    break;
  /* cgh - gcc */  
  case null_:
  default:
    break;
  }
  if (WITH->privlocus != NULL) {
    switch (WITH->privlocus->which) {

    case affection:
      getpen(&WITH->privlocus, &V);
      break;

    case quantitative:
      getquan(&WITH->privlocus, true, &V);
      break;
    /* cgh - gcc */  
    case null_:
    case binary_:
    default:
      break;
    }
  }
  if (LINK->nupriv == lastpriv && lastpriv != 0)
    lastpriv = V.system;
  if (!risk)
    return;
  if (LINK->i == risksys) {
    fscanf(datafile, "%d%*[^\n]", &TEMP);
    getc(datafile);
    riskall = TEMP;
  }
  if (riskall > holdlocus[LINK->i - 1]->nallele)
    inputerror(35L, LINK->i, (long)riskall, LINK->LINK);
  if (riskall < 0)
    inputerror(36L, LINK->i, (long)riskall, LINK->LINK);
}


Void gettheta(sex_, male, LINK)
double *sex_;
boolInt male;
struct LOC_readloci *LINK;
{
  if (readfemale || male) {
    fscanf(datafile, "%lf%*[^\n]", sex_);
    getc(datafile);
  } else {
    fscanf(datafile, "%lf%*[^\n]", &distratio);
    getc(datafile);
  }
  holdratio = distratio;
}




Local Void readloci(LINK)
struct LOC_inputdata *LINK;
{
  struct LOC_readloci V;
  long coupling, autosomal, independent, difference;


  V.LINK = LINK;
  lastpriv = 0;
  fscanf(datafile, "%d%d%ld%*[^\n]", &mlocus, &risksys, &autosomal);
  getc(datafile);
  /*Replace the above line with the next when using epistasis*/
  /*readln(datafile,mlocus,risksys,autosomal,lastpriv);*/
  if (mlocus > maxsys)
    inputerror(0L, mlocus, mlocus, LINK);
  if (mlocus <= 0)
    inputerror(1L, mlocus, mlocus, LINK);
  risk = (risksys != 0);
  sexlink = (autosomal == 1);
  printf("YOU ARE USING LINKAGE (V%3.1f (1-Feb-1991)) WITH%3d-POINT\n",
	 fVersion, mlocus);
  printf("YOU ARE USING FASTLINK (V%s (6-Oct-1997))",
	 fastversion);
  if (sexlink)
    printf(" SEXLINKED DATA\n");
  else
    printf(" AUTOSOMAL DATA\n");
  fscanf(datafile, "%d%lf%lf%ld%*[^\n]", &mutsys, &mutmale, &mutfemale,
	 &coupling);
  getc(datafile);
  if (mutsys > maxsys)
    inputerror(39L, mutsys, mutsys, LINK);
  if (mutsys < 0)
    inputerror(40L, mutsys, mutsys, LINK);
  if (coupling != 0)
    inputerror(41L, coupling, coupling, LINK);
  disequi = false;
  fscanf(datafile, "%*[^\n]");
  getc(datafile);
  V.nupriv = 0;
  for (V.i = 1; V.i <= mlocus; V.i++)
    getlocus(V.i, &V);
  fscanf(datafile, "%ld", &difference);
  if ((unsigned long)difference > 2) {
    inputwarning(0L, difference, difference, LINK);
    difference = 0;
  }
  sexdif = (difference != 0);
  readfemale = (difference == 2);
  fscanf(datafile, "%ld%*[^\n]", &independent);
  getc(datafile);
  if ((unsigned long)independent > 2) {
    inputwarning(1L, independent, independent, LINK);
    independent = 0;
  }
  interfer = (independent != 0);
  mapping = (independent == 2);
  gettheta(&holdmtheta, true, &V);
  nuneed = 7; /*value for 2 loci*/
  maletheta = (thetavalues *)Malloc(sizeof(thetavalues));
  if (maletheta == NULL)
    malloc_err("maletheta");
  /*Next allocation added by A. A. Schaffer*/
  maletheta->segprob = (double *) malloc(nuneed * sizeof(double));
  if ((maletheta->segprob)==NULL)
    malloc_err("segprob array in maletheta");
  if (sexlink && sexdif) {
    inputwarning(2L, difference, difference, LINK);
    sexdif = false;
    readfemale = false;
  }
  if (sexdif) {
    gettheta(&holdftheta, false, &V);
    femaletheta = (thetavalues *)Malloc(sizeof(thetavalues));
    if (femaletheta == NULL)
      malloc_err("female_theta");
    /*Next allocation added by A. A. Schaffer*/
    femaletheta->segprob = (double *) malloc(nuneed * sizeof(double));
    if ((femaletheta->segprob)==NULL)
      malloc_err("segprob array in femaletheta");
  } else
    femaletheta = maletheta;
  if (!sexlink) {
    if (mutsys == 0)
      thispath = auto_;
    else
      thispath = mauto;
  } else if (mutsys == 0)
    thispath = sex;
  else
    thispath = msex;
  segscale = scale;
  for (V.i = 1; V.i <= 2; V.i++)
    segscale *= scalemult;
  fscanf(datafile, "%d%*[^\n]", &hitsys);
  getc(datafile);
  itsys = 0;
  for (V.i = 1; V.i <= maxn; V.i++)
    itp[V.i - 1] = 0;
  V.i = 0;
  while ((V.i <= maxn) & (!P_eoln(datafile))) {
    V.i++;
    fscanf(datafile, "%d", &itp[V.i - 1]);
  }
  fscanf(datafile, "%*[^\n]");
  getc(datafile);
  memcpy(holditp, itp, sizeof(itertype));
  V.i = 0;
  while (!P_eoln(datafile)) {
    V.i++;
    fscanf(datafile, "%d", &locuslist1[V.i - 1]);
    if (locuslist1[V.i - 1] > mlocus)
      inputerror(42L, locuslist1[V.i - 1], mlocus, LINK);
    if (locuslist1[V.i - 1] <= 0)
      inputerror(43L, locuslist1[V.i - 1], mlocus, LINK);
  }
  fscanf(datafile, "%*[^\n]");
  getc(datafile);
  nlocus1 = V.i;
  V.i = 0;
  while (!P_eoln(datafile)) {
    V.i++;
    fscanf(datafile, "%d", &locuslist2[V.i - 1]);
    if (locuslist2[V.i - 1] > mlocus)
      inputerror(42L, locuslist2[V.i - 1], mlocus, LINK);
    if (locuslist2[V.i - 1] <= 0)
      inputerror(43L, locuslist2[V.i - 1], mlocus, LINK);
  }
  nlocus2 = V.i;
  risk = false;
}


Void inputdata()
{
  struct LOC_inputdata V;


  readloci(&V);
  readped(&V);
}

