source: branches/profile/GDE/PHYLIP/phylip.c

Last change on this file was 2183, checked in by westram, 20 years ago
  • distinguish between EOF and EOL
  • show partly read name in case of error
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 65.9 KB
Line 
1
2/* version 3.6. (c) Copyright 1993-2002 by the University of Washington.
3   Written by Joseph Felsenstein, Akiko Fuseki, Sean Lamont, Andrew Keeffe,
4   and Dan Fineman.
5   Permission is granted to copy and use this program provided no fee is
6   charged for it and provided that this copyright notice is not removed. */
7
8#include <stdio.h>
9#include <signal.h>
10#ifdef WIN32
11#include <windows.h>
12/* for console code (clear screen, text color settings) */
13CONSOLE_SCREEN_BUFFER_INFO savecsbi;
14HANDLE hConsoleOutput;
15
16void phyClearScreen();
17void phySaveConsoleAttributes();
18void phySetConsoleAttributes();
19void phyRestoreConsoleAttributes();
20void phyFillScreenColor();
21#endif
22
23#include "phylip.h"
24
25#ifndef OLDC
26static void crash_handler(int signum);
27
28#endif
29
30FILE *infile, *outfile, *intree, *intree2, *outtree, *weightfile, *catfile, *ancfile, *mixfile, *factfile;
31long spp, words, bits;
32boolean ibmpc, ansi, tranvsp;
33naym *nayme;                     /* names of species */
34
35static void crash_handler(int sig_num)
36{ /* when we crash, lets print out something usefull */
37  printf("ERROR:  ");
38  switch(sig_num) {
39#ifdef SIGSEGV
40    case SIGSEGV:
41      puts("This program has caused a Segmentation fault.");
42      break;
43#endif /* SIGSEGV */
44#ifdef SIGFPE
45    case SIGFPE:
46      puts("This program has caused a Floating Point Exception");
47      break;
48#endif  /* SIGFPE */
49#ifdef SIGILL
50    case SIGILL:
51      puts("This program has attempted an illegal instruction");
52      break;
53#endif  /* SIGILL */
54#ifdef SIGPIPE
55    case SIGPIPE:
56      puts("This program tried to write to a broken pipe");
57      break;
58#endif  /* SIGPIPE */
59#ifdef SIGBUS
60    case SIGBUS:
61      puts("This program had a bus error");
62      break;
63#endif /* SIGBUS */
64  }
65  if (sig_num == SIGSEGV) {
66    puts("       This may have been caused by an incorrectly formatted");
67    puts("       input tree file or input file.  You should check those");
68    puts("       files carefully.");
69    puts("       If this seems to be a bug, please mail joe@gs.washington.edu");
70  }
71  else {
72    puts("       Most likely, you have encountered a bug in the program.");
73    puts("       Since this seems to be a bug, please mail joe@gs.washington.edu");
74  }
75  puts("       with the name of the program, your computer system type,");
76  puts("       a full description of the problem, and with the input data file.");
77  puts("       (which should be in the body of the message, not as an Attachment).");
78
79#ifdef WIN32
80  puts ("Hit Enter or Return to close program.");
81  puts("  You may have to hit Enter or Return twice.");
82  getchar ();
83  getchar ();
84  phyRestoreConsoleAttributes();
85#endif
86  abort();
87}
88
89
90void init(int argc, char** argv)
91{ /* initialization routine for all programs
92   * anything done at the beginig for every program should be done here */
93
94  /* set up signal handler for
95   * segfault,floating point exception, illeagal instruction, bad pipe, bus error
96   * there are more signals that can cause a crash, but these are the most common
97   * even these aren't found on all machines.  */
98#ifdef SIGSEGV
99  signal(SIGSEGV, crash_handler);
100#endif /* SIGSEGV */
101#ifdef SIGFPE
102  signal(SIGFPE, crash_handler);
103#endif /* SIGFPE */
104#ifdef SIGILL
105  signal(SIGILL, crash_handler);
106#endif /* SIGILL */
107#ifdef SIGPIPE
108  signal(SIGPIPE, crash_handler);
109#endif /* SIGPIPE */
110#ifdef SIGBUS
111  signal(SIGBUS, crash_handler);
112#endif /* SIGBUS */
113
114#ifdef WIN32
115  phySetConsoleAttributes();
116  phyClearScreen();
117#endif
118
119}
120
121void scan_eoln(FILE *f)
122{ /* eat everything to the end of line or eof*/
123  char ch;
124
125  while (!eoff(f) && !eoln(f))
126    gettc(f);
127  if (!eoff(f))
128    ch = gettc(f);
129  if (ch == '\r' && !eoff(f) && eoln(f))
130    gettc(f);
131}
132
133
134boolean eoff(FILE *f)
135{ /* check for end of file */
136    int ch;
137
138    if (feof(f))
139      return true;
140    ch = getc(f);
141    if (ch == EOF) {
142      ungetc(ch, f);
143      return true;
144    }
145    ungetc(ch, f);
146    return false;
147}  /*eoff*/
148
149
150boolean eoln(FILE *f)
151{ /* check for end of line or eof*/
152    register int ch;
153
154    ch = getc(f);
155    if (ch == EOF)
156      return true;
157    ungetc(ch, f);
158    return ((ch == '\n') || (ch == '\r'));
159}  /*eoln*/
160
161
162int filexists(char *filename)
163{ /* check whether file already exists */
164  FILE *fp;
165  fp =fopen(filename,"r");
166  if (fp) {
167    fclose(fp);
168    return 1;
169  } else
170    return 0;
171}  /*filexists*/
172
173
174const char* get_command_name (const char *vektor)
175{ /* returns the name of the program from vektor without the whole path */
176  char *last_slash;
177
178  /* Point to the last slash... */
179  last_slash = strrchr (vektor, DELIMITER);
180
181  if (last_slash)
182    /* If there was a last slash, return the character after it */
183    return last_slash + 1;
184  else
185    /* If not, return the vector */
186    return vektor;
187
188}  /*get_command_name*/
189
190
191void getstryng(char *fname)
192{ /* read in a file name from stdin and take off newline if any */
193
194  fname = fgets(fname, 100, stdin);
195  if (strchr(fname, '\n') != NULL)
196    *strchr(fname, '\n') = '\0';
197} /* getstryng */
198
199
200void countup(long *loopcount, long maxcount)
201{ /* count how many times this loop has tried to read data, bail out
202     if exceeds maxcount */
203
204  (*loopcount)++;
205  if ((*loopcount) >= maxcount) {
206    printf("\nERROR: Made %ld attempts to read input in loop. Aborting run.\n",
207            *loopcount);
208    exxit(-1);
209  }
210} /* countup */
211
212
213void openfile(FILE **fp,const char *filename,const char *filedesc,
214              const char *mode,const char *application, char *perm)
215{ /* open a file, testing whether it exists etc. */
216  FILE *of;
217  char file[FNMLNGTH];
218  char filemode[2];
219  char input[FNMLNGTH];
220  char ch;
221  const char *progname_without_path;
222  long loopcount, loopcount2;
223
224  progname_without_path = get_command_name(application);
225
226  strcpy(file,filename);
227  strcpy(filemode,mode);
228  loopcount = 0;
229  while (1){
230    if (filemode[0] == 'w' && filexists(file)){
231      printf("\n%s: the file \"%s\" that you wanted to\n",
232          progname_without_path, file);
233      printf("     use as %s already exists.\n", filedesc);
234      printf("     Do you want to Replace it, Append to it,\n");
235      printf("     write to a new File, or Quit?\n");
236      loopcount2 = 0;
237      do {
238        printf("     (please type R, A, F, or Q) \n");
239#ifdef WIN32
240        phyFillScreenColor();
241#endif
242        fgets(input, sizeof(input), stdin);
243        ch  = input[0];
244        uppercase(&ch);
245        countup(&loopcount2, 10);
246      } while (ch != 'A' && ch != 'R' && ch != 'F' && ch != 'Q');
247      if (ch == 'Q')
248        exxit(-1);
249      if (ch == 'A') {
250        strcpy(filemode,"a");
251        continue;
252      }
253      else if (ch == 'F') {
254        file[0] = '\0';
255        loopcount2 = 0;
256        while (file[0] =='\0') {
257          printf("Please enter a new file name> ");
258          getstryng(file);
259          countup(&loopcount2, 10);
260        }
261        strcpy(filemode,"w");
262        continue;
263      }
264    }
265    of = fopen(file,filemode);
266    if (of)
267      break;
268    else {
269      switch (filemode[0]){
270
271      case 'r':
272        printf("%s: can't find %s \"%s\"\n", progname_without_path,
273            filedesc, file);
274        file[0] = '\0';
275        loopcount2 = 0;
276        while (file[0] =='\0'){
277          printf("Please enter a new file name> ");
278          countup(&loopcount2, 10);
279          getstryng(file);}
280        break;
281
282      case 'w':
283      case 'a':
284        printf("%s: can't write %s file %s\n", progname_without_path,
285            filedesc, file);
286        file[0] = '\0';
287        loopcount2 = 0;
288        while (file[0] =='\0'){
289          printf("Please enter a new file name> ");
290          countup(&loopcount2, 10);
291          getstryng(file);}
292        continue;
293      default:
294     printf("There is some error in the call of openfile. Unknown mode.\n");
295        exxit(-1);
296      }
297    }
298    countup(&loopcount, 20);
299  }
300  *fp = of;
301  if (perm != NULL)
302    strcpy(perm,file);
303} /* openfile */
304
305
306void cleerhome()
307{ /* home cursor and clear screen, if possible */
308  printf("%s", ((ibmpc || ansi) ? ("\033[2J\033[H") : "\n\n"));
309} /* cleerhome */
310
311
312double randum(longer seed)
313{ /* random number generator -- slow but machine independent
314  This is a multiplicative congruential 32-bit generator
315  x(t+1) = 1664525 * x(t) mod 2^32, one that passes the
316  Coveyou-Macpherson and Lehmer tests, see Knuth ACP vol. 2   */
317  long i, j, k, sum;
318  longer mult, newseed;
319  double x;
320
321  mult[0] = 13;   /* these four statements set the multiplier */
322  mult[1] = 24;   /* -- they are its "digits" in a base-64    */
323  mult[2] = 22;   /*    notation: 1664525 = 13*64^3+24*64^2   */
324  mult[3] = 6;    /*                         +22*64+6         */
325  for (i = 0; i <= 5; i++)
326    newseed[i] = 0;
327  for (i = 0; i <= 5; i++) {
328    sum = newseed[i];
329    k = i;
330    if (i > 3)
331      k = 3;
332    for (j = 0; j <= k; j++)
333      sum += mult[j] * seed[i - j];
334    newseed[i] = sum;
335    for (j = i; j <= 4; j++) {
336      newseed[j + 1] += newseed[j] / 64;
337      newseed[j] &= 63;
338    }
339  }
340  memcpy(seed, newseed, sizeof(longer));
341  seed[5] &= 3;
342  x = 0.0;
343  for (i = 0; i <= 5; i++)
344    x = x / 64.0 + seed[i];
345  x /= 4.0;
346  return x;
347}  /* randum */
348
349
350void randumize(longer seed, long *enterorder)
351{ /* randomize input order of species */
352  long i, j, k;
353
354  for (i = 0; i < spp; i++) {
355    j = (long)(randum(seed) * (i+1));
356    k = enterorder[j];
357    enterorder[j] = enterorder[i];
358    enterorder[i] = k;
359  }
360} /* randumize */
361
362
363double normrand(longer seed)
364{/* standardized Normal random variate */
365  double x;
366
367  x = randum(seed)+randum(seed)+randum(seed)+randum(seed)
368       + randum(seed)+randum(seed)+randum(seed)+randum(seed)
369       + randum(seed)+randum(seed)+randum(seed)+randum(seed)-6.0;
370  return(x);
371} /* normrand */
372
373
374long readlong(const char *prompt)
375{ /* read a long */
376  long res, loopcount;
377  char string[100];
378
379  loopcount = 0;
380  do {
381    printf("%s",prompt);
382    getstryng(string);
383    if (sscanf(string,"%ld",&res) == 1)
384      break;
385    countup(&loopcount, 10);
386   } while (1);
387  return res;
388}  /* readlong */
389
390
391void uppercase(Char *ch)
392{ /* convert ch to upper case */
393  *ch = (islower (*ch) ? toupper(*ch) : (*ch));
394}  /* uppercase */
395
396
397void initseed(long *inseed, long *inseed0, longer seed)
398{ /* input random number seed */
399  long i, loopcount;
400
401  loopcount = 0;
402  do {
403    printf("Random number seed (must be odd)?\n");
404    scanf("%ld%*[^\n]", inseed);
405    getchar();
406    countup(&loopcount, 10);
407  } while (((*inseed) < 0) || ((*inseed) & 1) == 0);
408  *inseed0 = *inseed;
409  for (i = 0; i <= 5; i++)
410    seed[i] = 0;
411  i = 0;
412  do {
413    seed[i] = *inseed & 63;
414    *inseed /= 64;
415    i++;
416  } while (*inseed != 0);
417}  /*initseed*/
418
419
420void initjumble(long *inseed, long *inseed0, longer seed, long *njumble)
421{ /* input number of jumblings for jumble option */
422  long loopcount;
423
424  initseed(inseed, inseed0, seed);
425  loopcount = 0;
426  do {
427    printf("Number of times to jumble?\n");
428    scanf("%ld%*[^\n]", njumble);
429    getchar();
430    countup(&loopcount, 10);
431  } while ((*njumble) < 1);
432}  /*initjumble*/
433
434
435void initoutgroup(long *outgrno, long spp)
436{ /* input outgroup number */
437  long loopcount;
438  boolean done;
439
440  loopcount = 0;
441  do {
442    printf("Type number of the outgroup:\n");
443    scanf("%ld%*[^\n]", outgrno);
444    getchar();
445    done = (*outgrno >= 1 && *outgrno <= spp);
446    if (!done) {
447      printf("BAD OUTGROUP NUMBER: %ld\n", *outgrno);
448      printf("  Must be in range 1 - %ld\n", spp);
449    }
450    countup(&loopcount, 10);
451  } while (done != true);
452}  /*initoutgroup*/
453
454
455void initthreshold(double *threshold)
456{ /* input threshold for threshold parsimony option */
457  long loopcount;
458  boolean done;
459
460  loopcount = 0;
461  do {
462    printf("What will be the threshold value?\n");
463    scanf("%lf%*[^\n]", threshold);
464    getchar();
465    done = (*threshold >= 1.0);
466    if (!done)
467      printf("BAD THRESHOLD VALUE:  it must be greater than 1\n");
468    else
469      *threshold = (long)(*threshold * 10.0 + 0.5) / 10.0;
470    countup(&loopcount, 10);
471  } while (done != true);
472}  /*initthreshold*/
473
474
475void initcatn(long *categs)
476{ /* initialize category number for rate categories */
477  long loopcount;
478
479  loopcount = 0;
480  do {
481    printf("Number of categories (1-%d)?\n", maxcategs);
482    scanf("%ld%*[^\n]", categs);
483    getchar();
484    countup(&loopcount, 10);
485  } while (*categs > maxcategs || *categs < 1);
486}  /*initcatn*/
487
488
489void initcategs(long categs, double *rate)
490{ /* initialize category rates for HMM rates */
491  long i, loopcount, scanned;
492  char line[100], rest[100];
493  boolean done;
494
495  loopcount = 0;
496  for (;;){
497    printf("Rate for each category? (use a space to separate)\n");
498    getstryng(line);
499    done = true;
500    for (i = 0; i < categs; i++){
501      scanned = sscanf(line,"%lf %[^\n]", &rate[i],rest);
502      if ((scanned < 2 && i < (categs - 1)) ||
503       (scanned < 1 && i == (categs - 1))){
504     printf("Please enter exactly %ld values.\n",categs);
505     done = false;
506     break;
507      }
508      strcpy(line,rest);
509    }
510    if (done)
511      break;
512    countup(&loopcount, 100);
513  }
514}  /*initcategs*/
515
516
517void initprobcat(long categs, double *probsum, double *probcat)
518{ /* input probabilities of rate categores for HMM rates */
519  long i, loopcount, scanned;
520  boolean done;
521  char line[100], rest[100];
522
523  loopcount = 0;
524  do {
525    printf("Probability for each category?");
526    printf(" (use a space to separate)\n");
527    getstryng(line);
528    done = true;
529    for (i = 0; i < categs; i++){
530      scanned = sscanf(line,"%lf %[^\n]",&probcat[i],rest);
531      if ((scanned < 2 && i < (categs - 1)) ||
532       (scanned < 1 && i == (categs - 1))){
533     done = false;
534     printf("Please enter exactly %ld values.\n",categs);
535     break;}
536      strcpy(line,rest);
537    }
538    if (!done)
539      continue;
540    *probsum = 0.0;
541    for (i = 0; i < categs; i++)
542      *probsum += probcat[i];
543    if (fabs(1.0 - (*probsum)) > 0.001) {
544      done = false;
545      printf("Probabilities must add up to");
546      printf(" 1.0, plus or minus 0.001.\n");
547    }
548    countup(&loopcount, 100);
549  } while (!done);
550}  /*initprobcat*/
551
552
553void lgr(long m, double b, raterootarray lgroot)
554{ /* For use by initgammacat.  Get roots of m-th Generalized Laguerre
555     polynomial, given roots of (m-1)-th, these are to be
556     stored in lgroot[m][] */
557  long i;
558  double upper, lower, x, y;
559  boolean dwn;   /* is function declining in this interval? */
560
561  if (m == 1) {
562    lgroot[1][1] = 1.0+b;
563  } else {
564    dwn = true;
565    for (i=1; i<=m; i++) {
566      if (i < m) {
567        if (i == 1)
568          lower = 0.0;
569        else
570          lower = lgroot[m-1][i-1];
571        upper = lgroot[m-1][i];
572      } else {                 /* i == m, must search above */
573        lower = lgroot[m-1][i-1];
574        x = lgroot[m-1][m-1];
575        do {
576          x = 2.0*x;
577          y = glaguerre(m, b,x);
578        } while ((dwn && (y > 0.0)) || ((!dwn) && (y < 0.0)));
579        upper = x;
580      }
581      while (upper-lower > 0.000000001) {
582        x = (upper+lower)/2.0;
583        if (glaguerre(m, b, x) > 0.0) {
584          if (dwn)
585            lower = x;
586          else
587            upper = x;
588        } else {
589          if (dwn)
590            upper = x;
591          else
592            lower = x;
593        }
594      }
595      lgroot[m][i] = (lower+upper)/2.0;
596      dwn = !dwn;                /* switch for next one */
597    }
598  }
599} /* lgr */
600
601
602double logfac (long n)
603{ /* log(n!) values were calculated with Mathematica
604     with a precision of 30 digits */
605  long i;
606  double x;
607
608  switch (n)
609    {
610    case 0:
611      return 0.;
612    case 1:
613      return 0.;
614    case 2:
615      return 0.693147180559945309417232121458;
616    case 3:
617      return 1.791759469228055000812477358381;
618    case 4:
619      return 3.1780538303479456196469416013;
620    case 5:
621      return 4.78749174278204599424770093452;
622    case 6:
623      return 6.5792512120101009950601782929;
624    case 7:
625      return 8.52516136106541430016553103635;
626    case 8:
627      return 10.60460290274525022841722740072;
628    case 9:
629      return 12.80182748008146961120771787457;
630    case 10:
631      return 15.10441257307551529522570932925;
632    case 11:
633      return 17.50230784587388583928765290722;
634    case 12:
635      return 19.98721449566188614951736238706;
636    default:
637      x = 19.98721449566188614951736238706;
638      for (i = 13; i <= n; i++)
639        x += log(i);
640      return x;
641    }
642}
643
644
645double glaguerre(long m, double b, double x)
646{ /* Generalized Laguerre polynomial computed recursively.
647     For use by initgammacat */
648  long i;
649  double gln, glnm1, glnp1; /* L_n, L_(n-1), L_(n+1) */
650
651  if (m == 0)
652    return 1.0;
653  else {
654    if (m == 1)
655      return 1.0 + b - x;
656    else {
657      gln = 1.0+b-x;
658      glnm1 = 1.0;
659      for (i=2; i <= m; i++) {
660        glnp1 = ((2*(i-1)+b+1.0-x)*gln - (i-1+b)*glnm1)/i;
661        glnm1 = gln;
662        gln = glnp1;
663      }
664      return gln;
665    }
666  }
667} /* glaguerre */
668
669
670void initlaguerrecat(long categs, double alpha, double *rate, double *probcat)
671{ /* calculate rates and probabilities to approximate Gamma distribution
672     of rates with "categs" categories and shape parameter "alpha" using
673     rates and weights from Generalized Laguerre quadrature */
674  long i;
675  raterootarray lgroot; /* roots of GLaguerre polynomials */
676  double f, x, xi, y;
677
678  alpha = alpha - 1.0;
679  lgroot[1][1] = 1.0+alpha;
680  for (i = 2; i <= categs; i++)
681    lgr(i, alpha, lgroot);                   /* get roots for L^(a)_n */
682  /* here get weights */
683  /* Gamma weights are (1+a)(1+a/2) ... (1+a/n)*x_i/((n+1)^2 [L_{n+1}^a(x_i)]^2)  */
684  f = 1;
685  for (i = 1; i <= categs; i++)
686    f *= (1.0+alpha/i);
687  for (i = 1; i <= categs; i++) {
688    xi = lgroot[categs][i];
689    y = glaguerre(categs+1, alpha, xi);
690    x = f*xi/((categs+1)*(categs+1)*y*y);
691    rate[i-1] = xi/(1.0+alpha);
692    probcat[i-1] = x;
693  }
694} /* initlaguerrecat */
695
696
697double hermite(long n, double x)
698{ /* calculates hermite polynomial with degree n and parameter x */
699  /* seems to be unprecise for n>13 -> root finder does not converge*/
700  double h1 = 1.;
701  double h2 = 2. * x;
702  double xx = 2. * x;
703  long i;
704
705  for (i = 1; i < n; i++) {
706    xx = 2. * x * h2 - 2. * (i) * h1;
707    h1 = h2;
708    h2 = xx;
709  }
710  return xx;
711} /* hermite */
712
713
714void root_hermite(long n, double *hroot)
715{ /* find roots of Hermite polynmials */
716  long z;
717  long ii;
718  long start;
719
720  if (n % 2 == 0) {
721    start = n/2;
722    z = 1;
723  } else {
724    start = n/2 + 1;
725    z=2;
726    hroot[start-1] = 0.0;
727  }
728  for (ii = start; ii < n; ii++) {         /* search only upwards*/
729    hroot[ii] = halfroot(hermite,n,hroot[ii-1]+EPSILON, 1./n);
730    hroot[start - z] = -hroot[ii];
731    z++;
732  }
733} /* root_hermite */
734
735
736double halfroot(double (*func)(long m, double x), long n, double startx,
737                double delta)
738{ /* searches from the bound (startx) only in one direction
739     (by positive or negative delta, which results in
740     other-bound=startx+delta)
741     delta should be small.
742     (*func) is a function with two arguments  */
743  double xl;
744  double xu;
745  double xm;
746  double fu;
747  double fl;
748  double fm = 100000.;
749  double gradient;
750  boolean dwn;
751
752  /* decide if we search above or below startx and escapes to trace back
753     to the starting point that most often will be
754     the root from the previous calculation */
755  if (delta < 0) {
756    xu = startx;
757    xl = xu + delta;
758  } else {
759    xl = startx;
760    xu = xl + delta;
761  }
762  delta = fabs(delta);
763  fu = (*func)(n, xu);
764  fl = (*func)(n, xl);
765  gradient = (fl-fu)/(xl-xu);
766  while(fabs(fm) > EPSILON) {        /* is root outside of our bracket?*/
767    if ((fu<0.0 && fl<0.0) || (fu>0.0 && fl > 0.0)) {
768      xu += delta;
769      fu = (*func)(n, xu);
770      fl = (*func)(n, xl);
771      gradient = (fl-fu)/(xl-xu);
772      dwn = (gradient < 0.0) ? true : false;
773    } else {
774      xm = xl - fl / gradient;
775      fm = (*func)(n, xm);
776      if (dwn) {
777        if (fm > 0.) {
778          xl = xm;
779          fl = fm;
780        } else {
781          xu = xm;
782          fu = fm;
783        }
784      } else {
785        if (fm > 0.) {
786          xu = xm;
787          fu = fm;
788        } else {
789          xl = xm;
790          fl = fm;
791        }
792      }
793      gradient = (fl-fu)/(xl-xu);
794    }
795  }
796  return xm;
797} /* halfroot */
798
799
800void hermite_weight(long n, double * hroot, double * weights)
801{
802  /* calculate the weights for the hermite polynomial at the roots
803     using formula Abramowitz and Stegun chapter 25.4.46 p.890 */
804  long i;
805  double hr2;
806  double numerator;
807
808  numerator = exp(0.6931471805599 * ( n-1.) + logfac(n)) / (n*n);
809  for (i = 0; i < n; i++) {
810    hr2 = hermite(n-1, hroot[i]);
811    weights[i] = numerator / (hr2*hr2);
812  }
813} /* hermiteweight */
814
815
816void inithermitcat(long categs, double alpha, double *rate, double *probcat)
817{ /* calculates rates and probabilities */
818  long i;
819  double *hroot;
820  double std;
821
822  std = SQRT2 /sqrt(alpha);
823  hroot = (double *) Malloc((categs+1) * sizeof(double));
824  root_hermite(categs, hroot);         /* calculate roots */
825  hermite_weight(categs, hroot, probcat);  /* set weights */
826  for (i=0; i<categs; i++) {           /* set rates */
827    rate[i] = 1.0 + std * hroot[i];
828    probcat[i] = probcat[i];
829  }
830  free(hroot);
831} /* inithermitcat */
832
833
834void initgammacat (long categs, double alpha, double *rate, double *probcat)
835{ /* calculate rates and probabilities to approximate Gamma distribution
836   of rates with "categs" categories and shape parameter "alpha" using
837   rates and weights from Generalized Laguerre quadrature or from
838   Hermite quadrature */
839
840  if (alpha >= 100.0)
841    inithermitcat(categs, alpha, rate, probcat);
842  else
843    initlaguerrecat(categs, alpha, rate, probcat);
844} /* initgammacat */
845
846
847void inithowmany(long *howmany, long howoften)
848{/* input how many cycles */
849  long loopcount;
850
851  loopcount = 0;
852  do {
853    printf("How many cycles of %4ld trees?\n", howoften);
854    scanf("%ld%*[^\n]", howmany);
855    getchar();
856    countup(&loopcount, 10);
857  } while (*howmany <= 0);
858}  /*inithowmany*/
859
860
861
862void inithowoften(long *howoften)
863{ /* input how many trees per cycle */
864  long loopcount;
865
866  loopcount = 0;
867  do {
868    printf("How many trees per cycle?\n");
869    scanf("%ld%*[^\n]", howoften);
870    getchar();
871    countup(&loopcount, 10);
872  } while (*howoften <= 0);
873}  /*inithowoften*/
874
875
876void initlambda(double *lambda)
877{ /* input patch length parameter for autocorrelated HMM rates */
878  long loopcount;
879
880  loopcount = 0;
881  do {
882    printf("Mean block length of sites having the same rate (greater than 1)?\n");
883    scanf("%lf%*[^\n]", lambda);
884    getchar();
885    countup(&loopcount, 10);
886  } while (*lambda <= 1.0);
887  *lambda = 1.0 / *lambda;
888}  /*initlambda*/
889
890
891void initfreqs(double *freqa, double *freqc, double *freqg, double *freqt)
892{ /* input frequencies of the four bases */
893  char input[100];
894  long scanned, loopcount;
895
896  printf("Base frequencies for A, C, G, T/U (use blanks to separate)?\n");
897  loopcount = 0;
898  do {
899    getstryng(input);
900    scanned = sscanf(input,"%lf%lf%lf%lf%*[^\n]", freqa, freqc, freqg, freqt);
901    if (scanned == 4)
902      break;
903    else
904      printf("Please enter exactly 4 values.\n");
905    countup(&loopcount, 100);
906  } while (1);
907}  /* initfreqs */
908
909
910void initratio(double *ttratio)
911{ /* input transition/transversion ratio */
912  long loopcount;
913
914  loopcount = 0;
915  do {
916    printf("Transition/transversion ratio?\n");
917    scanf("%lf%*[^\n]", ttratio);
918    getchar();
919    countup(&loopcount, 10);
920  } while (*ttratio < 0.0);
921}  /* initratio */
922
923
924void initpower(double *power)
925{
926  printf("New power?\n");
927  scanf("%lf%*[^\n]", power);
928  getchar();
929}  /*initpower*/
930
931
932void initdatasets(long *datasets)
933{
934  /* handle multi-data set option */
935  long loopcount;
936  boolean done;
937
938  loopcount = 0;
939  do {
940    printf("How many data sets?\n");
941    scanf("%ld%*[^\n]", datasets);
942    getchar();
943    done = (*datasets > 1);
944      if (!done)
945     printf("Bad data sets number:  it must be greater than 1\n");
946    countup(&loopcount, 10);
947  } while (!done);
948} /* initdatasets */
949
950
951void justweights(long *datasets)
952{
953  /* handle multi-data set option by weights */
954  long loopcount;
955  boolean done;
956
957  loopcount = 0;
958  do {
959    printf("How many sets of weights?\n");
960    scanf("%ld%*[^\n]", datasets);
961    getchar();
962    done = (*datasets >= 1);
963      if (!done)
964     printf("BAD NUMBER:  it must be greater than 1\n");
965    countup(&loopcount, 10);
966  } while (!done);
967} /* justweights */
968
969
970void initterminal(boolean *ibmpc, boolean *ansi)
971{
972  /* handle terminal option */
973  if (*ibmpc) {
974    *ibmpc = false;
975    *ansi = true;
976  } else if (*ansi)
977      *ansi = false;
978    else
979      *ibmpc = true;
980}  /*initterminal*/
981
982
983void initnumlines(long *screenlines)
984{
985  long loopcount;
986
987  loopcount = 0;
988  do {
989    *screenlines = readlong("Number of lines on screen?\n");
990    countup(&loopcount, 10);
991  } while (*screenlines <= 12);
992}  /*initnumlines*/
993
994
995void initbestrees(bestelm *bestrees, long maxtrees, boolean glob)
996{
997  /* initializes either global or local field of each array in bestrees */
998  long i;
999
1000  if (glob)
1001    for (i = 0; i < maxtrees; i++)
1002      bestrees[i].gloreange = false;
1003  else
1004    for (i = 0; i < maxtrees; i++)
1005      bestrees[i].locreange = false;
1006} /* initbestrees */
1007
1008
1009void newline(FILE *filename, long i, long j, long k)
1010{
1011  /* go to new line if i is a multiple of j, indent k spaces */
1012  long m;
1013
1014  if ((i - 1) % j != 0 || i <= 1)
1015    return;
1016  putc('\n', filename);
1017  for (m = 1; m <= k; m++)
1018    putc(' ', filename);
1019}  /* newline */
1020
1021void inputnumbersold(long *spp, long *chars, long *nonodes, long n)
1022{
1023  /* input the numbers of species and of characters */
1024
1025  if (fscanf(infile, "%ld%ld", spp, chars) != 2 || *spp <= 0 || *chars <= 0) {
1026    printf(
1027    "ERROR: Unable to read the number of species or characters in data set\n");
1028    printf(
1029      "The input file is incorrect (perhaps it was not saved text only).\n");
1030  }
1031  *nonodes = *spp * 2 - n;
1032}  /* inputnumbersold */
1033
1034
1035
1036void inputnumbers(long *spp, long *chars, long *nonodes, long n)
1037{
1038  /* input the numbers of species and of characters */
1039
1040  if (fscanf(infile, "%ld%ld", spp, chars) != 2 || *spp <= 0 || *chars <= 0) {
1041    printf(
1042    "ERROR: Unable to read the number of species or characters in data set\n");
1043    printf(
1044      "The input file is incorrect (perhaps it was not saved text only).\n");
1045  }
1046  fscanf(infile, "%*[^\n]");
1047  *nonodes = *spp * 2 - n;
1048}  /* inputnumbers */
1049
1050
1051void inputnumbers2(long *spp, long *nonodes, long n)
1052{
1053  /* read species number */
1054
1055  if (fscanf(infile, "%ld", spp) != 1 || *spp <= 0) {
1056    printf("ERROR: Unable to read the number of species in data set\n");
1057    printf(
1058      "The input file is incorrect (perhaps it was not saved text only).\n");
1059  }
1060  fscanf(infile, "%*[^\n]");
1061  fprintf(outfile, "\n%4ld Populations\n", *spp);
1062  *nonodes = *spp * 2 - n;
1063}  /* inputnumbers2 */
1064
1065
1066void inputnumbers3(long *spp, long *chars)
1067{
1068  /* input the numbers of species and of characters */
1069
1070  if (fscanf(infile, "%ld%ld", spp, chars) != 2 || *spp <= 0 || *chars <= 0) {
1071    printf(
1072    "ERROR: Unable to read the number of species or characters in data set\n");
1073    printf(
1074       "The input file is incorrect (perhaps it was not saved text only).\n");
1075    exxit(-1);
1076  }
1077}  /* inputnumbers3 */
1078
1079
1080void samenumsp(long *chars, long ith)
1081{
1082  /* check if spp is same as the first set in other data sets */
1083  long cursp, curchs;
1084
1085  if (eoln(infile))
1086    scan_eoln(infile);
1087  fscanf(infile, "%ld%ld", &cursp, &curchs);
1088  if (cursp != spp) {
1089    printf(
1090         "\n\nERROR: Inconsistent number of species in data set %ld\n\n", ith);
1091    exxit(-1);
1092  }
1093  *chars = curchs;
1094} /* samenumsp */
1095
1096
1097void samenumsp2(long ith)
1098{
1099  /* check if spp is same as the first set in other data sets */
1100  long cursp;
1101
1102  if (eoln(infile))
1103    scan_eoln(infile);
1104  if (fscanf(infile, "%ld", &cursp) != 1) {
1105    printf("\n\nERROR: Unable to read number of species in data set %ld\n",
1106      ith);
1107    printf(
1108      "The input file is incorrect (perhaps it was not saved text only).\n");
1109    exxit(-1);
1110  }
1111  if (cursp != spp) {
1112    printf(
1113      "\n\nERROR: Inconsistent number of species in data set %ld\n\n", ith);
1114    exxit(-1);
1115  }
1116} /* samenumsp2 */
1117
1118
1119void readoptions(long *extranum, const char *options)
1120{ /* read option characters from input file */
1121  Char ch;
1122
1123  while (!(eoln(infile))) {
1124    ch = gettc(infile);
1125    uppercase(&ch);
1126    if (strchr(options, ch) != NULL)
1127     (* extranum)++;
1128    else if (!(ch == ' ' || ch == '\t')) {
1129      printf("BAD OPTION CHARACTER: %c\n", ch);
1130      exxit(-1);
1131    }
1132  }
1133  scan_eoln(infile);
1134}  /* readoptions */
1135
1136
1137void matchoptions(Char *ch, const char *options)
1138{  /* match option characters to those in auxiliary options line */
1139
1140  *ch = gettc(infile);
1141  uppercase(ch);
1142  if (strchr(options, *ch) == NULL) {
1143    printf("ERROR: Incorrect auxiliary options line");
1144    printf(" which starts with %c\n", *ch);
1145    exxit(-1);
1146  }
1147}  /* matchoptions */
1148
1149
1150void inputweightsold(long chars, steptr weight, boolean *weights)
1151{
1152  Char ch;
1153  int i;
1154
1155  for (i = 1; i < nmlngth ; i++)
1156    getc(infile);
1157
1158  for (i = 0; i < chars; i++) {
1159    do {
1160      if (eoln(infile))
1161        scan_eoln(infile);
1162      ch = gettc(infile);
1163      if (ch == '\n')
1164        ch = ' ';
1165    } while (ch == ' ');
1166    weight[i] = 1;
1167    if (isdigit(ch))
1168      weight[i] = ch - '0';
1169    else if (isalpha(ch)) {
1170      uppercase(&ch);
1171      weight[i] = ch - 'A' + 10;
1172    } else {
1173      printf("\n\nERROR: Bad weight character: %c\n\n", ch);
1174      exxit(-1);
1175    }
1176  }
1177  scan_eoln(infile);
1178  *weights = true;
1179} /*inputweightsold*/
1180
1181void inputweights(long chars, steptr weight, boolean *weights)
1182{
1183  /* input the character weights, 0-9 and A-Z for weights 0 - 35 */
1184  Char ch;
1185  long i;
1186
1187  for (i = 0; i < chars; i++) {
1188    do {
1189      if (eoln(weightfile))
1190        scan_eoln(weightfile);
1191      ch = gettc(weightfile);
1192      if (ch == '\n')
1193        ch = ' ';
1194    } while (ch == ' ');
1195    weight[i] = 1;
1196    if (isdigit(ch))
1197      weight[i] = ch - '0';
1198    else if (isalpha(ch)) {
1199      uppercase(&ch);
1200      weight[i] = ch - 'A' + 10;
1201    } else {
1202      printf("\n\nERROR: Bad weight character: %c\n\n", ch);
1203      exxit(-1);
1204    }
1205  }
1206  scan_eoln(weightfile);
1207  *weights = true;
1208}  /* inputweights */
1209
1210
1211void inputweights2(long a, long b, long *weightsum,
1212        steptr weight, boolean *weights, const char *prog)
1213{
1214  /* input the character weights, 0 or 1 */
1215  Char ch;
1216  long i;
1217
1218  *weightsum = 0;
1219  for (i = a; i < b; i++) {
1220    do {
1221      if (eoln(weightfile))
1222        scan_eoln(weightfile);
1223      ch = gettc(weightfile);
1224    } while (ch == ' ');
1225    weight[i] = 1;
1226    if (ch == '0' || ch == '1')
1227      weight[i] = ch - '0';
1228    else {
1229      printf("\n\nERROR: Bad weight character: %c -- ", ch);
1230      printf("weights in %s must be 0 or 1\n", prog);
1231      exxit(-1);
1232    }
1233    *weightsum += weight[i];
1234  }
1235  *weights = true;
1236  scan_eoln(weightfile);
1237}  /* inputweights2 */
1238
1239
1240void printweights(FILE *filename, long inc, long chars,
1241        steptr weight, const char *letters)
1242{
1243  /* print out the weights of sites */
1244  long i, j;
1245  boolean letterweights;
1246
1247  letterweights = false;
1248  for (i = 0; i < chars; i++)
1249    if (weight[i] > 9)
1250      letterweights = true;
1251  fprintf(filename, "\n    %s are weighted as follows:",letters);
1252  if (letterweights)
1253    fprintf(filename, " (A = 10, B = 11, etc.)\n");
1254  else
1255    putc('\n', filename);
1256  for (i = 0; i < chars; i++) {
1257    if (i % 60 == 0) {
1258      putc('\n', filename);
1259      for (j = 1; j <= nmlngth + 3; j++)
1260        putc(' ', filename);
1261    }
1262    if (weight[i+inc] < 10)
1263      fprintf(filename, "%ld", weight[i + inc]);
1264    else
1265      fprintf(filename, "%c", 'A'-10+(int)weight[i + inc]);
1266    if ((i+1) % 5 == 0 && (i+1) % 60 != 0)
1267      putc(' ', filename);
1268  }
1269  fprintf(filename, "\n\n");
1270}  /* printweights */
1271
1272
1273void inputcategs(long a, long b, steptr category, long categs,const char *prog)
1274{
1275  /* input the categories, 1-9 */
1276  Char ch;
1277  long i;
1278
1279  for (i = a; i < b; i++) {
1280    do {
1281      if (eoln(catfile))
1282        scan_eoln(catfile);
1283      ch = gettc(catfile);
1284    } while (ch == ' ');
1285    if ((ch >= '1') && (ch <= ('0'+categs)))
1286      category[i] = ch - '0';
1287    else {
1288      printf("\n\nERROR: Bad category character: %c", ch);
1289      printf(" -- categories in %s are currently 1-%ld\n", prog, categs);
1290      exxit(-1);
1291    }
1292  }
1293  scan_eoln(catfile);
1294}  /* inputcategs */
1295
1296
1297void printcategs(FILE *filename, long chars, steptr category,
1298                 const char *letters)
1299{
1300  /* print out the sitewise categories */
1301  long i, j;
1302
1303  fprintf(filename, "\n    %s are:\n",letters);
1304  for (i = 0; i < chars; i++) {
1305    if (i % 60 == 0) {
1306      putc('\n', filename);
1307      for (j = 1; j <= nmlngth + 3; j++)
1308        putc(' ', filename);
1309    }
1310    fprintf(filename, "%ld", category[i]);
1311    if ((i+1) % 10 == 0 && (i+1) % 60 != 0)
1312      putc(' ', filename);
1313  }
1314  fprintf(filename, "\n\n");
1315}  /* printcategs */
1316
1317
1318void inputfactors(long chars, Char *factor, boolean *factors)
1319{
1320  /* reads the factor symbols */
1321  long i;
1322
1323  for (i = 1; i < nmlngth; i++)
1324    gettc(infile);
1325  for (i = 0; i < (chars); i++) {
1326    if (eoln(infile))
1327      scan_eoln(infile);
1328    factor[i] = gettc(infile);
1329    if (factor[i] == '\n')
1330      factor[i] = ' ';
1331  }
1332  scan_eoln(infile);
1333  *factors = true;
1334}  /* inputfactors */
1335
1336void inputfactorsnew(long chars, Char *factor, boolean *factors)
1337{
1338  /* reads the factor symbols */
1339  long i;
1340
1341  for (i = 0; i < (chars); i++) {
1342    if (eoln(factfile))
1343      scan_eoln(factfile);
1344    factor[i] = gettc(factfile);
1345    if (factor[i] == '\n')
1346      factor[i] = ' ';
1347  }
1348  scan_eoln(factfile);
1349  *factors = true;
1350}  /* inputfactorsnew */
1351
1352void printfactors(FILE *filename, long chars, Char *factor, const char *letters)
1353{
1354  /* print out list of factor symbols */
1355  long i;
1356
1357  fprintf(filename, "Factors%s:\n\n", letters);
1358  for (i = 1; i <= nmlngth - 5; i++)
1359    putc(' ', filename);
1360  for (i = 1; i <= (chars); i++) {
1361    newline(filename, i, 55, nmlngth + 3);
1362    putc(factor[i - 1], filename);
1363    if (i % 5 == 0)
1364      putc(' ', filename);
1365  }
1366  putc('\n', filename);
1367}  /* printfactors */
1368
1369
1370void headings(long chars, const char *letters1, const char *letters2)
1371{
1372  long i, j;
1373
1374  putc('\n', outfile);
1375  j = nmlngth + (chars + (chars - 1) / 10) / 2 - 5;
1376  if (j < nmlngth - 1)
1377    j = nmlngth - 1;
1378  if (j > 37)
1379    j = 37;
1380  fprintf(outfile, "Name");
1381  for (i = 1; i <= j; i++)
1382    putc(' ', outfile);
1383  fprintf(outfile, "%s\n", letters1);
1384  fprintf(outfile, "----");
1385  for (i = 1; i <= j; i++)
1386    putc(' ', outfile);
1387  fprintf(outfile, "%s\n\n", letters2);
1388}  /* headings */
1389
1390
1391void initname(long i)
1392{
1393  /* read in species name */
1394  long j;
1395
1396  for (j = 0; j < nmlngth; j++) {
1397    if (eoff(infile) || eoln(infile)) {
1398        int j2;
1399        if (eoff(infile)) {
1400            printf("\n\nERROR: end-of-file");
1401        }
1402        else {
1403            printf("\n\nERROR: end-of-line");
1404        }
1405
1406        printf(" in the middle of species name for species %ld (got '", i+1);
1407        for (j2 = 0; j2<j; ++j2) fputc(nayme[i][j2], stdout);
1408        printf("')\n\n", i+1);
1409        exxit(-1);
1410    }
1411    nayme[i][j] = gettc(infile);
1412    if ((nayme[i][j] == '(') || (nayme[i][j] == ')') || (nayme[i][j] == ':')
1413        || (nayme[i][j] == ',') || (nayme[i][j] == ';') || (nayme[i][j] == '[')
1414        || (nayme[i][j] == ']')) {
1415      printf("\nERROR: Species name may not contain characters ( ) : ; , [ ] \n");
1416      printf("       In name of species number %ld there is character %c\n\n",
1417              i+1, nayme[i][j]);
1418      exxit(-1);
1419    }
1420  }
1421} /* initname */
1422
1423
1424void findtree(boolean *found,long *pos,long nextree,long *place,bestelm *bestrees)
1425{
1426  /* finds tree given by array place in array bestrees by binary search */
1427  /* used by dnacomp, dnapars, dollop, mix, & protpars */
1428  long i, lower, upper;
1429  boolean below, done;
1430
1431  below = false;
1432  lower = 1;
1433  upper = nextree - 1;
1434  (*found) = false;
1435  while (!(*found) && lower <= upper) {
1436    (*pos) = (lower + upper) / 2;
1437    i = 3;
1438    done = false;
1439    while (!done) {
1440      done = (i > spp);
1441      if (!done)
1442        done = (place[i - 1] != bestrees[(*pos) - 1].btree[i - 1]);
1443      if (!done)
1444        i++;
1445    }
1446    (*found) = (i > spp);
1447    if (*found)
1448      break;
1449    below = (place[i - 1] <  bestrees[(*pos )- 1].btree[i - 1]);
1450    if (below)
1451      upper = (*pos) - 1;
1452    else
1453      lower = (*pos) + 1;
1454  }
1455  if (!(*found) && !below)
1456    (*pos)++;
1457}  /* findtree */
1458
1459
1460void addtree(long pos,long *nextree,boolean collapse,long *place,bestelm *bestrees)
1461{
1462  /* puts tree from array place in its proper position in array bestrees */
1463  /* used by dnacomp, dnapars, dollop, mix, & protpars */
1464  long i;
1465
1466  for (i = *nextree - 1; i >= pos; i--){
1467    memcpy(bestrees[i].btree, bestrees[i - 1].btree, spp * sizeof(long));
1468    bestrees[i].gloreange = bestrees[i - 1].gloreange;
1469    bestrees[i - 1].gloreange = false;
1470    bestrees[i].locreange = bestrees[i - 1].locreange;
1471    bestrees[i - 1].locreange = false;
1472    bestrees[i].collapse = bestrees[i - 1].collapse;
1473  }
1474  for (i = 0; i < spp; i++)
1475    bestrees[pos - 1].btree[i] = place[i];
1476    bestrees[pos - 1].collapse = collapse;
1477  (*nextree)++;
1478}  /* addtree */
1479
1480
1481long findunrearranged(bestelm *bestrees, long nextree, boolean glob)
1482{
1483  /* finds bestree with either global or local field false */
1484  long i;
1485
1486  if (glob) {
1487    for (i = 0; i < nextree - 1; i++)
1488      if (!bestrees[i].gloreange)
1489        return i;
1490  } else {
1491    for (i = 0; i < nextree - 1; i++)
1492      if (!bestrees[i].locreange)
1493        return i;
1494  }
1495  return -1;
1496} /* findunrearranged */
1497
1498
1499boolean torearrange(bestelm *bestrees, long nextree)
1500{ /* sees if any best tree is yet to be rearranged */
1501
1502  if (findunrearranged(bestrees, nextree, true) >= 0)
1503    return true;
1504  else if (findunrearranged(bestrees, nextree, false) >= 0)
1505    return true;
1506  else
1507    return false;
1508} /* torearrange */
1509
1510
1511void reducebestrees(bestelm *bestrees, long *nextree)
1512{
1513  /* finds best trees with collapsible branches and deletes them */
1514  long i, j;
1515
1516  i = 0;
1517  j = *nextree - 2;
1518  do {
1519    while (!bestrees[i].collapse && i < *nextree - 1) i++;
1520    while (bestrees[j].collapse && j >= 0) j--;
1521    if (i < j) {
1522      memcpy(bestrees[i].btree, bestrees[j].btree, spp * sizeof(long));
1523      bestrees[i].gloreange = bestrees[j].gloreange;
1524      bestrees[i].locreange = bestrees[j].locreange;
1525      bestrees[i].collapse = false;
1526      bestrees[j].collapse = true;
1527    }
1528  } while (i < j);
1529  *nextree = i + 1;
1530} /* reducebestrees */
1531
1532
1533void shellsort(double *a, long *b, long n)
1534{ /* Shell sort keeping a, b in same order */
1535  /* used by dnapenny, dolpenny, & penny */
1536  long gap, i, j, itemp;
1537  double rtemp;
1538
1539  gap = n / 2;
1540  while (gap > 0) {
1541    for (i = gap + 1; i <= n; i++) {
1542      j = i - gap;
1543      while (j > 0) {
1544     if (a[j - 1] > a[j + gap - 1]) {
1545       rtemp = a[j - 1];
1546       a[j - 1] = a[j + gap - 1];
1547       a[j + gap - 1] = rtemp;
1548       itemp = b[j - 1];
1549       b[j - 1] = b[j + gap - 1];
1550       b[j + gap - 1] = itemp;
1551     }
1552     j -= gap;
1553      }
1554    }
1555    gap /= 2;
1556  }
1557}  /* shellsort */
1558
1559
1560void getch(Char *c, long *parens, FILE *treefile)
1561{ /* get next nonblank character */
1562
1563  do {
1564    if (eoln(treefile))
1565      scan_eoln(treefile);
1566    (*c) = gettc(treefile);
1567
1568    if ((*c) == '\n' || (*c) == '\t')
1569      (*c) = ' ';
1570  } while ( *c == ' ' && !eoff(treefile) );
1571  if ((*c) == '(')
1572    (*parens)++;
1573  if ((*c) == ')')
1574    (*parens)--;
1575}  /* getch */
1576
1577
1578void getch2(Char *c, long *parens)
1579{ /* get next nonblank character */
1580  do {
1581    if (eoln(intree))
1582      scan_eoln(intree);
1583    *c = gettc(intree);
1584    if (*c == '\n' || *c == '\t')
1585      *c = ' ';
1586  } while (!(*c != ' ' || eoff(intree)));
1587  if (*c == '(')
1588   (*parens)++;
1589  if (*c == ')')
1590    (*parens)--;
1591}  /* getch2 */
1592
1593
1594void findch(Char c, Char *ch, long which)
1595{ /* scan forward until find character c */
1596  boolean done;
1597  long dummy_parens;
1598  done = false;
1599  while (!done) {
1600    if (c == ',') {
1601      if (*ch == '(' || *ch == ')' || *ch == ';') {
1602        printf(
1603      "\n\nERROR in user tree %ld: unmatched parenthesis or missing comma\n\n",
1604          which);
1605        exxit(-1);
1606      } else if (*ch == ',')
1607        done = true;
1608    } else if (c == ')') {
1609      if (*ch == '(' || *ch == ',' || *ch == ';') {
1610        printf("\n\nERROR in user tree %ld: ", which);
1611        printf("unmatched parenthesis or non-bifurcated node\n\n");
1612        exxit(-1);
1613      } else {
1614        if (*ch == ')')
1615          done = true;
1616      }
1617    } else if (c == ';') {
1618      if (*ch != ';') {
1619        printf("\n\nERROR in user tree %ld: ", which);
1620        printf("unmatched parenthesis or missing semicolon\n\n");
1621        exxit(-1);
1622      } else
1623        done = true;
1624    }
1625    if (*ch != ')' && done)
1626      continue;
1627   getch(ch, &dummy_parens, intree);
1628  }
1629}  /* findch */
1630
1631
1632void findch2(Char c, long *lparens, long *rparens, Char *ch)
1633{ /* skip forward in user tree until find character c */
1634  boolean done;
1635  long dummy_parens;
1636  done = false;
1637  while (!done) {
1638    if (c == ',') {
1639      if (*ch == '(' || *ch == ')' || *ch == ':' || *ch == ';') {
1640        printf("\n\nERROR in user tree: ");
1641        printf("unmatched parenthesis, missing comma");
1642        printf(" or non-trifurcated base\n\n");
1643     exxit(-1);
1644      } else if (*ch == ',')
1645        done = true;
1646    } else if (c == ')') {
1647      if (*ch == '(' || *ch == ',' || *ch == ':' || *ch == ';') {
1648        printf(
1649   "\n\nERROR in user tree: unmatched parenthesis or non-bifurcated node\n\n");
1650        exxit(-1);
1651      } else if (*ch == ')') {
1652        (*rparens)++;
1653        if ((*lparens) > 0 && (*lparens) == (*rparens)) {
1654          if ((*lparens) == spp - 2) {
1655           getch(ch, &dummy_parens, intree);
1656            if (*ch != ';') {
1657              printf( "\n\nERROR in user tree: ");
1658              printf("unmatched parenthesis or missing semicolon\n\n");
1659              exxit(-1);
1660            }
1661          }
1662        }
1663     done = true;
1664      }
1665    }
1666    if (*ch != ')' && done)
1667      continue;
1668    if (*ch == ')')
1669     getch(ch, &dummy_parens, intree);
1670  }
1671}  /* findch2 */
1672
1673void processlength(double *valyew, double *divisor, Char *ch,
1674        boolean *minusread, FILE *treefile, long *parens)
1675{ /* read a branch length from a treefile */
1676  long digit, ordzero;
1677  boolean pointread;
1678
1679  ordzero = '0';
1680  *minusread = false;
1681  pointread = false;
1682  *valyew = 0.0;
1683  *divisor = 1.0;
1684  getch(ch, parens, treefile);
1685  digit = (long)(*ch - ordzero);
1686  while ( ((digit <= 9) && (digit >= 0)) || *ch == '.' || *ch == '-') {
1687    if (*ch == '.' )
1688      pointread = true;
1689    else if (*ch == '-' )
1690      *minusread = true;
1691    else {
1692      *valyew = *valyew * 10.0 + digit;
1693      if (pointread)
1694        *divisor *= 10.0;
1695    }
1696    getch(ch, parens, treefile);
1697    digit = (long)(*ch - ordzero);
1698  }
1699  if (*minusread)
1700    *valyew = -(*valyew);
1701}  /* processlength */
1702
1703
1704void writename(long start, long n, long *enterorder)
1705{ /* write species name and number in entry order */
1706  long i, j;
1707
1708  for (i = start; i < start+n; i++) {
1709    printf(" %3ld. ", i+1);
1710    for (j = 0; j < nmlngth; j++)
1711      putchar(nayme[enterorder[i] - 1][j]);
1712    putchar('\n');
1713    fflush(stdout);
1714  }
1715}  /* writename */
1716
1717
1718void memerror()
1719{
1720  printf("Error allocating memory\n");
1721  exxit(-1);
1722}  /* memerror */
1723
1724
1725void odd_malloc(long x)
1726{ /* error message if attempt to malloc too little or too much memory */
1727  printf ("ERROR: a function asked for an inappropriate amount of memory:");
1728  printf ("  %ld bytes\n", x);
1729  printf ("       This can mean one of two things:\n");
1730  printf ("       1.  The input file is incorrect");
1731  printf (" (perhaps it was not saved as Text Only),\n");
1732  printf ("       2.  There is a bug in the program.\n");
1733  printf ("       Please check your input file carefully.\n");
1734  printf ("       If it seems to be a bug, please mail joe@gs.washington.edu\n");
1735  printf ("       with the name of the program, your computer system type,\n");
1736  printf ("       a full description of the problem, and with the input data file.\n");
1737  printf ("       (which should be in the body of the message, not as an Attachment).\n");
1738
1739  /* abort() can be used to crash
1740   * for debugging */
1741
1742  exxit(-1);
1743}
1744
1745
1746MALLOCRETURN *mymalloc(long x)
1747{ /* wrapper for malloc, allowing error message if too little, too much */
1748  MALLOCRETURN *new_block;
1749
1750  if ((x <= 0) ||
1751      (x > TOO_MUCH_MEMORY))
1752    odd_malloc(x);
1753
1754  new_block = (MALLOCRETURN *)calloc(1,x);
1755
1756  if (!new_block) {
1757    memerror();
1758    return (MALLOCRETURN *) new_block;
1759  } else
1760    return (MALLOCRETURN *) new_block;
1761} /* mymalloc */
1762
1763
1764void gnu(node **grbg, node **p)
1765{ /* this and the following are do-it-yourself garbage collectors.
1766     Make a new node or pull one off the garbage list */
1767
1768  if (*grbg != NULL) {
1769    *p = *grbg;
1770    *grbg = (*grbg)->next;
1771  } else
1772    *p = (node *)Malloc(sizeof(node));
1773
1774  (*p)->back       = NULL;
1775  (*p)->next       = NULL;
1776  (*p)->tip        = false;
1777  (*p)->times_in_tree = 0.0;
1778  (*p)->r          = 0.0;
1779  (*p)->theta      = 0.0;
1780  (*p)->x          = NULL;
1781  (*p)->protx           = NULL;        /* for the sake of proml     */
1782}  /* gnu */
1783
1784
1785void chuck(node **grbg, node *p)
1786{ /* collect garbage on p -- put it on front of garbage list */
1787  p->back = NULL;
1788  p->next = *grbg;
1789  *grbg = p;
1790}  /* chuck */
1791
1792
1793void zeronumnuc(node *p, long endsite)
1794{
1795  long i,j;
1796
1797  for (i = 0; i < endsite; i++)
1798    for (j = (long)A; j <= (long)O; j++)
1799      p->numnuc[i][j] = 0;
1800} /* zeronumnuc */
1801
1802
1803void zerodiscnumnuc(node *p, long endsite)
1804{
1805  long i,j;
1806
1807  for (i = 0; i < endsite; i++)
1808    for (j = (long)zero; j <= (long)seven; j++)
1809      p->discnumnuc[i][j] = 0;
1810} /* zerodiscnumnuc */
1811
1812
1813void allocnontip(node *p, long *zeros, long endsite)
1814{ /* allocate an interior node */
1815  /* used by dnacomp, dnapars, & dnapenny */
1816
1817  p->numsteps = (steptr)Malloc(endsite*sizeof(long));
1818  p->oldnumsteps = (steptr)Malloc(endsite*sizeof(long));
1819  p->base = (baseptr)Malloc(endsite*sizeof(long));
1820  p->oldbase = (baseptr)Malloc(endsite*sizeof(long));
1821  p->numnuc = (nucarray *)Malloc(endsite*sizeof(nucarray));
1822  memcpy(p->base, zeros, endsite*sizeof(long));
1823  memcpy(p->numsteps, zeros, endsite*sizeof(long));
1824  memcpy(p->oldbase, zeros, endsite*sizeof(long));
1825  memcpy(p->oldnumsteps, zeros, endsite*sizeof(long));
1826  zeronumnuc(p, endsite);
1827}  /* allocnontip */
1828
1829
1830void allocdiscnontip(node *p, long *zeros, unsigned char *zeros2, long endsite)
1831{ /* allocate an interior node */
1832  /* used by pars */
1833
1834  p->numsteps = (steptr)Malloc(endsite*sizeof(long));
1835  p->oldnumsteps = (steptr)Malloc(endsite*sizeof(long));
1836  p->discbase = (discbaseptr)Malloc(endsite*sizeof(unsigned char));
1837  p->olddiscbase = (discbaseptr)Malloc(endsite*sizeof(unsigned char));
1838  p->discnumnuc = (discnucarray *)Malloc(endsite*sizeof(discnucarray));
1839  memcpy(p->discbase, zeros2, endsite*sizeof(unsigned char));
1840  memcpy(p->numsteps, zeros, endsite*sizeof(long));
1841  memcpy(p->olddiscbase, zeros2, endsite*sizeof(unsigned char));
1842  memcpy(p->oldnumsteps, zeros, endsite*sizeof(long));
1843  zerodiscnumnuc(p, endsite);
1844}  /* allocdiscnontip */
1845
1846
1847void allocnode(node **anode, long *zeros, long endsite)
1848{ /* allocate a node */
1849  /* used by dnacomp, dnapars, & dnapenny */
1850
1851  *anode = (node *)Malloc(sizeof(node));
1852  allocnontip(*anode, zeros, endsite);
1853}  /* allocnode */
1854
1855
1856void allocdiscnode(node **anode, long *zeros, unsigned char *zeros2,
1857        long endsite)
1858{ /* allocate a node */
1859  /* used by pars */
1860
1861  *anode = (node *)Malloc(sizeof(node));
1862  allocdiscnontip(*anode, zeros, zeros2, endsite);
1863}  /* allocdiscnontip */
1864
1865
1866void gnutreenode(node **grbg, node **p, long i, long endsite, long *zeros)
1867{ /* this and the following are do-it-yourself garbage collectors.
1868     Make a new node or pull one off the garbage list */
1869
1870  if (*grbg != NULL) {
1871    *p = *grbg;
1872    *grbg = (*grbg)->next;
1873    memcpy((*p)->numsteps, zeros, endsite*sizeof(long));
1874    memcpy((*p)->oldnumsteps, zeros, endsite*sizeof(long));
1875    memcpy((*p)->base, zeros, endsite*sizeof(long));
1876    memcpy((*p)->oldbase, zeros, endsite*sizeof(long));
1877    zeronumnuc(*p, endsite);
1878  } else
1879    allocnode(p, zeros, endsite);
1880  (*p)->back = NULL;
1881  (*p)->next = NULL;
1882  (*p)->tip = false;
1883  (*p)->visited = false;
1884  (*p)->index = i;
1885  (*p)->numdesc = 0;
1886  (*p)->sumsteps = 0.0;
1887}  /* gnutreenode */
1888
1889
1890void gnudisctreenode(node **grbg, node **p, long i,
1891        long endsite, long *zeros, unsigned char *zeros2)
1892{ /* this and the following are do-it-yourself garbage collectors.
1893     Make a new node or pull one off the garbage list */
1894
1895  if (*grbg != NULL) {
1896    *p = *grbg;
1897    *grbg = (*grbg)->next;
1898    memcpy((*p)->numsteps, zeros, endsite*sizeof(long));
1899    memcpy((*p)->oldnumsteps, zeros, endsite*sizeof(long));
1900    memcpy((*p)->discbase, zeros2, endsite*sizeof(unsigned char));
1901    memcpy((*p)->olddiscbase, zeros2, endsite*sizeof(unsigned char));
1902    zerodiscnumnuc(*p, endsite);
1903  } else
1904    allocdiscnode(p, zeros, zeros2, endsite);
1905  (*p)->back = NULL;
1906  (*p)->next = NULL;
1907  (*p)->tip = false;
1908  (*p)->visited = false;
1909  (*p)->index = i;
1910  (*p)->numdesc = 0;
1911  (*p)->sumsteps = 0.0;
1912}  /* gnudisctreenode */
1913
1914
1915void chucktreenode(node **grbg, node *p)
1916{ /* collect garbage on p -- put it on front of garbage list */
1917
1918  p->back = NULL;
1919  p->next = *grbg;
1920  *grbg = p;
1921}  /* chucktreenode */
1922
1923
1924void setupnode(node *p, long i)
1925{ /* initialization of node pointers, variables */
1926
1927  p->next = NULL;
1928  p->back = NULL;
1929  p->times_in_tree = (double) i * 1.0;
1930  p->index = i;
1931  p->tip = false;
1932}  /* setupnode */
1933
1934
1935long count_sibs (node *p)
1936{ /* Count the number of nodes in a ring, return the total number of */
1937  /* nodes excluding the one passed into the function (siblings)     */
1938  node *q;
1939  long return_int = 0;
1940
1941  if (p->tip) {
1942   printf ("Error: the function count_sibs called on a tip.  This is a bug.\n");
1943    exxit (-1);
1944  }
1945
1946  q = p->next;
1947  while (q != p) {
1948    if (q == NULL) {
1949      printf ("Error: a loop of nodes was not closed.\n");
1950      exxit (-1);
1951    } else {
1952      return_int++;
1953      q = q->next;
1954    }
1955  }
1956
1957  return return_int;
1958}  /* count_sibs */
1959
1960
1961void inittrav (node *p)
1962{ /* traverse to set pointers uninitialized on inserting */
1963  long i, num_sibs;
1964  node *sib_ptr;
1965
1966  if (p == NULL)
1967    return;
1968  if (p->tip)
1969    return;
1970  num_sibs = count_sibs (p);
1971  sib_ptr  = p;
1972  for (i=0; i < num_sibs; i++) {
1973    sib_ptr              = sib_ptr->next;
1974    sib_ptr->initialized = false;
1975    inittrav(sib_ptr->back);
1976  }
1977} /* inittrav */
1978
1979
1980void commentskipper(FILE ***intree, long *bracket)
1981{ /* skip over comment bracket contents in reading tree */
1982  char c;
1983
1984  c = gettc(**intree);
1985
1986  while (c != ']') {
1987
1988    if(feof(**intree)) {
1989      printf("\n\nERROR: Unmatched comment brackets\n\n");
1990      exxit(-1);
1991    }
1992
1993    if(c == '[') {
1994      (*bracket)++;
1995      commentskipper(intree, bracket);
1996    }
1997    c = gettc(**intree);
1998  }
1999  (*bracket)--;
2000}  /* commentskipper */
2001
2002
2003long countcomma(FILE **treefile, long *comma)
2004{
2005  /* Modified by Dan F. 11/10/96 */
2006
2007  /* The next line inserted so this function leaves the file pointing
2008     to where it found it, not just re-winding it. */
2009  long orig_position = ftell (*treefile);
2010
2011  Char c;
2012  long  lparen = 0;
2013  long bracket = 0;
2014  (*comma) = 0;
2015
2016
2017  for (;;){
2018    c = getc(*treefile);
2019    if (feof(*treefile))
2020      break;
2021    if (c == ';')
2022      break;
2023    if (c == ',')
2024      (*comma)++;
2025    if (c == '(')
2026         lparen++;
2027    if (c == '[') {
2028      bracket++;
2029      commentskipper(&treefile, &bracket);
2030    }
2031  }
2032
2033  /* Don't just rewind, */
2034  /* rewind (*treefile); */
2035  /* Re-set to where it pointed when the function was called */
2036
2037  fseek (*treefile, orig_position, SEEK_SET);
2038
2039  return lparen + (*comma);
2040}  /*countcomma*/
2041/* countcomma rewritten so it passes back both lparen+comma to allocate nodep
2042   and a pointer to the comma variable.  This allows the tree to know how many
2043   species exist, and the tips to be placed in the front of the nodep array */
2044
2045
2046long countsemic(FILE **treefile)
2047{ /* Used to determine the number of user trees.  Return
2048     either a: the number of semicolons in the file outside comments
2049     or b: the first integer in the file */
2050  Char c;
2051  long return_val, semic = 0;
2052  long bracket = 0;
2053
2054  /* Eat all whitespace */
2055  c = gettc(*treefile);
2056  while ((c == ' ')  ||
2057      (c == '\t') ||
2058      (c == '\n')) {
2059    c = gettc(*treefile);
2060  }
2061
2062  /* Then figure out if the first non-white character is a digit; if
2063     so, return it */
2064  if (isdigit (c)) {
2065    return_val = atoi(&c);
2066  } else {
2067
2068    /* Loop past all characters, count the number of semicolons
2069       outside of comments */
2070    for (;;){
2071      c = fgetc(*treefile);
2072      if (feof(*treefile))
2073     break;
2074      if (c == ';')
2075     semic++;
2076      if (c == '[') {
2077     bracket++;
2078     commentskipper(&treefile, &bracket);
2079      }
2080    }
2081    return_val = semic;
2082  }
2083
2084  rewind (*treefile);
2085  return return_val;
2086}  /* countsemic */
2087
2088
2089void hookup(node *p, node *q)
2090{ /* hook together two nodes */
2091
2092  p->back = q;
2093  q->back = p;
2094}  /* hookup */
2095
2096
2097void link_trees(long local_nextnum, long nodenum, long local_nodenum,
2098        pointarray nodep)
2099{
2100  if(local_nextnum == 0)
2101    hookup(nodep[nodenum],nodep[local_nodenum]);
2102  else if(local_nextnum == 1)
2103      hookup(nodep[nodenum], nodep[local_nodenum]->next);
2104    else if(local_nextnum == 2)
2105        hookup(nodep[nodenum],nodep[local_nodenum]->next->next);
2106      else
2107        printf("Error in Link_Trees()");
2108} /* link_trees() */
2109
2110
2111void allocate_nodep(pointarray *nodep, FILE **treefile, long  *precalc_tips)
2112{ /* pre-compute space and allocate memory for nodep */
2113
2114  long numnodes;      /* returns number commas & (    */
2115  long numcom = 0;        /* returns number commas */
2116
2117  numnodes = countcomma(treefile, &numcom) + 1;
2118  *nodep      = (pointarray)Malloc(2*numnodes*sizeof(node *));
2119
2120  (*precalc_tips) = numcom + 1;        /* this will be used in placing the
2121                                          tip nodes in the front region of
2122                                          nodep.  Used for species check?  */
2123} /* allocate_nodep -plc */
2124
2125
2126void malloc_pheno (node *p, long endsite, long rcategs)
2127{ /* Allocate the phenotype arrays; used by dnaml */
2128  long i;
2129
2130  p->= (phenotype)Malloc(endsite*sizeof(ratelike));
2131  for (i = 0; i < endsite; i++)
2132    p->x[i]  = (ratelike)Malloc(rcategs*sizeof(sitelike));
2133} /* malloc_pheno */
2134
2135
2136void malloc_ppheno (node *p,long endsite, long rcategs)
2137{
2138  /* Allocate the phenotype arrays; used by proml */
2139  long i;
2140
2141  p->protx  = (pphenotype)Malloc(endsite*sizeof(pratelike));
2142  for (i = 0; i < endsite; i++)
2143    p->protx[i]  = (pratelike)Malloc(rcategs*sizeof(psitelike));
2144} /* malloc_ppheno */
2145
2146
2147long take_name_from_tree (Char *ch, Char *str, FILE *treefile)
2148{
2149  /* This loop takes in the name from the tree.
2150     Return the length of the name string.  */
2151
2152  long name_length = 0;
2153
2154  do {
2155    if ((*ch) == '_')
2156      (*ch) = ' ';
2157    str[name_length++] = (*ch);
2158    if (eoln(treefile))
2159      scan_eoln(treefile);
2160    (*ch) = gettc(treefile);
2161    if (*ch == '\n')
2162      *ch = ' ';
2163  } while ((*ch) != ':' && (*ch) != ',' && (*ch) != ')' &&
2164        (*ch) != '[' && (*ch) != ';' && name_length <= MAXNCH);
2165  return name_length;
2166}  /* take_name_from_tree */
2167
2168
2169void match_names_to_data (Char *str, pointarray treenode, node **p, long spp)
2170{
2171  /* This loop matches names taken from treefile to indexed names in
2172     the data file */
2173
2174  boolean found;
2175  long i, n;
2176
2177  n = 1;
2178  do {
2179    found = true;
2180    for (i = 0; i < nmlngth; i++) {
2181      found = (found && ((str[i] == nayme[n - 1][i]) ||
2182        (((nayme[n - 1][i] == '_') && (str[i] == ' ')) ||
2183        ((nayme[n - 1][i] == ' ') && (str[i] == '\0')))));
2184    }
2185
2186    if (found)
2187      *p = treenode[n - 1];
2188    else
2189      n++;
2190
2191  } while (!(n > spp || found));
2192
2193  if (n > spp) {
2194    printf("\n\nERROR: Cannot find species: ");
2195    for (i = 0; (str[i] != '\0') && (i < MAXNCH); i++)
2196      putchar(str[i]);
2197    printf(" in data file\n\n");
2198    exxit(-1);
2199  }
2200}  /* match_names_to_data */
2201
2202
2203void addelement(node **p, node *q, Char *ch, long *parens, FILE *treefile,
2204        pointarray treenode, boolean *goteof, boolean *first, pointarray nodep,
2205        long *nextnode, long *ntips, boolean *haslengths, node **grbg,
2206        initptr initnode)
2207{
2208  /* Recursive procedure adds nodes to user-defined tree
2209     This is the main (new) tree-reading procedure */
2210
2211  node *pfirst;
2212  long i, len = 0, nodei = 0;
2213  boolean notlast;
2214  Char str[MAXNCH];
2215  node *r;
2216
2217  if ((*ch) == '(') {
2218    (*nextnode)++;          /* get ready to use new interior node */
2219    nodei = *nextnode;      /* do what needs to be done at bottom */
2220    (*initnode)(p, grbg, q, len, nodei, ntips,
2221                  parens, bottom, treenode, nodep, str, ch, treefile);
2222    pfirst      = (*p);
2223    notlast = true;
2224    while (notlast) {          /* loop through immediate descendants */
2225      (*initnode)(&(*p)->next, grbg, q,
2226                   len, nodei, ntips, parens, nonbottom, treenode,
2227                   nodep, str, ch, treefile);
2228                       /* ... doing what is done before each */
2229      r = (*p)->next;
2230      getch(ch, parens, treefile);      /* look for next character */
2231
2232      addelement(&(*p)->next->back, (*p)->next, ch, parens, treefile,
2233        treenode, goteof, first, nodep, nextnode, ntips,
2234        haslengths, grbg, initnode);        /* call self recursively */
2235
2236      (*initnode)(&r, grbg, q, len, nodei, ntips,
2237                    parens, hslength, treenode, nodep, str, ch, treefile);
2238                           /* do what is done after each about length */
2239      pfirst->numdesc++;               /* increment number of descendants */
2240      *p = r;                         /* make r point back to p */
2241
2242      if ((*ch) == ')') {
2243        notlast = false;
2244        do {
2245          getch(ch, parens, treefile);
2246        } while ((*ch) != ',' && (*ch) != ')' &&
2247           (*ch) != '[' && (*ch) != ';' && (*ch) != ':');
2248      }
2249    }
2250
2251    (*p)->next = pfirst;
2252    (*p)       = pfirst;
2253
2254  } else if ((*ch) != ')') {       /* if it's a species name */
2255    for (i = 0; i < MAXNCH; i++)   /* fill string with nulls */
2256      str[i] = '\0';
2257
2258    len = take_name_from_tree (ch, str, treefile);  /* get the name */
2259
2260    if ((*ch) == ')')
2261      (*parens)--;         /* decrement count of open parentheses */
2262    (*initnode)(p, grbg, q, len, nodei, ntips,
2263                  parens, tip, treenode, nodep, str, ch, treefile);
2264                              /* do what needs to be done at a tip */
2265  } else
2266    getch(ch, parens, treefile);
2267  if (q != NULL)
2268    hookup(q, (*p));                    /* now hook up */
2269  (*initnode)(p, grbg, q, len, nodei, ntips,
2270                parens, iter, treenode, nodep, str, ch, treefile);
2271  if ((*ch) == ':')
2272    (*initnode)(p, grbg, q, len, nodei, ntips,
2273                  parens, length, treenode, nodep, str, ch, treefile);
2274                                   /* do what needs to be done with length */
2275  else if ((*ch) != ';' && (*ch) != '[')
2276    (*initnode)(p, grbg, q, len, nodei, ntips,
2277                  parens, hsnolength, treenode, nodep, str, ch, treefile);
2278                             /* ... or what needs to be done when no length */
2279  if ((*ch) == '[')
2280    (*initnode)(p, grbg, q, len, nodei, ntips,
2281                  parens, treewt, treenode, nodep, str, ch, treefile);
2282                             /* ... for processing a tree weight */
2283  else if ((*ch) == ';')     /* ... and at end of tree */
2284    (*initnode)(p, grbg, q, len, nodei, ntips,
2285                  parens, unittrwt, treenode, nodep, str, ch, treefile);
2286}  /* addelement */
2287
2288
2289void treeread (FILE *treefile, node **root, pointarray treenode,
2290        boolean *goteof, boolean *first, pointarray nodep,
2291        long *nextnode, boolean *haslengths, node **grbg, initptr initnode)
2292{
2293  /* read in user-defined tree and set it up */
2294  char  ch;
2295  long parens = 0;
2296  long ntips = 0;
2297
2298  (*goteof) = false;
2299  (*nextnode) = spp;
2300
2301  /* eat blank lines */
2302  while (eoln(treefile) && !eoff(treefile))
2303    scan_eoln(treefile);
2304
2305  if (eoff(treefile)) {
2306    (*goteof) = true;
2307    return;
2308  }
2309
2310  getch(&ch, &parens, treefile);
2311
2312  while (ch != '(') {
2313    /* Eat everything in the file (i.e. digits, tabs) until you
2314       encounter an open-paren */
2315    getch(&ch, &parens, treefile);
2316  }
2317  (*haslengths) = true;
2318  addelement(root, NULL, &ch, &parens, treefile,
2319         treenode, goteof, first, nodep, nextnode, &ntips,
2320         haslengths, grbg, initnode);
2321
2322  /* Eat blank lines and end of current line*/
2323  do {
2324    scan_eoln(treefile);
2325  }
2326  while (eoln(treefile) && !eoff(treefile));
2327
2328  (*first) = false;
2329  if (parens != 0) {
2330    printf("\n\nERROR in tree file: unmatched parentheses\n\n");
2331    exxit(-1);
2332  }
2333}  /* treeread */
2334
2335
2336void addelement2(node *q, Char *ch, long *parens, FILE *treefile,
2337        pointarray treenode, boolean lngths, double *trweight, boolean *goteof,
2338        long *nextnode, long *ntips, long no_species, boolean *haslengths)
2339{
2340  /* recursive procedure adds nodes to user-defined tree
2341     -- old-style bifurcating-only version */
2342  node *pfirst = NULL, *p;
2343  long i, len, current_loop_index;
2344  boolean notlast, minusread;
2345  Char str[MAXNCH];
2346  double valyew, divisor;
2347
2348  if ((*ch) == '(') {
2349
2350    current_loop_index = (*nextnode) + spp;
2351    (*nextnode)++;
2352
2353    /* This is an assignment of an interior node */
2354    p = treenode[current_loop_index];
2355    pfirst = p;
2356    notlast = true;
2357    while (notlast) {
2358      /* This while loop goes through a circle (triad for
2359      bifurcations) of nodes */
2360      p = p->next;
2361      /* added to ensure that non base nodes in loops have indices */
2362      p->index = current_loop_index + 1;
2363
2364      getch(ch, parens, treefile);
2365
2366      addelement2(p, ch, parens, treefile, treenode, lngths, trweight,
2367        goteof, nextnode, ntips, no_species, haslengths);
2368
2369      if ((*ch) == ')') {
2370        notlast = false;
2371        do {
2372          getch(ch, parens, treefile);
2373        } while ((*ch) != ',' && (*ch) != ')' &&
2374           (*ch) != '[' && (*ch) != ';' && (*ch) != ':');
2375      }
2376    }
2377
2378  } else if ((*ch) != ')') {
2379    for (i = 0; i < MAXNCH; i++)
2380      str[i] = '\0';
2381    len = take_name_from_tree (ch, str, treefile);
2382    match_names_to_data (str, treenode, &p, spp);
2383    pfirst = p;
2384    if ((*ch) == ')')
2385      (*parens)--;
2386    (*ntips)++;
2387    strncpy (p->nayme, str, len);
2388  } else
2389    getch(ch, parens, treefile);
2390
2391  if ((*ch) == '[') {    /* getting tree weight from last comment field */
2392    if (!eoln(treefile)) {
2393      fscanf(treefile, "%lf", trweight);
2394      getch(ch, parens, treefile);
2395      if (*ch != ']') {
2396        printf("\n\nERROR: Missing right square bracket\n\n");
2397        exxit(-1);
2398      }
2399      else {
2400        getch(ch, parens, treefile);
2401        if (*ch != ';') {
2402          printf("\n\nERROR: Missing semicolon after square brackets\n\n");
2403          exxit(-1);
2404        }
2405      }
2406    }
2407  }
2408  else if ((*ch) == ';') {
2409    (*trweight) = 1.0 ;
2410    if (!eoln(treefile))
2411      printf("WARNING: tree weight set to 1.0\n");
2412  }
2413  else
2414    (*haslengths) = ((*haslengths) && q == NULL);
2415
2416  if (q != NULL)
2417    hookup(q, pfirst);
2418  if (q != NULL) {
2419    if (q->branchnum < pfirst->branchnum)
2420      pfirst->branchnum = q->branchnum;
2421    else
2422      q->branchnum = pfirst->branchnum;
2423  }
2424
2425  if ((*ch) == ':') {
2426    processlength(&valyew, &divisor, ch,
2427       &minusread, treefile, parens);
2428    if (q != NULL) {
2429      if (!minusread)
2430        q->oldlen = valyew / divisor;
2431      else
2432        q->oldlen = 0.0;
2433      if (lngths) {
2434        q->v = valyew / divisor;
2435        q->back->v = q->v;
2436        q->iter = false;
2437        q->back->iter = false;
2438        q->back->iter = false;
2439    }
2440    }
2441  }
2442
2443}  /* addelement2 */
2444
2445
2446void treeread2 (FILE *treefile, node **root, pointarray treenode,
2447        boolean lngths, double *trweight, boolean *goteof,
2448        boolean *haslengths, long *no_species)
2449{
2450  /* read in user-defined tree and set it up
2451     -- old-style bifurcating-only version */
2452  char  ch;
2453  long parens = 0;
2454  long ntips = 0;
2455  long nextnode;
2456
2457  (*goteof) = false;
2458  nextnode = 0;
2459
2460  /* Eats all blank lines at start of file */
2461  while (eoln(treefile) && !eoff(treefile))
2462    scan_eoln(treefile);
2463
2464  if (eoff(treefile)) {
2465    (*goteof) = true;
2466    return;
2467  }
2468
2469  getch(&ch, &parens, treefile);
2470
2471  while (ch != '(') {
2472    /* Eat everything in the file (i.e. digits, tabs) until you
2473       encounter an open-paren */
2474    getch(&ch, &parens, treefile);
2475  }
2476
2477  addelement2(NULL, &ch, &parens, treefile, treenode, lngths, trweight,
2478          goteof, &nextnode, &ntips, (*no_species), haslengths);
2479  (*root) = treenode[*no_species];
2480
2481  /*eat blank lines */
2482  while (eoln(treefile) && !eoff(treefile))
2483    scan_eoln(treefile);
2484
2485  (*root)->oldlen = 0.0;
2486
2487  if (parens != 0) {
2488    printf("\n\nERROR in tree file:  unmatched parentheses\n\n");
2489    exxit(-1);
2490  }
2491}  /* treeread2 */
2492
2493void exxit(int exitcode)
2494{
2495#ifdef WIN32
2496  if (exitcode == 0)
2497#endif
2498    exit (exitcode);
2499#ifdef WIN32
2500  else {
2501    puts ("Hit Enter or Return to close program.");
2502    puts("  You may have to hit Enter or Return twice.");
2503    getchar ();
2504    getchar ();
2505    phyRestoreConsoleAttributes();
2506    exit (exitcode);
2507  }
2508#endif
2509} /* exxit */
2510
2511
2512char gettc(FILE* file)
2513{ /* catch eof's so that other functions not expecting an eof
2514   * won't have to worry about it */
2515  int ch;
2516
2517  ch = getc(file);
2518
2519  if (ch == EOF )   {
2520    puts("Unexpected End of File");
2521    exxit(-1);
2522  }
2523/*   printf("ch='%c'\n", (char)ch); */
2524  return ch;
2525} /* gettc */
2526
2527
2528#ifdef WIN32
2529void phySaveConsoleAttributes()
2530{
2531  GetConsoleScreenBufferInfo( hConsoleOutput, &savecsbi );
2532} /* PhySaveConsoleAttributes */
2533
2534
2535void phySetConsoleAttributes()
2536{
2537  hConsoleOutput = GetStdHandle(STD_OUTPUT_HANDLE);
2538
2539  phySaveConsoleAttributes();
2540
2541  SetConsoleTextAttribute(hConsoleOutput,
2542    BACKGROUND_GREEN | BACKGROUND_BLUE | BACKGROUND_INTENSITY);
2543} /* phySetConsoleAttributes */
2544
2545
2546void phyRestoreConsoleAttributes()
2547{
2548  COORD coordScreen = { 0, 0 };
2549  DWORD cCharsWritten;
2550  DWORD dwConSize;
2551
2552  dwConSize = savecsbi.dwSize.X * savecsbi.dwSize.Y;
2553
2554  SetConsoleTextAttribute(hConsoleOutput, savecsbi.wAttributes);
2555
2556  FillConsoleOutputAttribute( hConsoleOutput, savecsbi.wAttributes,
2557         dwConSize, coordScreen, &cCharsWritten );
2558} /* phyRestoreConsoleAttributes */
2559
2560
2561void phyFillScreenColor()
2562{
2563  COORD coordScreen = { 0, 0 };
2564  DWORD cCharsWritten;
2565  CONSOLE_SCREEN_BUFFER_INFO csbi; /* to get buffer info */
2566  DWORD dwConSize;
2567
2568  GetConsoleScreenBufferInfo( hConsoleOutput, &csbi );
2569  dwConSize = csbi.dwSize.X * csbi.dwSize.Y;
2570
2571  FillConsoleOutputAttribute( hConsoleOutput, csbi.wAttributes,
2572         dwConSize, coordScreen, &cCharsWritten );
2573} /* PhyFillScreenColor */
2574
2575
2576void phyClearScreen()
2577{
2578   COORD coordScreen = { 0, 0 };    /* here's where we'll home the
2579                                       cursor */
2580   DWORD cCharsWritten;
2581   CONSOLE_SCREEN_BUFFER_INFO csbi; /* to get buffer info */
2582   DWORD dwConSize;                 /* number of character cells in
2583                                       the current buffer */
2584
2585   /* get the number of character cells in the current buffer */
2586
2587   GetConsoleScreenBufferInfo( hConsoleOutput, &csbi );
2588   dwConSize = csbi.dwSize.X * csbi.dwSize.Y;
2589
2590   /* fill the entire screen with blanks */
2591
2592   FillConsoleOutputCharacter( hConsoleOutput, (TCHAR) ' ',
2593      dwConSize, coordScreen, &cCharsWritten );
2594
2595   /* get the current text attribute */
2596
2597   GetConsoleScreenBufferInfo( hConsoleOutput, &csbi );
2598
2599   /* now set the buffer's attributes accordingly */
2600
2601   FillConsoleOutputAttribute( hConsoleOutput, csbi.wAttributes,
2602      dwConSize, coordScreen, &cCharsWritten );
2603
2604   /* put the cursor at (0, 0) */
2605
2606   SetConsoleCursorPosition( hConsoleOutput, coordScreen );
2607   return;
2608} /* PhyClearScreen */
2609#endif
2610
Note: See TracBrowser for help on using the repository browser.