Sophie

Sophie

distrib > Mandriva > 2010.0 > i586 > by-pkgid > bb2b3181a15385f4d6701135404d7ec7 > files > 61

drakx-autoinstall-doc-10.0.3-6mdv2010.0.noarch.rpm

/*
 *      File:   so_split.c
 *      Date:   2004-02-21
 *
 *      This program is used to split the Open/Star Office HTML file
 *      into seperate files at the H1 level and H2 for a specific
 *      section (Split_Section_Title).
 *
 *      Copyright 2001,2002,2003,2004 David Eastcott <david@eastcott.net>
 *      Released under terms of GPL
 *
 */

#include "stdio.h"
#include "string.h"
#include "stdlib.h"
#include "ctype.h"
#include "so_split.h"

// Local Global Data
static  char    Document_Title[TITLE_NAME_SIZE+2];
static  char    Target_Dir[FILE_NAME_SIZE+2];
static char next_line_buffer[BUFFER_SIZE+1];


//
static  void    add_end_file( FILE *pout )
{

        fputs( "</BODY>\n", pout );
        fputs( "</HTML>\n", pout );
}

//
static  void    add_end_leader( FILE *pout, SECTION_INFO *section_info )
{
    char    **html;                 // raw HTML
    int     length;

    html = end_leader;
    length = strlen ( Target_Dir );

    while ( *html != (char *)NULL )
    {
        if ( (strcmp( *html, "PREV" )) == 0 )
        { // insert previous document reference if any

            if ( section_info->prvs != NULL )
            {
                fputs( HREF_TAG, pout );
                fputs( &section_info->prvs->filename[length], pout );
                fputs( HREF_TAG_END, pout );
                fputs( "Prev", pout );
                fputs( ANCHOR_TAG_END, pout );
                fputs( TABLE_CELL_TAG_END, pout );
            }

            else
            {
                fputs( "Prev", pout );
                fputs( TABLE_CELL_TAG_END, pout );
            }
        }

        else if ( (strcmp( *html, "NEXT" )) == 0 )
        { // insert next document reference if any

            if ( section_info->pfwd != NULL )
            {
                fputs( HREF_TAG, pout );
                fputs( &section_info->pfwd->filename[length], pout );
                fputs( HREF_TAG_END, pout );
                fputs( "Next", pout );
                fputs( ANCHOR_TAG_END, pout );
                fputs( TABLE_CELL_TAG_END, pout );
            }

//          else
//              fputs( "Next</td>", pout );
        }

        else if ( (strcmp( *html, "PREVIOUS_SECTION" )) == 0 )
        { // insert previous document title

            if ( section_info->prvs != NULL )
            {

                if( section_info->prvs->title[0] != 0 )
                    fputs( section_info->prvs->title, pout );
            }
        }

        else if ( (strcmp( *html, "NEXT_SECTION" )) == 0 )
        { // insert next document title

            if ( section_info->pfwd != NULL )
            {

                if( section_info->pfwd->title[0] != 0 )
                    fputs( section_info->pfwd->title, pout );
            }
        }

        else
            fputs( *html, pout );

        // next string
        html++;
    };
}

//
static  void    add_head_file( FILE *pout )
{
    FILE    *pin;
    char    line_buffer[BUFFER_SIZE+1];     // working line buffer
    char    filename[FILE_NAME_SIZE+1];

    strcpy( filename, Target_Dir );
    strcat( filename, HEAD_FILE );
    pin = fopen( filename, "r" );

    while( (fgets( line_buffer, BUFFER_SIZE, pin )) != NULL )
    {
        fputs( line_buffer, pout );
    };

    // clean up
    fclose ( pin );
}

//
static  void    add_head_leader( FILE *pout, SECTION_INFO *section_info )
{
    char    **html;                 // raw HTML
    int     length;

    html = head_leader;
    length = strlen ( Target_Dir );

    while ( *html != (char *)NULL )
    {
        if ( (strcmp( *html, "TITLE" )) == 0 )
        { // insert document title

            if( Document_Title[0] != 0 )
                fputs( Document_Title, pout );
        }

        else if ( (strcmp( *html, "PREV" )) == 0 )
        { // insert previous document reference if any

            if ( section_info->prvs != NULL )
            {
                fputs( HREF_TAG, pout );
                fputs( &section_info->prvs->filename[length], pout );
                fputs( HREF_TAG_END, pout );
                fputs( "Prev", pout );
                fputs( ANCHOR_TAG_END, pout );
                fputs( TABLE_CELL_TAG_END, pout );
            }

            else
            {
                fputs( "Prev", pout );
                fputs( TABLE_CELL_TAG_END, pout );
            }
        }

        else if ( (strcmp( *html, "NEXT" )) == 0 )
        { // insert next document reference if any

            if ( section_info->pfwd != NULL )
            {
                fputs( HREF_TAG, pout );
                fputs( &section_info->pfwd->filename[length], pout );
                fputs( HREF_TAG_END, pout );
                fputs( "Next", pout );
                fputs( ANCHOR_TAG_END, pout );
                fputs( TABLE_CELL_TAG_END, pout );
            }

//          else
//              fputs( "Next</td>", pout );
        }

        else
            fputs( *html, pout );

        // next string
        html++;
    };
}
//
static  void    add_to_queue ( SECTION_INFO **section_info_queue, SECTION_INFO *section_info )
{
    SECTION_INFO    *pnext;

    // if queue is empty, put item at head
    if( *section_info_queue == NULL )
    {
        *section_info_queue = section_info;
        section_info->pfwd = NULL;
        section_info->prvs = NULL;
    }

    else
    { // move down the chain till we get to last item

        for( pnext = *section_info_queue;
             pnext->pfwd != NULL;
             pnext = pnext->pfwd )
            ;

        // make new item as the last in the chain
        pnext->pfwd = section_info;

        // make sure the new item does not point to junk
        section_info->pfwd = NULL;
        section_info->prvs = pnext;
    }
}

//
static  void    add_to_symbols( SYMBOL_TABLE *symbol, SYMBOL_QUEUE *symbol_queue )
{
    if ( symbol_queue->head == NULL )
    { // insert symbol at head of queue

        symbol_queue->head = symbol;
        symbol_queue->tail = symbol;

        symbol->pfwd = NULL;
    }

    else
    { // add new symbol to tail, updating fwd pntr of old tail

        symbol_queue->tail->pfwd = symbol;
        symbol_queue->tail = symbol;

        symbol->pfwd = NULL;
    }
}

//
static  void    adjust_href( char *line_buffer, SECTION_INFO *section_info, SYMBOL_QUEUE *symbol_queue )
{
    char            *position, *sposition;
    char            *fposition;
    char            buffer[TITLE_NAME_SIZE+2];
    int             length, fragment;
    SYMBOL_TABLE    *symbol;

    // first locate the reference point
    position = strstr( line_buffer, HREF_TAG );
    position += strlen ( HREF_TAG );

    // check to see if this is  TOC reference
    if ( *position == '\"' )
    {  // this means we have to find the tag based on the name text
#ifdef DEBUG
printf ( "\nSearching for TOC Reference in >>%s<<", line_buffer );
#endif
        // move to Text area
        sposition = position + 2;

        // get copy of the text string
        length = strcspn( sposition, "<" );
        strncpy( buffer, sposition, length );
        buffer[length] = 0;

        // locate the string in the available symbols
        for( symbol = symbol_queue->head; symbol != NULL; symbol = symbol->pfwd )
        {
            if ( (strcmp ( symbol->name_text, buffer )) == 0 )
                break;  // we have a match
        }

        // on error, report and exit
        if( symbol == NULL )
        {
            printf ( "Error: unable to locate symbol for %s\n", buffer );
            return;
        }

        // make room for tag, and isert it with leading #
        length = strlen ( position );
        my_memmove( position+(strlen(symbol->name) + 1), position, length );
        *position = '#';
        strncpy ( position+1, symbol->name, strlen( symbol->name ) );
    }

    // exit now if href is not a relative type
    if ( *position != '#' )
        return;
    //
    //      SO 6.0Beta Bug Fix
    //  if ( (strncmp ( position+1, "http:", 5)) == 0 ||
    //      (strncmp ( position+1, "ftp:", 4)) == 0 )
    //      return;
#ifdef DEBUG
printf ( "\nSearching for Relative Reference in >>%s<<", line_buffer );
#endif

    // get copy of the tag string
    length = strcspn( position, "\"" );
    strncpy( buffer, position+1, length-1 );
    buffer[length-1] = 0;

    // locate the string in the available symbols
    for( symbol = symbol_queue->head; symbol != NULL; symbol = symbol->pfwd )
    {
        if ( (strcmp ( symbol->name, buffer )) == 0 )
            break;  // we have a match
    }

    // on error, report and exit
    if( symbol == NULL )
    {
        printf ( "Error: unable to locate symbol for %s\n", buffer );
        return;
    }

    // if the symbols section is the same as the one we are in now, just leave it relative
    if ( symbol->section_info == section_info )
        return;

    // make room in buffer for filename and insert filename ahead of tag
    fposition = &symbol->section_info->filename[0] + strlen( Target_Dir );
    fragment = strlen( position );
    my_memmove( (position+(strlen ( fposition ))), position, fragment );
    strncpy( position, fposition, (strlen(fposition)) );

}

//
static  void    build_symbol_table( char *line_buffer, SECTION_INFO **section_info_queue, SYMBOL_QUEUE *symbol_queue )
{
    SECTION_INFO    *section_info;
    FILE            *pin;
    char            *position;
    int             length;
    SYMBOL_TABLE    *symbol;

    // go thru each section and extract Anchor symbols
    for( section_info = *section_info_queue;
         section_info != NULL;
         section_info = section_info->pfwd )
    {
        // open file for reading
        pin = fopen ( section_info->section_id_name, "r" );

        // read lines from file
        while( (fgets( line_buffer, BUFFER_SIZE, pin )) != NULL )
        {
            // keep reading till we find the start of the Anchnor
            if ( (position = strstr( line_buffer, ANCHOR_TAG_NAME )) == NULL )
                continue;

            // tag found, create structure to hold data
            symbol = calloc( 1, sizeof(SYMBOL_TABLE) );

            // load structure
            symbol->section_info = section_info;
            // transfer anchor attribute
            position += strlen( ANCHOR_TAG_NAME );
            get_html_field( pin, NULL, line_buffer, position, symbol->name, ANCHOR_TAG_NAME_END );
            // now the text
            position = strstr( position, ANCHOR_TAG_END );
            position += strlen ( ANCHOR_TAG_END );
            get_html_field( pin, NULL, line_buffer, position, symbol->name_text, HEADER_TAG_END_OPEN );

            // add it to the symbol table
            add_to_symbols ( symbol, symbol_queue );
#ifdef DEBUG
            printf( "Anch: %s, Text: %s, File: %s\n", symbol->name, symbol->name_text, symbol->section_info->filename );
#endif
        }

        // clean up
        fclose ( pin );
    }
}

//
static  void    get_head( FILE *pin, char *line_buffer )
{
    FILE    *pout;
    char    *position, **html;
    int     title_size;
    char    filename[FILE_NAME_SIZE+1];

    strcpy( filename, Target_Dir );
    strcat( filename, HEAD_FILE );
    pout = fopen( filename, "w" );

    // read lines from source until </HEAD> encountered,
    // transfering them to the HEAD_FILE as we go
    while( (fgets( line_buffer, BUFFER_SIZE, pin )) != NULL )
    {
        // extract document title
        if( (position = strstr( line_buffer, TITLE_TAG )) )
        {  // end of where we want

            position += strlen( TITLE_TAG );
            title_size = strcspn( position, "<" );
            strncpy( Document_Title, position, (title_size < TITLE_NAME_SIZE) ? title_size : TITLE_NAME_SIZE );
        }

        if( (position = strstr( line_buffer, HEAD_TAG_END )) )
        {  // end of where we want

            // write last line and exit
            fputs( line_buffer, pout );
            break;
        }

        // write line
        fputs( line_buffer, pout );
    };

    // insert basic head stuff
    for( html = head_lines; *html != NULL; html++ )
        fputs( *html, pout );

    // clean up
    fclose( pout );
}

//
static  void    get_html_field( FILE *pin, FILE *pout, char *line_buffer, char *position, char *token_buffer, char *end_tag )
{
    char    *tposition;
    char    end[2];
    int     length;

    // preset for null token
    *token_buffer = 0;
    end[0] = *end_tag;
    end[1] = 0;

    // see if the end tag is on this line
    if ( (tposition = strstr (position, end_tag )) != NULL )
    { // YES, transfer to buffer and mark end with null

        position = move_past_tokens( position );
        length = strcspn( position, end );	// find length of text
        strncpy( token_buffer, position, length );
        token_buffer[length] = 0;
    }

    else
    { // Nope, hard times now

        position = move_past_tokens( position );
        strcpy( token_buffer, position );       // get first part
        strip_tail_white_space( token_buffer );

        // add a SPACE because the text crossed line boundaries
        if ( (strlen ( token_buffer )) > 0 )
            strcat ( token_buffer, " " );

        // write out current line
        if ( pout != NULL )
            fputs( line_buffer, pout );

        // get next line
        fgets( line_buffer, BUFFER_SIZE, pin );

        // append text up to end marker
        position = move_past_tokens( line_buffer );
        length = strcspn( position, end );
        strncat ( token_buffer, position, length );
        strip_tail_white_space( token_buffer );
    }
}

//
static  void    get_section_title( char *line_buffer, SECTION_INFO *section_info, char *end_tag, FILE *pin, FILE *pout )
{
    char    *position, *tposition;
    int     length;

    // move to the begining of the name
    // <H1 STYLE="page-break-before: always"><A NAME="Introduction"></A>Introduction</H1>  <-- if we're lucky
    position = strstr( line_buffer, ANCHOR_TAG_END );
    position += strlen ( ANCHOR_TAG_END );

    get_html_field ( pin, pout, line_buffer, position, section_info->title, end_tag );
}

//
static  void    get_title_section( FILE *pin, char *line_buffer, SECTION_INFO **section_info_queue )
{
    FILE            *pout;
    char            *position;
    SECTION_INFO    *section_info;


    // create section for the title page
    section_info = calloc( 1, sizeof(SECTION_INFO) );
    section_info->section_id = TITLE_SECTION_ID;
    sprintf( section_info->section_id_name, "%s%d.tmp.html", Target_Dir, section_info->section_id );
    strcpy ( section_info->filename, Target_Dir );
    strcat ( section_info->filename, TITLE_FILE );
    strcpy ( section_info->title, "Title" );

    // add the new section to chain
    add_to_queue( section_info_queue, section_info );

    // open file for output
    pout = fopen( section_info->section_id_name, "w" );

    // read lines from source starting at current position until <DIV> encountered,
    // transfering them to the temp Title file as we go

    // seek to next line after <BODY>
    while( (fgets( line_buffer, BUFFER_SIZE, pin )) != NULL )
    {
        if( (position = strstr( line_buffer, BODY_TAG_OPEN )) )
            break;
    };

    // now transfer the stuff we want
    while( (fgets( line_buffer, BUFFER_SIZE, pin )) != NULL )
    {
        // Stop when we get to the TOC stuff
        if( (position = strstr( line_buffer, TOC_DIV_TAG )) )
            break;

        // write line
        fputs( line_buffer, pout );
    };

    // clean up
    fclose( pout );
}

//
static  void    get_toc_section( FILE *pin, char *line_buffer, SECTION_INFO **section_info_queue )
{
    FILE            *pout;
    int             iteration;
    char            *position, *tposition;
    SECTION_INFO    *section_info;
    int             offset, toc_error;

    toc_error = FALSE;

    // create section for the Table of Contents page
    section_info = calloc( 1, sizeof(SECTION_INFO) );
    section_info->section_id = TOC_SECTION_ID;
    sprintf( section_info->section_id_name, "%s%d.tmp.html", Target_Dir, section_info->section_id );
    strcpy ( section_info->filename, Target_Dir );
    strcat ( section_info->filename, TOC_FILE );
    strcpy ( section_info->title, "Table of Contents" );

    // add the new section to chain
    add_to_queue( section_info_queue, section_info );

    // open file for output
    pout = fopen( section_info->section_id_name, "w" );

    // then the opening <DIV line that was picked up by get_title_section for us
    fputs( line_buffer, pout );

    // now read lines from source starting at current position until <DIV> encountered,
    // transfering them to the temp TOC file as we go
    iteration = 1;

    while( (fgets( line_buffer, BUFFER_SIZE, pin )) != NULL )
    {
        // Watch out for the 2nd one because a title for TOC was entered
        if( (strstr( line_buffer, TOC_DIV_TAG )) )
            iteration += 1;

        // stop reading when 2nd occurance of </DIV seen
        if( (strstr( line_buffer, DIV_TAG_END_OPEN )) )
        {
            iteration -= 1;

            // second time we're done
            if ( iteration == 0 )
            {
                fputs( line_buffer, pout );
                break;
            }
        }

        // locate the lines which are the actual table of contents
        // and strip page number, and add empty HREF for later
        //
        // this is VERY SO 6 beta specific
        if ( iteration == 1 )
        {
            // locate line with desired text on it
            if ( (strstr( line_buffer, PARA_TAG_OPEN )) != NULL )
            {
                // now see if we have all we need
                if ( (position = strstr( line_buffer, PARA_TAG_END )) == NULL )
                { // nope - magic time

                    do
                    {
                        // get next line
                        fgets( next_line_buffer, BUFFER_SIZE, pin );

                        if ( (strlen ( line_buffer ) + strlen ( next_line_buffer )) >= BUFFER_SIZE )
                        {
                            printf ( "Error: Paragraph size too large in TOC\n" );
                            toc_error = TRUE;
                            break;
                        }

                        // first strip whitespace and EOL from previous line
                        position = &line_buffer[(strlen(line_buffer))-1];
                        *position-- = '\0';
                        while (position != line_buffer && isspace(*position) )
                            *position-- = '\0';

                        // now move past all whitespace at front of current line
                        tposition = next_line_buffer;
                        while ( isspace( *tposition ) ) tposition++;

                        if ( !(*tposition == '<' || *position == '>') )
                        {
                            *++position = ' ';
                            *++position = '\0';
                        }
                        strcat( position, tposition ); // merge the lines into one till we find the end of tag
#ifdef DEBUG1
printf ( "\nTOC BEG:\n%s\n:END", line_buffer );
#endif
                    } while ( (strstr ( next_line_buffer, PARA_TAG_END )) == NULL );

                    if ( toc_error )
                    {  // stop processing on a line error

                        toc_error = FALSE;
                        continue;
                    }

                    // now reset as though it was all one line
                    position = strstr( line_buffer, PARA_TAG_END );
                }

                // remove page number from line
                tposition = position = move_past_token ( BACKWARD, position );     // get to page number
                position++;
                while ( isdigit( *tposition ) ) tposition--;            // move past number
                while ( isspace( *tposition ) ) tposition--;             // move to end of actual entry
                tposition++;
                strcpy ( tposition, position );

                // now add tail stuff before paragraph close
                my_memmove ( tposition+(strlen(ANCHOR_TAG_END)), tposition, strlen( tposition ));
                strncpy( tposition, ANCHOR_TAG_END, strlen( ANCHOR_TAG_END ) );

                // now insert dummy HREF for later
                tposition = move_past_token ( FORWARD, line_buffer );   // move to real text
                my_memmove( tposition+(strlen(HREF_TAG)+(strlen(HREF_TAG_END))), tposition, (strlen (tposition)) );
                strncpy ( tposition, HREF_TAG, strlen (HREF_TAG) );  // add lead stuff
                strncpy ( tposition+strlen(HREF_TAG), HREF_TAG_END, strlen( HREF_TAG_END) );
            }
        }

        // write line
        fputs( line_buffer, pout );
    };

    // clean up
    fclose( pout );
}

//
static  void    make_adjusted_html( char *line_buffer, SECTION_INFO **section_info_queue, SYMBOL_QUEUE *symbol_queue )
{
    FILE            *pin, *pout;
    SECTION_INFO    *section_info;
    int             toc_found, toc_count, toc_error;
    char            *position, *tposition, **html;

    toc_found = FALSE;
    toc_count = 0;
    toc_error = FALSE;
    // now convert all temp sections to final html files
    for( section_info = *section_info_queue; section_info != NULL; section_info = section_info->pfwd )
    {
        pout = fopen( section_info->filename, "w" );
        pin = fopen( section_info->section_id_name, "r" );

        // transfer all body stuff now, adjust hrefs as we go
        while( (fgets( line_buffer, BUFFER_SIZE, pin )) != NULL )
        {
            if( (strstr( line_buffer, TOC_DIV_TAG )) != NULL )
            {
                toc_found = TRUE;
                toc_count += 1;
            }

            if ( toc_found == TRUE )
            {
                if( (strstr( line_buffer, DIV_TAG_END )) != NULL )
                    toc_count -= 1;

            }
#ifdef DEBUG1
printf ( "\nF=%d, C=%d, >>%s<<\n", toc_found, toc_count, line_buffer );
#endif
            if ( toc_found && toc_count == 1 )
            {  // adjust TOC text line with a dummy href

                // locate line with desired text on it
                if ( (strstr( line_buffer, PARA_TAG_OPEN )) != NULL )
                {
                    // now see if we have all we need
                    if ( (position = strstr( line_buffer, PARA_TAG_END )) == NULL )
                    { // nope - magic time

                        do
                        {
                            // get next line
                            fgets( next_line_buffer, BUFFER_SIZE, pin );

                            if ( (strlen ( line_buffer ) + strlen ( next_line_buffer )) >= BUFFER_SIZE )
                            {
                                printf ( "Error: Paragraph size too large in TOC\n" );
                                toc_error = TRUE;
                                break;
                            }

                            // first strip whitespace and EOL from previous line
                            position = &line_buffer[(strlen(line_buffer))-1];
                            *position-- = '\0';
                            while (position != line_buffer && isspace(*position) )
                                *position-- = '\0';

                            // now move past all whitespace at front of current line
                            tposition = next_line_buffer;
                            while ( isspace( *tposition ) ) tposition++;

                            if ( !(*tposition == '<' || *position == '>') )
                            {
                                *++position = ' ';
                                *++position = '\0';
                            }
                            strcat( position, tposition ); // merge the lines into one till we find the end of tag
#ifdef DEBUG1
printf ( "\nHTML BEG:\n%s\n:END", line_buffer );
printf ( "\ntoc_found %d, toc_count %d\n", toc_found, toc_count );
#endif
                        } while ( (strstr( next_line_buffer, PARA_TAG_END )) == NULL );

                        if ( toc_error )
                        { // stop processing line on error

                            toc_error = FALSE;
                            continue;
                        }

                        // now reset as though it was all one line
                        position = strstr( line_buffer, PARA_TAG_END );
                    }

                    // remove page number from line
                    tposition = position = move_past_token ( BACKWARD, position );     // get to page number
                    position++;
                    while ( isdigit( *tposition ) ) tposition--;            // move past number
                    while ( isspace( *tposition ) ) tposition--;             // move to end of actual entry
                    tposition++;
                    strcpy ( tposition, position );

                    // now add tail stuff before paragraph close
                    my_memmove ( tposition+(strlen(ANCHOR_TAG_END)), tposition, strlen( tposition ));
                    strncpy( tposition, ANCHOR_TAG_END, strlen( ANCHOR_TAG_END ) );

                    // now insert dummy HREF for later
                    tposition = move_past_token ( FORWARD, line_buffer );   // move to real text
                    my_memmove( tposition+(strlen(HREF_TAG)+(strlen(HREF_TAG_END))), tposition, (strlen (tposition)) );
                    strncpy ( tposition, HREF_TAG, strlen (HREF_TAG) );  // add lead stuff
                    strncpy ( tposition+strlen(HREF_TAG), HREF_TAG_END, strlen( HREF_TAG_END) );
                }
            }

            // replace the <BODY tag with our own, so that we get the attributes too
            if ( (strstr( line_buffer, BODY_TAG_OPEN )) != NULL )
            {
                for( html = head_lines; *html != NULL; html++ )
                    fputs( *html, pout );
                continue;
            }

            // adjust all href so that they point to the correct files
            if ( (strstr( line_buffer, HREF_TAG )) != NULL )
                adjust_href( line_buffer, section_info, symbol_queue );

            // write line
            fputs( line_buffer, pout );
        };

        // close this one and remove temp
        fclose( pin );
        fclose( pout );

    };
}

//
static  void    make_html( char *line_buffer, SECTION_INFO **section_info_queue, SYMBOL_QUEUE *symbol_queue )
{
    FILE            *pin, *pout;
    SECTION_INFO    *section_info;

    // now convert all temp sections to final html files
    for( section_info = *section_info_queue; section_info != NULL; section_info = section_info->pfwd )
    {
        pout = fopen( section_info->filename, "w" );
        pin = fopen( section_info->section_id_name, "r" );

        if( section_info->section_id == TITLE_SECTION_ID )
        { // process title page differnent than others

            add_head_file( pout );
        }

        else
        {
            add_head_file( pout );
            add_head_leader( pout, section_info );
        }

        // transfer all boady stuff now, adjust hrefs as we go
        while( (fgets( line_buffer, BUFFER_SIZE, pin )) != NULL )
        {
            // adjust all href so that they point to the correct files
            if ( (strstr( line_buffer, HREF_TAG )) != NULL )
                adjust_href( line_buffer, section_info, symbol_queue );

            // write line
            fputs( line_buffer, pout );
        };

        // closing remarks
        if ( section_info->section_id != TITLE_SECTION_ID )
            add_end_leader( pout, section_info );

        add_end_file( pout );

        // close this one and remove temp
        fclose( pin );
        fclose( pout );
        unlink( section_info->section_id_name );

    }
}

//
static  char    *move_past_tokens( char *position )
{
    // if the first character is not a token start, we're done
    if ( *position != '<' )
        return ( position );

    else
    {
        // as long as there are characters to check, look for close of token
        while ( *position != 0 )
        {
            // exit if end of token, but watch for second in a row
            if ( *position == '>' && *(position+1) != '<' )
                return ( ++position );

            position++;
        }
        return ( position );
    }
}

//
static  char    *move_past_token( int direction, char *buffer )
{
    if ( direction == FORWARD )
    {
        while ( TRUE )
        {
            while ( isspace( *buffer ) ) buffer++;  // skip any white space

            if ( *buffer != '<' )
                break;                          // no token start, so must be done

            while ( *buffer != '>' ) buffer++;
            buffer++;                               // move to next charc after token stop
        };
    }
    else // must be BACKWARDS
    {
        while ( TRUE )
        {
            if ( *buffer == '<' )
                buffer--;                       // back up if token start

            while ( isspace( *buffer ) ) buffer--; // skip any white space

            if ( *buffer != '>' )
                break;                          // done, if this is not the end on another token

            while ( *buffer != '<' ) buffer--;      // move to start of token
        };
    }
}

//
static  void    my_memmove( char *dest, char *src, int count )
{
    // adjust src and dest to end of strings
    dest += count;
    src += count;
    count += 1; // to account for the null
    while( count-- )
        *dest-- = *src--;
}

//
static  void    split_source( FILE *pin, char *line_buffer, SECTION_INFO **section_info_queue )
{
    int             section_id, sub_section_id, name_len;
    int             enable_H2;
    char            *position, *last_position;
    FILE            *pout;
    SECTION_INFO    *section_info;

    // make sure we are at the beginning of the source file
    rewind( pin );
    pout = NULL;
    section_id = BODY_SECTION_ID;
    sub_section_id = 0;
    enable_H2 = FALSE;

    // run through the source file and create temp section files as we go
    // that contain the "body" of each <H1 tag
    // target file names based on the <H1 tag's title
    while( (fgets( line_buffer, BUFFER_SIZE, pin )) != NULL )
    {
        // stop scanning lines if end of BODY seen
        if( (position = strstr( line_buffer, BODY_TAG_END )) != NULL )
        {
            // if there is an open file, do end processing
            if ( pout != NULL )
            {
                fclose ( pout );
                pout = NULL;

                // set for next section id
                section_id += 1;
            }

            // go get next line
            continue;
        }

        // we have a line, lets see if its the start of a desired definition
        if( (position = strstr( line_buffer, HEADER_1_TAG )) == line_buffer ||
            (enable_H2 && ((position = strstr( line_buffer, HEADER_2_TAG )) == line_buffer)) )
        {  // extract section title, and make it the section filename

            // if there is an open file, do end processing
            if ( pout != NULL )
            {
                fclose ( pout );
                pout = NULL;

                // set for next section id
                if ( (position = strstr( line_buffer, HEADER_1_TAG )) == line_buffer )
                {  // move to next section id and stop splitting at H2
                    section_id += 1;
                    enable_H2 = FALSE;
                }

                else
                    sub_section_id +=1;
            }

            // get and initialize a section block with the name
            section_info = calloc( 1, sizeof(SECTION_INFO) );
            section_info->section_id = section_id;

            if ( enable_H2 )
            {  // for H2, extend names to include sub-section ID

                section_info->sub_section_id = sub_section_id;
                sprintf( section_info->section_id_name, "%s%d-%d.tmp.html", Target_Dir,
                section_info->section_id, section_info->sub_section_id );
                sprintf( section_info->filename, "%ssection%d-%d.html", Target_Dir,
                section_info->section_id-BODY_SECTION_ID+1, section_info->sub_section_id );
            }

            else
            { // H1, names only include section ID
                sprintf( section_info->section_id_name, "%s%d.tmp.html", Target_Dir,
                section_info->section_id );
                sprintf( section_info->filename, "%ssection%d.html", Target_Dir,
                section_info->section_id-BODY_SECTION_ID+1 );
            }
            // remove old file, if it exists
            unlink ( section_info->filename );

            // create and initialize the new file
            pout = fopen( section_info->section_id_name, "w" );

            // get section title, and put in structure
            get_section_title( line_buffer, section_info,
                (enable_H2 ? HEADER_2_TAG_END : HEADER_1_TAG_END), pin, pout );

            // add the new section to chain
            add_to_queue( section_info_queue, section_info );

            // then check to see if this section is the one that we are to split at the H2 level
            if( (strcmp( section_info->title, Split_Section_Title )) == 0 )
                enable_H2 = TRUE;

#ifdef  DEBUG
            printf ( "Section %d = %s\n", section_info->section_id, section_info->filename );
            printf( "Title: <%s>  Look:<%s>\n\n", section_info->title, Split_Section_Title );
#endif
        }

        // output lines if we have skipped all the intro stuff
        if ( pout != NULL )
            fputs( line_buffer, pout );
    };

    // if there is an open files, do end processing
    if ( pout != NULL )
        fclose ( pout );
}

//
static  void    strip_tail_white_space( char *token_buffer )
{
    char    *end;

    // get end of buffer
    end = &token_buffer[(strlen(token_buffer))-1];

    // moving backward, strip white space from end of line
    while ( isspace( *end ) )
    {
        *end = 0;
        if ( end == token_buffer )
            break;
        else
            end--;
    }
}


//

// Local Private Data
static  SECTION_INFO    *section_info_queue = NULL;     // section structure chain origin
static  SYMBOL_QUEUE    symbol_queue = { NULL, NULL }; // symbol table chain
static  char            line_buffer[BUFFER_SIZE+1];     // working line buffer
static  char            filename[FILE_NAME_SIZE+1];     // temp filename buffer

static  int     split_main( int argc, char *argv[] )
{
    FILE            *pin;

    // set up directory leader
    if ( argc > 3 )
    {
        strncpy ( Target_Dir, argv[3], FILE_NAME_SIZE );

        // make sure path has terminating '/'
        if ( strlen ( Target_Dir ) > 1 )
        {
            if ( Target_Dir[(strlen(Target_Dir)-1)] != '/' )
                strcat( Target_Dir, "/" );
        }
    }

    else    // use current directory for files
        Target_Dir[0] = 0;

    // open source file for reading
    if ( !(pin = fopen ( argv[2], "r" )) )
    {
        printf ( "Error: Unable to open source file: %s\n", argv[2] );
        return ( 1 );
    }

    // clear document title
    memset ( Document_Title, 0, sizeof(Document_Title) );

    //      First, extract up to </HEAD> into a temp file
    //      picking up document title as we go
    get_head ( pin, line_buffer );

    //      Then get the TITLE data into a seperate file
    get_title_section ( pin, line_buffer, &section_info_queue );

    //      Then extract the <DIV ... /DIV> since it contains the Table of contents
    get_toc_section ( pin, line_buffer, &section_info_queue );

    //      Next run thru the source file and create independant files
    //      which are delineated by the <H1 tag
    split_source ( pin, line_buffer, &section_info_queue );

    //      Next, build Anchor/Href symbol table
    build_symbol_table( line_buffer, &section_info_queue, &symbol_queue );

    //      Finally create file HTML files and add some beautifying code
    //      that simplifies navigating about
    make_html ( line_buffer, &section_info_queue, &symbol_queue );

    // all done, close up shop
    fclose ( pin );
    strcpy ( filename, Target_Dir );
    strcat ( filename, HEAD_FILE );
    unlink ( filename );

    return ( 0 );
}

static  int     toc_main( int argc, char *argv[] )
{
    FILE            *pin;
    SECTION_INFO    *section_info;

    // set up directory leader
    if ( argc > 3 )
    {
        strncpy ( Target_Dir, argv[3], FILE_NAME_SIZE );

        // make sure path has terminating '/'
        if ( strlen ( Target_Dir ) > 1 )
        {
            if ( Target_Dir[(strlen(Target_Dir)-1)] != '/' )
                strcat( Target_Dir, "/" );
        }
    }

    else    // use current directory for files
        Target_Dir[0] = 0;

    // open source file for reading
    if ( !(pin = fopen ( argv[2], "r" )) )
    {
        printf ( "Error: Unable to open source file: %s\n", argv[2] );
        return ( 1 );
    }
    // close it for now
    fclose ( pin );

    //      First, build Anchor/Href symbol table
    // create section for the Table of Contents page
    section_info = calloc( 1, sizeof(SECTION_INFO) );
    section_info->section_id = TOC_SECTION_ID;
    sprintf( section_info->section_id_name, "%s", argv[2] );
    strcpy ( section_info->filename, Target_Dir );
    strcat ( section_info->filename, "new." );
    strcat ( section_info->filename, argv[2] );
    strcpy ( section_info->title, "Table of Contents" );

    // add the new section to chain
    add_to_queue( &section_info_queue, section_info );

    // now build up symbol table
    build_symbol_table( line_buffer, &section_info_queue, &symbol_queue );

    //      Finally create file HTML files and add some beautifying code
    //      that simplifies navigating about
    make_adjusted_html ( line_buffer, &section_info_queue, &symbol_queue );

    // all done, close up shop
    return ( 0 );
}

int main( int argc, char *argv[] )
{

    // Check that we have some parameters
    if ( argc < 3 )
    {
        printf ( usage );
        return ( 1 );
    }

    // see which mode wanted
    if ( (strncmp( argv[1], "-t", 2 )) == 0 )
    {  //wants to adjust TOC only
        return ( toc_main( argc, argv ) );
    }

    else if ( (strncmp( argv[1], "-s", 2 )) == 0 )
    {  // wants to split the file up
        return ( split_main( argc, argv ) );
    }

    else
    {  // report error and exit
        printf ( usage );
        return ( 1 );
    }
}