SHTHEAP.MOD 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  1. (* Release 3.10 *)
  2. (*-------------------------------------------------------------------------*
  3. * *
  4. * SHTHEAP.MOD - Short heaps *
  5. * *
  6. * COPYRIGHT (C) 1987..1992 Clarion Software Corporation. *
  7. * All Rights Reserved *
  8. * *
  9. *--------------------------------------------------------------------------*)
  10. (*# call(o_a_copy => on,
  11. o_a_size => on) *)
  12. (*%F _fdata *)
  13. (*# call(seg_name => null) *)
  14. (*# data(seg_name => null) *)
  15. (*%E *)
  16. (*# module(implementation=>off) *)
  17. (*# check(stack=>off,
  18. index=>off,
  19. range=>off,
  20. overflow=>off,
  21. nil_ptr=>off) *)
  22. IMPLEMENTATION MODULE ShtHeap ;
  23. IMPORT Lib, SYSTEM, CoreSig;
  24. TYPE Offset = CARDINAL;
  25. Block = RECORD
  26. Siz: Size;
  27. Nxt: Pointer;
  28. END;
  29. PROCEDURE Initialize ( H: Segment; Z: Size );
  30. VAR B,F: POINTER H TO Block;
  31. BEGIN
  32. Z := (Z DIV Align) * Align;
  33. IF Z < 10 THEN
  34. Lib.RunTimeError(CoreSig._FatalErrorPos(), 9AH, 'ShtHeap.Initialize : Size Too Small');
  35. END;
  36. B := Pointer ( 0 );
  37. F := Pointer ( Align );
  38. B^.Siz := Z;
  39. B^.Nxt := F;
  40. F^.Siz := Z - Align;
  41. F^.Nxt := Nil;
  42. END Initialize;
  43. PROCEDURE Increase ( H: Segment; Z: Size );
  44. VAR B,L,I: POINTER H TO Block;
  45. BEGIN
  46. IF Debug THEN
  47. Test ( H );
  48. END;
  49. Z := (Z DIV Align) * Align;
  50. B := Pointer ( 0 );
  51. IF Z > MAX(Size) - B^.Siz THEN
  52. Lib.RunTimeError(CoreSig._FatalErrorPos(), 9BH, 'ShtHeap.Increase : Size Too Large');
  53. END;
  54. I := B;
  55. REPEAT
  56. L := I;
  57. I := I^.Nxt;
  58. UNTIL I = Nil;
  59. IF (L # B) AND (Offset ( L ) + L^.Siz = B^.Siz) THEN
  60. INC ( L^.Siz , Z );
  61. ELSE
  62. I := Pointer ( B^.Siz );
  63. L^.Nxt := I;
  64. I^.Siz := Z;
  65. I^.Nxt := Nil;
  66. END;
  67. INC ( B^.Siz , Z );
  68. END Increase;
  69. PROCEDURE Allocate ( H: Segment; VAR P: Pointer; Z: Size );
  70. VAR B,F,G,N: POINTER H TO Block;
  71. BEGIN
  72. IF Debug THEN
  73. Test ( H );
  74. END;
  75. Z := ( (Z+Align-1) DIV Align) * Align;
  76. IF Z = 0 THEN
  77. Lib.RunTimeError(CoreSig._FatalErrorPos(), 9CH, 'ShtHeap.Allocate : Size Too Small');
  78. END;
  79. B := Pointer ( 0 );
  80. G := B;
  81. LOOP
  82. F := G^.Nxt;
  83. IF F = Nil THEN
  84. IF Check THEN
  85. Lib.RunTimeError(CoreSig._FatalErrorPos(), 9DH, 'ShtHeap.Allocate : Out Of Memory');
  86. ELSE
  87. P := Nil;
  88. RETURN;
  89. END;
  90. ELSIF F^.Siz >= Z THEN
  91. EXIT;
  92. END;
  93. G := F;
  94. END;
  95. IF F^.Siz = Z THEN
  96. G^.Nxt := F^.Nxt;
  97. ELSE
  98. N := Pointer ( Offset ( F ) + Z );
  99. G^.Nxt := N;
  100. N^.Siz := F^.Siz - Z;
  101. N^.Nxt := F^.Nxt;
  102. END;
  103. IF Clear THEN
  104. Lib.WordFill ( ADR(F^) , Z DIV 2 , 0 );
  105. END;
  106. P := F;
  107. END Allocate;
  108. PROCEDURE Free ( H: Segment; VAR P: Pointer; Z: Size );
  109. VAR B,F,G,Q: POINTER H TO Block;
  110. BEGIN
  111. IF Debug THEN
  112. Test ( H );
  113. END;
  114. Z := ( (Z+Align-1) DIV Align) * Align;
  115. Q := P;
  116. P := Nil;
  117. IF Q = Nil THEN
  118. Lib.RunTimeError(CoreSig._FatalErrorPos(), 9EH, 'ShtHeap.Free : Invalid Argument');
  119. END;
  120. B := Pointer ( 0 );
  121. G := B;
  122. LOOP
  123. F := G^.Nxt;
  124. IF (F = Nil) OR (Offset ( Q ) < Offset ( F )) THEN EXIT; END;
  125. G := F;
  126. END;
  127. IF Offset ( G ) + G^.Siz = Offset ( Q ) THEN
  128. INC ( G^.Siz , Z );
  129. Q := G;
  130. ELSE
  131. G^.Nxt := Q;
  132. Q^.Nxt := F;
  133. Q^.Siz := Z;
  134. END;
  135. IF Offset ( Q ) + Q^.Siz = Offset ( F ) THEN
  136. INC ( Q^.Siz , F^.Siz );
  137. Q^.Nxt := F^.Nxt;
  138. END;
  139. END Free;
  140. PROCEDURE Largest ( H: Segment ): Size;
  141. VAR P: POINTER H TO Block;
  142. Z: Size;
  143. BEGIN
  144. IF Debug THEN
  145. Test ( H );
  146. END;
  147. P := Pointer ( 0 );
  148. P := P^.Nxt;
  149. Z := 0;
  150. WHILE P # Nil DO
  151. IF Z < P^.Siz THEN
  152. Z := P^.Siz;
  153. END;
  154. P := P^.Nxt;
  155. END;
  156. RETURN Z;
  157. END Largest;
  158. PROCEDURE Total ( H: Segment ): Size;
  159. VAR P: POINTER H TO Block;
  160. Z: Size;
  161. BEGIN
  162. IF Debug THEN
  163. Test ( H );
  164. END;
  165. P := Pointer ( 0 );
  166. P := P^.Nxt;
  167. Z := 0;
  168. WHILE P # Nil DO
  169. INC ( Z , P^.Siz );
  170. P := P^.Nxt;
  171. END;
  172. RETURN Z;
  173. END Total;
  174. PROCEDURE Test ( H: Segment );
  175. VAR B,F,G: POINTER H TO Block;
  176. BEGIN
  177. B := Pointer ( 0 );
  178. IF B^.Siz MOD Align # 0 THEN
  179. Lib.RunTimeError(CoreSig._FatalErrorPos(), 9FH, 'ShtHeap.Test : Non-aligned heap size.');
  180. END;
  181. G := B;
  182. LOOP
  183. F := G^.Nxt;
  184. IF F = Nil THEN EXIT; END;
  185. IF Offset ( F ) >= B^.Siz THEN
  186. Lib.RunTimeError(CoreSig._FatalErrorPos(), 9FH, "ShtHeap.Test: Free block out of range" );
  187. ELSIF Offset ( F ) MOD Align # 0 THEN
  188. Lib.RunTimeError(CoreSig._FatalErrorPos(), 9FH, "ShtHeap.Test: Non-aligned free block" );
  189. ELSIF F^.Siz MOD Align # 0 THEN
  190. Lib.RunTimeError(CoreSig._FatalErrorPos(), 9FH, "ShtHeap.Test: Non-aligned free block size" );
  191. ELSIF Offset ( F ) < Offset ( G ) THEN
  192. Lib.RunTimeError(CoreSig._FatalErrorPos(), 9FH, "ShtHeap.Test: Unordered free list" );
  193. ELSIF (G # B) AND (Offset ( G ) + G^.Siz = Offset ( F )) THEN
  194. Lib.RunTimeError(CoreSig._FatalErrorPos(), 9FH, "ShtHeap.Test: Unjoined free list" );
  195. ELSIF (G # B) AND (Offset ( G ) + G^.Siz > Offset ( F )) THEN
  196. Lib.RunTimeError(CoreSig._FatalErrorPos(), 9FH, "ShtHeap.Test: Overlapping free list" );
  197. END;
  198. G := F;
  199. END;
  200. END Test;
  201. BEGIN
  202. IF SIZE ( Block ) > Align THEN
  203. Lib.FatalError ( "ShtHeap: Alignment too small" );
  204. END;
  205. Clear := FALSE;
  206. Check := TRUE;
  207. Debug := FALSE;
  208. END ShtHeap.
  209.