loadfile.c

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

C
1,187
字号
        *currpos++ = '\'';
    } else {
        utoa( ordinal, currpos, 10 );
        currpos += strlen( currpos );
    }
#if !defined( __UNIX__ )
    *currpos++ = '\r';
#endif
    *currpos = '\n';
    BufImpWrite( buff, currpos - buff + 1 );
}

static void FlushImpBuffer( void )
/********************************/
{
    QWrite( ImpLib.handle, ImpLib.buffer, ImpLib.bufsize, ImpLib.fname );
}

static void BufImpWrite( char *buffer, int len )
/**********************************************/
{
    int     diff;

    diff = ImpLib.bufsize + len - IMPLIB_BUFSIZE;
    if( diff >= 0 ) {
        memcpy( ImpLib.buffer + ImpLib.bufsize , buffer, len - diff );
        ImpLib.bufsize = IMPLIB_BUFSIZE;
        FlushImpBuffer();
        ImpLib.bufsize = diff;
        if( diff > 0 ) {
            memcpy( ImpLib.buffer, buffer + len - diff, diff );
        }
    } else {
        memcpy( ImpLib.buffer + ImpLib.bufsize, buffer, len );
        ImpLib.bufsize += len;
    }
}

extern void WriteLoad3( void* dummy, char *buff, unsigned size )
/**************************************************************/
/* write a buffer out to the load file (useful as a callback) */
{
    dummy = dummy;
    WriteLoad( buff, size );
}

extern unsigned_32 CopyToLoad( f_handle handle, char * name )
/***********************************************************/
{
    unsigned_32     amt_read;
    unsigned_32     wrote;

    wrote = 0;
    for(;;) {
        amt_read = QRead( handle, TokBuff, TokSize, name );
        if( amt_read == 0 ) break;
        WriteLoad( TokBuff, amt_read );
        wrote += amt_read;
    }
    QClose( handle, name );
    return( wrote );
}

extern unsigned long NullAlign( unsigned align )
/**********************************************/
/* align loadfile -- assumed power of two alignment */
{
    unsigned long       off;
    unsigned            pad;

    off = PosLoad();
    align--;
    pad = ( (off+align) & ~(unsigned long)align ) - off;
    PadLoad( pad );
    return( off + pad );
}

extern unsigned long OffsetAlign( unsigned long off, unsigned long align )
/************************************************************************/
/* align loadfile -- assumed power of two alignment */
{
    unsigned long       pad;

    align--;
    pad = ( (off+align) & ~align ) - off;
    PadLoad( pad );
    return( off + pad );
}

static bool WriteSegData( void *_sdata, void *_start )
/****************************************************/
{
    segdata *sdata = _sdata;
    unsigned long *start = _start;
    unsigned long newpos;
    signed long pad;

    if( !sdata->isuninit && !sdata->isdead && sdata->length > 0 ) {
        newpos = *start + sdata->a.delta;
        pad = newpos - PosLoad();
        DbgAssert( pad >= 0 );
        PadLoad( pad );
        WriteInfo( sdata->data, sdata->length );
        sdata->data = newpos;   // for incremental linking
    }
    return FALSE;
}

static void DoWriteLeader( seg_leader *seg, unsigned long start )
/***************************************************************/
{
    RingLookup( seg->pieces, WriteSegData, &start );
}

extern void WriteLeaderLoad( void *seg )
/**************************************/
{
    DoWriteLeader( seg, PosLoad() );
}

static bool DoGroupLeader( void *seg, void *start )
/*************************************************/
{
    // If class or sector should not be output, skip it
    if ( !(((seg_leader *)seg)->class->flags & CLASS_NOEMIT ||
           ((seg_leader *)seg)->segflags & SEG_NOEMIT) ) {
        DoWriteLeader( seg, *(unsigned long *)start + GetLeaderDelta( seg ) );
    }
    return FALSE;
}

static bool DoDupGroupLeader( void *seg, void *start )
/*************************************************/
{
    // Substitute groups generally are sourced from NO_EMIT classes,
    // As copies, they need to be output, so ignore their MOEMIT flag here
    DoWriteLeader( seg, *(unsigned long *)start + GetLeaderDelta( seg ) );
    return FALSE;
}

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

static bool WriteCopyGroups( 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, DoDupGroupLeader, (&info->pos));
        info->pos += seg->group->totalsize;
    }
    return FALSE;
}

extern void WriteGroupLoad( group_entry *group )
/**********************************************/
{
    grpwriteinfo     info;
    class_entry *    class;

    class = group->leaders->class;

    info.pos = PosLoad();
    // If group is a copy group, substitute source group(s) here
    if (class->flags & CLASS_COPY ) {
        info.lastgrp = NULL; // so it will use the first group
        RingLookup( class->DupClass->segs->group->leaders, WriteCopyGroups, &info );
    }
    else {
        Ring2Lookup( group->leaders, DoGroupLeader, &(info.pos) );
    }
}

static void OpenOutFiles( void )
/******************************/
{
    outfilelist * fnode;

    fnode = OutFiles;   // skip the root
    while( fnode != NULL ) {
        OpenBuffFile( fnode );
        fnode = fnode->next;
    }
}

static void CloseOutFiles( void )
/*******************************/
{
    outfilelist *   fnode;

    fnode = OutFiles;
    while( fnode != NULL ) {
        if( fnode->handle != NIL_HANDLE ) {
            CloseBuffFile( fnode );
        }
        fnode = fnode->next;
    }
}

extern void FreeOutFiles( void )
/******************************/
{
    outfilelist *   fnode;

    CloseOutFiles();
    fnode = OutFiles;
    while( fnode != NULL ) {
        if( LinkState & LINK_ERROR ) {
            QDelete( fnode->fname );
        }
        _LnkFree( fnode->fname );
        OutFiles = fnode->next;
        _LnkFree( fnode );
        fnode = OutFiles;
    }
}

static void * SetToZero( void *dest, const void *dummy, unsigned size )
/*********************************************************************/
{
    memset( dest, FmtData.FillChar, size );
    return (void *) dummy;
}

extern void PadLoad( unsigned long size )
/***************************************/
/* pad out load file with zeros */
{
    outfilelist *       outfile;

    if( size == 0 ) return;
    outfile = CurrSect->outfile;
    if( outfile->buffer != NULL ) {
        WriteBuffer( NULL, size, outfile, SetToZero );
    } else {
        WriteNulls( outfile->handle, size, outfile->fname );
    }
}

extern void PadBuffFile( outfilelist *outfile, unsigned long size )
/*****************************************************************/
/* pad out load file with zeros */
{
    if( size == 0 )
        return;
    if( outfile->buffer != NULL ) {
        WriteBuffer( NULL, size, outfile, SetToZero );
    } else {
        WriteNulls( outfile->handle, size, outfile->fname );
    }
}

extern void WriteLoad( void *buff, unsigned long size )
/*****************************************************/
/* write a buffer out to the load file */
{
    outfilelist *       outfile;

    outfile = CurrSect->outfile;
    if( outfile->buffer != NULL ) {
        WriteBuffer( buff, size, outfile, memcpy );
    } else {
        QWrite( outfile->handle, buff, size, outfile->fname );
    }
}

static void * NullBuffFunc( void *dest, const void *dummy, unsigned size )
/************************************************************************/
{
    dummy = dummy;
    size = size;
    return dest;
}

extern void SeekLoad( unsigned long offset )
/******************************************/
{
    outfilelist *       outfile;

    outfile = CurrSect->outfile;
    if( outfile->buffer != NULL && offset < outfile->bufpos ) {
        FlushBuffFile( outfile );
    }
    if( outfile->buffer == NULL ) {
        QSeek( outfile->handle, offset, outfile->fname );
    } else {
        WriteBuffer( NULL, offset - outfile->bufpos, outfile, NullBuffFunc );
    }
}

extern void SeekEndLoad( unsigned long offset )
/*********************************************/
{
    outfilelist *       outfile;

    outfile = CurrSect->outfile;
    if( outfile->buffer != NULL && offset > 0 ) {
        FlushBuffFile( outfile );
    }
    if( outfile->buffer == NULL ) {
        QLSeek( outfile->handle, offset, LSEEK_END, outfile->fname );
    }
}

extern unsigned long PosLoad( void )
/**********************************/
{
    if( CurrSect->outfile->buffer != NULL ) {
        return CurrSect->outfile->bufpos;
    } else {
        return QPos( CurrSect->outfile->handle );
    }
}

#define BUFF_BLOCK_SIZE (16*1024)

extern void InitBuffFile( outfilelist *outfile, char *filename, bool executable )
/*******************************************************************************/
{
    outfile->fname    = filename;
    outfile->handle   = NIL_HANDLE;
    outfile->file_loc = 0;
    outfile->bufpos   = 0;
    outfile->buffer   = NULL;
    outfile->ovlfnoff = 0;
    outfile->is_exe   = executable;
}

extern void OpenBuffFile( outfilelist *outfile )
/**********************************************/
{
    if( outfile->is_exe )
        outfile->handle = ExeCreate( outfile->fname );
    else
        outfile->handle = QOpenRW( outfile->fname );
    if( outfile->handle == NIL_HANDLE ) {
        PrintIOError( FTL+MSG_CANT_OPEN_NO_REASON, "s", outfile->fname );
    }
    _ChkAlloc( outfile->buffer, BUFF_BLOCK_SIZE );
}

static void FlushBuffFile( outfilelist *outfile )
/***********************************************/
{
    unsigned    modpos;

    modpos = outfile->bufpos % BUFF_BLOCK_SIZE;
    if( modpos != 0 ) {
        QWrite( outfile->handle, outfile->buffer, modpos, outfile->fname );
    }
    _LnkFree( outfile->buffer );
    outfile->buffer = NULL;
}

extern void CloseBuffFile( outfilelist *outfile )
/***********************************************/
{
    if( outfile->buffer != NULL ) {
        FlushBuffFile( outfile );
    }
    QClose( outfile->handle, outfile->fname );
    outfile->handle = NIL_HANDLE;
}

static void WriteBuffer( char *info, unsigned long len, outfilelist *outfile,
                         void * (*rtn)(void *, const void *, unsigned) )
/***************************************************************************/
{
    unsigned modpos;
    unsigned adjust;

    modpos = outfile->bufpos % BUFF_BLOCK_SIZE;
    outfile->bufpos += len;
    while( modpos + len >= BUFF_BLOCK_SIZE ) {
        adjust = BUFF_BLOCK_SIZE - modpos;
        rtn( outfile->buffer + modpos, info, adjust );
        QWrite( outfile->handle, outfile->buffer, BUFF_BLOCK_SIZE,
                outfile->fname );
        info += adjust;
        len -= adjust;
        modpos = 0;
    }
    if( len > 0 ) {
        rtn( outfile->buffer + modpos, info, len );
    }
}

⌨️ 快捷键说明

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