symtable.c

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

C
1,080
字号
    char        buff[20];
    char        *stringpad = NULL;
    int         stringpadlen = 0;


    SortSymbols();

    // figure out this dictionary sizes

    switch( Options.libtype ) {
        case WL_TYPE_AR:
            dict1_size = sizeof( unsigned_32 )
                       + NumSymbols * sizeof(unsigned_32)
                       + RoundWord( TotalSymbolLength );

            dict2_size = sizeof( unsigned_32 )
                       + NumFiles * sizeof( unsigned_32 )
                       + sizeof( unsigned_32 )
                       + NumSymbols * sizeof( unsigned_16 )
                       + RoundWord( TotalSymbolLength );

            header_size = AR_IDENT_LEN
                        + 3 * AR_HEADER_SIZE
                        + dict1_size
                        + dict2_size
                        + RoundWord( TotalNameLength );
            stringpad   = "\0";
            stringpadlen= 1;
            break;
        case WL_TYPE_MLIB:
            dict2_size = sizeof( unsigned_32 )
                        + NumSymbols * (1 + sizeof( unsigned_32 ) )
                        + TotalSymbolLength;

            header_size = LIBMAG_LEN + LIB_CLASS_LEN + LIB_DATA_LEN
                        + 3 * LIB_HEADER_SIZE
                        + RoundWord( dict2_size )
                        + RoundWord( TotalNameLength )
                        + RoundWord( TotalFFNameLength );
            stringpad   = LIB_LONG_NAME_END_STRING;
            stringpadlen= LIB_LONG_NAME_END_STRING_LEN;
            break;
    }

    // calculate the object files offsets

    index = 0;
    obj_offset = 0;
    for( file = FileTable.first; file != NULL; file = file->next ) {
        file->new_offset = obj_offset + header_size;
        file->index = ++index;
        obj_offset += RoundWord( file->arch.size ) + AR_HEADER_SIZE;
    }

    switch( Options.libtype ) {
        case WL_TYPE_AR:
            WriteNew( AR_IDENT, AR_IDENT_LEN );
            break;
        case WL_TYPE_MLIB:
            WriteNew( LIBMAG, LIBMAG_LEN );
            WriteNew( LIB_CLASS_DATA_SHOULDBE, LIB_CLASS_LEN + LIB_DATA_LEN );
            break;
    }

    // write the useless dictionary

    arch.date = currenttime;
    arch.uid = 0;
    arch.gid = 0;
    arch.mode = 0;
    if( Options.libtype == WL_TYPE_AR ) {
        arch.size = dict1_size;
        arch.name = "/";
        WriteFileHeader( &arch );

        WriteBigEndian32( NumSymbols );
        for( file = FileTable.first; file != NULL; file = file->next ) {
            for( sym = file->first; sym != NULL; sym = sym->next ) {
                WriteBigEndian32( sym->file->new_offset );
            }
        }
        for( file = FileTable.first; file != NULL; file = file->next ) {
            for( sym = file->first; sym != NULL; sym = sym->next ) {
                WriteNew( sym->name, sym->len+1 );
            }
        }
        WritePad( TotalSymbolLength );
    }

    // write the useful dictionary

    arch.size = dict2_size;
    arch.name = "/";
    WriteFileHeader( &arch );

    if( Options.libtype == WL_TYPE_AR ) {
        WriteLittleEndian32( NumFiles );
        for( file = FileTable.first; file != NULL; file = file->next ) {
            WriteLittleEndian32( file->new_offset );
        }
    }

    WriteLittleEndian32( NumSymbols );
    switch( Options.libtype ) {
        case WL_TYPE_AR:
            for( i = 0; i < NumSymbols; ++i ) {
                WriteLittleEndian16( SortedSymbols[i]->file->index );
            }
            break;
        case WL_TYPE_MLIB:
            for( i = 0; i < NumSymbols; ++i ) {
                WriteLittleEndian32( SortedSymbols[i]->file->index );
            }
            for( i=0; i < NumSymbols; ++i ) {
                WriteNew( &(SortedSymbols[i]->info), 1 );
            }
            break;
    }
    for( i = 0; i < NumSymbols; ++i ) {
        WriteNew( SortedSymbols[i]->name, SortedSymbols[i]->len + 1 );
    }
    switch( Options.libtype ) {
        case WL_TYPE_AR:
            WritePad( TotalSymbolLength );
            break;
        case WL_TYPE_MLIB:
            WritePad( dict2_size );
            break;
    }

    // write the string table

    arch.size = TotalNameLength;
    arch.name = "//";
    WriteFileHeader( &arch );
    for( file = FileTable.first; file != NULL; file = file->next ) {
        if( file->name_offset == -1 ) continue;
        // Always write the "full" filename for AR
        if( Options.libtype == WL_TYPE_AR && file->arch.ffname ) {
            WriteNew( file->arch.ffname, file->ffname_length );
        } else {
            WriteNew( file->arch.name, file->name_length );
        }
        WriteNew( stringpad, stringpadlen );
    }
    WritePad( TotalNameLength );

    // write the full filename table

    if( Options.libtype == WL_TYPE_MLIB ) {
        arch.size = TotalFFNameLength;
        arch.name = "///";
        WriteFileHeader( &arch );
        for( file=FileTable.first; file != NULL; file = file->next ) {
            WriteNew( file->arch.ffname, file->ffname_length + 1 );
        }
        WritePad( TotalFFNameLength );
    }

    for( file = FileTable.first; file != NULL; file = file->next ) {
        arch = file->arch;
        buff[0] = '/';
        itoa( file->name_offset, buff+1, 10 );
        arch.name = buff;
        WriteFileHeader( &arch );
        if( file->import == NULL ){
            if( file->inlib_offset != 0 ) {
                LibSeek( InLibHandle( file->inlib ), file->inlib_offset, SEEK_SET );
                Copy( InLibHandle( file->inlib ), NewLibrary, arch.size );
            } else {
                io = LibOpen( file->full_name, LIBOPEN_BINARY_READ );
                Copy( io, NewLibrary, arch.size );
                LibClose( io );
            }
        }else{
            switch( file->import->type ) {
                case ELF:
                case ELFRENAMED:
                    ElfWriteImport( NewLibrary, file );
                    break;
                default:
                    CoffWriteImport( NewLibrary, file );
                    break;
            }
        }
        WritePad( file->arch.size );
    }
}

void WriteFileTable( void )
/*************************/
{
    if( Options.libtype == 0 && Options.omf_found ) {
        if( Options.coff_found ) {
            Options.libtype = WL_TYPE_AR;
        } else {
            Options.libtype = WL_TYPE_OMF;
            }
        }
    if( Options.coff_found && (Options.libtype == 0 || Options.libtype == WL_TYPE_OMF) ) {
        Options.libtype = WL_TYPE_AR;
    }
    if( Options.elf_found && (Options.libtype == 0 || Options.libtype == WL_TYPE_OMF) ) {
        Options.libtype = WL_TYPE_AR;
    }
    if( Options.libtype == WL_TYPE_AR || Options.libtype == WL_TYPE_MLIB ) {
        WriteArMlibFileTable();
    } else {
        WriteOmfFileTable();
    }
}

static int Hash( char *string, unsigned *plen )
/*********************************************/
{
    unsigned long       g;
    unsigned long       h;

    h = 0;
    *plen = 0;
    while( *string != 0 ) {
        h = ( h << 4 ) + *string;
        if( (g = h & 0xf0000000) ) {
            h = h ^ ( g >> 24 );
            h = h ^ g;
        }
        ++string;
        ++*plen;
    }
    return( h % HASH_SIZE );
}

void AddSym( char *name, symbol_strength strength, unsigned char info )
/*********************************************************************/
{
    sym_entry   *sym,**owner;
    int         hash;
    unsigned    name_len;

    hash = Hash( name, &name_len );
    for( sym = HashTable[ hash ]; sym != NULL; sym = sym->hash ) {
        if( sym->len != name_len ) continue;
        if( SymbolNameCmp( sym->name, name ) == 0 ) {
            if( strength > sym->strength ) {
                owner = &sym->file->first;
                while( *owner != sym ) {
                    owner = &(*owner)->next;
                }
                *owner = sym->next;
                owner = &HashTable[ hash ];
                while( *owner != sym ) {
                    owner = &(*owner)->hash;
                }
                *owner = sym->hash;
                MemFreeGlobal( sym );
                break; //db
            } else if( strength == sym->strength ) {
                if( strength == SYM_STRONG ) {
                    Warning( ERR_DUPLICATE_SYMBOL, FormSym( name ) );
                }
            }
            return;
        }
    }
    sym = MemAllocGlobal( sizeof(sym_entry) + name_len );
    sym->len = name_len;
    sym->strength = strength;
    sym->info = info;
    memcpy( sym->name, name, name_len + 1 );
    sym->next = CurrFile->first;
    CurrFile->first = sym;
    sym->file = CurrFile;
    sym->hash = HashTable[ hash ];
    HashTable[ hash ] = sym;
}


#ifdef __DEBUG__
void DumpFileTable( void )
{
    sym_file    *file;
    sym_entry   *entry;
    sym_entry   *hash;
    unsigned    len;
    int         hval;
    long        files    = 0L;
    long        symbols  = 0L;

    printf("----------------------------------------------------------\n");
    printf("File Table Dump\n");
    printf("----------------------------------------------------------\n");

    for (file = FileTable.first; file; file = file->next) {
        ++files;
        printf("File: \"%s\"\n", file->full_name);
        for (entry = file->first; entry; entry = entry->next) {
            ++symbols;

            hval = Hash(entry->name, &len);
            printf("\t\"%s\" (%d, %u, \"%s\")", entry->name, hval, len,
                (HashTable[hval] ? HashTable[hval]->name : "(NULL)"));

            for (hash = entry->hash; hash; hash = hash->hash) {
                printf(" -> \"%s\"", hash->name);
                fflush(stdout);
            }
            printf("\n");
        }
    }
    printf("----------------------------------------------------------\n");
    printf("Files         : %ld\n", files);
    printf("Symbols       : %ld\n", symbols);
    printf("----------------------------------------------------------\n");
} /* DumpFileTable() */


void DumpHashTable( void )
{
    sym_entry   *hash;
    int         i;
    int         length;

    printf("----------------------------------------------------------\n");
    printf("Hash Table Dump\n");
    printf("----------------------------------------------------------\n");

    for (i = 0; i < HASH_SIZE; ++i) {
        length = 0;

        if (HashTable[i]) {
            for (hash = HashTable[i]; hash; hash = hash->next) {
                ++length;
            }
        }

        printf("Offset %6d: %d\n", i, length);
    }
    printf("----------------------------------------------------------\n");
} /* DumpHashTable() */
#endif // __DEBUG__


bool RemoveObjectSymbols( char *name )
/************************************/
{
    sym_file    *file;
    sym_file    *prev;
    sym_entry   *sym;

    prev = NULL;
    for( file = FileTable.first; file != NULL; file = file->next ) {
        if( SymbolNameCmp( file->full_name, name ) == 0 ) {
            if (prev) { /* Not deleting from head of list */
                prev->next = file->next;

                if( FileTable.add_to == &file->next ){ /* Last node in list */
                    FileTable.add_to = &prev->next;
                }
            } else {
                if (FileTable.add_to == &file->next) { /* Only node in list */

⌨️ 快捷键说明

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