/*******************************************************************************
*                                                                              *
*                                   Viewmol                                    *
*                                                                              *
*                            R E A D G A U S S . C                             *
*                                                                              *
*                 Copyright (c) Joerg-R. Hill, October 2003                    *
*                                                                              *
********************************************************************************
*
* $Id: readgauss.c,v 1.7 2004/07/04 15:28:50 jrh Exp $
* $Log: readgauss.c,v $
* Revision 1.7  2004/07/04 15:28:50  jrh
* Updated for Gaussian03
*
* Revision 1.6  2003/11/07 11:13:35  jrh
* Release 2.4
*
* Revision 1.5  2000/12/10 15:15:24  jrh
* Release 2.3
*
* Revision 1.4  1999/05/24 01:27:15  jrh
* Release 2.2.1
*
* Revision 1.3  1999/02/07 21:55:46  jrh
* Release 2.2
*
* Revision 1.2  1998/01/26 00:49:14  jrh
* Release 2.1
*
* Revision 1.1  1996/12/10  18:43:35  jrh
* Initial revision
*
*/
#include<ctype.h>
#include<math.h>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include "isotopes.h"

#define TRUE  1
#define FALSE 0

#define MAXLENLINE 134
#define TABMAR "---"
#define EHF "rhf) ="
#define EMP2 "eump2"
#define EMP4 "sdtq)="
#define EDFT ") ="
#define EUHF "uhf) ="
#define EMPTWO "ump2 ="
#define FRAME "framework group"
#define STAOR "standard orientation:"
#define INPOR "input orientation:"
#define GAUSS1 "entering gaussian system"
#define GAUSS2 "entering link 1 ="
#define GAUSSIAN03 "This is the Gaussian(R) 03 program."
#define XCOORD "x-coord"
#define OSYM "orbital symmetries"
#define AMOS "alpha mos:"
#define BMOS "beta  mos:"
#define MOCOEFFICIENTS "molecular orbital coefficients"
#define AXES "***** axes restored to original set *****"
#define SYMMETRIES   1
#define ALPHAMOS     2
#define COEFFICIENTS 3

int  main(int, char **);
void readBasis(FILE *, int);
void readMOs(int, FILE *);
void readFrq(FILE *, int, int, int);
int  readOpg(FILE *, int, int, char *, char *);
void printCoord(double **, char **, int);
double reade(char *, char *, int *);
int msub(char *, int, char *);
void makeLower(char *);
void changeDs(char *);

extern void *getmem(size_t, size_t);
extern void *expmem(void *, size_t, size_t);
extern void fremem(void **);
extern void eof(char *, char *, int);

int main(int argc, char **argv)
{
  FILE *file;
  double etotal, *xcoord, *ycoord, *zcoord;
  char emark[2][7] = {"0@  ~0", "0@  ~0"}, line[MAXLENLINE], *word;
  char *symbol, orientation[24];
  int freq=FALSE, gfprn=FALSE, opt=FALSE;
  int nemark=0, nout, na, ncent, nuc;
  int mna=50, cycle=0;
  int etex;
  int version = 98;
  register double x, y, z;
  register int i, mak;

  if ((file=fopen(argv[1], "r")) == NULL) eof("noFile", argv[1], 1);

/* Check type of calculation */

  do
  {
    if (fgets(line, MAXLENLINE, file) == NULL) eof("wrongFiletype", argv[1], 1);
    makeLower(line);
  } while (!(strstr(line, GAUSS1) || strstr(line, GAUSS2)));

  for (i=0; i<10; i++)  /* test for Gaussian03 */
  {
    if (fgets(line, MAXLENLINE, file) == NULL) eof("wrongFiletype", argv[1], 1);
    if (strstr(line, GAUSSIAN03)) version=3;
  }

  do
  {
    if (fgets(line, MAXLENLINE, file) == NULL) eof("noCoordinates", argv[1], 1);
/*} while (!strstr(line, TABMAR));
  fgets(line, MAXLENLINE, file);*/
  } while (strncmp(line, " #", 2));
  do
  {
    makeLower(line);
    if (strstr(line, "gfprint")) gfprn=TRUE;
    if (strstr(line, "nosymm"))
      strcpy(orientation, INPOR);
    else
      strcpy(orientation, STAOR);
    if (strstr(line, "opt")) opt=TRUE;
    if (strstr(line, "freq")) freq=TRUE;
    if (strstr(line, "hf"))
    {
      strcpy(emark[0], EHF);
      strcpy(emark[1], EUHF);
      nemark=2;
    }
    if (strstr(line, "scf"))
    {
      strcpy(emark[0], EHF);
      nemark=2;
    }
    if (strstr(line, "mp2"))
    {
      strcpy(emark[0], EMP2);
      strcpy(emark[1], EMPTWO);
      nemark=2;
    }
    if (strstr(line, "mp4"))
    {
      strcpy(emark[0], EMP4);
      nemark=1;
    }
    if (!strncmp(line, " #", 2))
    {
      printf("$pople ");
      if (!strstr(line, "5d"))
          printf("6d ");
      else
          printf("5d ");
      if (!strstr(line, "7f"))
          printf("10f ");
      else
          printf("7f");
      printf("\n");
    }

/* AdM added IF block for DFT overruling all previous stuff */

    if (strstr(line, "lyp") || strstr(line, "pl") || strstr(line, "andh") ||
        strstr(line, "hfb") || strstr(line, "xalpha") || strstr(line, "hfs") ||
        strstr(line, "p86") || strstr(line, "vwn") || strstr(line, "pw91"))
    {
      strcpy(emark[0], EDFT);
      nemark=1;
    }

    if (fgets(line, MAXLENLINE, file) == NULL) eof("noCoordinates", argv[1], 1);
    makeLower(line);
  } while (!strstr(line, TABMAR));

/* Load Title */

/*rewind(file);
  int ntmar=0;
  while (ntmar != 3)
  { */
    do
    {
      if (fgets(line, MAXLENLINE, file) == NULL) eof("noCoordinates", argv[1], 1);
    } while (!strstr(line, TABMAR));
/*  ntmar++;
  } */
  fgets(line, MAXLENLINE, file);
  printf("$title\n%s", line);

/* Look whether molecule is linear or not */

  do
  {
    if (fgets(line, MAXLENLINE, file) == NULL) eof("noCoordinates", argv[1], 1);
    makeLower(line);
  } while (!strstr(line, FRAME));
  if (strstr(line, "C*V") || strstr(line, "D*H"))
    nout=5;
  else
    nout=6;
  strtok(line, " \t");
  strtok(NULL, " \t");
  word=strtok(NULL, " [");
  printf("$symmetry %s\n", word);

/* Load coordinates */

  do
  {
    if (fgets(line, MAXLENLINE, file) == NULL) eof("noCoordinates", argv[1], 1);
    makeLower(line);
  } while (!strstr(line, orientation));
  fgets(line, MAXLENLINE, file);
  fgets(line, MAXLENLINE, file);
  fgets(line, MAXLENLINE, file);
  fgets(line, MAXLENLINE, file);
  na=0;
  ncent=0;
  if (!opt) printf("$coord 1.0\n");
  xcoord=(double *)getmem(mna, sizeof(double));
  ycoord=(double *)getmem(mna, sizeof(double));
  zcoord=(double *)getmem(mna, sizeof(double));
  symbol=(char *)getmem(mna, 3*sizeof(char));
  while (fgets(line, MAXLENLINE, file) != NULL)
  {
    if (strstr(line, TABMAR)) break;
    ncent++;
    strtok(line, " \t");
    nuc=atoi(strtok(NULL, " \t"))-1;
    word=strtok(NULL, " \t");
    if (strchr(word, '.'))
      x=atof(word);
    else
      x=atof(strtok(NULL, " \t\n"));
    y=atof(strtok(NULL, " \t\n"));
    z=atof(strtok(NULL, " \t\n"));

    if (nuc >= 0)                            /* only for Z-ori ! */
    {
      symbol[3*na]=pse[nuc][0];
      symbol[3*na+1]=pse[nuc][1];
      symbol[3*na+2]='\0';
	xcoord[na]=x;
	ycoord[na]=y;
	zcoord[na]=z;
      if (!opt) printf("%22.14f%22.14f%22.14f  %s\n", x, y, z, &symbol[3*na]);
      if (++na >= mna)
      {
        mna+=50;
        xcoord=(double *)expmem((void *)xcoord, mna, sizeof(double));
        ycoord=(double *)expmem((void *)ycoord, mna, sizeof(double));
        zcoord=(double *)expmem((void *)zcoord, mna, sizeof(double));
        symbol=(char *)expmem((void *)symbol, mna, 3*sizeof(char));
      }
    }
  }

/* Load optimization history */
  if (opt) cycle=readOpg(file, na, nemark, &emark[0][0], orientation);

/* Load basis functions */

  if (gfprn)
  {
    printf("$atoms\n");
    for (i=0; i<na; i++)
    {
      printf("%s %d \\\n", &symbol[3*i], i+1);
      printf("   basis =%s basis%d\n", &symbol[3*i], i+1);
    }
    readBasis(file, na);
  }

/* Load total energy */
  if (!opt)
  {
    rewind(file);
    do
    {
      if (fgets(line, MAXLENLINE, file) == NULL) eof("noEnergy", argv[1], 0);
      makeLower(line);
    } while ((mak=msub(line, nemark, &emark[0][0])) == 0);
    etotal=reade(line, emark[mak], &etex);
    printf("$grad\n");
    printf("  cycle =   1    SCF energy = %17.10f   |dE/xyz| = 0.0\n", etotal);
    for (i=0; i<na; i++)
      printf("%22.14f%22.14f%22.14f  %s\n", xcoord[i], ycoord[i], zcoord[i], &symbol[3*i]);
    for (i=0; i<na; i++)
      printf("%22.14e%22.14e%22.14e\n", 0.0, 0.0, 0.0);
/*  if (!etex) exit(-1);*/
  }

/* Load orbital energies and symmetries */

  readMOs(cycle, file);
  if (na <= 1)
  {
    freq=FALSE;
    opt=FALSE;
  }

/* Load frequencies and normal modes vectors */

  if (freq) readFrq(file, na, nout, version);

  printf("$end\n");
  fclose(file);
  fremem((void **)&xcoord);
  fremem((void **)&ycoord);
  fremem((void **)&zcoord);
  fremem((void **)&symbol);
  return(0);
}

void readBasis(FILE *file, int na)
{
  double *ex, *scoeff, *pcoeff, *dcoeff, *fcoeff;
  double scalefactor;
  char line[MAXLENLINE], *word, shell[3];
  int maxpri=20, atom=1;
  register int i, j;

  ex=(double *)getmem(maxpri, sizeof(double));
  scoeff=(double *)getmem(maxpri, sizeof(double));
  pcoeff=(double *)getmem(maxpri, sizeof(double));
  dcoeff=(double *)getmem(maxpri, sizeof(double));
  fcoeff=(double *)getmem(maxpri, sizeof(double));

  rewind(file);
  do
  {
    if (fgets(line, MAXLENLINE, file) == NULL) return;
    makeLower(line);
  } while (!strstr(line, XCOORD));
  fgets(line, MAXLENLINE, file);

  printf("$basis\n*\n");
  fgets(line, MAXLENLINE, file);       /* Atom   ============== */
  strtok(line, " \t");
  word=strtok(NULL, " \t");
  printf("%s basis%d\n*\n", word, atom++);
  fgets(line, MAXLENLINE, file);       /* Shell  ============== */
  while (TRUE)
  {
    word=strtok(line, " \t");
    word=strtok(NULL, " \t");
    word=strtok(NULL, " \t");
    if (strchr(word, '.'))
    {
      strcpy(shell, "?");
      scalefactor=atof(word);
    }
    else
    {
      if (isdigit(*word)) word=strtok(NULL, " \t");
      if (strchr(word, '.'))
      {
        strcpy(shell, "?");
        scalefactor=atof(word);
      }
      else
      {
        strcpy(shell, word);
        scalefactor=atof(strtok(NULL, " \t"));
      }
    }
  
    i=0;
    while (TRUE)
    {
      fgets(line, MAXLENLINE, file);
      if (line[49] != ' ') break;
      changeDs(line);
      word=strchr(line, '.')-1;
      sscanf(word, "%12le%12le%12le%12le%12le", &ex[i], &scoeff[i],
             &pcoeff[i], &dcoeff[i], &fcoeff[i]);
      ex[i++]*=scalefactor;
      if (i >= maxpri)
      {
        maxpri+=20;
        ex=(double *)expmem((void *)ex, maxpri, sizeof(double));
        scoeff=(double *)expmem((void *)scoeff, maxpri, sizeof(double));
        pcoeff=(double *)expmem((void *)pcoeff, maxpri, sizeof(double));
        dcoeff=(double *)expmem((void *)dcoeff, maxpri, sizeof(double));
        fcoeff=(double *)expmem((void *)fcoeff, maxpri, sizeof(double));
      }
    }
    if (shell[0] == '?')
    {
      if (scoeff[0] != 0.0) strcpy(shell, "S");
      if (pcoeff[0] != 0.0) strcpy(shell, "P");
      if (scoeff[0] != 0.0 && pcoeff[0] != 0.0) strcpy(shell, "SP");
      if (dcoeff[0] != 0.0) strcpy(shell, "D");
      if (fcoeff[0] != 0.0) strcpy(shell, "F");
    }
    for (word=&shell[0]; *word; word++)
    {
      if (isalpha(*word))
      {
        printf("%4d  %c\n", i, tolower(*word));
        for (j=0; j<i; j++)
        {
          switch (*word)
          {
            case 'S': printf("%15.6f %10.6f\n", ex[j], scoeff[j]);
                      break;
            case 'P': printf("%15.6f %10.6f\n", ex[j], pcoeff[j]);
                      break;
            case 'D': printf("%15.6f %10.6f\n", ex[j], dcoeff[j]);
                      break;
            case 'F': printf("%15.6f %10.6f\n", ex[j], fcoeff[j]);
                      break;
          }
        }
      }
    }
    if (line[49] == '-')
    {
      fgets(line, MAXLENLINE, file);
      strtok(line, " \t");
      word=strtok(NULL, " \t");
      printf("*\n%s basis%d\n*\n", word, atom++);
      fgets(line, MAXLENLINE, file);
    }
    if (line[49] == '*') break;
  }
  printf("*\n");
  fremem((void **)&ex);
  fremem((void **)&scoeff);
  fremem((void **)&pcoeff);
  fremem((void **)&dcoeff);
  fremem((void **)&fcoeff);
}

void readMOs(int cycle, FILE *file)
{
  double *eorb, *cmo;
  int ia=0, ie, mno=20, mnc=200, norbital=0, offset, occ=TRUE, nocc=0;
  int info, found;
  char line[MAXLENLINE], number[8], *word, *begin, *symorb, *closed;
  register int i, j, k;

  rewind(file);
  while (TRUE)
  {
    if (fgets(line, MAXLENLINE, file) == NULL) return;
    makeLower(line);
    if (strstr(line, OSYM) && !strstr(line, "in"))
    {
      info=SYMMETRIES;
      break;
    }
    if (strstr(line, AMOS))
    {
      info=ALPHAMOS;
      break;
    }
  }

  symorb=(char *)getmem(mno, 4*sizeof(char));
  closed=(char *)getmem(20, MAXLENLINE*sizeof(char));
  if (info == SYMMETRIES)
  {
    i=0;

    while (fgets(line, MAXLENLINE, file))
    {
      makeLower(line);
      if ((word=strrchr(line, '\n')) != NULL) *word='\0';
      if (strstr(line, "the electronic state") || strstr(line, " alpha deviation from unit magnitude")) break;
      if (strstr(line, "occupied") || strstr(line, "virtual"))
      {
        if (strstr(line, "virtual")) occ=FALSE;
        strtok(line, " \t");
        begin=NULL;
      }
      else
        begin=line;
      while ((word=strtok(begin, " \t")) != NULL)
      {
        begin=NULL;
        strncpy(&symorb[4*i], word+1, 4);
        if ((word=strrchr(&symorb[4*i], ')')) != NULL) *word='\0';
        if (occ)
        {
          found=FALSE;
          for (j=0; j<nocc; j++)
          {
            if (!strncmp(&symorb[4*i], &closed[MAXLENLINE*j], strlen(&symorb[4*i])))
            {
              sprintf(number, ",%d", i+1);
              strcat(&closed[MAXLENLINE*j], number);
              found=TRUE;
              break;
            }
          }
          if (!found)
          {
            sprintf(&closed[MAXLENLINE*nocc], "%s %d", &symorb[4*i], i+1);
            nocc++;
          }
        }
        i++;
        if (i >= mno)
        {
          mno+=20;
          symorb=(char *)expmem((void *)symorb, mno, 4*sizeof(char));
        }
      }
    }
    norbital=i;
  }
  else
  {
    rewind(file);
    do
    {
      if (fgets(line, MAXLENLINE, file) == NULL) return;
      makeLower(line);
    } while (!strstr(line, "symmetry adapted basis"));
    while (strstr(line, "symmetry adapted basis"))
    {
      strtok(line, " \t");
      strtok(NULL, " \t");
      norbital+=atof(strtok(NULL, " \t"));
      fgets(line, MAXLENLINE, file);
      makeLower(line);
    }
    symorb=(char *)expmem((void *)symorb, norbital, 4*sizeof(char));
    strcpy(closed, "A1 1-");
  }

  rewind(file);
  do
  {
    if (fgets(line, MAXLENLINE, file) == NULL) return;
    makeLower(line);
    word=strstr(line, AMOS);
    if (word) cycle--;
    if (!word)
    {
      word=strstr(line, MOCOEFFICIENTS);
      if (word)
	info=COEFFICIENTS;
    }
  } while (!word || cycle > 0);

  printf("$scfmo gaussian\n");
  eorb=(double *)getmem(norbital, sizeof(double));
  cmo=(double *)getmem(mnc, sizeof(double));
  fgets(line, MAXLENLINE, file);
  do
  {
    ie=0;
    strtok(line, " \t");
    while (strtok(NULL, " \t") != NULL) ie++;
    ie++;
    fgets(line, MAXLENLINE, file);
    if (info == COEFFICIENTS)
      fgets(line, MAXLENLINE, file);
    strtok(line, " \t");
    strtok(NULL, " \t");
    for (i=ia; i<ia+ie; i++)
    {
      eorb[i]=atof(strtok(NULL, " \t"));
      if (info == ALPHAMOS)
      {
        strcpy(&symorb[4*i], "A1");
        if (eorb[i] > 0.0 && nocc == 0)
        {
          sprintf(number, "%d", i+1);
          strcat(closed, number);
          nocc++;
        }
      }
    }

    k=0;
    for (j=0; j<norbital; j++)
    {
      fgets(line, MAXLENLINE, file);
      word=strtok(line, " \t");
      while (!strchr(word, '.')) word=strtok(NULL, " \t");
      for (i=0; i<ie; i++)
      {
        cmo[k]=atof(word);
        if (++k >= mnc)
        {
          mnc+=200;
          cmo=(double *)expmem((void *)cmo, mnc, sizeof(double));
        }
        word=strtok(NULL, " \t");
      }
    }
    for (i=ia; i<ia+ie; i++)
    {
      word=&symorb[4*i];
      printf("%6d  %s     eigenvalue=%20.14e   nsaos=%d\n", i+1, word, eorb[i], norbital);
      offset=ie;
      for (j=0; j<norbital; j++)
      {
        printf(" %19.14e", cmo[i-ia+j*offset]);
        if ((j+1) % 4 == 0) printf("\n");
      }
      if (j % 4 != 0) printf("\n");
    }
    fgets(line, MAXLENLINE, file);
    makeLower(line);
    ia+=ie;
  }
  while (!strstr(line, BMOS) && !strstr(line, "condensed to atoms"));

  printf("$closed shells\n");
  for (i=0; i<nocc; i++)
    printf(" %s\n", &closed[MAXLENLINE*i]);
  fremem((void **)&symorb);
  fremem((void **)&closed);
  fremem((void **)&eorb);
  fremem((void **)&cmo);
}

void readFrq(FILE *file, int na, int nout, int version)
{
  static int first=TRUE;
  double *freq, *ir, *raman, *nmo;
  int ncart=3*na-nout, nfrq=0;
  char line[MAXLENLINE], *symmod, *word;
  register int i, j, k, end;

  rewind(file);
  do
  {
    if (fgets(line, MAXLENLINE, file) == NULL) return;
    makeLower(line);
  } while (!strstr(line, "harmonic frequencies") && first);

  first=FALSE;
  freq=(double *)getmem(ncart, sizeof(double));
  ir=(double *)getmem(ncart, sizeof(double));
  raman=(double *)getmem(ncart, sizeof(double));
  symmod=(char *)getmem(ncart, 4*sizeof(char));
  nmo=(double *)getmem(ncart*(ncart+nout), sizeof(double));

  do
  {
    fgets(line, MAXLENLINE, file);
  }
  while (!strstr(line, ":"));
  while (nfrq < ncart)
  {

    fgets(line, MAXLENLINE, file);
    fgets(line, MAXLENLINE, file);
    strcpy(&symmod[4*nfrq], strtok(line, " \t\n"));
    i=nfrq+1;
    while ((word=strtok(NULL, " \t\n")) != NULL)
    {
      strcpy(&symmod[4*i], word);
      i++;
    }
    end=i;

    fgets(line, MAXLENLINE, file);
    strtok(line, " \t");
    strtok(NULL, " \t");
    for (i=nfrq; i<end; i++)
      freq[i]=atof(strtok(NULL, " \t"));

    fgets(line, MAXLENLINE, file);
    fgets(line, MAXLENLINE, file);
    fgets(line, MAXLENLINE, file);
    strtok(line, " \t");
    strtok(NULL, " \t");
    strtok(NULL, " \t");
    for (i=nfrq; i<end; i++)
      ir[i]=atof(strtok(NULL, " \t"));

    fgets(line, MAXLENLINE, file);
    if (strstr(line, "Raman"))
    {
      strtok(line, " \t");
      strtok(NULL, " \t");
      strtok(NULL, " \t");
      for (i=nfrq; i<end; i++)
        raman[i]=atof(strtok(NULL, " \t"));
      fgets(line, MAXLENLINE, file);
      fgets(line, MAXLENLINE, file);
      if (version == 3) fgets(line, MAXLENLINE, file);  /* skip additional "Depolar" for Gaussian03 */
    }
    printf("%s", line);
    makeLower(line);
    if (strstr(line, "x      y      z"))
    {
      for (i=0; i<na; i++)
      {
          fgets(line, MAXLENLINE, file);
        strtok(line, " \t");
        strtok(NULL, " \t");
        for (j=nfrq; j<end; j++)
        {
          for (k=0; k<3; k++)
            nmo[(3*i+k)*ncart+j]=atof(strtok(NULL, " \t"));
        }
      }
      nfrq+=3;
    }
    else
    {
      for (i=0; i<ncart+nout; i++)
      {
          fgets(line, MAXLENLINE, file);
        strtok(line, " \t");
        strtok(NULL, " \t");
        strtok(NULL, " \t");
        for (j=nfrq; j<end; j++)
          nmo[i*ncart+j]=atof(strtok(NULL, " \t"));
      }
      nfrq+=5;
    }
  }
  printf("$vibrational spectrum\n");
  word=symmod;
  for (i=0; i<ncart; i++)
  {
    printf("%s %f %f %f\n", word, freq[i], ir[i], raman[i]);
    word+=4; 
  }

  printf("$vibrational normal modes\n");
  for (i=0; i<ncart+nout; i++)
  {
    for (j=0; j<ncart; j++)
    {
      if (j % 5 == 0)
      {
        if (j == 0)
          printf("%2d %2d ", i+1, j/5+1);
        else
          printf("\n%2d %2d ", i+1, j/5+1);
      }
      printf("%15.10f", nmo[i*ncart+j]);
    }
    printf("\n");
  }

  fremem((void **)&symmod);
  fremem((void **)&freq);
  fremem((void **)&ir);
  fremem((void **)&raman);
  fremem((void **)&nmo);
}

int readOpg(FILE *file, int na, int nemark, char *emark, char *orientation)
{
  double *x, *y, *z, *gx, *gy, *gz;
  double energy, gnorm;
  int cycle=0, mak=0, etex;
  char line[MAXLENLINE], *symbol, *word;
  register int i, nuc;

  x=(double *)getmem(na, 6*sizeof(double));
  y=x+na;
  z=y+na;
  gx=z+na;
  gy=gx+na;
  gz=gy+na;
  symbol=(char *)getmem(na, 3*sizeof(char));

  rewind(file);
  while (TRUE)
  {
    do
    {
      if (fgets(line, MAXLENLINE, file) == NULL)
      {
        printCoord(&x, &symbol, na);
        return(cycle);
      }
      makeLower(line);
    } while (!strstr(line, orientation));

    fgets(line, MAXLENLINE, file);
    fgets(line, MAXLENLINE, file);
    fgets(line, MAXLENLINE, file);
    fgets(line, MAXLENLINE, file);
    i=0;
    while (TRUE)
    {
      if (fgets(line, MAXLENLINE, file) == NULL)
      {
        printCoord(&x, &symbol, na);
        return(cycle);
      }
      if (strstr(line, TABMAR)) break;
      strtok(line, " \t");
      nuc=atoi(strtok(NULL, " \t"))-1;
      symbol[3*i]=pse[nuc][0];
      symbol[3*i+1]=pse[nuc][1];
      symbol[3*i+2]='\0';
      word=strtok(NULL, " \t");
      if (strchr(word, '.'))
        x[i]=atof(word);
      else
        x[i]=atof(strtok(NULL, " \t\n"));
      y[i]=atof(strtok(NULL, " \t\n"));
      z[i]=atof(strtok(NULL, " \t\n"));
      i++;
    }
    do
    {
      if (fgets(line, MAXLENLINE, file) == NULL) break;
      makeLower(line);
      mak=msub(line, nemark, emark);
    } while (mak == 0);
    energy=reade(line, &emark[mak], &etex);
    if (!etex) continue;
    do
    {
      if (fgets(line, MAXLENLINE, file) == NULL)
      {
        printCoord(&x, &symbol, na);
        return(cycle);
      }
      makeLower(line);
    } while (!strstr(line, AXES));
    fgets(line, MAXLENLINE, file);
    fgets(line, MAXLENLINE, file);
    fgets(line, MAXLENLINE, file);
    fgets(line, MAXLENLINE, file);
    i=0;
    while (TRUE)
    {
      if (fgets(line, MAXLENLINE, file) == NULL)
      {
        printCoord(&x, &symbol, na);
        return(cycle);
      }
      if (strstr(line, TABMAR)) break;
      strtok(line, " \t");
      strtok(NULL, " \t");
      gx[i]=atof(strtok(NULL, " \t"));
      gy[i]=atof(strtok(NULL, " \t"));
      gz[i]=atof(strtok(NULL, " \t"));
      i++;
    }
    fgets(line, MAXLENLINE, file);
    strtok(line, " \t");
    strtok(NULL, " \t");
    strtok(NULL, " \t");
    gnorm=atof(strtok(NULL, " \t"));
    if (!cycle++) printf("$grad\n");
    printf("  cycle = %3d    SCF energy = %17.10f   |dE/xyz| = %9.6f\n", cycle, energy, gnorm);
    for (i=0; i<na; i++)
      printf("%22.14f%22.14f%22.14f  %s\n", x[i], y[i], z[i], &symbol[3*i]);
    for (i=0; i<na; i++)
      printf("%22.14e%22.14e%22.14e\n", gx[i], gy[i], gz[i]);
  }
  /* We should never reach this point */
  /* NOTREACHED */
  return(cycle);
}

void printCoord(double **coord, char **symbol, int na)
{
  double *x, *y, *z;
  char *s;
  register int i;

  x=*coord;
  y=x+na;
  z=y+na;
  s=*symbol;
  printf("$coord 1.0\n");
  for (i=0; i<na; i++)
    printf("%22.14f%22.14f%22.14f  %s\n", x[i], y[i], z[i], &s[3*i]);

  fremem((void **)coord);
  fremem((void **)symbol);
}

double reade(char *line, char *emark, int *done)
{
  char *p;

  strtok(line, "=");
  *done=TRUE;
  if ((p=strtok(NULL, " ")) != NULL) return(atof(p));
  *done=FALSE;
  return(0.0);
}

int msub(char *string, int n, char *pattern)
{
  char *p=pattern;
  register int i;

  for (i=0; i<n; i++);
  {
    if (strstr(string, p)) return(i);
    p+=strlen(p);
  }
  return(0);
}

void makeLower(char *line)
{
  char *p=line;

  while (*p)
  {
    *p=tolower(*p);
    p++;
  }
}

void changeDs(char *line)
{
  char *p;

  p=line;
  while (*p)
  {
    if (*p == 'D') *p='e';
    if (*p == '\n') *p='\0';
    p++;
  }
}
