anchor.diff:            *options*)))
   
   (defmacro define-opts (&rest descriptions)
  -  "Define command line options. DESCRIPTIONS must be a list, where every
  -element is also a list. CAR of this list must be a keyword denoting name of
  -the option. CADR of this list must be a string describing the option. Next,
  -there may be a character (short option) and/or string (long option). If
  -particular option should take an argument, you may add a function that will
  -be called to parse the argument in form of string into your desired type."
  -  `(dolist (description ',descriptions)
  -     (apply #'add-option description)))
  +  "Define command line options. Arguments of this macro must be plists
  +containing various parameters. Here we enumerate all allowed parameters:
  +
  +:NAME - keyword that will be included in list returned by GET-OPTS function
  +if actual option is supplied by user.
  +
  +:DESCRIPTION - description of the option (it will be used in DESCRIBE
  +command. This argument is optional, it's recommended to supply it.
  +
  +:SHORT - single character - short variant of the option. You may omit this
  +argument if you supply :LONG variant of option.
  +
  +:LONG - string, long variant of option. You may omit this argument if you
  +supply :SHORT variant of option.
  +
  +:ARG-PARSER - if actual option must take an argument, supply this argument,
  +it must be a function that takes a string and parses it.
  +
  +:META-VAR - if actual option requires an argument, this is how it will be
  +printed in option description."
  +  `(progn
  +     ,@(mapcar (lambda (args) (cons 'add-option args))
  +               descriptions)))
   
   (defun argv ()
     "Return list of program's arguments, including command used to execute the
  
positive.code: be printed in option description"))
    (:documentation "representation of an option"))
  
  (defparameter *options* nil
    "list of all defined options")
  
  (defun add-option (&rest args)
    "Register an option."
    (let ((name        (getf args :name))
          (description (getf args :description "?"))
          (short       (getf args :short))
          (long        (getf args :long))
          (arg-parser  (getf args :arg-parser))
          (meta-var    (getf args :meta-var "ARG")))
      (unless (or short long)
        (error "at least one form of the option must be provided"))
  
negative.code:   #+lispworks system:*line-arguments-list*
    #+sbcl      sb-ext:*posix-argv*)
  
  (defun get-opts (&optional options)
    "Parse command line options. If OPTIONS is given, it should be a list to
  parse. If it's not given, the function will use ARGV function to get list of
  command line arguments. Return two values: list that contains keywords
  associated with command line options with DEFINE-OPTS macro, and list of
  free arguments. If some option requires an argument, you can use GETF to
  test presence of the option and get its argument if the option is present.
  
  The parser may signal various conditions, let's list them all specifying
  which restarts are available for every condition, and what kind of
  information the programmer can extract from the conditions.
  
  UNKNOWN-OPTION is thrown when parser encounters unknown (not previously
  defined with DEFINE-OPTS) option. Use OPTION reader to get name of the
  option (string). Available restarts: USE-VALUE (substitute the option and
  try again), SKIP-OPTION (ignore the option).
  
  MISSING-ARG is thrown when some option wants an argument, but there is no
  such argument given. Use OPTION reader to get name of the
  option (string). Available restarts: USE-VALUE (supplied value will be
  used), SKIP-OPTION (ignore the option).
  
  ARG-PARSER-FAILED is thrown when some option wants an argument, it's given
  but cannot be parsed by argument parser. Use OPTION reader to get name of
  the option (string) and RAW-ARG to get raw string representing the argument
  before parsing. Available restarts: USE-VALUE (supplied value will be used),
  SKIP-OPTION (ignore the option), REPARSE-ARG (supplied string will be parsed
  instead)."
    (flet ((split-short-opts (arg)
             (if (and (> (length arg) 1)
                      (char=  #\- (char arg 0))
                      (char/= #\- (char arg 1)))
                 (mapcar (lambda (c) (format nil "-~c" c))
                         (cdr (coerce arg 'list)))
                 (list arg)))
           (shortp (opt)
             (and (= (length opt) 2)
                  (char=  #\- (char opt 0))))
           (longp (opt)
             (and (> (length opt) 2)
                  (char= #\- (char opt 0))
                  (char= #\- (char opt 1)))))
      (do ((tokens (mapcan #'split-short-opts
                           (or options (cdr (argv))))
                   (cdr tokens))
           pending-arg ; don't forget about --file=blah syntax
           result)
          ((null tokens) (nreverse result))
        (let ((item (car tokens)))
          nil))))
  
  (defun describe (&key prefix suffix (stream *standard-output*))
    "Return string describing options of the program that were defined with
  