anchor.diff:                      :while arguments
                       :do (setf arguments (call-option-function (pop arguments)
                                                                 arguments
  -                                                              undefined-argument)))
  +                                                              undefined-argument
  +                                                              case-sensitive)))
                     nil)
                    (default
                     (funcall default)))))
  
positive.code:                           (rest body)
                            body)))
      `(progn
         (setf (gethash ',main-name *options*)
               (wrap-option-function ',(cons main-name other-names)
                                     ',parameters
                                     ',docstring
                                     (lambda ,(remove '&rest parameters)
                                       ,docstring
                                       (block ,lisp-name
                                         ,@body))))
         ,@(mapcar (lambda (other-name)
                     `(setf (gethash ',other-name *options*) (gethash ',main-name *options*)))
                   other-names)
         ',lisp-name)))
  
  
  
negative.code:        :documentation (split-string docstring (string #\newline))))))
  
  
  
  
  ;;; ---
  
  ;;; The public API is:
  ;;; (register-option option warn-on-conflicts)
  ;;; (get-option key case-sensitive)
  
  
  (defparameter *options* '()
    "A list of all registered options.")
  
  (defparameter *case-sensitive-options-map* nil
    "A cached dictionary of options.")
  (defparameter *case-insensitive-options-map* nil
    "A cached dictionary of options.")
  
  (defun find-option (keys)
    (let* ((options (loop
                      :for option :in *options*
                      :append (loop
                                :for key :in keys
                                :if (member key (option-keys option))
                                  :collect (list option "case sensitive" key)
                                :else
                                  :if (member key (option-keys option) :test (function equalp))
                                    :collect (list option "case insensitive" key))))
           (option (remove-duplicates (mapcar (function first) options))))
      (values option options)))
  
  (defun fill-option-map (table)
    (loop
      :for option :in *options*
      :do (loop :for key :in (option-keys option)
                :do (setf (gethash key table) option)))
    table)
  
  (defun register-option (option warn-on-conflicts)
    (when warn-on-conflicts
      (multiple-value-bind (old-option conflicts) (find-option (option-keys option))
        (when old-option
          (let ((*print-circle* nil) (*print-escape* nil))
           (warn "There are already options for ~:{the ~A key ~A~^, ~}."
                 (print (mapcar (function rest) conflicts)))))))
    (push option *options*))
  
  (defun get-option (key case-sensitive)
    (let ((table (if case-sensitive
                     *case-sensitive-options-map*
                     *case-insensitive-options-map*)))
      (gethash key
               (or table
                   (fill-option-map 
                    (if case-sensitive
                        (setf *case-sensitive-options-map*   (make-hash-table :test (function equal)))
                        (setf *case-insensitive-options-map* (make-hash-table :test (function equalp)))))))))
  
  
  
  
  ;;; ---
  
  (defgeneric call-option-function (option arguments undefined-argument case-sensitive)
    (:documentation  "
  DO:                  Call the option function with the ARGUMENTS.
  RETURN:              The remaining list of arguments.
  