TokenTypes Scanner::handleSlash( Token * tok ) { TokenTypes result; int current = nextch(); if( current == S_ENDC ) { HCWarning( RTF_BADEOF, _source->name() ); result = TOK_END; } else if( current == '*' ) { // Certain RTF commands begin with "\*\", not "\". current = nextch(); if( current != '\\' ) { HCWarning( RTF_BADCOMMAND, _lineNum, _source->name() ); if( current != S_ENDC ) { putback( current ); } result = TOK_NONE; } else { result = handleSlash( tok ); } } else if( current == '\n' ) { // A "\" just before a new-line is the same as "\par". memcpy( tok->_text, "par", 4 ); result = TOK_COMMAND; ++_lineNum; } else if( isSpecial( current ) ) { // Some characters are escaped, like "\{". result = TOK_SPEC_CHAR; tok->_value = current; } else if( current == '\'' ) { // "\'nnn" signifies the byte with value nnn. result = TOK_SPEC_CHAR; pullHex( tok ); } else if( islower( current ) ) { // All RTF commands are in lower case. putback( current ); result = TOK_COMMAND; pullCommand( tok ); } else { HCWarning( RTF_BADCOMMAND, _lineNum, _source->name() ); result = TOK_NONE; } return( result ); }
void HFBitmaps::note( char const name[] ) { Image *current; StrNode *curdir = _root; uint_16 magic; InFile *bmp = new InFile( name, 1 ); while( bmp->bad() && curdir != NULL ){ chdir( curdir->_name ); curdir = curdir->_next; bmp->open( name ); chdir( _startDir ); } if( bmp->bad() ){ HCWarning( FILE_ERR, name ); delete bmp; return; } bmp->reset(); bmp->readbuf( &magic, 1, 2 ); switch( magic ){ case BITMAP_MAGIC: case SHG1_MAGIC: case SHG2_MAGIC: break; default: throw ImageNotSupported(); // EXCEPTION } bmp->reset(); current = new Image; current->_name = new char[strlen(name)+1]; strcpy( current->_name, name ); current->_next = _files; _files = current; if( magic == BITMAP_MAGIC ){ current->_image = new Bitmap(bmp); } else { current->_image = new SegGraph(bmp); } if( !current->_image->validImage() ){ // Keep the bad image in the list for reference, // but warn the user. HCWarning( HLP_BADIMAGE, current->_name ); } return; }
int HPJReader::handleMap() { int result; char *token; uint_32 hash_value; int con_num; int is_good_string, i; for( ;; ){ result = _scanner.getLine(); if( !result || _scanner[0] == '[' ) break; token = _scanner.tokLine(); if( token == NULL ) continue; // "#include" means go to another file. if( stricmp( token, Sinclude ) == 0 ){ includeMapFile( _scanner.endTok() ); continue; } // "#define" is an optional header, ignore it. if( stricmp( token, Sdefine ) == 0 ){ token = _scanner.tokLine(); } if( token == NULL ) continue; // verify that the current token at this point is a context string. is_good_string = 1; for( i=0; token[i] != '\0'; ++i ){ if( !isalnum( token[i] ) && token[i] != '.' && token[i] != '_' ){ is_good_string = 0; } } if( !is_good_string ){ HCWarning( CON_BAD, token, _scanner.lineNum(), _scanner.name() ); } else { // Associate the context string with a context number. hash_value = Hash(token); token = _scanner.tokLine(); if( token == NULL ){ HCWarning( CON_NONUM, token, _scanner.lineNum(), _scanner.name() ); } else { con_num = atol( token ); _theFiles->_mapFile->addMapRec( con_num, hash_value ); } } } return result; }
int HFContext::dump( OutFile * dest ) { FutureHash *current = _head; while( current != NULL ){ HCWarning( HLP_NOTOPIC, (const char *)current->_string ); current = current->_next; } return _data->dump( dest ); }
void HFBitmaps::addToPath( char const path[] ) { char const *arg = path; if( arg == NULL ) return; StrNode *current, *temp; // Update the search paths. current = _root; if( current != NULL ) { while( current->_next != NULL ) { current = current->_next; } } // There may be many directories specified on each line. int j; while( arg[0] != '\0' ) { j = 0; while( arg[j] != '\0' && arg[j] != ',' && arg[j] != ';' ) { ++j; } temp = new StrNode; temp->_name = new char[j + 1]; memcpy( temp->_name, arg, j ); temp->_name[j] = '\0'; temp->_next = NULL; if( chdir( temp->_name ) == 0 ) { chdir( _startDir ); if( current == NULL ) { _root = temp; current = _root; } else { current->_next = temp; current = current->_next; } } else { HCWarning( HPJ_BADDIR, temp->_name ); delete[] temp->_name; delete temp; } arg += j; if( arg[0] != '\0' ) { ++arg; } } }
int HPJReader::handleBitmaps() { int result; int i; for( ;; ){ result = _scanner.getLine(); if( !result || _scanner[0] == '[' ) break; for( i=0; _scanner[i] != '\0'; i++ ){ if( !isspace( _scanner[i] ) ) break; } if( _scanner[i] == '\0' ) continue; try{ _theFiles->_bitFiles->note( &_scanner[i] ); } catch( HFBitmaps::ImageNotSupported ) { HCWarning( UNKNOWN_IMAGE, &_scanner[0], _scanner.lineNum(), _scanner.name() ); } } return result; }
uint_32 HFCtxomap::size() { CmapRec *current = _firstRec; uint_32 true_offset; if( !_resolved ){ while( current != NULL ){ true_offset = _offsetFile->getOffset( current->_offset ); if( true_offset == HFContext::_badValue ){ char str[16] = "MAP number "; ltoa( current->_mapnum, str+11, 10 ); HCWarning( HLP_NOTOPIC, (const char *) str ); } else { current->_offset = true_offset; } current = current->_nextRec; } _resolved = 1; } return _size; }
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; }
int main( int argc, char *[] ) { if( argc < 2 || argc > 3 ) { HCWarning( USAGE ); return( -1 ); } // Parse the command line. char cmdline[80]; char *pfilename, *temp; int quiet = 0; getcmd( cmdline ); temp = cmdline; pfilename = NULL; while( *temp != '\0' && isspace( *temp ) ) { temp++; } if( *temp == '-' || *temp == '/' ) { temp++; if( (*temp != 'q' && *temp != 'Q') || !isspace( *(temp+1) ) ) { HCWarning( USAGE ); return( -1 ); } else { quiet = 1; temp++; while( *temp != '\0' && isspace( *temp ) ) { temp++; } if( *temp == '\0' ) { HCWarning( USAGE ); return( -1 ); } else { pfilename = temp; } } } else if( *temp != '\0' ) { pfilename = temp++; while( *temp != '\0' && *temp != '/' && *temp != '-' ) { temp++; } if( *temp != '\0' ) { *temp = '\0'; temp++; if( *temp != 'q' && *temp != 'Q' ) { HCWarning( USAGE ); return( -1 ); } else { temp++; while( *temp != '\0' && isspace( *temp ) ) { temp++; } if( *temp != '\0' ){ HCWarning( USAGE ); return( -1 ); } else { quiet = 1; } } } } SetQuiet( quiet ); // Parse the given filename. char path[_MAX_PATH]; char drive[_MAX_DRIVE]; char dir[_MAX_DIR]; char fname[_MAX_FNAME]; char ext[_MAX_EXT]; _fullpath( path, pfilename, _MAX_PATH ); _splitpath( path, drive, dir, fname, ext ); if( stricmp( ext, PhExt ) == 0 || stricmp( ext, HlpExt ) == 0 ) { HCWarning( BAD_EXT ); return( -1 ); } if( ext[0] == '\0' ){ _makepath( path, drive, dir, fname, HpjExt ); } char destpath[_MAX_PATH]; _makepath( destpath, drive, dir, fname, HlpExt ); InFile input( path ); if( input.bad() ) { HCWarning( FILE_ERR, pfilename ); return( -1 ); } // Set up and start the help compiler. try { HFSDirectory helpfile( destpath ); HFFont fontfile( &helpfile ); HFContext contfile( &helpfile ); HFSystem sysfile( &helpfile, &contfile ); HFCtxomap ctxfile( &helpfile, &contfile ); HFTtlbtree ttlfile( &helpfile ); HFKwbtree keyfile( &helpfile ); HFBitmaps bitfiles( &helpfile ); Pointers my_files = { NULL, NULL, &sysfile, &fontfile, &contfile, &ctxfile, &keyfile, &ttlfile, &bitfiles, }; if( stricmp( ext, RtfExt ) == 0 ) { my_files._topFile = new HFTopic( &helpfile ); RTFparser rtfhandler( &my_files, &input ); rtfhandler.Go(); } else { HPJReader projfile( &helpfile, &my_files, &input ); projfile.parseFile(); } helpfile.dump(); if( my_files._topFile != NULL ) { delete my_files._topFile; } if( my_files._phrFile != NULL ) { delete my_files._phrFile; } } catch( HCException ) { HCWarning( PROGRAM_STOPPED ); return( -1 ); } return( 0 ); }
void HPJReader::includeMapFile( char i_str[] ) { int i = 0; char seek_char; // Get the filename. while( i_str[i] != '\0' && isspace( i_str[i] ) ){ ++i; } switch( i_str[i] ){ case '"': seek_char = '"'; break; case '<': seek_char = '>'; break; default: HCWarning( HPJ_BADINCLUDE, _scanner.lineNum(), _scanner.name() ); return; } ++i; int j = i; while( i_str[j] != '\0' && i_str[j] != seek_char ){ ++j; } if( j == '\0' ){ HCWarning( HPJ_BADINCLUDE, _scanner.lineNum(), _scanner.name() ); return; } // Now try to find it in the ROOT path and/or current directory. i_str[j] = '\0'; StrNode *current = _root; InFile source; if( current == NULL ){ source.open( i_str+i ); } else while( current != NULL ){ chdir( current->_name ); source.open( i_str+i ); chdir( _homeDir ); if( !source.bad() ) break; current = current->_next; } if( source.bad() ){ HCWarning(INCLUDE_ERR, (const char *) (i_str+i), _scanner.lineNum(), _scanner.name() ); return; } HCStartFile( i_str+i ); // Now parse the secondary file. HPJScanner input( &source ); int not_done; char *token; int is_good_str, con_num; uint_32 hash_value; for( ;; ){ not_done = input.getLine(); if( !not_done ) break; token = input.tokLine(); if( stricmp( token, Sinclude ) == 0 ){ // "#include" directives may be nested. includeMapFile( input.endTok() ); continue; } else if( stricmp( token, Sdefine ) == 0 ){ // "#define" directives specify a context string. token = input.tokLine(); if( token == NULL ) continue; is_good_str = 1; for( i=0; token[i] != '\0'; ++i ){ if( !isalnum( token[i] ) && token[i] != '.' && token[i] != '_' ){ is_good_str = 0; } } if( !is_good_str ){ HCWarning( CON_BAD, token, input.lineNum(), input.name() ); } else { hash_value = Hash(token); token = input.tokLine(); if( token == NULL ){ HCWarning( CON_NONUM, token, input.lineNum(), input.name() ); } else { con_num = atol( token ); _theFiles->_mapFile->addMapRec( con_num, hash_value ); } } } else if( strncmp( token, SstartComment, 2 ) == 0 ){ // #include-d files may contain comments. int startcomment = input.lineNum(); while( token != NULL && strstr( token, SendComment ) == NULL ){ do{ token = input.tokLine(); if( token != NULL ) break; not_done = input.getLine(); } while( not_done ); } if( token == NULL ){ HCWarning( HPJ_RUNONCOMMENT, startcomment, input.name() ); break; } } else { HCWarning( HPJ_INC_JUNK, input.lineNum(), input.name() ); continue; } } HCDoneTick(); return; }
int HPJReader::handleWindows() { int result; int i, limit; char *arg; int bad_param; int red, green, blue; uint_16 wflags; char name[HLP_SYS_NAME]; char caption[HLP_SYS_CAP]; uint_16 x = 0; uint_16 y = 0; uint_16 width = 0; uint_16 height = 0; uint_16 use_max_flag = 0; uint_32 rgb_main, rgb_nonscroll; for( ; (result = _scanner.getLine()) != 0; ) { if( _scanner[0] == '[' ) break; limit = HLP_SYS_NAME-1; if( limit > result-1 ){ limit = result-1; } for( i=0; i<limit && !isspace(_scanner[i]) && _scanner[i] != '=' ; i++ ) { name[i] = _scanner[i]; } if( i == result-1 ){ HCWarning( HPJ_INCOMPLETEWIN, _scanner.lineNum(), _scanner.name() ); continue; } else if( i == HLP_SYS_NAME ){ HCWarning( HPJ_LONGWINNAME, _scanner.lineNum(), _scanner.name() ); } name[i] = '\0'; while( i<result-1 && !isspace(_scanner[i]) ){ i++; } arg = _scanner.getArg(i); if( arg == NULL || *arg == '\0' ){ HCWarning( HPJ_INCOMPLETEWIN, _scanner.lineNum(), _scanner.name() ); continue; } wflags = VALID_TYPE | VALID_NAME; _winParamBuf = arg; arg = nextWinParam(); if( *arg != '\0' ){ i = 0; if( *arg == '"' ){ arg++; } while( i<HLP_SYS_CAP-1 && *arg != '\0' && *arg != '"' ){ caption[i++] = *arg++; } caption[i] = '\0'; wflags |= VALID_CAPTION; } bad_param = 0; arg = nextWinParam(); if( *arg != '\0' ){ x = (uint_16) strtol( arg, NULL, 0 ); if( x > PARAM_MAX ){ bad_param = 1; } else { wflags |= VALID_X; } } arg = nextWinParam(); if( *arg != '\0' ){ y = (uint_16) strtol( arg, NULL, 0 ); if( y > PARAM_MAX ){ bad_param = 1; } else { wflags |= VALID_Y; } } arg = nextWinParam(); if( *arg != '\0' ){ width = (uint_16) strtol( arg, NULL, 0 ); if( width > PARAM_MAX ){ bad_param = 1; } else { wflags |= VALID_WIDTH; } } arg = nextWinParam(); if( *arg != '\0' ){ height = (uint_16) strtol( arg, NULL, 0 ); if( height > PARAM_MAX ){ bad_param = 1; } else { wflags |= VALID_HEIGHT; } } if( bad_param ){ HCWarning( HPJ_WINBADPARAM, _scanner.lineNum(), _scanner.name() ); continue; } arg = nextWinParam(); if( *arg != '\0' ){ use_max_flag = (uint_16) strtol( arg, NULL, 0 ); wflags |= VALID_MAX; } red = green = blue = 0; bad_param = 0; arg = nextWinParam(); if( *arg != '\0' ){ red = strtol( arg, NULL, 0 ); if( red < 0 || red > 255 ){ bad_param = 1; } wflags |= VALID_RGB1; } arg = nextWinParam(); if( *arg != '\0' ){ green = strtol( arg, NULL, 0 ); if( green < 0 || green > 255 ){ bad_param = 1; } wflags |= VALID_RGB1; } arg = nextWinParam(); if( *arg != '\0' ){ blue = strtol( arg, NULL, 0 ); if( blue < 0 || blue > 255 ){ bad_param = 1; } wflags |= VALID_RGB1; } if( bad_param ){ HCWarning( HPJ_WINBADCOLOR, _scanner.lineNum(), _scanner.name() ); continue; } else { rgb_main = (uint_32) (red + (green<<8) + (blue<<16)); } red = green = blue = 0; bad_param = 0; arg = nextWinParam(); if( *arg != '\0' ){ red = strtol( arg, NULL, 0 ); if( red < 0 || red > 255 ){ bad_param = 1; } wflags |= VALID_RGB2; } arg = nextWinParam(); if( *arg != '\0' ){ green = strtol( arg, NULL, 0 ); if( green < 0 || green > 255 ){ bad_param = 1; } wflags |= VALID_RGB2; } arg = nextWinParam(); if( *arg != '\0' ){ blue = strtol( arg, NULL, 0 ); if( blue < 0 || blue > 255 ){ bad_param = 1; } wflags |= VALID_RGB2; } if( bad_param ){ HCWarning( HPJ_WINBADCOLOR, _scanner.lineNum(), _scanner.name() ); continue; } else { rgb_nonscroll = (uint_32) (red + (green<<8) + (blue<<16)); } arg = nextWinParam(); if( *arg != 0 || strtol( arg, NULL, 0 ) != 0 ){ wflags |= VALID_ONTOP; } if( strcmp( name, Smain ) == 0 ){ _sysFile->addRecord( new SystemWin( wflags, Smain, name, caption, x, y, width, height, use_max_flag, rgb_main, rgb_nonscroll ) ); } else { _sysFile->addRecord( new SystemWin( wflags, Ssecondary, name, caption, x, y, width, height, use_max_flag, rgb_main, rgb_nonscroll ) ); } } return result; }
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 ); _theFiles->_bitFiles->addToPath( arg ); } else if( strcmp( option, SRoot ) == 0 ){ // Update the search paths. arg = _scanner.getArg( i ); StrNode *current; current = _root; if( current != NULL ){ while( current->_next != NULL ){ current = current->_next; } } // There may be many directories specified on each line. if( arg != NULL ){ int j; StrNode *temp; while( arg[0] != '\0' ){ j = 0; while( arg[j] != '\0' && arg[j] != ',' && arg[j] != ';' ){ ++j; } temp = new StrNode; temp->_name = new char[ j+1 ]; strncpy( temp->_name, arg, j ); temp->_name[j] = '\0'; temp->_next = NULL; if( chdir( temp->_name ) == 0 ){ chdir( _homeDir ); if( current == NULL ){ _root = temp; current = _root; } else { current->_next = temp; current = current->_next; } } else { HCWarning( HPJ_BADDIR, temp->_name ); delete[] temp->_name; delete temp; } arg += j; if( arg[0] != '\0' ) ++arg; } } } } return result; }
void 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; } }