mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1241 lines
23 KiB
1241 lines
23 KiB
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
Copyright (c) 1989 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
stream.cxx
|
|
|
|
Abstract:
|
|
|
|
transparent stream implementation on memory or file.
|
|
|
|
Notes:
|
|
|
|
We may use better streams later. This is just to get me going.
|
|
|
|
Author:
|
|
|
|
VibhasC
|
|
|
|
History:
|
|
|
|
VibhasC Aug-04-1993 Created.
|
|
|
|
----------------------------------------------------------------------------*/
|
|
|
|
/****************************************************************************
|
|
* include files
|
|
***************************************************************************/
|
|
|
|
#include "nulldefs.h"
|
|
extern "C"
|
|
{
|
|
#include <stdio.h>
|
|
#include <assert.h>
|
|
#include <string.h>
|
|
#include <share.h>
|
|
#include <memory.h>
|
|
#include <io.h>
|
|
}
|
|
|
|
#include "stream.hxx"
|
|
#include "errors.hxx"
|
|
|
|
|
|
STREAM::~STREAM()
|
|
{
|
|
Close();
|
|
}
|
|
|
|
STREAM::STREAM(
|
|
IN char * pFileName,
|
|
IN unsigned char SProt )
|
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Routine Description:
|
|
|
|
A Constructor.
|
|
|
|
Arguments:
|
|
|
|
pFileName - name of the file to open the stream to.
|
|
|
|
Return Value:
|
|
|
|
NA
|
|
|
|
Notes:
|
|
|
|
If this is a null filename, we want to write to a null stream.
|
|
|
|
----------------------------------------------------------------------------*/
|
|
{
|
|
|
|
ResetConsoleStream();
|
|
pSpecialCommentString = NULL;
|
|
|
|
// no alternate file to begin with
|
|
StreamOpenStatus = FILE_STATUS_OK;
|
|
|
|
if( !pFileName )
|
|
{
|
|
SetStreamType( STREAM_NULL );
|
|
ResetError();
|
|
ResetEnd();
|
|
return;
|
|
}
|
|
else if( *(pFileName+2) == '-' )
|
|
{
|
|
S.F.pHandle = stdout;
|
|
SetConsoleStream();
|
|
}
|
|
else // named file stream
|
|
{
|
|
// if this is a not a file to overwrite, and it exists, don't overwrite it
|
|
// substitute a temp file instead
|
|
if ( (SProt != FILE_STREAM_OVERWRITE) &&
|
|
!_access( pFileName, 0 ) )
|
|
{
|
|
if ( SProt == FILE_STREAM_REWRITE )
|
|
{
|
|
// note that tmpfile is opened w+b
|
|
S.F.pHandle = tmpfile();
|
|
StreamOpenStatus = FILE_STATUS_TEMP;
|
|
}
|
|
else // write-once file already exists, do nothing
|
|
{
|
|
S.F.pHandle = NULL;
|
|
StreamOpenStatus = FILE_STATUS_NO_WRITE;
|
|
SetStreamType( STREAM_NULL );
|
|
ResetError();
|
|
ResetEnd();
|
|
return;
|
|
}
|
|
}
|
|
else // overwritable file...
|
|
{
|
|
S.F.pHandle = _fsopen( pFileName, "wt", SH_DENYWR);
|
|
}
|
|
|
|
if ( S.F.pHandle )
|
|
{
|
|
setvbuf( S.F.pHandle, NULL, _IOFBF, 32768 );
|
|
}
|
|
}
|
|
|
|
if( S.F.pHandle == (FILE *)0 )
|
|
{
|
|
RpcError( (char *)NULL,
|
|
0,
|
|
ERROR_WRITING_FILE,
|
|
pFileName );
|
|
|
|
exit( ERROR_WRITING_FILE );
|
|
}
|
|
else
|
|
{
|
|
SetStreamType( STREAM_FILE );
|
|
ResetError();
|
|
ResetEnd();
|
|
}
|
|
}
|
|
|
|
STREAM::STREAM(
|
|
IN FILE * pFile )
|
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Routine Description:
|
|
|
|
Another constructor.
|
|
|
|
Arguments:
|
|
|
|
pFile - a pointer to an already open file handle.
|
|
|
|
Return Value:
|
|
|
|
NA
|
|
|
|
Notes:
|
|
|
|
----------------------------------------------------------------------------*/
|
|
{
|
|
S.F.pHandle = pFile;
|
|
ResetError();
|
|
ResetEnd();
|
|
pSpecialCommentString = NULL;
|
|
|
|
// no alternate file to begin with
|
|
StreamOpenStatus = FILE_STATUS_OK;
|
|
}
|
|
|
|
STREAM::STREAM()
|
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Routine Description:
|
|
|
|
Memory stream constructor.
|
|
|
|
Arguments:
|
|
|
|
None.
|
|
|
|
Return Value:
|
|
|
|
Notes:
|
|
|
|
Create the stream with a default memory buffer.
|
|
----------------------------------------------------------------------------*/
|
|
{
|
|
SetStreamType( STREAM_MEMORY );
|
|
ResetEnd();
|
|
ResetError();
|
|
StreamOpenStatus = FILE_STATUS_OK;
|
|
|
|
SetCurrentPtr( new char[ SetInitialSize( DEFAULT_MEM_SIZE_FOR_STREAM ) ] );
|
|
SetInitialIncr( DEFAULT_MEM_INCR_FOR_STREAM );
|
|
SetStart( GetCurrentPtr() );
|
|
SetMemStreamEnd( GetCurrentPtr() + GetInitialSize() );
|
|
}
|
|
|
|
STREAM::STREAM(
|
|
int InitialSize,
|
|
int InitialIncr )
|
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Routine Description:
|
|
|
|
Memory stream constructor.
|
|
|
|
Arguments:
|
|
|
|
DefaultSize - The start size.
|
|
DefaultIncr - The initial increment.
|
|
|
|
Return Value:
|
|
|
|
Notes:
|
|
|
|
Create the stream with a default memory buffer.
|
|
----------------------------------------------------------------------------*/
|
|
{
|
|
SetStreamType( STREAM_MEMORY );
|
|
ResetEnd();
|
|
ResetError();
|
|
StreamOpenStatus = FILE_STATUS_OK;
|
|
|
|
SetCurrentPtr( new char[ SetInitialSize( InitialSize ) ] );
|
|
SetInitialIncr( InitialIncr );
|
|
SetStart( GetCurrentPtr() );
|
|
SetMemStreamEnd( GetCurrentPtr() + GetInitialSize() );
|
|
}
|
|
|
|
#if 0
|
|
|
|
void
|
|
STREAM::Write(
|
|
IN char C )
|
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Write this character to the file.
|
|
|
|
|
|
Arguments:
|
|
|
|
C - The character to be written.
|
|
|
|
|
|
Return Value:
|
|
|
|
Notes:
|
|
|
|
----------------------------------------------------------------------------*/
|
|
{
|
|
if( (GetStreamType() == STREAM_FILE ) && !IsError() )
|
|
putc( C, S.F.pHandle );
|
|
else
|
|
{
|
|
if( S.M.pCurrent >= S.M.pEnd )
|
|
{
|
|
Expand();
|
|
}
|
|
*(S.M.pCurrent)++ = C;
|
|
}
|
|
}
|
|
#endif // 0
|
|
|
|
void
|
|
STREAM::Write(
|
|
IN const char * const pString )
|
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Routine Description:
|
|
|
|
put a string out to the file.
|
|
|
|
Arguments:
|
|
|
|
pString - The string to be output.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
Notes:
|
|
|
|
----------------------------------------------------------------------------*/
|
|
{
|
|
if ( ( GetStreamType() == STREAM_NULL ) || IsError())
|
|
return;
|
|
|
|
if( (GetStreamType() == STREAM_FILE ) )
|
|
{
|
|
fputs( pString, S.F.pHandle );
|
|
if( IsConsoleStream() )
|
|
fflush( S.F.pHandle );
|
|
}
|
|
else
|
|
{
|
|
short Len = strlen( pString );
|
|
|
|
if( (GetCurrentPtr() + Len) >= S.M.pEnd )
|
|
{
|
|
ExpandBy( Len + GetInitialIncr() );
|
|
}
|
|
memcpy( GetCurrentPtr(), pString, Len );
|
|
SetCurrentPtr( GetCurrentPtr() + Len );
|
|
}
|
|
}
|
|
|
|
void
|
|
STREAM::WriteNumber(
|
|
IN const char * pFmt,
|
|
IN const unsigned long ul )
|
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Routine Description:
|
|
|
|
put a number out to the file.
|
|
|
|
Arguments:
|
|
|
|
pFmt - printf style format for the number.
|
|
ul - the number to print.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
Notes:
|
|
|
|
----------------------------------------------------------------------------*/
|
|
{
|
|
char buffer[128];
|
|
|
|
if ( ( GetStreamType() == STREAM_NULL ) || IsError())
|
|
return;
|
|
|
|
if( (GetStreamType() == STREAM_FILE ) )
|
|
{
|
|
fprintf( S.F.pHandle, pFmt, ul );
|
|
if( IsConsoleStream() )
|
|
fflush( S.F.pHandle );
|
|
}
|
|
else
|
|
{
|
|
sprintf( buffer, pFmt, ul );
|
|
|
|
short Len = strlen( buffer );
|
|
|
|
if( (GetCurrentPtr() + Len) >= S.M.pEnd )
|
|
{
|
|
ExpandBy( Len + GetInitialIncr() );
|
|
}
|
|
memcpy( GetCurrentPtr(), buffer, Len );
|
|
SetCurrentPtr( GetCurrentPtr() + Len );
|
|
}
|
|
}
|
|
|
|
void
|
|
STREAM::Flush()
|
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Routine Description:
|
|
|
|
Flush the stream.
|
|
|
|
Arguments:
|
|
|
|
None.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
Notes:
|
|
|
|
In case of the file stream, flush the file.
|
|
|
|
----------------------------------------------------------------------------*/
|
|
{
|
|
|
|
if( (GetStreamType() == STREAM_FILE ) && !IsError() )
|
|
if( IsConsoleStream() )
|
|
fflush( S.F.pHandle );
|
|
}
|
|
|
|
void
|
|
STREAM::Close()
|
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Routine Description:
|
|
|
|
Close the stream.
|
|
|
|
|
|
Arguments:
|
|
|
|
None.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
Notes:
|
|
|
|
----------------------------------------------------------------------------*/
|
|
{
|
|
if( (GetStreamType() == STREAM_FILE ) )
|
|
fclose( S.F.pHandle );
|
|
}
|
|
|
|
int
|
|
STREAM::SetInitialSize(
|
|
int InitialSize )
|
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Routine Description:
|
|
|
|
Set the initial size of memory stream.
|
|
|
|
Arguments:
|
|
|
|
InitialSize - Initial size.
|
|
|
|
Return Value:
|
|
|
|
Notes:
|
|
|
|
----------------------------------------------------------------------------*/
|
|
{
|
|
if( GetStreamType() == STREAM_MEMORY )
|
|
return (S.M.InitialSize = InitialSize);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
STREAM::GetInitialSize()
|
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Routine Description:
|
|
|
|
Set the initial size of memory stream.
|
|
|
|
Arguments:
|
|
|
|
None.
|
|
|
|
Return Value:
|
|
|
|
Notes:
|
|
|
|
----------------------------------------------------------------------------*/
|
|
{
|
|
if( GetStreamType() == STREAM_MEMORY )
|
|
return S.M.InitialSize;
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
STREAM::SetInitialIncr(
|
|
int InitialIncr )
|
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Routine Description:
|
|
|
|
Set the initial increment of memory stream.
|
|
|
|
Arguments:
|
|
|
|
InitialIncr - Initial Incr.
|
|
|
|
Return Value:
|
|
|
|
Notes:
|
|
|
|
----------------------------------------------------------------------------*/
|
|
{
|
|
if( GetStreamType() == STREAM_MEMORY )
|
|
return (S.M.Increment = InitialIncr);
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
STREAM::GetInitialIncr()
|
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Routine Description:
|
|
|
|
Set the initial increment of memory stream.
|
|
|
|
Arguments:
|
|
|
|
None.
|
|
|
|
Return Value:
|
|
|
|
Notes:
|
|
|
|
----------------------------------------------------------------------------*/
|
|
{
|
|
if( GetStreamType() == STREAM_MEMORY )
|
|
return S.M.Increment;
|
|
|
|
return 0;
|
|
}
|
|
|
|
char *
|
|
STREAM::Expand()
|
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Routine Description:
|
|
|
|
Expand the memory buffer.
|
|
|
|
Arguments:
|
|
|
|
None.
|
|
|
|
Return Value:
|
|
|
|
Notes:
|
|
|
|
Expansion will occur with the current increment.
|
|
----------------------------------------------------------------------------*/
|
|
{
|
|
if( GetStreamType() == STREAM_MEMORY )
|
|
{
|
|
int Len = GetInitialSize();
|
|
char * pTemp = GetStart();
|
|
|
|
SetStart( new char[ SetInitialSize( Len + GetInitialIncr() ) ] );
|
|
|
|
memcpy( GetStart(), pTemp, Len );
|
|
SetCurrentPtr( GetStart() + Len );
|
|
delete pTemp;
|
|
return GetCurrentPtr();
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
char *
|
|
STREAM::ExpandBy( short Amt)
|
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Routine Description:
|
|
|
|
Expand the memory buffer.
|
|
|
|
Arguments:
|
|
|
|
Amt = the amount to expand by.
|
|
|
|
Return Value:
|
|
|
|
Notes:
|
|
|
|
Expansion will occur with the current increment.
|
|
----------------------------------------------------------------------------*/
|
|
{
|
|
if( GetStreamType() == STREAM_MEMORY )
|
|
{
|
|
int Len = GetInitialSize();
|
|
char * pTemp = GetStart();
|
|
|
|
SetStart( new char[ SetInitialSize( Len + GetInitialIncr() + Amt ) ] );
|
|
|
|
memcpy( GetStart(), pTemp, Len );
|
|
SetCurrentPtr( GetStart() + Len );
|
|
delete pTemp;
|
|
return GetCurrentPtr();
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
char *
|
|
STREAM::NewCopy()
|
|
{
|
|
if( GetStreamType() == STREAM_MEMORY )
|
|
{
|
|
int Len = S.M.pCurrent - S.M.pMem + 1;
|
|
char * p = new char[ Len ];
|
|
memcpy( p, S.M.pMem, Len );
|
|
return p;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
char *
|
|
STREAM::SetCurrentPtr(
|
|
char * pCur)
|
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Routine Description:
|
|
|
|
Set the current memory pointer.
|
|
|
|
Arguments:
|
|
|
|
pCur - The current pointer.
|
|
|
|
Return Value:
|
|
|
|
Notes:
|
|
|
|
----------------------------------------------------------------------------*/
|
|
{
|
|
if( GetStreamType() == STREAM_MEMORY )
|
|
return (S.M.pCurrent = pCur);
|
|
return 0;
|
|
}
|
|
|
|
char *
|
|
STREAM::GetCurrentPtr()
|
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Routine Description:
|
|
|
|
Set the initial increment of memory stream.
|
|
|
|
Arguments:
|
|
|
|
None.
|
|
|
|
Return Value:
|
|
|
|
Notes:
|
|
|
|
----------------------------------------------------------------------------*/
|
|
{
|
|
if( GetStreamType() == STREAM_MEMORY )
|
|
return S.M.pCurrent;
|
|
return 0;
|
|
}
|
|
|
|
long
|
|
STREAM::GetCurrentPosition()
|
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Routine Description:
|
|
|
|
Get the current position of the file stream.
|
|
|
|
Arguments:
|
|
|
|
Return Value:
|
|
|
|
Position from the beginning of the file.
|
|
|
|
----------------------------------------------------------------------------*/
|
|
{
|
|
if( GetStreamType() == STREAM_FILE )
|
|
return ftell( S.F.pHandle );
|
|
return 0;
|
|
}
|
|
|
|
void
|
|
STREAM::SetCurrentPosition( long Position)
|
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Routine Description:
|
|
|
|
Set the current position of the file stream.
|
|
The new position is relative to the beginning of the file.
|
|
|
|
Arguments:
|
|
|
|
None.
|
|
|
|
Return Value:
|
|
|
|
----------------------------------------------------------------------------*/
|
|
{
|
|
if( GetStreamType() == STREAM_FILE )
|
|
fseek( S.F.pHandle, Position, SEEK_SET );
|
|
return;
|
|
}
|
|
|
|
|
|
char *
|
|
STREAM::SetStart(
|
|
char * pStart)
|
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Routine Description:
|
|
|
|
Set the start of the memory buffer.
|
|
|
|
Arguments:
|
|
|
|
pStart - the start.
|
|
|
|
Return Value:
|
|
|
|
Notes:
|
|
|
|
----------------------------------------------------------------------------*/
|
|
{
|
|
if( GetStreamType() == STREAM_MEMORY )
|
|
return (S.M.pMem = pStart);
|
|
return 0;
|
|
}
|
|
|
|
char *
|
|
STREAM::GetStart()
|
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Routine Description:
|
|
|
|
Get the start of the memory block.
|
|
|
|
Arguments:
|
|
|
|
None.
|
|
|
|
Return Value:
|
|
|
|
Notes:
|
|
|
|
----------------------------------------------------------------------------*/
|
|
{
|
|
if( GetStreamType() == STREAM_MEMORY )
|
|
return S.M.pMem;
|
|
return 0;
|
|
}
|
|
|
|
/****************************************************************************
|
|
ISTREAM functions
|
|
****************************************************************************/
|
|
|
|
#define MAX_INDENT (sizeof(SpaceBuffer) - 1)
|
|
|
|
static
|
|
char SpaceBuffer[] = " "
|
|
" "
|
|
" "
|
|
" ";
|
|
|
|
#define MAX_NEWLINES (sizeof(NewLineBuffer) - 1)
|
|
|
|
static
|
|
char NewLineBuffer[] = "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n";
|
|
|
|
|
|
void
|
|
ISTREAM::NewLine()
|
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Routine Description:
|
|
|
|
Writes a new line to the stream.
|
|
|
|
Arguments:
|
|
|
|
None.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
Notes:
|
|
|
|
Write out a new line and prepare for the next line to be at the correct
|
|
indent.
|
|
|
|
The indentation correction stuff should be the responsibility of the
|
|
method that creates a new line.
|
|
----------------------------------------------------------------------------*/
|
|
{
|
|
unsigned short usIndent = CurrentIndent;
|
|
|
|
if (usIndent > MAX_INDENT )
|
|
{
|
|
usIndent = MAX_INDENT;
|
|
};
|
|
|
|
Write('\n');
|
|
|
|
SpaceBuffer[usIndent] = '\0';
|
|
Write( (char *) SpaceBuffer);
|
|
|
|
SpaceBuffer[usIndent] = ' ';
|
|
}
|
|
|
|
void
|
|
ISTREAM::NewLine( unsigned short count )
|
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Routine Description:
|
|
|
|
Writes a bunch of new lines to the stream.
|
|
|
|
Arguments:
|
|
|
|
None.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
Notes:
|
|
|
|
Write out a bunch of new lines and prepare for the next line to be at the correct
|
|
indent.
|
|
|
|
The indentation correction stuff should be the responsibility of the
|
|
method that creates a new line.
|
|
----------------------------------------------------------------------------*/
|
|
{
|
|
unsigned short usIndent = CurrentIndent;
|
|
|
|
if (usIndent > MAX_INDENT )
|
|
{
|
|
usIndent = MAX_INDENT;
|
|
};
|
|
|
|
if ( count > MAX_NEWLINES )
|
|
{
|
|
count = MAX_NEWLINES;
|
|
};
|
|
|
|
NewLineBuffer[ count ] = '\0';
|
|
Write( (char *) NewLineBuffer);
|
|
NewLineBuffer[ count ] = '\n';
|
|
|
|
SpaceBuffer[usIndent] = '\0';
|
|
Write( (char *) SpaceBuffer);
|
|
|
|
SpaceBuffer[usIndent] = ' ';
|
|
}
|
|
|
|
|
|
void
|
|
ISTREAM::Spaces(
|
|
unsigned short NoOfSpaces )
|
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Routine Description:
|
|
|
|
Write out the given number of spaces to the stream.
|
|
|
|
Arguments:
|
|
|
|
NoOfSpaces - the number of spaces.
|
|
|
|
Return Value:
|
|
|
|
Notes:
|
|
|
|
----------------------------------------------------------------------------*/
|
|
{
|
|
if (NoOfSpaces > MAX_INDENT )
|
|
{
|
|
NoOfSpaces = MAX_INDENT;
|
|
};
|
|
|
|
SpaceBuffer[NoOfSpaces] = '\0';
|
|
Write( (char *) SpaceBuffer);
|
|
|
|
SpaceBuffer[NoOfSpaces] = ' ';
|
|
}
|
|
|
|
|
|
void
|
|
RW_ISTREAM::OpenOriginalFileForRead( char * pFileName )
|
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Routine Description:
|
|
|
|
Prepare to read from the original file.
|
|
|
|
Arguments:
|
|
|
|
pFileName - the original file name
|
|
|
|
Return Value:
|
|
|
|
Notes:
|
|
|
|
----------------------------------------------------------------------------*/
|
|
{
|
|
pOrigFileName = pFileName;
|
|
pOrigFile = _fsopen( pFileName, "r+t", _SH_DENYWR );
|
|
if ( !pOrigFile )
|
|
{
|
|
RpcError( (char *)NULL,
|
|
0,
|
|
ERROR_WRITING_FILE,
|
|
pFileName );
|
|
|
|
exit( ERROR_WRITING_FILE );
|
|
}
|
|
}
|
|
|
|
void
|
|
RW_ISTREAM::UpdateOriginalFile()
|
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Routine Description:
|
|
|
|
Write the contents of the temp file onto the original file.
|
|
|
|
Arguments:
|
|
|
|
none.
|
|
|
|
Return Value:
|
|
|
|
Notes:
|
|
|
|
----------------------------------------------------------------------------*/
|
|
{
|
|
if ( IsTempStream() )
|
|
{
|
|
// copy everything
|
|
CopyFile( pOrigFile );
|
|
}
|
|
}
|
|
|
|
#define MIDL_TOKEN_STRING "//@@MIDL_"
|
|
// length of above token
|
|
#define TOKEN_FLAG_LENGTH 9
|
|
|
|
#define MAX_TOKEN_TYPE_LENGTH 24
|
|
|
|
struct _token_table_ent
|
|
{
|
|
const char * pToken;
|
|
MIDL_FLAG_TOKEN TokenType;
|
|
}
|
|
TokenTable[] =
|
|
{
|
|
{"CLASS_DEFN", START_CLASS_TOKEN},
|
|
{"END_CLASS_DEFN", END_CLASS_TOKEN},
|
|
{"CLASS_USER_PART", START_CLASS_USER_TOKEN},
|
|
{"END_CLASS_USER_PART", END_CLASS_USER_TOKEN},
|
|
{"INCLUDES_LIST", START_INCLUDES_TOKEN},
|
|
{"END_INCLUDES_LIST", END_INCLUDES_TOKEN},
|
|
{"CLASS_METHODS", START_CLASS_METHODS_TOKEN},
|
|
{"METHOD", START_METHOD_TOKEN},
|
|
{"METHOD_BODY", START_METHOD_BODY_TOKEN},
|
|
{"CLASS_METHODS_END", END_CLASS_METHODS_TOKEN},
|
|
{"CLASS_DESTRUCTOR", CLASS_DESTRUCTOR_TOKEN},
|
|
{"FILE_HEADING", FILE_HEADING_TOKEN},
|
|
};
|
|
|
|
const int TokenTableSize = sizeof(TokenTable)/sizeof(_token_table_ent);
|
|
|
|
|
|
const char *
|
|
MIDL_TOKEN::GetStringForToken()
|
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Routine Description:
|
|
|
|
fetch the midl token name
|
|
|
|
Arguments:
|
|
|
|
none.
|
|
|
|
Return Value:
|
|
|
|
Notes:
|
|
|
|
----------------------------------------------------------------------------*/
|
|
{
|
|
for ( int i = 0; i<TokenTableSize; i++ )
|
|
{
|
|
if ( TokenType == TokenTable[i].TokenType )
|
|
return TokenTable[i].pToken;
|
|
}
|
|
|
|
assert( !"Token string not found" );
|
|
return NULL;
|
|
}
|
|
|
|
void
|
|
MIDL_TOKEN::EmitToken(
|
|
STREAM * pStream )
|
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Routine Description:
|
|
|
|
emit a MIDL token to the ISTREAM, NOT on a new line
|
|
format: //@@MIDL_xxxxx( <name> )
|
|
|
|
|
|
Arguments:
|
|
|
|
none.
|
|
|
|
Return Value:
|
|
|
|
Notes:
|
|
|
|
----------------------------------------------------------------------------*/
|
|
{
|
|
pStream->EmitSpecialCommentString();
|
|
pStream->Write( MIDL_TOKEN_STRING );
|
|
pStream->Write( GetStringForToken() );
|
|
pStream->Write( "( " );
|
|
pStream->Write( TokenParm );
|
|
pStream->Write( " )" );
|
|
}
|
|
|
|
MIDL_FLAG_TOKEN
|
|
MIDL_TOKEN::ParseForToken(
|
|
char * pS )
|
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Routine Description:
|
|
|
|
determine if the given string is a MIDL token
|
|
format: //@@MIDL_xxxxx( <name> )
|
|
|
|
|
|
Arguments:
|
|
|
|
none.
|
|
|
|
Return Value:
|
|
|
|
Notes:
|
|
|
|
----------------------------------------------------------------------------*/
|
|
{
|
|
char * pOpenParen;
|
|
char * pCloseParen;
|
|
char TokenTypeString[ MAX_TOKEN_TYPE_LENGTH+1 ];
|
|
unsigned long ulTokenTypeLength;
|
|
|
|
TokenType = NO_TOKEN;
|
|
|
|
pS = strstr( pS, MIDL_TOKEN_STRING );
|
|
if ( !pS )
|
|
return TokenType;
|
|
|
|
// found the "//@@MIDL_" part, now find the open paren
|
|
pOpenParen = strchr( pS, '(' );
|
|
|
|
pCloseParen = strchr( pOpenParen, ')' );
|
|
|
|
// check for malformed token
|
|
if ( !pOpenParen || !pCloseParen )
|
|
{
|
|
TokenType = BAD_TOKEN;
|
|
return TokenType;
|
|
}
|
|
|
|
// get the interesting part of the token name
|
|
pS += TOKEN_FLAG_LENGTH;
|
|
ulTokenTypeLength = (unsigned long)pOpenParen -
|
|
(unsigned long) pS;
|
|
|
|
if ( ulTokenTypeLength > MAX_TOKEN_TYPE_LENGTH )
|
|
{
|
|
TokenType = BAD_TOKEN;
|
|
return TokenType;
|
|
}
|
|
|
|
// save out a copy of the interesting part with a null terminator
|
|
strncpy( TokenTypeString, pS, ulTokenTypeLength );
|
|
|
|
// remove trailing white space
|
|
while( isspace( TokenTypeString[ulTokenTypeLength-1] ) )
|
|
ulTokenTypeLength--;
|
|
|
|
TokenTypeString[ ulTokenTypeLength ] = '\0';
|
|
|
|
// now see which token type it is
|
|
for ( int i=0; i < TokenTableSize; i++ )
|
|
{
|
|
// match found
|
|
if ( !strcmp( TokenTypeString, TokenTable[i].pToken ) )
|
|
{
|
|
char * pSrcPosn = pOpenParen;
|
|
char * pDestPosn = TokenParm;
|
|
|
|
TokenType = TokenTable[i].TokenType;
|
|
|
|
// save the parameter string; skip white space
|
|
while ( ++pSrcPosn != pCloseParen )
|
|
{
|
|
if ( !isspace( *pSrcPosn ) )
|
|
*pDestPosn++ = *pSrcPosn;
|
|
}
|
|
|
|
return TokenType;
|
|
}
|
|
}
|
|
|
|
// token not matched
|
|
TokenType = BAD_TOKEN;
|
|
return TokenType;
|
|
|
|
}
|
|
|
|
void
|
|
RW_ISTREAM::DiscardToNextMidlToken( MIDL_TOKEN & Token )
|
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Routine Description:
|
|
|
|
Skip ahead in pOrigFile to the next MIDL token, discarding as we go
|
|
|
|
Arguments:
|
|
|
|
none.
|
|
|
|
Return Value:
|
|
|
|
Notes:
|
|
|
|
----------------------------------------------------------------------------*/
|
|
{
|
|
// temp string buffer
|
|
char StringBuffer[STRINGBUFFERSIZE+1];
|
|
|
|
// make sure that the string buffer is always terminated
|
|
StringBuffer[STRINGBUFFERSIZE] = '\0';
|
|
|
|
// loop ends on feof, or matched token
|
|
while ( fgets( StringBuffer, STRINGBUFFERSIZE, pOrigFile) )
|
|
{
|
|
if ( Token.ParseForToken( StringBuffer ) != NO_TOKEN )
|
|
return;
|
|
}
|
|
}
|
|
|
|
|
|
void
|
|
RW_ISTREAM::SaveToNextMidlToken( MIDL_TOKEN & Token )
|
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Routine Description:
|
|
|
|
Skip ahead in pOrigFile to the next MIDL token, saving to our ISTREAM as we go
|
|
|
|
Arguments:
|
|
|
|
none.
|
|
|
|
Return Value:
|
|
|
|
Notes:
|
|
|
|
----------------------------------------------------------------------------*/
|
|
{
|
|
// temp string buffer
|
|
char StringBuffer[STRINGBUFFERSIZE+1];
|
|
|
|
// make sure that the string buffer is always terminated
|
|
StringBuffer[STRINGBUFFERSIZE] = '\0';
|
|
|
|
// loop ends on feof, or matched token (which is NOT copied to output)
|
|
while ( fgets( StringBuffer, STRINGBUFFERSIZE, pOrigFile) )
|
|
{
|
|
if ( Token.ParseForToken( StringBuffer ) != NO_TOKEN )
|
|
return;
|
|
// copy the line to the temp file
|
|
fputs( StringBuffer, S.F.pHandle );
|
|
}
|
|
|
|
}
|
|
|
|
|
|
void
|
|
STREAM::CopyFile( FILE * pDest )
|
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Routine Description:
|
|
|
|
Write the contents of the temp file onto the original file.
|
|
|
|
Arguments:
|
|
|
|
none.
|
|
|
|
Return Value:
|
|
|
|
Notes:
|
|
|
|
----------------------------------------------------------------------------*/
|
|
{
|
|
long lFileSize;
|
|
|
|
if ( ( GetStreamType() != STREAM_FILE ) || IsError())
|
|
return;
|
|
|
|
// reposition both files to the beginning
|
|
fseek( pDest, 0, SEEK_SET );
|
|
fseek( S.F.pHandle, 0, SEEK_SET );
|
|
|
|
// big buffer for copies
|
|
const size_t BIG_BUFSIZE = 16384;
|
|
char buffer[BIG_BUFSIZE];
|
|
size_t sBytesCopied;
|
|
|
|
while ( !feof( S.F.pHandle ) )
|
|
{
|
|
sBytesCopied = fread( buffer, sizeof( char ), BIG_BUFSIZE, S.F.pHandle );
|
|
|
|
sBytesCopied = fwrite( buffer, sizeof( char ), sBytesCopied, pDest );
|
|
}
|
|
|
|
// make sure the dest file does not have trailing gunk
|
|
fflush( pDest );
|
|
lFileSize = ftell( pDest );
|
|
|
|
_chsize( _fileno( pDest ), lFileSize );
|
|
|
|
}
|
|
|
|
RW_ISTREAM::~RW_ISTREAM()
|
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Routine Description:
|
|
|
|
Destructor for RW_ISTREAM.
|
|
|
|
Clean up the pOrigFile if needed
|
|
|
|
Arguments:
|
|
|
|
none.
|
|
|
|
Return Value:
|
|
|
|
Notes:
|
|
|
|
----------------------------------------------------------------------------*/
|
|
{
|
|
if ( pOrigFile )
|
|
{
|
|
fclose( pOrigFile );
|
|
}
|
|
}
|