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

📄 exerespe.c

📁 开放源码的编译器open watcom 1.6.0版的源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
/****************************************************************************
*
*                            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:  WHEN YOU FIGURE OUT WHAT THIS FILE DOES, PLEASE
*               DESCRIBE IT HERE!
*
****************************************************************************/


#include <unistd.h>
#include <time.h>
#include <string.h>
#include <errno.h>
#include "watcom.h"
#include "exepe.h"
#include "wresall.h"
#include "wrmergdi.h"
#include "rcmem.h"
#include "pass2.h"
#include "rcstr.h"
#include "exeutil.h"
#include "exeobj.h"
#include "global.h"
#include "errors.h"
#include "exerespe.h"
#include "iortns.h"

#define RESOURCE_OBJECT_NAME ".rsrc"

#ifndef MAKELANGID
#define MAKELANGID(p, s)       ( ( ( (uint_16)(s) ) << 10 ) | (uint_16)(p) )
#endif

/* structures and routines to manipulate a queue of PEResDirEntry * */
/* This uses a linked list representation despite the overhead of the pointer */
/* since the total number of entries in the queue should be small and this is */
/* easier to code while still being dynamic */

typedef struct QueueNode {
    struct QueueNode *  next;
    PEResDirEntry *     entry;
} QueueNode;

typedef struct DirEntryQueue {
    QueueNode *     front;
    QueueNode *     back;
} DirEntryQueue;

extern int RcPadFile( int, long );

static void QueueInit( DirEntryQueue * queue )
/********************************************/
{
    queue->front = NULL;
    queue->back = NULL;
} /* QueueInit */

static void QueueEmpty( DirEntryQueue * queue )
/*********************************************/
{
    QueueNode * curr;
    QueueNode * old;

    curr = queue->front;
    while( curr != NULL ) {
        old = curr;
        curr = curr->next;
        RcMemFree( old );
    }

    QueueInit( queue );
} /* QueueEmpty */

static int QueueIsEmpty( DirEntryQueue * queue )
/**********************************************/
{
    return( queue->front == NULL );
}

static void QueueAdd( DirEntryQueue * queue, PEResDirEntry * entry )
/******************************************************************/
{
    QueueNode *     new;

    new = RcMemMalloc( sizeof(QueueNode) );
    new->entry = entry;
    new->next = NULL;
    if( queue->front == NULL ) {
        queue->front = new;
        queue->back = new;
    } else {
        queue->back->next = new;
        queue->back = new;
    }
} /* QueueAdd */

static PEResDirEntry * QueueRemove( DirEntryQueue * queue )
/*********************************************************/
{
    QueueNode *     old;
    PEResDirEntry * entry;

    old = queue->front;
    if( old == NULL ) {
        return( NULL );
    }

    queue->front = old->next;
    if( queue->front == NULL ) {
        queue->back = NULL;
    }

    entry = old->entry;
    RcMemFree( old );
    return( entry );
} /* QueueRemove */

static void PEResDirEntryInit( PEResDirEntry * entry, int num_entries )
/*********************************************************************/
{
    entry->Head.flags = 0;
    entry->Head.time_stamp = time( NULL );
    entry->Head.major = 0;
    entry->Head.minor = 0;
    entry->Head.num_name_entries = 0;
    entry->Head.num_id_entries = 0;
    entry->NumUnused = num_entries;
    entry->Children = RcMemMalloc( num_entries * sizeof(PEResEntry) );
}

static void PEResDirAdd( PEResDirEntry * entry, WResID * name,
                    StringBlock * strings )
/***********************************************************/
{
    int             entry_num;
    int_32          name_off;
    PEResEntry *    curr;


    entry_num = entry->Head.num_name_entries + entry->Head.num_id_entries;
    curr = entry->Children + entry_num;
    if( name->IsName ) {
        name_off = StringBlockFind( strings, &name->ID.Name );
        if( name_off == -1 ) {
            /* this case should not happen */
            curr->Entry.id_name = PE_RESOURCE_MASK_ON | 0;
            curr->Name = NULL;
        } else {
            /* This value will be changed later when we know the size of the */
            /* the resource directory */
            curr->Entry.id_name = PE_RESOURCE_MASK_ON | name_off;
            curr->Name = (char *)strings->StringBlock + name_off;
        }
        entry->Head.num_name_entries++;
    } else {
        curr->Entry.id_name = name->ID.Num;
        curr->Name = NULL;
        entry->Head.num_id_entries++;
    }
    entry->NumUnused--;
}


static int PEResDirAddDir( PEResDirEntry * entry, WResID * name,
                    int num_sub_entries, StringBlock * strings )
/***************************************************************/
{
    int             entry_num;
    PEResEntry *    curr;

    if( entry->NumUnused <= 0 ) return( TRUE );

    PEResDirAdd( entry, name, strings );

    entry_num = entry->Head.num_name_entries + entry->Head.num_id_entries - 1;
    curr = entry->Children + entry_num;
    curr->IsDirEntry = TRUE;
    PEResDirEntryInit( &curr->u.Dir, num_sub_entries );

    return( FALSE );
}

static int PEResDirAddData( PEResDirEntry * entry, WResID * name,
                    WResDirWindow wind, StringBlock * strings )
/***************************************************************/
{
    int             entry_num;
    PEResEntry *    curr;

    if( entry->NumUnused <= 0 ) return( TRUE );

    PEResDirAdd( entry, name, strings );

    entry_num = entry->Head.num_name_entries + entry->Head.num_id_entries - 1;
    curr = entry->Children + entry_num;
    curr->IsDirEntry = FALSE;
    curr->u.Data.Wind = wind;
    /* The Data.Entry field will be filled in as the resource is writen */
    return( FALSE );
}

static int AddType( PEResDir * res, WResTypeInfo * type )
/*******************************************************/
{
    return( PEResDirAddDir( &res->Root, &type->TypeName, type->NumResources,
                                &res->String ) );
}

static int AddLang( PEResDir *res, WResDirWindow wind ) {
/*******************************************************/

    int                 entry_num;
    PEResEntry          *currres;
    PEResEntry          *currtype;
    WResLangInfo        *langinfo;
    WResID              lang_id;

    langinfo = WResGetLangInfo( wind );
    /* find the current type */
    entry_num = res->Root.Head.num_name_entries
                + res->Root.Head.num_id_entries - 1;
    currtype = res->Root.Children + entry_num;

    /* find the current resource */
    entry_num = currtype->u.Dir.Head.num_name_entries
                        + currtype->u.Dir.Head.num_id_entries - 1;
    currres = currtype->u.Dir.Children + entry_num;

    lang_id.IsName = FALSE;
    lang_id.ID.Num = MAKELANGID( langinfo->lang.lang, langinfo->lang.sublang );
    if( PEResDirAddData( &currres->u.Dir, &lang_id, wind,
                        &res->String ) ) {
        return( TRUE );
    }
    return( FALSE );
}

static int AddRes( PEResDir * res, WResDirWindow wind )
/*****************************************************/
{
    int             entry_num;
    PEResEntry *    currtype;
    WResResInfo *   resinfo;

    resinfo = WResGetResInfo( wind );

    /* find the current type */
    entry_num = res->Root.Head.num_name_entries + res->Root.Head.num_id_entries;
    currtype = res->Root.Children + entry_num - 1;

    /* Add a directory level for the languages */
    if( PEResDirAddDir( &currtype->u.Dir, &resinfo->ResName,
                        resinfo->NumResources, &res->String ) ) {
        return( TRUE );
    }

    return( FALSE );
}


static int PEResDirBuild( PEResDir * res, WResDir dir )
/*****************************************************/
{
    WResDirWindow   wind;

    if( WResIsEmpty( dir ) ) {
        res->Root.Head.num_name_entries = 0;
        res->Root.Head.num_id_entries = 0;
        res->Root.Children = NULL;
        res->ResRVA = 0;
        res->ResOffset = 0;
        res->ResSize = 0;
    } else {
        StringBlockBuild( &res->String, dir, TRUE );
        res->DirSize = sizeof(resource_dir_header);
        PEResDirEntryInit( &res->Root, WResGetNumTypes( dir ) );
        wind = WResFirstResource( dir );
        while( !WResIsEmptyWindow( wind ) ) {
            if( WResIsFirstResOfType( wind ) ) {
                if( AddType( res, WResGetTypeInfo( wind ) ) ) return( TRUE );
            }
            if( WResIsFirstLangOfRes( wind ) ) {
                if( AddRes( res, wind ) ) return( TRUE );
            }
            AddLang( res, wind );
            wind = WResNextResource( wind, dir );
        }
    }
    return( FALSE );
}

/*
 * traverseTree
 * NB when a visit function returns an error this function MUST return
 *    without altering errno
 */

⌨️ 快捷键说明

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