Windows NT 4.0 source code leak
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

/***********************************************************************
* 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;
}