libr.c

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

C
739
字号
    unsigned long       pos;
    bool                retval;

    if( lib->u.dict == NULL ) {
        if( !CacheOpen( lib ) ) return( NULL );
        if( CheckLibraryType( lib, &pos, TRUE ) == -1 ) return( NULL );
        if( !(lib->status & STAT_IS_LIB) ) {
            BadLibrary( lib );
            return NULL;
        }
    } else {
        if( !CacheOpen( lib ) ) return( NULL );
    }
    if( lib->status & STAT_OMF_LIB ) {
        retval = OMFSearchExtLib( lib, name, &pos );
    } else {
        retval = ARSearchExtLib( lib, name, &pos );
    }
    if( !retval ) return NULL;

/*
    update lib struct since we found desired object file
*/
    obj = NewModEntry();
    obj->location = pos;
    obj->f.source = lib;
    obj->modtime = obj->f.source->file->modtime;
    obj->modinfo = lib->status & DBI_MASK;
    return( obj );
}


static void HashSymbol( hash_entry *hash, char *name )
/****************************************************/
/* Hash specified name. */
{
    unsigned_16     major_class;
    unsigned_16     minor_class;
    unsigned_16     major_inc;
    unsigned_16     minor_inc;
    unsigned_16     count;
    unsigned_16     curr;
    unsigned char * leftptr;
    unsigned char * rightptr;

    count = strlen( name );
    leftptr = name;
    rightptr = leftptr + count;
    major_class = count | 0x20;
    major_inc = 0;
    minor_class = 0;
    minor_inc = count | 0x20;
    for(;;) {
        --rightptr;
        curr = *rightptr | 0x20;/*  zap to lower case (sort of) */
        major_inc = curr ^ Rotl16( major_inc, 2 );
        minor_class = curr ^ Rotr16( minor_class, 2 );
        if( --count == 0 ) break;
        curr = *leftptr | 0x20;
        ++leftptr;
        major_class = curr ^ Rotl16( major_class, 2 );
        minor_inc = curr ^ Rotr16( minor_inc, 2 );
    }
    minor_class = minor_class % 37;
    minor_inc = minor_inc % 37;
    if( minor_inc == 0 ) {
        minor_inc = 1;
    }
    hash->major_class = major_class;
    hash->major_inc = major_inc;
    hash->minor_class = minor_class;
    hash->minor_inc = minor_inc;
}


static bool OMFSearchExtLib( file_list *lib, char *name, unsigned long *off )
/***************************************************************************/
/* Search library for specified member. */
{
    unsigned_16     minor_class;
    unsigned_16     major_count;
    unsigned_16     major_class;
    unsigned_16     major_inc;
    unsigned_16     minor_count;
    unsigned_16     sector;
    hash_entry      hash;
    omf_dict_entry *dict;

    dict = &lib->u.dict->o;
    major_count = dict->pages;
    HashSymbol( &hash, name );
    major_class = hash.major_class % major_count;
    major_inc = hash.major_inc % major_count;
    if( major_inc == 0 ) {
        major_inc = 1;
    }
    minor_class = hash.minor_class;  /* ATK */
    do {/*  over major classes */
        SetDict( lib, major_class );
        minor_count = 37;
        do {/*  over minor classes */
            if( dict->buffer[ minor_class ] == LIB_NOT_FOUND ) {
                if( dict->buffer[ 37 ] != LIB_FULL_PAGE ) return( FALSE );
                break;
            }
            sector = OMFCompName( name, dict->buffer, minor_class );
            if( sector != 0 ) {
                *off = (unsigned long) dict->rec_length * sector;
                return TRUE;
            }
            minor_class += hash.minor_inc;
            if( minor_class >= 37 ) {
                minor_class -= 37;
            }
        } while( !( --minor_count == 0 ) );
        major_class += major_inc;
        if( major_class >= dict->pages ) {
            major_class -= dict->pages;
        }
    } while( !( --major_count == 0 ) );
    return( FALSE );
}

static void SetDict( file_list *lib, unsigned_16 dict_page )
/**********************************************************/
/* set lib->buffer to the dict_page th page in lib 's dictionary */
{
    unsigned_16     pages;
    unsigned_16     num_buckets;
    unsigned_16     residue;
    unsigned_16     bucket;
    unsigned long   off;
    unsigned long   dictoff;
    omf_dict_entry *dict;

    dict = &lib->u.dict->o;
    if( dict->cache == NULL ) {
        pages = dict->pages;
        num_buckets = pages / PAGES_IN_CACHE;
        residue = pages - num_buckets * PAGES_IN_CACHE;
        dict->cache = AllocDict( num_buckets, residue );
        if( dict->cache != NULL ) {
            QSeek( lib->file->handle, dict->start, lib->file->name );
            for( bucket = 0; bucket != num_buckets; ++bucket ) {
                QRead( lib->file->handle, dict->cache[ bucket ],
                    DIC_REC_SIZE * PAGES_IN_CACHE, lib->file->name );
            }
            QRead( lib->file->handle, dict->cache[ bucket ],
                    DIC_REC_SIZE * residue, lib->file->name );
            lib->file->currpos = dict->start + DIC_REC_SIZE * residue +
                (unsigned long)  DIC_REC_SIZE * PAGES_IN_CACHE * num_buckets;
        }
    }
    if( dict->cache == NULL ) {
        off = dict_page;
        off *= DIC_REC_SIZE;
        dictoff = dict->start + off;
        dict->buffer = TokBuff;
        QSeek( lib->file->handle, dictoff, lib->file->name );
        QRead( lib->file->handle, dict->buffer, DIC_REC_SIZE, lib->file->name );
        lib->file->currpos = dictoff + DIC_REC_SIZE;
    } else {
        bucket = dict_page / PAGES_IN_CACHE;
        residue = dict_page - bucket * PAGES_IN_CACHE;
        dict->buffer = (char *)dict->cache[ bucket ] + residue * DIC_REC_SIZE;
    }
}


static void FreeDictCache( void **cache, unsigned_16 buckets )
/************************************************************/
{
    while( buckets != 0 ) {
        _LnkFree( cache[ --buckets ] );
    }
    _LnkFree( cache );
}

static void ** AllocDict( unsigned_16 num_buckets, unsigned_16 residue )
/**********************************************************************/
/* allocate a chunk of dict memory, down from the top */
{
    void **         cache;
    unsigned_16     bucket;

    _LnkAlloc( cache,sizeof( void * ) * ( num_buckets + 1 ) );
    if( cache == NULL ) return( NULL );
    for( bucket = 0; bucket != num_buckets; ++bucket ) {
        _LnkAlloc( cache[ bucket ], DIC_REC_SIZE * PAGES_IN_CACHE );
        if( cache[ bucket ] == NULL ) {
            FreeDictCache( cache, bucket );
            return( NULL );
        }
    }

    if( residue != 0 ) {
        _LnkAlloc( cache[ bucket ], residue * DIC_REC_SIZE );
        if( cache[ bucket ] == NULL ) {
            FreeDictCache( cache, bucket );
            return( NULL );
        }
    } else {
       cache[ bucket ] = NULL;
    }
    return( cache );
}


extern bool DiscardDicts( void )
/******************************/
/* called when dictionaries forced out of dict memory */
{
    omf_dict_entry *    ptr;
    file_list *         curr;

    ptr = NULL;
    for( curr = ObjLibFiles; curr != NULL; curr = curr->next_file ) {
        if( curr->u.dict == NULL ) continue;
        if( curr->status & STAT_AR_LIB ) continue;
        if( curr->u.dict->o.cache == NULL ) continue;
        ptr = &curr->u.dict->o;
    }
    if( ptr == NULL ) return( FALSE ); /* no dicts in memory */
    FreeDictCache( ptr->cache, (ptr->pages/PAGES_IN_CACHE) + 1 );
    ptr->cache = NULL;
    return( TRUE );
}


extern void BurnLibs( void )
/**************************/
/* let dict memory know it's no longer needed */
{
    file_list * temp;
    dict_entry *dict;

    for( temp = ObjLibFiles; temp != NULL; temp = temp->next_file ) {
        if( temp->status & STAT_AR_LIB ) {
            CacheFree( temp, temp->strtab );
            temp->strtab = NULL;
        }
        dict = temp->u.dict;
        if( dict == NULL ) continue;
        if( temp->status & STAT_AR_LIB ) {
            CacheFree( temp, dict->a.filepostab - 1 );
            _LnkFree( dict->a.fnametab );
        } else {
            if( dict->o.cache != NULL ) {
                FreeDictCache( dict->o.cache, (dict->o.pages/PAGES_IN_CACHE)+1);
            }
        }
        _LnkFree( dict );
        temp->u.dict = NULL;
        FreeObjCache( temp );
    }
}

static unsigned_16 OMFCompName( char *name, char *buff, unsigned_16 index )
/*************************************************************************/
/* Compare name. */
{
    int         len;
    unsigned_16 off;
    unsigned_16 returnval;
    size_t      result;

    returnval = 0;
    off = buff[ index ];
    buff += off * 2;
    len = *buff++;
    if( LinkFlags & CASE_FLAG ) {
        result = memcmp( buff, name, len );
    } else {
        result = memicmp( buff, name, len );
    }
    if( result == 0 && name[len] == '\0' ) {
        _TargU16toHost( _GetU16( &buff[ len ] ), returnval );
    }
    return( returnval );
}

static int ARCompName( const void *key, const void *vbase )
/**********************************************************/
{
    char **     base;

    base = (char **)vbase;
    return strcmp( key, *base );
}

static int ARCompIName( const void *key, const void *vbase )
/**********************************************************/
{
    char **     base;

    base = (char **)vbase;
    return stricmp( key, *base );
}

static bool ARSearchExtLib( file_list *lib, char *name, unsigned long *off )
/**************************************************************************/
/* Search AR format library for specified member. */
{
    char **             result;
    ar_dict_entry *     dict;
    unsigned            tabidx;

    dict = &lib->u.dict->a;
    if( LinkFlags & CASE_FLAG ) {
        result = bsearch( name, dict->fnametab, dict->num_entries,
                          sizeof(char *), ARCompName );
    } else {
        result = bsearch( name, dict->fnametab, dict->num_entries,
                          sizeof(char *), ARCompIName );
    }
    if( result != NULL ) {
        tabidx = result - dict->fnametab;
        if (dict->offsettab == NULL)
            *off = dict->filepostab[tabidx];
        else
            *off = dict->filepostab[dict->offsettab[tabidx] - 1];
        return TRUE;
    }
    return FALSE;
}

extern char *GetARName( ar_header *header, file_list *list )
/**********************************************************/
{
    char *              buf;
    char *              name;
    unsigned long       len;

    name = NULL;
    if( header->name[0] == '/' ) {
        len = GetARValue( &header->name[1], AR_NAME_LEN - 1 );
        buf = list->strtab + len;
        len = strlen( buf );
    } else {
        buf = memchr( header->name, '/', AR_NAME_LEN );
        if( buf == NULL ) {
            len = AR_NAME_LEN;
        } else {
            len = buf - header->name;
        }
        buf = header->name;
    }
    if( len > 0 ) {
        _ChkAlloc( name, len + 1 );
        memcpy( name, buf, len );
        name[len] = '\0';
    }
    return( name );
}

extern unsigned long GetARValue( char *str, int max )
/***************************************************/
// get a numeric value from an ar_header
{
    char                save;
    unsigned long       value;

    save = *(str + max);
    *(str + max) = '\0';
    value = strtoul( str, NULL, 10 );
    *(str + max) = save;
    return value;
}

⌨️ 快捷键说明

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