hpjread.cpp
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C++ 代码 · 共 1,091 行 · 第 1/2 页
CPP
1,091 行
/****************************************************************************
*
* Open Watcom Project
*
* Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved.
*
* ========================================================================
*
* This file contains Original Code and/or Modifications of Original
* Code as defined in and that are subject to the Sybase Open Watcom
* Public License version 1.0 (the 'License'). You may not use this file
* except in compliance with the License. BY USING THIS FILE YOU AGREE TO
* ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is
* provided with the Original Code and Modifications, and is also
* available at www.sybase.com/developer/opensource.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM
* ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR
* NON-INFRINGEMENT. Please see the License for the specific language
* governing rights and limitations under the License.
*
* ========================================================================
*
* Description: Parsing of .hpj files.
*
****************************************************************************/
#include <stdlib.h>
#include <ctype.h>
#ifdef __UNIX__
#include <dirent.h>
#include <unistd.h>
#else
#include <direct.h>
#endif
#include "hpjread.h"
#include "hcerrors.h"
#include "parsing.h"
#include "topic.h"
#include "phrase.h"
#include "bmx.h"
#define NB_FILES 10
#define LINE_BLOCK 128
char const HpjExt[] = ".HPJ";
// Other string resources.
static char const SBaggage[] = "BAGGAGE";
static char const SOptions[] = "OPTIONS";
static char const SConfig[] = "CONFIG";
static char const SFiles[] = "FILES";
static char const SMap[] = "MAP";
static char const SBitmaps[] = "BITMAPS";
static char const SWindows[] = "WINDOWS";
static char const STitle[] = "TITLE";
static char const SCopyright[] = "COPYRIGHT";
static char const SCompress[] = "COMPRESS";
static char const STrue[] = "TRUE";
static char const SHigh[] = "HIGH";
static char const SMedium[] = "MEDIUM";
static char const SYes[] = "YES";
static char const SFalse[] = "FALSE";
static char const SLow[] = "LOW";
static char const SNo[] = "NO";
static char const SOldKeyPhrase[] = "OLDKEYPHRASE";
static char const SContents[] = "CONTENTS";
static char const SIndex[] = "INDEX";
static char const SBmRoot[] = "BMROOT";
static char const SRoot[] = "ROOT";
static char const Sinclude[] = "#include";
static char const Sdefine[] = "#define";
static char const Smain[] = "main";
static char const Ssecondary[] = "secondary";
static char const SstartComment[] = "/*";
static char const SendComment[] = "*/";
// C-tor and D-tor for class HPJScanner
HPJScanner::HPJScanner( InFile *src )
: _input( src )
{
_lineNum = 0;
if( !_input->bad() ){
_curLine = new char[LINE_BLOCK];
_lineSize = LINE_BLOCK;
} else {
_curLine = NULL;
}
}
HPJScanner::~HPJScanner()
{
if( _curLine ) delete[] _curLine;
}
// HPJScanner::open --Initialize the parser on a given filename.
int HPJScanner::open( char const filename[] )
{
int result = _input->open( filename, File::READ|File::TEXT );
if( !result ){
if( _curLine == NULL ){
_curLine = new char[120]; // Overflow possibility
}
}
return result;
}
// HPJScanner::getLine --Read a single line of text into _curLine.
// Returns the line length (0 in case of failure).
int HPJScanner::getLine()
{
int current;
int has_text;
int cur_len=0;
// Loop until we've identified a single line.
while( cur_len == 0 ){
++_lineNum;
current = 0;
cur_len = 0;
has_text = 0;
for( ;; ){
current = _input->nextch();
if( current == ';' && cur_len == 0 ) break;
if( current == EOF || current == '\n' ) break;
if( !isspace( current ) ) {
has_text = 1;
}
if( cur_len == _lineSize ){
_lineSize += LINE_BLOCK;
renew( _curLine, _lineSize );
}
_curLine[cur_len++] = (char) current;
}
if( current == ';' && cur_len == 0 ){
do {
current = _input->nextch();
}while( current != EOF && current != '\n' );
if( cur_len == 0 ){
continue;
}
}
if( current != EOF || cur_len > 0 ){
if( cur_len == _lineSize ){
_lineSize += LINE_BLOCK;
renew( _curLine, _lineSize );
}
_curLine[cur_len++] = '\0';
} else {
break;
}
if( !has_text ){
cur_len = 0;
}
}
// Set up the buffer so this line can be tokenized.
if( cur_len > 0 ){
_bufPos = 0;
_bufChar = _curLine[0];
}
return cur_len;
}
// HPJScanner::getArg --Read a "= <string>" argument from the .HPJ file.
char *HPJScanner::getArg( int start_pos )
{
int i;
// Eat whitespace.
for( i = start_pos; isspace( _curLine[i] ) ; i++ ){
if( _curLine[i] == '\0' ) break;
}
// The next character had better be an '='.
if( _curLine[i] != '=' ){
HCWarning( HPJ_NOARG, _lineNum, name() );
return NULL;
}
i++;
// Eat whitespace again.
while( isspace( _curLine[i] ) && _curLine[i] != '\0' ){
i++;
}
return _curLine+i;
}
// HPJScanner::tokLine --Tokenize a line, like the strtok() function.
char *HPJScanner::tokLine()
{
int i,j;
_curLine[_bufPos] = _bufChar;
// Find the beginning of the token.
for( i=_bufPos; _curLine[i] != '\0' && isspace( _curLine[i] ); ++i){
} // empty
if( _curLine[i] == '\0' ) return NULL;
// Find the end of the token.
for( j=i; _curLine[j] != '\0' && !isspace( _curLine[j] ); ++j){
} // empty
_bufPos = j;
_bufChar = _curLine[j];
_curLine[j] = '\0';
return _curLine+i;
}
// HPJScanner::endTok --Stop tokenizing and get the rest of the line.
char *HPJScanner::endTok()
{
_curLine[_bufPos] = _bufChar;
return _curLine+_bufPos;
}
static HPJReader::StrNode *HPJReader::_topFile = NULL;
static HPJReader::StrNode *HPJReader::_curFile = NULL;
static HPJReader::StrNode *HPJReader::_firstDir = NULL;
static char const *HPJReader::_startDir = NULL;
// HPJReader::HPJReader
HPJReader::HPJReader( HFSDirectory * d_file, Pointers *other_files,
InFile *input )
: _scanner( input )
{
_dir = d_file;
_theFiles = other_files;
_sysFile = other_files->_sysFile;
_numBagFiles = 0;
_rtfFiles = _root = NULL;
_homeDir = new char[ _MAX_PATH ];
getcwd( _homeDir, _MAX_PATH );
if( input->bad() ){
_bagFiles = NULL;
} else {
_bagFiles = new Baggage*[NB_FILES];
}
_oldPhrases = 0;
}
// HPJReader::~HPJReader
HPJReader::~HPJReader()
{
delete[] _homeDir;
StrNode *current, *temp;
current = _root;
while( current != NULL ){
temp = current;
current = current->_next;
delete[] temp->_name;
delete temp;
}
current = _rtfFiles;
while( current != NULL ){
temp = current;
current = current->_next;
delete[] temp->_name;
delete temp;
}
if( _bagFiles ){
for( int i=0; i<_numBagFiles; i++ ){
delete _bagFiles[i];
}
delete[] _bagFiles;
}
}
// HPJReader::firstFile --Callback function for the phrase handler.
static InFile *HPJReader::firstFile()
{
_curFile = _topFile;
return nextFile();
}
// HPJReader::nextFile --Callback function for the phrase handler.
static InFile *HPJReader::nextFile()
{
static InFile result;
StrNode *curdir;
do{
if( _curFile == NULL ){
return NULL;
}
curdir = _firstDir;
if( curdir == NULL ){
result.open( _curFile->_name );
} else {
while( curdir != NULL ){
chdir( curdir->_name );
result.open( _curFile->_name );
chdir( _startDir );
if( !result.bad() ) break;
curdir = curdir->_next;
}
}
_curFile = _curFile->_next;
} while( result.bad() );
return &result;
}
// HPJReader::parseFile --Parse an .HPJ file, and call .RTF parsers
// as appropriate.
HPJReader::parseFile()
{
HCStartFile( _scanner.name() );
int length = _scanner.getLine(); // Get the first line.
char section[15];
int i;
while( length != 0 ){
// The first line had better be the beginning of a section.
if( _scanner[0] != '[' ){
HCWarning( HPJ_NOTSECTION, _scanner.lineNum(), _scanner.name() );
length = skipSection();
continue;
}
// Read in the name of the section.
for( i=1; i < length ; i++ ){
if( _scanner[i] == ']' ) break;
section[i-1] = (char) toupper( _scanner[i] );
}
// If the section name wasn't terminated properly, skip the section.
if( i == length ){
HCWarning( HPJ_BADSECTION, _scanner.lineNum(), _scanner.name() );
length = skipSection();
continue;
}
section[i-1] = '\0';
// Pass control to the appropriate "section handler".
if( strcmp( section, SBaggage ) == 0 ){
length = handleBaggage();
} else if( strcmp( section, SOptions ) == 0 ){
length = handleOptions();
} else if( strcmp( section, SConfig ) == 0 ){
length = handleConfig();
} else if( strcmp( section, SFiles ) == 0 ){
length = handleFiles();
} else if( strcmp( section, SMap ) == 0 ){
length = handleMap();
} else if( strcmp( section, SBitmaps ) == 0 ){
length = handleBitmaps();
} else if( strcmp( section, SWindows ) == 0 ){
length = handleWindows();
} else {
HCWarning( HPJ_BADSECTION, _scanner.lineNum(), _scanner.name() );
length = skipSection();
}
}
if( _rtfFiles == NULL ){
HCError( HPJ_NOFILES );
}
// Now parse individual RTF files.
StrNode *curfile = _rtfFiles;
StrNode *curdir;
InFile source;
// First, implement phrase replacement if desired.
if( _theFiles->_sysFile->isCompressed() ){
_topFile = _rtfFiles;
_firstDir = _root;
_startDir = _homeDir;
_theFiles->_phrFile = new HFPhrases( _dir, &firstFile, &nextFile );
char full_path[_MAX_PATH];
char drive[_MAX_DRIVE];
char dir[_MAX_DIR];
char fname[_MAX_FNAME];
char ext[_MAX_EXT];
_fullpath( full_path, _scanner.name(), _MAX_PATH );
_splitpath( full_path, drive, dir, fname, ext );
_makepath( full_path, drive, dir, fname, PhExt );
if( !_oldPhrases || !_theFiles->_phrFile->oldTable(full_path) ){
_theFiles->_phrFile->readPhrases();
_theFiles->_phrFile->createQueue( full_path );
}
}
_theFiles->_topFile = new HFTopic( _dir, _theFiles->_phrFile );
// For each file, search the ROOT path, and create a RTFparser
// to deal with it.
curfile = _rtfFiles;
while( curfile != NULL ){
curdir = _root;
if( curdir == NULL ){
source.open( curfile->_name );
} else while( curdir != NULL ){
chdir( curdir->_name );
source.open( curfile->_name );
chdir( _homeDir );
if( !source.bad() ) break;
curdir = curdir->_next;
}
if( source.bad() ){
HCWarning( FILE_ERR, curfile->_name );
} else {
RTFparser rtfhandler( _theFiles, &source );
rtfhandler.Go();
source.close();
}
curfile = curfile->_next;
}
}
// HPJReader::skipSection --Jump to the next section header.
int HPJReader::skipSection()
{
int result;
do{
result = _scanner.getLine();
} while( result != 0 && _scanner[0] != '[' );
return result;
}
// HPJReader::handleBaggage --Create baggage files.
int HPJReader::handleBaggage()
{
int result;
while( _numBagFiles < NB_FILES ){
result = _scanner.getLine();
if( !result ) break;
if( _scanner[0] == '[' ) break;
_bagFiles[ _numBagFiles++ ] = new Baggage( _dir, _scanner );
}
return result;
}
// HPJReader::handleOptions --Parse the [OPTIONS] section.
#define MAX_OPTION_LEN 12
int HPJReader::handleOptions()
{
int result;
char option[MAX_OPTION_LEN+1];
char *arg;
int i;
for( ;; ){
result = _scanner.getLine();
if( !result || _scanner[0] == '[' ) break;
// Read in the name of the option.
for( i=0; i<MAX_OPTION_LEN; i++ ){
if( isspace( _scanner[i] ) || _scanner[i] == '=' ) break;
option[i] = (char) toupper( _scanner[i] );
}
option[i] = '\0';
// At present, I only support a few options.
// Most of these involve passing information to
// the HFSystem object "_sysFile".
if( strcmp( option, STitle ) == 0 ){
arg = _scanner.getArg( i );
if( arg != NULL ){
_sysFile->addRecord( new SystemText( HFSystem::SYS_TITLE, arg ) );
}
} else if( strcmp( option, SCopyright ) == 0 ){
arg = _scanner.getArg( i );
if( arg != NULL ){
_sysFile->addRecord( new SystemText( HFSystem::SYS_COPYRIGHT, arg ) );
}
} else if( strcmp( option, SCompress ) == 0 ){
arg = _scanner.getArg( i );
if( arg != NULL ){
if( stricmp( arg, STrue ) == 0 ||
stricmp( arg, SHigh ) == 0 ||
stricmp( arg, SMedium ) == 0 ||
stricmp( arg, SYes ) == 0 ){
_sysFile->setCompress( 1 );
} else if( stricmp( arg, SFalse ) == 0 ||
stricmp( arg, SLow ) == 0 ||
stricmp( arg, SNo ) == 0 ){
_sysFile->setCompress( 0 );
}
}
} else if( strcmp( option, SOldKeyPhrase ) == 0 ){
arg = _scanner.getArg( i );
if( arg != NULL ){
if( stricmp( arg, STrue ) == 0 ||
stricmp( arg, SYes ) == 0 ){
_oldPhrases = 1;
} else {
_oldPhrases = 0;
}
}
} else if( strcmp( option, SContents ) == 0 ||
strcmp( option, SIndex ) == 0 ){
arg = _scanner.getArg( i );
if( arg != NULL ){
_sysFile->setContents( Hash( arg ) );
}
} else if( strcmp( option, SBmRoot ) == 0 ){
arg = _scanner.getArg( i );
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?