File: mol_read.c

package info (click to toggle)
c2x 2.42%2Bds-1
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 1,316 kB
  • sloc: ansic: 28,166; makefile: 31; sh: 1
file content (142 lines) | stat: -rw-r--r-- 3,715 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
/* A very simplistic .mol (or .sdf) reader */

#include<stdio.h>
#include<stdlib.h> /* malloc */
#include<string.h>
#include<ctype.h>

#include "c2xsf.h"

static void mol3_read(FILE* infile, struct unit_cell *c, struct contents *m);

/* The format limits lines to 80 characters, or perhaps 200 */
#define LINE_SIZE 200

void mol_read(FILE* infile, struct unit_cell *c, struct contents *m){
  char buffer[LINE_SIZE+1],buff[12],*cptr,*cptr2;
  int i,j,n,ver;

  buffer[0]=0;
  
  /* Does first line contain any text? */
  fgets(buffer,LINE_SIZE,infile);
  i=0;
  while((buffer[i])&&(isspace(buffer[i]))) i++;
  if (isalnum(buffer[i])){
    m->title=malloc(strlen(buffer+i)+1);
    if (!m->title) error_exit("malloc error for title");
    cptr=buffer+i;
    cptr2=m->title;
    while((*cptr)&&(*cptr!='\n')) *(cptr2++)=*(cptr++);
    *cptr2=0;
  }

  /* skip two lines */

  fgets(buffer,LINE_SIZE,infile);
  fgets(buffer,LINE_SIZE,infile);

  /* read counts line */
  fgets(buffer,LINE_SIZE,infile);
  i=sscanf(buffer,"%d",&n);
  if (i!=1) error_exit("failed to read count line of mol file");
  cptr=strchr(buffer,'V');
  if (!cptr) error_exit("invalid count line in mol file");
  sscanf(cptr+1,"%d",&ver);
  if (ver==3000){
    mol3_read(infile,c,m);
    return;
  }
  if (ver!=2000)
    fprintf(stderr,"Unexpected mol file version. Have %d, expected 2000\n",
	    ver);
  if (n<1) error_exit("mol file contains no atoms");

  m->n=n;
  m->atoms=malloc(n*sizeof(struct atom));
  if (!m->atoms) error_exit("malloc error for atoms");
  init_atoms(m->atoms,n);

  /* Fields are not guaranteed to be space-separated, hence copying */
  
  for(i=0;i<n;i++){
    fgets(buffer,LINE_SIZE,infile);
    for(j=0;j<3;j++){
      strncpy(buff,buffer+10*j,10);
      buff[10]=0;
      if(sscanf(buff,"%lf",m->atoms[i].abs+j)!=1)
	error_exit("Parse error for atomic position");
    }
    strncpy(buff,buffer+31,3);
    buff[3]=0;
    m->atoms[i].atno=atsym2no(buff);
  }
  
  add_basis(c,m);
  real2rec(c);
  addfrac(m->atoms,m->n,c->recip);
  
}

static void mol3_read(FILE* infile, struct unit_cell *c, struct contents *m){
  char buffer[LINE_SIZE+1],*cptr,name[5];
  int i,j,n,found,junk;

  if (debug) fprintf(stderr,"Reading V3000 mol file\n");
  
  name[4]=0;
  n=0;
  while(fgets(buffer,LINE_SIZE,infile)){
    if (strncasecmp(buffer,"M  V30",6)) continue;
    cptr=buffer+6;
    while((*cptr)&&(isspace(*cptr))) cptr++;
    if (!strncasecmp(cptr,"COUNTS",6)){
      cptr+=6;
      if (sscanf(cptr,"%d",&n)!=1) error_exit("error parsing counts line");
      break;
    }
  }

  if (n<1) error_exit("no atoms found");

  found=0;
  while(fgets(buffer,LINE_SIZE,infile)){
    if (strncasecmp(buffer,"M  V30",6)) continue;
    cptr=buffer+6;
    while((*cptr)&&(isspace(*cptr))) cptr++;
    if (!strncasecmp(cptr,"BEGIN",5)){
      cptr+=5;
      while((*cptr)&&(isspace(*cptr))) cptr++;
      if (!strncasecmp(cptr,"ATOM",4)){
	found=1;
	break;
      }
    }
  }

  if (!found) error_exit("no atom block found");

  m->n=n;
  m->atoms=malloc(n*sizeof(struct atom));
  if (!m->atoms) error_exit("malloc error for atoms");
  init_atoms(m->atoms,n);
  
  for(i=0;i<n;i++){
    if (!fgets(buffer,LINE_SIZE,infile)) error_exit("unexpected end of file");
    if (strncasecmp(buffer,"M  V30",6)) {i--; continue;}
    cptr=buffer+6;
    if (sscanf(cptr,"%d %4s %lf %lf %lf %n",&junk,name,
	       m->atoms[i].abs,m->atoms[i].abs+1,m->atoms[i].abs+2,&j)!=5)
      error_exit("parse error for atom line");
    m->atoms[i].atno=atsym2no(name);
    if (!m->atoms[i].atno){
      fprintf(stderr,"Unable to parse %s as atomic symbol\n",name);
      exit(1);
    }
  }

  add_basis(c,m);
  real2rec(c);
  addfrac(m->atoms,m->n,c->recip);

}