wat2can1.c

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

C
1,387
字号
        base_type = mapIdx( getIndex() );
        CanTReUse( new_hdl );
        CanTArrayD( base_type, lo_type, hi_type, bounds );
        break;
    default:
/**/    never_reach();
    }
/**/myassert( endOfRecord() );
}

STATIC void typeSubRange( uint_8 type_class ) {

    uint_32     lo;
    uint_32     hi;
    type_handle base_type;
    type_handle new_hdl;

    switch( type_class & 0x0f ) {
    case WAT_SR_BYTE_RANGE:
        lo = get8();
        hi = get8();
        break;
    case WAT_SR_WORD_RANGE:
        lo = get16();
        hi = get16();
        break;
    case WAT_SR_LONG_RANGE:
        lo = get32();
        hi = get32();
        break;
    default:
/**/    never_reach();
    }
    new_hdl = CanTReserve();
    mapAdd( new_hdl );
    base_type = mapIdx( getIndex() );
    CanTReUse( new_hdl );
    CanTSubRange( base_type, lo, hi );
/**/myassert( endOfRecord() );
}

STATIC uint_8 ptrConvTab[] = {
    0,
    CANT_PTR_FAR,
    CANT_PTR_HUGE | CANT_PTR_FAR,
    CANT_PTR_DEREF,
    CANT_PTR_FAR | CANT_PTR_DEREF,
    CANT_PTR_HUGE | CANT_PTR_FAR | CANT_PTR_DEREF,
    CANT_PTR_386,
    CANT_PTR_386 | CANT_PTR_FAR,
    CANT_PTR_386 | CANT_PTR_DEREF,
    CANT_PTR_386 | CANT_PTR_DEREF | CANT_PTR_FAR
};

STATIC void typePointer( uint_8 type_class ) {

    type_handle base_type;
    type_handle new_hdl;

    type_class &= 0x0f;
/**/myassert( type_class < sizeof( ptrConvTab ) / sizeof( uint_8 ) );
    new_hdl = CanTReserve();
    mapAdd( new_hdl );
    base_type = mapIdx( getIndex() );
    CanTReUse( new_hdl );
    CanTPointer( base_type, ptrConvTab[ type_class ] );
/**/myassert( endOfRecord() );
}

STATIC void typeEnumerated( uint_8 type_class ) {

    uint_16     num_consts;
    type_handle base_type;
    enum_const  *enum_c;
    enum_const  *enum_cstop;
    cantype     *type;

/**/myassert( (type_class & 0x0f) == WAT_EN_LIST );
    num_consts = get16();
    base_type = stbToCanT( get8() );
    type = CanTEnum( base_type, num_consts );
    mapAdd( type->hdl );
    enum_c = type->d.enumr.consts;
    if( enum_c != NULL ) {
        enum_cstop = enum_c + num_consts;
        while( enum_c < enum_cstop ) {
            type_class = nextRec();
/**/        myassert( (type_class & 0xf0) == WAT_ENUMERATED );
            splatRec( SPLAT_DONT_COUNT );
            switch( type_class & 0x0f ) {
            case WAT_EN_CONST_BYTE: enum_c->value = get8();     break;
            case WAT_EN_CONST_WORD: enum_c->value = get16();    break;
            case WAT_EN_CONST_LONG: enum_c->value = get32();    break;
            default:
/**/            never_reach();
            }
            enum_c->name = hdlName();
/**/        myassert( endOfRecord() );
            ++enum_c;
        }
    }
    CanTGraph( type );
/**/myassert( endOfRecord() );
}

STATIC void typeStructure( uint_8 type_class ) {

    uint_16         num_fields;
    bitsize         bit_offset;
    uint_8          bit_size;
    cantype         *type;
    struct_field    *field;
    struct_field    *field_stop;

/**/myassert( ( type_class & 0x0f ) == WAT_ST_LIST );
    num_fields = get16();
    if( wat->rec_len > sizeof(unsigned_8) + sizeof(unsigned_16) ) {
        get32();        // skip the size field
    }
    type = CanTStruct( num_fields );
    mapAdd( type->hdl );
    field = type->d.strct.fields;
    if( field != NULL ) {
        field_stop = field + num_fields;
        while( field < field_stop ) {
            type_class = nextRec();
/**/        myassert( ( type_class & 0xf0 ) == WAT_STRUCTURE );
            splatRec( SPLAT_DONT_COUNT );
            switch( type_class & 0x0f ) {
            case WAT_ST_FIELD_BYTE:
            case WAT_ST_BIT_BYTE:
                bit_offset = get8();
                break;
            case WAT_ST_FIELD_WORD:
            case WAT_ST_BIT_WORD:
                bit_offset = get16();
                break;
            case WAT_ST_FIELD_LONG:
            case WAT_ST_BIT_LONG:
                bit_offset = get32();
                break;
            default:
                Fatal( MSG_CPP_EXTENSION );
            }
            bit_offset <<= 3;
            field->bitfield = 0;
            switch( type_class & 0x0f ) {
            case WAT_ST_FIELD_BYTE:
            case WAT_ST_FIELD_WORD:
            case WAT_ST_FIELD_LONG:
                field->type = mapIdx( getIndex() );
                break;
            case WAT_ST_BIT_BYTE:
            case WAT_ST_BIT_WORD:
            case WAT_ST_BIT_LONG:
                field->bitfield = 1;
                bit_offset += (bitsize)get8();
                bit_size = (bitsize)get8();
                field->type = CanTDupSize( mapIdx( getIndex() ), bit_size );
                break;
            default:
/**/            never_reach();
            }
            field->name = hdlName();
            field->bit_offset = bit_offset;
/**/        myassert( endOfRecord() );
            ++field;
        }
    }
    CanTGraph( type );
/**/myassert( endOfRecord() );
}

STATIC void typeProcedure( uint_8 type_class ) {

    type_handle ret_type;
    uint_8      num_parms;
    type_handle proc_type;
    uint_8      proc_class;
    cantype     *type;
    proc_parm   *parm;
    proc_parm   *parm_stop;
    type_handle parm_type;
    uint_16     ret_idx;

    proc_class = 0;
    switch( type_class & 0x0f ) {
    case WAT_PR_NEAR:   proc_class = 0;                         break;
    case WAT_PR_FAR:    proc_class = CANT_PROC_FAR;             break;
    case WAT_PR_NEAR386:proc_class = CANT_PROC_386;             break;
    case WAT_PR_FAR386: proc_class = CANT_PROC_FAR | CANT_PROC_386;break;
    default:
/**/    never_reach();
    }
    proc_type = CanTReserve();
    mapAdd( proc_type );
    ret_idx = getIndex();
    if( ret_idx == 0 ) {
            /* fortran does this! */
        ret_type = stbToCanT( WAT_STB_CLASS_VOID );
    } else {
        ret_type = mapIdx( ret_idx );
    }
    num_parms = get8();
    if( num_parms == 0 ) {
        CanTReUse( proc_type );
        type = CanTProcedure( ret_type, proc_class, num_parms );
    } else {
        parm_type = mapIdx( getIndex() );
        if( num_parms == 1 && ( CanTFind( parm_type ) )->class == CANT_VOID ) {
            /* function has one parameter -- a void parameter... */
            num_parms = 0;
            CanTReUse( proc_type );
            type = CanTProcedure( ret_type, proc_class, num_parms );
        } else {
            CanTReUse( proc_type );
            type = CanTProcedure( ret_type, proc_class, num_parms );
            parm = type->d.proc.parms;
            parm_stop = parm + num_parms;
            for(;;) {
                parm->type = parm_type;
                ++parm;
                if( parm == parm_stop ) break;
                if( endOfRecord() ) {
                    /* too many parameters to fit in one record
                       -- next will be an extended parms record */
                    nextRec();
                }
                parm_type = mapIdx( getIndex() );
            }
        }
    }
    CanTGraph( type );
/**/myassert( endOfRecord() );
}

STATIC void typeCharacterBlock( uint_8 type_class ) {

    uint_32     length_val;
    type_handle length_type;
    addr_handle length_addr;

    switch( type_class & 0x0f ) {
    case WAT_CB_CHAR_BYTE:
        length_val = get8();
        mapAdd( CanTCharB( length_val ) );
        break;
    case WAT_CB_CHAR_WORD:
        length_val = get16();
        mapAdd( CanTCharB( length_val ) );
        break;
    case WAT_CB_CHAR_LONG:
        length_val = get32();
        mapAdd( CanTCharB( length_val ) );
        break;
    case WAT_CB_CHAR_IND:
        length_type = stbToCanT( get8() );
        length_addr = getAddr32();
        mapAdd( CanTCharBI( length_type, length_addr ) );
        break;
    case WAT_CB_CHAR_IND_386:
        length_type = stbToCanT( get8() );
        length_addr = getAddr48();
        mapAdd( CanTCharBI( length_type, length_addr ) );
        break;
    default:
/**/    never_reach();
    }
/**/myassert( endOfRecord() );
}

STATIC void parseType( void ) {

    uint_8      type_class;

    type_class = nextRec();
    if( (type_class & 0xf0) == SPLAT ) {
        wat->ptr += wat->rec_len - 2;
        if( ( type_class & 0x0f ) == 0 ) {
            ++wat->index;               /* we count this splat record */
        }
    } else {
        splatRec( SPLAT_COUNT );
        switch( type_class & 0xf0 ) {
        case WAT_TYPE_NAME:     typeTypeName( type_class );         break;
        case WAT_ARRAY:         typeArray( type_class );            break;
        case WAT_SUBRANGE:      typeSubRange( type_class );         break;
        case WAT_POINTER:       typePointer( type_class );          break;
        case WAT_ENUMERATED:    typeEnumerated( type_class );       break;
        case WAT_STRUCTURE:     typeStructure( type_class );        break;
        case WAT_PROCEDURE:     typeProcedure( type_class );        break;
        case WAT_CHARACTER_BLOCK:typeCharacterBlock( type_class );  break;
        default:
/**/        never_reach();
        }
        ++wat->index;
    }
/**/myassert( endOfRecord() );
}


/*
    Routines for processing Watcom symbolic information

    We use the extra field in the cansymb records for BLOCKs to indicate
    the offset from the start of the code segment of the block.
*/
STATIC symb_handle offMapCur( void ) {

    symb_handle hdl;
    offset_map  *om;

/**/myassert( !parsingTypes );
    hdl = CanSNew( CANS_BLOCK );
    hdl->d.block.end = CANS_NULL;       /* for recursion protection */
    om = MemAlloc( sizeof( *om ) );
    om->next = offsetMap;
    offsetMap = om;
    om->offset = wat->start_rec - ddSymbols->data;
    om->hdl = hdl;
    return( hdl );
}

FORWARD STATIC symb_handle symbCode( uint_8 symb_class );

STATIC symb_handle offMap( uint_16 offset ) {

    offset_map  *om;
    uint_8      symb_class;
    symb_handle ret_hdl;

/**/myassert( !parsingTypes );
    om = offsetMap;
    while( om ) {
        if( om->offset == offset ) {
            return( om->hdl );
        }
        om = om->next;
    }
    /* hasn't been defined yet */
    pushPosn();
    wat->ptr = wat->start_rec = ddSymbols->data + offset;
    wat->rec_len = 0;
    symb_class = nextRec();
    splatRec( SPLAT_COUNT );
/**/myassert( ( symb_class & 0xf0 ) == WAT_CODE );
    ret_hdl = symbCode( symb_class );
    popPosn();
    return( ret_hdl );
}

STATIC void destroyOffsetMap( void ) {

    offset_map  *cur;
    offset_map  *next;

    cur = offsetMap;
    while( cur ) {
        next = cur->next;
        MemFree( cur );
        cur = next;
    }
}

STATIC const register_type watRegMap[] = {
/*WAT_REG_AL    */  CANS_REG_AL,
/*WAT_REG_AH    */  CANS_REG_AH,
/*WAT_REG_BL    */  CANS_REG_BL,
/*WAT_REG_BH    */  CANS_REG_BH,
/*WAT_REG_CL    */  CANS_REG_CL,
/*WAT_REG_CH    */  CANS_REG_CH,
/*WAT_REG_DL    */  CANS_REG_DL,
/*WAT_REG_DH    */  CANS_REG_DH,
/*WAT_REG_AX    */  CANS_REG_AX,
/*WAT_REG_BX    */  CANS_REG_BX,
/*WAT_REG_CX    */  CANS_REG_CX,
/*WAT_REG_DX    */  CANS_REG_DX,
/*WAT_REG_SI    */  CANS_REG_SI,
/*WAT_REG_DI    */  CANS_REG_DI,
/*WAT_REG_BP    */  CANS_REG_BP,
/*WAT_REG_SP    */  CANS_REG_SP,
/*WAT_REG_CS    */  CANS_REG_CS,
/*WAT_REG_SS    */  CANS_REG_SS,
/*WAT_REG_DS    */  CANS_REG_DS,
/*WAT_REG_ES    */  CANS_REG_ES,
/*WAT_REG_ST0   */  CANS_REG_ST0,
/*WAT_REG_ST1   */  CANS_REG_ST1,
/*WAT_REG_ST2   */  CANS_REG_ST2,
/*WAT_REG_ST3   */  CANS_REG_ST3,
/*WAT_REG_ST4   */  CANS_REG_ST4,
/*WAT_REG_ST5   */  CANS_REG_ST5,
/*WAT_REG_ST6   */  CANS_REG_ST6,
/*WAT_REG_ST7   */  CANS_REG_ST7,
/*WAT_REG_EAX   */  CANS_REG_EAX,
/*WAT_REG_EBX   */  CANS_REG_EBX,
/*WAT_REG_ECX   */  CANS_REG_ECX,
/*WAT_REG_EDX   */  CANS_REG_EDX,
/*WAT_REG_ESI   */  CANS_REG_ESI,
/*WAT_REG_EDI   */  CANS_REG_EDI,
/*WAT_REG_EBP   */  CANS_REG_EBP,
/*WAT_REG_ESP   */  CANS_REG_ESP,
/*WAT_REG_FS    */  CANS_REG_FS,
/*WAT_REG_GS    */  CANS_REG_GS
};

STATIC register_type watReg2CanReg( uint_8 wat ) {

/**/myassert( wat <= WAT_REG_GS );
    return( watRegMap[ wat ] );
}

STATIC symb_handle hdlLocation( void ) {

    symb_handle hdl;
    uint_8      loc_class;
    int_32      offset;
    addr_handle addr_hdl;
    int         i;

    loc_class = get8();
    if( loc_class == 0 ) {
        return( CANS_NULL );
    }
    switch( loc_class & 0xf0 ) {
    case WAT_BP_OFFSET:
        switch( loc_class & 0x0f ) {
        case WAT_BP_BYTE:   offset = (int_8)get8();     break;
        case WAT_BP_WORD:   offset = (int_16)get16();   break;
        case WAT_BP_DWORD:  offset = (int_32)get32();   break;
        default:
/**/        never_reach();
        }
        hdl = CanSNew( CANS_BP_OFFSET );
        hdl->d.bpoff.offset = offset;
        break;

    case WAT_MEMORY:
        switch( loc_class & 0x0f ) {
        case WAT_MEM_ADDR_286:  addr_hdl = getAddr32(); break;
        case WAT_MEM_ADDR_386:  addr_hdl = getAddr48(); break;
        default:
            Fatal( MSG_CPP_EXTENSION );
        }
        hdl = CanSNew( CANS_MEM_LOC );
        hdl->d.memloc.mem_hdl = addr_hdl;
        hdl->d.memloc.is_static = 1;
        break;

    case WAT_MULTI_REG:
        loc_class &= 0x0f;
        ++loc_class;
        if( loc_class > CANS_MAX_REGISTERS ) {
            Fatal( MSG_TOO_MANY_REGS );
        }
        hdl = CanSNew( CANS_REGISTER );
        hdl->d.reg.num_regs = loc_class;
        for( i=0; i < loc_class; ++i ) {
            hdl->d.reg.reg[ i ] = watReg2CanReg( get8() );
        }
        break;

    case WAT_REG:
        hdl = CanSNew( CANS_REGISTER );

⌨️ 快捷键说明

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