#include "niml_private.h"
#undef SKIP_COMMENT_FLAG
#define SKIP_COMMENT_FLAG 1
static char * my_fgets( char *, int, FILE *, int ) ;
/*---------------------------------------------------------------*/
/*! Read an un-headered file into a data element, guessing at
its structure from the 1st non-comment line.
-----------------------------------------------------------------*/
NI_element * NI_read_file_nohead( char *fname )
{
FILE *fp ;
char prefix[32] , *ptr ;
NI_element *nel ;
if( fname == NULL || *fname == '\0' ) return NULL ;
fp = fopen( fname , "r" ) ; if( fp == NULL ) return NULL ;
/** see if this looks like a NIML-formatted file **/
memset(prefix,0,32) ; fread(prefix,1,31,fp) ; rewind(fp) ;
ptr = strchr(prefix,'<') ;
if( ptr != NULL && isalpha(*(ptr+1)) ){
NI_stream ns ;
fclose(fp) ;
ptr = NI_malloc(char, strlen(fname)+16) ;
sprintf(ptr,"file:%s",fname) ;
ns = NI_stream_open(ptr,"r") ; NI_free(ptr) ;
if( ns == NULL ) return NULL ;
nel = NI_read_element( ns , 66 ) ;
NI_stream_close(ns) ;
return nel ;
}
}
/*---------------------------------------------------------------*/
/*! Length of line buffer */
#define LBUF 65536
/*---------------------------------------------------------------*/
/*! Like fgets, but also
- skips blank lines
- skips comment lines (if flags&SKIP_COMMENT_FLAG)
- skips leading and trailing whitespace
- catenates lines that end in '\' (replacing '\' with ' ')
-----------------------------------------------------------------*/
static char * my_fgets( char *buf, int size, FILE *fts, int flags )
{
char *ptr ;
int nbuf , ll,ii , cflag ;
static char *qbuf=NULL ;
int skip_comm = (flags & SKIP_COMMENT_FLAG) != 0 ;
if( buf == NULL || size < 1 || fts == NULL ){
NI_free(qbuf); qbuf = NULL; return NULL;
}
if( qbuf == NULL ) qbuf = NI_malloc(char, LBUF) ; /* 1st time in */
nbuf = 0 ; /* num bytes stored in buf so far */
cflag = 0 ; /* flag if we're catenating lines */
while(1){ /* loop and read lines, creating a logical line */
ptr = fgets( qbuf , LBUF , fts ) ; /* read next whole line */
if( ptr == NULL ) break ; /* must be end-of-file */
/* skip leading whitespace */
for( ; *ptr != '\0' && isspace(*ptr) ; ptr++ ) ; /* nada */
/* skip entirely blank lines, unless we are catenating */
if( *ptr == '\0' ){ if(cflag) break; else continue; }
/* skip comment lines (even if we are catenating) */
if( skip_comm &&
(*ptr == '#' || (*ptr == '/' && *(ptr+1) == '/')) ) continue ;
/* strip trailing whitespace */
ll = strlen(ptr) ; /* will be > 0 */
for( ii=ll-1 ; isspace(ptr[ii]) && ii > 0 ; ii-- ) /* blank => NUL */
ptr[ii] = '\0' ;
ll = strlen(ptr) ; /* number of chars left */
if( ll == 0 ) continue ; /* should not happen */
cflag = (ptr[ll-1] == '\\') ; /* catenate next line? */
if( cflag && ll > 1 && ptr[ll-2] == '\\' ) cflag = 0 ;
if( cflag ) ptr[ll-1] = ' ' ; /* replace '\' with ' ' */
/* now copy what's left (ll+1 bytes) at tail of output buffer */
if( nbuf+ll+1 > size ){ /* too much for output buffer? */
ll = size - (nbuf+1) ;
if( ll <= 0 ) break ; /* should not happen */
}
memcpy(buf+nbuf,ptr,ll+1) ; nbuf += ll ;
if( !cflag ) break ;
} /* loop to get next line if catenation is turned on */
/* and we is done */
if( nbuf > 0 ) return buf ; /* return what we read already */
return NULL ; /* signal of failure get data */
}
syntax highlighted by Code2HTML, v. 0.9.1