ftp.nice.ch/pub/next/text/framemaker/fmbib.1.3.s.tar.gz#/mifread.c

This is mifread.c in view mode; [Download] [Up]

/* mifread.c
 * cm, 17 Dec 90
 *
 * HISTORY
 *  28 May 92, neek: Added support for include swapping the current
 *				     IOstream w/ a temporary one, for @include functionality.
 * 
 *
 * read/parse FrameMaker files
 * external entry points:
 *	mif_open():  open the file to filter, validate file type.
 *	mif_gets():  returns the next line (Null replaces newline) from file.
 *	mif_getc():  returns the next byte from file.
 *	mif_ungetc(): place previously read char back on input stream.
 * 	mif_close():  close specified file.
 * 	mif_lineno(): returns value of the current line number in input stream. 
 */

/*
 * Copyright (c) 1991 Carnegie Mellon University
 * All Rights Reserved.
 * 
 * Permission to use, copy, modify and distribute this software and its
 * documentation is hereby granted, provided that both the copyright
 * notice and this permission notice appear in all copies of the
 * software, derivative works or modified versions, and any portions
 * thereof, and that both notices appear in supporting documentation.
 *
 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
 * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
 *
 * Carnegie Mellon requests users of this software to return to
 *
 *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
 *  School of Computer Science
 *  Carnegie Mellon University
 *  Pittsburgh PA 15213-3890
 *
 * any improvements or extensions that they make and grant Carnegie Mellon
 * the rights to redistribute these changes.
 */

#include <stdio.h>
#include <errno.h>
#include <sys/file.h>
#include <mif.h>

#define BLKSIZE (1024*4)
#define MAX_TMP_STREAMS	12

typedef struct 
{
	char	rbuf[BLKSIZE];	/* read buffer  */
	char	fname[256];	/* file name */
	char	*rp;		/* current point in read buffer */
	char	*erp;		/* current end of read buffer */
	int	rfd;		/* read file descriptor */
	int	lineno;		/* current line no. of file */
	char	eof;		/* true if end of stream hit */
} IOstream;

static IOstream	streams[4];	/* mif, bib, ref, tmp files */
static IOstream streamstack[MAX_TMP_STREAMS];
int stacktop;


/* open input file for processing (.mif file )
 * return 1 on success, 0 on failure.
 */
mif_open( type, fname )
	register char *fname;
{
	register IOstream	*sp;

	sp = &streams[type];
	
	if( (sp->rfd = open( fname, O_RDONLY)) < 0 )
	{
		err( WARN, "Can't open <%s>, errno=%d\n", 
			fname, errno );
		return(0);
	}
	sp->lineno = 1;
	sp->eof = 0;
	strcpy( sp->fname, fname );
	return(1);
}


/* close the current .mif input file 
 */
mif_close(type)
{
	IOstream *sp;

	sp = &streams[type];
	close(sp->rfd);
}


/* push the current IOstream onto a stack */
mif_push_readcontext(type)
{
	if( stacktop == MAX_TMP_STREAMS )
		return(0);
	copy_streams(&streamstack[stacktop], &streams[type]);
	stacktop++;
	return(1);
}

/* pop the next IOstream from the stack */
mif_pop_readcontext(type)
{
	if( stacktop == 0 )
		return(0);
	stacktop--;
	copy_streams(&streams[type], &streamstack[stacktop]);
	return(1);
}

static
copy_streams( dp, sp )
	register IOstream *dp;	/* destination */
	register IOstream *sp;	/* source */
{
	bcopy( sp->rbuf, dp->rbuf, BLKSIZE );
	strcpy( dp->fname, sp->fname );
	dp->rp = sp->rp;
	dp->erp = sp->erp;
	dp->rfd = sp->rfd;
	dp->lineno = sp->lineno;
	dp->eof = sp->eof;
}


/* read next line from mif file buffer.
 * if necessary, read from file. Return pointer to
 * next line, or NULL if at end of file.
 */
char *
mif_gets(type, dest)
	register char *dest;
{
	char *retp;
	int	n;
	register IOstream *sp; 

	sp = &streams[type];

	if( sp->eof ) return( (char *)0);

	if( sp->rp >= sp->erp )
	{
		n=mif_readbuf(sp);
		if( n == 0 )	 /* eof */
		{
			sp->eof = 1;
			return( (char *) 0 );
		}
	}
	retp = sp->rp;
	sp->rp += strlen( sp->rp ) + 1;
	sp->lineno++;
	strcpy( dest, retp );
	return( retp );		
}


/* pass pointer to the next char in input stream.
 * read in another buffer if necessary.
 * return NULL if at end of file.
 */
char *
mif_getc(type)
{
	char *retp;
	int	n;
	register IOstream *sp; 

	sp = &streams[type];
	if( sp->eof ) return( (char *)0);

	if( sp->rp >= sp->erp )
	{
		n=mif_readbuf(sp);
		if( n == 0 )	 /* eof */
		{
			sp->eof = 1;
			return( (char *) 0 );
		}
	}
	retp = sp->rp;
	if( *retp == 0 )
		sp->lineno++;
	sp->rp++;
	return( retp );		
}

/* decrement input stream pointer */
mif_ungetc(type)
{
	register IOstream *sp; 

	sp = &streams[type];
	sp->rp--;
	if( *(sp->rp) == 0 )
		sp->lineno--;
}

/* read into read buffer at specified location, as much as
 * will fill the input buffer.  Assure we've ended on an
 * even newline, to ease the parsing.  Replace all newlines
 * w/ 0.
 */
static int
mif_readbuf(sp)
	register IOstream *sp;
{
	register dec;	
	register char *cp;
	int n;

	if((n=read( sp->rfd, sp->rbuf, BLKSIZE )) < 0 )
		err( FATAL, "Fatal read on .mif file,  errno=%d\n",
			errno );

	/* bailout if eof */
	if( n == 0 )
		return( 0 );

	sp->rp = sp->rbuf;
	sp->erp = sp->rp+n;

	/* assure read ends on even newline 
	 */
	for( cp = sp->erp-1; (cp>sp->rbuf) && (*cp != '\n'); cp-- )
		; if ( dec = cp - sp->erp + 1 ) { sp->erp += dec;
		if( lseek( sp->rfd, dec, L_INCR ) < 0 )
			err( FATAL, "lseek failed on mif file, errno=%d\n",
				errno );
		
	}	

	/* change newlines to nulls for easy string retrieval 
	 */
	for(cp=sp->rbuf; cp<sp->erp; cp++)
		if( *cp == '\n' ) 
			*cp=0;

	return(sp->erp - sp->rbuf);
}


mif_lineno(type)
{
	register IOstream *sp; 

	sp = &streams[type];
	return( sp->lineno );
}


char *
mif_filename(type)
{
	register IOstream *sp; 

	sp = &streams[type];
	return( sp->fname );
}

These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.