source: trunk/GDE/PHYLIP/phylip.c

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