define(LOC_MEMEND,1) # pointer to end of memory define(LOC_AVAIL,2) # start of available space list define(LAMBDA,0) # null link (end of avail list) define(C,8) # threshhold for close-fitting blocks define(LINK,0) # link field of storage block define(SIZE,1) # size field of storage block define(OVERHEAD,2) # total words of overhead per block # alloc --- get pointer to block of at least w available words pointer function alloc (w) integer w integer mem (1) common /dsmem$/ mem pointer p, q, l integer n, k character c n = w + OVERHEAD q = LOC_AVAIL repeat { p = mem (q + LINK) if (p == LAMBDA) { call remark ("in alloc: out of storage space.") call remark ("type 'c' or 'i' for char or integer dump.") call getch (c, ERRIN) if (c == 'c'c | c == 'C'c) call dsdump (LETTER) else if (c == 'i'c | c == 'I'c) call dsdump (DIGIT) call error ("program terminated.") } if (mem (p + SIZE) >= n) break q = p } k = mem (p + SIZE) - n if (k < C) { mem (q + LINK) = mem (p + LINK) l = p } else { mem (p + SIZE) = k l = p + k mem (l + SIZE) = n } alloc = l + OVERHEAD return end # free --- return a block of storage to the available space list subroutine free (block) pointer block integer mem (1) common /dsmem$/ mem pointer p0, p, q integer n p0 = block - OVERHEAD n = mem (p0 + SIZE) q = LOC_AVAIL repeat { p = mem (q + LINK) if (p == LAMBDA | p > p0) break q = p } if (p0 + n == p & p ~= LAMBDA) { n = n + mem (p + SIZE) mem (p0 + LINK) = mem (p + LINK) } else mem (p0 + LINK) = p if (q + mem (q + SIZE) == p0) { mem (q + SIZE) = mem (q + SIZE) + n mem (q + LINK) = mem (p0 + LINK) } else { mem (q + LINK) = p0 mem (p0 + SIZE) = n } return end # dsdump --- produce semi-readable dump of storage subroutine dsdump (form) character form integer mem (1) common /dsmem$/ mem pointer p, t, q t = LOC_AVAIL call print (ERROUT, "** DYNAMIC STORAGE DUMP ***n.") call print (ERROUT, "*5i *i words in use*n.", 1, OVERHEAD + 1) p = mem (t + LINK) while (p ~= LAMBDA) { call print (ERROUT, "*5i *i words available*n.", p, mem (p + SIZE)) q = p + mem (p + SIZE) while (q ~= mem (p + LINK) & q < mem (LOC_MEMEND)) call dsdbiu (q, form) p = mem (p + LINK) } call print (ERROUT, "** END DUMP ***n.") return end # dsdbiu --- dump contents of block-in-use subroutine dsdbiu (b, form) pointer b character form integer mem (1) common /dsmem$/ mem integer l, s, lmax call print (ERROUT, "*5i *i words in use*n.", b, mem (b + SIZE)) l = 0 s = b + mem (b + SIZE) if (form == DIGIT) lmax = 5 else lmax = 50 for (b = b + OVERHEAD; b < s; b = b + 1) { if (l == 0) call print (ERROUT, " .") if (form == DIGIT) call print (ERROUT, " *10i.", mem (b)) else if (form == LETTER) call print (ERROUT, "*c.", mem (b)) l = l + 1 if (l >= lmax) { l = 0 call print (ERROUT, "*n.") } } if (l ~= 0) call print (ERROUT, "*n.") return end # dsinit --- initialize dynamic storage space to w words subroutine dsinit (w) integer w integer mem (1) common /dsmem$/ mem pointer t if (w < 2 * OVERHEAD + 2) call error ("in dsinit: unreasonably small memory size.") # set up avail list: t = LOC_AVAIL mem (t + SIZE) = 0 mem (t + LINK) = LOC_AVAIL + OVERHEAD # set up first block of space: t = LOC_AVAIL + OVERHEAD mem (t + SIZE) = w - OVERHEAD - 1 # -1 for MEMEND mem (t + LINK) = LAMBDA # record end of memory: mem (LOC_MEMEND) = w return end