Source code of Windows XP (NT5)
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.

950 lines
32 KiB

  1. /*_________________________________________________________________*
  2. | |
  3. | MODULE |
  4. | |
  5. | HSORT |
  6. | (C) Copyright Microsoft Corp 1988 |
  7. | 10 March 1988 |
  8. | |
  9. | FUNCTION |
  10. | |
  11. | Sorting functions required by linker. |
  12. | |
  13. | DEFINES |
  14. | |
  15. | void AllocSortBuffer(unsigned max, int AOrder) |
  16. | RBTYPE ExtractMin(unsigned n) |
  17. | void FreeSortBuffer(void) |
  18. | void InitSort(RBTYPE **buf, WORD *base1, WORD *lim1, |
  19. | WORD *base2, WORD *lim2 ) |
  20. | RBTYPE GetSymPtr(unsigned n) |
  21. | void Store(RBTYPE element) |
  22. | |
  23. | USES |
  24. | |
  25. | cmpf global pointer to comparing function |
  26. | AREASORT area in virtual memory where sort buffer is |
  27. | extended |
  28. | |
  29. | CHANGES |
  30. | |
  31. | symMac global counter of sorted symbols |
  32. | |
  33. | MODIFICATION HISTORY |
  34. | |
  35. | 88/03/10 Wieslaw Kalkus Initial version |
  36. | |
  37. | |
  38. | |
  39. |_________________________________________________________________|
  40. * */
  41. #include <minlit.h> /* Types and constants */
  42. #include <bndtrn.h> /* Basic type & const declarations */
  43. #include <bndrel.h> /* Types and constants */
  44. #include <lnkio.h> /* Linker I/O definitions */
  45. #include <lnkmsg.h> /* Error messages */
  46. #include <extern.h> /* External declarations */
  47. #define VMBuffer(x) (RBTYPE *)mapva((long)(AREASORT+((long)(x)*sizeof(RBTYPE))),FALSE)
  48. #define SORTDEBUG FALSE
  49. LOCAL WORD LastInBuf; /* Last element in sort buffer */
  50. LOCAL RBTYPE *SortBuffer; /* Sort buffer allocated on near heap */
  51. LOCAL FTYPE fVMReclaim; /* TRUE if VM page buffers reclaimed */
  52. LOCAL FTYPE fInMemOnly; /* TRUE if not using VM for sort buffer */
  53. LOCAL FTYPE fFirstTime = (FTYPE) TRUE;
  54. LOCAL WORD SortIndex = 0;
  55. LOCAL int (NEAR *TestFun)(RBTYPE *arg1, RBTYPE *arg2);
  56. LOCAL int (NEAR *TestFunS)(RBTYPE *arg1, RBTYPE *arg2);
  57. /*
  58. * LOCAL FUNCTION PROTOTYPES
  59. */
  60. LOCAL void NEAR SiftDown(unsigned n);
  61. LOCAL void NEAR SiftUp(unsigned n);
  62. LOCAL int NEAR AscendingOrder(RBTYPE *arg1, RBTYPE *arg2);
  63. LOCAL int NEAR DescendingOrder(RBTYPE *arg1, RBTYPE *arg2);
  64. /*
  65. * DEBUGING FUNCTIONS
  66. */
  67. #if SORTDEBUG
  68. LOCAL void NEAR DumpSortBuffer(unsigned max, int faddr);
  69. LOCAL void NEAR DumpElement(unsigned el, int faddr);
  70. LOCAL void NEAR CheckSortBuffer(unsigned n, unsigned max);
  71. LOCAL void NEAR CheckSortBuffer(unsigned root, unsigned max)
  72. {
  73. DWORD c;
  74. RBTYPE child[2];
  75. RBTYPE parent;
  76. RBTYPE *VMp;
  77. c = root << 1;
  78. if (c > (long) max)
  79. return;
  80. /* c is the left child of root */
  81. if (c + 1 <= (long) max)
  82. {
  83. /* c + 1 is the right child of root */
  84. if (c > LastInBuf)
  85. { /* Fetch element from virtual memory */
  86. VMp = VMBuffer(c);
  87. child[0] = *VMp;
  88. VMp = VMBuffer(c + 1);
  89. child[1] = *VMp;
  90. }
  91. else
  92. {
  93. child[0] = SortBuffer[c];
  94. if (c + 1 > LastInBuf)
  95. {
  96. VMp = VMBuffer(c + 1);
  97. child[1] = *VMp;
  98. }
  99. else child[1] = SortBuffer[c+1];
  100. }
  101. }
  102. else
  103. {
  104. /* only left child of root */
  105. if (c > LastInBuf)
  106. { /* Fetch element from virtual memory */
  107. VMp = VMBuffer(c);
  108. child[0] = *VMp;
  109. }
  110. else child[0] = SortBuffer[c];
  111. }
  112. if (root > LastInBuf)
  113. {
  114. VMp = VMBuffer(root);
  115. parent = *VMp;
  116. }
  117. else parent = SortBuffer[root];
  118. if (!(*TestFun)(&parent, &child[0]))
  119. {
  120. fprintf(stdout, "\r\nBAD sort buffer --> root = %u; left child = %lu \r\n", root, c);
  121. DumpElement(root, cmpf == FGtAddr);
  122. DumpElement(c, cmpf == FGtAddr);
  123. }
  124. if (c + 1 < (long) max)
  125. {
  126. if (!(*TestFun)(&parent, &child[1]))
  127. {
  128. fprintf(stdout, "\r\nBAD sort buffer --> root = %u; right child = %lu \r\n", root, c+1);
  129. DumpElement(root, cmpf == FGtAddr);
  130. DumpElement(c+1, cmpf == FGtAddr);
  131. }
  132. }
  133. CheckSortBuffer((unsigned) c, max);
  134. if (c + 1 < (long) max)
  135. CheckSortBuffer((unsigned) c+1, max);
  136. return;
  137. }
  138. LOCAL void NEAR DumpSortBuffer(unsigned max, int faddr)
  139. {
  140. unsigned x;
  141. for (x = 1; x <= max; x++)
  142. {
  143. fprintf(stdout, "SortBuffer[%u] = ", x);
  144. DumpElement(x, faddr);
  145. fprintf(stdout, " \r\n");
  146. }
  147. }
  148. LOCAL void NEAR DumpElement(unsigned el, int faddr)
  149. {
  150. unsigned i;
  151. RBTYPE *VMp;
  152. RBTYPE symp;
  153. AHTEPTR hte;
  154. APROPNAMEPTR prop;
  155. char name[40];
  156. union {
  157. long vptr; /* Virtual pointer */
  158. BYTE far *fptr; /* Far pointer */
  159. struct {
  160. unsigned short offset;
  161. /* Offset value */
  162. unsigned short seg;
  163. } /* Segmnet value */
  164. ptr;
  165. }
  166. pointer; /* Different ways to describe pointer */
  167. if (el > LastInBuf)
  168. {
  169. VMp = VMBuffer(el);
  170. symp = *VMp;
  171. }
  172. else
  173. symp = SortBuffer[el];
  174. pointer.fptr = (BYTE far *) symp;
  175. if(pointer.ptr.seg) /* If resident - segment value != 0 */
  176. picur = 0; /* Picur not valid */
  177. else
  178. pointer.fptr = (BYTE far *) mapva(AREASYMS + (pointer.vptr << SYMSCALE),FALSE);
  179. /* Fetch from virtual memory */
  180. if (faddr) /* If buffer sorted by addresses */
  181. {
  182. prop = (APROPNAMEPTR ) pointer.fptr;
  183. while (prop->an_attr != ATTRNIL)
  184. {
  185. pointer.fptr = (BYTE far *) prop->an_next;
  186. if(pointer.ptr.seg) /* If resident - segment value != 0 */
  187. picur = 0; /* Picur not valid */
  188. else
  189. pointer.fptr = (BYTE far *) mapva(AREASYMS + (pointer.vptr << SYMSCALE),FALSE);
  190. /* Fetch from virtual memory */
  191. prop = (APROPNAMEPTR ) pointer.fptr;
  192. }
  193. }
  194. hte = (AHTEPTR ) pointer.fptr;
  195. for (i = 0; i < B2W(hte->cch[0]); i++)
  196. name[i] = hte->cch[i+1];
  197. name[i] = '\0';
  198. fprintf(stdout, " %s ", name);
  199. }
  200. #endif
  201. #if AUTOVM
  202. /*
  203. * A sorting algorithm:
  204. *
  205. * for i := 1 to SymMax do
  206. * begin
  207. * { Insert element }
  208. * SortBuffer[i] = pointer-to-symbol;
  209. * SiftUp(i);
  210. * end
  211. *
  212. * for i := SymMax downto 2 do
  213. * begin
  214. * { Extract min element }
  215. * Do-what-you-want-with SortBuffer[1] element;
  216. * Swap(SortBuffer[1], SortBuffer[i]);
  217. * SiftDown(i - 1);
  218. * end
  219. */
  220. /*_________________________________________________________________*
  221. | |
  222. | NAME |
  223. | |
  224. | SiftUp |
  225. | |
  226. | INPUT |
  227. | |
  228. | Actual size of sorting heap. |
  229. | |
  230. | FUNCTION |
  231. | |
  232. | Placing an arbitrary element in SortBuffer[n] when |
  233. | SortBuffer[n-1] has a heap property will probably not |
  234. | yield the property heap(1, n) for the SortBuffer; |
  235. | establishing this property is the job of procedure SiftUp. |
  236. | |
  237. | RETURNS |
  238. | |
  239. | Nothing. |
  240. | |
  241. |_________________________________________________________________|
  242. * */
  243. LOCAL void NEAR SiftUp(unsigned n)
  244. {
  245. unsigned i;
  246. unsigned p;
  247. RBTYPE child;
  248. RBTYPE parent;
  249. RBTYPE *VMp;
  250. /*
  251. * Precondition: SortBuffer has property heap(1, n-1) and n > 0
  252. */
  253. i = n;
  254. for (;;)
  255. {
  256. /*
  257. * Loop invariant condition: SortBuffer has property heap(1, n)
  258. * except perhaps between "i" and its parent.
  259. */
  260. if (i == 1)
  261. return; /* POSTCONDITION: SortBuffer HAS PROPERTY HEAP(1, N). */
  262. p = i >> 1; /* p = i div 2 */
  263. if (i > LastInBuf)
  264. { /* Fetch element from virtual memory */
  265. VMp = VMBuffer(i);
  266. child = *VMp;
  267. }
  268. else child = SortBuffer[i];
  269. if (p > LastInBuf)
  270. { /* Fetch element from virtual memory */
  271. VMp = VMBuffer(p);
  272. parent = *VMp;
  273. }
  274. else parent = SortBuffer[p];
  275. if ((*TestFun)(&parent, &child))
  276. break;
  277. /* swap(p, i) */
  278. if (p > LastInBuf)
  279. {
  280. VMp = VMBuffer(p);
  281. *VMp = child;
  282. markvp();
  283. }
  284. else SortBuffer[p] = child;
  285. if (i > LastInBuf)
  286. { /* Fetch element from virtual memory */
  287. VMp = VMBuffer(i);
  288. *VMp = parent;
  289. markvp();
  290. }
  291. else SortBuffer[i] = parent;
  292. #if SORTDEBUG
  293. fprintf(stdout, " \r\nSIFTUP - swap ");
  294. DumpElement(p, cmpf == FGtAddr);
  295. fprintf(stdout, " with ");
  296. DumpElement(i, cmpf == FGtAddr);
  297. fprintf(stdout, " \r\n");
  298. #endif
  299. i = p;
  300. }
  301. /* POSTCONDITION: SortBuffer HAS PROPERTY HEAP(1, N). */
  302. return;
  303. }
  304. /*_________________________________________________________________*
  305. | |
  306. | NAME |
  307. | |
  308. | SiftDown |
  309. | |
  310. | INPUT |
  311. | |
  312. | Actual size of sorting heap. |
  313. | |
  314. | FUNCTION |
  315. | |
  316. | Assigning a new value to SortBuffer[1] leaves the |
  317. | SortBuffer[2 ... n] with heap property. Procedure |
  318. | SiftDown makes heap(SortBuffer[1 ... n]) true. |
  319. | |
  320. | RETURNS |
  321. | |
  322. | Nothing. |
  323. | |
  324. |_________________________________________________________________|
  325. * */
  326. LOCAL void NEAR SiftDown(unsigned n)
  327. {
  328. DWORD i;
  329. DWORD c;
  330. RBTYPE child[2];
  331. RBTYPE parent;
  332. RBTYPE *VMp;
  333. /*
  334. * Precondition: SortBuffer has property heap(2, n) and n > 0
  335. */
  336. i = 1L;
  337. for (;;)
  338. {
  339. /*
  340. * Loop invariant condition: SortBuffer has property heap(1, n)
  341. * except perhaps between "i" and its (0, 1 or 2) children.
  342. */
  343. c = i << 1;
  344. if (c > (DWORD) n)
  345. break;
  346. /* c is the left child of i */
  347. if (c + 1 <= (DWORD) n)
  348. {
  349. /* c + 1 is the right child of i */
  350. if (c > LastInBuf)
  351. { /* Fetch element from virtual memory */
  352. VMp = VMBuffer(c);
  353. child[0] = *VMp;
  354. VMp = VMBuffer(c + 1);
  355. child[1] = *VMp;
  356. }
  357. else
  358. {
  359. child[0] = SortBuffer[c];
  360. if (c + 1 > LastInBuf)
  361. {
  362. VMp = VMBuffer(c + 1);
  363. child[1] = *VMp;
  364. }
  365. else child[1] = SortBuffer[c+1];
  366. }
  367. if ((*TestFunS)(&child[1], &child[0]))
  368. {
  369. c++;
  370. child[0] = child[1];
  371. }
  372. }
  373. else
  374. {
  375. /* only left child of i */
  376. if (c > LastInBuf)
  377. { /* Fetch element from virtual memory */
  378. VMp = VMBuffer(c);
  379. child[0] = *VMp;
  380. }
  381. else child[0] = SortBuffer[c];
  382. }
  383. /* c is the least child of i */
  384. if (i > LastInBuf)
  385. {
  386. VMp = VMBuffer(i);
  387. parent = *VMp;
  388. }
  389. else parent = SortBuffer[i];
  390. if ((*TestFun)(&parent, &child[0]))
  391. break;
  392. /* swap(p, i) */
  393. if (i > LastInBuf)
  394. {
  395. VMp = VMBuffer(i);
  396. *VMp = child[0];
  397. markvp();
  398. }
  399. else SortBuffer[i] = child[0];
  400. if (c > LastInBuf)
  401. {
  402. VMp = VMBuffer(c);
  403. *VMp = parent;
  404. markvp();
  405. }
  406. else SortBuffer[c] = parent;
  407. #if SORTDEBUG
  408. fprintf(stdout, " \r\nSIFTDOWN - swap ");
  409. DumpElement(i, cmpf == FGtAddr);
  410. fprintf(stdout, " with ");
  411. DumpElement(c, cmpf == FGtAddr);
  412. fprintf(stdout, " \r\n");
  413. #endif
  414. i = c;
  415. }
  416. /* POSTCONDITION: SortBuffer HAS PROPERTY HEAP(1, N). */
  417. return;
  418. }
  419. #endif
  420. LOCAL int NEAR AscendingOrder(RBTYPE *arg1, RBTYPE *arg2)
  421. {
  422. return((*cmpf)(arg1, arg2) <= 0);
  423. }
  424. LOCAL int NEAR DescendingOrder(RBTYPE *arg1, RBTYPE *arg2)
  425. {
  426. return((*cmpf)(arg1, arg2) >= 0);
  427. }
  428. LOCAL int NEAR AscendingOrderSharp(RBTYPE *arg1, RBTYPE *arg2)
  429. {
  430. return((*cmpf)(arg1, arg2) < 0);
  431. }
  432. LOCAL int NEAR DescendingOrderSharp(RBTYPE *arg1, RBTYPE *arg2)
  433. {
  434. return((*cmpf)(arg1, arg2) > 0);
  435. }
  436. /*_________________________________________________________________*
  437. | |
  438. | NAME |
  439. | |
  440. | ExtractMin |
  441. | |
  442. | INPUT |
  443. | |
  444. | Actual size of sorting heap. |
  445. | |
  446. | FUNCTION |
  447. | |
  448. | Get smallest element from SortBuffer and reheap if |
  449. | neccesary. Function takes into account fact that |
  450. | SortBuffer can be allocated only in "real" memory and if |
  451. | this is true, than QUICKSORT is used instead of HEAPSORT. |
  452. | |
  453. | RETURNS |
  454. | |
  455. | Pointer to smallest element from SortBuffer. |
  456. | |
  457. |_________________________________________________________________|
  458. * */
  459. RBTYPE NEAR ExtractMin(unsigned n)
  460. {
  461. RBTYPE *VMp;
  462. RBTYPE RetVal;
  463. if (fInMemOnly)
  464. {
  465. if (fFirstTime)
  466. {
  467. /* First time called - sort buffer */
  468. qsort(SortBuffer, symMac, sizeof(RBTYPE),
  469. (int (__cdecl *)(const void *, const void *)) cmpf);
  470. fFirstTime = FALSE;
  471. }
  472. RetVal = SortBuffer[SortIndex++];
  473. if (SortIndex >= symMac)
  474. {
  475. /* Last element extracted - reset flags and counters */
  476. fFirstTime = (FTYPE) TRUE;
  477. SortIndex = 0;
  478. }
  479. }
  480. #if AUTOVM
  481. else
  482. {
  483. RetVal = SortBuffer[1];
  484. #if SORTDEBUG
  485. fprintf(stdout, " \r\nAFTER EXTRACTING element ");
  486. DumpElement(1, cmpf == FGtAddr);
  487. #endif
  488. if (n > LastInBuf)
  489. {
  490. VMp = VMBuffer(n);
  491. SortBuffer[1] = *VMp;
  492. }
  493. else
  494. SortBuffer[1] = SortBuffer[n];
  495. SiftDown(n - 1);
  496. #if SORTDEBUG
  497. fprintf(stdout, "\r\nVerifying Sort Buffer - size = %u ", n-1);
  498. CheckSortBuffer(1,n-1);
  499. #endif
  500. }
  501. #endif
  502. return(RetVal);
  503. }
  504. /*_________________________________________________________________*
  505. | |
  506. | NAME |
  507. | |
  508. | Store |
  509. | |
  510. | INPUT |
  511. | |
  512. | Element to be put in SortBuffer |
  513. | |
  514. | FUNCTION |
  515. | |
  516. | Put element into SortBuffer and reheap if neccesary. |
  517. | Function takes into account fact that SortBuffer can be |
  518. | allocated only in "real" memory. |
  519. | |
  520. | RETURNS |
  521. | |
  522. | Nothing. |
  523. | |
  524. |_________________________________________________________________|
  525. * */
  526. void NEAR Store(RBTYPE element)
  527. {
  528. RBTYPE *VMp;
  529. #if AUTOVM
  530. if (fInMemOnly)
  531. {
  532. SortBuffer[symMac++] = element;
  533. }
  534. else
  535. {
  536. symMac++;
  537. if (symMac > LastInBuf)
  538. {
  539. VMp = VMBuffer(symMac);
  540. *VMp = element;
  541. markvp();
  542. }
  543. else
  544. SortBuffer[symMac] = element;
  545. #if SORTDEBUG
  546. fprintf(stdout, " \r\nAFTER ADDING element ");
  547. DumpElement(symMac, cmpf == FGtAddr);
  548. #endif
  549. SiftUp(symMac);
  550. #if SORTDEBUG
  551. fprintf(stdout, "\r\nVerifying Sort Buffer - size = %u ", symMac);
  552. CheckSortBuffer(1,symMac);
  553. #endif
  554. }
  555. #else
  556. SortBuffer[symMac++] = element;
  557. #endif
  558. return;
  559. }
  560. /*_________________________________________________________________*
  561. | |
  562. | NAME |
  563. | |
  564. | InitSort |
  565. | |
  566. | INPUT |
  567. | |
  568. | Nothing. |
  569. | |
  570. | FUNCTION |
  571. | |
  572. | Initialize global variables used by INCREMENTAL module. |
  573. | Function takes into account fact that SortBuffer can be |
  574. | allocated only in "real" memory and if this is true than |
  575. | QUICKSORT instead of HEAPSORT to sort the SortBuffer. |
  576. | |
  577. | RETURNS |
  578. | |
  579. | Nothing. |
  580. | |
  581. |_________________________________________________________________|
  582. * */
  583. void NEAR InitSort(RBTYPE **buf, WORD *base1, WORD *lim1,
  584. WORD *base2, WORD *lim2 )
  585. {
  586. RBTYPE *VMp;
  587. RBTYPE first, last;
  588. unsigned n, lx;
  589. if (fInMemOnly)
  590. {
  591. /* SortBuffer allocated only in "real" memory - use QUICKSORT */
  592. qsort(SortBuffer, symMac, sizeof(RBTYPE),
  593. (int (__cdecl *)(const void *, const void *)) cmpf);
  594. *base1 = 0;
  595. *lim1 = symMac;
  596. *base2 = symMac + 1;
  597. *lim2 = symMac + 1;
  598. }
  599. #if AUTOVM
  600. else
  601. {
  602. /* SortBuffer allocated in "real" and "virtual" memory - use HEAPSORT */
  603. for (n = 1, lx = symMac; lx > 2; n++, lx--)
  604. {
  605. if (lx > LastInBuf)
  606. {
  607. VMp = VMBuffer(lx);
  608. last = *VMp;
  609. }
  610. else
  611. last = SortBuffer[lx];
  612. first = SortBuffer[1];
  613. SortBuffer[1] = last;
  614. if (lx > LastInBuf)
  615. {
  616. *VMp = first;
  617. markvp();
  618. }
  619. else
  620. SortBuffer[lx] = first;
  621. SiftDown(lx - 1);
  622. }
  623. first = SortBuffer[1];
  624. SortBuffer[1] = SortBuffer[2];
  625. SortBuffer[2] = first;
  626. *base1 = 1;
  627. *lim1 = (symMac < LastInBuf) ? symMac + 1 : LastInBuf + 1;
  628. *base2 = *lim1;
  629. *lim2 = symMac + 1;
  630. }
  631. #endif
  632. *buf = SortBuffer;
  633. }
  634. #if AUTOVM
  635. /*_________________________________________________________________*
  636. | |
  637. | NAME |
  638. | |
  639. | GetSymPtr |
  640. | |
  641. | INPUT |
  642. | |
  643. | Index in SortBuffer. |
  644. | |
  645. | FUNCTION |
  646. | |
  647. | Get element from "virtual" portion of SortBuffer. |
  648. | |
  649. | RETURNS |
  650. | |
  651. | Retrieved element. |
  652. | |
  653. |_________________________________________________________________|
  654. * */
  655. RBTYPE NEAR GetSymPtr(unsigned n)
  656. {
  657. RBTYPE *VMp;
  658. RBTYPE RetVal;
  659. VMp = VMBuffer(n);
  660. RetVal = *VMp;
  661. return(RetVal);
  662. }
  663. #endif
  664. /*_________________________________________________________________*
  665. | |
  666. | NAME |
  667. | |
  668. | AllocSortBuffer |
  669. | |
  670. | INPUT |
  671. | |
  672. | Max number of elements to be sorted and sorting order flag.|
  673. | |
  674. | FUNCTION |
  675. | |
  676. | Allocate space for SortBuffer and set pointer to test |
  677. | function accordingly to sorting order flag. |
  678. | |
  679. | RETURNS |
  680. | |
  681. | Nothing. |
  682. | |
  683. |_________________________________________________________________|
  684. * */
  685. void NEAR AllocSortBuffer(unsigned max, int AOrder)
  686. {
  687. extern short pimac;
  688. unsigned long SpaceAvail;
  689. unsigned long SpaceNeeded;
  690. unsigned long VMBufferSize;
  691. /*
  692. * Determine how much space is available on near heap and how much
  693. * we need. Assume ascending sort order. Set number of elements
  694. * in "real" portion of SortBuffer.
  695. */
  696. SpaceNeeded = (long)(max + 1) * sizeof(RBTYPE);
  697. LastInBuf = (WORD) max;
  698. fInMemOnly = (FTYPE) TRUE;
  699. TestFun = AscendingOrder;
  700. TestFunS = AscendingOrderSharp;
  701. #if OSMSDOS AND AUTOVM
  702. SpaceAvail = _memmax();
  703. if (SpaceNeeded > SpaceAvail)
  704. {
  705. /*
  706. * We need more than there is available - try deallocate
  707. * VM page buffers
  708. */
  709. if (pimac > 8)
  710. {
  711. /* For perfomance reasons we need at least 8 page buffer */
  712. VMBufferSize = 8 * PAGLEN;
  713. /* Cleanup near heap by relaiming all virtual memory page buffers */
  714. FreeMem(ReclaimVM(MAXBUF * PAGLEN));
  715. }
  716. else
  717. VMBufferSize = 0;
  718. /* Check how much is now available */
  719. SpaceAvail = _memmax() - VMBufferSize;
  720. if (SpaceNeeded > SpaceAvail)
  721. fInMemOnly = FALSE;
  722. /* Sorting buffer will be split between "real" and "virtual" memory */
  723. else
  724. SpaceAvail = SpaceNeeded;
  725. /* Calculate how many elements can go into "real" part of SortBuffer */
  726. LastInBuf = (unsigned)SpaceAvail / sizeof(RBTYPE);
  727. /* Allocate space for SortBuffer */
  728. SortBuffer = (RBTYPE *) GetMem(LastInBuf * sizeof(RBTYPE));
  729. LastInBuf--;
  730. fVMReclaim = (FTYPE) TRUE;
  731. /*
  732. * If descending sort order was requested and SortBuffer is split
  733. * between "real" and "virtual" memory change test function.
  734. */
  735. if (!fInMemOnly && !AOrder)
  736. {
  737. TestFun = DescendingOrder;
  738. TestFunS = DescendingOrderSharp;
  739. }
  740. return;
  741. }
  742. #endif
  743. /* There is space available so take it. */
  744. SortBuffer = (RBTYPE *) GetMem((unsigned)SpaceNeeded);
  745. fVMReclaim = FALSE;
  746. return;
  747. }
  748. /*_________________________________________________________________*
  749. | |
  750. | NAME |
  751. | |
  752. | FreeSortBuffer |
  753. | |
  754. | INPUT |
  755. | |
  756. | Nothing. |
  757. | |
  758. | FUNCTION |
  759. | |
  760. | Free space allocated for SortBuffer and if neccesary |
  761. | perform near heap cleanup by reclaiming all VM |
  762. | page buffers. |
  763. | |
  764. | RETURNS |
  765. | |
  766. | Nothing. |
  767. | |
  768. |_________________________________________________________________|
  769. * */
  770. void NEAR FreeSortBuffer(void)
  771. {
  772. extern short pimac, pimax;
  773. if (SortBuffer != NULL)
  774. FFREE(SortBuffer);
  775. }