b_write.c

来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 1,191 行 · 第 1/3 页

C
1,191
字号
/****************************************************************************
*
*                            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:  WHEN YOU FIGURE OUT WHAT THIS FILE DOES, PLEASE
*               DESCRIBE IT HERE!
*
****************************************************************************/


#include <string.h>     // for memset
#include <stdarg.h>     // for BRIAddType
#include <assert.h>
#include "b_write.h"
#include "carve.h"

#ifndef boolean
typedef int boolean;
#endif

#ifndef TRUE
#define TRUE (1)
#endif

#ifndef FALSE
#define FALSE (0)
#endif

#ifndef EOF
#include <stdio.h>
#endif

#define BRI_write( cli, buf, len )      cli->rtns.write( cli->io_cookie, buf, len )
#define BRI_lseek( cli, off, whe )      cli->rtns.lseek( cli->io_cookie, off, whe )
#define BRI_malloc( cli, size )         cli->rtns.malloc( size )
#define BRI_free( cli, ptr )            cli->rtns.free( ptr )

#define LIST_BLOCK      0x180
#define CHAR_BLOCK      0x180
#define NUM_BUCKETS     0x100

#define BRI_MAX_LINE  0x00007ffful
#define BRI_MAX_COL   0x0000007ful

#define TYPE_BRANCH     8
#define TYPE_FULL( t )  ((t)->type_ids[TYPE_BRANCH-2]!=NULL)
#define TYPE_BOTTOM( t ) ((t)->next[0]==NULL)

/******************************
    Type Declarations.
******************************/

typedef struct BRI_FileCounter {
    BRI_StringID                filename_id;
    uint_32                     line,column;
    boolean                     template;
    struct BRI_FileCounter *    next;
} BRI_FileCounter;

typedef struct BRI_TypeCounter {
    struct BRI_TypeCounter      *next[TYPE_BRANCH];
    BRI_TypeID                  type_ids[TYPE_BRANCH-1];
} BRI_TypeCounter;

typedef struct BRI_HashString {
    struct BRI_HashString *     next;
    BRI_StringID                index;
    unsigned                    offset;
} BRI_HashString;

struct BRI_Handle {
    /* callback functions */
    BRI_Routines        rtns;

    /* Browse header */
    BRI_Header *        hdr;

    /* file io information */
    int                 io_cookie;
    unsigned long       start;

    /* other data */
    BRI_FileCounter *   files;
    BRI_TypeCounter *   types;
    carve_t             carve_types;

    /* string storage */
    BRI_HashString *    table[NUM_BUCKETS];
    char *              char_buf;
    unsigned            buf_size;
    unsigned            buf_top;
    carve_t             carve_string;
};


/*****************************
    Static functions.
*****************************/

static uint_32 const bmask[5] = {
    0x00000000,
    0x000000ff,
    0x0000ffff,
    0x00ffffff,
    0xffffffff,
};


/*  hashString
*/

static int hashString( char const *string, int len )
/**************************************************/
{
    uint_32 *s = (uint_32*) string;
    uint_32 mask;
    uint_32 c;
    uint_32 g;
    uint_32 h;

    h = len;
    c = len;
    if( len > sizeof( uint_32 ) ) {
        do {
            c += *s;
            h = ( h << 4 ) + c;
            g = h & ~0x0ffffff;
            h ^= g;
            h ^= g >> (4+4+4+4+4);
            ++s;
            len -= sizeof( uint_32 );
        } while( len > sizeof( uint_32 ) );
    }
    mask = bmask[ len ];
    c += *s & mask;
    h = ( h << 4 ) + c;
    g = h & ~0x0ffffff;
    h ^= g;
    h ^= g >> (4+4+4+4+4);
    g = h & ~0x0fff;
    h ^= g;
    h ^= g >> (4+4+4);
    h ^= h >> (2+4);
    assert( ( h & ~0x0fff ) == 0 );
    return( (int) (h%NUM_BUCKETS) );
}


/*  insertStringID      -- Insert a string into the string table without
                           replacement.
*/

static BRI_StringID insertStringID( BRI_HANDLE handle, BRI_StringID index,
                            char const *string, uint_32 length )
/************************************************************************/
{
    BRI_StringID        result;
    BRI_HashString *    current;
    BRI_HashString *    prev;
    BRI_HashString *    newstring;
    int                 hash_val;
    int                 comparison;

    hash_val = hashString( string, length );

    prev = NULL;
    current = handle->table[hash_val];
    while( current != NULL ){
        comparison = strcmp( handle->char_buf+current->offset, string );
        if( comparison >= 0 ){
            break;
        }
        prev = current;
        current = current->next;
    }

    if( current == NULL || comparison > 0 ){
        newstring = CarveAlloc( handle->carve_string );
        newstring->next = current;
        newstring->index = index;
        if( prev != NULL ){
            prev->next = newstring;
        } else {
            handle->table[hash_val] = newstring;
        }
        if( length + handle->buf_top > handle->buf_size ){
            int         new_size;
            char *      temp;

            new_size = 2*handle->buf_size;
            if( new_size < length + handle->buf_top ){
                new_size = length + handle->buf_top;
            }
            temp = BRI_malloc( handle, new_size*sizeof(char) );
            memcpy( temp, handle->char_buf, handle->buf_size );
            BRI_free( handle, handle->char_buf );
            handle->char_buf = temp;
            handle->buf_size = new_size;
        }
        newstring->offset = handle->buf_top;
        memcpy( handle->char_buf+handle->buf_top, string,
                length*sizeof(char) );
        handle->buf_top += length;
        result = index;
    } else {
        result = current->index;
    }

    return result;
}


/*  insertTypeID        -- Record a type id as having been seen.
                           Assumes the id was not seen previously.
*/

static void insertTypeID( BRI_HANDLE handle, BRI_TypeID type_id )
/***************************************************************/
{
    BRI_TypeCounter     *current;
    BRI_TypeCounter     *parent;
    BRI_TypeID          temp_id;
    int                 follow;
    int                 i;

    current = handle->types;
    if( current == NULL ){
        current = CarveAlloc( handle->carve_types );
        memset( current->type_ids, 0,
                (TYPE_BRANCH-1)*sizeof(BRI_TypeID) );
        memset( current->next, 0, TYPE_BRANCH*sizeof(BRI_TypeCounter *) );
        current->type_ids[0] = type_id;
        handle->types = current;
        return;
    }
    parent = NULL;
    for(;;){
        if( TYPE_FULL( current ) ){
            // Split the current node
            BRI_TypeCounter     *sibling;
            BRI_TypeCounter     *temp_ctr1, *temp_ctr2;
            BRI_TypeID          promote;
            int                 divider;

            divider = TYPE_BRANCH/2;
            sibling = CarveAlloc( handle->carve_types );
            memset( sibling->next, 0, TYPE_BRANCH*sizeof(BRI_TypeCounter *) );
            memset( sibling->type_ids, 0,
                    (TYPE_BRANCH-1)*sizeof(BRI_TypeID) );
            memcpy( sibling->next, current->next+divider,
                    divider*sizeof( BRI_TypeCounter * ) );
            memcpy( sibling->type_ids, current->type_ids+divider,
                    (divider-1)*sizeof( BRI_TypeID ) );
            promote = current->type_ids[divider-1];
            memset( current->next+divider, 0,
                    divider*sizeof( BRI_TypeCounter * ) );
            memset( current->type_ids+divider-1, 0,
                    divider*sizeof( BRI_TypeID ) );
            if( parent == NULL ){
                temp_ctr1 = CarveAlloc( handle->carve_types );
                memset( temp_ctr1->next, 0,
                        TYPE_BRANCH*sizeof(BRI_TypeCounter *) );
                memset( temp_ctr1->type_ids, 0,
                        (TYPE_BRANCH-1)*sizeof(BRI_TypeID) );
                temp_ctr1->next[0] = current;
                temp_ctr1->next[1] = sibling;
                temp_ctr1->type_ids[0] = promote;
                handle->types = temp_ctr1;
            } else {
                for( i=follow; i<TYPE_BRANCH-1; i++ ){
                    temp_id = parent->type_ids[i];
                    parent->type_ids[i] = promote;
                    promote = temp_id;
                }
                temp_ctr2 = sibling;
                for( i=follow+1; i<TYPE_BRANCH; i++ ){
                    temp_ctr1 = parent->next[i];
                    parent->next[i] = temp_ctr2;
                    temp_ctr2 = temp_ctr1;
                }
            }
            if( type_id > promote ){
                current = sibling;
            }
        }
        if( TYPE_BOTTOM( current ) ){
            break;
        }
        for( follow=0; follow<TYPE_BRANCH-1; follow++ ){
            if( current->type_ids[follow] == BRI_NULL_ID ){
                break;
            } else if( current->type_ids[follow] > type_id ){
                break;
            }
        }
        parent = current;
        current = current->next[follow];
    }

    for( follow=0; follow<TYPE_BRANCH-1; follow++ ){
        if( current->type_ids[follow] == BRI_NULL_ID ){
            break;
        } else if( current->type_ids[follow] > type_id ){
            break;
        }
    }
    for( i=follow; i<TYPE_BRANCH-1; i++ ){
        temp_id = current->type_ids[i];
        current->type_ids[i] = type_id;
        type_id = temp_id;
    }

    return;
}


/******************************
    External functions.
******************************/


/*  BRIBeginWrite       -- Create a browse handle, ready for use.
*/

BRI_HANDLE BRIBeginWrite( BRI_Routines const *rtns, int io_cookie,
                          unsigned long start )
/*****************************************************************/
{
    BRI_HANDLE          result;
    BRI_Header *        hdr;

    result = (BRI_HANDLE) rtns->malloc( sizeof(BRI_Handle) );
    if( result == NULL ) {
        // TODO:  FATAL ERROR
        return (BRI_HANDLE) NULL;
    }

    memset( result, 0, sizeof( *result ) );
    result->rtns = *rtns;
    result->io_cookie = io_cookie;
    result->start = start;
    result->files = NULL;
    result->types = NULL;
    result->carve_types = CarveCreate( sizeof(BRI_TypeCounter), LIST_BLOCK );
    result->char_buf = BRI_malloc( result, CHAR_BLOCK*sizeof(char) );
    result->buf_size = CHAR_BLOCK;
    result->buf_top = 0;
    memset( result->table, 0, NUM_BUCKETS*sizeof(BRI_HashString*) );
    result->carve_string = CarveCreate( sizeof(BRI_HashString), LIST_BLOCK );

    hdr = (BRI_Header *) BRI_malloc( result, sizeof( BRI_Header ) );
    memset( hdr, 0, sizeof(*hdr) );
    hdr->magic = BRI_MAGIC;
    hdr->major_ver = BRI_MAJOR_VER;
    hdr->minor_ver = BRI_MINOR_VER;
    BRI_write( result, hdr, sizeof( *hdr ) );
    result->hdr = hdr;

    return result;
}


/*  BRIEndWrite         -- Finish using a browse handle and destroy it.
*/

void BRIEndWrite( BRI_HANDLE handle )
/***********************************/
{
    int                 out_len;
    // int                 i;

    // Get the current position in the file.
    out_len = BRI_lseek( handle, 0, BRI_SEEK_CUR );

    handle->hdr->file_len = out_len - handle->start;

⌨️ 快捷键说明

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