madman.c

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

C
2,275
字号
/****************************************************************************
*
*                            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:  Machine Architecture Description manager - generic routines.
*
****************************************************************************/


#include <string.h>
#include <ctype.h>
#include <limits.h>
#include <float.h>
#include <stdlib.h>
#include <stdio.h>
#include <stddef.h>
#include <i64.h>
#include "mad.h"
#include "madimp.h"
#include "madcli.h"
#include "xfloat.h"

#if defined( __386__ ) || defined( __I86__ ) || defined( __ALPHA__ ) || defined( __PPC__ ) || defined( __MIPS__ )
   #define MNR_HOST_SIGNED      MNR_TWOS_COMP
   #define FLOAT_IEEE
#else
   #error Host MAD type info not configured
#endif

#if defined( __BIG_ENDIAN__ )
    #define ME_HOST             ME_BIG
#else
    #define ME_HOST             ME_LITTLE
#endif

const static unsigned EndMap[2][8] = {
        /* ME_LITTLE */ { 0, 1, 2, 3, 4, 5, 6, 7 },
        /* ME_BIG */    { 7, 6, 5, 4, 3, 2, 1, 0 },
};

struct mad_state_data {
    mad_state_data      *next;
    /* followed by the imp_mad_state structure */
};

typedef struct mad_entry mad_entry;
struct mad_entry {
    mad_entry           *next;
    char                *file;
    char                *desc;
    mad_imp_routines    *rtns;
    mad_state_data      *sl;
    mad_handle          mh;
    unsigned long       sh;
};

static mad_entry        *MADList;
static mad_entry        *Active;

/*
 * System specific support routines
 */
mad_status      MADSysLoad( char *, mad_client_routines *,
                                mad_imp_routines **, unsigned long * );
void            MADSysUnload( unsigned long );

/*
 * Client interface
 */


static mad_status DIGCLIENT MADCliTypeInfoForHost( mad_type_kind tk, int size, mad_type_info *mti )
{
    return( MADTypeInfoForHost( tk, size, mti ) );
}

static mad_status DIGCLIENT MADCliTypeConvert( const mad_type_info *in_t, const void *in_d, const mad_type_info *out_t, void *out_d, addr_seg seg )
{
    return( MADTypeConvert( in_t, in_d, out_t, out_d, seg ) );
}

static mad_status DIGCLIENT MADCliTypeToString( unsigned radix, const mad_type_info *mti, const void *data, unsigned *max, char *buff )
{
    return( MADTypeToString( radix, mti, data, max, buff ) );
}

mad_client_routines MADClientInterface = {
    MAD_MAJOR,
    MAD_MINOR_OLD, //NYI: change to MAD_MINOR when everybody's updated
    sizeof( mad_client_routines ),

    DIGCliAlloc,
    DIGCliRealloc,
    DIGCliFree,

    DIGCliOpen,
    DIGCliSeek,
    DIGCliRead,
    DIGCliClose,

    MADCliReadMem,
    MADCliWriteMem,

    MADCliString,
    MADCliAddString,
    MADCliRadixPrefix,

    MADCliNotify,

    DIGCliMachineData,

    MADCliAddrToString,
    MADCliMemExpr,

    MADCliAddrSection,
    MADCliAddrOvlReturn,

    MADCliSystemConfig,

    MADCliTypeInfoForHost,
    MADCliTypeConvert,
    MADCliTypeToString
};

/*
 *      Support Routines
 */

static mad_imp_routines DummyRtns;      /* forward reference */

static mad_entry        Dummy =
        { NULL, "", "Unknown Architecture", &DummyRtns, MAD_NIL, 0 };

static const mad_string EmptyStrList[] = { MSTR_NIL };
static const mad_toggle_strings EmptyToggleList[] = { { MSTR_NIL }, { MSTR_NIL }, { MSTR_NIL } };

static mad_status MADStatus( mad_status ms )
{
    MADCliNotify( MNT_ERROR, &ms );
    return( ms );
}

static mad_entry *MADFind( mad_handle mh )
{
    mad_entry   *curr;

    if( mh == MAD_NIL ) return( NULL );
    if( mh == Active->mh ) return( Active );
    for( curr = MADList; curr != NULL; curr = curr->next ) {
        if( curr->mh == mh ) return( curr );
    }
    return( NULL );
}


/*
 *      Control Routines
 */

mad_status      MADInit( void )
{
    static const struct {
        mad_handle      mh;
        const char      *file;
        const char      *desc;
    } list[] = {
        { MAD_X86,      "madx86",       "Intel Architecture [80(x)86]" },
        { MAD_AXP,      "madaxp",       "Alpha Architecture" },
        { MAD_PPC,      "madppc",       "PowerPC Architecture" },
        { MAD_MIPS,     "madmips",      "MIPS Architecture" },
        { MAD_MSJ,      "msj",          "Java Virtual Machine (Microsoft)" }
    };

    mad_status  ms;
    unsigned    i;

    MADList = NULL;
    Active = &Dummy;
    for( i = 0; i < sizeof( list ) / sizeof( list[0] ); ++i ) {
        ms = MADRegister( list[i].mh, list[i].file, list[i].desc );
        if( ms != MS_OK ) return( ms );
    }
    return( ms );
}

mad_status      MADRegister( mad_handle mh, const char *file, const char *desc )
{
    mad_entry   **owner;
    mad_entry   *curr;
    mad_entry   *old;
    unsigned    file_len;
    unsigned    desc_len;

    owner = &MADList;
    for( ;; ) {
        curr = *owner;
        if( curr == NULL ) break;
        if( curr->mh == mh ) {
            *owner = curr->next;
            old = Active;
            Active = curr;
            while( curr->sl != NULL ) {
                MADStateDestroy( curr->sl );
            }
            Active = old;
            if( curr == Active ) Active = &Dummy;
            /* MADUnload( curr->mh );  Did not work from here. */
            /* Removed call, and moved fixed functionality here */
                if( curr->rtns != NULL ) {
                    curr->rtns->MIFini();
                    curr->rtns = NULL;
                }
                if( curr->sh != 0 ) MADSysUnload( curr->sh );
            DIGCliFree( curr );
            break;
        }
        owner = &curr->next;
    }
    if( file == NULL ) return( MS_OK );
    file_len = strlen( file );
    desc_len = strlen( desc );
    curr = DIGCliAlloc( (sizeof( *curr ) + 2) + file_len + desc_len );
    if( curr == NULL ) return( MADStatus( MS_ERR | MS_NO_MEM ) );
    curr->next = *owner;
    *owner = curr;
    curr->file = (char *)curr + sizeof( *curr );
    curr->desc = &curr->file[ file_len + 1 ];
    curr->rtns = NULL;
    curr->sl   = NULL;
    curr->mh   = mh;
    curr->sh   = 0;
    strcpy( curr->file, file );
    strcpy( curr->desc, desc );
    return( MS_OK );
}

static mad_status DIGREGISTER DummyInit( void )
{
    /* never actually called */
    return( MS_OK );
}

mad_status      MADLoad( mad_handle mh )
{
    mad_entry           *me;
    mad_status          ms;

    me = MADFind( mh );
    if( me == NULL ) return( MADStatus( MS_ERR | MS_UNREGISTERED_MAD ) );
    if( me->rtns != NULL ) return( MS_OK );
    ms = MADSysLoad( me->file, &MADClientInterface, &me->rtns, &me->sh );
    if( ms != MS_OK ) {
        me->rtns = NULL;
        return( MADStatus( ms ) );
    }
    if( MADClientInterface.major != me->rtns->major
     || MADClientInterface.minor > me->rtns->minor ) {
        me->rtns = NULL;
        MADUnload( mh );
        return( MADStatus( MS_ERR|MS_INVALID_MAD_VERSION ) );
    }
    ms = me->rtns->MIInit();
    if( ms != MS_OK ) {
        me->rtns = NULL;
        MADUnload( mh );
        return( MADStatus( ms ) );
    }
    if( me->sl == NULL ) {
        me->sl = DIGCliAlloc( sizeof( *me->sl ) + me->rtns->MIStateSize() );
        if( me->sl == NULL ) {
            MADUnload( mh );
            return( MADStatus( MS_ERR|MS_NO_MEM ) );
        }
        me->rtns->MIStateInit( (imp_mad_state_data *)&me->sl[1] );
        me->sl->next = NULL;
    }
    Active->rtns->MIStateSet( (imp_mad_state_data *)&me->sl[1] );
    return( MS_OK );
}

static void DIGREGISTER DummyFini( void )
{
    /* never actually called */
}

void            MADUnload( mad_handle mh )
{
    mad_entry   *me;

    me = MADFind( mh );
    if( me == NULL ) return;
    if( me->rtns != NULL ) {
        me->rtns->MIFini();
        me->rtns = NULL;
    }
    if( me->sh != 0 ) {
        MADSysUnload( me->sh );
    }
}

mad_status      MADLoaded( mad_handle mh )
{
    mad_entry   *me;

    me = MADFind( mh );
    if( me == NULL ) return( MADStatus( MS_ERR|MS_UNREGISTERED_MAD ) );
    return( me->rtns != NULL ? MS_OK : MS_FAIL );
}

mad_handle      MADActiveSet( mad_handle mh )
{
    mad_handle  old;
    mad_entry   *me;

    old = Active->mh;
    me = MADFind( mh );
    if( me != NULL ) Active = me;
    return( old );
}

static unsigned DIGREGISTER DummyStateSize( void )
{
    return( 0 );
}

static void DIGREGISTER DummyStateInit( imp_mad_state_data *msd )
{
    msd = msd;
}

static void DIGREGISTER DummyStateSet( imp_mad_state_data *msd )
{
    msd = msd;
}

static void DIGREGISTER DummyStateCopy( const imp_mad_state_data *src, imp_mad_state_data *dst )
{
    src = src;
    dst = dst;
}

mad_state_data  *MADStateCreate( void )
{
    mad_state_data      *new;

    new = DIGCliAlloc( sizeof( *new ) + Active->rtns->MIStateSize() );
    if( new == NULL ) {
        MADStatus( MS_ERR | MS_NO_MEM );
        return( NULL );
    }
    /* first one is currently active state */
    new->next = Active->sl->next;
    Active->sl->next = new;
    Active->rtns->MIStateInit( (imp_mad_state_data *)&new[1] );
    return( new );
}

mad_state_data  *MADStateSet( mad_state_data *msd )
{
    mad_state_data      **owner;
    mad_state_data      *curr;

    if( msd == NULL ) return( Active->sl );
    owner = &Active->sl;
    for( ;; ) {
        curr = *owner;
        if( curr == NULL ) {
            MADStatus( MS_ERR|MS_NO_MEM );
            return( Active->sl );
        }
        if( curr == msd ) break;
        owner = &curr->next;
    }
    curr = Active->sl;
    *owner = msd->next;
    msd->next = curr;
    Active->sl = msd;
    Active->rtns->MIStateSet( (imp_mad_state_data *)&msd[1] );
    return( curr );
}

void            MADStateCopy( const mad_state_data *src, mad_state_data *dst )
{
    Active->rtns->MIStateCopy( (const imp_mad_state_data *)&src[1], (imp_mad_state_data *)&dst[1] );
}

void            MADStateDestroy( mad_state_data *msd )
{
    mad_state_data      **owner;
    mad_state_data      *curr;

    owner = &Active->sl;
    for( ;; ) {
        curr = *owner;
        if( curr == NULL ) {
            MADStatus( MS_ERR|MS_INVALID_STATE );
            return;
        }
        if( curr == msd ) break;
        owner = &curr->next;
    }
    *owner = msd->next;
    DIGCliFree( msd );
}

void            MADFini( void )
{
    while( MADList != NULL ) {
        MADRegister( MADList->mh, NULL, NULL );
    }
}

walk_result     MADWalk( MAD_WALKER *wk, void *d )
{
    walk_result wr;
    mad_entry   *me;

    for( me = MADList; me != NULL; me = me->next ) {
        wr = wk( me->mh, d );
        if( wr != WR_CONTINUE ) return( wr );
    }
    return( WR_CONTINUE );
}

unsigned        MADNameFile( mad_handle mh, unsigned max, char *name )
{
    mad_entry   *me;
    unsigned    len;

    me = MADFind( mh );
    if( me == NULL ) {
        MADStatus( MS_ERR|MS_UNREGISTERED_MAD );
        return( 0 );

⌨️ 快捷键说明

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