linkutil.c

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

C
617
字号
/*********************************/
/* Free a list of nodes. */
{
    node                *curr = _curr;
    node                *next_node;

    while( curr ) {
        next_node = curr->next;
        _LnkFree( curr );
        curr = next_node;
    }
}

extern name_list * AddNameTable( char *name, unsigned len, bool is_mod,
                                                        name_list **owner )
/*************************************************************************/
{
    name_list * imp;
    unsigned_32 off;
    unsigned_16 index;

    index = 1;
    off = 1;
    for( ;; ) {
        imp = *owner;
        if( imp == NULL ) {
            _PermAlloc( imp, sizeof( name_list ) );
            imp->next = NULL;
            imp->len = len;
            ReserveStringTable( &PermStrings, len + 1 );
            imp->name = AddStringTable( &PermStrings, name, len );
            CharStringTable( &PermStrings, '\0' );
            imp->num = is_mod ? index : off;
            *owner = imp;
            break;
        }
        if( len == imp->len && memcmp( imp->name, name, len ) == 0 )
            break;
        off += imp->len + 1;
        owner = &imp->next;
        ++index;
    }
    return( imp );
}

extern unsigned_16 binary_log( unsigned_16 value )
/************************************************/
// This calculates the binary log of value, truncating decimals.
{
    unsigned_16 log;

    if( value == 0 ) {
        return( 0 );
    }
    log = 15;
    for( ; ; ) {
        if( value & 0x8000 ) {  // done if high bit on
            break;
        }
        value <<= 1;            // shift left and decrease possible log.
        log--;
    }
    return( log );
}

extern unsigned_16 blog_32( unsigned_32 value )
/*********************************************/
// This calculates the binary log of a 32-bit value, truncating decimals.
{
    unsigned_16 log;

    if( value == 0 ) {
        return( 0 );
    }
    log = 31;
    for( ; ; ) {
        if( value & 0x80000000 ) {  // done if high bit on
            break;
        }
        value <<= 1;            // shift left and decrease possible log.
        log--;
    }
    return( log );
}

extern char * RemovePath( char *name, int *len )
/**********************************************/
/* parse name as a filename, "removing" the path and the extension */
/* returns a pointer to the "base" of the filename, and a length without
 * the extension */
{
    char *  dotpoint;
    char *  namestart;
    char *  string;
    char    ch;

    dotpoint = NULL;
    string = namestart = name;
    while( *string != '\0' ) {    // ignore path & extension in module name.
        ch = *string;
        if( ch == '.' ) {
            dotpoint = string;
        }
        if( IS_PATH_SEP( ch ) ) {
            namestart = string + 1;
            dotpoint = NULL;
        }
        string++;
    }
    if( dotpoint != NULL ) {
        *len = dotpoint - namestart;
    } else {
        *len = string - namestart;
    }
    return( namestart );
}

#define MAXDEPTH        ( sizeof( unsigned ) * 8 )

extern void VMemQSort( virt_mem base, unsigned n, unsigned width,
                        void (*swapfn)( virt_mem, virt_mem ),
                        int (*cmpfn)( virt_mem, virt_mem ) )
/***************************************************************/
// qsort stolen from clib, and suitably modified since we need to be able
// to swap parallel arrays.
{
    virt_mem    p1;
    virt_mem    p2;
    virt_mem    mid;
    int         comparison;
    int         last_non_equal_count;
    unsigned    i;
    unsigned    count;
    unsigned    sp;
    auto virt_mem base_stack[MAXDEPTH];
    auto unsigned n_stack[MAXDEPTH];

    sp = 0;
    for( ; ; ) {
        while( n > 1 ) {
            p1 = base + width;
            if( n == 2 ) {
                if( cmpfn( base, p1 ) > 0 ) {
                    swapfn( base, p1 );
                }
                break;
            } else {
                /* store mid element at base for pivot */
                /* this will speed up sorting of a sorted list */
                mid = base + ( n >> 1 ) * width;
                swapfn( base, mid );
                p2 = base;
                count = 0;
                last_non_equal_count = 0;
                for( i = 1; i < n; ++i ) {
                    comparison = cmpfn( p1, base );
                    if( comparison <= 0 ) {
                        p2 += width;
                        count++;
                        if( i != count ) {              /* p1 != p2 */
                            swapfn( p1, p2 );
                        }
                    }
                    if( comparison != 0 )
                        last_non_equal_count = count;
                    p1 += width;
                }
                /* special check to see if all values compared are equal */
                if( ( count == n-1 ) && ( last_non_equal_count == 0 ) )
                    break;
                if( count != 0 ) {  /* store pivot in right spot */
                    swapfn( base, p2 );
                }
#if 0
                qsort( base, count, size, cmp );
                qsort( p2 + size, n - count - 1, size, cmp );
#endif
                n = n - count - 1;          /* calc. size of right part */

                /* The pivot is at p2. It is in its final position.
                   There are count items to the left of the pivot.
                   There are n items to the right of the pivot.
                */

                if( count != last_non_equal_count ) {   /* 18-jul-90 */
                    /*
                       There are last_non_equal_count+1 items to the left
                       of the pivot that still need to be checked.
                       There are (count - (last_non_equal_count+1)) items
                       immediately to the left of the pivot that are
                       equal to the pivot. They are in their final position.
                    */
                    count = last_non_equal_count + 1;
                }
                if( count < n ) {           /* if left part is shorter */
                    base_stack[sp] = p2 + width;  /* - stack right part */
                    n_stack[sp] = n;
                    n = count;
                } else {                    /* right part is shorter */
                    base_stack[sp] = base;  /* - stack left part */
                    n_stack[sp] = count;
                    base = p2 + width;
                }
                ++sp;
            }
        }
        if( sp == 0 )
            break;
        --sp;
        base = base_stack[sp];
        n    = n_stack[sp];
    }
}

static void *SpawnStack;

extern int Spawn( void (*fn)() )
/******************************/
{
    void *  save_env;
    jmp_buf env;
    int     status;

    save_env = SpawnStack;
    SpawnStack = env;
    status = setjmp( env );
    if( status == 0 ) {
        (*fn)();
    }
    SpawnStack = save_env;  /* unwind */
    return( status );
}

extern void Suicide( void )
/*************************/
{
    if( SpawnStack != NULL ) {
        longjmp( SpawnStack, 1 );
    }
}

extern f_handle SearchPath( char *name )
/**************************************/
{
    char *      path;
    f_handle    file;
    char        fullpath[PATH_MAX];

    file = QObjOpen( name );
    if( file != NIL_HANDLE ) {
        return( file );
    }
#if defined( __QNX__ )
    path = "/usr/watcom";
#else
    path = GetEnvString( "PATH" );
#endif
    if( path != NULL ) {
        while( QMakeFileName( &path, name, fullpath ) ) {
            file = QObjOpen( fullpath );
            if( file != NIL_HANDLE ) {
                return( file );
            }
        }
    }
    return( NIL_HANDLE );
}

extern group_entry *FindGroup( segment seg )
/******************************************/
{
    group_entry *group;

    group = Groups;
    for( ;; ) {
        if( group == NULL )
            break;
        if( group->grp_addr.seg == seg )
            break;
        group = group->next_group;
    }
    return( group );
}

extern offset FindLinearAddr( targ_addr *addr )
/*********************************************/
{
    group_entry *group;

    group = FindGroup( addr->seg );
    if( group != NULL ) {
        return( addr->off + ( group->linear - group->grp_addr.off ) );
    }
    return( addr->off );
}

extern offset FindLinearAddr2( targ_addr *addr )
/*********************************************/
{
    group_entry *group;

    group = FindGroup( addr->seg );
    if( group != NULL ) {
        return( addr->off + group->linear + FmtData.base );
    }
    return( addr->off );
}

⌨️ 快捷键说明

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