#pragma inline
#include <asmrules.h>
#include <stdlib.h>
typedef int _CType comparF (const void _FAR *, const void _FAR *);
static comparF *Fcmp;
static unsigned qWidth;
static void near pascal Exchange (void *leftP, void *rightP)
{
#if 0
int i;
char c;
for (i = 0; i < qWidth; i++ ;)
{
c = *((char *) rightP);
*((char *) rightP )++ = *((char *) leftP);
*((char *) leftP )++ = c;
}
#endif
#if ! LDATA
asm push DS
#else
asm push DS
#endif
asm cld
asm mov cx, qWidth
asm LES_ di, rightP
asm LDS_ si, leftP
asm jnc xch_wordLoop
asm mov al, ES_ [di]
asm mov [si-1], al
xch_wordLoop:
asm mov ax, ES_ [di]
asm mov [si-2], ax
asm loop xch_wordLoop
xch_end:
#if LDATA
asm pop DS
#endif
return;
}
#ifdef __HUGE__
# define _LT_(x,y) (x < y)
#else
# define _LT_(x,y) ((unsigned short) x < (unsigned short) y)
#endif
#else
#define _LT_(x,y) (x < y)
#endif
#pragma warn -sig
#if defined(__HUGE__) || defined(__FARFUNCS__)
#pragma warn -sus
static void near pascal qSortHelp (char huge *pivotP, size_t nElem)
#else
static void near pascal qSortHelp (char *pivotP, size_t nElem)
#endif
{
#if defined(__HUGE__) || defined(__FARFUNCS__)
char huge *leftP, huge *rightP;
char huge *pivotEnd, huge *pivotTemp, huge *leftTemp;
#else
char *leftP, *rightP, *pivotEnd, *pivotTemp, *leftTemp;
#endif
unsigned lNum;
int retval;
tailRecursion:
if (nElem <= 2)
{
if (nElem == 2)
{
if (Fcmp (pivotP, rightP = qWidth + pivotP) > 0)
Exchange (pivotP, rightP);
}
return;
}
rightP = (nElem - 1) * qWidth + pivotP;
leftP = (nElem >> 1) * qWidth + pivotP;
if (Fcmp (leftP, rightP) > 0)
Exchange (leftP, rightP);
if (Fcmp (leftP, pivotP) > 0)
Exchange (leftP, pivotP);
else if (Fcmp (pivotP, rightP) > 0)
Exchange (pivotP, rightP);
if (nElem == 3)
{
Exchange (pivotP, leftP);
return;
}
leftP = pivotEnd = pivotP + qWidth;
do
{
while ((retval = Fcmp(leftP, pivotP)) <= 0)
{
if (retval == 0)
{
Exchange(leftP, pivotEnd);
pivotEnd += qWidth;
}
if (_LT_ (leftP, rightP))
leftP += qWidth;
else
goto qBreak;
}
while (_LT_(leftP, rightP))
{
if ((retval = Fcmp(pivotP, rightP)) < 0)
rightP -= qWidth;
else
{
Exchange (leftP, rightP);
if (retval != 0)
{
leftP += qWidth;
rightP -= qWidth;
}
break;
}
}
} while (_LT_(leftP, rightP));
qBreak:
if (Fcmp(leftP, pivotP) <= 0)
leftP = leftP + qWidth;
leftTemp = leftP - qWidth;
pivotTemp = pivotP;
while ((pivotTemp < pivotEnd) && (leftTemp >= pivotEnd))
{
Exchange(pivotTemp, leftTemp);
pivotTemp += qWidth;
leftTemp -= qWidth;
}
lNum = (leftP - pivotEnd) / qWidth;
nElem = ((nElem * qWidth + pivotP) - leftP)/qWidth;
// Sort smaller partition first to reduce stack usage
if (nElem < lNum)
{
qSortHelp (leftP, nElem);
nElem = lNum;
}
else
{
qSortHelp (pivotP, lNum);
pivotP = leftP;
}
goto tailRecursion;
}
#pragma warn .sig
#if defined(__HUGE__) || defined(__FARFUNCS__)
#pragma warn .sus
#endif
#if defined(__FARFUNCS__)
#include <_farfunc.h>
#endif
void _CType _FARFUNC qsort (void _FAR * baseP, size_t nElem, size_t width,
comparF *compar)
{
if ((qWidth = width) == 0)
return;
Fcmp = compar;
qSortHelp (baseP, nElem);
}