parsing.cpp

来自「开放源码的编译器open watcom 1.6.0版的源代码」· C++ 代码 · 共 1,349 行 · 第 1/3 页

CPP
1,349
字号
    _topFile->setPar( TOP_CENTRE_JUST );
    break;


    case RC_QJ: // Normal justification
    case RC_QL: // deliberate fall-through
    _topFile->unsetPar( TOP_RIGHT_JUST );
    _topFile->unsetPar( TOP_CENTRE_JUST );
    break;


    case RC_QR: // Right Justification
    _topFile->unsetPar( TOP_CENTRE_JUST );
    _topFile->setPar( TOP_RIGHT_JUST );
    break;


    case RC_RI: // The "Right Indent" command.
    if( !_current->_hasValue ){
        HCWarning( RTF_NOARG, (const char *) _current->_text,
                   _current->_lineNum, _fname );
        _wereWarnings = 1;
    } else {
        if( !_topFile->setPar( TOP_RIGHT_INDENT, _current->_value ) ){
        HCWarning( TOP_BADARG, _current->_value, _current->_lineNum, _fname );
        _wereWarnings = 1;
        }
    }
    break;


    case RC_SA: // The "Space After Paragraph" command.
    if( !_current->_hasValue ){
        HCWarning( RTF_NOARG, (const char *) _current->_text,
                   _current->_lineNum, _fname );
        _wereWarnings = 1;
    } else {
        if( !_topFile->setPar( TOP_SPACE_AFTER, _current->_value ) ){
        HCWarning( TOP_BADARG, _current->_value, _current->_lineNum, _fname );
        _wereWarnings = 1;
        }
    }
    break;


    case RC_SB: // The "Space Before Paragraph" command.
    if( !_current->_hasValue ){
        HCWarning( RTF_NOARG, (const char *) _current->_text,
                   _current->_lineNum, _fname );
        _wereWarnings = 1;
    } else {
        if( !_topFile->setPar( TOP_SPACE_BEFORE, _current->_value ) ){
        HCWarning( TOP_BADARG, _current->_value, _current->_lineNum, _fname );
        _wereWarnings = 1;
        }
    }
    break;


    case RC_SL: // "Line Spacing".
    if( !_current->_hasValue ){
        HCWarning( RTF_NOARG, (const char *) _current->_text,
                   _current->_lineNum, _fname );
        _wereWarnings = 1;
    } else {
        if( !_topFile->setPar( TOP_LINE_SPACE, _current->_value ) ){
        HCWarning( TOP_BADARG, _current->_value, _current->_lineNum, _fname );
        _wereWarnings = 1;
        }
    }
    break;


    case RC_TAB:    // The "Tab" command. (Well, DUH! :-)
    _topFile->addAttr( TOP_HTAB );
    break;


    case RC_TQC:    // "Center tab"
    _tabType = TAB_CENTER;
    break;


    case RC_TQR:
    _tabType = TAB_RIGHT;
    break;


    case RC_TX: // "Set Tab Stop"
    if( !_current->_hasValue ){
        HCWarning( RTF_NOARG, (const char *) _current->_text,
                   _current->_lineNum, _fname );
        _wereWarnings = 1;
    } else {
        if( !_topFile->setTab( _current->_value, _tabType ) ){
        HCWarning( TOP_BADTAB, _current->_value, _current->_lineNum, _fname );
        _wereWarnings = 1;
        } else {
        _tabType = TAB_LEFT;
        }
    }
    break;


    case RC_V:  // "Start/Stop Hidden Text".
    if( !_current->_hasValue || _current->_value == 0 ){
        attribs = _fontFile->getAttribs( _curFont );
        if( attribs & FNT_UNDERLINE ){
        _linkType = POPUP;
        handleHidden(1);
        } else if( attribs & (FNT_STRIKEOUT | FNT_DBL_UNDER ) ){
        _linkType = JUMP;
        handleHidden(1);
        } else {
        handleHidden(0);
        }
    }
    break;


    default:
    HCWarning( RTF_UNKNOWN, (const char *) _current->_text,
               _current->_lineNum, _fname );
    _wereWarnings = 1;
    }
}


//  RTFparser::Go   --The parser "main loop".

#define NOT_A_BITMAP ((FontFlags) 0)

RTFparser::Go()
{
    HCStartFile( _fname );

    // Make sure the first three tokens are an RTF header.
    _input->next();
    _wereWarnings = 1;
    if( _input->look(0)->_type != TOK_PUSH_STATE ){
    HCWarning( RTF_HEADER, _fname );
    } else if( _input->look(1)->_type != TOK_COMMAND ||
               FindCommand( _input->look(1)->_text ) != RC_RTF ){
    HCWarning( RTF_RTF, _fname );
    } else if( _input->look(2)->_type != TOK_COMMAND ){
    HCWarning( RTF_CHARSET, _fname );
    } else {
    int command = FindCommand( _input->look(2)->_text );
    if( command != RC_ANSI &&
        command != RC_PC &&
        command != RC_WINDOWS ){
        HCWarning( RTF_CHARSET, _fname );
    } else {
        _wereWarnings = 0;
    }
    }
    if( _wereWarnings ){
    HCError( BAD_RTF, _fname );
    }
    _nestLevel = 1;


    // Dump the first three tokens; we don't need them anymore.
    _input->next();
    _input->next();


    uint_16 temp_font;  // for font changes
    uint_8  attribs;    // for font changes
    char    smallstr[2];    // for creating bits of text.
    smallstr[1] = '\0';

    _writeState = HEADER;

    // Loop until we 'pop' out of the main block.
    while( _nestLevel > 0 ){
    _current = _input->next();
    if( _current->_type == TOK_END ) break;
    if( _current->_type == TOK_NONE ) continue;

    switch( _current->_type ){

    case TOK_TEXT:
        // At this stage of the program, text is just
        // dumped to output.
        if( _writeState == HEADER ){
        _writeState = SCROLL;
        _topFile->newNode(0);
        _topFile->addAttr( TOP_FONT_CHANGE, _curFont );
        _topFile->startScroll();
        }
        _topFile->addText( _current->_text, 1 );
        break;


    case TOK_PUSH_STATE:
        // Store the _current font once for every consecutive '{'
        for( ;; ){
        _fontFile->push();
        ++_nestLevel;
        if( _input->look(1)->_type != TOK_PUSH_STATE ) break;
        _input->next();
        }
        break;


    case TOK_POP_STATE:
        // Restore the correct font.
        --_nestLevel;
        _fontFile->pop();
        temp_font = closeBraces();

        // If the next command is "\v" we may have just terminated
        // a hotlink.
        if( _input->look(1)->_type == TOK_COMMAND &&
        FindCommand( _input->look(1)->_text ) == RC_V &&
        ( !_input->look(1)->_hasValue ||
        _input->look(1)->_value != 0 ) ){
        attribs = _fontFile->getAttribs( _curFont );
        if( attribs & FNT_UNDERLINE ){
            _linkType = POPUP;
            handleHidden(1);
        } else if( attribs & (FNT_STRIKEOUT | FNT_DBL_UNDER ) ){
            _linkType = JUMP;
            handleHidden(1);
        } else {
            handleHidden(0);
        }
        } else if( temp_font != _curFont ){

        // We may also be just starting a hotlink.
        _lastFont = _curFont;
        _curFont = temp_font;
        int attr = _topFile->addAttr( TOP_FONT_CHANGE,
                           _curFont );
        attribs = _fontFile->getAttribs( _curFont );
        if( attribs & ( FNT_UNDERLINE | FNT_STRIKEOUT |
            FNT_DBL_UNDER ) ){
            _hotlinkStart = attr;
        }
        }
        break;


    case TOK_SPEC_CHAR:
        // This character may start a footnote.
        if( _input->isFootnoteChar( (char) _current->_value ) ){
        if( _input->look(1)->_type == TOK_PUSH_STATE &&
            _input->look(2)->_type == TOK_COMMAND    &&
            FindCommand( _input->look(2)->_text ) == RC_FOOTNOTE ){
            char fchar = (char) _current->_value;
            _input->next();
            _input->next();
            handleFootnote( fchar );
        } else {
            smallstr[0] = (char) _current->_value;
            _topFile->addText( smallstr );
        }
        } else if( _current->_value == '{' &&
               _input->look(1)->_type == TOK_TEXT &&
               _input->look(2)->_type == TOK_SPEC_CHAR &&
               _input->look(2)->_value == '}' ){

        // We must perform a special check for the
        // "\{bm* image_file\}" construct.

        char const  *string = _input->look(1)->_text;
        uint_16     bmnum;

        FontFlags   bmtype = NOT_A_BITMAP;

        if( strncmp( string, "bmc ", 4 ) == 0 ){
            bmtype = TOP_CENT_BITMAP;
        } else if( strncmp( string, "bml ", 4 ) == 0 ){
            bmtype = TOP_LEFT_BITMAP;
        } else if( strncmp( string, "bmr ", 4 ) == 0 ){
            bmtype = TOP_RIGHT_BITMAP;
        }

        if( bmtype != NOT_A_BITMAP ){
            string += 4;
            while( isspace( *string ) ){
            string++;
            }
            try{
            bmnum = _bitFiles->use( string );
            _topFile->addAttr( bmtype, bmnum );
            } catch( HFBitmaps::ImageNotFound ){
            HCWarning( RTF_NOSUCHIMAGE, string, _current->_lineNum, _fname );
            _wereWarnings = 1;
            } catch( HFBitmaps::ImageNotSupported ){
            HCWarning( UNKNOWN_IMAGE, string, _current->_lineNum, _fname );
            _wereWarnings = 1;
            } catch( HFBitmaps::ImageNotValid ){
            HCWarning( RTF_USEDBADIMAGE, string, _current->_lineNum, _fname );
            _wereWarnings = 1;
            }

            _input->next();
            _input->next();
        } else {
            smallstr[0] = '{';
            _topFile->addText( smallstr );
        }
        } else {
        if( _current->_value == '~' ){
            smallstr[0] = (char) 0xA0;
        } else {
            smallstr[0] = (char) _current->_value;
        }
        _topFile->addText( smallstr );
        }
        break;


    case TOK_COMMAND:
        // For font commands, we go through the same junk as for
        // TOK_POP_STATE.  Other commands go to handleCommand().
        temp_font = _curFont;
        if( isFontCommand( _current, &temp_font ) ){
        if( _writeState == HEADER ){
            _topFile->newNode(0);
            _topFile->addAttr( TOP_FONT_CHANGE, _curFont );
            _topFile->startScroll();
            _writeState = SCROLL;
        }
        temp_font = closeBraces();
        if( _input->look(1)->_type == TOK_COMMAND &&
            FindCommand( _input->look(1)->_text ) == RC_V &&
            ( !_input->look(1)->_hasValue ||
            _input->look(1)->_value != 0 ) ){
            attribs = _fontFile->getAttribs( _curFont );
            if( attribs & FNT_UNDERLINE ){
            _linkType = POPUP;
            handleHidden(1);
            } else if( attribs & (FNT_STRIKEOUT | FNT_DBL_UNDER ) ){
            _linkType = JUMP;
            handleHidden(1);
            } else {
            handleHidden(0);
            }
        } else if( temp_font != _curFont ){
            _lastFont = _curFont;
            _curFont = temp_font;
            int attr = _topFile->addAttr( TOP_FONT_CHANGE,
                                               _curFont );
            attribs = _fontFile->getAttribs( _curFont );
            if( attribs & ( FNT_UNDERLINE | FNT_STRIKEOUT |
                FNT_DBL_UNDER ) ){
            _hotlinkStart = attr;
            }
        }
        } else {
        handleCommand();
        }
        break;
    }
    }

    // Now we clean up...check the nesting level, close the topic text...
    if( _nestLevel != 0 ){
    HCWarning( RTF_BADEOF, _fname );
    _wereWarnings = 1;
    } else {
    do{
        _current = _input->next();
    } while( _current->_type == TOK_NONE );
    if( _current->_type != TOK_END ){
        HCWarning( RTF_EXTRATEXT, _fname );
        _wereWarnings = 1;
    }
    }
    _fontFile->clearFonts();
    _topFile->newNode(1);
    HCDoneTick();

    if( _wereWarnings ){
    HCWarning( PROBLEM_RTF, _fname );
    _wereWarnings = 1;
    }
}


//  RTFparser::skipSpaces   --utility function to skip whitespace.

char *RTFparser::skipSpaces( char * start )
{
    while( isspace( *start ) ){
    start++;
    }
    return start;
}


//  RTFparser::handleFootnote   --Footnotes signal all sorts of things
//                in a HLP file.

void RTFparser::handleFootnote( char Fchar )
{
    // store the text of the footnote in a buffer
    _storSize = 0;
    for( ;; ){
    _current = _input->next();
    if( _current->_type == TOK_POP_STATE ||
        _current->_type == TOK_END ) break;

    if( _current->_type == TOK_TEXT ){
        if( _storSize + _current->_value + 1 >= _maxStor ){
        _maxStor = (_storSize+_current->_value+1) / BLOCK_SIZE + 1;
        _maxStor *= BLOCK_SIZE;
        _storage.resize( _maxStor );
        }
        memcpy( _storage+_storSize, _current->_text, _current->_value );
        _storSize += _current->_value;
    } else if( _current->_type == TOK_SPEC_CHAR ){
        if( _storSize + 2 >= _maxStor ){
        _maxStor += BLOCK_SIZE;
        _storage.resize( _maxStor );
        }
        _storage[_storSize++] = (char) _current->_value;
    }
    }
    if( _current->_type == TOK_END ){
    HCWarning( RTF_BADEOF, _fname );
    _wereWarnings = 1;
    return;
    }

    _storage[_storSize] = '\0';

    // parse the footnote string according to the footnote character.
    char *start = _storage;
    if( *start == Fchar ) ++start;
    char *end;
    int finished = 0;
    switch( Fchar ){

    case '#':   // Context string
    start = skipSpaces( start );
    if( *start == '\0' ){
        HCWarning( CON_MISSING, _current->_lineNum, _fname );
        _wereWarnings = 1;
        break;
    }
    end = start;
    while( *end != '\0' && !isspace( *end ) ){
        if( !isalnum( *end ) && *end != '.' && *end != '_' ){
        HCWarning( CON_BADCHAR, _current->_lineNum, _fname );
        _wereWarnings = 1;
        break;

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?