nhlhcore.asm
上传用户:xiaoan1112
上传日期:2013-04-11
资源大小:19621k
文件大小:41k
源码类别:

操作系统开发

开发平台:

Visual C++

  1. TITLE NHLHCORE - Core Local Heap utilities
  2. ;***
  3. ;NHLHCORE - Core Local Heap utilities
  4. ;
  5. ; Copyright <C> 1987, Microsoft Corporation
  6. ;
  7. ;Purpose:
  8. ; This module contains the core local heap utilities that are required to
  9. ; support /O programs which use string space and simple OPEN statements. Field
  10. ; manipulations and additional CHAIN support is elsewhere.
  11. ;
  12. ;******************************************************************************
  13. ;
  14. ; Near Heap Support
  15. ;
  16. ; The near heap support code deals with three pieces:
  17. ;
  18. ; Local Heap - Contains FDBs & Dynamic (small) arrays & QBI tables
  19. ; String Space - Strings and FIELDed string entries
  20. ; Variable Heap - Interpeter Only, value tables
  21. ;
  22. ; In memory, the heaps, associated variables and stack are layed out as
  23. ; follows:
  24. ;
  25. ;    High Memory (DGROUP)
  26. ;
  27. ; +--+--+--+--+--+--+--+--+
  28. ; b$HEAP_FIRST --> | | odd: last useable physical
  29. ; +--+--+--+--+--+--+--+--+ byte of Heap
  30. ; b$NH_last --> | | even: last useable physical
  31. ;     word of Heap
  32. ; Local Heap
  33. ;  
  34. ; | |
  35. ; +--+--+--+--+--+--+--+--+
  36. ; b$HEAP_END --> |    LH_END Constant | odd: ?
  37. ; +--+--+--+--+--+--+--+--+
  38. ; | |
  39. ; + +
  40. ; b$STRING_END --> | | even: word containing 0xFFFF
  41. ;  
  42. ; String Space
  43. ; b$NH_First -   
  44. ; b$STRING_FIRST ----> | | first useable byte/word
  45. ; +--+--+--+--+--+--+--+--+ 
  46. ; b$HEAP_FIRST_SWAP --> | |  
  47. ;      
  48. ;       Variable Heap      Interpeter Only
  49. ;      /
  50. ; b$HEAP_END_SWAP   --> | |  /
  51. ; +--+--+--+--+--+--+--+--+ /
  52. ; | |
  53. ; + +
  54. ; __atopsp --> | | last useable word of stack
  55. ;  
  56. ;   Stack
  57. ;  
  58. ; b$pend --> | | first useable word of stack
  59. ; +--+--+--+--+--+--+--+--+
  60. ;
  61. ;==============================================================================
  62. ;
  63. ;
  64. ; Heap Entry:
  65. ;
  66. ; +--+--+--+--+--+--+--+--+ High memory
  67. ; Pointer to entry --> |    Entry Type Byte |
  68. ; +--+--+--+--+--+--+--+--+
  69. ; | File #, if applicable |
  70. ; +--+--+--+--+--+--+--+--+
  71. ; | |
  72. ; +   Total Entry Size +
  73. ; | |
  74. ; +--+--+--+--+--+--+--+--+
  75. ; |     Back Pointer |
  76. ; + (Pointer to +
  77. ; |  owner pointer) |
  78. ; +--+--+--+--+--+--+--+--+
  79. ; | (offset part of sd |
  80. ; +  for fielded string +
  81. ; |  if applicable) |
  82. ; +--+--+--+--+--+--+--+--+
  83. ; | (length part of sd |
  84. ; +  for fielded string +
  85. ; |  if applicable) |
  86. ; +--+--+--+--+--+--+--+--+
  87. ; | |
  88. ;  
  89. ;  Data
  90. ;  
  91. ; Start of Data --> | |
  92. ; +--+--+--+--+--+--+--+--+
  93. ; | |
  94. ; +   Total Entry Size +
  95. ; |  (Same as in header) |
  96. ; +--+--+--+--+--+--+--+--+ Low memory
  97. ;
  98. ; The pointer to an entry normally points to the type byte in the header; since
  99. ; length of the entry (hdr + data + trailer length word) is kept at the start
  100. ; and the end of the block, it is easy to access; subtract that length from the
  101. ; current entry pointer, and it will be pointing to the same place in the next
  102. ; hdr - - - yes, since the heap grows down, subtracting from the pointer moves
  103. ; you "forward" in the heap. Heap entries can be of any even-byte size; headers
  104. ; are 6 bytes in length, except for fdb's, which have 10-byte headers.
  105. ;
  106. ;==============================================================================
  107. ;
  108. ; Internal structure of (simple) fielded strings.
  109. ;
  110. ; FDB:
  111. ;
  112. ;    /--+-----------------------+--/ /--+---------------+--/ /--+-------+
  113. ; |   Field Buffer | |  String Desc | |LH_FILE|
  114. ;    /--+-----------------------+--/ /--+------------+--+--/ /--+-------+
  115. ;        ^   ^    ^       ^      |
  116. ;        |   |    |       |      |
  117. ; Individual   |   |    +-----------+      |      |
  118. ; Static       |   |        |      |      |
  119. ; String       |   +-------+        |      |      |
  120. ; Descriptors: |    |        |      |      |
  121. ;        |    |        |      |      |
  122. ;   +-------+   +-------+   +-------+   |      |
  123. ;   |  SD   |   |   SD  |   |  SD   |   |      |
  124. ;   +-------+   +-------+   +-------+   |      |
  125. ; ^     ^ ^     |      |
  126. ; Fielded |     | |     |      |
  127. ; String +----+     ++      +--+     |      |
  128. ; BackPointer      |      |      |       |      |
  129. ; String:      |      |      |       |      |
  130. ;      |      |      |       |      |
  131. ;     +---------------------------------+      |
  132. ;     |      |      |      |      |
  133. ;     |   +----------------------------------+
  134. ;     |  /  |      |      |
  135. ; +---+---+----+--+----+--+----+--+--/
  136. ; | BkPtr | SD Ptr| SD Ptr| SD Ptr|
  137. ; +-------+-------+-------+-------+--/
  138. ;
  139. ; In summary, the FDB contains a string descriptor which references a string
  140. ; (the fielded string backpointer string) containing pointers to several string
  141. ; descriptors. These string descriptors (static, in this example) reference
  142. ; locations in the FIELD buffer in the FDB, and define the position and length
  143. ; of the individual FIELDs.
  144. ;
  145. ; The backpointer string can grow as additional FIELD statements are executed,
  146. ; and can shrink at CHAIN time. Since it is a string, it is also subject to
  147. ; movement as string-space compaction occurs. The compaction code must be
  148. ; sensitive to the pointers involved in such movement.
  149. ;
  150. ; When the fielded strings are defined in  a static string array, operation is
  151. ; essentially the same as individual static strings. The static SD's do not
  152. ; move, and dereferencing performed by any calling code looks exactly like
  153. ; static individual SD's.
  154. ;
  155. ;
  156. ; Internal structure of fielded strings in dynamic arrays.
  157. ;
  158. ; FDB:
  159. ;
  160. ;    /--+-----------------------+--/ /--+---------------+--/ /--+-------+
  161. ; |   Field Buffer | |  String Desc | |LH_FILE|
  162. ;    /--+-----------------------+--/ /--+------------+--+--/ /--+-------+
  163. ;        ^   ^    ^       ^      |
  164. ;        |   |    |       |      +------------------+
  165. ; Array of     |   |    +---+       |  |
  166. ; String       |   |        |       +---------------------+ |
  167. ; Descriptors: |   +---+       |     | |
  168. ;        |       |       |     | |
  169. ; +------++------++------++--/ /--+-------+--/ /--+-------+   | |
  170. ; |  SD |   SD |  SD | | BkPtr | |LH_ARRA|   | |
  171. ; +-------+-------+-------+--/ /--+-----+-+--/ /--+-------+   | |
  172. ;        ^       ^       ^       |      | |
  173. ; Fielded      |       |       |       |      | |
  174. ; String       +-----+ +-----+ +-----+       +----+     | |
  175. ; BackPointer  ^     |      |      |    |     | |
  176. ; String:      +-----|-------|-------|----------+  |     | |
  177. ;      |      |      | |  |     | |
  178. ;     +-------------------------------------------------------+ |
  179. ;     |      |      |      | |  | |
  180. ;     |   +-----------------------------------------------------+
  181. ;     |  /  |      |      | |  |
  182. ; +---+---+----+--+----+--+----+--+--/ |  |
  183. ; | BkPtr | SD Ptr| SD Ptr| SD Ptr| |  |
  184. ; +-------+-------+-------+-------+--/ |  |
  185. ; |  |
  186. ; String  +------------------------------+  |
  187. ; Array   |    |
  188. ; Descriptor:  |     +---------------------------+
  189. ;  |    /
  190. ; ++------+--/
  191. ; |DatPtr |
  192. ; +-------+--/
  193. ;
  194. ;
  195. ; The added complication of dynamic fielded string arrays is that the string
  196. ; descriptors live in the local heap, and hence can move, in addition to the
  197. ; backpoint string, which lives in string space and can also move. Both LH and
  198. ; SS code must update pointers appropriately.
  199. ;
  200. ;==============================================================================
  201. INCLUDE switch.inc
  202. INCLUDE baslibma.inc
  203. INCLUDE files.inc
  204. INCLUDE rmacros.inc
  205. USESEG _DATA
  206. USESEG _BSS
  207. USESEG NH_TEXT
  208. INCLUDE seg.inc
  209. INCLUDE nhutil.inc ;for heap definitions
  210. INCLUDE idmac.inc
  211. INCLUDE array.inc ;for array definitions
  212. sBegin _BSS
  213. externW b$STRING_END ;defined in NHSTUTIL.ASM
  214. externW b$STRING_FREE ; defined in NHSTUTIL.ASM
  215. externW b$NH_first ;defined in NHINIT.ASM
  216. externW b$PTRFIL ;defined in GLOBAL.INC
  217. ;NOTE: Variable Heap support code requires next 4 data items be contiguous [23]
  218. globalW b$HEAP_FIRST,,1  ;heap start pointer
  219. globalW b$HEAP_FREE,,1
  220. globalW b$HEAP_END,,1
  221. globalW b$P_HEAP_GROW,,1
  222. ;NOTE: Variable Heap support code requires next 4 data items be contiguous [23]
  223. globalW b$HEAP_FIRST_SWAP,,1  
  224. globalW b$HEAP_FREE_SWAP,,1  
  225. globalW b$HEAP_END_SWAP,,1  
  226. staticW P_HEAP_GROW_SWAP,,1  
  227. globalW b$fVarHeapActive,,1  ; non-0 when variable heap
  228.  ; is active
  229. sEnd _BSS
  230. sBegin _DATA
  231. globalW b$pFHRaiseBottom,Near_Ret,1  ;vector for B$FHRaiseBottom
  232. globalB b$Clearing,0,1 ; CLEAR statement in process flag
  233. sEnd _DATA
  234. externFP B$ULDataRelease ;releases ul Data images
  235. externFP CompressHelp
  236. sBegin NH_TEXT
  237. ASSUMES CS,NH_TEXT
  238. PUBLIC B$LHNXTFIL ; find next file entry in heap
  239. PUBLIC B$LHADJ ;adjust heap entry
  240. PUBLIC B$LHDALC ;deallocate heap entry
  241. PUBLIC B$LHFLDDESCADJ ; delete/adjust descriptor in backpointer string
  242. PUBLIC B$LHDALCALLFLD ; deallocate all fielded strings from heap entry
  243. PUBLIC B$LHSetFree ;set free heap entry pointer
  244. PUBLIC B$LH_ALC_FREE ;[ln]
  245. PUBLIC B$LH_PTR_FROM_DATA 
  246. PUBLIC B$LH_CPCT
  247. PUBLIC B$LH_FROM_SS ;[ln]
  248. PUBLIC B$LH_PTR_CHECK ;[ln] check entry at [SI] for consistency
  249. PUBLIC B$LH_SCAN ;[ln]
  250. PUBLIC B$NHINIT ;initialize dynamic space
  251. externNP B$LH_I_ADJ ;[ln] adjust backptrs to any owners in this entry
  252. externNP B$VAR_ALC_GROW ;[ln]
  253. externNP B$ERR_SSC  
  254. externNP B$STCPCT
  255. externNP B$STADJ
  256. externNP B$STINIT
  257. externNP B$STSetFree
  258. externNP B$SSClean ; clean string space
  259. ASSERT_NOT_VARHEAP MACRO SEG ;
  260. ENDM ;
  261. PAGE
  262. ;***
  263. ; LH_ALC_GROW - Grow local heap to support allocation of a block of given size
  264. ; Purpose:
  265. ; Added with revision [23].
  266. ;
  267. ; Inputs:
  268. ; ES = DS
  269. ; BX = total size of local heap space to be allocated
  270. ; DL = type of heap entry to allocate.
  271. ; CL = if DL=LH_FILE, file number
  272. ; CX = if DL anything else, ptr to owner (where backptr should point to)
  273. ; Outputs:
  274. ; Carry Clear if allocation accomplished successfully
  275. ; Modifies:
  276. ; SI
  277. ; Exceptions:
  278. ;
  279. ;****
  280. DbPub LH_ALC_GROW
  281. LH_ALC_GROW:
  282. ; Step 3 - Get free string entry to heap space, test free entry.
  283. CALL B$LH_FROM_SS ;[ln] get free string from string space
  284. CALL B$LH_ALC_FREE ;test free entry for room
  285. JNC LH_ALC_GROW_DONE; allocated - jump to return to string
  286. ; Step 4 - Perform string compaction, get free string, test free entry.
  287. CALL B$STCPCT ;perform the string compaction
  288. CALL B$LH_FROM_SS ;[ln] get free string from string space
  289. CALL B$LH_ALC_FREE ;test free entry for room
  290. JNC LH_ALC_GROW_DONE; allocated - jump to return to string
  291. ;
  292. ; Step 5 - Kick FH out of DS if possible
  293. ;
  294. CALL [b$pFHRaiseBottom] ;[46]
  295. CALL B$LH_FROM_SS ;[ln] get free string from string space
  296. CALL B$LH_ALC_FREE ; test free entry for room
  297. JNC LH_ALC_GROW_DONE;allocated jump to return string
  298. ;
  299. ; Step 6 - Kick UL data images out of FH and raise the bottom
  300. PUSH AX ;preserve AX-DX across call to
  301. PUSH BX ;B$ULDataRelease, as the far
  302. PUSH CX ;call dispatcher to the quicklibrary
  303. PUSH DX ;can honk on these registers.
  304. CALL B$ULDataRelease ;free UL data images if allocated
  305. POP DX
  306. POP CX
  307. POP BX
  308. POP AX ;recover regs
  309. CALL [b$pFHRaiseBottom] ;give FH's free space to NH
  310. CALL B$LH_FROM_SS ;[ln]get free string from string space
  311. CALL B$LH_ALC_FREE ;test free entry for room
  312. JNC LH_ALC_GROW_DONE;allocated jump to return string
  313. ;
  314. ; Step 7 - Kick Help out of FH and raise the bottom
  315. PUSH AX ;preserve AX-DX across call to
  316. PUSH BX ;CompressHelp
  317. PUSH CX
  318. PUSH DX
  319. CALL CompressHelp ;Free the help system
  320. POP DX
  321. POP CX
  322. POP BX
  323. POP AX ;recover regs
  324. CALL [b$pFHRaiseBottom] ;give FH's free space to NH
  325. CALL B$LH_FROM_SS ;get free string from string space
  326. CALL B$LH_ALC_FREE ;test free entry for room
  327. Near_Ret: ;Near Return for vector
  328. LH_ALC_GROW_DONE:
  329. RET
  330. ;***
  331. ; B$LH_FROM_SS - get local heap space from string space
  332. ; Purpose:
  333. ; Determine if a free entry exists at the end of
  334. ; string space.  If so, change the string and heap
  335. ; space pointers so that it is now part of the local
  336. ; heap space.
  337. ;
  338. ; Mostly rewritten with revision [53].
  339. ;
  340. ; Strategy (order of attempts swapped with revision [64]):
  341. ; (1) If the last entry in the LH is a free entry, tack the free
  342. ; string bytes onto that entry and move b$HEAP_END past it.
  343. ;
  344. ; (2) If the last entry in the LH is NOT a free entry and the free
  345. ; string is large enough to create a heap entry (LH_STD_HDR_LEN
  346. ; bytes + 2 bytes for back length), then create a new LH entry
  347. ; with the free space.
  348. ;
  349. ; If neither (1) or (2) is possible, then we can't give any of
  350. ; the free string to the LH, just exit.
  351. ;
  352. ; Inputs:
  353. ; None.
  354. ; Outputs:
  355. ; [b$HEAP_FREE] = pointer to new (or enlarged) free heap entry.
  356. ; Modifies:
  357. ; None.
  358. ; Exceptions:
  359. ; None.
  360. ;****
  361. B$LH_FROM_SS:
  362. ASSERT_NOT_VARHEAP NH_TEXT
  363. PUSH AX ;save registers...
  364. PUSH SI
  365. PUSH DI
  366. CALL B$STSetFree ;SI points to trailing free string
  367. MOV AX,[b$STRING_END] ;get end pointer in AX
  368. SUB AX,SI ;compute size of free string
  369. JZ LH_SS_RETURN ;if no free bytes, exit quickly
  370. ; Size of free string (including header) is in AX.
  371. ; Pointer to free string header is in SI.
  372. DbAssertTst AX,Z,1,NH_TEXT,<Free string size odd in B$LH_FROM_SS>
  373. ; (1) If the last entry in the LH is free, tack the new empty space
  374. ;     on to it.
  375. MOV DI,[b$HEAP_END]  ;[DI] = heap END entry
  376. CMP DI,[B$HEAP_FIRST] ; is END the only entry?
  377. JE LH_SS_TRY_2 ; yes, go create a free entry
  378. ADD DI,[DI+1] ;[DI] = last entry before END
  379. CMP [DI].LHTYPE,LOW LH_FREE ;is entry unallocated?
  380. JNE LH_SS_TRY_2 ;no, go try next option
  381. ADD AX,[DI].LHLEN ;compute new length
  382. JMP SHORT LH_SS_FINISH_UP ; finish updating pointers and exit
  383. ; (2) If there are enough free bytes to create a new free entry at the
  384. ;     end of the LH, do that.
  385. LH_SS_TRY_2:
  386. CMP AX,LH_STD_HDR_LEN+2 ;enough free space?
  387. JB LH_SS_RETURN ;if not, we can't do anything
  388. ; Create the new heap entry from the empty space.
  389. MOV DI,SI ;[DI] = what will be string END entry
  390. ADD DI,LH_STD_HDR_LEN+1 ;[DI] = what will be heap END entry
  391. ADD DI,AX ;[DI] = new entry being created
  392. LH_SS_FINISH_UP:
  393. ; When we get here:
  394. ; SI points to new string space end location
  395. ; DI points to new (or enlarged) free heap entry
  396. ; AX = size of new (or enlarged) free heap entry
  397. ; Define the new string space end entry and its pointer.
  398. MOV [SI],0FFFFH ;set string end entry
  399. MOV [b$STRING_END],SI ;set string end pointer
  400. MOV [b$STRING_FREE],SI ;set free string pointer
  401. ; Define the new heap END entry and its pointer.
  402. ADD SI,LH_STD_HDR_LEN+1 ;point to new END entry
  403. MOV [SI].LHTYPE,LOW LH_END ;define the entry type
  404. MOV [b$HEAP_END],SI  ;define the heap end pointer
  405. ; Update header for new or enlarged free heap entry and set
  406. ; b$HEAP_FREE to point to it.
  407. MOV [DI].LHTYPE,LOW LH_FREE ;set heap entry type
  408. MOV [DI].LHLEN,AX ;set free heap entry length
  409. MOV [SI+1],AX ;set free heap entry backlength
  410. MOV [b$HEAP_FREE],DI ;set heap free entry pointer
  411. LH_SS_RETURN:
  412. POP DI ;restore registers...
  413. POP SI
  414. POP AX
  415. RET ;return with new heap free entry
  416. ;***
  417. ; B$LH_SCAN -Scan the entire local heap area for an entry of the
  418. ;    requested amount of storage.  Adjacent unallocated
  419. ;    entries are combined before tested for allocation.
  420. ;
  421. ; Inputs:  BX - amount of heap storage to allocate.
  422. ; DL - type of heap entry to allocate.
  423. ; CL - if DL=LH_FILE, file number
  424. ; CX - if DL=LH_ARRAY, array descriptor offset
  425. ; [b$HEAP_FIRST] - pointer to first entry to test
  426. ;
  427. ; Outputs: CF=0 - allocation was successful.
  428. ;      SI - pointer to data in allocated entry.
  429. ; CF=1 - allocation failed.
  430. ;
  431. ; Start the scan with the entry pointed by [b$HEAP_FIRST].
  432. ;****
  433. B$LH_SCAN:
  434. MOV SI,[b$HEAP_FIRST] ;starting point of scan
  435. ; No pending unallocated entries.  If END entry, then failed.
  436. ; If FREE entry, then jump to try to combine subsequent ones.
  437. LH_SCAN_NEXT:
  438. CMP [SI].LHTYPE,LOW LH_END ;test if last local heap entry
  439. JE LH_SCAN_FAIL ;if so, then allocation failed
  440. CMP [SI].LHTYPE,LOW LH_FREE ;test if entry is unallocated
  441. JE LH_SCAN_FREE ;if so, jump to scan for next free entries
  442. SUB SI,[SI].LHLEN ;move pointer to the next entry
  443. JMP SHORT LH_SCAN_NEXT ;and try again
  444. ; Pending unallocated entry.  Test the next entry.  If END, try
  445. ; a final allocation attempt.  If allocated, attempt allocation
  446. ; and continue scan if it fails. If FREE, combine the two entries
  447. ; and loop back. Keep size of free entry in AX until allocation.
  448. LH_SCAN_FREE:
  449. MOV AX,[SI].LHLEN ;get size of first free block
  450. LH_SCAN_NEXT_FREE:
  451. MOV DI,SI ;get copy of present scan pointer
  452. SUB DI,AX ;now points to following entry
  453. CMP [DI].LHTYPE,LOW LH_END ;test if next entry is END
  454. JE LH_SCAN_TRY ;if so, try a final allocation
  455. CMP [DI].LHTYPE,LOW LH_FREE ;test if next entry is FREE
  456. JNE LH_SCAN_TRY ;if not, try allocation, but continue
  457. ADD AX,[DI].LHLEN ;add for length of both FREE entries
  458. JMP SHORT LH_SCAN_NEXT_FREE ;and loop to try again
  459. ; Try to allocate from the entry at [SI].  If failure, point
  460. ; past the allocated entry at [DI] and continue scan if not at
  461. ; heap end.  If at heap end, return with failure.
  462. LH_SCAN_TRY:
  463. MOV [SI].LHLEN,AX ;set the new length of the combined block
  464. SUB SI,AX ;point to next block (one after backlength)
  465. MOV [SI+1],AX ;set the backlength
  466. ADD SI,AX ;return pointer to start of combined block
  467. CMP AX,BX ;test entry against allocation needed
  468. JAE LH_ALC ;if enough room, finish allocation
  469. CMP [DI].LHTYPE,LOW LH_END ;test if at end of heap
  470. JE LH_SCAN_FAIL ;if so, then just fail
  471. SUB DI,[DI].LHLEN ;point to entry after allocated one
  472. MOV SI,DI ;move pointer to continue scan
  473. JMP SHORT LH_SCAN_NEXT ;and jump to continue it
  474. ; Allocate not possible, return with carry set for failure.
  475. LH_SCAN_FAIL:
  476. MOV [b$HEAP_FREE],SI ;set free entry to last unallocated one
  477. STC ;carry set for failure
  478. RET ;and return to caller
  479. ; B$LH_ALC_FREE - test if free heap entry can allocate the
  480. ; requested amount of storage
  481. ; Inputs:  BX - amount of heap storage to allocate.
  482. ; DL - type of heap entry to allocate.
  483. ; CL - if DL=LH_FILE, file number
  484. ; CX - if DL=LH_ARRAY, array descriptor offset
  485. ; [b$HEAP_FREE] - pointer to entry to test
  486. ; Outputs: CF=0 - allocation was successful.
  487. ;      SI - pointer to data in allocated entry.
  488. ; CF=1 - allocation failed.
  489. ; Test if free local heap entry is unallocated and large enough.
  490. ; If so, then allocate it, otherwise fail.
  491. B$LH_ALC_FREE:
  492. MOV SI,[b$HEAP_FREE] ;point to free local heap entry
  493. CMP [SI].LHTYPE,LOW LH_FREE ;test if free entry is unallocated
  494. JNE LH_ALC_FAIL ;if not free, then jump to fail
  495. MOV AX,[SI].LHLEN ;get length of the entry
  496. CMP AX,BX ;test if entry is large enough
  497. JAE LH_ALC ;if so, then jump to allocate
  498. LH_ALC_FAIL:
  499. STC ;set carry to note failure
  500. RET ;return to caller
  501. ; There wasn't enough room to split entry and allocate a new FREE
  502. ; entry. Allocate the whole entry instead of splitting it.
  503. LH_ALC_ALL:
  504. ADD BX,AX ;change requested block size to whole entry
  505. JMP SHORT LH_ALC_EXACT ;allocate whole block
  506. ; The entry at [SI] can be allocated.  If the entry is larger than
  507. ; the size needed, split it into two entries with the higher one
  508. ; used in the allocation.
  509. LH_ALC:
  510. JE LH_ALC_EXACT ;if exact allocation, then no split needed
  511. SUB AX,BX ;size of remainder block
  512. CMP AX,LH_STD_HDR_LEN ;is there enough room for new header?
  513. JB LH_ALC_ALL ;allocate whole entry if not enough room
  514. SUB SI,BX ;point to header of new remainder entry
  515. MOV [SI].LHTYPE,LOW LH_FREE ;set type for FREE entry
  516. MOV [SI].LHLEN,AX ;put size into new entry header
  517. SUB SI,AX ;point to next entry (byte before backlength)
  518. MOV [SI+1],AX ;put in backlength for the present entry
  519. ADD SI,AX ;point back to remainder block
  520. ADD SI,BX ;point back to newly allocated block
  521. LH_ALC_EXACT:
  522. ; Clear the new heap entry to zeroes.
  523. PUSH CX ;save registers for clear...
  524. PUSH DI
  525. PUSH ES
  526. PUSH DS
  527. POP ES ;set ES = DS
  528. MOV DI,SI ;copy pointer to header of allocated block
  529. SUB DI,BX ;point to header of previous block
  530. MOV [b$HEAP_FREE],DI ;free entry is now previous block
  531. INC DI ;now point to data of block to be allocated
  532. XOR AX,AX ;value to set entry locations
  533. MOV CX,BX ;get size of entry in bytes
  534. SHR CX,1 ;convert size to words
  535. REP STOSW ;clear the entry
  536. POP ES
  537. POP DI ;restore registers...
  538. POP CX
  539. ; Finish by setting the header values
  540. MOV [SI].LHTYPE,DL ;set the heap entry type
  541. MOV [SI].LHLEN,BX ;set the heap entry length
  542. SUB SI,BX ;point to next entry (byte before backlength)
  543. MOV [SI+1],BX ;set the backlength
  544. ADD SI,BX ;set point back to entry header
  545. CMP [SI].LHTYPE,LOW LH_FILE ;test if FILE entry
  546. JNE LH_ALC_NOT_FILE ;if not, then branch
  547. MOV [SI].LHFNUM,CL ;set file number
  548. JMP SHORT LH_ALC_EXIT
  549. LH_ALC_NOT_FILE:
  550. MOV [SI].LHBAKP,CX ;all entries have backpointers except fdb's
  551. LH_ALC_EXIT:
  552. SUB SI,BX ;point to previous entry
  553. ADD SI,3 ;set to start of entry data (past backlength)
  554. RET ;return with carry clear
  555. page
  556. ;*** 
  557. ; B$LHDALC_CPCT -- deallocate heap entry and compact heap.  Added with [44].
  558. ;
  559. ;Purpose:
  560. ; Deallocates heap entry, and then compacts local heap, so that no 
  561. ; no "holes" develop in the heap.
  562. ;
  563. ;Entry/Exit/Uses/Exceptions:
  564. ; Same as B$LHDALC/B$LH_CPCT.
  565. ;
  566. ;******************************************************************************
  567. cProc B$LHDALC_CPCT,<PUBLIC,NEAR>
  568. cBegin
  569. CALL B$LHDALC ; deallocate heap entry
  570. cEnd <nogen> ; fall into B$LH_CPCT
  571. ;***
  572. ; B$LH_CPCT - compact local heap space
  573. ; Purpose:
  574. ; Compacts all allocated local heap entries to the top of
  575. ; the local heap space.  The backpointers in the ARRAY and FILE
  576. ; entries are adjusted appropriately to reflect their movement.
  577. ; The remaining unallocated space is made into the free entry.
  578. ; NOTE: The scan (and compaction) moves from high memory to low.
  579. ;
  580. ; Inputs:
  581. ; None
  582. ; Outputs:
  583. ; [b$HEAP_FREE] points to the new free heap entry.
  584. ; Exceptions:
  585. ; B$ERR_SSC - nontrappable error if compaction finds corruption
  586. ;   in the local heap space structure.
  587. ;****
  588. B$LH_CPCT PROC    NEAR
  589. PUSH ES
  590. PUSH DS
  591. POP ES ;Set ES = DS
  592. PUSH AX ;save registers used...
  593. PUSH BX
  594. PUSH CX
  595. PUSH SI
  596. PUSH DI
  597. MOV SI,[b$HEAP_FIRST] ;pointer to heap scan
  598. ; Skip over leading allocated entries which can be ignored since
  599. ; they will not be moved.  While skipping, an END entry implies
  600. ; no compaction need to be done. Check all allocated entries.
  601. B$LH_CPCT_SKIP:
  602. CMP [SI].LHTYPE,LOW LH_END ;test for end of local heap
  603. JE B$LH_CPCT_DONE    ;if so, no compact, just return
  604. CALL B$LH_PTR_CHECK   ;check entry at [SI] for consistency
  605. CMP [SI].LHTYPE,LOW LH_FREE ;test if leading allocated entry
  606. JE B$LH_CPCT_FIRST_FREE ;if not, then skipping is over
  607. SUB SI,[SI].LHLEN ;point to next entry
  608. JMP SHORT B$LH_CPCT_SKIP ;and try again
  609. ; First unallocated heap entry found.  Initialize compacted pointer DI.
  610. B$LH_CPCT_FIRST_FREE:
  611. MOV DI,SI ;SI=scan pointer - DI=compacted pointer
  612. ; Unallocated heap entry just advances the scan pointer SI.
  613. B$LH_CPCT_NEXT_FREE:
  614. SUB SI,[SI].LHLEN ;point to entry after unallocated one
  615. ; Process the entry at [SI].  First check consistency of entry.
  616. B$LH_CPCT_NEXT:
  617. ; If END entry, compaction is done - jump to finish up.
  618. CMP [SI].LHTYPE,LOW LH_END ;test for END entry
  619. JE B$LH_CPCT_SETUP_FREE ;jump to set up free entry
  620. ; If FREE entry, jump to advance scan pointer SI.
  621. CALL B$LH_PTR_CHECK   ;check entry at [SI]
  622. CMP [SI].LHTYPE,LOW LH_FREE ;test for FREE entry
  623. JE B$LH_CPCT_NEXT_FREE ;jump to advance scan pointer
  624. ; Allocated entry - adjust the entry backpointers to reflect
  625. ; its new location at [DI].
  626. MOV AX,DI ;set to new entry location
  627. SUB AX,SI ;subtract to get adjustment factor
  628. CALL B$LHADJ ;adjust the entry using the factor in AX
  629. ; Move the entry from [SI] to [DI] with direction flag SET.
  630. MOV CX,[SI].LHLEN ;get length of entry in bytes
  631. SHR CX,1 ;make the length in words
  632. DEC SI ;point to word address in source
  633. DEC DI ;point to word address in destination
  634. STD ;all strings move down in memory
  635. REP MOVSW ;move the entry to its new location
  636. CLD ;restore direction flag
  637. INC SI ;point back to byte in source
  638. INC DI ;also in destination
  639. ; Now make the space between the moved entry and the next entry
  640. ; a free heap entry.  This will ensure heap consistency and
  641. ; allow routines called during the middle of compaction to
  642. ; walk the heap.
  643. MOV [DI].LHTYPE,LOW LH_FREE ;set type of FREE entry
  644. MOV [DI].LHLEN,AX ;set size of new entry
  645. MOV [SI+1],AX ;also set backlength of new entry
  646. JMP SHORT B$LH_CPCT_NEXT ;try again (SI and DI are already adjusted)
  647. ; Compaction is done - set up the unused space as a FREE entry and
  648. ; point to it for the next allocation.
  649. B$LH_CPCT_SETUP_FREE:
  650. MOV AX,DI ;get length of remaining entry...
  651. SUB AX,SI ;by the difference of the pointers
  652. JZ B$LH_CPCT_NO_FREE ;if no entry left, then jump
  653. MOV [DI].LHTYPE,LOW LH_FREE ;set type of FREE entry
  654. MOV [DI].LHLEN,AX ;set size of new entry
  655. MOV [SI+1],AX ;also set backlength of new entry
  656. B$LH_CPCT_NO_FREE:
  657. MOV [b$HEAP_FREE],DI ;new entry for next allocation
  658. ; Restore registers and return.
  659. B$LH_CPCT_DONE:
  660. POP DI ;restore registers...
  661. POP SI
  662. POP CX
  663. POP BX
  664. POP AX
  665. B$LH_CPCT_EXIT:
  666. POP ES
  667. RET ;return to caller
  668. B$LH_CPCT ENDP
  669. ;***
  670. ; B$LHDALC - deallocate heap entry
  671. ; Purpose:
  672. ; To deallocate the heap entry whose data area is pointed by SI.
  673. ;
  674. ; Inputs:
  675. ; SI = pointer to heap entry data area
  676. ; Outputs:
  677. ; None.
  678. ; Modifies:
  679. ; ES, if interpreter version
  680. ; Exceptions:
  681. ; None.
  682. ;****
  683. B$LHDALC PROC NEAR
  684. PUSH ES
  685. PUSH DS
  686. POP ES ;Set ES = DS
  687. PUSH AX ;save registers...
  688. PUSH SI
  689. CALL B$LH_PTR_FROM_DATA ;get entry pointer from SI data pointer
  690. XOR AX,AX ;set flag for entry deallocation
  691. CALL B$LHADJ ;call to deallocate all string data in entry
  692. MOV [SI].LHTYPE,LOW LH_FREE ;set array type to FREE
  693. POP SI ;restore registers...
  694. POP AX
  695. POP ES
  696. RET ;return to caller
  697. B$LHDALC ENDP
  698. ;***
  699. ; B$LHADJ - delete/adjust a heap entry
  700. ; Function:
  701. ; Deallocates or adjusts the heap entry pointed by SI.
  702. ; If AX=0, all string data referenced by descriptors within
  703. ; the entry is deallocated.
  704. ; If AX<>0, all backpointers referenced within the entry are
  705. ; adjusted by the value of AX.
  706. ;
  707. ; NOTE: In QB versions, B$LHDALC can call this routine to deallocate [23]
  708. ; NOTE: an entry in the variable heap while the local heap is active. [23]
  709. ; NOTE: This causes no problems in this routine as it is now, because [23]
  710. ; NOTE: we'll never have an LH_FILE or LH_ARRAY entry in the variable [23]
  711. ; NOTE: heap.                                                         [23]
  712. ;
  713. ; Inputs:
  714. ; AX = adjustment value
  715. ;      AX=0  - deallocate all entry string data.
  716. ;      AX<>0 - adjust all entry backpointers.
  717. ; SI = address of heap entry.
  718. ; DS = segment that heap is in
  719. ; ES = segment that state vars are in
  720. ; Outputs:
  721. ; None.
  722. ; Modifies:
  723. ; None.
  724. ; Exceptions:
  725. ; None.
  726. ;****
  727. assumes ES,DGROUP
  728. assumes DS,NOTHING
  729. B$LHADJ  PROC   NEAR
  730. PUSH BX ;save registers...
  731. PUSH CX
  732. CMP [SI].LHTYPE,LOW LH_FILE ;test if entry is FILE
  733. JNE ADJLHP_NOT_FILE ;if not, then jump [23]
  734. ASSERT_NOT_VARHEAP NH_TEXT 
  735. LEA BX,[SI+3] ;point to 1 word past heap header
  736. SUB BX,[SI].LHLEN ;point at heap entry data
  737. CMP BX,ES:[b$PTRFIL] ;are we moving PTRFIL?
  738. JNZ NotPtrFil ;brif not
  739. ADD ES:[b$PTRFIL],AX ;adjust if moving ptrfil
  740. NotPtrFil:
  741. ; Entry is FILE - deallocate/adjust the fielded string backpointer
  742. ; if it exists.
  743. CMP WORD PTR [SI].LHPLEN,0 ;test if fielded string is null
  744. JZ ADJLHP_EXIT ;if so, then just return
  745. MOV BX,[SI].LHPOFF ;get offset of fielded string data
  746. ADD [BX-2],AX ;add adjustment to the string backpointer
  747. OR AX,AX ;test if deallocation was requested
  748. ; JNZ ADJLHP_QUIT ;if just adjustment, then jump
  749. JNZ ADJLHP_ALL_FLDS ;if adjustment, then adust fielded strings
  750. MOV [SI].LHTYPE,LOW LH_FREE ;mark the deallocated block free
  751. CALL B$LHDALCALLFLD ; otherwise deallocate all fielded strings
  752. JMP SHORT ADJLHP_QUIT ;jump to return to caller
  753. ; Entry contains fielded strings - adjust pointers into field buffer
  754. ADJLHP_ALL_FLDS:
  755. MOV CX,[SI].LHPLEN ;get size of string entry for fielded strs
  756. SHR CX,1 ;compute number of fielded strings
  757. PUSH SI ;preserve heap pointer
  758. ADJ_FLD_LOOP:
  759. MOV SI,[BX]  ;get pointer to field variable
  760. ADD [SI+2],AX ;adjust pointer into field buffer
  761. INC BX ;move to next field variable
  762. INC BX
  763. LOOP ADJ_FLD_LOOP ;loop until all ptrs to field buffer have
  764. ;been adjusted
  765. POP SI ;recover heap pointer
  766. ADJLHP_EXIT:
  767. JMP SHORT ADJLHP_QUIT ;jump to return to caller
  768. ; If entry is not ARRAY, then return.
  769. ADJLHP_NOT_FILE:
  770. CMP [SI].LHTYPE,LOW LH_ARRAY ;test if entry is ARRAY
  771. JNE ADJLHP_INTERP ;if not, consider interp. entries (if any)
  772. ; Entry is ARRAY, first clear/adjust the array descriptor pointer.
  773. MOV BX,[SI].LHBAKP ;get offset of array descriptor
  774. OR AX,AX ;test if array is being deallocated
  775. JNZ ADJLHP_ADJUST ;if just being adjusted, then jump
  776. MOV [BX].AD_fhd.FHD_hData,AX ;deallocated - clear the descriptor
  777. MOV [SI].LHBAKP,AX ;also clear the heap backpointer
  778. MOV [SI].LHTYPE,LOW LH_FREE ;mark the deallocated block free
  779. ADJLHP_ADJUST:
  780. ; Next, get pointer to start of array data and deallocate/adjust
  781. ; the backpointers of all nonnull strings in the array.
  782. MOV CX,[SI].LHLEN ;get length of heap entry (hdr+data+backlen)
  783. MOV BX,SI ;get copy of heap entry pointer
  784. SUB BX,CX ;point to next heap entry
  785. ADD BX,3 ;move past backlength to array start
  786. SUB CX,LH_STD_HDR_LEN+2 ;data length less header and backlength
  787. SHR CX,1 ;data length in words...
  788. SHR CX,1 ;length in doublewords (number of descs)
  789. ; For each nonnull descriptor, deallocate/adjust the string data.
  790. ; Process null strings through B$STADJ, fielded ones must be adjusted.
  791. ADJLHP_LOOP:
  792. ; CMP WORD PTR [BX],0 ;test if string is nonnull
  793. ; JZ ADJLHP_NEXT ;if so, then skip this entry
  794. CALL B$STADJ ;deallocate/adjust the string at desc [BX]
  795. ADJLHP_NEXT:
  796. ADD BX,4 ;point to next descriptor
  797. LOOP ADJLHP_LOOP ;loop to process the next one
  798. ADJLHP_INTERP:
  799. OR AX,AX
  800. JZ ADJLHP_QUIT ;brif deallocation - the below is for adjustment
  801. CALL B$LH_I_ADJ ;[ln] adjust backptrs to any owners in this entry
  802. ADJLHP_DONE:
  803. ;NOTE: important to update the owner LAST, after interpreter call
  804. ; back work is done.
  805. MOV BX,[SI].LHBAKP ;get pointer to owner
  806. ADD [BX],AX  ;add adjustment to owner pointer
  807. CMP [SI].LHTYPE,LOW LH_ARRAY; test if entry is ARRAY
  808. JNE ADJLHP_QUIT ; jump if not
  809. ADD [BX].AD_oAdjusted,AX ; else update adjusted pointer
  810. ADJLHP_QUIT:
  811. POP CX ;restore registers...
  812. POP BX
  813. RET ;return to caller
  814. B$LHADJ  ENDP
  815. assumes DS,DGROUP
  816. assumes ES,NOTHING
  817. ;***
  818. ; B$LHDALCALLFLD - deallocate all fielded strings for heap entry
  819. ; Purpose:
  820. ; To deallocate all fielded strings associated with the heap
  821. ; entry pointed by SI.  The heap backpointer string is also
  822. ; deallocated.
  823. ;
  824. ; Inputs:
  825. ; SI = pointer to heap entry
  826. ; Outputs:
  827. ; None.
  828. ; Modifies:
  829. ; None.
  830. ; Exceptions:
  831. ; None.
  832. ;****
  833. B$LHDALCALLFLD:
  834. ASSERT_NOT_VARHEAP NH_TEXT 
  835. PUSH AX ;save registers...
  836. PUSH BX
  837. PUSH CX
  838. PUSH DI
  839. XOR AX,AX ;clear AX to zero
  840. MOV BX,AX ;same for BX...
  841. MOV CX,AX ;and CX
  842. XCHG CX,[SI].LHPLEN ;swap bkptr str len and 0
  843. XCHG BX,[SI].LHPOFF ;swap bkptr str off and 0
  844. INC CX ;add one for backpointer value
  845. MOV [BX-2],CX ;free string by setting backpointer value
  846. SHR CX,1 ;number of words to process
  847. DALCALLFLD_LOOP:
  848. MOV DI,[BX]  ;get next word from string
  849. MOV [DI],AX  ;clear descr length
  850. MOV [DI+2],AX ;clear descr offset
  851. ADD BX,2 ;point to next descriptor in string
  852. LOOP DALCALLFLD_LOOP ;if not done, then loop
  853. POP DI ;restore registers...
  854. POP CX
  855. POP BX
  856. POP AX
  857. RET ;return to caller
  858. ;***
  859. ; B$LHFLDDESCADJ - delete/adjust descriptor in field backpointer string.
  860. ; Purpose:
  861. ; Search through the local heap FILE entries for the descriptor
  862. ; address specified in BX.  If AX=0, then remove it from the
  863. ; field backpointer string.  If AX<>0, then just adjust the
  864. ; backpointer string element by adding AX to it.
  865. ;
  866. ; Inputs:
  867. ; AX = adjustment factor
  868. ;      AX=0 - delete descriptor BX from backpointer string.
  869. ;      AX<>0 - adjust descriptor BX in backpointer string by AX.
  870. ; BX = address of descriptor to be deleted/adjusted.
  871. ; DS = segment that heap is in
  872. ; ES = segment that state vars are in
  873. ; Outputs:
  874. ; None.
  875. ; Modifies:
  876. ; SI.
  877. ; Exceptions:
  878. ; B$ERR_SSC if descriptor offset not found.
  879. ;****
  880. B$LHFLDDESCADJ:
  881. assumes ES,DGROUP
  882. assumes DS,NOTHING
  883. ASSERT_NOT_VARHEAP NH_TEXT 
  884. PUSH AX ;save registers...
  885. PUSH BX
  886. PUSH CX
  887. PUSH DX
  888. PUSH DI
  889. XCHG DX,AX ; [DX] = adjustment factor
  890. XCHG AX,BX ; [AX] = object of searches
  891. XOR BX,BX ;start at beginning of heap
  892. FLDDESCADJ_NEXT:
  893. MOV SI,BX ;put current FDB point in for test
  894. CALL NXTFIL_ES ;get next FILE data pointer in SI
  895. JZ FLDDESCADJ_ERROR ;if no more entries, then done
  896. MOV BX,SI ;save current FDB point for next time
  897. CALL B$LH_PTR_FROM_DATA ;get heap entry pointer in SI
  898. ; Heap entry is for a file.  Determine if a backpointer string
  899. ; is defined.  If so, then scan string for descriptor value in AX.
  900. MOV CX,[SI].LHPLEN ;get length of string
  901. JCXZ FLDDESCADJ_NEXT ;if null string, then try next entry
  902. SHR CX,1 ;make it in words
  903. MOV DI,[SI].LHPOFF ;get offset of the string
  904. PUSH ES ;make sure that we use the proper
  905. PUSH DS ;segment in case that
  906. POP ES ;we are in the middle of unwinding a CHAIN
  907. REPNE SCASW ;scan for word in AX
  908. POP ES ;recover correct ES = BASIC DS
  909. JNZ FLDDESCADJ_NEXT ;if not there, try next
  910. ; Word found in string.  DI is pointing just after the word
  911. ; while CX contains the number of words in the string AFTER
  912. ; the one searched.  If modifying (DX<>0), just add the adjustment
  913. ; factor to the word.
  914. ADD [DI-2],DX ;assume adjustment is made (deleted otherwise)
  915. OR DX,DX ;test if adjustment really wanted
  916. JNZ FLDDESCADJ_DONE ;if so, then jump to return now
  917. ; If deleting (DX=0), start at DI and move CX words left by two
  918. ; and put a null free string header where the last word of the
  919. ; string was.
  920. SUB WORD PTR [SI].LHPLEN,2 ;string size is less by 2
  921. JZ FLDDESCADJ_CLR ;jump if string is now empty
  922. MOV SI,DI ;SI points to byte after
  923. DEC DI ;point DI to...
  924. DEC DI ;the word before (AX value)
  925. PUSH ES ;make sure that we use the proper
  926. PUSH DS ;segment in case that
  927. POP ES ;we are in the middle of unwinding a CHAIN
  928. REP MOVSW ;move the string left 2
  929. POP ES ;recover correct ES = BASIC DS
  930. MOV WORD PTR [DI],1 ;null string free header
  931. JMP SHORT FLDDESCADJ_DONE ;done, jump to finish
  932. FLDDESCADJ_CLR:
  933. XOR DI,DI ;clear register
  934. XCHG DI,[SI].LHPOFF ;clear descr offset, get it
  935. MOV WORD PTR [DI-2],3 ;set ptr to empty string
  936. FLDDESCADJ_DONE:
  937. POP DI ;restore registers...
  938. POP DX
  939. POP CX
  940. POP BX
  941. POP AX
  942. RET ;return to caller
  943. FLDDESCADJ_ERROR:
  944. JMP B$ERR_SSC ; report string space corruption
  945. assumes DS,DGROUP
  946. assumes ES,NOTHING
  947. ;***
  948. ; B$LHNXTFIL, NXTFIL_ES - return FDB pointer of next file in heap after [SI]
  949. ; Purpose:
  950. ; To return a pointer to the next FDB in the heap.  The
  951. ; local heap is searched from the last FDB specified in SI
  952. ; (or the first if SI=0).
  953. ;
  954. ; Inputs:
  955. ; SI = pointer to FDB to start search from (0 if first FDB
  956. ;      pointer is to be returned).
  957. ; Outputs:
  958. ; SI = pointer to next FDB after the one specified on routine
  959. ;      entry (0 if no more FDB's in the heap).
  960. ; ZF = clear if FDB returned
  961. ;      set if none returned
  962. ; Modifies:
  963. ; None.
  964. ; Exceptions:
  965. ; None.
  966. ;****
  967. NXTFIL_ES: ;Assumes ES already set up
  968. PUSH ES
  969. JMP SHORT NXTFIL_COMMON 
  970. B$LHNXTFIL:
  971. PUSH ES
  972. PUSH DS
  973. POP ES ;set ES = DS
  974. NXTFIL_COMMON: ;common entry
  975. ASSERT_NOT_VARHEAP NH_TEXT 
  976. assumes ES,DGROUP
  977. assumes DS,NOTHING
  978. OR SI,SI ;test if first file is to be searched
  979. JNZ NXTFIL_NEXT ;if so, then branch
  980. MOV SI,ES:[b$HEAP_FIRST] ;initialize to start of local heap
  981. ADD SI,3 ;adjust to avoid extra jump
  982. NXTFIL_NEXT:
  983. SUB SI,3 ;move from FDB over backlength to next entry
  984. NXTFIL_LOOP:
  985. CMP [SI].LHTYPE,LOW LH_END ;test if last entry in heap
  986. JE NXTFIL_END ;if so, then jump
  987. CMP [SI].LHTYPE,LOW LH_FILE ;test if entry is file
  988. JE NXTFIL_FILE ;if so, then jump
  989. SUB SI,[SI].LHLEN ;point to next heap entry
  990. JMP SHORT NXTFIL_LOOP ;and continue the search
  991. NXTFIL_FILE:
  992. SUB SI,[SI].LHLEN ;point to previous entry
  993. ADD SI,3 ;move over backlength to entry FDB
  994. assumes ES,NOTHING
  995. POP ES
  996. RET ;return to caller (ZF clear)
  997. NXTFIL_END:
  998. XOR SI,SI ;clear to show no more files
  999. POP ES
  1000. RET ;return to caller (ZF set)
  1001. ;***
  1002. ;B$LH_PTR_FROM_DATA - get heap entry pointer from data pointer
  1003. ;LH_PTR_FROM_BLEN - get heap entry pointer from backlength pointer
  1004. ;B$LH_PTR_CHECK     - check heap entry referenced by its pointer
  1005. ;
  1006. ;Purpose:
  1007. ; From the pointer given return the heap entry data pointer. Also check the
  1008. ; heap entry by matching its length and backlength values and confirming that
  1009. ; the length is nonzero.
  1010. ;
  1011. ;Inputs:
  1012. ; SI = specified pointer
  1013. ;
  1014. ;Outputs:
  1015. ;
  1016. ; SI = heap entry header pointer
  1017. ;
  1018. ;Modifies:
  1019. ; None.
  1020. ;
  1021. ;Exceptions:
  1022. ; If heap entry is inconsistent, jump to B$ERR_SSC.
  1023. ;****
  1024. B$LH_PTR_FROM_DATA:
  1025. SUB SI,2 ;now point to entry backlength
  1026. LH_PTR_FROM_BLEN:
  1027. ADD SI,[SI]  ;point to one past header entry
  1028. DEC SI ;point to header entry
  1029. B$LH_PTR_CHECK:
  1030. PUSH AX ;save registers...
  1031. PUSH DI
  1032. MOV AX,[SI].LHLEN ;get length of heap entry
  1033. MOV DI,SI ;compute offset of entry backlength...
  1034. SUB DI,AX ;by moving the pointer to before backlength
  1035. CMP [DI+1],AX ;compare entry length and backlength
  1036. JNE LH_PTR_ERROR ;if not equal, then report error
  1037. OR AX,AX ;test for illegal zero value
  1038. JZ LH_PTR_ERROR ;if so, then jump
  1039. POP DI ;restore registers...
  1040. POP AX
  1041. RET ;return to caller
  1042. LH_PTR_ERROR:
  1043. PUSH ES ;force DS = basic dgroup in case
  1044. POP DS ;we are unwinding chain
  1045. assumes DS,DGROUP
  1046. DbHalt NH_TEXT,<B$LH_PTR_CHECK found inconsistent heap entry>
  1047. JMP B$ERR_SSC ;note heap is inconsistent if ID_RELEASE version
  1048. ;***
  1049. ; B$LHSetFree - set free heap entry pointer
  1050. ; Purpose:
  1051. ; Determines if the current free heap entry is both the last
  1052. ; heap entry and unallocated.  If so, its current value is
  1053. ; returned in DI.  Otherwise, the free heap entry pointer
  1054. ; [b$HEAP_FREE] is set to the heap space end and its value returned
  1055. ; in DI.
  1056. ;
  1057. ; Inputs:
  1058. ; None.
  1059. ; Outputs:
  1060. ; DI = pointer to free heap entry [b$HEAP_FREE].
  1061. ; Modifies:
  1062. ; AX.
  1063. ; Exceptions:
  1064. ; None.
  1065. ;****
  1066. B$LHSetFree PROC NEAR
  1067. MOV DI,[b$HEAP_FREE] ;point to free heap entry
  1068. CMP [DI].LHTYPE,LOW LH_FREE ;test if entry unallocated
  1069. JNE LH_SET_END ;if allocated, then jump
  1070. MOV AX,DI ;get pointer to free entry
  1071. SUB AX,[DI].LHLEN ;point to entry after free one
  1072. CMP AX,[b$HEAP_END] ;test if free entry was last in space
  1073. JE LH_SET_RETURN ;if so, jump leaving pointer unchanged
  1074. LH_SET_END:
  1075. MOV DI,[b$HEAP_END] ;get pointer to heap end
  1076. CMP DI,[b$HEAP_FIRST] ; Empty heap?
  1077. JZ LH_SET_FREE ; then don't try anything fancy
  1078. MOV AX,DI ; [AX] = pointer to end entry
  1079. ADD AX,[DI+1] ; [AX] = pointer to entry before end
  1080. XCHG AX,DI ; [AX] = ptr to end, [DI] = entry before
  1081. CMP [DI].LHTYPE,LOW LH_FREE ; test if entry after unallocated
  1082. JZ LH_SET_FREE ; if so, that's the free entry
  1083. XCHG AX,DI ; else use end entry
  1084. LH_SET_FREE:
  1085. MOV [b$HEAP_FREE],DI ;and set the free pointer to it
  1086. LH_SET_RETURN:
  1087. RET ;return with DI pointing to free entry
  1088. B$LHSetFree ENDP
  1089. SUBTTL B$NHINIT - Initialize dynamic space
  1090. PAGE
  1091. ;***
  1092. ; B$NHINIT - Initialize dynamic space
  1093. ; Purpose:
  1094. ; Initialize the necessary pointers and structures for string and
  1095. ; local heap space.
  1096. ; Inputs:
  1097. ; AX = first word of dynamic space.
  1098. ; CX = last word of dynamic space.
  1099. ; Outputs:
  1100. ; None.
  1101. ; Modifies:
  1102. ; None.
  1103. ; Exceptions:
  1104. ; None.
  1105. ;****
  1106. cProc B$NHINIT,<PUBLIC,NEAR>,<AX,BX,CX,SI,DI>
  1107. cBegin
  1108. MOV SI,CX ;get last word of dynamic space
  1109. INC SI ;point to last byte of space
  1110. MOV [b$HEAP_FIRST],SI ;the local heap starts here...
  1111. MOV [b$HEAP_FREE],SI ;has its free entry here...
  1112. MOV [b$HEAP_END],SI  ;and ends here
  1113. MOV [SI].LHTYPE,LOW LH_END ;set the heap entry type
  1114. ADD AX,LH_STD_HDR_LEN ; dyn space starts after var heap
  1115. MOV [b$NH_first],AX
  1116. MOV BX,AX
  1117. DEC BX ; point to last byte of var heap
  1118. MOV [b$HEAP_FIRST_SWAP],BX ; the variable heap starts here...
  1119. MOV [b$HEAP_FREE_SWAP],BX ; has its free entry here...
  1120. MOV [b$HEAP_END_SWAP],BX ; and ends here
  1121. MOV [BX].LHTYPE,LOW LH_END ; set heap entry type
  1122. ;Set up pointers to routine to be called when B$ILHALC needs to
  1123. ;  grow the appropriate heap
  1124. MOV [P_HEAP_GROW_SWAP],NH_TEXTOFFSET B$VAR_ALC_GROW ;[ln]
  1125. MOV [b$P_HEAP_GROW],NH_TEXTOFFSET LH_ALC_GROW ;[ln]
  1126. SUB SI,LH_STD_HDR_LEN+1 ;point to even address before entry
  1127. CMP b$Clearing,0 ;are we doing a CLEAR statement?
  1128. JZ NotClearing ;no, go initialize string space
  1129. CALL B$SSClean ; clean out entries, so we don't
  1130. JMP SHORT InitExit ; bash function keys
  1131. NotClearing:
  1132. CALL B$STINIT ;initialize string space
  1133. InitExit:
  1134. cEnd
  1135. sEnd NH_TEXT
  1136. END