pcorec.c

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

C
899
字号
    return( fix );
}


static  void  FindTarget( char method, thread *trd )
/**************************************************/
{
    trd->datum = NULL;
    trd->address = NULL;
    if( method <= 3 ) {
        if( method == T_SEGWD ) {
            trd->datum = GetTab( GetIndex(), SegTab, TRUE );
        } else if( method == T_GRPWD ) {
            trd->datum = GetTab( GetIndex(), GrpTab, TRUE );
        } else if( method == T_EXTWD ) {
            trd->datum = GetTab( GetIndex(), ExtTab, TRUE );
        } else {    /* method == T_ABSWD */
            trd->address = GetWord();
        }
    }
}


void  THeadr()
/************/

{
    Mod = NewModule();
    Mod->name = GetName( MAX_NAME_LEN );
    if( Options & FORM_ASSEMBLER ) {
        Mod->imp_lookup = HashTableCreate( IMPORT_LOOKUP_TABLE_SIZE,
            HASH_STRING, (hash_table_comparison_func)stricmp );
        if( !Mod->imp_lookup ) {
            SysError( ERR_OUT_OF_MEM, FALSE );
        }
    }
}


void  LName()
/***********/

{
    while( EndOfRecord == FALSE ) {
        PutTab( ++NameIndex, NameTab, GetName( MAX_NAME_LEN ) );
    }
}


void  SegDef()
/************/

{
    uint_32             seg_len;
    segment             *seg;

    char                A;
    char                attr;

    seg = NewSegment();
    PutTab( ++SegIndex, SegTab, seg );
    seg->id = SegIndex;
    seg->attr = GetByte();
    A = _SegAlign( seg );
    if( A == ALIGN_ABS ) {
        seg->address = GetWord();
        if( IsPharLap ) {
            seg->offset = GetLong();
        } else {
            seg->offset = GetWord();
        }
    }
    if( IsPharLap || Is32Record ) {
        seg_len = GetLong();
    } else {
        seg_len = GetWord();
    }
    if( _Size64K( seg ) ) {
            /* FIXME if Is32Record then should be 2 ** 32 */
        seg_len = 0x10000;  /* exactly 64K */
    }
    seg->name = GetTab( GetIndex(), NameTab, FALSE );
    if( strstr( seg->name, WTLSEGStr ) != NULL ) {
        WtlsegPresent = TRUE;
    }
    seg->u.seg.class_name = GetTab( GetIndex(), NameTab, FALSE );
    seg->u.seg.overlay_id = GetIndex();
    seg->size = seg_len;
    seg->start = seg_len;
    if( !IsPharLap ) {
        seg->use_32 = ( seg->attr & 0x01 ) != 0;
    } else if( !EndOfRecord ) {
        attr = GetByte();
        seg->use_32 = ( attr & EASY_USE32_FIELD ) != 0;
        seg->access_attr = attr & EASY_PROTECT_FIELD;
        seg->access_valid = TRUE;
    } else {
        seg->use_32 = TRUE;
        seg->access_valid = FALSE;
    }
}


void ComDat()
/***********/
{
    segment     *seg;
    uint_8      flags;
    uint_8      attr;
    uint_8      align;
    unsigned    grp_id;
    unsigned    seg_id;
    unsigned    lname;

    flags = GetByte();
    attr = GetByte();
    align = GetByte();
    if( IsPharLap || Is32Record ) {
        Offset = GetLong();
    } else {
        Offset = GetWord();
    }
    GetIndex(); /* skip type index */
    grp_id = 0;
    seg_id = 0;
    if( (attr & COMDAT_ALLOC_MASK) == COMDAT_EXPLICIT ) {
        grp_id = GetIndex();
        seg_id = GetIndex();
        if( grp_id == 0 && seg_id == 0 ) {
            GetWord();
        }
    }
    lname = GetIndex();
    if( flags & COMDAT_CONTINUE ) {
        /* old comdat */
        seg = FindComdat( lname );
    } else {
        seg = NewSegment();
        seg->name = GetTab( lname, NameTab, FALSE );
        seg->class = TYPE_COMDAT;
        seg->id = lname;
        seg->attr = attr;
        seg->u.com.align = align;
        if( seg_id != 0 ) seg->u.com.seg = GetTab( seg_id, SegTab, TRUE );
        if( grp_id != 0 ) seg->u.com.grp = GetTab( grp_id, GrpTab, TRUE );
        switch( attr & COMDAT_ALLOC_MASK ) {
        case COMDAT_EXPLICIT:
            seg->use_32 = seg->u.com.seg->use_32;
            break;
        case COMDAT_FAR_CODE:
        case COMDAT_FAR_DATA:
            seg->use_32 = FALSE;
            break;
        case COMDAT_CODE32:
        case COMDAT_DATA32:
            seg->use_32 = TRUE;
            break;
        }
        if( !(flags & COMDAT_LOCAL) ) seg->public = TRUE;
    }
    Segment = seg;
    if( flags & COMDAT_ITERATED ) {
        DoLIData();
    } else {
        DoLEData();
    }
    if( seg->size < DataOffset ) seg->size = DataOffset;
}


static void DoBackPatch( unsigned loc_type )
/******************************************/
{
    uint_32     offset;
    uint_32     value;

    while( EndOfRecord == FALSE ) {
        if( IsPharLap || Is32Record ) {
            offset = GetLong();
            value  = GetLong();
        } else {
            offset = GetWord();
            value  = GetWord();
        }
        switch( loc_type ) {
        case 0: /* 8-bit lobyte */
            PutSegByte( offset, GetSegByte( offset ) + value );
            break;
        case 1: /* 16-bit offset */
            PutSegWord( offset, GetSegWord( offset ) + value );
            break;
        case 2: /* 32-bit offset */
            PutSegDWord( offset, GetSegDWord( offset ) + value );
            break;
        }
    }
}

void BackPatch()
/**************/
{
    unsigned    seg_id;

    seg_id = GetIndex();
    Segment = GetTab( seg_id, SegTab, TRUE );
    DoBackPatch( GetByte() );
}

void NBackPatch()
/***************/
{
    unsigned    loc_type;

    loc_type = GetByte();
    Segment = FindComdat( GetIndex() );
    DoBackPatch( loc_type );
}


static void DoLEData()
/********************/
{
    MarkBegData();
    DataOffset = Offset;
    if( DataOffset < Segment->start ) {
        Segment->start = DataOffset;
    }
    while( EndOfRecord == FALSE ) {
        PutSegByte( DataOffset++, GetByte() );
    }
}


void  LEData()
/************/
{
    uint_16     seg_id;

    seg_id = GetIndex();
    if( IsPharLap || Is32Record ) {
        Offset = GetLong();
    } else {
        Offset = GetWord();
    }
    Segment = GetTab( seg_id, SegTab, TRUE );
    DoLEData();
    if( DataOffset > Segment->size ) {
        Error( ERR_TOO_MUCH_LEDATA, TRUE );
    }
}

static void DoLIData()
/********************/
{
    code_block          *block;

    MarkBegData();
    DataOffset = Offset;
    if( DataOffset < Segment->start ) {
        Segment->start = DataOffset;
    }
    while( !EndOfRecord ) {
        block = IteratedData();
        DecodeLIData( block );
    }
}


void  LIData()
/************/
{
    uint_16             seg_id;

    seg_id = GetIndex();
    Segment = GetTab( seg_id, SegTab, TRUE );
    if( IsPharLap || Is32Record ) {
        Offset = GetLong();
    } else {
        Offset = GetWord();
    }
    DoLIData();
    if( DataOffset > Segment->size ) {
        Error( ERR_TOO_MUCH_LIDATA, TRUE );
    }
}


static  code_block  *IteratedData()
/*********************************/

{
    uint_32             rpt_count;
    uint_16             blk_count;
    char                num_bytes;
    code_block          *block;
    uint_16             i;

    if( Is32Record ) {
        rpt_count = GetLong();
    } else {
        rpt_count = GetWord();
    }
    blk_count = GetWord();
    if( blk_count == 0 ) {
        num_bytes = GetByte();
        block = AllocMem( sizeof( code_block ) + num_bytes );
        i = 1;
        do {
            block->data[ i ] = GetByte();
        } while( ++i <= num_bytes );
        block->data[ 0 ] = num_bytes;
    } else {
        block = AllocMem( sizeof( code_block ) + blk_count * sizeof( char * )
                          - sizeof( char ) );
        i = 0;
        do {
            ((ptr_table)block->data)[ i ] = IteratedData();
        } while( ++i != blk_count );
    }
    block->rpt_count = rpt_count;
    block->blk_count = blk_count;
    return( block );
}


static  void  DecodeLIData( code_block *block )
/*********************************************/
{
    uint_16             num;
    uint_32             i;

    i = 0;
    do {
        if( block->blk_count == 0 ) {
            num = 1;
            do {
                PutSegByte( DataOffset++, block->data[ num ] );
            } while( ++num <= block->data[ 0 ] );
        } else {
            num = 0;
            do {
                DecodeLIData( ( (ptr_table) block->data )[ num ] );
            } while( ++num != block->blk_count );
        }
    } while( ++i != block->rpt_count );
}


void  ModEnd()
/************/
{
    char                mod_typ;
    char                mattr;
    fixup               *fix;

    mod_typ = GetByte();
    mattr = ( mod_typ & 192 ) >> 6;
    if( mattr & 1 ) {   /* has start address */
        if( mod_typ & 1 ) {
            fix = FixField( TYPE_MODULE, 0, SEG_RELATIVE );
        } else {
            fix = NewFixup( TYPE_MODULE | SEG_RELATIVE );
            fix->seg_address = GetWord();
            fix->imp_address = GetByte();
        }
        Mod->start = fix;
    }
    if( mattr > 1 ) {
        Mod->main = TRUE;
    } else {
        Mod->main = FALSE;
    }
}


static  void  Add2List( handle **list, handle *hndl )
/***************************************************/
{
    handle              *tmp;

    for( ;; ) {
        tmp = *list;
        if( tmp == NULL ) break;
        list = &tmp->next_hndl;
    }
    *list = hndl;
}


void Coment()
/***********/

{
    char                attr;
    char                class;
    int                 len;
    int                 i;
    segment             *seg;
    scan_table          *scan_tab;
    int                 sidx;
    char                name[ 80 ];

    attr = GetByte();
    class = GetByte();
    if( ( attr == CMT_SOURCE_NAME && class == 0x80 ) ||
        ( attr == 0x80 && class == CMT_SOURCE_NAME ) ) {
        len = RecLen - 3;       /* class, attr, chksum */
        for( i = 0; i < len; ++i ) {
            name[ i ] = GetByte();
        }
        CommentName = NameAlloc( name, len );
    } else if( attr == 0x80 && class == CMT_DISASM_DIRECTIVE ) {
        class = GetByte();
        if( class == DDIR_SCAN_TABLE ||
            class == DDIR_SCAN_TABLE_32 ) {        /* 'S'can table indices */
            sidx = GetIndex();
            if( sidx == 0 ) {
                /* select table in a COMDAT record */
                seg = FindComdat( GetIndex() );
            } else {
                seg = GetTab( sidx, SegTab, TRUE );
            }
            scan_tab = AllocMem( sizeof( scan_table ) );
            if( class == DDIR_SCAN_TABLE_32 ) {
                scan_tab->starts = GetLong();
                scan_tab->ends = GetLong();
            } else {
                scan_tab->starts = GetWord();
                scan_tab->ends = GetWord();
            }
            scan_tab->next = seg->scan_tabs;
            seg->scan_tabs = scan_tab;
        } else {
            SkipPcoRec();
        }
    } else if( attr == 0x80 && class == CMT_EASY_OMF ) {
        len = RecLen - 3;       /* class, attr, chksum */
        for( i = 0; i < len; ++i ) {
            name[ i ] = GetByte();
        }
        if( memcmp( name, EASY_OMF_SIGNATURE, 5 ) == 0 ) {
            IsPharLap = TRUE;
            Is32BitObj = TRUE;
        }
    } else {
        SkipPcoRec();
    }
}

⌨️ 快捷键说明

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