📄 fuzzy.c
字号:
/*** See if the file exists here ***/
len = strlen( libpaths[count] ) +
( hasbackslash ? 0 : 1 ) +
strlen( filename ) + 1;
tryme = AllocMem( len );
sprintf( tryme, "%s%s%s", libpaths[count],
hasbackslash ? "" : "\\", filename );
rc = access( tryme, F_OK );
if( rc == 0 ) {
return( tryme );
} else {
FreeMem( tryme );
}
}
}
return( NULL );
}
/*
* Collect all external symbols from a library file. Returns 0 on error.
*/
static int handle_lib_file( const char *filename, const char *libpaths[] )
/************************************************************************/
{
char * realpath;
size_t len;
char * options;
const size_t leeway = 10; /* for "-tl" and such */
int rc;
realpath = find_file( filename, libpaths );
if( realpath == NULL ) {
Warning( "Cannot locate '%s'; skipping -- fuzzy name matching may not work",
filename );
return( 0 );
}
len = strlen( realpath );
options = AllocMem( leeway + len + 1 );
sprintf( options, "-tl %s", realpath );
rc = RunDllTool( dllhandle, options );
FreeMem( options );
if( rc ) {
return( 1 );
} else {
return( 0 );
}
}
/*
* Process output from the WLIB DLL.
*/
static int wlib_output( const char *text )
/****************************************/
{
int badness = 0;
if( ( strncmp( text, "Error!", 6 ) == 0 ) ||
( strncmp( text, "Warning!", 8 ) == 0 ) ) {
badness = 1;
}
if( !badness ) {
if( strchr( text, ' ' ) == NULL ) {
InsertHash( hashtable, (void*)DupStrMem( (char*)text ) );
}
return( 1 );
} else {
Warning( "Message from WLIB DLL: %s", text );
return( 0 );
}
}
/*
* WLIB DLL output callback functions.
*/
static IDEBool __stdcall print_message_crlf( IDECBHdl hdl, const char *text )
{
return( (IDEBool)wlib_output( text ) );
}
static IDEBool __stdcall print_with_info2( IDECBHdl hdl, IDEMsgInfo2 *info )
{
return( (IDEBool)wlib_output( info->msg ) );
}
static IDEBool __stdcall print_with_info( IDECBHdl hdl, IDEMsgInfo *info )
{
return( (IDEBool)wlib_output( info->msg ) );
}
/*
* Given a set of object and library files, prepare to use fuzzy linking.
* If symbols cannot be collected from a file, 'callback' will be called
* with the name of the offending file.
*/
void InitFuzzy( const char *objs[], const char *libs[],
const char *libpaths[], FuzzyInitCallback callback )
/******************************************************************/
{
unsigned count;
orl_funcs o_funcs;
orl_handle o_hnd;
int rc = 1;
DllToolCallbacks dllcallbacks;
/*** Create a hash table ***/
hashtable = InitHash( HASH_TABLE_SIZE, hash_symbol_name, hash_compare );
/*** Collect all external symbols from the specified object files ***/
if( objs != NULL ) {
/*** Initialize ORL ***/
o_funcs.read = &obj_read;
o_funcs.seek = &obj_seek;
o_funcs.alloc = &AllocMem;
o_funcs.free = &FreeMem;
o_hnd = ORLInit( &o_funcs );
if( o_hnd == NULL ) {
FatalError( "Got NULL orl_handle." );
}
/*** Scan the file(s) ***/
for( count=0; objs[count]!=NULL; count++ ) {
if( !handle_obj_file( objs[count], o_hnd ) ) {
rc = (*callback)( objs[count] );
if( !rc ) break;
}
}
/*** Tell ORL to go away ***/
if( ORLFini( o_hnd ) != ORL_OKAY ) {
Warning( "Error calling ORLFini." );
}
free_list( bufflist );
}
if( !rc ) return;
/*** Collect all external symbols from the specified library files ***/
if( libs != NULL ) {
/*** Load the WLIB DLL ***/
dllcallbacks.printmessage = NULL;
dllcallbacks.printmessageCRLF = print_message_crlf;
dllcallbacks.printwithinfo2 = print_with_info2;
dllcallbacks.printwithinfo = print_with_info;
dllcallbacks.cookie = NULL;
dllhandle = InitDllTool( DLLTOOL_WLIB, &dllcallbacks );
if( dllhandle == NULL ) {
Warning( "Cannot load WLIB DLL -- fuzzy name matching may not work" );
} else {
/*** Scan the file(s) ***/
for( count=0; libs[count]!=NULL; count++ ) {
if( !handle_lib_file( libs[count], libpaths ) ) {
rc = (*callback)( libs[count] );
if( !rc ) break;
}
}
FiniDllTool( dllhandle );
}
}
}
/*
* Disable the fuzzy linking module, freeing any allocated resources.
*/
void FiniFuzzy( void )
/********************/
{
if( hashtable == NULL ) Zoinks();
FiniHash( hashtable, 1 );
hashtable = NULL;
}
/*
* Check a hash table element during a walk of a hash table bucket.
*/
static int matching_callback( const void *name_, void *info_ )
/************************************************************/
{
const char *name = name_;
MatchingInfo *info = info_;
char matchstr[MAX_SYMBOL_LEN+1];
int addit = 0;
const char * p;
ListElem * newelem;
ListElem * nextelem;
if( name == NULL ) Zoinks();
if( strlen(info->basename)+2 > MAX_SYMBOL_LEN ) Zoinks();
/*** Try to match this symbol ***/
switch( info->findmode ) {
case MATCH_MODE_EXACT:
if( !strcmp( name, info->basename ) ) {
addit = 1;
}
break;
case MATCH_MODE_UNDERBAR_SYMBOL:
sprintf( matchstr, "_%s", info->basename );
if( !strcmp( name, matchstr ) ) {
addit = 1;
}
break;
case MATCH_MODE_SYMBOL_UNDERBAR:
sprintf( matchstr, "%s_", info->basename );
if( !strcmp( name, matchstr ) ) {
addit = 1;
}
break;
case MATCH_MODE_UNDERBAR_SYMBOL_AT_NUMBER:
sprintf( matchstr, "_%s@", info->basename );
if( strstr( name, matchstr ) == name ) {
p = name + strlen( matchstr );
while( isdigit( *p ) ) {
p++;
}
if( *p == '\0' ) {
addit = 1;
}
}
break;
default:
Zoinks();
}
/*** If it matches, add it to the found list ***/
if( addit ) {
nextelem = info->found;
newelem = AllocMem( sizeof( ListElem ) + strlen( name ) );
strcpy( newelem->buff, name );
newelem->next = nextelem;
info->found = newelem;
/*** Keep searching only if multiple matches are possible ***/
if( info->findmode == MATCH_MODE_UNDERBAR_SYMBOL_AT_NUMBER ) {
return( 1 );
} else {
return( 0 );
}
} else {
return( 1 );
}
}
/*
* Perform fuzzy matching on the given symbol. If exactly one match is
* found, a pointer to the real symbol name (in ' quotes) is returned;
* the caller is responsible for freeing this memory. In all other cases,
* NULL is returned.
*/
char *MatchFuzzy( const char *entryname )
/***************************************/
{
MatchingInfo info;
char * retval;
char * tmp;
unsigned numfound = 0;
ListElem * curelem;
if( hashtable == NULL ) Zoinks();
/*** Strip quotes from 'entryname' ***/
tmp = DupStrMem( entryname );
if( *tmp == '\'' ) {
info.basename = DupStrMem( tmp + 1 );
info.basename[ strlen(info.basename) - 1 ] = '\0';
FreeMem( tmp );
} else {
info.basename = tmp;
}
/*** Check for an exact match ***/
info.findmode = MATCH_MODE_EXACT;
info.found = NULL;
WalkBucketHash( hashtable, info.basename, matching_callback, &info );
/*** Check for _symbol ***/
if( info.found == NULL ) {
info.findmode = MATCH_MODE_UNDERBAR_SYMBOL;
WalkBucketHash( hashtable, info.basename, matching_callback, &info );
}
/*** Check for symbol_ ***/
if( info.found == NULL ) {
info.findmode = MATCH_MODE_SYMBOL_UNDERBAR;
WalkBucketHash( hashtable, info.basename, matching_callback, &info );
}
/*** Check for _symbol@number ***/
if( info.found == NULL ) {
info.findmode = MATCH_MODE_UNDERBAR_SYMBOL_AT_NUMBER;
WalkBucketHash( hashtable, info.basename, matching_callback, &info );
}
/*** Count how many matches we got ***/
numfound = 0;
curelem = info.found;
while( curelem != NULL ) {
numfound++;
curelem = curelem->next;
}
/*** If there was more than one match, complain ***/
if( numfound > 1 ) {
Warning( "Symbol with entry name %s has %u matching internal names:",
entryname, numfound );
curelem = info.found;
while( curelem != NULL ) {
Information( "%s", curelem->buff );
curelem = curelem->next;
}
Information( "Symbol will be ignored!" );
}
/*** Return an appropriate value ***/
if( numfound == 1 ) {
retval = DupQuoteStrMem( info.found->buff, '\'' );
} else {
retval = NULL;
}
free_list( info.found );
return( retval );
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -