951 lines
32 KiB
C
951 lines
32 KiB
C
|
|
|||
|
/*_________________________________________________________________*
|
|||
|
| |
|
|||
|
| MODULE |
|
|||
|
| |
|
|||
|
| HSORT |
|
|||
|
| (C) Copyright Microsoft Corp 1988 |
|
|||
|
| 10 March 1988 |
|
|||
|
| |
|
|||
|
| FUNCTION |
|
|||
|
| |
|
|||
|
| Sorting functions required by linker. |
|
|||
|
| |
|
|||
|
| DEFINES |
|
|||
|
| |
|
|||
|
| void AllocSortBuffer(unsigned max, int AOrder) |
|
|||
|
| RBTYPE ExtractMin(unsigned n) |
|
|||
|
| void FreeSortBuffer(void) |
|
|||
|
| void InitSort(RBTYPE **buf, WORD *base1, WORD *lim1, |
|
|||
|
| WORD *base2, WORD *lim2 ) |
|
|||
|
| RBTYPE GetSymPtr(unsigned n) |
|
|||
|
| void Store(RBTYPE element) |
|
|||
|
| |
|
|||
|
| USES |
|
|||
|
| |
|
|||
|
| cmpf global pointer to comparing function |
|
|||
|
| AREASORT area in virtual memory where sort buffer is |
|
|||
|
| extended |
|
|||
|
| |
|
|||
|
| CHANGES |
|
|||
|
| |
|
|||
|
| symMac global counter of sorted symbols |
|
|||
|
| |
|
|||
|
| MODIFICATION HISTORY |
|
|||
|
| |
|
|||
|
| 88/03/10 Wieslaw Kalkus Initial version |
|
|||
|
| |
|
|||
|
| |
|
|||
|
| |
|
|||
|
|_________________________________________________________________|
|
|||
|
* */
|
|||
|
|
|||
|
|
|||
|
#include <minlit.h> /* Types and constants */
|
|||
|
#include <bndtrn.h> /* Basic type & const declarations */
|
|||
|
#include <bndrel.h> /* Types and constants */
|
|||
|
#include <lnkio.h> /* Linker I/O definitions */
|
|||
|
#include <lnkmsg.h> /* Error messages */
|
|||
|
#include <extern.h> /* External declarations */
|
|||
|
|
|||
|
|
|||
|
#define VMBuffer(x) (RBTYPE *)mapva((long)(AREASORT+((long)(x)*sizeof(RBTYPE))),FALSE)
|
|||
|
#define SORTDEBUG FALSE
|
|||
|
|
|||
|
LOCAL WORD LastInBuf; /* Last element in sort buffer */
|
|||
|
LOCAL RBTYPE *SortBuffer; /* Sort buffer allocated on near heap */
|
|||
|
LOCAL FTYPE fVMReclaim; /* TRUE if VM page buffers reclaimed */
|
|||
|
LOCAL FTYPE fInMemOnly; /* TRUE if not using VM for sort buffer */
|
|||
|
LOCAL FTYPE fFirstTime = (FTYPE) TRUE;
|
|||
|
LOCAL WORD SortIndex = 0;
|
|||
|
LOCAL int (NEAR *TestFun)(RBTYPE *arg1, RBTYPE *arg2);
|
|||
|
LOCAL int (NEAR *TestFunS)(RBTYPE *arg1, RBTYPE *arg2);
|
|||
|
|
|||
|
/*
|
|||
|
* LOCAL FUNCTION PROTOTYPES
|
|||
|
*/
|
|||
|
|
|||
|
|
|||
|
LOCAL void NEAR SiftDown(unsigned n);
|
|||
|
LOCAL void NEAR SiftUp(unsigned n);
|
|||
|
LOCAL int NEAR AscendingOrder(RBTYPE *arg1, RBTYPE *arg2);
|
|||
|
LOCAL int NEAR DescendingOrder(RBTYPE *arg1, RBTYPE *arg2);
|
|||
|
|
|||
|
/*
|
|||
|
* DEBUGING FUNCTIONS
|
|||
|
*/
|
|||
|
|
|||
|
#if SORTDEBUG
|
|||
|
|
|||
|
LOCAL void NEAR DumpSortBuffer(unsigned max, int faddr);
|
|||
|
LOCAL void NEAR DumpElement(unsigned el, int faddr);
|
|||
|
LOCAL void NEAR CheckSortBuffer(unsigned n, unsigned max);
|
|||
|
|
|||
|
LOCAL void NEAR CheckSortBuffer(unsigned root, unsigned max)
|
|||
|
{
|
|||
|
DWORD c;
|
|||
|
RBTYPE child[2];
|
|||
|
RBTYPE parent;
|
|||
|
RBTYPE *VMp;
|
|||
|
|
|||
|
|
|||
|
|
|||
|
c = root << 1;
|
|||
|
|
|||
|
if (c > (long) max)
|
|||
|
return;
|
|||
|
|
|||
|
/* c is the left child of root */
|
|||
|
|
|||
|
if (c + 1 <= (long) max)
|
|||
|
{
|
|||
|
/* c + 1 is the right child of root */
|
|||
|
|
|||
|
if (c > LastInBuf)
|
|||
|
{ /* Fetch element from virtual memory */
|
|||
|
VMp = VMBuffer(c);
|
|||
|
child[0] = *VMp;
|
|||
|
VMp = VMBuffer(c + 1);
|
|||
|
child[1] = *VMp;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
child[0] = SortBuffer[c];
|
|||
|
if (c + 1 > LastInBuf)
|
|||
|
{
|
|||
|
VMp = VMBuffer(c + 1);
|
|||
|
child[1] = *VMp;
|
|||
|
}
|
|||
|
else child[1] = SortBuffer[c+1];
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
/* only left child of root */
|
|||
|
|
|||
|
if (c > LastInBuf)
|
|||
|
{ /* Fetch element from virtual memory */
|
|||
|
VMp = VMBuffer(c);
|
|||
|
child[0] = *VMp;
|
|||
|
}
|
|||
|
else child[0] = SortBuffer[c];
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
if (root > LastInBuf)
|
|||
|
{
|
|||
|
VMp = VMBuffer(root);
|
|||
|
parent = *VMp;
|
|||
|
}
|
|||
|
else parent = SortBuffer[root];
|
|||
|
|
|||
|
if (!(*TestFun)(&parent, &child[0]))
|
|||
|
{
|
|||
|
fprintf(stdout, "\r\nBAD sort buffer --> root = %u; left child = %lu \r\n", root, c);
|
|||
|
DumpElement(root, cmpf == FGtAddr);
|
|||
|
DumpElement(c, cmpf == FGtAddr);
|
|||
|
}
|
|||
|
|
|||
|
if (c + 1 < (long) max)
|
|||
|
{
|
|||
|
if (!(*TestFun)(&parent, &child[1]))
|
|||
|
{
|
|||
|
fprintf(stdout, "\r\nBAD sort buffer --> root = %u; right child = %lu \r\n", root, c+1);
|
|||
|
DumpElement(root, cmpf == FGtAddr);
|
|||
|
DumpElement(c+1, cmpf == FGtAddr);
|
|||
|
}
|
|||
|
}
|
|||
|
CheckSortBuffer((unsigned) c, max);
|
|||
|
if (c + 1 < (long) max)
|
|||
|
CheckSortBuffer((unsigned) c+1, max);
|
|||
|
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
LOCAL void NEAR DumpSortBuffer(unsigned max, int faddr)
|
|||
|
{
|
|||
|
|
|||
|
unsigned x;
|
|||
|
|
|||
|
for (x = 1; x <= max; x++)
|
|||
|
{
|
|||
|
fprintf(stdout, "SortBuffer[%u] = ", x);
|
|||
|
DumpElement(x, faddr);
|
|||
|
fprintf(stdout, " \r\n");
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
LOCAL void NEAR DumpElement(unsigned el, int faddr)
|
|||
|
{
|
|||
|
|
|||
|
unsigned i;
|
|||
|
RBTYPE *VMp;
|
|||
|
RBTYPE symp;
|
|||
|
AHTEPTR hte;
|
|||
|
APROPNAMEPTR prop;
|
|||
|
char name[40];
|
|||
|
union {
|
|||
|
long vptr; /* Virtual pointer */
|
|||
|
BYTE far *fptr; /* Far pointer */
|
|||
|
struct {
|
|||
|
unsigned short offset;
|
|||
|
/* Offset value */
|
|||
|
unsigned short seg;
|
|||
|
} /* Segmnet value */
|
|||
|
ptr;
|
|||
|
}
|
|||
|
pointer; /* Different ways to describe pointer */
|
|||
|
|
|||
|
|
|||
|
if (el > LastInBuf)
|
|||
|
{
|
|||
|
VMp = VMBuffer(el);
|
|||
|
symp = *VMp;
|
|||
|
}
|
|||
|
else
|
|||
|
symp = SortBuffer[el];
|
|||
|
|
|||
|
|
|||
|
pointer.fptr = (BYTE far *) symp;
|
|||
|
|
|||
|
if(pointer.ptr.seg) /* If resident - segment value != 0 */
|
|||
|
picur = 0; /* Picur not valid */
|
|||
|
else
|
|||
|
pointer.fptr = (BYTE far *) mapva(AREASYMS + (pointer.vptr << SYMSCALE),FALSE);
|
|||
|
/* Fetch from virtual memory */
|
|||
|
|
|||
|
if (faddr) /* If buffer sorted by addresses */
|
|||
|
{
|
|||
|
prop = (APROPNAMEPTR ) pointer.fptr;
|
|||
|
while (prop->an_attr != ATTRNIL)
|
|||
|
{
|
|||
|
pointer.fptr = (BYTE far *) prop->an_next;
|
|||
|
|
|||
|
if(pointer.ptr.seg) /* If resident - segment value != 0 */
|
|||
|
picur = 0; /* Picur not valid */
|
|||
|
else
|
|||
|
pointer.fptr = (BYTE far *) mapva(AREASYMS + (pointer.vptr << SYMSCALE),FALSE);
|
|||
|
/* Fetch from virtual memory */
|
|||
|
prop = (APROPNAMEPTR ) pointer.fptr;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
hte = (AHTEPTR ) pointer.fptr;
|
|||
|
|
|||
|
for (i = 0; i < B2W(hte->cch[0]); i++)
|
|||
|
name[i] = hte->cch[i+1];
|
|||
|
name[i] = '\0';
|
|||
|
fprintf(stdout, " %s ", name);
|
|||
|
}
|
|||
|
|
|||
|
#endif
|
|||
|
|
|||
|
#if AUTOVM
|
|||
|
|
|||
|
/*
|
|||
|
* A sorting algorithm:
|
|||
|
*
|
|||
|
* for i := 1 to SymMax do
|
|||
|
* begin
|
|||
|
* { Insert element }
|
|||
|
* SortBuffer[i] = pointer-to-symbol;
|
|||
|
* SiftUp(i);
|
|||
|
* end
|
|||
|
*
|
|||
|
* for i := SymMax downto 2 do
|
|||
|
* begin
|
|||
|
* { Extract min element }
|
|||
|
* Do-what-you-want-with SortBuffer[1] element;
|
|||
|
* Swap(SortBuffer[1], SortBuffer[i]);
|
|||
|
* SiftDown(i - 1);
|
|||
|
* end
|
|||
|
*/
|
|||
|
|
|||
|
|
|||
|
|
|||
|
/*_________________________________________________________________*
|
|||
|
| |
|
|||
|
| NAME |
|
|||
|
| |
|
|||
|
| SiftUp |
|
|||
|
| |
|
|||
|
| INPUT |
|
|||
|
| |
|
|||
|
| Actual size of sorting heap. |
|
|||
|
| |
|
|||
|
| FUNCTION |
|
|||
|
| |
|
|||
|
| Placing an arbitrary element in SortBuffer[n] when |
|
|||
|
| SortBuffer[n-1] has a heap property will probably not |
|
|||
|
| yield the property heap(1, n) for the SortBuffer; |
|
|||
|
| establishing this property is the job of procedure SiftUp. |
|
|||
|
| |
|
|||
|
| RETURNS |
|
|||
|
| |
|
|||
|
| Nothing. |
|
|||
|
| |
|
|||
|
|_________________________________________________________________|
|
|||
|
* */
|
|||
|
|
|||
|
|
|||
|
LOCAL void NEAR SiftUp(unsigned n)
|
|||
|
|
|||
|
{
|
|||
|
unsigned i;
|
|||
|
unsigned p;
|
|||
|
RBTYPE child;
|
|||
|
RBTYPE parent;
|
|||
|
RBTYPE *VMp;
|
|||
|
|
|||
|
|
|||
|
/*
|
|||
|
* Precondition: SortBuffer has property heap(1, n-1) and n > 0
|
|||
|
*/
|
|||
|
|
|||
|
i = n;
|
|||
|
|
|||
|
for (;;)
|
|||
|
{
|
|||
|
/*
|
|||
|
* Loop invariant condition: SortBuffer has property heap(1, n)
|
|||
|
* except perhaps between "i" and its parent.
|
|||
|
*/
|
|||
|
|
|||
|
if (i == 1)
|
|||
|
return; /* POSTCONDITION: SortBuffer HAS PROPERTY HEAP(1, N). */
|
|||
|
|
|||
|
p = i >> 1; /* p = i div 2 */
|
|||
|
|
|||
|
if (i > LastInBuf)
|
|||
|
{ /* Fetch element from virtual memory */
|
|||
|
VMp = VMBuffer(i);
|
|||
|
child = *VMp;
|
|||
|
}
|
|||
|
else child = SortBuffer[i];
|
|||
|
|
|||
|
if (p > LastInBuf)
|
|||
|
{ /* Fetch element from virtual memory */
|
|||
|
VMp = VMBuffer(p);
|
|||
|
parent = *VMp;
|
|||
|
}
|
|||
|
else parent = SortBuffer[p];
|
|||
|
|
|||
|
if ((*TestFun)(&parent, &child))
|
|||
|
break;
|
|||
|
|
|||
|
/* swap(p, i) */
|
|||
|
|
|||
|
if (p > LastInBuf)
|
|||
|
{
|
|||
|
VMp = VMBuffer(p);
|
|||
|
*VMp = child;
|
|||
|
markvp();
|
|||
|
}
|
|||
|
else SortBuffer[p] = child;
|
|||
|
|
|||
|
if (i > LastInBuf)
|
|||
|
{ /* Fetch element from virtual memory */
|
|||
|
VMp = VMBuffer(i);
|
|||
|
*VMp = parent;
|
|||
|
markvp();
|
|||
|
}
|
|||
|
else SortBuffer[i] = parent;
|
|||
|
|
|||
|
#if SORTDEBUG
|
|||
|
fprintf(stdout, " \r\nSIFTUP - swap ");
|
|||
|
DumpElement(p, cmpf == FGtAddr);
|
|||
|
fprintf(stdout, " with ");
|
|||
|
DumpElement(i, cmpf == FGtAddr);
|
|||
|
fprintf(stdout, " \r\n");
|
|||
|
#endif
|
|||
|
i = p;
|
|||
|
}
|
|||
|
/* POSTCONDITION: SortBuffer HAS PROPERTY HEAP(1, N). */
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
/*_________________________________________________________________*
|
|||
|
| |
|
|||
|
| NAME |
|
|||
|
| |
|
|||
|
| SiftDown |
|
|||
|
| |
|
|||
|
| INPUT |
|
|||
|
| |
|
|||
|
| Actual size of sorting heap. |
|
|||
|
| |
|
|||
|
| FUNCTION |
|
|||
|
| |
|
|||
|
| Assigning a new value to SortBuffer[1] leaves the |
|
|||
|
| SortBuffer[2 ... n] with heap property. Procedure |
|
|||
|
| SiftDown makes heap(SortBuffer[1 ... n]) true. |
|
|||
|
| |
|
|||
|
| RETURNS |
|
|||
|
| |
|
|||
|
| Nothing. |
|
|||
|
| |
|
|||
|
|_________________________________________________________________|
|
|||
|
* */
|
|||
|
|
|||
|
|
|||
|
|
|||
|
LOCAL void NEAR SiftDown(unsigned n)
|
|||
|
{
|
|||
|
DWORD i;
|
|||
|
DWORD c;
|
|||
|
RBTYPE child[2];
|
|||
|
RBTYPE parent;
|
|||
|
RBTYPE *VMp;
|
|||
|
|
|||
|
|
|||
|
/*
|
|||
|
* Precondition: SortBuffer has property heap(2, n) and n > 0
|
|||
|
*/
|
|||
|
|
|||
|
i = 1L;
|
|||
|
|
|||
|
for (;;)
|
|||
|
{
|
|||
|
/*
|
|||
|
* Loop invariant condition: SortBuffer has property heap(1, n)
|
|||
|
* except perhaps between "i" and its (0, 1 or 2) children.
|
|||
|
*/
|
|||
|
|
|||
|
c = i << 1;
|
|||
|
|
|||
|
if (c > (DWORD) n)
|
|||
|
break;
|
|||
|
|
|||
|
/* c is the left child of i */
|
|||
|
|
|||
|
if (c + 1 <= (DWORD) n)
|
|||
|
{
|
|||
|
/* c + 1 is the right child of i */
|
|||
|
|
|||
|
if (c > LastInBuf)
|
|||
|
{ /* Fetch element from virtual memory */
|
|||
|
VMp = VMBuffer(c);
|
|||
|
child[0] = *VMp;
|
|||
|
VMp = VMBuffer(c + 1);
|
|||
|
child[1] = *VMp;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
child[0] = SortBuffer[c];
|
|||
|
if (c + 1 > LastInBuf)
|
|||
|
{
|
|||
|
VMp = VMBuffer(c + 1);
|
|||
|
child[1] = *VMp;
|
|||
|
}
|
|||
|
else child[1] = SortBuffer[c+1];
|
|||
|
}
|
|||
|
|
|||
|
if ((*TestFunS)(&child[1], &child[0]))
|
|||
|
{
|
|||
|
c++;
|
|||
|
child[0] = child[1];
|
|||
|
}
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
/* only left child of i */
|
|||
|
|
|||
|
if (c > LastInBuf)
|
|||
|
{ /* Fetch element from virtual memory */
|
|||
|
VMp = VMBuffer(c);
|
|||
|
child[0] = *VMp;
|
|||
|
}
|
|||
|
else child[0] = SortBuffer[c];
|
|||
|
}
|
|||
|
|
|||
|
/* c is the least child of i */
|
|||
|
|
|||
|
if (i > LastInBuf)
|
|||
|
{
|
|||
|
VMp = VMBuffer(i);
|
|||
|
parent = *VMp;
|
|||
|
}
|
|||
|
else parent = SortBuffer[i];
|
|||
|
|
|||
|
if ((*TestFun)(&parent, &child[0]))
|
|||
|
break;
|
|||
|
|
|||
|
/* swap(p, i) */
|
|||
|
|
|||
|
if (i > LastInBuf)
|
|||
|
{
|
|||
|
VMp = VMBuffer(i);
|
|||
|
*VMp = child[0];
|
|||
|
markvp();
|
|||
|
}
|
|||
|
else SortBuffer[i] = child[0];
|
|||
|
|
|||
|
if (c > LastInBuf)
|
|||
|
{
|
|||
|
VMp = VMBuffer(c);
|
|||
|
*VMp = parent;
|
|||
|
markvp();
|
|||
|
}
|
|||
|
else SortBuffer[c] = parent;
|
|||
|
|
|||
|
#if SORTDEBUG
|
|||
|
fprintf(stdout, " \r\nSIFTDOWN - swap ");
|
|||
|
DumpElement(i, cmpf == FGtAddr);
|
|||
|
fprintf(stdout, " with ");
|
|||
|
DumpElement(c, cmpf == FGtAddr);
|
|||
|
fprintf(stdout, " \r\n");
|
|||
|
#endif
|
|||
|
i = c;
|
|||
|
}
|
|||
|
|
|||
|
/* POSTCONDITION: SortBuffer HAS PROPERTY HEAP(1, N). */
|
|||
|
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
#endif
|
|||
|
|
|||
|
LOCAL int NEAR AscendingOrder(RBTYPE *arg1, RBTYPE *arg2)
|
|||
|
{
|
|||
|
return((*cmpf)(arg1, arg2) <= 0);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
LOCAL int NEAR DescendingOrder(RBTYPE *arg1, RBTYPE *arg2)
|
|||
|
{
|
|||
|
return((*cmpf)(arg1, arg2) >= 0);
|
|||
|
}
|
|||
|
|
|||
|
LOCAL int NEAR AscendingOrderSharp(RBTYPE *arg1, RBTYPE *arg2)
|
|||
|
{
|
|||
|
return((*cmpf)(arg1, arg2) < 0);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
LOCAL int NEAR DescendingOrderSharp(RBTYPE *arg1, RBTYPE *arg2)
|
|||
|
{
|
|||
|
return((*cmpf)(arg1, arg2) > 0);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
/*_________________________________________________________________*
|
|||
|
| |
|
|||
|
| NAME |
|
|||
|
| |
|
|||
|
| ExtractMin |
|
|||
|
| |
|
|||
|
| INPUT |
|
|||
|
| |
|
|||
|
| Actual size of sorting heap. |
|
|||
|
| |
|
|||
|
| FUNCTION |
|
|||
|
| |
|
|||
|
| Get smallest element from SortBuffer and reheap if |
|
|||
|
| neccesary. Function takes into account fact that |
|
|||
|
| SortBuffer can be allocated only in "real" memory and if |
|
|||
|
| this is true, than QUICKSORT is used instead of HEAPSORT. |
|
|||
|
| |
|
|||
|
| RETURNS |
|
|||
|
| |
|
|||
|
| Pointer to smallest element from SortBuffer. |
|
|||
|
| |
|
|||
|
|_________________________________________________________________|
|
|||
|
* */
|
|||
|
|
|||
|
|
|||
|
RBTYPE NEAR ExtractMin(unsigned n)
|
|||
|
{
|
|||
|
|
|||
|
RBTYPE *VMp;
|
|||
|
RBTYPE RetVal;
|
|||
|
|
|||
|
|
|||
|
if (fInMemOnly)
|
|||
|
{
|
|||
|
if (fFirstTime)
|
|||
|
{
|
|||
|
/* First time called - sort buffer */
|
|||
|
|
|||
|
qsort(SortBuffer, symMac, sizeof(RBTYPE),
|
|||
|
(int (__cdecl *)(const void *, const void *)) cmpf);
|
|||
|
fFirstTime = FALSE;
|
|||
|
}
|
|||
|
|
|||
|
RetVal = SortBuffer[SortIndex++];
|
|||
|
|
|||
|
if (SortIndex >= symMac)
|
|||
|
{
|
|||
|
/* Last element extracted - reset flags and counters */
|
|||
|
|
|||
|
fFirstTime = (FTYPE) TRUE;
|
|||
|
SortIndex = 0;
|
|||
|
}
|
|||
|
}
|
|||
|
#if AUTOVM
|
|||
|
else
|
|||
|
{
|
|||
|
RetVal = SortBuffer[1];
|
|||
|
|
|||
|
#if SORTDEBUG
|
|||
|
fprintf(stdout, " \r\nAFTER EXTRACTING element ");
|
|||
|
DumpElement(1, cmpf == FGtAddr);
|
|||
|
#endif
|
|||
|
|
|||
|
if (n > LastInBuf)
|
|||
|
{
|
|||
|
VMp = VMBuffer(n);
|
|||
|
SortBuffer[1] = *VMp;
|
|||
|
}
|
|||
|
else
|
|||
|
SortBuffer[1] = SortBuffer[n];
|
|||
|
|
|||
|
SiftDown(n - 1);
|
|||
|
|
|||
|
#if SORTDEBUG
|
|||
|
fprintf(stdout, "\r\nVerifying Sort Buffer - size = %u ", n-1);
|
|||
|
CheckSortBuffer(1,n-1);
|
|||
|
#endif
|
|||
|
}
|
|||
|
#endif
|
|||
|
return(RetVal);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
/*_________________________________________________________________*
|
|||
|
| |
|
|||
|
| NAME |
|
|||
|
| |
|
|||
|
| Store |
|
|||
|
| |
|
|||
|
| INPUT |
|
|||
|
| |
|
|||
|
| Element to be put in SortBuffer |
|
|||
|
| |
|
|||
|
| FUNCTION |
|
|||
|
| |
|
|||
|
| Put element into SortBuffer and reheap if neccesary. |
|
|||
|
| Function takes into account fact that SortBuffer can be |
|
|||
|
| allocated only in "real" memory. |
|
|||
|
| |
|
|||
|
| RETURNS |
|
|||
|
| |
|
|||
|
| Nothing. |
|
|||
|
| |
|
|||
|
|_________________________________________________________________|
|
|||
|
* */
|
|||
|
|
|||
|
|
|||
|
|
|||
|
void NEAR Store(RBTYPE element)
|
|||
|
{
|
|||
|
|
|||
|
RBTYPE *VMp;
|
|||
|
|
|||
|
|
|||
|
#if AUTOVM
|
|||
|
if (fInMemOnly)
|
|||
|
{
|
|||
|
SortBuffer[symMac++] = element;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
symMac++;
|
|||
|
if (symMac > LastInBuf)
|
|||
|
{
|
|||
|
VMp = VMBuffer(symMac);
|
|||
|
*VMp = element;
|
|||
|
markvp();
|
|||
|
}
|
|||
|
else
|
|||
|
SortBuffer[symMac] = element;
|
|||
|
|
|||
|
#if SORTDEBUG
|
|||
|
fprintf(stdout, " \r\nAFTER ADDING element ");
|
|||
|
DumpElement(symMac, cmpf == FGtAddr);
|
|||
|
#endif
|
|||
|
|
|||
|
SiftUp(symMac);
|
|||
|
|
|||
|
#if SORTDEBUG
|
|||
|
fprintf(stdout, "\r\nVerifying Sort Buffer - size = %u ", symMac);
|
|||
|
CheckSortBuffer(1,symMac);
|
|||
|
#endif
|
|||
|
}
|
|||
|
#else
|
|||
|
SortBuffer[symMac++] = element;
|
|||
|
#endif
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
/*_________________________________________________________________*
|
|||
|
| |
|
|||
|
| NAME |
|
|||
|
| |
|
|||
|
| InitSort |
|
|||
|
| |
|
|||
|
| INPUT |
|
|||
|
| |
|
|||
|
| Nothing. |
|
|||
|
| |
|
|||
|
| FUNCTION |
|
|||
|
| |
|
|||
|
| Initialize global variables used by INCREMENTAL module. |
|
|||
|
| Function takes into account fact that SortBuffer can be |
|
|||
|
| allocated only in "real" memory and if this is true than |
|
|||
|
| QUICKSORT instead of HEAPSORT to sort the SortBuffer. |
|
|||
|
| |
|
|||
|
| RETURNS |
|
|||
|
| |
|
|||
|
| Nothing. |
|
|||
|
| |
|
|||
|
|_________________________________________________________________|
|
|||
|
* */
|
|||
|
|
|||
|
void NEAR InitSort(RBTYPE **buf, WORD *base1, WORD *lim1,
|
|||
|
WORD *base2, WORD *lim2 )
|
|||
|
{
|
|||
|
|
|||
|
RBTYPE *VMp;
|
|||
|
RBTYPE first, last;
|
|||
|
unsigned n, lx;
|
|||
|
|
|||
|
|
|||
|
if (fInMemOnly)
|
|||
|
{
|
|||
|
/* SortBuffer allocated only in "real" memory - use QUICKSORT */
|
|||
|
|
|||
|
qsort(SortBuffer, symMac, sizeof(RBTYPE),
|
|||
|
(int (__cdecl *)(const void *, const void *)) cmpf);
|
|||
|
*base1 = 0;
|
|||
|
*lim1 = symMac;
|
|||
|
*base2 = symMac + 1;
|
|||
|
*lim2 = symMac + 1;
|
|||
|
}
|
|||
|
#if AUTOVM
|
|||
|
else
|
|||
|
{
|
|||
|
/* SortBuffer allocated in "real" and "virtual" memory - use HEAPSORT */
|
|||
|
|
|||
|
for (n = 1, lx = symMac; lx > 2; n++, lx--)
|
|||
|
{
|
|||
|
if (lx > LastInBuf)
|
|||
|
{
|
|||
|
VMp = VMBuffer(lx);
|
|||
|
last = *VMp;
|
|||
|
}
|
|||
|
else
|
|||
|
last = SortBuffer[lx];
|
|||
|
|
|||
|
first = SortBuffer[1];
|
|||
|
SortBuffer[1] = last;
|
|||
|
|
|||
|
if (lx > LastInBuf)
|
|||
|
{
|
|||
|
*VMp = first;
|
|||
|
markvp();
|
|||
|
}
|
|||
|
else
|
|||
|
SortBuffer[lx] = first;
|
|||
|
|
|||
|
SiftDown(lx - 1);
|
|||
|
}
|
|||
|
|
|||
|
first = SortBuffer[1];
|
|||
|
SortBuffer[1] = SortBuffer[2];
|
|||
|
SortBuffer[2] = first;
|
|||
|
*base1 = 1;
|
|||
|
*lim1 = (symMac < LastInBuf) ? symMac + 1 : LastInBuf + 1;
|
|||
|
*base2 = *lim1;
|
|||
|
*lim2 = symMac + 1;
|
|||
|
}
|
|||
|
#endif
|
|||
|
|
|||
|
*buf = SortBuffer;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
#if AUTOVM
|
|||
|
|
|||
|
/*_________________________________________________________________*
|
|||
|
| |
|
|||
|
| NAME |
|
|||
|
| |
|
|||
|
| GetSymPtr |
|
|||
|
| |
|
|||
|
| INPUT |
|
|||
|
| |
|
|||
|
| Index in SortBuffer. |
|
|||
|
| |
|
|||
|
| FUNCTION |
|
|||
|
| |
|
|||
|
| Get element from "virtual" portion of SortBuffer. |
|
|||
|
| |
|
|||
|
| RETURNS |
|
|||
|
| |
|
|||
|
| Retrieved element. |
|
|||
|
| |
|
|||
|
|_________________________________________________________________|
|
|||
|
* */
|
|||
|
|
|||
|
RBTYPE NEAR GetSymPtr(unsigned n)
|
|||
|
{
|
|||
|
RBTYPE *VMp;
|
|||
|
RBTYPE RetVal;
|
|||
|
|
|||
|
VMp = VMBuffer(n);
|
|||
|
RetVal = *VMp;
|
|||
|
return(RetVal);
|
|||
|
}
|
|||
|
|
|||
|
#endif
|
|||
|
|
|||
|
/*_________________________________________________________________*
|
|||
|
| |
|
|||
|
| NAME |
|
|||
|
| |
|
|||
|
| AllocSortBuffer |
|
|||
|
| |
|
|||
|
| INPUT |
|
|||
|
| |
|
|||
|
| Max number of elements to be sorted and sorting order flag.|
|
|||
|
| |
|
|||
|
| FUNCTION |
|
|||
|
| |
|
|||
|
| Allocate space for SortBuffer and set pointer to test |
|
|||
|
| function accordingly to sorting order flag. |
|
|||
|
| |
|
|||
|
| RETURNS |
|
|||
|
| |
|
|||
|
| Nothing. |
|
|||
|
| |
|
|||
|
|_________________________________________________________________|
|
|||
|
* */
|
|||
|
|
|||
|
void NEAR AllocSortBuffer(unsigned max, int AOrder)
|
|||
|
{
|
|||
|
|
|||
|
extern short pimac;
|
|||
|
unsigned long SpaceAvail;
|
|||
|
unsigned long SpaceNeeded;
|
|||
|
unsigned long VMBufferSize;
|
|||
|
|
|||
|
/*
|
|||
|
* Determine how much space is available on near heap and how much
|
|||
|
* we need. Assume ascending sort order. Set number of elements
|
|||
|
* in "real" portion of SortBuffer.
|
|||
|
*/
|
|||
|
|
|||
|
SpaceNeeded = (long)(max + 1) * sizeof(RBTYPE);
|
|||
|
LastInBuf = (WORD) max;
|
|||
|
fInMemOnly = (FTYPE) TRUE;
|
|||
|
TestFun = AscendingOrder;
|
|||
|
TestFunS = AscendingOrderSharp;
|
|||
|
#if OSMSDOS AND AUTOVM
|
|||
|
SpaceAvail = _memmax();
|
|||
|
|
|||
|
if (SpaceNeeded > SpaceAvail)
|
|||
|
{
|
|||
|
/*
|
|||
|
* We need more than there is available - try deallocate
|
|||
|
* VM page buffers
|
|||
|
*/
|
|||
|
|
|||
|
if (pimac > 8)
|
|||
|
{
|
|||
|
/* For perfomance reasons we need at least 8 page buffer */
|
|||
|
|
|||
|
VMBufferSize = 8 * PAGLEN;
|
|||
|
|
|||
|
/* Cleanup near heap by relaiming all virtual memory page buffers */
|
|||
|
|
|||
|
FreeMem(ReclaimVM(MAXBUF * PAGLEN));
|
|||
|
}
|
|||
|
else
|
|||
|
VMBufferSize = 0;
|
|||
|
|
|||
|
/* Check how much is now available */
|
|||
|
|
|||
|
SpaceAvail = _memmax() - VMBufferSize;
|
|||
|
|
|||
|
if (SpaceNeeded > SpaceAvail)
|
|||
|
fInMemOnly = FALSE;
|
|||
|
/* Sorting buffer will be split between "real" and "virtual" memory */
|
|||
|
else
|
|||
|
SpaceAvail = SpaceNeeded;
|
|||
|
|
|||
|
/* Calculate how many elements can go into "real" part of SortBuffer */
|
|||
|
|
|||
|
LastInBuf = (unsigned)SpaceAvail / sizeof(RBTYPE);
|
|||
|
|
|||
|
/* Allocate space for SortBuffer */
|
|||
|
|
|||
|
SortBuffer = (RBTYPE *) GetMem(LastInBuf * sizeof(RBTYPE));
|
|||
|
|
|||
|
LastInBuf--;
|
|||
|
fVMReclaim = (FTYPE) TRUE;
|
|||
|
|
|||
|
/*
|
|||
|
* If descending sort order was requested and SortBuffer is split
|
|||
|
* between "real" and "virtual" memory change test function.
|
|||
|
*/
|
|||
|
|
|||
|
if (!fInMemOnly && !AOrder)
|
|||
|
{
|
|||
|
TestFun = DescendingOrder;
|
|||
|
TestFunS = DescendingOrderSharp;
|
|||
|
}
|
|||
|
|
|||
|
return;
|
|||
|
}
|
|||
|
#endif
|
|||
|
/* There is space available so take it. */
|
|||
|
|
|||
|
SortBuffer = (RBTYPE *) GetMem((unsigned)SpaceNeeded);
|
|||
|
fVMReclaim = FALSE;
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
/*_________________________________________________________________*
|
|||
|
| |
|
|||
|
| NAME |
|
|||
|
| |
|
|||
|
| FreeSortBuffer |
|
|||
|
| |
|
|||
|
| INPUT |
|
|||
|
| |
|
|||
|
| Nothing. |
|
|||
|
| |
|
|||
|
| FUNCTION |
|
|||
|
| |
|
|||
|
| Free space allocated for SortBuffer and if neccesary |
|
|||
|
| perform near heap cleanup by reclaiming all VM |
|
|||
|
| page buffers. |
|
|||
|
| |
|
|||
|
| RETURNS |
|
|||
|
| |
|
|||
|
| Nothing. |
|
|||
|
| |
|
|||
|
|_________________________________________________________________|
|
|||
|
* */
|
|||
|
|
|||
|
void NEAR FreeSortBuffer(void)
|
|||
|
{
|
|||
|
extern short pimac, pimax;
|
|||
|
|
|||
|
|
|||
|
if (SortBuffer != NULL)
|
|||
|
FFREE(SortBuffer);
|
|||
|
}
|