home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Oakland CPM Archive
/
oakcpm.iso
/
cpm
/
cpm86
/
fmacs86.ark
/
MINTFORM.A86
< prev
next >
Wrap
Text File
|
1989-02-09
|
10KB
|
354 lines
pagesize 86
include mintdefs.a86
data dseg byte public
extrn formb: word
extrn forme: word
extrn fend: word
extrn actptr: word
; formhash is the hashing table for form names. It is a list of
;pointers to forms. Each form, in turn, has a pointer to the next form whose
;name hashes to the same entry in formhash. To add a new form, we must add the
;name to the proper place in the table. To delete a form, the form name must
;be removed from formhash. After the remaining forms have been moved up in
;memory, their links in formhash and each of the forms must be updated.
; We use -1 for NIL because is above any legal address that a form may
;take on. When we adjust the hash links, we won't adjust any NILs because they
;seem to be a form which is above the one being moved.
public syntax_table
syntax_table dw NIL
;don't put anything here.
formhashsize equ 256
public formhash ;formhash is public for debugging purposes only.
formhash dw nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil
dw nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil
dw nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil
dw nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil
dw nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil
dw nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil
dw nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil
dw nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil
dw nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil
dw nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil
dw nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil
dw nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil
dw nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil
dw nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil
dw nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil
dw nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil
hash_value rw 1
;data ends
code cseg byte public
;*** assume cs:code, ds: data, es: data
;define a form. Enter with:
; si => name
; cx = name length
; di => data
; dx = data length
; bx = form pointer.
;this is what is accomplished: (a=active string, n=new form, o=old forms)
; aaaa nnnnnnnn ooooooo oooooooo
; ^ ^ ^
;actptr formb forme
; ^<------>^
; di cx si
public define_form
define_form:
push bx ;save the form pointer.
call find_form ;see if it already exists.
jnc define_form_1 ;it doesn't.
;check to see if the form is already big enough.
cmp dx,data_length[bx]
ja define_form_3 ;it isn't.
pop form_pointer[bx] ;set the form pointer.
mov si,di ;prepare to move the data.
lea di,name_offset[bx] ;->name.
add di,cx ;->data.
mov data_length[bx],dx ;set the data length.
jmps define_form_4
define_form_3:
push di
push si
push cx
call delete_form
pop cx
pop si
pop di
define_form_1:
pop bx ;restore form pointer.
push di
push si
push cx
add cx,size_form ;compute amount of space needed.
add cx,dx
push cx ;push the size
mov si,actptr
mov di,si
sub di,cx
mov ax,di ;see if we have that much space.
sub ax,free_space
cmp ax,fend
jb define_form_2 ;no, go show no mem
mov cx,formb ;compute the number of bytes to move.
sub cx,actptr
mov actptr,di ;update actptr
rep movsb
;di points to the free space. Leave it alone.
mov formb,di
pop form_length[di] ;get the total size. (pushed as cx)
mov form_pointer[di],bx
pop cx ;we have to pop into cx, because we
mov name_length[di],cx ; need it later for the movsb.
mov data_length[di],dx
pop si ;restore ->name
call hash_func
mov ax,[bx] ;get current formhash
mov [bx],di ;make formhash point to us.
mov hash_link[di],ax ;make us point to current formhash.
add di,name_offset ;lea di,[di].name_offset
rep movsb
pop si ;restore ->data
define_form_4:
;here with dx=data size, si->data, di->data area in form.
mov cx,dx
rep movsb
ret
define_form_2:
jmp nomem
;Find a form. Enter with:
; si => name
; cx = name length
;Preserve di
;Exit with:
; bx => form
; cy if form found,
; nc if form not found.
public find_form
find_form:
push dx
push di
call hash_func
mov hash_value,bx ;remember the formhash pointer.
xor dx,dx
mov bx,[bx] ;get ->first form that hashes here.
find_form_1:
cmp bx,NIL ;end of list?
je find_form_2 ;yes, we didn't find it.
cmp cx,name_length[bx] ;lengths equal?
jne find_form_3 ;no, go to next.
lea di,name_offset[bx] ;compare names.
push si
push cx
rep cmpsb
pop cx
pop si
jne find_form_3 ;names not equal.
or dx,dx ;did we find it first?
je find_form_4 ;yes - that's where we want it.
mov di,hash_value ;get the head of the list.
mov ax,[di]
mov [di],bx ;make head -> found.
xchg ax,hash_link[bx] ;make found -> old head.
mov di,dx
mov hash_link[di],ax ;make pred(found) -> succ(found).
find_form_4:
stc ;found the form!
pop di
pop dx
ret
find_form_3:
mov dx,bx
mov bx,hash_link[bx]
jmps find_form_1
find_form_2:
clc ;didn't find the form!
pop di
pop dx
ret
;delete a form. Enter with:
; bx=>form
;this is what is accomplished: (a=active string, f=forms, d=deleted form)
; aaaa ffffffff ddddddddddd ffffffff
; ^ ^ ^ ^^^^^^^ ^
;actptr formb bx delete forme
; <-------------->^ ^
; cx si di
public delete_form
delete_form:
;delete the form from the hashing table.
mov di,bx ;make a copy of the pointer to the form.
mov cx,name_length[bx]
lea si,name_offset[bx]
call hash_func
sub bx,hash_link ;pretend that formhash is a form itself.
delete_form_1:
cmp hash_link[bx],di ;does this form point to us?
je delete_form_2 ;yes.
mov bx,hash_link[bx] ;no - go to the next form.
jmps delete_form_1
delete_form_2:
mov ax,hash_link[di] ;unlink us from the list.
mov hash_link[bx],ax
;check for deletion of the syntax table.
cmp di,syntax_table
jne delete_form_7
mov syntax_table,NIL ;if we're deleting it, put NIL in.
delete_form_7:
;now adjust the hash links in formhash.
mov ax,form_length[di]
mov bx,offset syntax_table
mov cx,formhashsize+1 ;add one for the syntax table.
delete_form_3:
cmp [bx],di ;do we need to adjust this one?
jae delete_form_4 ;no.
add [bx],ax ;yes - do it.
delete_form_4:
add bx,2
loop delete_form_3
;now adjust all the hash links in the forms. Notice that we are adjusting
; the hash link in the form we are about to delete, but it doesn't hurt.
; We can also presume the existence of at least one form at this point.
mov bx,formb
delete_form_5:
cmp hash_link[bx],di ;do we need to adjust this one?
jae delete_form_6 ;no.
add hash_link[bx],ax ;yes - do it.
delete_form_6:
add bx,form_length[bx] ;compute the form after this one.
cmp bx,forme ;no forms after this one.
jb delete_form_5
add formb,ax
mov si,di ;now move everything up.
add di,ax
mov cx,si
sub cx,actptr
dec si
dec di
std ;reverse move
rep movsb
cld
inc di ;update actptr
mov actptr,di
ret
;find the form whose name is given in arg1. Return the form pointer in
;si, and the number of bytes remaining in the form in cx.
public find_arg1
find_arg1:
mov cx,1
;fall through to find_arg
;find the form whose name is given in the argument specified in cx. Return
; the form pointer in si, and the number of bytes remaining in the form in cx,
; and the pointer to the form in bx.
public find_arg
find_arg:
call getarg
call find_form
jnc find_arg1_1 ;if form doesn't exist, exit.
mov si,bx ;make si => form.data
add si,name_offset
add si,name_length[bx]
add si,form_pointer[bx]
mov cx,data_length[bx] ;make cx = number of bytes left.
sub cx,form_pointer[bx]
stc ;remember that form was found.
find_arg1_1:
ret
;rehash is used when the hash structure is garbage, i.e., when a file has
; been bulk-loaded.
public rehash
rehash:
mov di,offset formhash ;kill all of the current pointers.
mov cx,formhashsize
mov ax,NIL
rep stosw
mov di,formb
rehash_1:
lea si,name_offset[di] ;->name.
mov cx,name_length[di]
call hash_func
mov ax,[bx] ;get current formhash
mov [bx],di ;make formhash point to us.
mov hash_link[di],ax ;make us point to current formhash.
add di,form_length[di]
cmp di,forme
jb rehash_1
ret
hash_func:
;enter with si,cx ->name to be hashed.
;the particular function we will use is:
; value=(((char*2+char)*2+char)*2+char)*2+char ...
;of course, most of the chars will be in the range [A-Za-z], so this
; may not be the best hashing function. Time will tell.
;exit with entry into hash table in bx.
;preserve dl.
push si
push cx
xor bl,bl ;start with zero.
jcxz hash_func_1
hash_func_2:
add bl,bl ;*2
adc bl,0
lodsb
sub al,'a' ;subtract off the most probable char.
add bl,al ;+char
adc bl,0
loop hash_func_2
hash_func_1:
mov bh,0
add bx,bx
lea bx,formhash[bx] ;don't add bx,offset formhash!
pop cx
pop si
ret
;Adjust the form pointer after building a value which affects the
; form pointer. The new form pointer is derived from the count
; of characters left in cx. The form is pointed to by bx.
public set_form_pointer
set_form_pointer:
mov ax,data_length[bx]
sub ax,cx
mov form_pointer[bx],ax
ret
public return_form
return_form:
call set_form_pointer
jmp return_tos
extrn return_tos: near
extrn getarg: near
extrn nomem: near
;code ends
end