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 + -
显示快捷键?