! Alternative DISPOSE

%option "-low-nodiag-noline-nocheck"

@720(a5) %integer globalheap,localheap

%constinteger overhead=4,minsize=8+overhead
%recordformat holef(%byte level %or %integer size,
                    %record(holef)%name next,prev)
%recordformat basef(%integer limit,
                    (%byte level %or %integer rootsize),
                    %record(*)%name link,holes)

%routine sd6(%integer x)
  *move.l d0,d6
%end

%routine unassign(%integer pos,size)
  size = size&16_fffffc
  %while size>0 %cycle
    size = size-4
    integer(pos) = d7
    pos = pos+4
  %repeat
%end

%externalroutine heapput(%integer pos)
%record(basef)%name lhb
%integer holeend
%record(holef)%name hole,neighbour
  ->invalid %if pos<=0 %or pos&3#0 %or localheap=0
  lhb == record(localheap)
  hole == record(pos-4)
  ->invalid %if hole_level=0 %or hole_level>lhb_level
  hole_level = 0
  unassign(pos+8,hole_size-12)
  holeend = pos-4+hole_size
  %if holeend=lhb_limit %start
done:
    lhb_limit = lhb_limit-hole_size
    sd6(lhb_limit+256)
    %return
  %finish
  hole_next == lhb_holes; lhb_holes == hole; hole_prev == nil
  hole_next_prev == hole %unless hole_next==nil
  %cycle
    %signal 5,,holeend,"HEAPPUT: heap corrupt" %if holeend>lhb_limit
    neighbour == record(holeend)
    %returnunless neighbour_level=0
    hole_size = hole_size+neighbour_size
    holeend = holeend+neighbour_size
    neighbour_prev_next == neighbour_next
    neighbour_next_prev == neighbour_prev %unless neighbour_next==nil
    %if holeend=lhb_limit %start
      lhb_holes == hole_next
      hole_next_prev == nil %unless hole_next==nil
      ->done
    %finish
  %repeat
invalid: %signal 5,,,"HEAPPUT: Invalid address"
%end

%externalroutine dispose(%record(*)%name pos)
  *move.l a0,d0
  *bsr heapput
%end

%begin
@16_3ff0 %integer freebot
  freebot = d6
  freebot = freebot-256
  *lea dispose,a0
  *move.l a0,16_3e84
%endofprogram
