index.c

来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 414 行

C
414
字号
/****************************************************************************
*
*                            Open Watcom Project
*
*    Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved.
*
*  ========================================================================
*
*    This file contains Original Code and/or Modifications of Original
*    Code as defined in and that are subject to the Sybase Open Watcom
*    Public License version 1.0 (the 'License'). You may not use this file
*    except in compliance with the License. BY USING THIS FILE YOU AGREE TO
*    ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is
*    provided with the Original Code and Modifications, and is also
*    available at www.sybase.com/developer/opensource.
*
*    The Original Code and all software distributed under the License are
*    distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
*    EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM
*    ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF
*    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR
*    NON-INFRINGEMENT. Please see the License for the specific language
*    governing rights and limitations under the License.
*
*  ========================================================================
*
* Description:  InfoBench help file index creation.
*
****************************************************************************/


#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include "sorthelp.h"
#include "index.h"

#define STR_CNT 2
static int      dataPageCnt;
static int      indexPageCnt;
static int      topicCnt;


static unsigned markDataPages( void )
{
    unsigned            page;
    a_helpnode          *curnode;
    unsigned            size;
    unsigned            nodesize;

    size = sizeof( HelpPageHeader );
    curnode = HelpNodes;
    page = 0;
    topicCnt = 0;
    while( curnode != NULL ) {
        topicCnt++;
        nodesize = sizeof( PageIndexEntry ) + strlen( curnode->name ) + 1;
        if( nodesize + size > PAGE_SIZE ) {
            page++;
            size = sizeof( HelpPageHeader );
        }
        size += nodesize;
        curnode->data_page = page;
        curnode = curnode->next;
    }
    return( page + 1 );
}


static unsigned pagesInNextLevel( unsigned pages_in_this_level )
{
    unsigned            ret;

    ret = pages_in_this_level / INDEX_ENTRIES_PER_PAGE;
    if( pages_in_this_level % INDEX_ENTRIES_PER_PAGE != 0 ) ret++;
    return( ret );
}


static unsigned calcIndexPages( unsigned pagecnt )
{
    unsigned    numpages;
    unsigned    next_level;

    numpages = 0;
    for( ;; ) {
        next_level = pagesInNextLevel( pagecnt );
        pagecnt = next_level;
        numpages += next_level;
        if( pagecnt == 1 ) break;
    }
    return( numpages );
}


unsigned calcStringBlockSize( char **str )
{
    unsigned    blocksize;
    unsigned    i;

    blocksize = ( STR_CNT + 1 ) * sizeof( uint_16 );
    for( i = 0; i < STR_CNT; i++ ) {
        if( str[i] != NULL ) {
            blocksize += strlen( str[i] ) + 1;
        }
    }
    return( blocksize );
}


unsigned long CalcIndexSize( char **str, bool gen_str )
{
    unsigned long       ret;

    dataPageCnt = markDataPages();
    indexPageCnt = calcIndexPages( dataPageCnt );
    ret = ( dataPageCnt + indexPageCnt ) * PAGE_SIZE
            + dataPageCnt * sizeof( uint_16 );
    if( gen_str ) {
        ret += sizeof( HelpHeader ) + calcStringBlockSize( str );
    } else {
        ret += sizeof( OldHeader );
    }
    return( ret );
}


static a_helpnode *findFirstPage( page )
{
    a_helpnode          *curnode;

    curnode = HelpNodes;
    while( curnode != NULL && curnode->data_page + indexPageCnt != page ) {
        curnode = curnode->next;
    }
    return( curnode );
}


static unsigned countPageEntries( unsigned page )
{
    unsigned            cnt;
    a_helpnode          *curnode;

    curnode = HelpNodes;
    cnt = 0;
    curnode = findFirstPage( page );
    while( curnode != NULL && curnode->data_page + indexPageCnt == page ) {
        cnt ++;
        curnode = curnode->next;
    }
    return( cnt );
}


static int writeOneDataPage( int fout, unsigned pagenum )
{
    char                *page;
    HelpPageHeader      *pagehdr;
    PageIndexEntry      *index;
    char                *strings;
    unsigned            stroff;
    unsigned            len;
    a_helpnode          *curnode;

    page = malloc( PAGE_SIZE );
    memset( page, 0, PAGE_SIZE );
    pagehdr = (HelpPageHeader *)page;
    index = (PageIndexEntry *)( page + sizeof( HelpPageHeader ) );
    pagehdr->type = PAGE_DATA;
    pagehdr->num_entries = countPageEntries( pagenum );
    pagehdr->page_num = pagenum;
    strings = (char *)index + pagehdr->num_entries * sizeof( PageIndexEntry );
    stroff = 0;
    curnode = findFirstPage( pagenum );
    while( curnode != NULL && curnode->data_page + indexPageCnt == pagenum ) {
        index->name_offset = stroff;
        index->entry_offset = curnode->fpos;
        strcpy( strings, curnode->name );
        len = strlen( curnode->name ) + 1;
        stroff += len;
        strings += len;
        curnode = curnode->next;
        index++;
    }
    write( fout, page, PAGE_SIZE );
    free( page );
    return( 0 );
}


static int writeDataPages( int fout )
{
    unsigned            i;

    for( i=0; i < dataPageCnt; i++ ) {
        writeOneDataPage( fout, i + indexPageCnt );
    }
    return( 1 );
}


static char *getIndexString( void **pages, unsigned base, int datalevel )
{
    HelpIndexEntry      *entry;
    HelpPageHeader      *header;
    a_helpnode          *node;

    if( datalevel ) {
        node = findFirstPage( base );
        while( node->next != NULL &&
               node->next->data_page + indexPageCnt == base ) {
            node = node->next;
        }
        return( node->name );
    } else {
        header = pages[ base ];
        entry = (HelpIndexEntry *) ( (char *)header
                + sizeof( HelpPageHeader ) );
        return( entry[ header->num_entries - 1].start );
    }
}


static void fillIndexPage( void **pages, unsigned curpage, unsigned base,
                    int datalevel )
{
    HelpIndexEntry      *entry;
    HelpPageHeader      *header;
    unsigned            i;
    char                *src;

    header = pages[curpage];
    entry = (HelpIndexEntry *) ( (char *)header + sizeof( HelpPageHeader ) );
    for( i = 0; i < header-> num_entries; i++ ) {
        entry->nextpage = base;
        src = getIndexString( pages, base, datalevel );
        strncpy( entry->start, src, INDEX_LEN );
        entry->start[ INDEX_LEN -1 ] = '\0';
        base++;
        entry++;
    }
}


static void generateIndexLevel( void **pages, unsigned curbase,
                unsigned cur_level, unsigned prevbase, unsigned prev_level )
{
    unsigned            entries_per_page;
    unsigned            entries_last_page;
    unsigned            i;
    unsigned            base;
    HelpPageHeader      *header;

    entries_per_page = prev_level / cur_level;
    if( prev_level % cur_level != 0 ) {
        entries_per_page ++;
    }
    entries_last_page = prev_level - entries_per_page * ( cur_level - 1 );
    if( prevbase == -1 ) {
        base = indexPageCnt;
    } else {
        base = prevbase;
    }
    for( i = curbase; i < curbase + cur_level; i++ ) {
        pages[i] = malloc( PAGE_SIZE );
        memset( pages[i], 0, PAGE_SIZE );
    }
    /***********************************
     * for each B tree page in a level *
     ***********************************/
    for( i = curbase; i < curbase + cur_level; i++ ) {
        header = pages[i];
        header->type = PAGE_INDEX;
        if( i == curbase + cur_level - 1 ) {
            header->num_entries = entries_last_page;
        } else  {
            header->num_entries = entries_per_page;
        }
        header->page_num = i;
        fillIndexPage( pages, i, base, prevbase == -1 );
        base += entries_per_page;
    }
}


static int writeIndexPages( int fout )
{
    unsigned            prev_level;
    unsigned            cur_level;
    void                **pages;
    unsigned            curbase;
    unsigned            prevbase;
    unsigned            i;

    prev_level = dataPageCnt;
    prevbase = -1;
    pages = malloc( indexPageCnt * sizeof( void * ) );
    memset( pages, 0, indexPageCnt * sizeof( void * ) );
    curbase = indexPageCnt;

    /*************************
     * for each B tree level *
     *************************/
     for( ;; ) {
         cur_level = pagesInNextLevel( prev_level );
         curbase -= cur_level;
         generateIndexLevel( pages, curbase, cur_level, prevbase, prev_level );
         if( cur_level == 1 ) break;
         prev_level = cur_level;
         prevbase = curbase;
     }
     for( i = 0; i < indexPageCnt; i++ ) {
         write( fout, pages[i], PAGE_SIZE );
         if( pages[i] != NULL ) free( pages[i] );
     }
     free( pages );
     return( 0 );
}


static int writePageItemNumIndex( int fout )
{
    uint_16     *index;
    uint_16     indexsize;
    unsigned    i;

    indexsize = dataPageCnt * sizeof( uint_16 );
    index = malloc( indexsize );
    index[0] = 0; //countPageEntries( indexPageCnt );
    for( i=1; i < dataPageCnt; i++ ) {
        index[i] = index[ i-1 ] + countPageEntries( indexPageCnt + i - 1 );
    }
    write( fout, index, indexsize );
    free( index );
    return( 0 );
}


static int writeHeader( int fout, int blocksize )
{
    HelpHeader          header;

    memset( &header, 0, sizeof( HelpHeader ) );
    header.sig[0] = HELP_SIG_1;
    header.sig[1] = HELP_SIG_2;
    header.ver_maj = HELP_MAJ_VER;
    header.ver_min = HELP_MIN_VER;
    header.indexpagecnt = indexPageCnt;
    header.datapagecnt = dataPageCnt;
    header.topiccnt = topicCnt;
    header.str_size = blocksize;
    write( fout, &header, sizeof( HelpHeader ) );
    return( 0 );
}


static int writeOldHeader( int fout )
{
    OldHeader           header;

    memset( &header, 0, sizeof( OldHeader ) );
    header.sig[0] = HELP_SIG_1;
    header.sig[1] = HELP_SIG_2;
    header.ver_maj = 1;
    header.ver_min = HELP_MIN_VER;
    header.indexpagecnt = indexPageCnt;
    header.datapagecnt = dataPageCnt;
    header.topiccnt = topicCnt;
    write( fout, &header, sizeof( OldHeader ) );
    return( 0 );
}

static void writeStrings( int fout, char **str )
{
    unsigned    i;
    uint_16     tmp[STR_CNT + 1];

    tmp[0] = STR_CNT;
    for( i = 0; i < STR_CNT; i++ ) {
        if( str[i] != NULL ) {
            tmp[i + 1] = strlen( str[i] ) + 1;
        } else {
            tmp[i + 1] = 0;
        }
    }
    write( fout, &tmp, sizeof( uint_16 ) * ( STR_CNT + 1 ) );
    for( i = 0; i < STR_CNT; i++ ) {
        if( str[i] != NULL ) {
            write( fout, str[i], tmp[i + 1] );
        }
    }
}

int WriteIndex( int fout, char **str, bool gen_str )
{
    int         blocksize;

    lseek( fout, 0, SEEK_SET );
    if( gen_str ) {
        blocksize = calcStringBlockSize( str );
        writeHeader( fout, blocksize );
        writeStrings( fout, str );
    } else {
        writeOldHeader( fout );
    }
    writePageItemNumIndex( fout );
    writeIndexPages( fout );
    writeDataPages( fout );
    return( 0 );
}

⌨️ 快捷键说明

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