📄 rcio.c
字号:
InitOutPutInfo( &errinfo );
errinfo.severity = SEV_BANNER;
#ifdef __OSI__
if( _Copyright != NULL ) { /* 04-may-94 */
RcFprintf( stdout, &errinfo, "%s\n", _Copyright );
}
#endif
_splitpath( progpath, NULL, NULL, progfname, NULL );
strlwr( progfname );
GetRcMsg( USAGE_MSG_BASE, buf, sizeof( buf ) );
RcFprintf( stdout, &errinfo, buf, progfname );
RcFprintf( stdout, &errinfo, "\n" );
index = USAGE_MSG_BASE + 1;
for( ;; index++ ) {
GetRcMsg( index, buf, sizeof( buf ) );
if( buf[0] == '.' && buf[1] == '\0' ) break;
RcFprintf( stdout, &errinfo, "%s\n", buf );
}
}
/****** Text file input routines ******/
/* These routines maintain a stack of input files. Pushing a file onto the */
/* stack opens the file and sets up the buffer. Poping a file closes the file */
/* All other routines (except TextInputInit and TextInputShutdown) operate */
/* on the current file which is the one at the top of the stack */
#define MAX_INCLUDE_DEPTH 16
typedef struct PhysFileInfo {
char Filename[ _MAX_PATH ];
int IsOpen;
int Handle;
long Offset; /* offset in file to read from next time if this */
/* is not the current file */
} PhysFileInfo;
typedef struct FileStackEntry {
LogicalFileInfo Logical;
PhysFileInfo Physical;
} FileStackEntry;
typedef struct FileStack {
char * Buffer;
uint BufferSize;
char * NextChar;
char * EofChar; /* DON'T dereference, see below */
/* + 1 for the before first entry */
FileStackEntry Stack[ MAX_INCLUDE_DEPTH + 1 ];
FileStackEntry * Current;
} FileStack;
/* EofChar points to the memory location after the last character currently */
/* in the buffer. If the physical EOF has been reached it will point to */
/* within Buffer, otherwise it will point AFTER Buffer. If NextChar == */
/* EofChar then either EOF has been reached or it's time to read in more */
/* of the file */
#define IsEmptyFileStack( stack ) ((stack).Current == (stack).Stack)
FileStack InStack;
extern void RcIoTextInputInit( void )
/***********************************/
{
InStack.Buffer = RcMemMalloc( IO_BUFFER_SIZE );
InStack.BufferSize = IO_BUFFER_SIZE;
InStack.Current = InStack.Stack;
} /* RcIoTextInputInit */
extern int RcIoTextInputShutdown( void )
/**************************************/
{
if( InStack.Buffer != NULL ) {
RcMemFree( InStack.Buffer );
InStack.Buffer = NULL;
InStack.BufferSize = 0;
if( IsEmptyFileStack( InStack ) ) {
return( FALSE );
} else {
while( !IsEmptyFileStack( InStack ) ) {
RcIoPopInputFile();
}
// return( TRUE );
}
}
return( TRUE );
} /* RcIoTextInputShutdown */
static int OpenPhysicalFile( PhysFileInfo * phys )
/************************************************/
{
int seekrc;
if( !phys->IsOpen ) {
phys->Handle = RcIoOpenInput( phys->Filename, O_RDONLY | O_TEXT );
if( phys->Handle == -1 ) {
RcError( ERR_CANT_OPEN_FILE, phys->Filename, strerror( errno ) );
return( TRUE );
}
phys->IsOpen = TRUE;
seekrc = RcSeek( phys->Handle, phys->Offset, SEEK_SET );
if( seekrc == -1 ) {
RcError( ERR_READING_FILE, phys->Filename, strerror( errno ) );
return( TRUE );
}
}
return( FALSE );
} /* OpenPhysicalFile */
static int OpenNewPhysicalFile( PhysFileInfo * phys, char * filename )
/********************************************************************/
{
strncpy( phys->Filename, filename, _MAX_PATH );
phys->IsOpen = FALSE;
phys->Offset = 0;
return( OpenPhysicalFile( phys ) );
} /* OpenNewPhysicalFile */
static void SetPhysFileOffset( FileStack * stack )
/************************************************/
{
PhysFileInfo * phys;
uint_16 charsinbuff;
phys = &(stack->Current->Physical);
charsinbuff = stack->BufferSize - (stack->NextChar - stack->Buffer);
phys->Offset = RcTell( phys->Handle ) - charsinbuff;
} /* SetPhysFileOffset */
static int ReadBuffer( FileStack * stack )
/****************************************/
{
PhysFileInfo *phys;
int numread;
int error;
int inchar;
phys = &(stack->Current->Physical);
if( !phys->IsOpen ) {
error = OpenPhysicalFile( phys );
if( error ) return( TRUE );
}
if( CmdLineParms.NoPreprocess ) {
numread = RcRead( phys->Handle, stack->Buffer, stack->BufferSize );
} else {
for( numread = 0; numread < stack->BufferSize; numread++ ) {
inchar = PP_Char();
if( inchar == EOF ) {
break;
}
*( stack->Buffer + numread ) = (char)inchar;
}
}
stack->NextChar = stack->Buffer;
stack->EofChar = stack->Buffer + numread; /* may be past end of buffer */
return( FALSE );
} /* ReadBuffer */
extern int RcIoPushInputFile( char * filename )
/*********************************************/
{
int error;
if( InStack.Current == InStack.Stack + MAX_INCLUDE_DEPTH - 1 ) {
RcError( ERR_RCINCLUDE_TOO_DEEP, MAX_INCLUDE_DEPTH );
return( TRUE );
}
SetPhysFileOffset( &(InStack) );
InStack.Current++;
/* set up the logical file info */
RcIoSetLogicalFileInfo( 1, filename );
/* set up the physical file info */
error = OpenNewPhysicalFile( &(InStack.Current->Physical), filename );
if( error ) {
InStack.Current--;
} else {
error = ReadBuffer( &(InStack) );
}
return( error );
} /* RcIoPushInputFile */
static void ClosePhysicalFile( PhysFileInfo * phys )
/**************************************************/
{
if( phys->IsOpen ) {
RcClose( phys->Handle );
phys->IsOpen = FALSE;
}
} /* ClosePhysicalFile */
extern int RcIoPopInputFile( void )
/*********************************/
{
PhysFileInfo * phys;
phys = &(InStack.Current->Physical);
ClosePhysicalFile( phys );
InStack.Current--;
if( IsEmptyFileStack( InStack ) ) {
return( TRUE );
} else {
ReadBuffer( &(InStack) );
return( FALSE );
}
} /* RcIoPopInputFile */
static int GetLogChar( FileStack * stack )
/****************************************/
{
int newchar;
newchar = *(stack->NextChar);
if( newchar == '\n' ) {
stack->Current->Logical.LineNum++;
}
stack->NextChar++;
return( newchar );
} /* GetLogChar */
extern int RcIoGetChar( void )
/****************************/
{
int isempty;
int error;
if( IsEmptyFileStack( InStack ) ) {
return( RC_EOF );
}
if( InStack.NextChar >= InStack.EofChar ) {
/* if this is a real EOF */
if( InStack.NextChar < InStack.Buffer + InStack.BufferSize ) {
/* unstack one file */
isempty = RcIoPopInputFile();
if( isempty ) {
return( RC_EOF );
} else {
/* if we are still at the EOF char, there has been an error */
if( InStack.NextChar >= InStack.EofChar ) {
/* this error is reported in ReadBuffer so just terminate */
RcFatalError( ERR_NO_MSG );
} else {
/* return \n which will end the current token properly */
/* if it it is not a string and end it with a runaway */
/* string error for strings */
return( '\n' );
}
}
} else {
/* otherwise we have reached the end of the buffer */
error = ReadBuffer( &(InStack) );
if( error ) {
/* this error is reported in ReadBuffer so just terminate */
RcFatalError( ERR_NO_MSG );
}
}
}
return( GetLogChar( &InStack ) );
} /* RcIoGetChar */
extern const LogicalFileInfo * RcIoGetLogicalFileInfo( void )
/***********************************************************/
{
if( IsEmptyFileStack( InStack ) ) {
return( NULL );
} else {
return( &(InStack.Current->Logical) );
}
} /* RcIoGetLogicalFileInfo */
extern void RcIoOverrideIsCOrHFlag( void )
/****************************************/
{
LogicalFileInfo * log;
if( !IsEmptyFileStack( InStack ) ) {
log = &(InStack.Current->Logical);
log->IsCOrHFile = FALSE;
}
} /* RcIoOverrideIsCOrHFlag */
extern void RcIoSetIsCOrHFlag( void )
/***********************************/
{
LogicalFileInfo * log;
char ext[ _MAX_EXT ];
if( !IsEmptyFileStack( InStack ) ) {
log = &(InStack.Current->Logical);
_splitpath( log->Filename, NULL, NULL, NULL, ext );
/* if this is a c or h file ext will be '.', '[ch]', '\0' */
if( (ext[1] == 'c' || ext[1] == 'h' || ext[1] == 'C'
|| ext[1] == 'H' ) && ext[2] == '\0' ) {
/* if the logical file is a c or h file */
log->IsCOrHFile = TRUE;
} else {
log->IsCOrHFile = FALSE;
}
}
} /* RcIoSetIsCOrHFlag */
extern void RcIoSetLogicalFileInfo( int linenum, char * filename )
/****************************************************************/
{
LogicalFileInfo * log;
if( !IsEmptyFileStack( InStack ) ) {
log = &(InStack.Current->Logical);
log->LineNum = linenum;
if( filename != NULL ) {
strncpy( log->Filename, filename, _MAX_PATH );
RcIoSetIsCOrHFlag();
}
}
} /* RcIoSetLogicalFileInfo */
extern int RcIoIsCOrHFile( void )
/*******************************/
/* returns true if the current file is a .c or .h file, false otherwise */
{
if( IsEmptyFileStack( InStack ) ) {
return( FALSE );
} else {
return( InStack.Current->Logical.IsCOrHFile );
}
} /* RcIoIsCOrHFile */
/*
* RcIoOpenInput
* NB when an error occurs this function MUST return without altering errno
*/
extern int RcIoOpenInput( char * filename, int flags, ... )
/********************************************************/
{
int handle;
int perms;
va_list args;
FileStackEntry * currfile;
if( flags & O_CREAT ) {
va_start( args, flags );
perms = va_arg( args, int );
va_end( args );
} else {
perms = 0;
}
handle = RcOpen( filename, flags, perms );
if( handle == -1 && errno == EMFILE ) {
/* set currfile to be the first (not before first) entry */
currfile = InStack.Stack + 1;
/* close open files except the current input file until able to open */
/* don't close the current file because Offset isn't set */
while( currfile < InStack.Current && handle == -1 && errno == EMFILE ) {
if( currfile->Physical.IsOpen ) {
ClosePhysicalFile( &(currfile->Physical) );
handle = RcOpen( filename, flags, perms );
}
currfile++;
}
}
return( handle );
} /* RcIoOpenInput */
extern void RcIoInitStatics( void )
/*********************************/
{
memset( &InStack, 0, sizeof( FileStack ) );
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -