wat2can1.c

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

C
1,387
字号
/****************************************************************************
*
*                            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 <malloc.h>
#include <string.h>
#include <watcom.h>
#include "womp.h"
#include "genutil.h"
#include "watdbg.h"
#include "segment.h"
#include "myassert.h"
#include "cantype.h"
#include "canaddr.h"
#include "memutil.h"
#include "namemgr.h"
#include "cansymb.h"
#include "canmisc.h"
#include "array.h"
#ifndef NDEBUG
#include <io.h>
#include <fcntl.h>
#endif

/*
    The type map is implemented with variable sized arrays. (array.h)
*/
typedef struct {
    type_handle hdl;
} type_map_elm;

/*
    The offset map is a list of DDSymbols->data offsets of CODE_BLOCKs and
    their symb_handle.
*/
typedef struct offset_map {
    struct offset_map   *next;
    uint_16             offset;
    symb_handle         hdl;
} offset_map;

/*
    These structures maintain the current position within ddTypes->data
    or DDSymbols->data according to the boolean parsingTypes.
*/
struct pos {
    struct pos          *next;      /* stack of positions */
    uint_8              *ptr;       /* pointer to current position */
    uint_8              *start_rec; /* start of the current record */
    uint_8              *finish;    /* done when wat->ptr == wat->finish */
    uint_16             index;      /* index of the current record */
    uint_8              rec_len;    /* length of the current record*/
};

#define endOfRecord()   ( wat->ptr - wat->start_rec == wat->rec_len )

/*
    Some pointers we'll allocate memory for
*/
STATIC type_handle      unDefdType;
STATIC type_handle      *stbHdl;    /* table of 128 type_handles */
STATIC struct pos       *wat;
STATIC int              parsingTypes; /* boolean */
STATIC offset_map       *offsetMap;
STATIC symb_handle      headSymb;
STATIC seghdr           *ddTypes;
STATIC seghdr           *ddSymbols;
STATIC array_hdr        *typeMap;
STATIC type_map_elm     typeMapDef;

/*
    When we've processed a record, we splat the record type.  The different
    types indicate whether to count the record towards indexes or not.
    (indicies are not used during the symbol parsing)
*/
enum {
    SPLAT               = 0xf0,
    SPLAT_COUNT         = 0xf0,
    SPLAT_DONT_COUNT    = 0xf1
};
#define splatRec( ch )  ( wat->ptr[-1] = (ch) )

/*
    Routines to move through types buffer
*/
STATIC uint_8 get8( void ) {

    return( *(wat->ptr++) );
}

STATIC uint_16 get16( void ) {

    uint_16 word;

    word = ReadU16( wat->ptr );
    wat->ptr += 2;
    return( word );
}

STATIC uint_32 get32( void ) {

    uint_32 dword;

    dword = ReadU32( wat->ptr );
    wat->ptr += 4;
    return( dword );
}

STATIC uint_16 getIndex( void ) {

    uint_16 index;

    index = get8();
    if( index & 0x80 ) {
        index = ( ( index & 0x7f ) << 8 ) | get8();
    }

    return( index );
}

STATIC addr_handle getAddr32( void ) {

    addr_handle addr;

    if( parsingTypes ) {
        addr = CanACreateHdl( ddTypes, wat->ptr - ddTypes->data, 4 );
    } else {
        addr = CanACreateHdl( ddSymbols, wat->ptr - ddSymbols->data, 4 );
    }
    wat->ptr += 4;
    return( addr );
}

STATIC addr_handle getAddr48( void ) {

    addr_handle addr;

    if( parsingTypes ) {
        addr = CanACreateHdl( ddTypes, wat->ptr - ddTypes->data, 6 );
    } else {
        addr = CanACreateHdl( ddSymbols, wat->ptr - ddSymbols->data, 6 );
    }
    wat->ptr += 6;
    return( addr );
}

STATIC name_handle hdlName( void ) {

    unsigned    len;
    uint_8      *p;

    len = wat->rec_len - ( wat->ptr - wat->start_rec );
    if( len > 0 ) {
        p = wat->ptr;
        wat->ptr += len;
        return( NameAdd( p, len ) );
    } else {
        return( NAME_NULL );
    }
}

STATIC uint_8 hdlScope( void ) {

    unsigned    len;
    uint_8      *p;

    len = wat->rec_len - ( wat->ptr - wat->start_rec );
    if( len > 0 ) {
        p = wat->ptr;
        wat->ptr += len;
        if( memcmp( p, "struct", len ) == 0 ) {
            return( CANT_SCOPE_STRUCT );
        } else if( memcmp( p, "union", len ) == 0 ) {
            return( CANT_SCOPE_UNION );
        } else if( memcmp( p, "enum", len ) == 0 ) {
            return( CANT_SCOPE_ENUM );
        } else if( memcmp( p, "class", len ) == 0 ) {
            Fatal( MSG_CPP_EXTENSION );
        } else {
            p[len] = 0;
            Fatal( MSG_UNS_SCOPE, p );
        }
    }
    return( CANT_SCOPE_NULL );
}

/*
    Routines to manage the stack of buffer positions
*/
STATIC void pushPosn( void ) {

    struct pos *new;

    new = MemAlloc( sizeof( *new ) );
    *new = *wat;
    new->next = wat;
    wat = new;
}

STATIC void popPosn( void ) {

    struct pos *next;

    next = wat->next;
/**/myassert( next != NULL );
    MemFree( wat );
    wat = next;
}

/*
    Routines to move about in the buffer
*/
STATIC int countOrNot( uint_8 type_class ) {

/**/myassert( parsingTypes );
    switch( type_class & 0xf0 ) {
    case WAT_STRUCTURE:
    case WAT_ENUMERATED:
    case SPLAT:
        if( type_class & 0x0f ) {
            return( 0 );
        }
        break;
    }
    return( 1 );
}

STATIC void seekIndex( uint_16 index ) {

    uint_16     walk_index;
    uint_8      *walk_ptr;

/**/myassert( parsingTypes );
    if( wat->index > index ) {
        walk_ptr = ddTypes->data;
        walk_index = 1;
    } else {
        walk_ptr = wat->start_rec;
        walk_index = wat->index;
    }
    while( walk_index < index ) {
        if( walk_ptr[0] > 1 ) {
            walk_index += countOrNot( walk_ptr[1] );
        }
        walk_ptr += walk_ptr[0];
    }
    while( countOrNot( walk_ptr[1] ) == 0 ) {
        walk_ptr += walk_ptr[0];
    }
    wat->index = index;
    wat->ptr = walk_ptr;
}

STATIC uint_8 nextRec( void ) {

    for(;;) {
        wat->start_rec = wat->ptr;
        wat->rec_len = get8();
        if( wat->rec_len > 1 ) {
            return( get8() );
        }
/**/    never_reach();
    }
}

/*
    Routines to handle the mapping of a watcom index to a type_handle.
    mapIdx() takes care of forward references.
*/

STATIC void mapAdd( type_handle hdl ) {
/*
    add to map the mapping wat->index --> hdl
*/
    type_map_elm    *elm;

    elm = ArrNewElm( typeMap, (size_t)wat->index );
    elm->hdl = hdl;
}

STATIC void initTypeMap( void ) {

    type_map_elm    *elm;

    typeMapDef.hdl = unDefdType;
    typeMap = ArrCreate( sizeof( type_map_elm ), &typeMapDef );
    elm = ArrNewElm( typeMap, (size_t)0 );
    elm->hdl = CANT_NULL;
}

STATIC type_handle mapIdx( uint_16 index ) {

    type_map_elm    *elm;
    type_handle     hdl;

    elm = ArrNewElm( typeMap, (size_t)index );
    hdl = elm->hdl;
    if( hdl == unDefdType ) {       /* aha! forward reference!          */
/**/    myassert( parsingTypes );
        pushPosn();                 /* recursively take care of it      */
        seekIndex( index );
        parseType();
        popPosn();
        elm = ArrAccess( typeMap, (size_t)index );
        hdl = elm->hdl;
/**/    myassert( hdl != unDefdType );
    }
    return( hdl );
}

STATIC void finiTypeMap( void ) {

    ArrDestroy( typeMap );
}


/*
    Routines for parsing Watcom Type information
*/

STATIC type_handle stbToCanT( uint_8 stb ) {
/*
    convert a scalar_type_byte to a scalar cant
*/
    bitsize     size;
    uint_8      class;
    type_handle hdl;
#define SS(x)   ((x)>>WAT_STB_CLASS_SHIFT)

    if( stbHdl[ stb ] != unDefdType ) {
        return( stbHdl[ stb ] );
    }

    class = SS( stb & WAT_STB_CLASS_FIELD );
/**/myassert( class <= 4 );
    size = ( ( stb & WAT_STB_SIZE_FIELD ) + 1 ) * 8;
    switch( class ) {
    case SS(WAT_STB_CLASS_SINT):    hdl = CanTInteger( size,1 );break;
    case SS(WAT_STB_CLASS_UINT):    hdl = CanTInteger( size,0 );break;
    case SS(WAT_STB_CLASS_FLOAT):   hdl = CanTReal( size );     break;
    case SS(WAT_STB_CLASS_VOID):    hdl = CanTVoid();           break;
    case SS(WAT_STB_CLASS_COMPLEX): hdl = CanTComplex( size );  break;
    }
    stbHdl[ stb ] = hdl;
    return( hdl );
#undef SS
}

STATIC void typeTypeName( uint_8 type_class ) {

    type_handle new_hdl;
    uint_8      scope;
    type_handle type_hdl;
    name_handle name_hdl;

    type_class &= 0x0f; /* we're interested in low nibble */
    switch( type_class ) {
    case WAT_TN_SCALAR:
        type_hdl = stbToCanT( get8() );
        name_hdl = hdlName();
        if( name_hdl == NAME_NULL ) {   /* no name for type */
            mapAdd( type_hdl );
        } else {
            mapAdd( CanTTypeDef( CANT_NULL, type_hdl, name_hdl ) );
        }
        break;
    case WAT_TN_SCOPE:
            /* FIXME this is a kludge!! */
        mapAdd( 0xff00 | hdlScope() );
        break;
    case WAT_TN_NAME:
        new_hdl = CanTReserve();
        mapAdd( new_hdl );
        scope = (uint_8)mapIdx( getIndex() );
        type_hdl = mapIdx( getIndex() );
        name_hdl = hdlName();
        CanTReUse( new_hdl );
        CanTTypeDef( type_hdl, name_hdl, scope );
        break;
    default:
/**/    never_reach();
    }
/**/myassert( endOfRecord() );
}

STATIC void typeArray( uint_8 type_class ) {

    type_handle new_hdl;
    type_handle index_type;
    type_handle base_type;
    type_handle lo_type;
    type_handle hi_type;
    addr_handle bounds;
    uint_32     high;

    new_hdl = CanTReserve();
    mapAdd( new_hdl );
    type_class &= 0x0f; /* we're interested in low nibble */
    switch( type_class ) {
    case WAT_AY_BYTE_INDEX:
        high = (uint_32)get8();
        base_type = mapIdx( getIndex() );
        CanTReUse( new_hdl );
        CanTArrayZ( base_type, high );
        break;
    case WAT_AY_WORD_INDEX:
        high = (uint_32)get16();
        base_type = mapIdx( getIndex() );
        CanTReUse( new_hdl );
        CanTArrayZ( base_type, high );                  /* 01-may-91 AFS */
        break;
    case WAT_AY_LONG_INDEX:
        high = get32();
        base_type = mapIdx( getIndex() );
        CanTReUse( new_hdl );
        CanTArrayZ( base_type, high );                  /* 01-may-91 AFS */
        break;
    case WAT_AY_TYPE_INDEX:
        index_type = mapIdx( getIndex() );
        base_type = mapIdx( getIndex() );
        CanTReUse( new_hdl );
        CanTArray( base_type, index_type );
        break;
    case WAT_AY_DESC_INDEX:
        lo_type = stbToCanT( get8() );
        hi_type = stbToCanT( get8() );
        bounds = getAddr32();
        base_type = mapIdx( getIndex() );
        CanTReUse( new_hdl );
        CanTArrayD( base_type, lo_type, hi_type, bounds );
        break;
    case WAT_AY_DESC_INDEX_386:
        lo_type = stbToCanT( get8() );
        hi_type = stbToCanT( get8() );
        bounds = getAddr48();

⌨️ 快捷键说明

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