2020-09-30 17:12:29 +02:00

423 lines
9.2 KiB
C++

/************************************************************************
* *
* MAPREAD.CPP *
* *
* Copyright (C) Microsoft Corporation 1995 *
* All Rights reserved. *
* *
************************************************************************/
#include "stdafx.h"
#include "mapread.h"
#include "..\common\waitcur.h"
const int MAX_MAP_TABLES = 10;
static CTable* aMapTables[MAX_MAP_TABLES + 1];
static CTable* aAliasTables[MAX_MAP_TABLES + 1];
static CTable* ptblMapNames;
const char txtDBCSOption[] = "DBCS=";
extern const char txtMAP[];
static PSTR FASTCALL SkipToEndOfWord(PSTR psz);
/***************************************************************************
FUNCTION: CReadMapFile::CReadMapFile
PURPOSE: Read the [MAP] section of a project file into a double-table
PARAMETERS:
pszFile -- either help file or project file
fHelpFile -- TRUE (default) if it pszFile is a help file
RETURNS: m_ptblMap is non-NULL is a map table is available
COMMENTS:
Numbers are stored in the primary string, Topic IDs are stored in
the secondary string.
MODIFICATION DATES:
07-Mar-1995 [ralphw]
***************************************************************************/
CReadMapFile::CReadMapFile(PCSTR pszFile, BOOL fHelpFile)
{
m_ptblMap = NULL;
m_ptblAlias = NULL;
PCSTR pszProjectFile;
if (!ptblMapNames)
ptblMapNames = new CTable;
if (fHelpFile) {
ASSERT(pMapFile);
char szDummy[MAX_PATH];
PSTR pszFilePortion;
if (GetFullPathName(pszFile, sizeof(szDummy), szDummy, &pszFilePortion) == 0)
pszFilePortion = (PSTR) pszFile;
int pos = pMapFile->ctbl.IsPrimaryStringInTable(pszFilePortion) + 1;
if (pos < 2)
return; // we don't have a project file for this help file
else
pszProjectFile = pMapFile->ctbl.GetPointer(pos);
}
else
pszProjectFile = pszFile;
int pos = ptblMapNames->IsStringInTable(pszProjectFile);
if (pos) {
m_ptblMap = aMapTables[pos];
m_ptblAlias = aAliasTables[pos];
return;
}
CWaitCursor cwait;
/*
* Note that by adding the name here, we will never attempt to read
* this project file again if it can't be opened, or if it doesn't contain
* a [MAP] section.
*/
if (ptblMapNames->CountStrings() > MAX_MAP_TABLES) {
/*
* We overflowed, which means we probably have a lot of unused
* map tables hanging out. So we throw out the whole batch and
* start over.
*/
for (int i = 1; i <= ptblMapNames->CountStrings(); i++) {
if (aMapTables[i]) {
delete aMapTables[i];
aMapTables[i] = NULL;
}
if (aAliasTables[i]) {
delete aAliasTables[i];
aAliasTables[i] = NULL;
}
}
delete ptblMapNames;
ptblMapNames = new CTable;
}
pos = ptblMapNames->AddString(pszProjectFile);
iTop = 0;
if (!FPushFilePfs(pszProjectFile))
return;
char szOldDir[MAX_PATH];
GetCurrentDirectory(sizeof(szOldDir), szOldDir);
ChangeDirectory(pszProjectFile);
m_ptblDefine = new CTable;
fDBCSSystem = _fDBCSSystem;
CStr cszDst;
RC_TYPE rc = RC_Success;
CInput* pin = PfTopPfs();
while (rc == RC_Success) {
if (!pin->getline(&cszDst)) {
// Close current file, continue with nested file if there is one
FPopPfs();
if (!(pin = PfTopPfs())) {
rc = RC_EOF;
break;
}
continue;
}
LineRead:
if (rc != RC_Success)
break;
if (nstrsubcmp(cszDst, txtDBCSOption)) {
char szValue[256];
GetArg(szValue, FirstNonSpace(cszDst.psz + strlen(txtDBCSOption)));
fDBCSSystem = YesNo(szValue);
}
// REVIEW: we should handle DBCS=, ROOT=, and REPLACE=
else if (nstrisubcmp(cszDst, txtMAP)) {
if (!aMapTables[pos])
aMapTables[pos] = new CTable;
m_ptblMap = aMapTables[pos];
rc = CReadMapSection(&cszDst);
goto LineRead;
}
else if (nstrisubcmp(cszDst, "[ALIAS]")) {
if (!aAliasTables[pos])
aAliasTables[pos] = new CTable;
m_ptblAlias = aAliasTables[pos];
rc = CReadAliasSection(&cszDst);
goto LineRead;
}
}
if (rc != RC_Success) { // Happens if there is no map section
SetCurrentDirectory(szOldDir);
return;
}
if (m_ptblDefine) {
delete m_ptblDefine;
m_ptblDefine = NULL;
}
SetCurrentDirectory(szOldDir);
}
RC_TYPE CReadMapFile::CReadMapSection(CStr* pcszDst)
{
RC_TYPE rc = RC_Success;
while (rc == RC_Success) {
rc = RcGetLogicalLine(pcszDst);
if (rc != RC_Success)
return rc;
if (*pcszDst->psz == '[')
return RC_Success;
if (nstrisubcmp(pcszDst->psz, txtDefine) && m_ptblDefine->IsStringInTable(
FirstNonSpace(pcszDst->psz + strlen(txtDefine) + 1, fDBCSSystem)))
continue;
PSTR pszTmp;
if (!(pszTmp = StrChr(pcszDst->psz, CH_EQUAL, fDBCSSystem)))
pszTmp = SkipToEndOfWord(pcszDst->psz);
if (!pszTmp || !*pszTmp)
continue;
if (nstrisubcmp(pcszDst->psz, txtDefine)) {
strcpy(pcszDst->psz, FirstNonSpace(pcszDst->psz + strlen(txtDefine), fDBCSSystem));
if (*pszTmp != CH_EQUAL)
pszTmp = SkipToEndOfWord(pcszDst->psz);
if (!*pszTmp) {
continue;
}
}
*pszTmp = '\0';
SzTrimSz(pcszDst->psz);
// Special case no-help constant
if (nstrsubcmp(FirstNonSpace(pszTmp + 1, fDBCSSystem), "((DWORD) -1)"))
continue;
PSTR pszSave = pcszDst->psz;
PSTR pszLine = SzTrimSz(pszTmp + 1);
int val;
if (!FGetUnsigned(pszLine, &pszTmp, &val))
continue;
char szNum[20];
itoa(val, szNum, 10);
m_ptblMap->AddString(szNum, pszSave);
}
return rc;
}
RC_TYPE CReadMapFile::CReadAliasSection(CStr* pcszDst)
{
RC_TYPE rc = RC_Success;
while (rc == RC_Success) {
rc = RcGetLogicalLine(pcszDst);
if (rc != RC_Success)
return rc;
if (*pcszDst->psz == '[')
return RC_Success;
PSTR pszAlias;
if (!(pszAlias = StrChr(pcszDst->psz, CH_EQUAL, fDBCSSystem)))
continue;
*pszAlias++ = '\0';
SzTrimSz(pcszDst->psz);
SzTrimSz(pszAlias);
m_ptblAlias->AddString(pcszDst->psz, pszAlias);
}
return rc;
}
// Stolen shamelessly from hpj.cpp in hcrtf
static const char txtInclude[] = "#include";
static const char txtIfDef[] = "#ifdef";
static const char txtIfnDef[] = "#ifndef";
#define IsQuote(ch) ((ch) == CH_QUOTE || (ch) == CH_START_QUOTE || (ch) == CH_END_QUOTE)
RC_TYPE STDCALL CReadMapFile::RcGetLogicalLine(CStr* pcszDst)
{
PSTR pszDst = pcszDst->psz; // purely for our notational convenience
CInput* pin = PfTopPfs();
if (!pin)
return RC_EOF;
for (;;) {
if (!pin->getline(pcszDst)) {
// Close current file, continue with nested file if there is one
FPopPfs();
if (!(pin = PfTopPfs()))
return RC_EOF;
continue;
}
if (*pszDst == CH_SPACE || *pszDst == CH_TAB)
strcpy(pszDst, FirstNonSpace(pszDst, fDBCSSystem));
PSTR psz = pszDst;
switch (*psz) {
case 0:
case ';':
continue;
case '#':
if (nstrisubcmp(psz, txtInclude)) {
// process #include
psz = FirstNonSpace(pszDst + strlen(txtInclude), fDBCSSystem);
if (!psz) {
continue;
}
if (*psz == CH_QUOTE || *psz == '<') {
char ch = (*psz == CH_QUOTE) ? CH_QUOTE : '>';
psz++;
PSTR pszEnd = StrChr(psz, ch, fDBCSSystem);
if (*pszEnd)
*pszEnd = '\0';
}
FPushFilePfs(psz);
if (!(pin = PfTopPfs()))
return RC_EOF;
continue;
}
else if (nstrisubcmp(psz, txtDefine))
goto ValidString;
else if (nstrisubcmp(psz, txtIfDef))
m_ptblDefine->AddString(
FirstNonSpace(psz + strlen(txtIfDef) + 1, fDBCSSystem));
else if (nstrisubcmp(psz, txtIfnDef))
m_ptblDefine->AddString(
FirstNonSpace(psz + strlen(txtIfnDef) + 1, fDBCSSystem));
// REVIEW: process #ifdef, #ifndef, #else, #endif
continue;
default:
// We have a valid string.
if (psz != pszDst)
strcpy(pszDst, psz);
// Remove any comments
ValidString:
// Usually there are no comments, so the strchr/strstr checks
// are faster then stepping through every character in the line
if (strchr(pszDst, ';') || strstr(pszDst, "//")) {
for (psz = pszDst; *psz; psz++) {
if (IsQuote(*psz)) {
psz++;
while (!IsQuote(*psz) && *psz)
psz++;
}
if (*psz == ';') {
*psz = '\0';
break;
}
else if (*psz == '/' && psz[1] == '/') {
*psz = '\0';
break;
}
}
}
while ((psz = strstr(pszDst, "/*"))) {
PSTR pszTmp = strstr(psz, "*/");
if (pszTmp)
strcpy(psz, FirstNonSpace(pszTmp + 2, fDBCSSystem));
else {
char szBuf[512];
do {
if (!pin->getline(szBuf)) {
/*
* Close current file, continue with nested
* file if there is one
*/
FPopPfs();
if (!(pin = PfTopPfs()))
return RC_EOF;
continue;
}
} while (!(pszTmp = strstr(szBuf, "*/")));
strcpy(psz, FirstNonSpace(pszTmp + 2, fDBCSSystem));
// New line could have comments, so start all over
goto ValidString;
}
}
SzTrimSz(pszDst);
if (!*pszDst)
continue;
return RC_Success;
}
}
}
BOOL STDCALL CReadMapFile::FPushFilePfs(PCSTR szFile)
{
CInput* pin = new CInput(szFile);
if (!pin->fInitialized)
return FALSE;
apin[iTop++] = pin;
return TRUE;
}
BOOL CReadMapFile::FPopPfs(void)
{
if (iTop >= 0) {
ASSERT(PfTopPfs() != NULL);
delete PfTopPfs();
--iTop;
return TRUE;
}
return FALSE;
}
static PSTR FASTCALL SkipToEndOfWord(PSTR psz)
{
while (*psz != ' ' && *psz != '\t' && *psz)
psz++;
return psz;
}