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