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 + -
显示快捷键?