loados2.c

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

C
1,176
字号
/****************************************************************************
*
*                            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:  Utilities for processing creation of NE format files,
*               used by 16-bit OS/2 and Windows.
*
****************************************************************************/


#include <string.h>
#include <ctype.h>
#include "linkstd.h"
#include "ring.h"
#include "pcobj.h"
#include "newmem.h"
#include "msg.h"
#include "alloc.h"
#include "reloc.h"
#include "exeos2.h"
#include "exeflat.h"
#include "exepe.h"
#include "exedos.h"
#include "loadfile.h"
#include "specials.h"
#include "wlnkmsg.h"
#include "virtmem.h"
#include "objcalc.h"
#include "fileio.h"
#include "objfree.h"
#include "objpass1.h"
#include "dbgall.h"
#include "objstrip.h"
#include "strtab.h"
#include "carve.h"
#include "permdata.h"
#include "loadpe.h"
#include "rcstr.h"
#include "wres.h"
#include "loados2.h"
#include "impexp.h"

typedef struct FullResourceRecord {
    struct FullResourceRecord * Next;
    struct FullResourceRecord * Prev;
    resource_record             Info;
} FullResourceRecord;

typedef struct FullTypeRecord {
    struct FullTypeRecord * Next;
    struct FullTypeRecord * Prev;
    FullResourceRecord *    Head;
    FullResourceRecord *    Tail;
    resource_type_record    Info;
} FullTypeRecord;

typedef struct ExeResDir {
    uint_16             ResShiftCount;
    uint_16             NumTypes;
    uint_16             NumResources;
    uint_16             TableSize;
    FullTypeRecord *    Head;
    FullTypeRecord *    Tail;
} ExeResDir;

typedef struct ResTable {
    ExeResDir   Dir;
    StringBlock Str;
} ResTable;

extern  unsigned_32      Write_Stub_File( void );

static  void             SetGroupFlags( void );

static  char            DosStub[] = {
        0x4D, 0x5A, 0x80, 0x00, 0x01, 0x00, 0x00, 0x00,
        0x04, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00,
        0xB8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
        0x0E, 0x1F, 0xBA, 0x0E, 0x00, 0xB4, 0x09, 0xCD,
        0x21, 0xB8, 0x01, 0x4C, 0xCD, 0x21 };

static unsigned long WriteOS2Relocs( group_entry *group )
/*******************************************************/
/* write all relocs associated with group to the file */
{
    unsigned long relocsize;
    unsigned long relocnum;

    relocsize = RelocSize( group->g.grp_relocs );
    relocnum = relocsize / sizeof(os2_reloc_item);
    if( relocnum == 0 ) return 0;
    WriteLoad( &relocnum, 2 );
    DumpRelocList( group->g.grp_relocs );
    return( relocsize );
}

static void WriteOS2Data( unsigned_32 stub_len, os2_exe_header *exe_head )
/************************************************************************/
/* copy code from extra memory to loadfile. */
{
    group_entry *       group;
    unsigned            group_num;
    unsigned long       off;
    segment_record      segrec;
    unsigned_32         seg_addr;
    unsigned long       relocsize;

    DEBUG(( DBG_BASE, "Writing data" ));

    group_num = 0;
    for( group = Groups; group != NULL; group = group->next_group ) {
        if( group->totalsize == 0 ) continue;   // DANGER DANGER DANGER <--!!!
        segrec.info = group->segflags;
        // write segment
        segrec.min = MAKE_EVEN( group->totalsize );
        segrec.size = MAKE_EVEN( group->size );
        if( segrec.size != 0 ) {
            off = NullAlign( 1 << FmtData.u.os2.segment_shift );
            seg_addr = off >> FmtData.u.os2.segment_shift;
            if( seg_addr > 0xffff ) {
                LnkMsg( ERR+MSG_ALIGN_TOO_SMALL, NULL );
            };
            segrec.address = (unsigned_16)seg_addr;
            WriteGroupLoad( group );
            if( group->size & 0x1 ) {
                PadLoad( 1 );       // segment must be even length
            }
            relocsize = WriteOS2Relocs( group );
            if (relocsize != 0) {
                segrec.info |= SEG_RELOC;
            }

        } else {
            segrec.address = 0;
        }

        // write to segment table
        off = PosLoad();
        SeekLoad( exe_head->segment_off + stub_len +
                            group_num * sizeof(segment_record) );
        WriteLoad( &segrec, sizeof(segment_record) );
        SeekLoad( off );
        group_num++;
    }
}

static void AddLLItemAtEnd( void **head, void **tail, void *item )
/****************************************************************/
{
    struct dllist {
        struct dllist *next;
        struct dllist *prev;
        // SomeDataType some_data;
    } **h, **t, *i;

    h = head; t = tail; i = item;

    i->next = NULL;
    if( *h == NULL ) {
        *h = *t = i;
        i->next = NULL; // prev ptr
    } else {
        i->prev = *t; // prev ptr
        (*t)->next = i;  // next ptr
        *t = i;
    }
}

static uint_16 findResOrTypeName( ResTable * restab, WResID * name )
/******************************************************************/
{
    uint_16     name_id;
    int_32      str_offset;

    if (name->IsName) {
        str_offset = StringBlockFind( &restab->Str, &name->ID.Name );
        if (str_offset == -1 ) {
            name_id = 0;
        } else {
            name_id = str_offset + restab->Dir.TableSize;
        }
    } else {
        name_id = name->ID.Num | 0x8000;
    }

    return( name_id );
}

static FullTypeRecord * addExeTypeRecord( ResTable * restab,
                            WResTypeInfo * type )
/**********************************************************/
{
    FullTypeRecord      *exe_type;

    _ChkAlloc( exe_type, sizeof(FullTypeRecord) );

    exe_type->Info.reserved = 0;
    exe_type->Info.num_resources = type->NumResources;
    exe_type->Info.type = findResOrTypeName( restab, &(type->TypeName) );
    exe_type->Head = NULL;
    exe_type->Tail = NULL;
    exe_type->Next = NULL;
    exe_type->Prev = NULL;

    AddLLItemAtEnd( &(restab->Dir.Head), &(restab->Dir.Tail), exe_type );

    return( exe_type );
}

static void addExeResRecord( ResTable *restab, FullTypeRecord *type,
                            WResID *name, uint_16 mem_flags,
                            uint_16 exe_offset, uint_16 exe_length )
/********************************************************************/
{
    FullResourceRecord          *exe_res;

    _ChkAlloc( exe_res, sizeof(FullResourceRecord) );
    exe_res->Info.offset = exe_offset;
    exe_res->Info.length = exe_length;
    exe_res->Info.flags = mem_flags;
    exe_res->Info.reserved = 0;
    exe_res->Info.name = findResOrTypeName( restab, name );
    exe_res->Next = NULL;
    exe_res->Prev = NULL;
    AddLLItemAtEnd( &(type->Head), &(type->Tail), exe_res );
}

static FullTypeRecord * findExeTypeRecord( ResTable * restab,
                            WResTypeInfo * type )
/***********************************************************/
{
    FullTypeRecord      *exe_type;
    StringItem16        *exe_type_name;

    for (exe_type = restab->Dir.Head; exe_type != NULL;
                exe_type = exe_type->Next) {
        if (type->TypeName.IsName && !(exe_type->Info.type & 0x8000)) {
            /* if they are both names */
            exe_type_name = (StringItem16 *) ((char *) restab->Str.StringBlock +
                            (exe_type->Info.type - restab->Dir.TableSize));
            if( exe_type_name->NumChars == type->TypeName.ID.Name.NumChars
                && !memicmp( exe_type_name->Name, type->TypeName.ID.Name.Name,
                            exe_type_name->NumChars ) ) break;
        } else if (!(type->TypeName.IsName) && exe_type->Info.type & 0x8000) {
            /* if they are both numbers */
            if (type->TypeName.ID.Num == (exe_type->Info.type & ~0x8000)) {
                break;
            }
        }
    }
    if (exe_type == NULL) {              /* this is a new type */
        exe_type = addExeTypeRecord( restab, type );
    }
    return( exe_type );
} /* findExeTypeRecord */

static void FreeResTable( ResTable *restab )
/*******************************************/
{
    FullTypeRecord              *exe_type;
    FullTypeRecord              *old_type;
    FullResourceRecord          *exe_res;
    FullResourceRecord          *old_res;

    exe_type = restab->Dir.Head;
    while (exe_type != NULL) {
        exe_res = exe_type->Head;
        while (exe_res != NULL) {
            old_res = exe_res;
            exe_res = exe_res->Next;

            _LnkFree( old_res );
        }

        old_type = exe_type;
        exe_type = exe_type->Next;

        _LnkFree( old_type );
    }

    restab->Dir.Head = NULL;
    restab->Dir.Tail = NULL;
}

static void WriteResTable( ResTable *restab )
/*******************************************/
{
    FullTypeRecord *    exe_type;
    FullResourceRecord *exe_res;
    uint_16             zero;

    WriteLoad( &FmtData.u.os2.segment_shift, sizeof(uint_16) );
    for( exe_type = restab->Dir.Head; exe_type != NULL;
                                        exe_type = exe_type->Next) {
        WriteLoad( &(exe_type->Info), sizeof(resource_type_record) );
        for( exe_res = exe_type->Head; exe_res != NULL;
                                        exe_res = exe_res->Next ) {
            WriteLoad( &(exe_res->Info) , sizeof(resource_record));
        }
    }
    zero = 0;
    WriteLoad( &zero, sizeof(uint_16) );
    WriteLoad( restab->Str.StringBlock, restab->Str.StringBlockSize );
}

static void CopyResData( int resHandle, int len )
/***********************************************/
{
    char buff[512];

    for( ;len > 512; len -= 512 ) {
        QRead( resHandle, buff, 512, FmtData.resource );
        WriteLoad( buff, 512 );
    }
    QRead( resHandle, buff, len, FmtData.resource );
    WriteLoad( buff, len);
}

static void WriteOS2Resources( int reshandle, WResDir inRes, ResTable *outRes )
/*****************************************************************************/
{
    int shift_count = FmtData.u.os2.segment_shift;
    int align = 1 << shift_count;
    int outRes_off;
    WResDirWindow       wind;
    FullTypeRecord      *exe_type;
    WResResInfo         *res;
    WResLangInfo        *lang;

    if( inRes == NULL ) return;
    outRes_off = NullAlign(align) >> shift_count;
    /* walk through the WRes directory */
    wind = WResFirstResource( inRes );
    while (!WResIsEmptyWindow( wind )) {
        lang = WResGetLangInfo( wind );

        if (WResIsFirstResOfType( wind )) {
            exe_type = findExeTypeRecord( outRes, WResGetTypeInfo( wind ) );
        }
        res = WResGetResInfo( wind );
        addExeResRecord( outRes, exe_type, &(res->ResName),
                        lang->MemoryFlags, outRes_off,
                        (lang->Length + align - 1) >> shift_count );
        QSeek( reshandle, lang->Offset, FmtData.resource );
        CopyResData( reshandle, lang->Length );
        NullAlign( align );
        outRes_off += (lang->Length + align - 1) >> shift_count;

        wind = WResNextResource( wind, inRes );
    }
    NullAlign(align);
}


static unsigned long WriteTabList( name_list * val, unsigned long *count,
                                   bool upper)
/***********************************************************************/
{
    name_list   *       node;
    unsigned long       off;
    unsigned long       i;
    int                 j;

    i = 0;
    off = 0;

⌨️ 快捷键说明

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