libr.c

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

C
739
字号
/****************************************************************************
*
*                            Open Watcom Project
*
*    Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved.
*
*  ========================================================================
*
*    This file contains Original Code and/or Modifications of Original
*    Code as defined in and that are subject to the Sybase Open Watcom
*    Public License version 1.0 (the 'License'). You may not use this file
*    except in compliance with the License. BY USING THIS FILE YOU AGREE TO
*    ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is
*    provided with the Original Code and Modifications, and is also
*    available at www.sybase.com/developer/opensource.
*
*    The Original Code and all software distributed under the License are
*    distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
*    EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM
*    ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF
*    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR
*    NON-INFRINGEMENT. Please see the License for the specific language
*    governing rights and limitations under the License.
*
*  ========================================================================
*
* Description:  WHEN YOU FIGURE OUT WHAT THIS FILE DOES, PLEASE
*               DESCRIBE IT HERE!
*
****************************************************************************/


/*
 *  LIB      : search library file.
 *
 */

#include <stdlib.h>
#include <string.h>
#include "linkstd.h"
#include "pcobj.h"
#include "msg.h"
#include "alloc.h"
#include "wlnkmsg.h"
#include "library.h"
#include "objnode.h"
#include "fileio.h"
#include "objio.h"
#include "objcache.h"
#include <ar.h>

typedef struct omf_dict_entry {
    void **     cache;          /* for extra memory store of dictionary */
    unsigned_32 start;          /* recno of start of dictionary         */
    unsigned_16 pages;          /* number of pages in dictionary        */
    unsigned_16 rec_length;     /* record alignment of obj recs         */
    byte *      buffer;
} omf_dict_entry;

typedef struct ar_dict_entry {
    unsigned_32 *       filepostab;
    unsigned_16 *       offsettab;
    char **             fnametab;
    unsigned_32         num_entries;
} ar_dict_entry;

typedef union dict_entry {
    omf_dict_entry      o;
    ar_dict_entry       a;
} dict_entry;

#define PAGES_IN_CACHE      0x40U

static  bool            OMFSearchExtLib( file_list *, char *, unsigned long * );
static  bool            ARSearchExtLib( file_list *, char *, unsigned long * );
static  unsigned_16     OMFCompName( char *, char *, unsigned_16 );
static  void **         AllocDict( unsigned_16, unsigned_16 );
static  void            SetDict( file_list *, unsigned_16 );

#if (defined( __386__ ) || defined(M_I86)) && defined(__WATCOMC__)
#if defined( __386__ )
#define DATA16   0x66
#else
#define DATA16
#endif

unsigned_16 Rotr16( unsigned_16 value, unsigned_16 shift );
#pragma aux Rotr16 =\
    DATA16 0xd3 0xc8 /* ror ax,cl */ \
    parm            [ax] [cx]   \
    value           [ax];
unsigned_16 Rotl16( unsigned_16 value, unsigned_16 shift );
#pragma aux Rotl16 =\
    DATA16 0xd3 0xc0 /* rol ax,cl */ \
    parm            [ax] [cx]   \
    value           [ax];
#else
static unsigned_16 Rotr16( unsigned_16 value, unsigned_16 shift )
/***************************************************************/
{
    return (value << (16 - shift)) | (value >> shift);
}

static unsigned_16 Rotl16( unsigned_16 value, unsigned_16 shift )
/***************************************************************/
{
    return (value >> (16 - shift)) | (value << shift);
}
#endif

static void BadLibrary( file_list *list )
/***************************************/
{
    list->file->flags |= INSTAT_IOERR;
    _LnkFree( list->u.dict );
    list->u.dict = NULL;
    Locator( list->file->name, NULL, 0 );
    LnkMsg( ERR+MSG_LIB_FILE_ATTR, NULL );
}

static unsigned_32 ReadBigEndian32( unsigned char *buf )
{
    unsigned_32 res = 0;

    res = buf[0];
    res <<= 8;
    res |= buf[1];
    res <<= 8;
    res |= buf[2];
    res <<= 8;
    res |= buf[3];
    return res;
}

static bool ReadARDict( file_list *list, unsigned long *loc, unsigned *numdicts,
                        bool makedict )
/*****************************************************************************/
{
    ar_header *         ar_hdr;
    unsigned long       size;
    ar_dict_entry *     dict;
    char *              data;
    unsigned_32         num;
    unsigned            index;
    bool                retval;

    ar_hdr = CacheRead( list, *loc, sizeof(ar_header) );
    size = GetARValue( ar_hdr->size, AR_SIZE_LEN );
    retval = TRUE;
    if( ar_hdr->name[0] == '/' && ar_hdr->name[1] == ' ' ) {
        *numdicts += 1;
        *loc += sizeof(ar_header);
        if( makedict && (*numdicts == 1 || *numdicts == 2) ) {

            /* a dictionary in an AR archive commonly starts with
               a header marked with '/ '.
               AR archives on Linux commonly have only one dictionary
               which is of the form:

               (all numbers in *big* endian format)
               unsigned_32: number of entries (num)
               num unsigned_32's: offset within AR file of the object file
                 that the symbol name belongs too.
               num zero terminated strings: the symbols themselves
               (unsorted).
               WLIB however calls this the "useless dictionary".

               WLIB generates a second, more efficient dictionary:
               (all numbers in *little* endian format)
               unsigned_32: number of files in object
               nfiles unsigned_32's: offsets of the files within the archive
               unsigned_32: number of entries (num)
               num unsigned_16's: the file number that the symbol belongs to
               num zero terminated strings: the symbols themselves
               (sorted case-sensitively).               

               however WLINK needs to be able to parse both kinds.
               (dict->offsettab == NULL) means that we only know about
               an unsorted dictionary and it will be sorted later.
            */ 

            dict = &list->u.dict->a;
            data = CachePermRead( list, *loc, size );
            if ( *numdicts == 1 ) {
                num = ReadBigEndian32( data ); /* number of symbols */
                data += sizeof(unsigned_32);
                dict->filepostab = (unsigned_32 *) data;
                for( index = 0; index < num; index++ ) {
                    dict->filepostab[index] = ReadBigEndian32(data);
                    data += sizeof(unsigned_32);
                }
                dict->num_entries = num;
                dict->offsettab = NULL;
                dict->fnametab = NULL;
                if( num > 0 ) {
                    _ChkAlloc( dict->fnametab, sizeof(char *) * num );
                }
            } else /* if ( *numdicts == 2 ) */ {
                num = *((unsigned_32 *)data); /* number of files */
                data += sizeof(unsigned_32);
                dict->filepostab = (unsigned_32 *) data; /* first file off */
                data += num * sizeof(unsigned_32);
                num = *((unsigned_32 *)data); /* number of symbols */
                data += sizeof(unsigned_32);
                dict->offsettab = (unsigned_16 *) data; /* first offset */
                data += num * sizeof(unsigned_16);
                dict->num_entries = num;
                if( num > 0 && dict->fnametab == NULL ) {
                    _ChkAlloc( dict->fnametab, sizeof(char *) * num );
                }    
            }
            for( index = 0; index < num; index++ ) {
                dict->fnametab[index] = data;
                data = strchr( data, '\0' ) + 1;
            }
        }
        *loc += MAKE_EVEN( size );
    } else if( ar_hdr->name[0] == '/' && ar_hdr->name[1] == '/' ) {
        *loc += sizeof(ar_header);
        list->strtab = CachePermRead( list, *loc, size );
        *loc += MAKE_EVEN( size );
    } else {
        retval = FALSE;         // found an actual object file
    }
    return retval;
}


static ar_dict_entry *ARDict;   /* pointer to AR dictionary structures */

static int ARCompI( const void *index1, const void *index2 )
/**********************************************************/
{
    return stricmp( ARDict->fnametab[ *(unsigned_16 *)index1 ],
                    ARDict->fnametab[ *(unsigned_16 *)index2 ] );
}

static int ARComp( const void *index1, const void *index2 )
/**********************************************************/
{
    return strcmp( ARDict->fnametab[ *(unsigned_16 *)index1 ],
                   ARDict->fnametab[ *(unsigned_16 *)index2 ] );
}

extern int CheckLibraryType( file_list *list, unsigned long *loc, bool makedict)
/******************************************************************************/
{
    lib_header *        omf_hdr;
    unsigned_8 *        header;
    int                 reclength;
    omf_dict_entry *    omf_dict;
    ar_dict_entry *     ar_dict;
    unsigned            numdicts;

    unsigned_16 *       index_tab;
    unsigned            ix;
    unsigned            ix_next;
    unsigned            ix_save;
    char *              fname_save;
    unsigned_32         offset_save;

    omf_hdr = CacheRead( list, 0, sizeof(lib_header) );
    header = (unsigned_8*) omf_hdr;
    reclength = 0;

    if( makedict ) {
        _ChkAlloc( list->u.dict, sizeof(dict_entry) );
    }
    if( header[0] == 0xf0 && header[1] == 0x01 ) {
        // COFF object for PPC
    } else if( omf_hdr->cmd == LIB_HEADER_REC ) {   // reading from a library
        list->status |= STAT_OMF_LIB;
        omf_dict = &list->u.dict->o;
        _TargU16toHost( omf_hdr->length, reclength );
        reclength += 3;
        if( makedict ) {
            omf_dict->cache = NULL;
            if( omf_hdr->dict_start == 0 || omf_hdr->dict_size == 0 ) {
                BadLibrary( list );
                return -1;
            }
            _TargU16toHost( omf_hdr->dict_size, omf_dict->pages );
            _TargU32toHost( omf_hdr->dict_start, omf_dict->start );
            omf_dict->rec_length = reclength;
        }
        *loc = CalcAlign( sizeof(lib_header), reclength ) + sizeof(lib_header);
    } else if( memcmp( (void *)omf_hdr, AR_IDENT, AR_IDENT_LEN ) == 0 ) {
        list->status |= STAT_AR_LIB;
        reclength = 2;
        *loc = AR_IDENT_LEN;
        numdicts = 0;
        while( ReadARDict( list, loc, &numdicts, makedict ) ) {} // NULL loop
        if( numdicts < 1 && makedict ) {
            Locator( list->file->name, NULL, 0 );
            LnkMsg( ERR+MSG_NO_DICT_FOUND, NULL );
            _LnkFree( list->u.dict );
            list->u.dict = NULL;
            return -1;
        }
        ar_dict = &list->u.dict->a;
        if( (!(LinkFlags & CASE_FLAG) || numdicts == 1) &&
              (ar_dict->num_entries > 0) ) {
            // Create an index table that we will sort to match the
            // case-insensitive sort order that we want for our symbol names.
            _ChkAlloc( index_tab, sizeof(unsigned_16) * ar_dict->num_entries );
            for( ix = 0; ix < ar_dict->num_entries; ix++ ) {
                index_tab[ix] = ix;
            }
            // store the dictionary pointer into memory so we can fetch ar_dict in ARCompI
            ARDict = ar_dict;
            // Sort the index table using the corresponding symbol names
            // to determine the sort order (see ARCompI() for more info).
            if (LinkFlags & CASE_FLAG) {
                qsort( index_tab, ar_dict->num_entries, sizeof(unsigned_16),
                       ARComp );
            } else {
                qsort( index_tab, ar_dict->num_entries, sizeof(unsigned_16),
                       ARCompI );
            }

            // Reorder the function name table (a vector of pointers to
            // symbol names) and the offset table (a vector of 16-bit offsets
            // into the file position table) (see ReadARDict() for info).
            for( ix = 0; ix < ar_dict->num_entries; ) {
                ix_save = ix;
                // If this entry hasn't been corrected
                // then move out the entry that is present
                // so that we can correct it.
                if( ix != index_tab[ix] ) {
                    fname_save = ar_dict->fnametab[ix];
                    if (ar_dict->offsettab == NULL)
                        offset_save = ar_dict->filepostab[ix];
                    else
                        offset_save = ar_dict->offsettab[ix];
                    // Correct all the entries in this sequence
                    for(;;) {
                        ix_next = index_tab[ix];
                        index_tab[ix] = ix;

                        if( ix_next == ix_save ) break;

                        ar_dict->fnametab[ix] = ar_dict->fnametab[ix_next];
                        if (ar_dict->offsettab == NULL)
                            ar_dict->filepostab[ix] = ar_dict->filepostab[ix_next];
                        else
                            ar_dict->offsettab[ix] = ar_dict->offsettab[ix_next];
                        ix = ix_next;
                    }
                    // Update this final entry in the sequence from the
                    // values we set aside.
                    ar_dict->fnametab[ix] = fname_save;
                    if (ar_dict->offsettab == NULL)
                        ar_dict->filepostab[ix] = offset_save;
                    else
                        ar_dict->offsettab[ix] = offset_save;
                }
                ix = ix_save + 1;
            }

            _LnkFree( index_tab );
        }
    }
    return reclength;
}

extern mod_entry * SearchLib( file_list *lib, char *name )
/********************************************************/
/* Search the specified library file for the specified name & make a module */
{
    mod_entry *         obj;

⌨️ 快捷键说明

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