⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fuzzy.c

📁 开放源码的编译器open watcom 1.6.0版的源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
            /*** 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 + -