444 lines
9 KiB
C++
444 lines
9 KiB
C++
/* Copyright (C) Microsoft Corporation, 1998. All rights reserved. */
|
|
|
|
#include "precomp.h"
|
|
#include "getsym.h"
|
|
#include "utils.h"
|
|
|
|
|
|
CInput::
|
|
CInput
|
|
(
|
|
BOOL *pfRetCode,
|
|
LPSTR pszPathName,
|
|
UINT cbBufSize
|
|
)
|
|
:
|
|
m_cbBufSize(cbBufSize),
|
|
m_cbValidData(0),
|
|
m_nCurrOffset(0),
|
|
m_chCurr(INVALID_CHAR),
|
|
m_fEndOfFile(TRUE)
|
|
{
|
|
m_pszPathName = ::My_strdup(pszPathName);
|
|
m_pbDataBuf = new BYTE[m_cbBufSize];
|
|
|
|
m_hFile = ::CreateFile(pszPathName,
|
|
GENERIC_READ,
|
|
FILE_SHARE_READ,
|
|
NULL, // default security
|
|
OPEN_EXISTING,
|
|
FILE_ATTRIBUTE_NORMAL | FILE_ATTRIBUTE_READONLY,
|
|
NULL); // no template
|
|
|
|
m_cbFileSize = (NULL != m_hFile) ? ::GetFileSize(m_hFile, NULL) : 0;
|
|
|
|
*pfRetCode = (NULL != m_pszPathName) &&
|
|
(NULL != m_pbDataBuf) &&
|
|
(NULL != m_hFile);
|
|
|
|
if (*pfRetCode)
|
|
{
|
|
if (CheckBuffer(1))
|
|
{
|
|
m_chCurr = m_pbDataBuf[0];
|
|
m_fEndOfFile = FALSE;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
CInput::
|
|
~CInput ( void )
|
|
{
|
|
delete m_pszPathName;
|
|
delete m_pbDataBuf;
|
|
|
|
if (NULL != m_hFile)
|
|
{
|
|
::CloseHandle(m_hFile);
|
|
}
|
|
}
|
|
|
|
|
|
void CInput::
|
|
NextChar ( void )
|
|
{
|
|
if (INVALID_CHAR != m_chCurr)
|
|
{
|
|
// set up the next new char
|
|
if (CheckBuffer(1))
|
|
{
|
|
m_chCurr = m_pbDataBuf[++m_nCurrOffset];
|
|
}
|
|
else
|
|
{
|
|
m_chCurr = INVALID_CHAR;
|
|
m_fEndOfFile = TRUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void CInput::
|
|
PeekChars ( UINT cChars, LPSTR pszChars )
|
|
{
|
|
if (CheckBuffer(cChars - 1))
|
|
{
|
|
::CopyMemory(pszChars, &m_pbDataBuf[m_nCurrOffset], cChars);
|
|
}
|
|
else
|
|
{
|
|
::ZeroMemory(pszChars, cChars);
|
|
}
|
|
}
|
|
|
|
|
|
void CInput::
|
|
SkipChars ( UINT cChars )
|
|
{
|
|
for (UINT i = 0; i < cChars; i++)
|
|
{
|
|
NextChar();
|
|
}
|
|
}
|
|
|
|
|
|
BOOL CInput::
|
|
CheckBuffer ( UINT cChars )
|
|
{
|
|
if (m_nCurrOffset + cChars >= m_cbValidData)
|
|
{
|
|
ASSERT(m_cbValidData >= m_nCurrOffset);
|
|
UINT cbCurrValid = m_cbValidData - m_nCurrOffset;
|
|
UINT cbToRead = m_cbBufSize - cbCurrValid;
|
|
|
|
if (cbCurrValid > 0)
|
|
{
|
|
// Move the data to the front of the buffer.
|
|
::CopyMemory(&m_pbDataBuf[0], &m_pbDataBuf[m_nCurrOffset], cbCurrValid);
|
|
m_nCurrOffset = 0;
|
|
}
|
|
|
|
ULONG cbRead = 0;
|
|
if (::ReadFile(m_hFile, &m_pbDataBuf[cbCurrValid], cbToRead, &cbRead, NULL))
|
|
{
|
|
ASSERT(cbRead <= cbToRead);
|
|
m_cbValidData = cbCurrValid + cbRead;
|
|
m_nCurrOffset = 0;
|
|
|
|
if (cbRead < cbToRead)
|
|
{
|
|
m_fEndOfFile = TRUE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
m_fEndOfFile = TRUE;
|
|
}
|
|
|
|
return (m_nCurrOffset + cChars < m_cbValidData);
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
BOOL CInput::
|
|
Rewind ( void )
|
|
{
|
|
if ((DWORD) -1 != ::SetFilePointer(m_hFile, 0, NULL, FILE_BEGIN))
|
|
{
|
|
// clean up members
|
|
m_cbValidData = 0;
|
|
m_nCurrOffset = 0;
|
|
m_chCurr = INVALID_CHAR;
|
|
|
|
// set up the buffer
|
|
if (CheckBuffer(1))
|
|
{
|
|
m_chCurr = m_pbDataBuf[0];
|
|
m_fEndOfFile = FALSE;
|
|
}
|
|
else
|
|
{
|
|
m_fEndOfFile = TRUE;
|
|
}
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
|
|
|
|
CSymbol::
|
|
CSymbol ( CInput *pInput )
|
|
:
|
|
m_pInput(pInput),
|
|
m_eSymbolID(SYMBOL_UNKNOWN),
|
|
m_cchSymbolStr(0)
|
|
{
|
|
m_szSymbolStr[0] = '\0';
|
|
}
|
|
|
|
|
|
BOOL CSymbol::
|
|
NextSymbol ( void )
|
|
{
|
|
if (SYMBOL_EOF == m_eSymbolID)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
char ch = m_pInput->GetChar();
|
|
m_szSymbolStr[0] = ch;
|
|
m_cchSymbolStr = 1;
|
|
|
|
m_pInput->NextChar();
|
|
|
|
if (::isdigit(ch))
|
|
{
|
|
// numbers
|
|
while (INVALID_CHAR != (ch = m_pInput->GetChar()))
|
|
{
|
|
if (::isdigit(ch))
|
|
{
|
|
m_szSymbolStr[m_cchSymbolStr++] = ch;
|
|
m_pInput->NextChar();
|
|
}
|
|
else
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
m_eSymbolID = SYMBOL_NUMBER;
|
|
}
|
|
else
|
|
if (::isalpha(ch))
|
|
{
|
|
// alphanumeric
|
|
while (INVALID_CHAR != (ch = m_pInput->GetChar()))
|
|
{
|
|
if (::isalnum(ch) || '_' == ch || '-' == ch)
|
|
{
|
|
m_szSymbolStr[m_cchSymbolStr++] = ch;
|
|
m_pInput->NextChar();
|
|
}
|
|
else
|
|
{
|
|
m_szSymbolStr[m_cchSymbolStr] = '\0';
|
|
break;
|
|
}
|
|
}
|
|
|
|
m_eSymbolID = ::IsKeyword(&m_szSymbolStr[0]) ? SYMBOL_KEYWORD : SYMBOL_IDENTIFIER;
|
|
}
|
|
else
|
|
if ('\n' == ch)
|
|
{
|
|
m_szSymbolStr[m_cchSymbolStr++] = '\n';
|
|
m_eSymbolID = SYMBOL_SPACE_EOL;
|
|
}
|
|
else
|
|
if (::isspace(ch))
|
|
{
|
|
// space
|
|
m_eSymbolID = SYMBOL_SPACE;
|
|
while (INVALID_CHAR != (ch = m_pInput->GetChar()))
|
|
{
|
|
if (::isspace(ch))
|
|
{
|
|
m_szSymbolStr[m_cchSymbolStr++] = ch;
|
|
m_pInput->NextChar();
|
|
if ('\n' == ch)
|
|
{
|
|
m_eSymbolID = SYMBOL_SPACE_EOL;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
if ('&' == ch)
|
|
{
|
|
m_eSymbolID = SYMBOL_FIELD;
|
|
|
|
// alphanumeric
|
|
while (INVALID_CHAR != (ch = m_pInput->GetChar()))
|
|
{
|
|
if (::isalnum(ch) || '_' == ch)
|
|
{
|
|
m_szSymbolStr[m_cchSymbolStr++] = ch;
|
|
m_pInput->NextChar();
|
|
}
|
|
else
|
|
{
|
|
m_szSymbolStr[m_cchSymbolStr] = '\0';
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
char szTemp[4];
|
|
m_eSymbolID = SYMBOL_SPECIAL;
|
|
|
|
if (':' == ch)
|
|
{
|
|
m_pInput->PeekChars(2, &szTemp[0]);
|
|
if (':' == szTemp[0] && '=' == szTemp[1])
|
|
{
|
|
m_pInput->SkipChars(2);
|
|
m_szSymbolStr[m_cchSymbolStr++] = ':';
|
|
m_szSymbolStr[m_cchSymbolStr++] = '=';
|
|
m_eSymbolID = SYMBOL_DEFINITION;
|
|
}
|
|
}
|
|
else
|
|
if ('-' == ch)
|
|
{
|
|
m_pInput->PeekChars(1, &szTemp[0]);
|
|
if ('-' == szTemp[0])
|
|
{
|
|
m_pInput->SkipChars(1);
|
|
m_szSymbolStr[m_cchSymbolStr++] = '-';
|
|
m_eSymbolID = SYMBOL_COMMENT;
|
|
}
|
|
}
|
|
else
|
|
if ('.' == ch)
|
|
{
|
|
m_pInput->PeekChars(2, &szTemp[0]);
|
|
if ('.' == szTemp[0] && '.' == szTemp[1])
|
|
{
|
|
m_pInput->SkipChars(2);
|
|
m_szSymbolStr[m_cchSymbolStr++] = '.';
|
|
m_szSymbolStr[m_cchSymbolStr++] = '.';
|
|
m_eSymbolID = SYMBOL_DOTDOTDOT;
|
|
}
|
|
}
|
|
}
|
|
|
|
// null terminate the string
|
|
m_szSymbolStr[m_cchSymbolStr] = '\0';
|
|
|
|
if (INVALID_CHAR != m_szSymbolStr[0])
|
|
{
|
|
return TRUE;
|
|
}
|
|
|
|
m_eSymbolID = SYMBOL_EOF;
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
BOOL CSymbol::
|
|
NextUsefulSymbol ( void )
|
|
{
|
|
BOOL fInsideComment = FALSE;
|
|
while (NextSymbol())
|
|
{
|
|
if (SYMBOL_SPACE_EOL == m_eSymbolID)
|
|
{
|
|
fInsideComment = FALSE;
|
|
}
|
|
else
|
|
if (SYMBOL_COMMENT == m_eSymbolID)
|
|
{
|
|
fInsideComment = ! fInsideComment;
|
|
}
|
|
else
|
|
if (! fInsideComment)
|
|
{
|
|
if (SYMBOL_SPACE != m_eSymbolID)
|
|
{
|
|
return TRUE;
|
|
}
|
|
}
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
|
|
COutput::
|
|
COutput
|
|
(
|
|
BOOL *pfRetCode,
|
|
LPSTR pszPathName,
|
|
UINT cbBufSize
|
|
)
|
|
:
|
|
m_cbBufSize(cbBufSize),
|
|
m_cbValidData(0)
|
|
{
|
|
m_pszPathName = ::My_strdup(pszPathName);
|
|
m_pbDataBuf = new BYTE[m_cbBufSize];
|
|
m_hFile = ::CreateFile(pszPathName,
|
|
GENERIC_WRITE,
|
|
FILE_SHARE_READ,
|
|
NULL, // default security
|
|
CREATE_ALWAYS,
|
|
FILE_ATTRIBUTE_NORMAL,
|
|
NULL); // no template
|
|
*pfRetCode = (NULL != m_pszPathName) &&
|
|
(NULL != m_pbDataBuf) &&
|
|
(NULL != m_hFile);
|
|
}
|
|
|
|
|
|
COutput::
|
|
~COutput ( void )
|
|
{
|
|
delete m_pszPathName;
|
|
delete m_pbDataBuf;
|
|
|
|
if (NULL != m_hFile)
|
|
{
|
|
Flush();
|
|
::CloseHandle(m_hFile);
|
|
}
|
|
}
|
|
|
|
|
|
BOOL COutput::
|
|
Write
|
|
(
|
|
LPBYTE pbDataBuf,
|
|
UINT cbToWrite
|
|
)
|
|
{
|
|
ULONG cbWritten;
|
|
|
|
while (0 != cbToWrite)
|
|
{
|
|
if (::WriteFile(m_hFile, pbDataBuf, cbToWrite, &cbWritten, NULL))
|
|
{
|
|
pbDataBuf += cbWritten;
|
|
cbToWrite -= cbWritten;
|
|
}
|
|
else
|
|
{
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
BOOL COutput::
|
|
Writeln
|
|
(
|
|
LPBYTE pbDataBuf,
|
|
UINT cbToWrite
|
|
)
|
|
{
|
|
return Write(pbDataBuf, cbToWrite) && Write("\n", 1);
|
|
}
|
|
|
|
|