anchor.diff:  ;; should send the async replies in the body of the handler
   ;; i.e. before the original request was sent. this is the same 
   ;; thing that the linux kernel does so it should be ok 
  -;;(defrpc call-test-msg 6 nlm4-test-args :void)
  -;;(defrpc call-lock-msg 7 nlm4-lock-args :void)
  -;;(defrpc call-cancel-msg 8 nlm4-cancel-args :void)
  -;;(defrpc call-unlock-msg 9 nlm4-unlock-args :void)
  -;;(defrpc call-granted-msg 10 nlm4-test-args :void)
  -;;(defrpc call-test-res 11 nlm4-test-res :void)
  -;;(defrpc call-lock-res 12 nlm4-res :void)
  -;;(defrpc call-cancel-res 13 nlm4-res :void)
  -;;(defrpc call-unlock-res 14 nlm4-res :void)
  -;;(defrpc call-granted-res 15 nlm4-res :void)
  +
  +
  +(defrpc call-test-msg 6 
  +  (:list netobj :boolean nlm-lock)
  +  :void
  +  (:arg-transformer (lock &key cookie exclusive)
  +    (list cookie exclusive lock))
  +  (:documentation "The async version of TEST. Results are returned asyncronously by a call from TEST-RES."))
  +
  +(defrpc call-lock-msg 7 
  +  (:list netobj :boolean :boolean nlm-lock :boolean :int32)
  +  :void
  +  (:arg-transformer (lock &key cookie block exclusive reclaim (state 0))
  +    (list cookie block exclusive lock reclaim state))
  +  (:documentation "Results returned asyncronously by a call from LOCK-RES."))
  +
  +(defrpc call-cancel-msg 8 
  +  (:list netobj :boolean :boolean nlm-lock)
  +  :void
  +  (:arg-transformer (lock &key cookie block exclusive)
  +    (list cookie block exclusive lock))
  +  (:documentation "Asyncronous version of CANCEL."))
  +
  +(defrpc call-unlock-msg 9 
  +  (:list netobj nlm-lock)
  +  :void
  +  (:arg-transformer (lock &key cookie)
  +    (list cookie lock))
  +  (:documentation "Asyncronous version of UNLOCK."))
  +
  +(defrpc call-granted-msg 10
  +  (:list netobj :boolean nlm-lock)
  +  :void
  +  (:arg-transformer (lock &key cookie exclusive)
  +    (list cookie exclusive lock))
  +  (:documentation "Asyncronous version of GRANTED."))
  +
  +(defrpc call-test-res 11 
  +  (:list netobj 
  +         (:union nlm-stat 
  +           (:denied nlm-holder)
  +           (otherwise :void)))
  +  :void
  +  (:arg-transformer (stat cookie &key holder)
  +    (list cookie
  +          (make-xunion stat
  +                       (if (eq stat :denied)
  +                           holder
  +                           nil))))
  +  (:documentation "Asyncronous reply to TEST-MSG."))
  +
  +(defrpc call-lock-res 12
  +  (:list netobj nlm-stat)
  +  :void
  +  (:arg-transformer (stat cookie)
  +    (list cookie stat))
  +  (:documentation "asyncronous reply to LOCK-MSG."))
  +
  +(defrpc call-cancel-res 13
  +  (:list netobj nlm-stat)
  +  :void
  +  (:arg-transformer (stat cookie) (list cookie stat))
  +  (:documentation "Asyncronous reply to CANCEL-MSG."))
  +
  +(defrpc call-unlock-res 14
  +  (:list netobj nlm-stat)
  +  :void
  +  (:arg-transformer (stat cookie) (list cookie stat))
  +  (:documentation "asyncronous reply to UNLOCK-MSG."))
  +
  +(defrpc call-granted-res 15 
  +  (:list netobj nlm-stat)
  +  :void
  +  (:arg-transformer (stat cookie) (list cookie stat))
  +  (:documentation "Asyncronous reply to GRANTED-MSG."))
   
   ;; syncronous non-monitored lock and DOS file-sharing procedures 
   ;; don't support these
  -;;(defrpc call-share 20 nlm4-share-args nlm4-share-res)
  -;;(defrpc call-unshare 21 nlm4-share-args nlm4-share-res)
  -;;(defrpc call-nm-lock 22 nlm4-lock-args nlm4-res)
  -;;(defrpc call-free-all 23 nlm4-notify :void)
  -
  +(defrpc call-share 20 
  +  (:list netobj nlm-share :boolean)
  +  (:list netobj nlm-stat :int32)
  +  (:arg-transformer (share &key cookie reclaim)
  +    (list cookie share reclaim))
  +  (:documentation "Indicates that a client wishes to open a file using DOS 3.1 and above filesharing modes. 
  +
  +This procedure does not block: it is the responsibility of the client to retry any failed requests."))
  +
  +(defrpc call-unshare 21 
  +  (:list netobj nlm-share :boolean)
  +  (:list netobj nlm-stat :int32)
  +  (:arg-transformer (share &key cookie)
  +    (list cookie share nil))
  +  (:documentation "This procedure informs NLM that the client has closed the file named by the share, and the corresponding share reservation should be released. The reclaim field is unused in the procedure and should be ignored. It is included for symmetry with the NLM-SHARE procedure."))
  +
  +(defrpc call-nm-lock 22 
  +  (:list netobj :boolean :boolean nlm-lock :boolean :int32)
  +  (:list netobj nlm-stat)
  +  (:arg-transformer (lock &key cookie block exclusive reclaim (state 0))
  +    (list cookie block exclusive lock reclaim state))
  +  (:documentation "This proceudre should only be called by clients that do not run NSM. This procedure has the same functionality as the LOCK procedure except there is no monitoring from NSM. Locks created with this procedure should be released with the normal UNLOCK procedure.
  +
  +Because NLM has no way to detect client crashes while locks are in effect, the client should call FREE-ALL to release all the locks it may have held before the crash."))
  +
  +(defrpc call-free-all 23 
  +  (:list :string :uint32)
  +  :void
  +  (:arg-transformer (name) (list name 0))
  +  (:documentation "This procedure informs the server that the client NAME has rebooted and that all file-sharing reservations and locks held by the client should be discarded."))
  +
  +
  +
  
positive.code: (defpackage #:nefarious.nlm
    (:use #:cl #:frpc)
    (:nicknames #:nlm)
    (:export #:call-null
  ;;	   #:call-test
  	   #:call-lock
  	   #:call-cancel
  	   #:call-unlock
  	   #:call-granted
  ;;	   #:call-test-msg
  ;;	   #:call-lock-msg
  ;;	   #:call-cancel-msg
  ;;	   #:call-unlock-msg
  ;;	   #:call-granted-msg
  ;;	   #:call-test-res
  ;;	   #:call-lock-res
  ;;	   #:call-cancel-res
  ;;	   #:call-unlock-res
  ;;	   #:call-granted-res
  ;;	   #:call-share
  ;;	   #:call-nm-lock
  ;;	   #:call-free-all
  	   
  	   ))
  
  
negative.code: ;; Semantically they are not the same, because CANCEL is typically 
  ;; used by the system to clean up clients that didn't exit properly.
  
  (defrpc call-cancel 3 
    (:list netobj :boolean :boolean nlm-lock)
    (:list netobj nlm-stat)
    (:arg-transformer (lock &key cookie block exclusive)
      (list cookie block exclusive lock))
    (:documentation "Cancels an outstanding blocked lock request. If the client made a LOCK procedure call with BLOCKED true and the procedure was blocked by the server (it returned a status of :BLOCKED), then the client can cancel the outstanding lock request by using this procedure.
  
  The BLOCK, EXCLUSIVE and LOCK arguments must exactly match those in the corresponding LOCK request."))
  
  (defhandler %handle-cancel (args 3)
    (destructuring-bind (cookie block exclusive alock) args
      (declare (ignore block exclusive))
      (release-lock (nlm-lock-fh alock))
      (list cookie :granted)))
  
  ;; ------------------------------------------
  
  ;; UNLOCK :: release a lock 
  
  (defrpc call-unlock 4 
    (:list netobj nlm-lock)
    (:list netobj nlm-stat)
    (:arg-transformer (lock &key cookie)
      (list cookie lock))
    (:documentation "Release a lock. The information in LOCK should match the information in the LOCK which created the lock."))
  
  (defhandler %handle-unlock (args 4)
    (destructuring-bind (cookie alock) args
      (release-lock (nlm-lock-fh alock))
      (list cookie :granted)))
  
  ;; --------------------------------------------
  