mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
183 lines
5.2 KiB
183 lines
5.2 KiB
/***********************************************************************
|
|
* Microsoft (R) 32-Bit Incremental Linker
|
|
*
|
|
* Copyright (C) Microsoft Corp 1992-95. All rights reserved.
|
|
*
|
|
* File: ifpo.cpp
|
|
*
|
|
* File Comments:
|
|
*
|
|
* Incremental FPO management
|
|
*
|
|
***********************************************************************/
|
|
|
|
#include "link.h"
|
|
|
|
#include "ifpo.h"
|
|
|
|
IModIdx imodidx;
|
|
|
|
static FPO_DATA* rgfpoNew;
|
|
static IModIdx* rgimodNew;
|
|
static IFPO* rgifpoNew;
|
|
static IFPO ifpoNew = 0;
|
|
static IFPO ifpoMax = 0;
|
|
|
|
|
|
// set initial fpo table entry size
|
|
BOOL FPOInit(IFPO ifpoMax_)
|
|
{
|
|
IFPO ifpo;
|
|
ifpoMax = ifpoMax_;
|
|
// allocate tables to hold the new fpo additions - these should not exceed the
|
|
// ifpoMax of the incoming struct
|
|
|
|
rgfpoNew = (FPO_DATA *) PvAllocZ(sizeof(FPO_DATA) * ifpoMax);
|
|
rgimodNew = (IModIdx *) PvAllocZ(sizeof(IModIdx) * ifpoMax);
|
|
rgifpoNew = (IFPO *) PvAlloc(sizeof(IFPO) * ifpoMax);
|
|
|
|
for (ifpo = 0; ifpo < ifpoMax; ifpo++) {
|
|
rgifpoNew[ifpo] = ifpo;
|
|
}
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
static char rgcDelMods[(IMODIDXMAC + CHAR_BIT - 1) / CHAR_BIT];
|
|
|
|
_inline void setDelMods(IModIdx imod)
|
|
{
|
|
rgcDelMods[imod / CHAR_BIT] |= 1 << (imod % CHAR_BIT);
|
|
}
|
|
|
|
_inline BOOL fDelMods(IModIdx imod)
|
|
{
|
|
return rgcDelMods[imod / CHAR_BIT] & (1 << (imod % CHAR_BIT));
|
|
}
|
|
|
|
// imod has changed
|
|
BOOL FPODeleteImod(IModIdx imod)
|
|
{
|
|
assert(imod < IMODIDXMAC);
|
|
setDelMods(imod);
|
|
return TRUE;
|
|
}
|
|
|
|
// add group of FPOs
|
|
BOOL FPOAddFpo(IModIdx imod, FPO_DATA* rgfpo, IFPO cfpo)
|
|
{
|
|
IFPO ifpo;
|
|
if ((ifpoNew + cfpo) > ifpoMax) {
|
|
return(FALSE);
|
|
}
|
|
|
|
for (ifpo = 0; ifpo < cfpo; ifpo++) {
|
|
rgfpoNew[ifpoNew] = rgfpo[ifpo];
|
|
rgimodNew[ifpoNew++] = imod;
|
|
}
|
|
|
|
return(TRUE);
|
|
}
|
|
|
|
|
|
_inline int cmpfpo( FPO_DATA* pfpo1, FPO_DATA* pfpo2 )
|
|
{
|
|
return pfpo1->ulOffStart - pfpo2->ulOffStart;
|
|
}
|
|
|
|
|
|
int __cdecl cmpifpo(const void *elem1, const void *elem2)
|
|
{
|
|
return cmpfpo(&rgfpoNew[*((IFPO*)elem1)], &rgfpoNew[*((IFPO*)elem2)]);
|
|
}
|
|
|
|
// update FPO tables
|
|
// return FALSE if rgfpo overflow
|
|
BOOL FPOUpdate(FPOI* pfpoi)
|
|
{
|
|
IFPO ifpo;
|
|
|
|
// first sort all the new incoming fpo's
|
|
qsort((void *) rgifpoNew, (size_t) ifpoNew, sizeof(IFPO), cmpifpo);
|
|
|
|
if (pfpoi->ifpoMac) {
|
|
// there were existing fpo's - copy old fpo table to a new tmp table - discarding
|
|
// deleted mods as we go
|
|
FPO_DATA* rgfpoOld;
|
|
IModIdx* rgimodOld;
|
|
IFPO ifpoOld = 0;
|
|
IFPO ifpoOldIter = 0;
|
|
IFPO ifpoNewIter = 0;
|
|
|
|
rgfpoOld = (FPO_DATA *) PvAllocZ(sizeof(FPO_DATA) * pfpoi->ifpoMac);
|
|
rgimodOld = (IModIdx *) PvAllocZ(sizeof(IModIdx) * pfpoi->ifpoMac);
|
|
|
|
for (ifpo = 0; ifpo < pfpoi->ifpoMac; ifpo++) {
|
|
if (!fDelMods(pfpoi->rgimod[ifpo])) {
|
|
// copy it over - module was not deleted
|
|
rgfpoOld[ifpoOld] = pfpoi->rgfpo[ifpo];
|
|
rgimodOld[ifpoOld++] = pfpoi->rgimod[ifpo];
|
|
}
|
|
}
|
|
|
|
if ((pfpoi->ifpoMac = ifpoOld + ifpoNew) > ifpoMax) {
|
|
// total number of entries too much for allocated fpo space
|
|
// return FALSE
|
|
FreePv(rgfpoOld);
|
|
FreePv(rgimodOld);
|
|
FreePv(rgfpoNew);
|
|
FreePv(rgimodNew);
|
|
FreePv(rgifpoNew);
|
|
return FALSE;
|
|
}
|
|
|
|
// now merge the sorted copied old list and the sorted new list
|
|
for (ifpo = 0; ifpo < pfpoi->ifpoMac; ifpo++) {
|
|
if (ifpoOldIter >= ifpoOld) {
|
|
assert(ifpoNewIter < ifpoNew);
|
|
for (; ifpo < pfpoi->ifpoMac; ifpo++) {
|
|
pfpoi->rgfpo[ifpo] = rgfpoNew[rgifpoNew[ifpoNewIter]];
|
|
pfpoi->rgimod[ifpo] = rgimodNew[rgifpoNew[ifpoNewIter++]];
|
|
}
|
|
break;
|
|
}
|
|
else if (ifpoNewIter >= ifpoNew) {
|
|
assert(ifpoOldIter < ifpoOld);
|
|
memcpy(&pfpoi->rgfpo[ifpo], &rgfpoOld[ifpoOldIter],
|
|
(pfpoi->ifpoMac - ifpo) * sizeof(FPO_DATA));
|
|
memcpy(&pfpoi->rgimod[ifpo], &rgimodOld[ifpoOldIter],
|
|
(pfpoi->ifpoMac - ifpo) * sizeof(IModIdx));
|
|
break;
|
|
}
|
|
else {
|
|
// compare old and new list and copy the lesser of the two to the
|
|
// new destination
|
|
if (cmpfpo(&rgfpoOld[ifpoOldIter], &rgfpoNew[rgifpoNew[ifpoNewIter]]) < 0) {
|
|
pfpoi->rgfpo[ifpo] = rgfpoOld[ifpoOldIter];
|
|
pfpoi->rgimod[ifpo] = rgimodOld[ifpoOldIter++];
|
|
}
|
|
else {
|
|
pfpoi->rgfpo[ifpo] = rgfpoNew[rgifpoNew[ifpoNewIter]];
|
|
pfpoi->rgimod[ifpo] = rgimodNew[rgifpoNew[ifpoNewIter++]];
|
|
}
|
|
}
|
|
}
|
|
FreePv(rgfpoOld);
|
|
FreePv(rgimodOld);
|
|
}
|
|
else {
|
|
// write out sorted incoming fpo's
|
|
for (ifpo = 0; ifpo < ifpoNew; ifpo++) {
|
|
pfpoi->rgfpo[ifpo] = rgfpoNew[rgifpoNew[ifpo]];
|
|
pfpoi->rgimod[ifpo] = rgimodNew[rgifpoNew[ifpo]];
|
|
}
|
|
pfpoi->ifpoMac = ifpoNew;
|
|
}
|
|
|
|
pfpoi->ifpoMax = ifpoMax;
|
|
FreePv(rgfpoNew);
|
|
FreePv(rgimodNew);
|
|
FreePv(rgifpoNew);
|
|
return TRUE;
|
|
}
|