loadraw.c

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

C
396
字号
    i = 0;
    while( bufOfs ) { // Do data bytes, leaving BufOfs 0 at end
        sprintf( str_buf + 9 + 2 * i, "%02x", lineBuf[i] );
        checksum += lineBuf[i++];
        --bufOfs;
    }
    sprintf( str_buf + 9 + 2 * i, "%02x\r\n", (-checksum) & 0xFF );
    WriteLoad( str_buf, 13 + 2 * i );
}

static bool WriteHexData( void *_sdata, void *_addr )
/***************************************************/
{
    segdata         *sdata = _sdata;
    unsigned_32      pieceAddr = *(unsigned long *)_addr + sdata->a.delta;
    unsigned_16      len = sdata->length;
    unsigned_16      offset;
    unsigned_16      piece;

    if( !sdata->isuninit && !sdata->isdead && len > 0 ) {
        if( pieceAddr != nextAddr + bufOfs ) { // Must start new record if address not contiguous
            if( pieceAddr < nextAddr + bufOfs ) {
                LnkMsg( ERR + MSG_FIXED_LOC_BEFORE_CUR_LOC, "a", (targ_addr*)_addr);
            }
            if( bufOfs ) {              // If partial record in buffer, flush
                WriteHexLine();
            }
            nextAddr = pieceAddr;
        }
        offset = 0;
        while( len ) {                  // Now lob out records
            piece = HEXLEN - bufOfs;    // Handle partially filled buffer
            if( piece > len ) {         // Handle not enough to fill buffer
                piece = len;
            }
            ReadInfo( sdata->data + offset, lineBuf + bufOfs, piece );
            bufOfs += piece;
            if( bufOfs == HEXLEN ) {
                WriteHexLine();         // Only write full buffers
                nextAddr += HEXLEN;     // NextAddr reflects start of line
            }                           // Partial records will be written later
            offset += piece;            //   if address is not contiguous
            len -= piece;
        }
    }
    return( FALSE );
}

static bool DoHexLeader( void *seg, void *addr )
/**********************************************/
{
    if ( !(((seg_leader *)seg)->class->flags & CLASS_NOEMIT ||
           ((seg_leader *)seg)->segflags & SEG_NOEMIT) ) {
        unsigned long   segaddr = *(unsigned long *)addr + GetLeaderDelta( seg );

        RingLookup( ((seg_leader *)seg)->pieces, WriteHexData, &segaddr );
    }
    return( FALSE );
}

static bool DoHexDupLeader( void *seg, void *addr )
/************************************************/
{
    unsigned_32  segaddr = *(unsigned long *)addr + GetLeaderDelta( seg );

    RingLookup( ((seg_leader *)seg)->pieces, WriteHexData, &segaddr );
    return( FALSE );
}

void WriteStart( void )
/*********************/
{
    char    str_buf[22];

    if( StartInfo.addr.off > 0xffff ) {
        sprintf( str_buf, ":04000005%08lx%02x\r\n", StartInfo.addr.off,
                (-(9 + (StartInfo.addr.off >> 24) + ((StartInfo.addr.off >> 16) & 0xFF) +
                ((StartInfo.addr.off >> 8) & 0xFF) + (StartInfo.addr.off & 0xFF) )) & 0xFF );
    } else {
        sprintf( str_buf, ":04000003%04lx%04lx%02x\r\n", StartInfo.addr.seg, StartInfo.addr.off,
                (-(7 + (StartInfo.addr.seg >> 8) + (StartInfo.addr.seg & 0xFF) +
                (StartInfo.addr.off >> 8) + (StartInfo.addr.off & 0xFF) )) & 0xFF );
    }
    WriteLoad( str_buf, 21 );
}

typedef struct  {
    unsigned_32 addr;
    group_entry *lastgrp;  // used only for copy classes
} grpwriteinfo;

static bool WriteHexCopyGroups( void *_seg, void *_info )
/************************************************/
{
    // This is called by the outer level iteration looking for classes
    //  that have more than one group in them
    seg_leader * seg = _seg;
    grpwriteinfo *info = _info;

    if( info->lastgrp != seg->group ) {   // Only interate new groups
        info->lastgrp = seg->group;
        // Check each initialized segment in group
        Ring2Lookup( seg->group->leaders, DoHexDupLeader, &info->addr);
        info->addr += seg->group->totalsize;
    }
    return FALSE;
}


extern void HexOutput( void )
/***************************/
{
    outfilelist         *fnode;
    group_entry         *group;
    group_entry         *wrkgrp;
    section             *sect;
    outfilelist         *finfo;
    unsigned_32         size;
    class_entry        *class;
    grpwriteinfo        info;

    nextAddr = 0L;  // Start at absolute linear address 0
    linear   = 0;   //       in segmented mode
    seg      = 0;
    bufOfs   = 0;

    if( FmtData.type & (MK_PE | MK_QNX_FLAT | MK_OS2_FLAT | MK_ELF) ) {
        CurrSect = Root;    // needed for WriteInfo.
        Root->sect_addr = Groups->grp_addr;
        fnode = Root->outfile;
        fnode->file_loc = 0;
        Root->u.file_loc = Root->sect_addr.off - FmtData.output_offset;
        /* write groups */
        for( group = Groups; group != NULL; group = group->next_group ) {
            class = group->leaders->class;
            if( class->flags & CLASS_COPY ) {
                wrkgrp = class->DupClass->segs->group;
            } else {
                wrkgrp = group;
            }
            size = CalcGroupSize( wrkgrp );
            if( size != 0 ) {
                info.addr = (group->grp_addr.off + group->linear - FmtData.output_offset);
                sect = wrkgrp->section;
                CurrSect = sect;
                finfo = sect->outfile;
                DEBUG((DBG_LOADDOS, "group %a section %d to %l in %s",
                    &group->grp_addr, sect->ovl_num, info.addr, finfo->fname ));
                if( group->leaders->class->flags & CLASS_COPY ) {
                    Ring2Lookup( wrkgrp->leaders, DoHexDupLeader, &info.addr );
               } else {
                   Ring2Lookup( wrkgrp->leaders, DoHexLeader, &info.addr );
               }
            }
        }
    }
    else {
        OrderGroups( CompareDosSegments );
        CurrSect = Root;    // needed for WriteInfo.
        Root->sect_addr = Groups->grp_addr;
        fnode = Root->outfile;
        fnode->file_loc = 0;
        Root->u.file_loc = (Root->sect_addr.seg << FmtData.SegShift) + Root->sect_addr.off - FmtData.output_offset;
        /* write groups */
        for( group = Groups; group != NULL; group = group->next_group ) {
            class = group->leaders->class;
            if( class->flags & CLASS_COPY ) {
                sect = group->section;
                CurrSect = sect;
                finfo = sect->outfile;
                info.addr = SUB_ADDR( group->grp_addr, sect->sect_addr ) + sect->u.file_loc;
                DEBUG((DBG_LOADDOS, "group %a section %d to %l in %s",
                    &group->grp_addr, sect->ovl_num, info.addr, finfo->fname ));
                info.lastgrp = NULL;
                RingLookup( class->DupClass->segs->group->leaders, WriteHexCopyGroups, &info);
            } else {
                if( group->size != 0 ) {
                    sect = group->section;
                    CurrSect = sect;
                    finfo = sect->outfile;
                    info.addr = SUB_ADDR( group->grp_addr, sect->sect_addr ) + sect->u.file_loc;
                    DEBUG((DBG_LOADDOS, "group %a section %d to %l in %s",
                        &group->grp_addr, sect->ovl_num, info.addr, finfo->fname ));
                    Ring2Lookup( group->leaders, DoHexLeader, &info.addr );
               }
            }
        }
    }
    if( bufOfs ) {              // If partial record in buffer, flush
        WriteHexLine();
    }
    if( FmtData.output_start ) {
       WriteStart();
    }
    WriteLoad( ":00000001ff\r\n", 13 );
    WriteDBI();
}

⌨️ 快捷键说明

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