⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 exeres.c

📁 开放源码的编译器open watcom 1.6.0版的源代码
💻 C
字号:
/****************************************************************************
*
*                            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:  NE resource manipulation routines, Windows version.
*
****************************************************************************/


#include <unistd.h>
#include <string.h>
#include <ctype.h>
#include "watcom.h"
#include "exeos2.h"
#include "wresall.h"
#include "global.h"
#include "errors.h"
#include "rctypes.h"
#include "rcmem.h"
#include "rcstr.h"
#include "exeutil.h"
#include "exeres.h"
#include "iortns.h"


extern void InitResTable( void )
/******************************/
{
    ExeResDir           *res;
    StringBlock         *str;
    WResDir             dir;

    res = &(Pass2Info.TmpFile.u.NEInfo.Res.Dir);
    str = &(Pass2Info.TmpFile.u.NEInfo.Res.Str);
    dir = Pass2Info.ResFiles->Dir;

    if( CmdLineParms.NoResFile ) {
        res->NumTypes = 0;
        /* the 2 uint_16 are the resource shift count and the type 0 record */
        res->TableSize = 2 * sizeof( uint_16 );
        res->Head = NULL;
        res->Tail = NULL;

        str->StringBlockSize = 0;
        str->StringBlock = NULL;
        str->StringListLen = 0;
        str->StringList = NULL;

    } else {
        res->NumTypes = WResGetNumTypes( dir );
        res->NumResources = WResGetNumResources( dir );
        /* the 2 uint_16 are the resource shift count and the type 0 record */
        res->TableSize = res->NumTypes * sizeof( resource_type_record ) +
                            res->NumResources * sizeof( resource_record ) +
                            2 * sizeof( uint_16 );
        res->Head = NULL;
        res->Tail = NULL;

        StringBlockBuild( str, dir, FALSE );
    }
} /* InitResTable */


extern uint_32 ComputeResourceSize( WResDir dir )
/***********************************************/
{
    uint_32         length;
    WResDirWindow   wind;
    WResLangInfo    *res;

    length = 0;
    wind = WResFirstResource( dir );
    while( !WResIsEmptyWindow( wind ) ) {
        res = WResGetLangInfo( wind );
        length += res->Length;
        wind = WResNextResource( wind, dir );
    }
    return( length );
} /* ComputeResourceSize */


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 );
} /* findResOrTypeName */

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

    exe_type = RcMemMalloc( 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;

    /* use the general purpose linked list routines from WRes */
    ResAddLLItemAtEnd( (void **)&(restab->Dir.Head), (void **)&(restab->Dir.Tail), exe_type );

    return( exe_type );
} /* addExeTypeRecord */

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 addExeResRecord( ResTable *restab, FullTypeRecord *type,
                            WResID *name, uint_16 mem_flags,
                            uint_16 exe_offset, uint_16 exe_length )
/******************************************************************/
{
    FullResourceRecord          *exe_res;

    exe_res = RcMemMalloc( 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;

    /* use the general purpose linked list routines from WRes */
    ResAddLLItemAtEnd( (void **)&(type->Head), (void **)&(type->Tail), exe_res );
} /* addExeResRecord */

static RcStatus copyOneResource( ResTable *restab, FullTypeRecord *type,
            WResLangInfo *lang, WResResInfo *res, int reshandle,
            int outhandle, int shift_count, int *err_code )
/**********************************************************************/
{
    RcStatus            error;
    int                 iorc;
    uint_32             out_offset;
    uint_32             align_amount;

    /* align the output file to a boundary for shift_count */
    error = RS_OK;
    out_offset = RcTell( outhandle );
    if( out_offset == -1 ) {
        error = RS_WRITE_ERROR;
        *err_code = errno;
    }
    if( error == RS_OK ) {
        align_amount = AlignAmount( out_offset, shift_count );
        iorc = RcSeek( outhandle, align_amount, SEEK_CUR );
        if( iorc == -1 ) {
            error = RS_WRITE_ERROR;
            *err_code = errno;
        }
        out_offset += align_amount;
    }

    if( error == RS_OK ) {
        iorc = RcSeek( reshandle, lang->Offset, SEEK_SET );
        if( iorc == -1 ) {
            error = RS_READ_ERROR;
            *err_code = errno;
        }
    }
    if( error == RS_OK ) {
        error = CopyExeData( reshandle, outhandle, lang->Length );
        *err_code = errno;
    }
    if( error == RS_OK ) {
        align_amount = AlignAmount( RcTell( outhandle ), shift_count );
        error = PadExeData( outhandle, align_amount );
        *err_code = errno;
    }

    if( !error ) {
        addExeResRecord( restab, type, &(res->ResName), lang->MemoryFlags,
                out_offset >> shift_count,
                (lang->Length + align_amount) >> shift_count );
    }

    return( error );
} /* copyOneResource */

extern int CopyResources( uint_16 sect2mask, uint_16 sect2bits, bool sect2 )
/**************************************************************************/
/* Note: sect2 must be either 1 (do section 2) or 0 (do section 1) */
/* CopyResources should be called twice, once with sect2 false, and once with */
/* it true. The values of sect2mask and sect2bits should be the same for both */
/* calls. The resource table for the temporary file will not be properly */
/* filled in until after the second call */
{
    WResDir             dir;
    WResDirWindow       wind;
    ResTable            *restab;
    FullTypeRecord      *exe_type;
    WResResInfo         *res;
    WResLangInfo        *lang;
    int                 tmphandle;
    int                 reshandle;
    RcStatus            error;
    int                 err_code;

    dir = Pass2Info.ResFiles->Dir;
    restab = &(Pass2Info.TmpFile.u.NEInfo.Res);
    tmphandle = Pass2Info.TmpFile.Handle;
    reshandle = Pass2Info.ResFiles->Handle;
    error = RS_OK;

    /* walk through the WRes directory */
    wind = WResFirstResource( dir );
    exe_type = NULL;
    while( !WResIsEmptyWindow( wind ) ) {
        if( WResIsFirstResOfType( wind ) ) {
            exe_type = findExeTypeRecord( restab, WResGetTypeInfo( wind ) );
        }

        res = WResGetResInfo( wind );
        lang = WResGetLangInfo( wind );

        /* if the bits are unequal and this is section 1 --> copy segment */
        /* if the bits are equal and this is section 2   --> copy segment */
        /* otherwise                                     --> do nothing */

        if( ARE_BITS_EQUAL( sect2mask, sect2bits, lang->MemoryFlags ) == sect2 ) {
            error = copyOneResource( restab, exe_type, lang, res, reshandle,
                                    tmphandle, restab->Dir.ResShiftCount,
                                    &err_code );
        }

        if( error != RS_OK ) break;

        CheckDebugOffset( &(Pass2Info.TmpFile) );

        wind = WResNextResource( wind, dir );
    }

    switch( error ) {
    case RS_WRITE_ERROR:
        RcError( ERR_WRITTING_FILE, Pass2Info.TmpFile.name,
                 strerror( err_code ) );
        break;
    case RS_READ_ERROR:
        RcError( ERR_READING_RES, CmdLineParms.OutResFileName,
                 strerror( err_code ) );
        break;
    case RS_READ_INCMPLT:
        RcError( ERR_UNEXPECTED_EOF, CmdLineParms.OutResFileName );
        break;
    default:
        break;
    }
    return( error );
} /* CopyResources */


/*
 * writeTypeRecord-
 * NB when an error occurs this function must return without altering errno
 */
static RcStatus writeTypeRecord( int handle, resource_type_record *res )
/**********************************************************************/
{
    int     num_wrote;

    num_wrote = RcWrite( handle, res, sizeof( resource_type_record ) );
    if( num_wrote != sizeof( resource_type_record ) ) {
        return( RS_WRITE_ERROR );
    } else {
        return( RS_OK );
    }
} /* writeTypeRecord */


/*
 * writeResRecord-
 * NB when an error occurs this function must return without altering errno
 */
static RcStatus writeResRecord( int handle, resource_record *type )
/*****************************************************************/
{
    int     num_wrote;

    num_wrote = RcWrite( handle, type, sizeof( resource_record ) );
    if( num_wrote != sizeof( resource_record ) ) {
        return( RS_WRITE_ERROR );
    } else {
        return( RS_OK );
    }
} /* writeResRecord */


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;

            RcMemFree( old_res );
        }

        old_type = exe_type;
        exe_type = exe_type->Next;

        RcMemFree( old_type );
    }

    restab->Dir.Head = NULL;
    restab->Dir.Tail = NULL;
} /* freeResTable */


/*
 * writeStringBlock
 * NB when an error occurs this function must return without altering errno
 */
static int writeStringBlock( int handle, StringBlock *str )
/*********************************************************/
{
    int     numwrote;

    if( str->StringBlockSize > 0 ) {
        numwrote = RcWrite( handle, str->StringBlock, str->StringBlockSize );
        if( numwrote != str->StringBlockSize ) {
            return( RS_WRITE_ERROR );
        }
    }
    return( RS_OK );
} /* writeStringBlock */

/*
 * WriteResTable
 * NB when an error occurs this function must return without altering errno
 */
extern RcStatus WriteResTable( int handle, ResTable *restab, int *err_code )
/**************************************************************************/
{
    FullTypeRecord              *exe_type;
    FullResourceRecord          *exe_res;
    int                         num_wrote;
    int                         error;
    uint_16                     zero;

    error = RS_OK;
    num_wrote = RcWrite( handle, &(restab->Dir.ResShiftCount), sizeof( uint_16 ) );
    if( num_wrote != sizeof( uint_16 ) ) {
        error = RS_WRITE_ERROR;
    }

    for( exe_type = restab->Dir.Head; exe_type != NULL && error == RS_OK;
            exe_type = exe_type->Next ) {
        error = writeTypeRecord( handle, &(exe_type->Info) );

        for( exe_res = exe_type->Head; exe_res != NULL && error == RS_OK;
                exe_res = exe_res->Next ) {
            error = writeResRecord( handle, &(exe_res->Info) );
        }
    }

    if( error == RS_OK ) {
        zero = 0;
        num_wrote = RcWrite( handle, &zero, sizeof( uint_16 ) );
        if( num_wrote != sizeof( uint_16 ) ) {
            error = RS_WRITE_ERROR;
        }
    }

    if( error == RS_OK ) {
        error = writeStringBlock( handle, &(restab->Str) );
    }
    *err_code = errno;
    freeResTable( restab );

    return( error );
} /* WriteResTable */

⌨️ 快捷键说明

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