home *** CD-ROM | disk | FTP | other *** search
/ Oakland CPM Archive / oakcpm.iso / cpm / cpm86 / fmacs86.ark / MINTFORM.A86 < prev    next >
Text File  |  1989-02-09  |  10KB  |  354 lines

  1.     pagesize    86
  2.  
  3.     include    mintdefs.a86
  4.  
  5. data    dseg byte public
  6.     extrn    formb:    word
  7.     extrn    forme:    word
  8.     extrn    fend: word
  9.     extrn    actptr:    word
  10.  
  11. ;    formhash is the hashing table for form names.  It is a list of
  12. ;pointers to forms.  Each form, in turn, has a pointer to the next form whose
  13. ;name hashes to the same entry in formhash. To add a new form, we must add the
  14. ;name to the proper place in the table.  To delete a form, the form name must
  15. ;be removed from formhash. After the remaining forms have been moved up in
  16. ;memory, their links in formhash and each of the forms must be updated.
  17. ;    We use -1 for NIL because is above any legal address that a form may
  18. ;take on.  When we adjust the hash links, we won't adjust any NILs because they
  19. ;seem to be a form which is above the one being moved.
  20.  
  21.     public    syntax_table
  22. syntax_table    dw    NIL
  23. ;don't put anything here.
  24. formhashsize    equ    256
  25.     public    formhash    ;formhash is public for debugging purposes only.
  26. formhash dw nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil
  27.      dw nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil
  28.      dw nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil
  29.      dw nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil
  30.      dw nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil
  31.      dw nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil
  32.      dw nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil
  33.      dw nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil
  34.      dw nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil
  35.      dw nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil
  36.      dw nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil
  37.      dw nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil
  38.      dw nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil
  39.      dw nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil
  40.      dw nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil
  41.      dw nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil
  42.  
  43. hash_value    rw    1
  44.  
  45. ;data    ends
  46.  
  47. code    cseg byte public
  48.  
  49.     ;*** assume cs:code, ds: data, es: data
  50.  
  51.  
  52. ;define a form.  Enter with:
  53. ;    si => name
  54. ;    cx = name length
  55. ;    di => data
  56. ;    dx = data length
  57. ;    bx = form pointer.
  58.  
  59. ;this is what is accomplished: (a=active string, n=new form, o=old forms)
  60. ;  aaaa     nnnnnnnn   ooooooo     oooooooo
  61. ;  ^                   ^                    ^
  62. ;actptr               formb                forme
  63. ;  ^<------>^
  64. ;  di  cx   si
  65.  
  66.  
  67.     public    define_form
  68. define_form:
  69.     push    bx            ;save the form pointer.
  70.     call    find_form        ;see if it already exists.
  71.     jnc    define_form_1        ;it doesn't.
  72. ;check to see if the form is already big enough.
  73.     cmp    dx,data_length[bx]
  74.     ja    define_form_3        ;it isn't.
  75.     pop    form_pointer[bx]    ;set the form pointer.
  76.     mov    si,di            ;prepare to move the data.
  77.     lea    di,name_offset[bx]    ;->name.
  78.     add    di,cx            ;->data.
  79.     mov    data_length[bx],dx    ;set the data length.
  80.     jmps define_form_4
  81. define_form_3:
  82.     push    di
  83.     push    si
  84.     push    cx
  85.     call    delete_form
  86.     pop    cx
  87.     pop    si
  88.     pop    di
  89. define_form_1:
  90.     pop    bx        ;restore form pointer.
  91.     push    di
  92.     push    si
  93.     push    cx
  94.     add    cx,size_form    ;compute amount of space needed.
  95.     add    cx,dx
  96.     push    cx        ;push the size
  97.     mov    si,actptr
  98.     mov    di,si
  99.     sub    di,cx
  100.     mov    ax,di        ;see if we have that much space.
  101.     sub    ax,free_space
  102.     cmp    ax,fend
  103.     jb    define_form_2    ;no, go show no mem
  104.     mov    cx,formb    ;compute the number of bytes to move.
  105.     sub    cx,actptr
  106.     mov    actptr,di    ;update actptr
  107.     rep    movsb
  108. ;di points to the free space.  Leave it alone.
  109.     mov    formb,di
  110.     pop    form_length[di]        ;get the total size. (pushed as cx)
  111.     mov    form_pointer[di],bx
  112.     pop    cx            ;we have to pop into cx, because we
  113.     mov    name_length[di],cx    ;  need it later for the movsb.
  114.     mov    data_length[di],dx
  115.     pop    si            ;restore ->name
  116.     call    hash_func
  117.     mov    ax,[bx]            ;get current formhash
  118.     mov    [bx],di            ;make formhash point to us.
  119.     mov    hash_link[di],ax    ;make us point to current formhash.
  120.     add    di,name_offset        ;lea    di,[di].name_offset
  121.     rep    movsb
  122.     pop    si            ;restore ->data
  123. define_form_4:
  124. ;here with dx=data size, si->data, di->data area in form.
  125.     mov    cx,dx
  126.     rep    movsb
  127.     ret
  128. define_form_2:
  129.     jmp    nomem
  130.  
  131.  
  132. ;Find a form.  Enter with:
  133. ;    si => name
  134. ;    cx = name length
  135. ;Preserve di
  136. ;Exit with:
  137. ;    bx => form
  138. ;    cy if form found,
  139. ;    nc if form not found.
  140.     public    find_form
  141. find_form:
  142.     push    dx
  143.     push    di
  144.     call    hash_func
  145.     mov    hash_value,bx        ;remember the formhash pointer.
  146.     xor    dx,dx
  147.     mov    bx,[bx]            ;get ->first form that hashes here.
  148. find_form_1:
  149.     cmp    bx,NIL            ;end of list?
  150.     je    find_form_2        ;yes, we didn't find it.
  151.     cmp    cx,name_length[bx]    ;lengths equal?
  152.     jne    find_form_3        ;no, go to next.
  153.     lea    di,name_offset[bx]    ;compare names.
  154.     push    si
  155.     push    cx
  156.     rep    cmpsb
  157.     pop    cx
  158.     pop    si
  159.     jne    find_form_3        ;names not equal.
  160.     or    dx,dx            ;did we find it first?
  161.     je    find_form_4        ;yes - that's where we want it.
  162.     mov    di,hash_value        ;get the head of the list.
  163.     mov    ax,[di]
  164.     mov    [di],bx            ;make head -> found.
  165.     xchg    ax,hash_link[bx]    ;make found -> old head.
  166.     mov    di,dx
  167.     mov    hash_link[di],ax    ;make pred(found) -> succ(found).
  168. find_form_4:
  169.     stc                ;found the form!
  170.     pop    di
  171.     pop    dx
  172.     ret
  173. find_form_3:
  174.     mov    dx,bx
  175.     mov    bx,hash_link[bx]
  176.     jmps    find_form_1
  177. find_form_2:
  178.     clc            ;didn't find the form!
  179.     pop    di
  180.     pop    dx
  181.     ret
  182.  
  183.  
  184. ;delete a form.  Enter with:
  185. ;    bx=>form
  186. ;this is what is accomplished: (a=active string, f=forms, d=deleted form)
  187. ;  aaaa     ffffffff      ddddddddddd    ffffffff
  188. ;  ^        ^             ^   ^^^^^^^            ^
  189. ;actptr   formb          bx   delete           forme
  190. ;  <-------------->^                ^
  191. ;         cx       si               di
  192.  
  193.  
  194.     public    delete_form
  195. delete_form:
  196. ;delete the form from the hashing table.
  197.     mov    di,bx            ;make a copy of the pointer to the form.
  198.     mov    cx,name_length[bx]
  199.     lea    si,name_offset[bx]
  200.     call    hash_func
  201.     sub    bx,hash_link    ;pretend that formhash is a form itself.
  202. delete_form_1:
  203.     cmp    hash_link[bx],di    ;does this form point to us?
  204.     je    delete_form_2        ;yes.
  205.     mov    bx,hash_link[bx]    ;no - go to the next form.
  206.     jmps    delete_form_1
  207. delete_form_2:
  208.     mov    ax,hash_link[di]    ;unlink us from the list.
  209.     mov    hash_link[bx],ax
  210. ;check for deletion of the syntax table.
  211.     cmp    di,syntax_table
  212.     jne    delete_form_7
  213.     mov    syntax_table,NIL    ;if we're deleting it, put NIL in.
  214. delete_form_7:
  215. ;now adjust the hash links in formhash.
  216.     mov    ax,form_length[di]
  217.     mov    bx,offset syntax_table
  218.     mov    cx,formhashsize+1    ;add one for the syntax table.
  219. delete_form_3:
  220.     cmp    [bx],di            ;do we need to adjust this one?
  221.     jae    delete_form_4        ;no.
  222.     add    [bx],ax            ;yes - do it.
  223. delete_form_4:
  224.     add    bx,2
  225.     loop    delete_form_3
  226. ;now adjust all the hash links in the forms.  Notice that we are adjusting
  227. ;  the hash link in the form we are about to delete, but it doesn't hurt.
  228. ;  We can also presume the existence of at least one form at this point.
  229.     mov    bx,formb
  230. delete_form_5:
  231.     cmp    hash_link[bx],di    ;do we need to adjust this one?
  232.     jae    delete_form_6        ;no.
  233.     add    hash_link[bx],ax    ;yes - do it.
  234. delete_form_6:
  235.     add    bx,form_length[bx]    ;compute the form after this one.
  236.     cmp    bx,forme        ;no forms after this one.
  237.     jb    delete_form_5
  238.     add    formb,ax
  239.     mov    si,di            ;now move everything up.
  240.     add    di,ax
  241.     mov    cx,si
  242.     sub    cx,actptr
  243.     dec    si
  244.     dec    di
  245.     std                ;reverse move
  246.     rep    movsb
  247.     cld
  248.     inc    di            ;update actptr
  249.     mov    actptr,di
  250.     ret
  251.  
  252.  
  253. ;find the form whose name is given in arg1.  Return the form pointer in
  254. ;si, and the number of bytes remaining in the form in cx.
  255.     public    find_arg1
  256. find_arg1:
  257.     mov    cx,1
  258. ;fall through to find_arg
  259.  
  260. ;find the form whose name is given in the argument specified in cx.  Return
  261. ;  the form pointer in si, and the number of bytes remaining in the form in cx,
  262. ;  and the pointer to the form in bx.
  263.     public    find_arg
  264. find_arg:
  265.     call    getarg
  266.     call    find_form
  267.     jnc    find_arg1_1        ;if form doesn't exist, exit.
  268.     mov    si,bx            ;make si => form.data
  269.     add    si,name_offset
  270.     add    si,name_length[bx]
  271.     add    si,form_pointer[bx]
  272.     mov    cx,data_length[bx]    ;make cx = number of bytes left.
  273.     sub    cx,form_pointer[bx]
  274.     stc                ;remember that form was found.
  275. find_arg1_1:
  276.     ret
  277.  
  278.  
  279. ;rehash is used when the hash structure is garbage, i.e., when a file has
  280. ;  been bulk-loaded.
  281.  
  282.     public    rehash
  283. rehash:
  284.     mov    di,offset formhash    ;kill all of the current pointers.
  285.     mov    cx,formhashsize
  286.     mov    ax,NIL
  287.     rep    stosw
  288.     mov    di,formb
  289. rehash_1:
  290.     lea    si,name_offset[di]    ;->name.
  291.     mov    cx,name_length[di]
  292.     call    hash_func
  293.     mov    ax,[bx]            ;get current formhash
  294.     mov    [bx],di            ;make formhash point to us.
  295.     mov    hash_link[di],ax    ;make us point to current formhash.
  296.     add    di,form_length[di]
  297.     cmp    di,forme
  298.     jb    rehash_1
  299.     ret
  300.  
  301.  
  302. hash_func:
  303. ;enter with si,cx ->name to be hashed.
  304. ;the particular function we will use is:
  305. ;  value=(((char*2+char)*2+char)*2+char)*2+char ...
  306. ;of course, most of the chars will be in the range [A-Za-z], so this
  307. ;  may not be the best hashing function.  Time will tell.
  308. ;exit with entry into hash table in bx.
  309. ;preserve dl.
  310.     push    si
  311.     push    cx
  312.     xor    bl,bl            ;start with zero.
  313.     jcxz    hash_func_1
  314. hash_func_2:
  315.     add    bl,bl            ;*2
  316.     adc    bl,0
  317.     lodsb
  318.     sub    al,'a'            ;subtract off the most probable char.
  319.     add    bl,al            ;+char
  320.     adc    bl,0
  321.     loop    hash_func_2
  322. hash_func_1:
  323.     mov    bh,0
  324.     add    bx,bx
  325.     lea    bx,formhash[bx]        ;don't add bx,offset formhash!
  326.     pop    cx
  327.     pop    si
  328.     ret
  329.  
  330.  
  331. ;Adjust the form pointer after building a value which affects the
  332. ;  form pointer.  The new form pointer is derived from the count
  333. ;  of characters left in cx.  The form is pointed to by bx.
  334.     public    set_form_pointer
  335. set_form_pointer:
  336.     mov    ax,data_length[bx]
  337.     sub    ax,cx
  338.     mov    form_pointer[bx],ax
  339.     ret
  340.  
  341.     public    return_form
  342. return_form:
  343.     call    set_form_pointer
  344.     jmp    return_tos
  345.  
  346.  
  347.     extrn    return_tos: near
  348.     extrn    getarg: near
  349.     extrn    nomem: near
  350. ;code    ends
  351.  
  352.     end
  353.  
  354.