home *** CD-ROM | disk | FTP | other *** search
- ;--------------------------------
- ;-- Define Linked-List objects --
- ;--------------------------------
-
- MODEL SMALL
- LOCALS
-
- ;** Define Linked-List object **
-
- INCLUDE list.aso
- INCLUDE node.aso
-
- ;** Create instance of Linked-List virtual method table **
-
- DATASEG
-
- TBLINST
-
- ;** Define some macros for use by the methods **
- ;** These are used by the methods for storing and loading double registers **
-
- ;Load two 16-bit registers from an address in specified segment
- loadptr macro r2,r1, addr
- mov r2,word ptr [addr+2]
- mov r1,word ptr [addr]
- endm
-
- ;Store two 16-bit registers to an address in specified segment
- storeptr macro addr, r2,r1
- mov word ptr [addr+2],r2
- mov word ptr [addr],r1
- endm
-
- ;Check to see if two 16-bit registers are both set to 0
- ;(r1 cannot be ax)
- isnullptr macro r2,r1
- ifdifi <r1>,<ax>
- mov ax,r2
- or ax,r1
- else
- push bx
- push r2
- pop bx
- or bx,ax
- pop bx
- endif
- endm
-
- ;** Linked-List methods **
-
- CODESEG
-
- ;Construct a Linked-List object
- ;This is the method "list|construct"
- ;This must be a static method.
- ;Returns DX:AX pointing to linked-list object, null if none.
- ;Object is allocated but not yet initialized.
- list_construct PROC PASCAL FAR
- USES ds
- ;-- Allocate the Linked-List object --
- mov bx,list_size
- mov ah,48h
- int 21h
- jc @@err
- mov dx,ax
- sub ax,ax
- ret
- @@err: sub dx,dx
- sub ax,ax
- ret
- ENDP
-
-
- ;Destroy a Linked-List object.
- ;This is the method "list|destroy"
- list_destroy PROC PASCAL FAR
- ARG @@list:dword
- ;-- deallocate memory for list --
- mov es,word ptr @@list+2
- mov ah,49h
- int 21h
- ret
- ENDP
-
- ;Initialize a Linked-List object.
- ;This is the method "list|init"
- ;This must be a static method!
- list_init PROC PASCAL FAR
- ARG @@list:dword
- USES ds,bx
- lds bx,@@list
- ;-- Initialize any virtual method table for the object at ds:bx --
- TBLINIT ds:bx
- ;-- Initialize the object's data --
- sub ax,ax
- storeptr ds:bx.list_head, ax,ax
- storeptr ds:bx.list_tail, ax,ax
- ret
- ENDP
-
- ;Deinitialize a Linked-List object.
- ;This is the method "list|deinit"
- list_deinit PROC PASCAL FAR
- ARG @@list:dword
- ;does nothing.
- ret
- ENDP
-
-
- ;Insert a node into the Linked-List object.
- ;This is the method "list|insert".
- list_insert PROC PASCAL NEAR
- ARG @@list:dword,\ ;Pointer to list object
- @@new:dword,\ ;Pointer to new node to insert
- @@old:dword ;Pointer to node to insert before
- USES ds,es,bx,cx,dx,si,di
-
- les di,@@new ;es:di = new
- lds si,@@old ;ds:si = old
- ;-- First, adjust backward links --
- isnullptr ds,si ;old = null?
- jz @@a
- ;-- there is an old node to insert before
- loadptr dx,bx,ds:si.node_prev ;prev <- old.prev
- storeptr ds:si.node_prev,es,di ;old.prev <- new
- jmp short @@b
- @@a: ;-- there is no old node to insert before - insert at end
- push ds si ;(save old)
- lds si,@@list ;(get list object)
- loadptr dx,bx,ds:si.list_tail ;prev <- tail
- storeptr ds:si.list_tail,es,di ;tail <- new
- pop si ds ;(recall old)
- @@b: ;-- Next, adjust forward links --
- isnullptr dx,bx ;prev = null?
- jz @@c
- ;-- there is a prev node to insert after
- push ds ;(save old)
- mov ds,dx ;(ds:bx = prev)
- storeptr ds:bx.node_next,es,di ;prev.next <- new
- pop ds ;(recall old)
- jmp short @@d
- @@c: ;-- there is no prev node to insert after - insert at start
- push ds si ;(save old)
- lds si,@@list ;(ds:si = list object)
- storeptr ds:si.list_head,es,di ;head <- new
- pop si ds ;(recall old)
- @@d: ;-- Finally set pointers in this node
- storeptr es:di.node_prev,dx,bx ;new.prev <- prev
- storeptr es:di.node_next,ds,si ;new.next <- old
- ret
- ENDP
-
- ;Append a node at the end of a Linked-List object.
- ;This is the virtual method "list|append".
- list_append PROC PASCAL NEAR
- ARG @@list:dword,\
- @@new:dword
- USES ds,bx,es,di
- mov ax,@Data
- mov ds,ax
- les di,@@list
- sub ax,ax
- call es:di method list:insert uses ds:bx pascal,es di,@@new,ax ax
- ret
- ENDP
-
- ;Remove a node from a Linked-List object.
- ;This is the virtual method "list|remove"
- ;This simply unlinks the node from the list; the node itself must be
- ;delete by calling the node|deinit method.
- list_delete PROC PASCAL NEAR
- ARG @@list:dword,\ ;pointer to linked-list object
- @@node:dword ;pointer to node to delete
- USES ds,es,si,di
-
- lds si,@@node ;ds:si = node
- les di,ds:[si.node_prev] ;es:di = prev
- lds si,ds:[si.node_next] ;ds:si = next
- ;-- First change next node's previous pointer
- isnullptr ds,si ;next = 0?
- jz @@a ; yes - skip
- storeptr ds:si.node_prev,es,di ; no - next.prev <- prev
- jmp short @@b ; and skip...
- @@a: push ds si ;(save next)
- lds si,@@list ;(list object)
- storeptr ds:si.list_tail,es,di ;tail <- prev
- pop si ds ;(recall next)
- @@b: ;-- Now change previous node's next pointer
- isnullptr es,di ;prev = 0?
- jz @@c ; yes - skip
- storeptr es:di.node_next,ds,si ; no - prev.next <- next
- jmp short @@d ; and done...
- @@c: lds di,@@list ;(list object)
- storeptr ds:di.list_head,ds,si ;head <- next
- @@d: ret
- ENDP
-
- ;Return a pointer to the first node in the list
- ;This is the virtual method "list|first"
- ;Returns DX:AX pointing to first node in list (null if none)
- list_first PROC PASCAL NEAR
- ARG @@list:dword ;pointer to linked-list object
- USES ds,si
- lds si,@@list
- loadptr dx,ax, ds:si.list_head
- ret
- ENDP
-
- ;Return a pointer to the last node in the list
- ;This is the virtual method "list|last"
- ;Pass: pointer to object
- ;Ret: DX:AX points to last node in list (null if none)
- list_last PROC PASCAL NEAR
- ARG @@list:dword ;pointer to linked-list object
- USES ds,si
- lds si,@@list
- loadptr dx,ax, ds:si.list_tail
- ret
- ENDP
-
- END
-