loadfile.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 1,187 行 · 第 1/3 页
C
1,187 行
if( StartInfo.type != START_UNDEFED ) {
if( StartInfo.type == START_IS_SYM ) {
namelen = strlen( name );
if( namelen != strlen(StartInfo.targ.sym->name)
|| CmpRtn( StartInfo.targ.sym->name, name, namelen ) != 0 ) {
LnkMsg( LOC+ERR+MSG_MULT_START_ADDRS_BY, "12",
StartInfo.targ.sym->name, name );
}
} else {
LnkMsg( LOC+ERR+MSG_MULT_START_ADDRS, NULL );
}
} else {
StartInfo.targ.sym = RefISymbol( name );
StartInfo.targ.sym->info |= SYM_DCE_REF;
StartInfo.type = START_IS_SYM;
StartInfo.mod = CurrMod;
if( LinkFlags & STRIP_CODE ) {
DataRef( StartInfo.targ.sym );
}
}
}
extern void GetStartAddr( void )
/******************************/
{
bool addoff;
int deltaseg;
if( FmtData.type & MK_NOVELL ) return;
addoff = TRUE;
switch( StartInfo.type ) {
case START_UNDEFED: // NOTE: the possible fall through
addoff = FALSE;
if( !FmtData.dll ) {
if( Groups == NULL || FmtData.type & MK_ELF ) {
StartInfo.addr.seg = 0;
StartInfo.addr.off = 0;
} else {
StartInfo.addr = Groups->grp_addr;
}
LnkMsg( WRN+MSG_NO_START_ADDR, "a", &StartInfo.addr );
}
break;
case START_IS_SDATA:
StartInfo.addr = StartInfo.targ.sdata->u.leader->seg_addr;
StartInfo.addr.off += StartInfo.targ.sdata->a.delta;
/* if startaddr is not in first segment and segment is part of */
/* a group, adjust seg + off relative to start of group */
/* instead of start of seg. This allows far call optimization to work*/
if( (StartInfo.targ.sdata->u.leader->seg_addr.seg > 0) &&
(StartInfo.targ.sdata->u.leader->group != NULL) ) {
deltaseg = StartInfo.targ.sdata->u.leader->seg_addr.seg
- StartInfo.targ.sdata->u.leader->group->grp_addr.seg;
if( (deltaseg > 0) && (deltaseg <= StartInfo.targ.sdata->u.leader->seg_addr.seg) ) {
StartInfo.addr.seg -= deltaseg;
StartInfo.addr.off += 16 * deltaseg
- StartInfo.targ.sdata->u.leader->group->grp_addr.off;
}
}
break;
case START_IS_SYM:
StartInfo.addr = StartInfo.targ.sym->addr;
break;
}
if( addoff ) {
StartInfo.addr.off += StartInfo.off;
}
}
extern offset CalcGroupSize( group_entry *group )
/***********************************************/
/* calculate the total memory size of a potentially split group */
{
offset size;
if(( group == DataGroup ) && ( FmtData.dgroupsplitseg != NULL )) {
size = FmtData.dgroupsplitseg->seg_addr.off - group->grp_addr.off
- FmtData.bsspad;
DbgAssert( size >= group->size );
} else {
size = group->totalsize;
}
return( size );
}
extern offset CalcSplitSize( void )
/*********************************/
/* calculate the size of the uninitialized portion of a group */
{
offset size;
if( FmtData.dgroupsplitseg == NULL ) {
return( 0 );
} else {
size = DataGroup->totalsize -
(FmtData.dgroupsplitseg->seg_addr.off - DataGroup->grp_addr.off);
if( StackSegPtr != NULL ) {
size -= StackSize;
}
return( size );
}
}
extern bool CompareDosSegments( targ_addr *left, targ_addr *right )
/*****************************************************************/
{
return LESS_THAN_ADDR( *left, *right );
}
extern bool CompareOffsets( targ_addr *left, targ_addr *right )
/*****************************************************************/
{
return left->off < right->off;
}
extern bool CompareProtSegments( targ_addr *left, targ_addr *right )
/*****************************************************************/
{
if( left->seg == right->seg ) {
return left->off < right->off;
}
return left->seg < right->seg;
}
extern void OrderGroups( bool (*lessthan)(targ_addr *, targ_addr *) )
/*******************************************************************/
{
group_entry *group, *low_group, *firstgroup, **lastgroup;
targ_addr * low_addr;
targ_addr * grp_addr;
firstgroup = Groups;
lastgroup = &Groups;
while( firstgroup != NULL ) {
low_addr = &firstgroup->grp_addr;
low_group = NULL;
for( group = firstgroup; group->next_group != NULL;
group = group->next_group ) {
grp_addr = &group->next_group->grp_addr;
if( lessthan( grp_addr, low_addr ) ) {
low_addr = grp_addr;
low_group = group;
}
}
if( low_group == NULL ) {
*lastgroup = firstgroup;
lastgroup = &(firstgroup->next_group);
firstgroup = *lastgroup;
} else {
*lastgroup = low_group->next_group;
lastgroup = &(low_group->next_group->next_group);
low_group->next_group = *lastgroup;
}
}
}
extern bool WriteDOSGroup( group_entry *group )
/*********************************************/
/* write the data for group to the loadfile */
/* returns TRUE if the file should be repositioned */
{
unsigned long loc;
signed long diff;
section * sect;
bool repos;
outfilelist * finfo;
repos = FALSE;
if( group->size != 0 ) {
sect = group->section;
CurrSect = sect;
finfo = sect->outfile;
loc = SUB_ADDR( group->grp_addr, sect->sect_addr ) + sect->u.file_loc;
diff = loc - finfo->file_loc;
if( diff > 0 ) {
PadLoad( diff );
} else if( diff != 0 ) {
SeekLoad( loc );
repos = TRUE;
}
if( group == OvlGroup ) {
OvlTabOffset = loc;
}
DEBUG((DBG_LOADDOS, "group %a section %d to %l in %s",
&group->grp_addr, sect->ovl_num, loc, finfo->fname ));
WriteGroupLoad( group );
loc += group->size;
if( loc > finfo->file_loc ) {
finfo->file_loc = loc;
}
}
return( repos );
}
extern unsigned_32 MemorySize( void )
/***********************************/
/* Compute size of image when loaded into memory. */
{
unsigned_32 start;
unsigned_32 end;
unsigned_32 curr;
section *sect;
ovl_area *ovl;
if( !(FmtData.type & MK_REAL_MODE) ) {
return( Root->size );
} else {
start = MK_REAL_ADDR( Root->sect_addr.seg, Root->sect_addr.off );
end = start + Root->size;
for( ovl = Root->areas; ovl != NULL; ovl = ovl->next_area ) {
for( sect = ovl->sections; sect != NULL; sect = sect->next_sect ) {
curr = MK_REAL_ADDR( sect->sect_addr.seg,
sect->sect_addr.off ) + sect->size;
if( curr > end ) end = curr;
}
}
return( end - start );
}
}
extern unsigned_32 AppendToLoadFile( char * name )
/************************************************/
{
f_handle handle;
unsigned_32 wrote;
if( name != NULL ) {
handle = QOpenR( name );
wrote = CopyToLoad( handle, name );
} else {
wrote = 0;
}
return( wrote );
}
static void SetupImpLib( void )
/*****************************/
{
char * fname;
int namelen;
ImpLib.bufsize = 0;
ImpLib.handle = NIL_HANDLE;
ImpLib.buffer = NULL;
ImpLib.dllname = NULL;
ImpLib.didone = FALSE;
if( FmtData.make_implib ) {
_ChkAlloc( ImpLib.buffer, IMPLIB_BUFSIZE );
if( FmtData.make_impfile ) {
ImpLib.fname = ChkStrDup( FmtData.implibname );
ImpLib.handle = QOpenRW( ImpLib.fname );
} else {
ImpLib.handle = OpenTempFile( &ImpLib.fname );
}
/* RemovePath results in the filename only *
* it trims both the path, and the extension */
fname = RemovePath( Root->outfile->fname, &namelen );
ImpLib.dlllen = namelen;
/* increase length to restore full extension if not OS2 *
* sometimes the extension of the output name is important */
ImpLib.dlllen += strlen( fname + namelen );
_ChkAlloc( ImpLib.dllname, ImpLib.dlllen );
memcpy( ImpLib.dllname, fname, ImpLib.dlllen );
}
}
extern void BuildImpLib( void )
/*****************************/
{
if( LinkState & LINK_ERROR || ImpLib.handle == NIL_HANDLE
|| !FmtData.make_implib ) return;
if( ImpLib.bufsize > 0 ) {
FlushImpBuffer();
}
QClose( ImpLib.handle, ImpLib.fname );
if( !FmtData.make_impfile ) {
if( ImpLib.didone ) {
ExecWlib();
}
QDelete( ImpLib.fname );
}
_LnkFree( FmtData.implibname );
_LnkFree( ImpLib.fname );
_LnkFree( ImpLib.buffer );
_LnkFree( ImpLib.dllname );
}
#if defined( _DLLHOST )
extern bool ExecWlibDLL( char * );
static void ExecWlib( void )
/**************************/
{
char * cmdline;
char * temp;
size_t namelen;
size_t impnamelen;
namelen = strlen(ImpLib.fname);
impnamelen = strlen(FmtData.implibname);
/*
* in the following: +12 for options, +2 for spaces, +1 for @, +4 for quotes
* and +1 for nullchar
*/
_ChkAlloc( cmdline, namelen + impnamelen +15 +2 +1 +4 +1 );
memcpy( cmdline, "-c -b -n -q -ii \"", 17 );
temp = cmdline + 14;
if( LinkState & HAVE_ALPHA_CODE ) {
*temp = 'a';
} else if( LinkState & HAVE_PPC_CODE ) {
*temp = 'p';
}
temp += 3;
memcpy( temp, FmtData.implibname, impnamelen );
temp += impnamelen;
*temp++ = '"';
*temp++ = ' ';
*temp++ = '@';
*temp++ = '"';
memcpy( temp, ImpLib.fname, namelen );
temp += namelen;
*temp++ = '"';
*temp = '\0';
if( ExecWlibDLL( cmdline ) ) {
PrintIOError( ERR+MSG_CANT_EXECUTE, "12", "wlib.exe" );
}
_LnkFree( cmdline );
}
#elif defined( __LINUX__ )
static void ExecWlib( void ) {}
#else
static void ExecWlib( void )
/**************************/
{
char * atfname;
size_t namelen;
int retval;
char * libtype;
namelen = strlen(ImpLib.fname) + 1;
_ChkAlloc( atfname, namelen + 1 ); // +1 for the @
*atfname = '@';
memcpy( atfname + 1, ImpLib.fname, namelen );
if( LinkState & HAVE_ALPHA_CODE ) {
libtype = "-ia";
} else if( LinkState & HAVE_PPC_CODE ) {
libtype = "-ip";
} else {
libtype = "-ii";
}
retval = spawnlp( P_WAIT, "wlib.exe", "wlib.exe", "-c", "-b", "-n", "-q",
libtype, FmtData.implibname, atfname, NULL );
if( retval == -1 ) {
PrintIOError( ERR+MSG_CANT_EXECUTE, "12", "wlib.exe" );
}
_LnkFree( atfname );
}
#endif
extern void AddImpLibEntry( char *intname, char *extname, unsigned ordinal )
/**************************************************************************/
{
size_t intlen;
size_t otherlen;
char * buff;
char * currpos;
if( ImpLib.handle == NIL_HANDLE ) return;
ImpLib.didone = TRUE;
intlen = strlen( intname );
if( ordinal == NOT_IMP_BY_ORDINAL ) {
otherlen = strlen(extname);
} else {
otherlen = 10; // max length of a 32-bit int.
}
buff = alloca( intlen + otherlen + ImpLib.dlllen + 13 );
buff[0] = '+';
buff[1] = '+';
buff[2] = '\'';
currpos = buff + 3;
memcpy( currpos, intname, intlen );
currpos += intlen;
*currpos++ = '\'';
*currpos++ = '.';
*currpos++ = '\'';
memcpy( currpos, ImpLib.dllname, ImpLib.dlllen );
currpos += ImpLib.dlllen;
*currpos++ = '\'';
*currpos++ = '.';
if( ordinal == NOT_IMP_BY_ORDINAL ) {
*currpos++ = '.';
*currpos++ = '\'';
memcpy( currpos, extname, otherlen );
currpos += otherlen;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?