| home
| contents
| previous
| next page
| send comment
| send link
| add bookmark |
makehelp.cpp
/*-------------------------------------------------------------------------*
MAKEHELP.CPP
creates a data file from a text file for use by the
on-line help module 'timehelp'
a topic must begin with a line: #<topic name>$
the last line of source text must be: #INDEX$
by: Stephen R. Schmitt
*-------------------------------------------------------------------------*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct node
{
node *left; // ptr to left node
node *right; // ptr to right node
char *name; // ptr to topic string
long offset; // file offset of topic
}
NODE;
NODE *Topic_table = NULL;
NODE Topic_list[1024];
int Topic = 0;
/*-------------------------------------------------------------------------*
* "lookup" searches for an identifier in the symbol table.
* A pointer is returned if the identifier is found; NULL if not.
*
* returns: a pointer to the symbol table entry or NULL
*/
NODE *lookup( char *name, // of topic
NODE *idp ) // of symbol table
{
int cmp;
while( idp != NULL ) // another branch?
{
cmp = strcmp( name, idp->name );
if( cmp == 0 )
return( idp ); // found match
if( cmp < 0 )
idp = idp->left;
else
idp = idp->right;
}
return( NULL ); // if name not found
}
/*-------------------------------------------------------------------------*
* "insert" puts a new name into the symbol table.
*
* WARNING: Before using this function, "lookup" must return NULL.
*
* returns: a pointer to the symbol table entry
*/
NODE *insert( char *name, // of topic
NODE **idpp ) // of symbol table
{
int cmp;
NODE *new_idp, *idp;
/*
* create a new node for the identifier
*/
new_idp = (NODE *)calloc( 1, sizeof( NODE ) );
if( new_idp == NULL )
{
printf( "Error: OUT OF MEMORY\n" );
exit( 0 );
}
/*
* initialize
*/
new_idp->left = NULL;
new_idp->right = NULL;
new_idp->name = (char *)calloc( 1, strlen( name ) + 1 );
strcpy( new_idp->name, name );
idp = *idpp; // initial node pointer
/*
* now search for insertion point
*/
while( idp != NULL )
{
cmp = strcmp( name, idp->name );
if( cmp < 0 )
idpp = &(idp->left);
else
idpp = &(idp->right);
idp = *idpp;
}
/*
* set left/right pointer to new_idp
*/
*idpp = new_idp;
return( new_idp );
}
/*-------------------------------------------------------------------------*
* "create_topic_table" reads a text file and builds a linked list of
* topic titles.
*
* returns: length of text file
*/
long create_topic_table( FILE *txt ) // source file
{
int i, line, target;
long offset;
NODE *idp; // for node creation
char buffer[80];
offset = 0;
line = 0;
while( fgets( buffer, 80, txt ) )
{
line++;
offset += strlen( buffer ) + 1;
target = 0;
if( buffer[0] == '#' )
{
for( i = 0; i < 80; i++ )
{
if( buffer[i+1] == '$' )
{
buffer[i] = 0;
target = 1;
break;
}
else
buffer[i] = buffer[i+1];
}
if( !target )
printf( "-#- without matching -$- line %d\n", line );
else
{
printf( "topic -%s- offset %d\n",
buffer, offset );
idp = lookup( buffer, Topic_table );
if( idp == NULL )
{
idp = insert( buffer, &Topic_table );
idp->offset = offset;
}
else
printf( "duplicate topic -%s- line %d\n",
buffer, line );
// stop when end of source is reached
if( !strcmp( "INDEX", buffer ) )
break;
}
}
}
return( offset );
}
/*-------------------------------------------------------------------------*
* "verify_jumps" re-reads a text file and checks that a topic exists
* for each jump.
*
* returns: nothing
*/
void verify_jumps( FILE *txt ) // source file
{
int line, jump;
char *p, *beg, *end;
NODE *idp; // for node creation
char topic[80];
char buffer[80];
rewind( txt );
line = 0;
while( fgets( buffer, 80, txt ) )
{
line++;
jump = 0;
p = buffer;
while( *p && *p != '\n' )
{
if( *p == '@' )
{
p++;
beg = p;
jump = 1;
}
else if( *p == '$' )
{
if( jump )
{
end = p;
memset( topic, 0, 32 );
strncpy( topic, beg, (int)(end - beg) );
idp = lookup( topic, Topic_table );
if( !idp )
printf( "jump to non-existant topic -%s- line %d\n",
topic, line );
}
p++;
jump = 0;
}
p++;
}
if( jump )
printf( "-@- without matching -$- line %d\n", line );
}
}
/*-------------------------------------------------------------------------*
* "traverse" steps through the doubly linked list and creates a topic
* list in alphabetical order.
*
* returns: nothing
*/
void traverse( NODE *idp )
{
if( idp )
{
traverse( idp->left );
Topic_list[Topic] = *idp;
Topic++;
traverse( idp->right );
}
}
/*-------------------------------------------------------------------------*
* "make_jump_table" generates a jump table which consists of topic names
* and file offset values to be used in the help application to locate
* topics.
*
* returns: nothing
*/
void make_jump_table( FILE *hlp, // output file
long len ) // of input file
{
int i;
for( i = 0; i < Topic; i++ )
{
if( strcmp( "INDEX", Topic_list[i].name ) )
{
fprintf( hlp,
"<%s>%ld\n",
Topic_list[i].name,
Topic_list[i].offset );
}
}
fprintf( hlp, "<>%ld\n", len ); // jump to index
}
/*-------------------------------------------------------------------------*
* "append_topic_text" copies a text file to the help data file
*
* returns: nothing
*/
void append_topic_text( FILE *hlp, // help data file
FILE *txt ) // source text file
{
char buffer[80];
rewind( txt );
while( fgets( buffer, 80, txt ) )
{
if( !strncmp( "#INDEX$", buffer, 7 ) )
break;
fputs( buffer, hlp );
}
}
/*-------------------------------------------------------------------------*
* "append_index" generates text for an index which is appended to the
* help data file
*
* returns: nothing
*/
void append_index( FILE *hlp ) // output file
{
int i;
fprintf( hlp, "#INDEX$\n" );
fprintf( hlp, "Topic index\n\n" );
for( i = 0; i < Topic; i++ )
{
if( strcmp( "INDEX", Topic_list[i].name ) )
{
fprintf( hlp,
" @%s$\n",
Topic_list[i].name );
}
}
}
/*-------------------------------------------------------------------------*
* "main" make help entry point
*
* returns: non-zero on error
*/
int main( int argc, char *argv[] )
{
FILE *txt, *hlp;
long length;
if( argc == 3 )
{
txt = fopen( argv[1], "r" );
if( !txt )
{
printf( "could not open input file -%s-\n", argv[1] );
exit( 1 );
}
hlp = fopen( argv[2], "w" );
if( !txt )
{
printf( "could not open output file -%s-\n", argv[2] );
exit( 1 );
}
}
else
{
printf( "usage: makehelp <input file> <output file>\n" );
exit( 1 );
}
length = create_topic_table( txt );
verify_jumps( txt );
traverse( Topic_table );
make_jump_table( hlp, length );
append_topic_text( hlp, txt );
append_index( hlp );
fclose( txt );
fclose( hlp );
}
| home
| contents
| previous
| next page
| send comment
| send link
| add bookmark |
Copyright © 2004, Stephen R. Schmitt