mmio_63_unpacked
|
Makefile,
Makefile.none,
Makefile.pro,
RCS_version,
README,
README.src,
cfmmio.c,
cftest,
cmmio.c,
copyright.C,
copyright.Fortran,
ctest,
description.C,
description.Fortran,
description.all,
fcmmio.f,
fctest,
fmmio.f,
fout.f,
ftest,
gagcomp.dat,
gagfull.dat,
make.version,
mmio.c,
mmio.h,
mmio.inc,
mmio_convert.c,
mmio_def.h,
mmio_uncompress.f,
mmioc.c,
mmioc.h,
mmiof.c,
my_cp,
prepmake,
title.C,
title.Fortran,
|
|
|
/* Copyright 1995, Columbia University, all rights reserved.
* Permission is granted to utilize and disseminate this code or
* document without charge, provided that (1) this copyright notice is
* not removed, and (2) all changes made by other than members of the
* MacroModel Development Group at Columbia University are, if further
* disseminated, (a) noted as such; for example, by means of source-code
* comment lines, and (b) communicated back to the author for possible
* inclusion in subsequent versions. */
/****************************************************************************
* $RCSfile: mmio.c,v $
* $Revision: 1.35 $
* $Date: 1998/02/06 05:31:23 $
***************************************************************************/
#include
#include
#include
#include
#include
#include "mmio.h"
#include "mmioc.h"
#define FALSE 0
#define TRUE 1
/* used in declarations of arrays to be malloc()ed: */
#define AR *
/* maximum size of an input line from readfile or output line to writefile: */
#define MAXLINE 512
/* state used for both read and write structs: */
#define UNUSED 0
#define FILE_OPEN 1
#define CT_DONE 2
#define ATOMS_IN_PROGRESS 3
#define ATOMS_DONE 4
/* info readable from full CT but not from compressed CT: */
struct ct_conntag {
struct conn_atomtag {
/* atom data that don't change with coordinates: */
int itype; /* mmod atom type */
int nbond; /* number of bonded neighbors (n's) */
int bond_atom[ MMIO_MAXBOND ]; /* atom numbers of bonded n's */
int bond_order[ MMIO_MAXBOND ]; /* bond orders to bonded n's */
float charge1; /* 1st charge field in .dat */
float charge2; /* 1st charge field in .dat */
char chain; /* pdb chain designator */
int resnum; /* pdb res number */
char resname1; /* 1-char res name */
char resname4[ MMIO_S_STRLEN + 1 ]; /* 4-char pdb res name */
char pdbname[ MMIO_S_STRLEN + 1 ]; /* 4-char pdb atom name */
char growname[ MMIO_S_STRLEN + 1 ]; /* 4-char pdb atom name */
} AR atom;
int natom; /* no. of atoms in this molecule */
int ict_read; /* which CT this was read from */
};
/* info readable from compressed CT: */
struct ct_comptag {
struct comp_atomtag {
/* data per atom: */
float xyz[ 3 ]; /* coords */
int color; /* color */
int mmod_iatom; /* MacroModel atom number -- index origin 1 */
} AR atom;
int natom; /* number of atoms stored in this struct */
int ict_read; /* which CT this was read from */
char title[ MMIO_L_STRLEN + 1 ]; /* title from input file */
};
/* used only if mode is MMIO_READ; includes data to facilitate random
* access to CT's in the file: */
struct readtag {
/* Information on each CT visited so far in the input file, plus the
* file offset, only, of the next CT beyond the last one read: */
struct ct_readtag {
long int offset;/* offset of beginning of CT in readfile */
int ict_full; /* most recent full CT in readfile */
int ct_type; /* MMIO_FULL or MMIO_COMPRESSED */
int natom; /* number of atom lines in input file */
} AR ct;
int nct; /* number of elements in ct_read */
int ict_current;/* current ict in storage */
int ict_next; /* next ict in file */
int eof; /* TRUE if EOF has been encountered */
char buf[ MAXLINE ]; /* one-line read-ahead cache */
};
/* master data structure; one replicate is allocated for each open file: */
struct datasettag {
char *fname; /* fname used in fopen() */
FILE *file; /* returned by fopen */
int mode; /* MMIO_READ or MMIO_WRITE */
int state; /* read_state or write_state */
struct ct_conntag *ct_conn;
struct ct_comptag *ct_comp, *full_ct_comp;
struct readtag *read;
int ct_type_last;/* last ct_type written (WRITE) or requested (READ) */
};
static struct datasettag AR dataset = NULL;
static int ndataset = 0;
/* dataset elements common to READ and WRITE data: */
#define Fname datum->fname
#define File datum->file
#define Mode datum->mode
#define State datum->state
#define Conn datum->ct_conn
#define Comp datum->ct_comp
#define Full_comp datum->full_ct_comp
#define Ct_type_last datum->ct_type_last
/* dataset elements exclusive to READ data: */
#define Ct_read datum->read->ct
#define Nct_read datum->read->nct
#define Ict_read_current datum->read->ict_current
#define Ict_read_next datum->read->ict_next
#define Read_eof datum->read->eof
#define Buf datum->read->buf
/* destination for error messages: */
/* ...whether error IO is to be done via C or Fortran, or is turned off: */
#define ERR_NONE 0
#define ERR_C 1
#define ERR_FORTRAN 2
int err_api = ERR_NONE;
/* ...C err-destination specification: */
FILE *errfile = NULL;
/* ...Fortran err-destination specification: */
int errunit = -1;
#if defined( BIND_ )
#define fline_mmio fline_mmio_
#elif defined( BIND__ )
#define fline_mmio fline_mmio__
#elif defined( BINDCRAY )
#define fline_mmio FLINE_MMIO
#endif
/*******************************************************************/
/* prototypes: */
/* ...utilities: */
static struct datasettag *check_datum( int idataset, int mode );
static int new_datum( int *idataset, char *fname, int mode, FILE *file );
static int skip_new_ct( struct datasettag *datum );
static int new_ct_read( struct datasettag *datum, int ct_type, int natom );
static int read_header( struct datasettag *datum, int *natom, char *title,
int reposition );
static int read_ct( struct datasettag *datum, struct ct_conntag *ct_conn,
struct ct_comptag *ct_comp, int ict );
static int write_ct( struct datasettag *datum );
static int read_atom( struct datasettag *datum, struct ct_conntag *ct_conn,
struct ct_comptag *ct_comp, int iatom, int ct_type );
static char *state_name( int state );
static int seekto_ct( struct datasettag *datum, int ict );
static void dump_ct_read( struct datasettag *datum );
static char *file_mode( int mode );
int free_datum( struct datasettag *datum );
char *my_fgets( char *cache, char *buf, int nbuf, FILE *stream,
int reposition );
void fline_mmio( int *errunit, char *buf, int *len );
/*******************************************************************/
int _goto_ct( int idataset, int ict_new )
/* position oneself to read the specified ct (index-origin 0); return
* MMIO_OK if there is a CT here or not known to be an MMIO_EOF here;
* MMIO_EOF if we try to go past an MMIO_EOF, or know there is an
* MMIO_EOF here; in latter case, remain positioned at MMIO_EOF;
* return MMIO_ERR if an error occurs; similarly, return MMIO_BOF
* if we attempt to position before beginning of file; in this instance,
* file pointer is positioned at beginning of file: */
{
int iskip, nskip;
struct datasettag *datum = check_datum( idataset, MMIO_READ );
if( datum == NULL ) {
_error_mmio( "_goto_ct: check_datum() fails;"
" invalid dataset %d specified\n", idataset );
return MMIO_ERR;
}
if( ict_new < 0 ) {
/* go to 1st CT, return BOF: */
if( _goto_ct(idataset,0) == MMIO_ERR ) {
_error_mmio(
"_goto_ct: _goto_ct() fails, , src_line= %d\n",
__LINE__ );
return MMIO_ERR;
}
return MMIO_BOF;
} else if( ict_new < Nct_read ) {
/* we've been there before, so just go there: */
switch( seekto_ct(datum,ict_new) ) {
case MMIO_ERR:
_error_mmio( "_goto_ct: seekto_ct() fails,"
" ict_new= %d, src_line= %d\n",
ict_new, __LINE__ );
return MMIO_ERR;
case MMIO_EOF:
/* this branch entered only if both
* ict_new==Nct_read-1, and it's previously
* known that EOF occurs here: */
Ict_read_next = ict_new;
return MMIO_EOF;
default:
Ict_read_next = ict_new;
}
} else if( Read_eof ) {
/* we know this CT doesn't exist; position ourselves at EOF: */
if( seekto_ct(datum,Nct_read) == MMIO_ERR ) {
_error_mmio(
"_goto_ct: seekto_ct() fails, Nct_read= %d,"
" src_line= %d\n", Nct_read, __LINE__ );
return MMIO_ERR;
}
Ict_read_next = Nct_read;
return MMIO_EOF;
} else {
/* we'll have to read ahead into uncharted territory; */
/* first position ourselves at last struct whose
* beginning location we know: */
Ict_read_next = Nct_read == 0 ? 0 : Nct_read - 1;
if( Nct_read>0
&& seekto_ct(datum,Ict_read_next)==MMIO_ERR ) {
_error_mmio(
"_goto_ct: seekto_ct() fails, Nct_read= %d,"
" src_line=%d\n", Nct_read, __LINE__ );
return MMIO_ERR;
}
/* venture forth into the unknown, skipping over each ct,
* until we reach the one specified: */
nskip = ict_new - Ict_read_next;
for( iskip=0; iskip=ndataset ) {
_error_mmio(
"check_datum: idataset= %d is outside current range of"
" 0 to %d\n", ndataset );
return NULL;
}
datum = dataset + idataset;
/* mode check is necessary if mode is other than MMIO_UNUSED: */
if( mode != MMIO_UNUSED ) {
return datum;
} else {
if( mode == MMIO_READ ) {
/* make sure datum is open for reading: */
if( Mode == MMIO_READ ) {
return datum;
}
} else if( mode==MMIO_WRITE || mode==MMIO_APPEND ) {
/* make sure datum is open for
* (any sort of) writing: */
if( Mode == MMIO_WRITE || mode==MMIO_APPEND ) {
return datum;
}
}
}
_error_mmio( "check_datum: mode= %s specified; "
" idataset %d has mode %s\n", file_mode(mode), idataset,
file_mode(Mode) );
return NULL;
}
/*******************************************************************/
int _skip_ct( int idataset, int nct_skip )
/* skip the specified number of ct's; remain positioned to read the next;
* return MMIO_OK, MMIO_EOF or MMIO_ERR: */
{
struct datasettag *datum = check_datum( idataset, MMIO_READ );
if( datum == NULL ) {
_error_mmio(
"_skip_ct: check_datum() fails; invalid dataset\n" );
return MMIO_ERR;
}
if( State < FILE_OPEN ) {
_error_mmio( "_skip_ct: state error; no input file open\n" );
return MMIO_ERR;
}
return _goto_ct( idataset, Ict_read_next+nct_skip );
}
/*******************************************************************/
int _count_ct( int idataset, int *nct )
/* read to EOF, keep no. of CT's in Nct_read and also return in nct;
* return status MMIO_OK or MMIO_ERR;
* return file pointer to where we originally were: */
{
struct datasettag *datum = check_datum( idataset, MMIO_READ );
int new_status;
int ict_temp;
if( datum == NULL ) {
_error_mmio(
"_count_ct: check_datum() fails; invalid dataset\n" );
return MMIO_ERR;
}
if( State < FILE_OPEN ) {
_error_mmio(
"_count_ct: state error; no input file open\n" );
return MMIO_ERR;
}
if( ! Read_eof ) {
ict_temp = Ict_read_next;
switch( _goto_ct(idataset,Nct_read) ) {
case MMIO_EOF:
/* discovered EOF at first unread CT: */
break;
case MMIO_ERR:
_error_mmio( "_count_ct: _goto_ct() fails, "
"Nct_read = %d\n", Nct_read );
return MMIO_ERR;
default:
break;
}
while( 1 ) {
new_status = skip_new_ct( datum );
if( new_status == MMIO_OK ) {
Ict_read_next += 1;
continue;
} else if( new_status == MMIO_ERR ) {
_error_mmio(
"_count_ct: skip_new_ct() fails\n" );
return MMIO_ERR;
} else if( new_status == MMIO_EOF ) {
break;
}
}
Ict_read_next = ict_temp;
if( seekto_ct(datum,ict_temp) == MMIO_ERR ) {
_error_mmio( "_count_ct: seekto_ct() fails,"
" Ict_read_next= %d\n", Ict_read_next );
return MMIO_ERR;
}
}
/* nct is one less than Nct_read, because there's an extra
* Ct_read[] element for the EOF marker: */
*nct = Nct_read - 1;
return MMIO_OK;
}
/*******************************************************************/
int _get_ct( int idataset, int ct_type_requested, int *natom, char *title )
/* Read the CT that we're positioned at the head of.
* Always return title from header line in variable title. if
* ct_type_requested is MMIO_FULL, natom will be the number of atoms in the
* full CT. If ct_type_requested is MMIO_COMPRESSED, then, if the CT
* in the disk file is in fact compressed and has the same CT as the
* last full CT read, natom will the the number of atoms in the compressed
* CT. If ct_type_requested is MMIO_FULL, or the current CT on disk is
* a full CT, then natom will contain the full number of atoms.
* Either way, the library will expect exactly natom calls to _get_atom()
* after this _get_ct() returns successfully. This function returns
* staus MMIO_EOF if EOF is encountered while reading the header, MMIO_ERR
* if MMIO_EOF encountered while reading atoms (incomplete CT) or if
* some other type of error occurs, and MMIO_COMPRESSED or MMIO_FULL
* depending on what type of CT is actually found in readfile. */
{
int retcode, ct_type;
struct datasettag *datum = check_datum( idataset, MMIO_READ );
if( datum == NULL ) {
_error_mmio(
"_goto_ct: check_datum() fails; invalid dataset\n" );
return MMIO_ERR;
}
/* check state: */
switch( State ) {
/* three states are legal for this command: */
case FILE_OPEN:
case CT_DONE:
/* in this case, the calling program is simply
* looking at all the title lines, and ignoring
* the atom data. */
case ATOMS_DONE:
break;
default:
_error_mmio(
"_get_ct: state error; current state is %s\n",
state_name(State) );
return MMIO_ERR;
}
Ct_type_last = ct_type_requested;
if( Ict_read_next < Nct_read-1 ) {
/* we've been here before: */
if( Ct_read[Ict_read_next].ct_type==MMIO_FULL ) {
switch( read_ct(datum,Conn,Full_comp,Ict_read_next)){
case MMIO_OK:
Ict_read_current = Ict_read_next;
Ict_read_next += 1;
break;
case MMIO_EOF:
return MMIO_EOF;
case MMIO_ERR:
_error_mmio(
"_get_ct: read_ct() fails,"
" Ict_read_next= %d, src_line= %d\n",
Ict_read_next, __LINE__ );
return MMIO_ERR;
}
*natom = Full_comp->natom;
strcpy( title, Full_comp->title );
retcode = MMIO_FULL;
} else if( Ct_read[Ict_read_next].ct_type==MMIO_COMPRESSED ) {
/* compressed ct; read comp here, conn elsewhere
* if necessary: */
switch( read_ct(datum,NULL,Comp,Ict_read_next) ) {
case MMIO_OK:
Ict_read_current = Ict_read_next;
Ict_read_next += 1;
retcode = MMIO_COMPRESSED;
break;
case MMIO_EOF:
return MMIO_EOF;
case MMIO_ERR:
_error_mmio(
"_get_ct: read_ct() fails,"
" Ict_read_next= %d, src_line=%d\n",
Ict_read_next, __LINE__ );
return MMIO_ERR;
}
if( Ct_read[Ict_read_current].ict_full
!= Conn->ict_read ) {
/* We need a different full CT: */
/* Go to correct full CT: */
switch( seekto_ct( datum,
Ct_read[Ict_read_current].ict_full) ) {
case MMIO_OK:
retcode = MMIO_FULL;
break;
case MMIO_EOF:
case MMIO_ERR:
_error_mmio(
"_get_ct: seekto_ct() "
"fails for ict_full= %d, "
"src_line= %d\n",
Ct_read[Ict_read_current]
.ict_full, __LINE__ );
return MMIO_ERR;
}
/* Read correct full CT: */
switch(
read_ct(datum,Conn,Full_comp,
Ct_read[Ict_read_current].ict_full) ) {
case MMIO_OK:
break;
case MMIO_EOF:
case MMIO_ERR:
_error_mmio(
"_get_ct: read_ct() "
"fails, ict_full= %d, "
"src_line= %d\n",
Ct_read[Ict_read_current]
.ict_full, __LINE__ );
return MMIO_ERR;
}
*natom = Full_comp->natom;
retcode = MMIO_FULL;
} else {
/* We have the right full CT: */
if( ct_type_requested == MMIO_FULL ) {
/* user requested full CT: */
*natom = Full_comp->natom;
retcode = MMIO_FULL;
} else {
/* user requested compressed CT: */
*natom = Comp->natom;
retcode = MMIO_COMPRESSED;
}
}
strcpy( title, Comp->title );
} else {
/* current CT has corrupted CT type: */
_error_mmio( "_get_ct: corrupted CT type '%s',"
" Ict_read_next= %d\n",
_return_code(Ct_read[Ict_read_next].ct_type),
Ict_read_next );
return MMIO_ERR;
}
} else if( Read_eof ) {
/* we know current CT request is beyond eof: */
Ict_read_next = Nct_read;
retcode = MMIO_EOF;
} else {
/* we don't know what lies ahead; read header to find out: */
ct_type = read_header( datum, natom, NULL, TRUE );
if( ct_type == MMIO_FULL ) {
switch( read_ct(datum,Conn,Full_comp,Ict_read_next) ) {
case MMIO_OK:
Ict_read_current = Ict_read_next;
Ict_read_next += 1;
break;
case MMIO_EOF:
return MMIO_EOF;
case MMIO_ERR:
_error_mmio(
"_get_ct: read_ct() fails, ",
"Ict_read_next= %d, src_line= %d\n",
Ict_read_next, __LINE__ );
return MMIO_ERR;
}
if( new_ct_read(datum,ct_type,Full_comp->natom)
!= MMIO_OK ) {
_error_mmio(
"_get_ct: new_ct_read() fails, ",
"Nct_read= %d, src_line= %d\n",
Nct_read, __LINE__ );
return MMIO_ERR;
}
*natom = Full_comp->natom;
strcpy( title, Full_comp->title );
retcode = MMIO_FULL;
} else if( ct_type == MMIO_COMPRESSED ) {
/* compressed ct; read comp here, conn elsewhere
* if necessary: */
switch( read_ct(datum,NULL,Comp,Ict_read_next) ) {
case MMIO_OK:
Ict_read_current = Ict_read_next;
Ict_read_next += 1;
retcode = MMIO_COMPRESSED;
break;
case MMIO_EOF:
return MMIO_EOF;
case MMIO_ERR:
_error_mmio(
"_get_ct: read_ct() fails, ",
"Ict_read_current= %d,"
" src_line= %d\n",
Ict_read_current, __LINE__ );
return MMIO_ERR;
}
if( new_ct_read(datum,ct_type,Comp->natom)
!= MMIO_OK ) {
_error_mmio(
"_get_ct: new_ct_read() fails, ",
"Nct_read= %d, src_line= %d\n",
Nct_read, __LINE__ );
return MMIO_ERR;
}
if( Ct_read[Ict_read_current].ict_full
!= Conn->ict_read ) {
/* We need a different full CT: */
/* Go to correct full CT: */
switch( seekto_ct(datum,
Ct_read[Ict_read_current].ict_full) ) {
case MMIO_OK:
retcode = MMIO_FULL;
break;
case MMIO_EOF:
case MMIO_ERR:
_error_mmio(
"_get_ct: seekto_ct() "
"fails for ict_full= %d, ",
"src_line= %d\n",
Ct_read[Ict_read_current]
.ict_full, __LINE__ );
return MMIO_ERR;
}
/* Read correct full CT: */
switch(
read_ct(datum,Conn,Full_comp,
Ct_read[Ict_read_current].ict_full) ) {
case MMIO_OK:
break;
case MMIO_EOF:
case MMIO_ERR:
_error_mmio(
"_get_ct: read_ct() "
"fails, ict_full= %d, "
"src_line= %d\n",
Ct_read[Ict_read_current]
.ict_full, __LINE__ );
return MMIO_ERR;
}
*natom = Full_comp->natom;
retcode = MMIO_FULL;
} else {
/* We had the correct full CT: */
if( ct_type_requested == MMIO_FULL ) {
/* user requested full CT: */
*natom = Full_comp->natom;
retcode = MMIO_FULL;
} else {
/* user requested compressed CT: */
*natom = Comp->natom;
retcode = MMIO_COMPRESSED;
}
}
strcpy( title, Comp->title );
} else if( ct_type == MMIO_ERR ) {
_error_mmio( "_get_ct: read_header() fails,"
" Ict_read_next= %d\n", Ict_read_next );
return MMIO_ERR;
} else if( ct_type == MMIO_EOF ) {
retcode = MMIO_EOF;
}
}
/* position ourselves just before next CT to be read;
* (under certain circumstances, we may already be there): */
if( seekto_ct(datum,Ict_read_next) == MMIO_ERR ) {
_error_mmio(
"_get_ct: seekto_ct() fails, Ict_read_next= %d, offset="
" %d\n", Ict_read_next, Ct_read[Ict_read_next].offset );
return MMIO_ERR;
}
/* update state: */
switch( retcode ) {
case MMIO_EOF:
break;
default:
State = CT_DONE;
}
return retcode;
}
/*******************************************************************/
static int skip_new_ct( struct datasettag *datum )
/* Starting just before the header line of a CT, skip over the CT.
* Return MMIO_OK if successful, MMIO_EOF if MMIO_EOF encountered
* while reading the header, MMIO_ERR if MMIO_EOF encountered while
* reading atoms (incomplete CT) or if MMIO_ERR is encountered anywhere.
* This function should be called only when reading over a portion of
* the file not visited before, when it is desired to skip over,
* rather than store, the contents.
* This routine calls new_ct_read(), which stores summary info
* about the CT skipped. These data can be used on subsequent visits
* to this part of the file. */
{
char buf[ MAXLINE ];
int natom, iatom;
int ct_type, retcode;
/* read the header line, checking for MMIO_EOF or MMIO_ERR: */
switch( ct_type=read_header(datum,&natom,NULL,FALSE) ) {
case MMIO_EOF:
retcode = MMIO_EOF;
break;
case MMIO_ERR:
_error_mmio( "skip_new_ct: read_header() fails\n" );
return MMIO_ERR;
default:
retcode = MMIO_OK;
break;
}
if( retcode == MMIO_OK ) {
/* skip one line in input file for each atom: */
for( iatom=0; iatom=0; --ict ) {
if( Ct_read[ict].ct_type == MMIO_FULL ) {
Ct_read[ ict_current ].ict_full = ict;
break;
}
}
}
if( ct_type != MMIO_EOF ) {
/* fill in the .offset field for the next CT to be read, based
* on current file position: */
Ct_read[ ict_next ].offset = ftell( File );
Ct_read[ ict_next ].ct_type = MMIO_OK; /* nonsense */
}
return MMIO_OK;
}
/*******************************************************************/
static int read_ct( struct datasettag *datum, struct ct_conntag *ct_conn,
struct ct_comptag *ct_comp, int ict)
/* read conn info into ct_conn, unless this ptr is NULL; read
* comp info into ct_comp, unless this ptr is NULL;
* return status MMIO_OK if all goes well, MMIO_EOF if eof encountered,
* MMIO_ERR if err encountered: */
{
int natom, iatom;
int ct_type, retcode;
char title[ MMIO_L_STRLEN + 1 ];
switch( ct_type=read_header(datum,&natom,title,FALSE) ) {
case MMIO_ERR:
_error_mmio( "read_ct: read_header() fails\n" );
return MMIO_ERR;
case MMIO_EOF:
retcode = MMIO_EOF;
natom = 0;
break;
default:
retcode = MMIO_OK;
break;
}
/* alloc conn atom struct: */
if( ct_conn != NULL ) {
/* make sure ct_conn has the right number of
* atoms; if not, realloc(): */
if( ct_conn->atom == NULL ) {
ct_conn->atom = ( struct conn_atomtag *)
malloc( natom*sizeof(struct conn_atomtag) );
} else if( natom != ct_conn->natom ) {
ct_conn->atom = ( struct conn_atomtag *)
realloc( ct_conn->atom,
natom*sizeof(struct conn_atomtag) );
}
if( ct_conn->atom == NULL ) {
_error_mmio( "read_ct: malloc() fails for"
" ct_conn->atom\n" );
return MMIO_ERR;
}
ct_conn->natom = natom;
ct_conn->ict_read = ict;
}
/* alloc comp atom struct: */
if( ct_comp != NULL ) {
/* make sure ct_comp has the right number of
* atoms; if not, realloc(): */
if( natom!=ct_comp->natom || ct_comp->atom==NULL ) {
if( ct_comp->atom == NULL ) {
ct_comp->atom = ( struct comp_atomtag *)
malloc(
natom*sizeof(struct comp_atomtag) );
} else {
ct_comp->atom = ( struct comp_atomtag *)
realloc( ct_comp->atom,
natom*sizeof(struct comp_atomtag) );
}
if( ct_comp->atom == NULL ) {
_error_mmio( "read_ct: malloc() fails for "
"ct_comp->atom\n" );
return MMIO_ERR;
}
ct_comp->natom = natom;
}
/* copy title into ct_comp: */
strncpy( ct_comp->title, title, MMIO_L_STRLEN );
ct_comp->title[ MMIO_L_STRLEN ] = '\0';
ct_comp->ict_read = ict;
}
/* read atom lines, checking for MMIO_EOF or MMIO_ERR: */
for( iatom=0; iatom= 0 ) {
err_api = ERR_FORTRAN;
} else {
err_api = ERR_NONE;
}
errunit = unit;
}
/*******************************************************************/
static int read_atom( struct datasettag *datum, struct ct_conntag *ct_conn,
struct ct_comptag *ct_comp, int iatom, int ct_type )
/* read info out of buf, which is an atom line from a MMIO_FULL or
* MMIO_COMPRESSED CT entry, into temporary variables; copy
* appropriate variables to ct_conn, if this is not NULL, and ct_comp,
* if this is not NULL.
* iatom is the serial atom-line entry in the CT; if the CT was in
* MMIO_FULL format, this is the index into the ct_comp and ct_conn atom
* entries; if the CT was in MMIO_COMPRESSED format, obtain this index
* from the first entry in buf.
* ct_type had better be either MMIO_COMPRESSED or MMIO_FULL; if not,
* MMIO_ERR is returned.
* A variety of ugh-er-ly kludges are necessary to read old mmod
* formats using C IO. Fortran IO can just read the lines.
* I leave it to the more philosophical to speculate upon the
* implications of this. */
{
struct conn_atomtag *conn_atom;
struct comp_atomtag *comp_atom;
int len;
int nscan, nscan_comp=5, nscan_full=24;
char buf[ MAXLINE ];
char *ptr;
/* format for reading full atom line: */
char *fmt_read_full = "%*c%3d" /* atom type */
"%*c%5d%*c%1d%*c%5d%*c%1d%*c%5d%*c%1d" /* 6 conn atoms & bond-orders*/
"%*c%5d%*c%1d%*c%5d%*c%1d%*c%5d%*c%1d"
"%*c%11f%*c%11f%*c%11f%*c" /* xyz */
/* everything beyond this point is read into fixed-lenth strings: */
"%5c%c%c" /* res#, 1-letter code, chain */
"%4c%9c%9c" /* color, charge1, charge2 */
"%*c%4c%*c%4c" /* 4-letter resname, pdbname */
"%*c%4c"; /* 4-letter growname */
/* format for reading compressed atom line: */
char *fmt_read_comp = "%d %f %f %f %d"; /* atom number, xyz, color */
int i;
/* atom data that don't change with coordinates: */
int itype; /* mmod atom type */
int nbond; /* number of bonded neighbors (n's) */
int bond_atom[ MMIO_MAXBOND ]; /* atom numbers of bonded n's */
int bond_order[ MMIO_MAXBOND ]; /* bond orders to bonded n's */
float charge1; /* 1st charge field in .dat */
float charge2; /* 1st charge field in .dat */
int resnum; /* pdb res number */
char resname1; /* 1-char res name */
char chain; /* pdb chain designator */
char resname4[ MMIO_S_STRLEN + 1 ]; /* 4-char pdb res name */
char pdbname[ MMIO_S_STRLEN + 1 ]; /* 4-char pdb atom name */
char growname[ MMIO_S_STRLEN + 1 ]; /* 4-char pdb atom name */
/* strings for temp. storage of integer and float data occurring
* after the xyz fields in a full atom line; this is part of
* the accommodation of old-style mmod formats: */
char resnum_str[ 6 ], color_str[ 5 ],
charge1_str[ 10 ], charge2_str[ 10 ];
/* atom data that do change with coordinates: */
int mmod_iatom; /* mmod atom number: index origin 1 */
float xyz[ 3 ]; /* coords */
int color; /* color */
/* try to get a line from the file; bomb out if we fail: */
if( my_fgets(Buf,buf,MAXLINE,File,FALSE) == NULL ) {
_error_mmio( "read_atom: my_fgets() fails\n" );
return MMIO_ERR;
}
/* preprocess atom line: */
/* ... first remove any embedded ASCII NULs --
* (these sometimes exist in old mmod files): */
for( ptr=buf; ptr-bufatom + iatom;
conn_atom->itype = itype;
nbond = 0;
for( i=0; i<6; ++i ) {
if( bond_atom[i] > 0 ) {
nbond += 1;
} else {
break;
}
conn_atom->bond_atom[ i ] = bond_atom[ i ];
conn_atom->bond_order[ i ] = bond_order[ i ];
}
conn_atom->nbond = nbond;
conn_atom->charge1 = charge1;
conn_atom->charge2 = charge2;
conn_atom->chain = chain;
conn_atom->resnum = resnum;
conn_atom->resname1 = resname1;
strcpy( conn_atom->resname4, resname4 );
strcpy( conn_atom->pdbname, pdbname );
strcpy( conn_atom->growname, growname );
}
/* copy comp info: */
if( ct_comp != NULL ) {
comp_atom = ct_comp->atom + iatom;
for( i=0; i<3; ++i ) {
comp_atom->xyz[ i ] = xyz[ i ];
}
comp_atom->color = color;
if( ct_type == MMIO_FULL ) {
comp_atom->mmod_iatom = iatom + 1;
} else {
comp_atom->mmod_iatom = mmod_iatom;
}
}
return MMIO_OK;
}
/*******************************************************************/
int _get_atom( int idataset, int *mmod_iatom, int *itype, int *nbond,
int *bond_atom, int *bond_order, float *xyz, float *charge1, float *charge2,
char *chain, int *color, int *resnum, char *resname1, char *resname4,
char *pdbname, char *growname, int from_fortran )
/* Return info on the next atom on the list. If the current CT
* (ict_read) is MMIO_FULL, we will always traverse the entire atom list. If
* it is MMIO_COMPRESSED, we will traverse the entire list if
* ct_type_last_requested is MMIO_FULL; else, if ct_type_last_requested is
* MMIO_COMPRESSED, we will traverse only the atoms that have comp info
* differing from that of its corresponding full CT. Above info is
* returned in the argument list.
* The function itself returns MMIO_ERR if error encountered, MMIO_DONE when
* returning info on the last atom, and MMIO_OK when returning info on
* other atoms: */
{
static int ifull, icomp, comp_natom, get_full;
struct comp_atomtag *comp_atom;
struct conn_atomtag *conn_atom;
int i, iconn, retcode = MMIO_OK;
struct datasettag *datum = check_datum( idataset, MMIO_READ );
static int ct_type_current;
if( datum == NULL ) {
_error_mmio(
"_get_atom: check_datum() fails; invalid dataset\n" );
return MMIO_ERR;
}
/* error check on read_state: */
switch( State ) {
case CT_DONE:
/* Initializations which will hold until all atoms
* are transferred: */
/* ... indices into full_ct_comp and ct_comp: */
ifull = icomp = 0;
/* ... type of ct that we are reading from: */
ct_type_current = Ct_read[ Ict_read_current ].ct_type;
/* ... number of atoms to be read from ct_comp: */
comp_natom
= ct_type_current == MMIO_FULL
? 0 : Comp->natom;
/* ... TRUE if we're returning the full CT: */
get_full =
ct_type_current == MMIO_FULL
|| Ct_type_last == MMIO_FULL;
State = ATOMS_IN_PROGRESS;
break;
case ATOMS_IN_PROGRESS:
break;
default:
_error_mmio( "_get_atom: state error; state"
" is %s\n", state_name(State) );
return MMIO_ERR;
}
if( get_full ) {
/* We're reporting all atoms.
* Figure out which comp to get the data from; use
* read_full_ct_comp if any of the following three
* conditions is met:
* 1.current ct_type is MMIO_FULL,
* 2.we've exhausted the end of ct_comp,
* 3.next atom to be reported doesn't exist in
* read_ct_comp:*/
if( ct_type_current==MMIO_FULL
|| icomp>=comp_natom
|| Full_comp->atom[ifull].mmod_iatom
atom[icomp].mmod_iatom ) {
/* get data from read_full_ct_comp: */
comp_atom = Full_comp->atom + ifull;
} else {
/* get data from ct_comp: */
comp_atom = Comp->atom + icomp;
icomp += 1;
}
*mmod_iatom = ifull + 1;
iconn = ifull;
ifull += 1;
if( ifull >= Conn->natom ) {
retcode = MMIO_DONE;
}
} else {
/* we're reporting only on the updated atoms: */
comp_atom = Comp->atom + icomp;
*mmod_iatom = comp_atom->mmod_iatom;
iconn = comp_atom->mmod_iatom - 1;
icomp += 1;
if( icomp >= comp_natom ) {
retcode = MMIO_DONE;
}
}
/* comp data: */
xyz[ 0 ] = comp_atom->xyz[ 0 ];
xyz[ 1 ] = comp_atom->xyz[ 1 ];
xyz[ 2 ] = comp_atom->xyz[ 2 ];
*color = comp_atom->color;
if( get_full ) {
/* conn data: */
conn_atom = Conn->atom + iconn;
*itype = conn_atom->itype;
*nbond = conn_atom->nbond;
for( i=0; inbond; ++ i ) {
bond_atom[ i ] = conn_atom->bond_atom[ i ];
bond_order[ i ] = conn_atom->bond_order[ i ];
}
*charge1 = conn_atom->charge1;
*charge2 = conn_atom->charge2;
*chain = conn_atom->chain;
*resnum = conn_atom->resnum;
*resname1 = conn_atom->resname1;
strncpy( resname4, conn_atom->resname4, MMIO_S_STRLEN );
strncpy( pdbname, conn_atom->pdbname, MMIO_S_STRLEN );
strncpy( growname, conn_atom->growname, MMIO_S_STRLEN );
if( ! from_fortran ) {
resname4[ MMIO_S_STRLEN ]
= pdbname[ MMIO_S_STRLEN ]
= growname[ MMIO_S_STRLEN ]
= '\0';
}
}
if( retcode == MMIO_DONE ) {
State = ATOMS_DONE;
}
return retcode;
}
/*******************************************************************/
int _file_open( int *idataset, char *fname, int mode )
/* Open a disk file for reading (if mode is MMIO_READ) or for writing (if
* mode is MMIO_WRITE or MMIO_APPEND; "MMIO_WRITE" implies overwriting.
* Return MMIO_OK unless an error occurs, in which case return MMIO_ERR: */
{
char *fmode;
FILE *file;
/* first check input args: */
if( mode == MMIO_READ ) {
fmode = "r";
} else if( mode == MMIO_WRITE ) {
fmode = "w";
} else if( mode == MMIO_APPEND ) {
fmode = "a";
} else {
_error_mmio( "_file_open: illegal mode %d received; must be"
" MMIO_READ, MMIO_WRITE or MMIO_APPEND\n", mode );
return MMIO_ERR;
}
/* open file; first see if stdin/stdout was requested: */
if( strcmp(fname,"-") == 0 ) {
/* stdin/stdout: */
if( mode == MMIO_READ ) {
file = stdin;
} else {
/* no further mode-checking necessary, since we
* exhausted all possibilities in previous block: */
file = stdout;
}
} else if( (file=fopen(fname,fmode)) == NULL ) {
/* a named file is specified: */
_error_mmio( "_file_open: fopen() fails, "
"fname= '%s', fmode= '%s', '%s'\n", fname, fmode,
strerror(errno) );
return MMIO_ERR;
}
/* alloc a new dataset: */
if( new_datum(idataset,fname,mode,file) == MMIO_ERR ) {
_error_mmio( "_file_open: dataset() fails, fname= '%s'\n",
fname );
return MMIO_ERR;
}
return MMIO_OK;
}
/*******************************************************************/
static int new_datum( int *idataset, char *fname, int mode, FILE *file )
{
struct datasettag *datum = NULL;
int idata;
*idataset = -1;
/* look for existing dataset whose contents have been freed: */
for( idata=0; idatafname = malloc( strlen(fname) + 1 );
if( datum->fname == NULL ) {
_error_mmio( "new_datum: malloc of datum->fname fails, "
"fname= '%s', ndataset= %d\n", fname, ndataset );
return MMIO_ERR;
}
strcpy( datum->fname, fname );
datum->file = file;
datum->mode = mode;
datum->state = FILE_OPEN;
datum->ct_conn = (struct ct_conntag *)malloc(
sizeof(struct ct_conntag) );
if( datum->ct_conn == NULL ) {
_error_mmio( "new_datum: malloc of ct_conn fails, "
"ndataset= %d\n", ndataset );
return MMIO_ERR;
}
datum->ct_conn->atom = NULL;
datum->ct_conn->natom = 0;
datum->ct_conn->ict_read = -1;
datum->ct_comp = (struct ct_comptag *)malloc(
sizeof(struct ct_comptag) );
if( datum->ct_comp == NULL ) {
_error_mmio( "new_datum: malloc of ct_comp fails, "
"ndataset= %d\n", ndataset );
return MMIO_ERR;
}
datum->ct_comp->atom = NULL;
datum->ct_comp->natom = 0;
datum->full_ct_comp = (struct ct_comptag *)malloc(
sizeof(struct ct_comptag) );
if( datum->ct_comp == NULL ) {
_error_mmio( "new_datum: malloc of full_ct_comp fails, "
"ndataset= %d\n", ndataset );
return MMIO_ERR;
}
datum->full_ct_comp->atom = NULL;
datum->full_ct_comp->natom = 0;
datum->ct_type_last = MMIO_ERR;
/* initialize dataset elements used only for READ structures: */
if( mode == MMIO_READ ) {
datum->read
= (struct readtag *)malloc( sizeof(struct readtag) );
if( datum->read == NULL ) {
_error_mmio( "new_datum: malloc of read fails, "
"ndataset= %d\n", ndataset );
return MMIO_ERR;
}
datum->read->ct = NULL;
datum->read->nct = 0;
datum->read->ict_current = -1;
datum->read->ict_next = 0;
datum->read->eof = FALSE;
datum->read->buf[0] = '\0';
} else {
datum->read = NULL;
}
return MMIO_OK;
}
/*******************************************************************/
int _put_ct( int idataset, int ct_type, int natom, char *title )
/* Prepare to write to disk either a MMIO_FULL or a MMIO_COMPRESSED CT,
* depending on the value of ct_type. natom is the number of atom
* lines that will be written. Return MMIO_OK or MMIO_ERR: */
{
struct ct_comptag *comp;
struct datasettag *datum = check_datum( idataset, MMIO_WRITE );
char *ptr;
if( datum == NULL ) {
_error_mmio(
"_put_ct: check_datum() fails; invalid dataset\n" );
return MMIO_ERR;
}
switch( State ) {
/* it's legal to write a CT only in two write-states: */
case FILE_OPEN:
case ATOMS_DONE:
break;
default:
_error_mmio( "_put_ct: state error; write_state= %s\n",
state_name(State) );
return MMIO_ERR;
}
if( ct_type == MMIO_FULL ) {
/* full CT; update conn & full comp: */
comp = Full_comp;
Ct_type_last = MMIO_FULL;
} else if( ct_type == MMIO_COMPRESSED ) {
/* partial CT; update partial comp: */
comp = Comp;
Ct_type_last = MMIO_COMPRESSED;
} else {
_error_mmio( "_put_ct: illegal ct_type= %s\n",
_return_code(ct_type) );
return MMIO_ERR;
}
/* set no. of atoms in whichever comp we're using;
* alloc storage for them: */
comp->natom = natom;
if( comp->atom == NULL ) {
comp->atom = ( struct comp_atomtag *)malloc(
natom*sizeof(struct comp_atomtag) );
} else {
comp->atom = ( struct comp_atomtag *)realloc(
comp->atom, natom*sizeof(struct comp_atomtag) );
}
if( comp->atom == NULL ) {
comp->natom = 0;
_error_mmio( "_put_ct: malloc fails for comp->atom\n" );
return MMIO_ERR;
}
strncpy( comp->title, title, MMIO_L_STRLEN );
comp->title[ MMIO_L_STRLEN ] = '\0';
/* truncate trailing blanks: */
for( ptr=comp->title+MMIO_L_STRLEN-1; *ptr==' '; --ptr ) {
*ptr = '\0';
}
if( Ct_type_last == MMIO_FULL ) {
/* set number of atoms in conn & alloc storage for them: */
Conn->natom = natom;
if( Conn->atom == NULL ) {
Conn->atom = ( struct conn_atomtag *)malloc(
natom*sizeof(struct conn_atomtag) );
} else {
Conn->atom = ( struct conn_atomtag *)realloc(
Conn->atom,natom*sizeof(struct conn_atomtag) );
}
if( Conn->atom == NULL ) {
Conn->natom = 0;
_error_mmio(
"_put_ct: malloc() fails for Conn->atom\n" );
return MMIO_ERR;
}
}
State = CT_DONE;
return MMIO_OK;
}
/*******************************************************************/
int _file_close( int idataset )
/* Close the file that is open for MMIO_READ, MMIO_WRITE or MMIO_APPEND,
* depending on the value of mode. Return MMIO_ERR or MMIO_OK.
* MMIO_WRITE or MMIO_APPEND are synonymous in this function: */
{
struct datasettag *datum = check_datum( idataset, MMIO_ERR );
if( datum == NULL ) {
_error_mmio( "_file_close: check_datum() fails\n" );
}
/* first perform bounds/consistency check on input: */
if( idataset<0 || idataset>=ndataset ) {
_error_mmio(
"_file_close: idataset= %d is outside current range of "
"0 through %d\n", ndataset-1 );
return MMIO_ERR;
}
datum = dataset + idataset;
if( Mode == MMIO_UNUSED ) {
_error_mmio(
"_file_close: idataset= %d was not open\n", idataset );
return MMIO_ERR;
}
if( free_datum(datum) == MMIO_ERR ) {
_error_mmio( "_file_close: free_datum() fails\n" );
return MMIO_ERR;
}
return MMIO_OK;
}
/*******************************************************************/
static int write_ct( struct datasettag *datum )
/* Write to disk the CT currently in the write buffer. If
* ct_type_last_written is MMIO_FULL, write in full CT format, taking
* conn data from write_ct_conn and comp data from write_full_ct_comp;
* else, if ct_type_last_written is MMIO_COMPRESSED, write in compressed
* CT format, ignoring conn data and taking comp data from write_ct_comp.
* Return MMIO_OK if we succeed, MMIO_ERR if an error occurs: */
{
struct comp_atomtag *comp_atom;
struct conn_atomtag *conn_atom;
int iatom, natom, ibond, nbond;
char *title;
/* format for writing header line: */
#if 0
char *fmt_header = " %5d %-70s\n";
#endif
char *fmt_header = " %5d %s\n";
/* format for writing full atom line: */
char *fmt_conn = "%4d " /* atom type */
"%5d %1d %5d %1d %5d %1d %5d %1d %5d %1d %5d %1d " /*atoms & b-orders*/
"%11.6f %11.6f %11.6f " /* xyz */
"%5d" /* skip space, res number */
"%c%c" /* 1-letter res code, chain */
"%4d%9.5f%9.5f" /* color, charge1, charge2 */
" %4s %4s\n"; /* 4-letter resname, atomname */
/* format for writing compressed atom line: */
char *fmt_comp
= "%5d %11.6f %11.6f %11.6f %5d\n";/* mmod#, xyz, color */
/* define origin of data to be written: */
if( Ct_type_last == MMIO_FULL ) {
natom = Full_comp->natom;
title = Full_comp->title;
comp_atom = Full_comp->atom;
conn_atom = Conn->atom;
} else if( Ct_type_last == MMIO_COMPRESSED ) {
natom = Comp->natom;
title = Comp->title;
comp_atom = Comp->atom;
conn_atom = NULL;
} else {
_error_mmio( "write_ct: illegal ct_type_last_written= %s\n",
_return_code(Ct_type_last) );
return MMIO_ERR;
}
/* write header line: */
if( fprintf(File,fmt_header,
Ct_type_last==MMIO_COMPRESSED?-natom:natom,title) == EOF ) {
_error_mmio( "write_ct: fprintf() fails for header, '%s'\n",
strerror(errno) );
return MMIO_ERR;
}
/* write atom lines: */
if( Ct_type_last == MMIO_FULL ) {
for( iatom=0; iatomnbond;
for( ibond=nbond; ibondbond_atom[ ibond ] = 0;
conn_atom->bond_order[ ibond ] = 0;
}
if( fprintf(File, fmt_conn,
conn_atom->itype,
conn_atom->bond_atom[0],
conn_atom->bond_order[0],
conn_atom->bond_atom[1],
conn_atom->bond_order[1],
conn_atom->bond_atom[2],
conn_atom->bond_order[2],
conn_atom->bond_atom[3],
conn_atom->bond_order[3],
conn_atom->bond_atom[4],
conn_atom->bond_order[4],
conn_atom->bond_atom[5],
conn_atom->bond_order[5],
comp_atom->xyz[0],
comp_atom->xyz[1],
comp_atom->xyz[2],
conn_atom->resnum,
conn_atom->resname1,
conn_atom->chain,
comp_atom->color,
conn_atom->charge1,
conn_atom->charge2,
conn_atom->resname4,
conn_atom->pdbname ) == EOF ) {
_error_mmio( "write_ct: fprintf() fails "
"for atom %d, src_line= %d, '%s'\n",
iatom, __LINE__, strerror(errno) );
return MMIO_ERR;
}
conn_atom += 1;
comp_atom += 1;
}
} else {
for( iatom=0; iatommmod_iatom,
comp_atom->xyz[0],
comp_atom->xyz[1],
comp_atom->xyz[2],
comp_atom->color) == EOF ) {
_error_mmio( "write_ct: fprintf() fails "
"for atom %d, src_line= %d, '%s'\n",
iatom, __LINE__, strerror(errno) );
return MMIO_ERR;
}
comp_atom += 1;
}
}
if( fflush(File) != 0 ) {
_error_mmio( "write_ct: fflush() fails, fname= '%s', '%s'\n",
Fname, strerror(errno) );
return MMIO_ERR;
}
return MMIO_OK;
}
/*******************************************************************/
int _put_atom( int idataset, int mmod_iatom, int itype, int nbond,
int *bond_atom, int *bond_order, float *xyz, float charge1, float charge2,
char chain, int color, int resnum, char resname1, char *resname4,
char *pdbname, char *growname )
/* Fill an atom entry in the write buffer with info for the next atom.
* If ct_type_last_written is MMIO_FULL, we will write conn info into
* write_ct_conn and comp info into write_full_ct_comp; else, if
* ct_type_last_written is MMIO_COMPRESSED, we will write no conn info and
* will write comp info into write_ct_comp.
* After info for the last expected atom is received, write the CT
* out to disk, reset write_state and return MMIO_DONE. For previous atoms,
* just return MMIO_OK. If an error occurs anywhere, return MMIO_ERR: */
{
static int iatom, natom;
static struct comp_atomtag *comp_atom;
static struct conn_atomtag *conn_atom;
int ibond;
struct datasettag *datum = check_datum( idataset, MMIO_WRITE );
if( datum == NULL ) {
_error_mmio(
"_put_atom: check_datum() fails; invalid dataset\n" );
return MMIO_ERR;
}
switch( State ) {
/* two legal states for this command: */
case CT_DONE:
iatom = 0;
if( Ct_type_last == MMIO_FULL ) {
natom = Full_comp->natom;
comp_atom = Full_comp->atom;
conn_atom = Conn->atom;
} else if( Ct_type_last == MMIO_COMPRESSED ) {
natom = Comp->natom;
comp_atom = Comp->atom;
conn_atom = NULL;
} else {
_error_mmio( "_put_atom: illegal "
"Ct_type_last= %s\n",
_return_code(Ct_type_last) );
return MMIO_ERR;
}
break;
case ATOMS_IN_PROGRESS:
break;
default:
_error_mmio(
"_put_atom: state error; write_state= %s\n",
state_name(State) );
return MMIO_ERR;
}
/* comp data: */
comp_atom->xyz[ 0 ] = xyz[ 0 ];
comp_atom->xyz[ 1 ] = xyz[ 1 ];
comp_atom->xyz[ 2 ] = xyz[ 2 ];
comp_atom->color = color;
comp_atom->mmod_iatom = mmod_iatom;
/* conn data: */
if( conn_atom != NULL ) {
conn_atom->itype = itype;
conn_atom->nbond = nbond;
for( ibond=0; ibondbond_atom[ ibond ]
= bond_atom[ ibond ];
conn_atom->bond_order[ ibond ]
= bond_order[ ibond ];
}
conn_atom->charge1 = charge1;
conn_atom->charge2 = charge2;
conn_atom->chain = chain;
conn_atom->resnum = resnum;
conn_atom->resname1 = resname1;
strncpy( conn_atom->resname4, resname4, MMIO_S_STRLEN );
conn_atom->resname4[ MMIO_S_STRLEN ] = '\0';
strncpy( conn_atom->pdbname, pdbname, MMIO_S_STRLEN );
strncpy( conn_atom->growname, growname, MMIO_S_STRLEN );
conn_atom->pdbname[ MMIO_S_STRLEN ] = '\0';
conn_atom->growname[ MMIO_S_STRLEN ] = '\0';
conn_atom += 1;
}
comp_atom += 1;
iatom += 1;
if( iatom >= natom ) {
State = ATOMS_DONE;
if( write_ct(datum) != MMIO_OK ) {
_error_mmio( "_put_atom: write_ct() fails\n" );
return MMIO_ERR;
}
return MMIO_DONE;
} else {
State = ATOMS_IN_PROGRESS;
return MMIO_OK;
}
}
/*******************************************************************/
char *_return_code( int status )
{
static char errmsg[ MMIO_L_STRLEN ];
switch( status ) {
case MMIO_COMPRESSED:
return "MMIO_COMPRESSED";
case MMIO_FULL:
return "MMIO_FULL";
case MMIO_OK:
return "MMIO_OK";
case MMIO_EOF:
return "MMIO_EOF";
case MMIO_BOF:
return "MMIO_BOF";
case MMIO_DONE:
return "MMIO_DONE";
case MMIO_ERR:
return "MMIO_ERR";
default:
sprintf( errmsg, "unknown return code %d", status );
return errmsg;
}
}
/*******************************************************************/
static char *file_mode( int mode )
{
static char errmsg[ MMIO_L_STRLEN ];
switch( mode ) {
case MMIO_READ:
return "MMIO_READ";
case MMIO_WRITE:
return "MMIO_WRITE";
case MMIO_APPEND:
return "MMIO_APPEND";
case MMIO_UNUSED:
return "MMIO_UNUSED";
default:
sprintf( errmsg, "unknown file mode %d", mode );
return errmsg;
}
}
/*******************************************************************/
static int read_header( struct datasettag *datum, int *natom, char *title,
int reposition )
/* read the header line that we're pointing at now; return number
* of atoms in natom. If title is not passed as NULL, return Title
* in title. If reposition is TRUE, fseek() to where we were
* in the input file at function entry before returning.
* return status MMIO_FULL, MMIO_COMPRESSED, MMIO_EOF or MMIO_ERR: */
{
char buf[ MAXLINE ];
char *ptr;
int ct_type;
int nscan;
/* read the line: */
if( my_fgets(Buf,buf,MAXLINE,File,reposition) == NULL ) {
/* handle EOF or ERR: */
if( feof(File) != 0 ) {
/* EOF: */
Read_eof = TRUE;
ct_type = MMIO_EOF;
*natom = 0;
return MMIO_EOF;
} else if( ferror(File) != 0 ) {
/* ERR: */
_error_mmio( "read_header: ferror() returns"
" error condition, '%s'\n", strerror(errno) );
return MMIO_ERR;
}
}
/* read from the header line: */
ptr = buf + 1;
nscan = sscanf( ptr, "%5d", natom );
if( nscan != 1 ) {
_error_mmio( "read_header: sscanf() fails, "
"src_line= %d; expected 1 field, got %d\n", __LINE__, nscan );
return MMIO_ERR;
}
if( title != NULL ) {
/* truncate string before NL char, if any: */
ptr = strchr( buf, '\n' );
if( ptr != NULL ) {
*ptr = '\0';
}
/* truncate trailing blanks: */
for( ptr=buf+strlen(buf)-1; *ptr==' '; --ptr ) {
*ptr = '\0';
}
ptr = buf + 8;
strcpy( title, ptr );
}
/* determine nature of CT, and adjust sign of natom, if necessary: */
if( *natom < 0 ) {
*natom = - *natom;
ct_type = MMIO_COMPRESSED;
} else {
ct_type = MMIO_FULL;
}
return ct_type;
}
/*******************************************************************/
static char *state_name( int state )
{
switch( state ) {
case UNUSED:
return "UNUSED";
case FILE_OPEN:
return "FILE_OPEN";
case CT_DONE:
return "CT_DONE";
case ATOMS_IN_PROGRESS:
return "ATOMS_IN_PROGRESS";
case ATOMS_DONE:
return "ATOMS_DONE";
default:
return "unknown read state";
}
}
/*******************************************************************/
static int seekto_ct( struct datasettag *datum, int ict_input )
/* fseek() to beginning of a previously read CT in read_file, return ct_type;
* if ict_input is <0, return BOF; if >Nct_read-1, return EOF; in these
* cases, position file ptr at beginning or end of file, respectively: */
{
int ict = ict_input;
int retcode;
/* bounds check on ict: */
if( ict_input < 0 ) {
ict = 0;
retcode = MMIO_BOF;
} else if( ict_input >= Nct_read ) {
ict = Nct_read - 1;
if( ict < 0 ) {
/* this will occur if no CT's have been successfully
* read; e.g., zero-length file: */
return MMIO_EOF;
}
retcode = MMIO_EOF;
}
/* if file-pointer is not positioned where we want it, fseek()
* to the desired position: */
if( ftell(File) != Ct_read[ict].offset ) {
if( fseek(File,Ct_read[ict].offset,SEEK_SET) != 0 ) {
_error_mmio(
"seekto_ct: fseek() fails, ict_input= %d, ict= %d, "
" '%s'\n", ict_input, ict, strerror(errno) );
return MMIO_ERR;
}
}
return ict==ict_input ? Ct_read[ ict ].ct_type : retcode;
}
/*******************************************************************/
static void dump_ct_read( struct datasettag *datum )
/* dump the contents of the ct_read structure to the errfile, for
* diagnostic purposes: */
{
int ict;
_error_mmio( "Beginning dump of ct_read{}[], dataset %d, File '%s',"
" Nct_read= %d\n", datum-dataset, Fname, Nct_read );
_error_mmio( "%10s %10s %10s %20s %10s\n",
"ict", "offset", "ict_full", "ct_type", "natom" );
for( ict=0; ictread->ct );
free( datum->read );
}
/* free structures common to READ and WRITE: */
if( datum->ct_comp != NULL ) {
if( datum->ct_comp->atom != NULL ) {
free( datum->ct_comp->atom );
}
free( datum->ct_comp );
}
if( datum->full_ct_comp != NULL ) {
if( datum->full_ct_comp->atom != NULL ) {
free( datum->full_ct_comp->atom );
}
free( datum->full_ct_comp );
}
if( datum->ct_conn != NULL ) {
if( datum->ct_conn->atom != NULL ) {
free( datum->ct_conn->atom );
}
free( datum->ct_conn );
}
free( datum->fname );
/* reset variables to NULL or equivalent values: */
datum->read = NULL;
datum->ct_conn = NULL;
datum->ct_comp = NULL;
datum->full_ct_comp = NULL;
datum->fname = NULL;
datum->ct_type_last = 0;
datum->mode = MMIO_UNUSED;
datum->state = UNUSED;
/* close the file: */
if( fclose(datum->file) == EOF ) {
_error_mmio(
"free_datum: fclose() fails, idataset= %d, fname=%s; '%s'\n",
datum-dataset, Fname, strerror(errno) );
return MMIO_ERR;
}
datum->file = NULL;
return MMIO_OK;
}
/*******************************************************************/
char *my_fgets( char *cache, char *buf, int nbuf, FILE *stream,
int reposition )
/* Enable push-back of a full-line of input, even when reading from a pipe.
* The line is actually stored in cache[]. If "reposition" is TRUE, then
* store it in cache[], so that it will be reread on the next call.
* Return diagnostics are as for fgets(): */
{
if( cache[0] == '\0' ) {
/* The cache is empty, so read the input file: */
if( reposition ) {
/* store line just read in cache[], for later
* re-reading; also copy to buf: */
if( fgets(cache,nbuf,stream) == NULL ) {
return NULL;
}
strcpy( buf, cache );
} else {
/* we won't need this line again; bypass cache[],
* so read directly into buf: */
if( fgets(buf,nbuf,stream) == NULL ) {
return NULL;
}
}
} else {
/* The cache is full, so read from it: */
if( reposition ) {
/* Copy from cache into buf, and keep cache for
* subsequent rereading: */
strcpy( buf, cache );
} else {
/* Copy from cache into buf, and destroy cache: */
strcpy( buf, cache );
cache[ 0 ] = '\0';
}
}
return buf;
}
/*******************************************************************/
#if defined( C_API )
void fline_mmio( int *errunit, char *buf, int *len ) { }
#endif
/*******************************************************************/
|