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