omfutil.c

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

C
528
字号
/****************************************************************************
*
*                            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:  Utility routines for OMF libraries.
*
****************************************************************************/


#include "wlib.h"
static OmfRecord    *omfRec;
static unsigned     omfRecLen;
static unsigned long charCount;
static unsigned long symCount;


static unsigned                         PrimeNos[] = {
  2,      3,      5,      7,     11,     13,     17,     19,     23,     29,
 31,     37,     41,     43,     47,     53,     59,     61,     67,     71,
 73,     79,     83,     89,     97,    101,    103,    107,    109,    113,
127,    131,    137,    139,    149,    151,    157,    163,    167,    173,
179,    181,    191,    193,    197,    199,    211,    223,    227,    229,
233,    239,    241,    251,      0 /* terminator */
};

void InitOmfUtil()
{
    omfRec = MemAlloc( INIT_OMF_REC_SIZE );
    omfRecLen = INIT_OMF_REC_SIZE;
    charCount = 0;
    symCount = 0;
}

void FiniOmfUtil()
{
    MemFree( omfRec );
    omfRecLen = 0;
}


static void CheckForOverflow(file_offset current)
{
    char buffer[10];

    if ((current / Options.page_size) > (unsigned long)(USHRT_MAX)) {
        sprintf(buffer, "%u", Options.page_size);
        FatalError(ERR_LIB_TOO_LARGE, buffer);
    }
}

void PadOmf( bool force )
{
    unsigned    padding;
    char        *tmpbuf;

    // page size is always a power of 2
    // therefor x % Options.page_size == x & ( Options.page_size - 1 )

    padding = Options.page_size -( LibTell( NewLibrary ) & ( Options.page_size - 1 ) );
    if( padding != Options.page_size || force ) {
        tmpbuf = MemAlloc( padding );
        memset( tmpbuf, 0, padding );
        WriteNew( tmpbuf, padding );
        MemFree( tmpbuf);
        }
}

static bool ReadOmfRecord( libfile io )
{
    if( LibRead( io, omfRec, 3 ) != 3 ) {
        return( FALSE );
    }

    if ( omfRec->basic.len + 3 > omfRecLen ){
        OmfRecord *new;
        omfRecLen = omfRec->basic.len + 3;
        new = MemAlloc( omfRecLen );
        new->basic.len = omfRec->basic.len;
        new->basic.type = omfRec->basic.type;
        MemFree( omfRec );
        omfRec = new;
    }
    if( LibRead( io, ( omfRec )->basic.contents, omfRec->basic.len ) != omfRec->basic.len ) {
        return( FALSE );
    }
    return( TRUE );
}

static void WriteOmfRecord( void )
{
    WriteNew( omfRec, omfRec->basic.len + 3 );
}

static void WriteTimeStamp( sym_file *file )
{
    OmfRecord   rec;
    unsigned_8  sum;
    unsigned    i;

    rec.time.type = CMD_COMENT;
    rec.time.len = sizeof( rec.time ) - 3;
    rec.time.attribute = CMT_TNP | CMT_TNL;
    rec.time.class = CMT_LINKER_DIRECTIVE;
    rec.time.subclass = LDIR_OBJ_TIMESTAMP;
    rec.time.stamp = file->arch.date;
    rec.time.chksum = 0;
    sum = 0;
    for( i = 0; i < sizeof( rec.time ); ++i ) {
        sum += rec.chkcalc[i];
    }
    rec.time.chksum = -sum;
    WriteNew( &rec, sizeof( rec.time ) );
}

void WriteOmfLibTrailer( void )
{
    unsigned    size;

    size = DIC_REC_SIZE - LibTell( NewLibrary ) % DIC_REC_SIZE;
    if( omfRecLen < size ){
        omfRecLen = size;
        MemFree( omfRec );
        omfRec = MemAlloc( size );
    }
    memset( omfRec, 0, size );
    omfRec->basic.type = LIB_TRAILER_REC;
    omfRec->basic.len = size - 3;
    WriteOmfRecord();
}

void WriteOmfLibHeader( unsigned_32 dict_offset, unsigned_16 dict_size )
{
    OmfRecord  rec;     // i didn't use omfRec because page size can be quite big
    LibSeek( NewLibrary, 0, SEEK_SET );
    rec.lib_header.type = LIB_HEADER_REC;
    rec.lib_header.page_size = Options.page_size - 3;
    rec.lib_header.dict_offset = dict_offset;
    rec.lib_header.dict_size = dict_size;
    if( Options.respect_case ){
        rec.lib_header.flags = 1;
    } else {
        rec.lib_header.flags = 0;
    }
    WriteNew( &rec, sizeof( rec.lib_header ) );
}

static int isPrime( unsigned num )
{
    unsigned *test_p;
    unsigned p;

    for( test_p = PrimeNos;; ++test_p ) {
        if( *test_p == 0 ){
            return ( -1 );
        }
        p = *test_p;
        if(( p * p ) > num ) break;
        if(( num % p ) == 0 ) {
            return( FALSE );
        }
    }
    return( TRUE );
}


/*
 * Find the prime number of dictionary pages
 */
static unsigned NextPrime( unsigned maj )
{
    int test;

    if( maj > 2 )  {
        maj |= 1;               /* make it odd */
        do{
            test = isPrime( maj );
            maj += 2;
        } while( test == 0 );
        maj -= 2;
        if ( test == -1 ){
            return( 0 );
        }
    }
    return( maj );
}

#define _rotl( a, b )   ( ( a << b ) | ( a >> ( 16 - b ) ) )
#define _rotr( a, b )   ( ( a << ( 16 - b ) ) | ( a  >> b ) )

static bool InsertOmfDict( OmfLibBlock *lib_block, unsigned num_blocks,
    char *sym, unsigned len, unsigned_16 offset )
{
    char            *leftptr;
    char            *rightptr;
    unsigned_16     curr;
    unsigned_16     block;
    unsigned_16     bucket;
    unsigned_16     dblock;
    unsigned_16     dbucket;
    unsigned        count;
    unsigned int    loc;
    unsigned int    entry_len;
    unsigned int    i;
    unsigned int    j;

    count = len;
    leftptr = sym;
    rightptr = leftptr + count;
    block = count | 0x20;
    dblock = 0;
    bucket = 0;
    dbucket = count | 0x20;
    for( ;; ) {
        --rightptr;
        /* zap to lower case (sort of) */
        curr = *rightptr | 0x20;
        dblock = curr ^ _rotl( dblock, 2 );
        bucket = curr ^ _rotr( bucket, 2 );
        if( --count == 0 ) {
            break;
        }
        curr = *leftptr | 0x20;
        ++leftptr;
        block = curr ^ _rotl( block, 2 );
        dbucket = curr ^ _rotr( dbucket, 2 );
    }
    bucket %= NUM_BUCKETS;
    dbucket %= NUM_BUCKETS;
    if( dbucket == 0 ) {
        dbucket = 1;
    }
    block %= num_blocks;
    dblock %= num_blocks;
    if( dblock == 0 ) {
        dblock = 1;
    }
    entry_len = (len | 1) + 3  ;
    for( i = 0; i < num_blocks; i++ ) {
        loc = lib_block[block].fflag * 2;
        for( j = 0; j < NUM_BUCKETS; j++ ){
            if( lib_block[block].htab[bucket] == 0 ) {
                if( ( DIC_REC_SIZE - loc - 2 ) < entry_len ){

⌨️ 快捷键说明

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