symtable.c

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

C
1,080
字号
/****************************************************************************
*
*                            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:  Librarian symbol table processing.
*
****************************************************************************/


#include <wlib.h>

static sym_table        FileTable;
sym_file                *CurrFile;
static sym_entry        **HashTable;
static sym_entry        **SortedSymbols;

#define HASH_SIZE       256

static int Hash( char *string, unsigned *plen );

void InitFileTab( void )
/**********************/
{
    FileTable.first = NULL;
    FileTable.add_to = &FileTable.first;
    SortedSymbols = NULL;
    HashTable = MemAllocGlobal( HASH_SIZE * sizeof( HashTable[0] ) );
    memset( HashTable, 0, HASH_SIZE * sizeof( HashTable[0] ) );
}

void FiniSymFile( sym_file *file )
/********************************/
{
    sym_entry           *sym, *next_sym;
    elf_import_sym      *temp;

    for( sym = file->first; sym != NULL; sym = next_sym ) {
        next_sym = sym->next;
        MemFreeGlobal( sym );
    }
    MemFreeGlobal( file->full_name );
    MemFreeGlobal( file->arch.name );
    MemFreeGlobal( file->arch.ffname );
    if( file->import != NULL ) {
        switch( file->import->type ) {
        case ELF:
        case ELFRENAMED:
            for( temp=file->import->symlist; temp!=NULL;
                         temp=file->import->symlist ) {
                file->import->symlist = temp->next;
                MemFreeGlobal( temp->name );
                MemFreeGlobal( temp );
            }
            MemFreeGlobal( file->import->DLLName );
            break;
        default:
            MemFreeGlobal( file->import->DLLName );
            MemFreeGlobal( file->import->symName );
            MemFreeGlobal( file->import->exportedName );
            break;
        }
        MemFreeGlobal( file->import );
    }
    MemFreeGlobal( file );
}


void CleanFileTab( void )
/***********************/
{
    sym_file *last = NULL;
    sym_file *curr;
    sym_file *next;

    for (curr = FileTable.first; curr; curr = next) {
        next = curr->next;

        /*
         * If curr->first is NULL then either this file contains no
         * symbols or we are ignoring all of them.  Remove the file.
         */
        if (!curr->first) {
            if (last) {
                last->next = curr->next;
            } else {
                FileTable.first = curr->next;
            }

            if (&(curr->next) == FileTable.add_to) {
                if (last) {
                    FileTable.add_to = &(last->next);
                } else {
                    FileTable.add_to = &(FileTable.first);
                }
            }

            FiniSymFile(curr);
        } else {
            last = curr;
        }
    } /* for */
} /* CleanFileTab() */


void ResetFileTab( void )
/***********************/
{
    sym_file            *file, *next_file;

    memset( HashTable, 0, HASH_SIZE * sizeof( HashTable[0] ) );
    for( file = FileTable.first; file != NULL; file = next_file ) {
        next_file = file->next;
        FiniSymFile( file );
    }
    FileTable.first = NULL;
    FileTable.add_to = &FileTable.first;
    MemFreeGlobal( SortedSymbols );
    SortedSymbols = NULL;
}

void FiniFileTab( void )
/***********************/
{
    MemFreeGlobal( HashTable );
}


void RemoveFromHashTable( sym_entry *sym )
/****************************************/
{
    sym_entry *hash;
    sym_entry *prev;
    int        hval;
    unsigned   len;

    hval = Hash(sym->name, &len);
    hash = HashTable[hval];

    if (hash == sym) {
        HashTable[hval] = sym->hash;
    } else if (hash) {
        prev = hash;

        for (hash = hash->hash; hash; hash = hash->hash) {
            if (hash == sym) {
                prev->hash = hash->hash;
                break;
            } else {
                prev = hash;
            }
        }
    }
} /* RemoveFromHashTable() */


static void NewSymFile( arch_header *arch )
/*****************************************/
{
    sym_file    *file;

    file = MemAllocGlobal( sizeof(sym_file) );
    file->first = NULL;
    file->next = NULL;
    file->arch = *arch;
    file->import = NULL;
    file->inlib_offset = 0;
    file->full_name = DupStrGlobal( file->arch.name );
    file->arch.name = DupStrGlobal( TrimPath( file->arch.name ) ); // make own copy
    file->name_length = strlen( file->arch.name );
    if( file->arch.ffname ) {
        file->arch.ffname = DupStrGlobal( file->arch.ffname );
        file->ffname_length = strlen( file->arch.ffname );
    } else {
        file->ffname_length = 0;
    }
    *(FileTable.add_to) = file;
    FileTable.add_to = &file->next;
    CurrFile = file;
}



static int CompSyms( const void *ap, const void *bp )
/***************************************************/
{
    const sym_entry *a = *(const sym_entry**)ap;
    const sym_entry *b = *(const sym_entry**)bp;
    return( strcmp( a->name, b->name ) );
}

static void WriteFileHeader( arch_header *arch )
/**********************************************/
{
    ar_header   ar;

    CreateARHeader( &ar, arch );
    WriteNew( &ar, AR_HEADER_SIZE );
}

static void WritePad( file_offset size )
/**************************************/
{
    if( NeedsRounding( size ) ) {
        WriteNew( AR_FILE_PADDING_STRING, 1 );
    }
}

static long             NumFiles;
static long             NumSymbols;
static file_offset      TotalNameLength;
static file_offset      TotalFFNameLength;
static file_offset      TotalSymbolLength;

static void SortSymbols( void )
/*****************************/
{
    sym_file *  file;
    sym_entry * sym;
    sym_entry   **sym_curr;
    int         i;
    int         name_length = 0;
    int         name_extra = 0;

    NumFiles = 0;
    NumSymbols = 0;
    TotalNameLength = 0;
    TotalFFNameLength = 0;
    TotalSymbolLength = 0;
    switch( Options.libtype ) {
        case WL_TYPE_AR:
            name_extra = 1;
            break;
        case WL_TYPE_MLIB:
            name_extra = 2;
            break;
    }
    for( file = FileTable.first; file != NULL; file = file->next ) {
        ++NumFiles;
        file->name_offset = TotalNameLength;
        switch( Options.libtype ) {
            case WL_TYPE_AR:
                // Always using "full" filename for AR
                if( file->arch.ffname ) {
                    name_length = file->ffname_length;
                } else {
                    file->ffname_length = 0;
                    name_length = file->name_length;
                }
                break;
            case WL_TYPE_MLIB:
                // If no full filename, assume name is full, and trim
                // it to get non-full filename.
                if( file->arch.ffname == NULL ) {
                    file->arch.ffname = file->arch.name;
                    file->ffname_length = strlen( file->arch.ffname );
                    file->arch.name = MemAllocGlobal( _MAX_FNAME + _MAX_EXT + 1 );
                    _splitpath( file->arch.ffname, NULL, NULL, file->arch.name, NULL );
                    _splitpath( file->arch.ffname, NULL, NULL, NULL, file->arch.name + strlen( file->arch.name ) );
                    file->name_length = strlen( file->arch.name );
                }
                name_length = file->name_length;
                break;
        }
        TotalNameLength += name_length + name_extra;
        TotalFFNameLength += file->ffname_length + 1;
        for( sym = file->first; sym != NULL; sym = sym->next ) {
            ++NumSymbols;
            TotalSymbolLength += sym->len + 1;
        }
    }

    if( NumSymbols == 0 ) {
        SortedSymbols = NULL;
        Warning( ERR_NO_SYMBOLS );
    } else {
        SortedSymbols = MemAllocGlobal( NumSymbols * sizeof( SortedSymbols[0] ) );
    }

    sym_curr = SortedSymbols;
    for( file = FileTable.first; file != NULL; file = file->next ) {
        for( sym = file->first; sym != NULL; sym = sym->next ) {
            *sym_curr = sym;
            ++sym_curr;
        }
    }

    qsort( SortedSymbols, NumSymbols, sizeof(sym_entry *), CompSyms );

    // re-hook symbols onto files in sorted order

    for( file = FileTable.first; file != NULL; file = file->next ) {
        file->first = NULL;
    }

    for( i = NumSymbols - 1; i >= 0; --i ) {
        sym = SortedSymbols[i];
        sym->next = sym->file->first;
        sym->file->first = sym;
    }
}

static void WriteOmfFileTable( void )
/***********************************/
{
    sym_file    *file;
    unsigned    num_blocks;
    unsigned    dict_offset;

    if( Options.page_size == 0 ){
        Options.page_size = DEFAULT_PAGE_SIZE;
    }
    InitOmfUtil();
    PadOmf( TRUE );

    for( file = FileTable.first; file != NULL; file = file->next ) {
        WriteOmfFile(file);
    }
    WriteOmfLibTrailer();
    dict_offset = LibTell( NewLibrary );
    num_blocks = WriteOmfDict( FileTable.first );
    WriteOmfLibHeader( dict_offset, num_blocks );
    FiniOmfUtil();
}

static void WriteArMlibFileTable( void )
/**************************************/
{
    arch_header arch;
    sym_file    *file;
    sym_entry   *sym;
    file_offset dict1_size = 0;
    file_offset dict2_size = 0;
    file_offset header_size = 0;
    int         i;
    time_t      currenttime = time( NULL );
    file_offset obj_offset;
    int         index;
    libfile     io;

⌨️ 快捷键说明

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