WSTORAGE.MOD 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602
  1. (* Release 3.10 *)
  2. (*-------------------------------------------------------------------------*
  3. * *
  4. * WSTORAGE.MOD - Dynamic allocations under Windows *
  5. * *
  6. * COPYRIGHT (C) 1987..1992 Clarion Software Corporation. *
  7. * All Rights Reserved *
  8. * *
  9. *--------------------------------------------------------------------------*)
  10. (*%F _fdata *)
  11. (*# call(seg_name => null) *)
  12. (*%E *)
  13. (*# data(seg_name => null) *)
  14. (*# check(stack=>off,
  15. index=>off,
  16. range=>off,
  17. overflow=>off,
  18. nil_ptr=>off) *)
  19. (*# module(implementation=>off) *)
  20. IMPLEMENTATION MODULE Storage;
  21. IMPORT SYSTEM, Lib, Windows, CoreSig;
  22. (*%T _mthread *)
  23. IMPORT Process;
  24. (*%E *)
  25. CONST
  26. EndMarker = 0FFFFH;
  27. Align = 4;
  28. (* This is DOS ONLY *)
  29. PROCEDURE FarMakeHeap( Source : CARDINAL; (* base segment of heap *)
  30. Size : CARDINAL (* size in paragraphs *)
  31. ) : FarHeapRecPtr;
  32. VAR
  33. storage,first,last : FarHeapRecPtr;
  34. BEGIN
  35. (*%T _mthread *)
  36. Process.Lock;
  37. (*%E *)
  38. storage := [Source:0];
  39. first := [Source+1:0];
  40. last := [Source+Size-1:0];
  41. storage^.next := first;
  42. storage^.size := 0;
  43. first^.next := last;
  44. last^.next := storage;
  45. first^.size := Size-2;
  46. last^.size := EndMarker;
  47. (*%T _mthread *)
  48. Process.Unlock;
  49. (*%E *)
  50. RETURN storage;
  51. END FarMakeHeap;
  52. PROCEDURE FarHeapAllocate(Source : FarHeapRecPtr; (* source heap *)
  53. VAR A : FarADDRESS; (* result *)
  54. Size : CARDINAL); (* request size in paragraphs *)
  55. VAR
  56. res,prev,split : FarHeapRecPtr;
  57. BEGIN
  58. IF Source = MainHeap THEN
  59. FarAllocate(A,Size);
  60. RETURN;
  61. END;
  62. (*%T _mthread *)
  63. Process.Lock;
  64. (*%E *)
  65. IF Size=0 THEN INC(Size) END ;
  66. prev := Source;
  67. WHILE prev^.next^.size < Size DO
  68. prev := prev^.next;
  69. END;
  70. res := prev^.next;
  71. IF res^.size = EndMarker THEN (* heap run out of space *)
  72. SYSTEM.EI ;
  73. Lib.RunTimeError(CoreSig._FatalErrorPos(), 90H, 'FarHeapAllocate : Out Of Space');
  74. END;
  75. IF res^.size = Size THEN (* block correct size *)
  76. prev^.next := res^.next;
  77. ELSE (* split block, bottom half returned, top half linked to free chain *)
  78. split := [CARDINAL(Seg(res^))+Size:0];
  79. prev^.next := split;
  80. split^.next := res^.next;
  81. split^.size := res^.size - Size;
  82. END;
  83. (*%T _mthread *)
  84. Process.Unlock;
  85. (*%E *)
  86. A := FarADR(res^);
  87. END FarHeapAllocate;
  88. PROCEDURE FarHeapAvail(Source: FarHeapRecPtr) : CARDINAL;
  89. (* returns the largest block size available for allocation in paragraphs *)
  90. VAR
  91. size : CARDINAL;
  92. p : FarHeapRecPtr;
  93. BEGIN
  94. IF Source = MainHeap THEN
  95. RETURN 1000H;
  96. END;
  97. (*%T _mthread *)
  98. Process.Lock;
  99. (*%E *)
  100. p := Source^.next;
  101. size := 0;
  102. WHILE p^.size <> EndMarker DO
  103. IF p^.size>size THEN size := p^.size END;
  104. p := p^.next;
  105. END;
  106. (*%T _mthread *)
  107. Process.Unlock;
  108. (*%E *)
  109. RETURN size;
  110. END FarHeapAvail;
  111. PROCEDURE FarHeapTotalAvail(Source: FarHeapRecPtr) : CARDINAL;
  112. (* returns the total block size available for allocation in paragraphs *)
  113. VAR
  114. size : CARDINAL;
  115. p : FarHeapRecPtr;
  116. BEGIN
  117. IF Source = MainHeap THEN
  118. RETURN 0FFFFH;
  119. END;
  120. (*%T _mthread *)
  121. Process.Lock;
  122. (*%E *)
  123. p := Source^.next;
  124. size := 0;
  125. WHILE p^.size <> EndMarker DO
  126. INC(size,p^.size);
  127. p := p^.next;
  128. END;
  129. (*%T _mthread *)
  130. Process.Unlock;
  131. (*%E *)
  132. RETURN size;
  133. END FarHeapTotalAvail;
  134. PROCEDURE FarHeapDeallocate(Source : FarHeapRecPtr; (* source heap *)
  135. VAR A: FarADDRESS;
  136. Size : CARDINAL ); (* size of block
  137. in paragraphs *)
  138. VAR
  139. target,prev,split : FarHeapRecPtr;
  140. tseg : CARDINAL;
  141. BEGIN
  142. IF Source = MainHeap THEN
  143. FarDeallocate(A,Size);
  144. RETURN;
  145. END;
  146. IF (CARDINAL(Seg(A^))=0)OR(CARDINAL(Ofs(A^))<>0) THEN
  147. Lib.RunTimeError(CoreSig._FatalErrorPos(), 91H, 'FarHeapDeallocate : Invalid Argument');
  148. END;
  149. (*%T _mthread *)
  150. Process.Lock;
  151. (*%E *)
  152. IF Size=0 THEN INC(Size) END ;
  153. target := A;
  154. prev := Source;
  155. tseg := Seg(target^);
  156. WHILE CARDINAL(Seg(prev^.next^)) < tseg DO
  157. prev := prev^.next;
  158. END;
  159. IF CARDINAL(Seg(prev^))+prev^.size = tseg THEN (* amalgamate with prev *)
  160. prev^.size := prev^.size + Size;
  161. target := prev;
  162. ELSIF CARDINAL(Seg(prev^))+prev^.size > tseg THEN (* Heap corrupt *)
  163. SYSTEM.EI;
  164. Lib.RunTimeError(CoreSig._FatalErrorPos(), 92H, 'FarHeapDeallocate : Heap Corrupt');
  165. ELSE
  166. (* link after prev *)
  167. target^.next := prev^.next;
  168. prev^.next := target;
  169. target^.size := Size;
  170. END;
  171. IF (target^.next^.size <> EndMarker)
  172. AND (CARDINAL(Seg(target^.next^)) = CARDINAL(Seg(target^))+target^.size) THEN
  173. (* amalgamate with next block *)
  174. target^.size := target^.size+target^.next^.size;
  175. target^.next := target^.next^.next;
  176. END;
  177. A := SYSTEM.FarNIL;
  178. (*%T _mthread *)
  179. Process.Unlock;
  180. (*%E *)
  181. END FarHeapDeallocate;
  182. PROCEDURE FarHeapChangeAlloc(Source : FarHeapRecPtr; (* source heap *)
  183. A : FarADDRESS; (* block to change *)
  184. OldSize, (* old size of block *)
  185. NewSize : CARDINAL) (* new size of block *)
  186. (* in paragraphs *)
  187. : BOOLEAN; (* if sucessful *)
  188. (* This procedure attempts to change the size of an allocated block
  189. It returns TRUE if succeeded (only expansion can fail)
  190. *)
  191. VAR
  192. target,prev,
  193. split : FarHeapRecPtr;
  194. tseg : CARDINAL;
  195. result : BOOLEAN;
  196. extendsize : CARDINAL;
  197. Res : FarADDRESS;
  198. BEGIN
  199. IF Source = MainHeap THEN
  200. RETURN FALSE;
  201. END;
  202. IF (CARDINAL(Seg(A^))=0)OR(CARDINAL(Ofs(A^))<>0) THEN
  203. Lib.RunTimeError(CoreSig._FatalErrorPos(), 93H, 'FarHeapChangeAlloc : Invalid Argument');
  204. END;
  205. IF OldSize = NewSize THEN RETURN TRUE END;
  206. IF OldSize > NewSize THEN
  207. target := [CARDINAL(Seg(A^))+NewSize:0];
  208. FarHeapDeallocate(Source,target,OldSize-NewSize);
  209. RETURN TRUE;
  210. END;
  211. extendsize := NewSize-OldSize;
  212. (*%T _mthread *)
  213. Process.Lock;
  214. (*%E *)
  215. target := A;
  216. prev := Source;
  217. tseg := Seg(target^);
  218. WHILE CARDINAL(Seg(prev^.next^)) < tseg DO
  219. prev := prev^.next;
  220. END;
  221. IF (prev^.next^.size <> EndMarker) AND
  222. (CARDINAL(Seg(prev^.next^)) = CARDINAL(Seg(target^))+OldSize) AND
  223. (extendsize <= prev^.next^.size) THEN
  224. IF (extendsize = prev^.next^.size) THEN
  225. prev^.next := prev^.next^.next
  226. ELSE
  227. split := [CARDINAL(Seg(target^))+NewSize:0];
  228. split^.next := prev^.next^.next;
  229. split^.size := prev^.next^.size - extendsize;
  230. prev^.next := split;
  231. END;
  232. result := TRUE;
  233. ELSE
  234. result := FALSE;
  235. END;
  236. (*%T _mthread *)
  237. Process.Unlock;
  238. (*%E *)
  239. RETURN result;
  240. END FarHeapChangeAlloc;
  241. PROCEDURE FarHeapChangeSize(Source : FarHeapRecPtr; (* source heap *)
  242. VAR A : FarADDRESS; (* block to change *)
  243. OldSize, (* old size of block *)
  244. NewSize : CARDINAL ); (* new size of block
  245. in paragraphs *)
  246. (*
  247. This procedure will change the size of an allocated block
  248. avoiding any copy of data if possible
  249. calls HeapChangeAlloc
  250. *)
  251. VAR
  252. na : FarADDRESS;
  253. BEGIN
  254. IF Source = MainHeap THEN
  255. Lib.RunTimeError(CoreSig._FatalErrorPos(), 94H, 'FarHeapChangeSize : Out Of Memory');
  256. RETURN;
  257. END;
  258. IF NOT FarHeapChangeAlloc ( Source, A, OldSize, NewSize ) THEN
  259. FarHeapAllocate(Source,na,NewSize);
  260. Lib.FarWordMove(A, na, OldSize*8);
  261. FarHeapDeallocate(Source,A,OldSize);
  262. A := na;
  263. END;
  264. END FarHeapChangeSize;
  265. PROCEDURE NearMakeHeap(Source: NearADDRESS; Size: CARDINAL): NearHeapRecPtr;
  266. (* ========== *)
  267. VAR Storage, FirstFree: NearHeapRecPtr;
  268. BEGIN
  269. Size := (Size DIV Align) * Align;
  270. IF Size < 10 THEN
  271. Lib.RunTimeError(CoreSig._FatalErrorPos(), 95H, 'NearMakeHeap: Size Too Small');
  272. END;
  273. Storage := NearHeapRecPtr(Source);
  274. Storage^.next := NearHeapRecPtr(CARDINAL(Source)+Align);
  275. Storage^.size :=4;
  276. FirstFree := Storage^.next;
  277. FirstFree^.size := Size - Align;
  278. FirstFree^.next := SYSTEM.NearNIL;
  279. RETURN Storage;
  280. END NearMakeHeap;
  281. PROCEDURE NearHeapAllocate(Source: NearHeapRecPtr; VAR A: NearADDRESS; Size: CARDINAL);
  282. (* ======== *)
  283. VAR Base, Free, New: NearHeapRecPtr;
  284. BEGIN
  285. IF Size = 0 THEN INC(Size) END;
  286. Size := (( (Size+Align-1) DIV Align) * Align) + Align;
  287. IF Size = 0 THEN
  288. Size:=MAX(CARDINAL);
  289. END;
  290. Base := Source;
  291. LOOP
  292. Free := Base^.next;
  293. IF Free = SYSTEM.NearNIL THEN
  294. IF Check THEN
  295. Lib.RunTimeError(CoreSig._FatalErrorPos(), 96H, 'NearHeapAllocate: Out Of Memory');
  296. ELSE
  297. A := SYSTEM.NearNIL;
  298. RETURN;
  299. END;
  300. ELSIF Free^.size >= Size THEN
  301. EXIT;
  302. END;
  303. Base := Free;
  304. END;
  305. IF Free^.size = Size THEN
  306. Base^.next := Free^.next;
  307. ELSE
  308. New := NearHeapRecPtr(CARDINAL(Free)+Size);
  309. Base^.next := New;
  310. New^.size := Free^.size - Size;
  311. New^.next := Free^.next;
  312. END;
  313. IF ClearOnAllocate THEN
  314. Lib.WordFill ( ADDRESS(CARDINAL(Free)+Align) , (Size-Align) DIV 2 , 0 );
  315. END;
  316. A := NearADDRESS(CARDINAL(Free)+Align);
  317. END NearHeapAllocate;
  318. PROCEDURE Merge(PrevRec, LowRec, HighRec, Source: NearHeapRecPtr);
  319. BEGIN
  320. IF (LowRec = SYSTEM.NearNIL) OR (HighRec = SYSTEM.NearNIL) THEN RETURN END;
  321. IF (LowRec = Source) THEN RETURN END;
  322. IF NearHeapRecPtr(CARDINAL(LowRec)+LowRec^.size) # HighRec THEN RETURN END;
  323. INC(LowRec^.size, HighRec^.size);
  324. LowRec^.next:=HighRec^.next;
  325. PrevRec^.next:=LowRec;
  326. RETURN;
  327. END Merge;
  328. PROCEDURE NearHeapDeallocate(Source: NearHeapRecPtr; VAR A: NearADDRESS; Size: CARDINAL );
  329. VAR
  330. Curr, Base, Free: NearHeapRecPtr;
  331. BEGIN
  332. Size := (( (Size+Align-1) DIV Align) * Align) + Align;
  333. Curr := NearHeapRecPtr(CARDINAL(A) - Align);
  334. A := SYSTEM.NearNIL;
  335. IF Curr = SYSTEM.NearNIL THEN
  336. Lib.RunTimeError(CoreSig._FatalErrorPos(), 97H, 'NearHeapDeallocate: Invalid Argument');
  337. END;
  338. Base:=Source;
  339. LOOP
  340. Free := Base^.next;
  341. IF (Free = SYSTEM.NearNIL) OR (CARDINAL(Curr) < CARDINAL(Free)) THEN EXIT; END;
  342. Base := Free;
  343. END;
  344. IF (CARDINAL(Base) + Base^.size = CARDINAL(Curr)) AND (Base # Source) THEN
  345. INC ( Base^.size , Size );
  346. Curr := Base;
  347. ELSE
  348. Base^.next := Curr;
  349. Curr^.next := Free;
  350. Curr^.size := Size;
  351. END;
  352. IF CARDINAL(Curr) + Curr^.size = CARDINAL(Free) THEN
  353. INC ( Curr^.size, Free^.size);
  354. Curr^.next := Free^.next;
  355. END;
  356. END NearHeapDeallocate;
  357. PROCEDURE NearHeapAvail(Source: NearHeapRecPtr): CARDINAL;
  358. VAR
  359. Curr: NearHeapRecPtr;
  360. Size: CARDINAL;
  361. BEGIN
  362. Curr := Source;
  363. Size := 0;
  364. WHILE Curr # SYSTEM.NearNIL DO
  365. IF Size < Curr^.size THEN
  366. Size := Curr^.size;
  367. END;
  368. Curr := Curr^.next;
  369. END;
  370. RETURN Size - Align;
  371. END NearHeapAvail;
  372. PROCEDURE NearHeapTotalAvail(Source: NearHeapRecPtr): CARDINAL;
  373. VAR
  374. Curr: NearHeapRecPtr;
  375. Size: CARDINAL;
  376. BEGIN
  377. Curr := Source^.next;
  378. Size := 0;
  379. WHILE Curr # SYSTEM.NearNIL DO
  380. INC ( Size , Curr^.size - Align);
  381. Curr := Curr^.next;
  382. END;
  383. RETURN Size;
  384. END NearHeapTotalAvail;
  385. PROCEDURE NearHeapChangeSize(Source: NearHeapRecPtr; VAR A: NearADDRESS;
  386. OldSize, NewSize : CARDINAL);
  387. VAR
  388. Curr, NextRec, PrevRec, NewRec: NearHeapRecPtr;
  389. SplitSize: CARDINAL;
  390. OldA: NearADDRESS;
  391. BEGIN
  392. NewSize := (( (NewSize+Align-1) DIV Align) * Align) + Align;
  393. OldSize := (( (OldSize+Align-1) DIV Align) * Align) + Align;
  394. IF OldSize = NewSize THEN RETURN END;
  395. Curr:=NearHeapRecPtr(CARDINAL(A)-Align);
  396. NextRec:=Source;
  397. PrevRec:=Source;
  398. LOOP
  399. IF NextRec = SYSTEM.NearNIL THEN EXIT END;
  400. IF CARDINAL(NextRec) > CARDINAL(Curr) THEN EXIT END;
  401. PrevRec:=NextRec;
  402. NextRec:=NextRec^.next;
  403. END;
  404. IF OldSize > NewSize THEN
  405. SplitSize:=OldSize-NewSize;
  406. Curr^.size:=NewSize;
  407. NewRec:=NearHeapRecPtr(CARDINAL(Curr)+NewSize);
  408. NewRec^.size:=SplitSize;
  409. NewRec^.next:=PrevRec^.next;
  410. PrevRec^.next:=NewRec;
  411. Merge(PrevRec, NewRec, NextRec, Source);
  412. RETURN ;
  413. END;
  414. IF NearHeapRecPtr(CARDINAL(Curr)+OldSize) = NextRec THEN (* Next Block is free *)
  415. Curr^.size := OldSize;
  416. Merge(PrevRec, Curr, NextRec, Source);
  417. IF OldSize = NewSize THEN
  418. PrevRec^.next := Curr^.next;
  419. RETURN;
  420. ELSE
  421. NewRec := NearHeapRecPtr(CARDINAL(Curr)+NewSize);
  422. NewRec^.size := Curr^.size-NewSize;
  423. NewRec^.next := Curr^.next;
  424. PrevRec^.next := NewRec;
  425. RETURN;
  426. END;
  427. END;
  428. OldA:=A;
  429. NearHeapDeallocate(Source, A, OldSize);
  430. NearHeapAllocate(Source, A, NewSize);
  431. Lib.WordMove(ADR(OldA), ADR(A), OldSize DIV 2);
  432. RETURN;
  433. END NearHeapChangeSize;
  434. PROCEDURE NearHeapChangeAlloc(Source: NearHeapRecPtr; A: NearADDRESS;
  435. OldSize, NewSize : CARDINAL): BOOLEAN;
  436. VAR
  437. Curr, NextRec, PrevRec, NewRec: NearHeapRecPtr;
  438. SplitSize: CARDINAL;
  439. BEGIN
  440. NewSize := (( (NewSize+Align-1) DIV Align) * Align) + Align;
  441. OldSize := (( (OldSize+Align-1) DIV Align) * Align) + Align;
  442. IF OldSize = NewSize THEN RETURN TRUE END;
  443. Curr:=NearHeapRecPtr(CARDINAL(A)-Align);
  444. PrevRec:=Source;
  445. NextRec:=Source;
  446. LOOP
  447. IF NextRec = SYSTEM.NearNIL THEN EXIT END;
  448. IF CARDINAL(NextRec) > CARDINAL(Curr) THEN EXIT END;
  449. PrevRec:=NextRec;
  450. NextRec:=NextRec^.next;
  451. END;
  452. IF OldSize > NewSize THEN
  453. SplitSize:=OldSize-NewSize;
  454. Curr^.size:=NewSize;
  455. NewRec:=NearHeapRecPtr(CARDINAL(Curr)+NewSize);
  456. NewRec^.size:=SplitSize;
  457. NewRec^.next:=PrevRec^.next;
  458. PrevRec^.next:=NewRec;
  459. Merge(PrevRec, NewRec, NextRec, Source);
  460. RETURN TRUE;
  461. END;
  462. IF NearHeapRecPtr(CARDINAL(Curr)+OldSize) = NextRec THEN (* Next Block is free *)
  463. Curr^.size := OldSize;
  464. Merge(PrevRec, Curr, NextRec, Source);
  465. IF OldSize = NewSize THEN
  466. PrevRec^.next := Curr^.next;
  467. ELSE
  468. NewRec := NearHeapRecPtr(CARDINAL(Curr)+NewSize);
  469. NewRec^.size := OldSize-NewSize;
  470. NewRec^.next := Curr^.next;
  471. PrevRec^.next := NewRec;
  472. END;
  473. RETURN TRUE;
  474. ELSE
  475. RETURN FALSE;
  476. END;
  477. END NearHeapChangeAlloc;
  478. TYPE
  479. HANDLEPtr = POINTER TO Windows.HANDLE;
  480. PROCEDURE NearDeallocate(VAR a: NearADDRESS; size: CARDINAL);
  481. BEGIN
  482. IF ORD(Windows.LocalFree(Windows.HANDLE(a))) # 0 THEN END;
  483. a:= NearADDRESS(NIL);
  484. END NearDeallocate;
  485. PROCEDURE NearAllocate(VAR a: NearADDRESS; size: CARDINAL);
  486. VAR
  487. mode: CARDINAL;
  488. h: Windows.HANDLE;
  489. BEGIN
  490. IF size = 0 THEN size := 2 END;
  491. mode := Windows.LMEM_FIXED;
  492. IF ClearOnAllocate THEN
  493. mode := mode + Windows.LMEM_ZEROINIT;
  494. END;
  495. h := Windows.LocalAlloc(mode, size);
  496. IF ORD(h) = 0 THEN
  497. Lib.RunTimeError(CoreSig._FatalErrorPos(), 98H, 'NearAllocate: Out Of Memory');
  498. END;
  499. a := NearADDRESS(h);
  500. END NearAllocate;
  501. PROCEDURE NearAvailable(size: CARDINAL) : BOOLEAN;
  502. BEGIN
  503. RETURN TRUE;
  504. END NearAvailable;
  505. PROCEDURE FarAllocate (VAR a: FarADDRESS; size: CARDINAL);
  506. BEGIN
  507. a := Windows.GlobalLock(Windows.GlobalAlloc(Windows.GMEM_MOVEABLE,LONGCARD(size)));
  508. END FarAllocate;
  509. PROCEDURE FarDeallocate(VAR a: FarADDRESS; size: CARDINAL);
  510. VAR h : Windows.HANDLE;
  511. BEGIN
  512. h := CARDINAL(Windows.GlobalHandle(Seg(a^)));
  513. Windows.GlobalUnlock(h);
  514. Windows.GlobalFree(h);
  515. a := FarNIL;
  516. END FarDeallocate;
  517. PROCEDURE FarAvailable(size: CARDINAL ): BOOLEAN;
  518. BEGIN
  519. RETURN TRUE;
  520. END FarAvailable;
  521. PROCEDURE SegAllocate(Size: CARDINAL): CARDINAL;
  522. VAR
  523. a : FarADDRESS;
  524. BEGIN
  525. FarAllocate(a,Size);
  526. RETURN Seg(a^);
  527. END SegAllocate;
  528. PROCEDURE SegDeallocate(Sel: CARDINAL; Size: CARDINAL);
  529. VAR a : FarADDRESS;
  530. BEGIN
  531. a := [Sel:0];
  532. FarDeallocate(a,Size);
  533. END SegDeallocate;
  534. BEGIN
  535. MainHeap:=[0:0FFFFH];
  536. END Storage.
  537.