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 + -
显示快捷键?