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 + -
显示快捷键?