- optname
- (mapcar #'opt-long-name matches))))
- (process-option (car matches)
- optname
- negp
- :arg (and eqpos
- (subseq arg (1+ eqpos)))))))
- (with-simple-restart (skip-option "Skip this bogus option.")
- (cond
- ;;
- ;; We're embroiled in short options: handle them.
- ((op-short-opt op)
- (if (>= (op-short-opt-index op) (length (op-short-opt op)))
- (setf (op-short-opt op) nil)
- (let* ((str (op-short-opt op))
- (i (op-short-opt-index op))
- (ch (char str i))
- (negp (op-short-opt-neg-p op))
- (name (format nil "~C~A" (if negp #\+ #\-) ch))
- (o (find ch (op-options op) :key #'opt-short-name)))
- (incf i)
- (setf (op-short-opt-index op) i)
- (when (or (not o)
- (and negp (not (opt-negated-tag o))))
- (option-parse-error "Unknown option `~A'" name))
- (process-option o
- name
- negp
- :argfunc
- (and (< i (length str))
- (lambda ()
- (prog1
- (subseq str i)
- (setf (op-short-opt op)
- nil))))))))
- ;;
- ;; End of the list. Say we've finished.
- ((not (more-args-p))
- (finished))
- ;;
- ;; Process the next option.
- (t
- (let ((arg (peek-arg)))
- (cond
- ;;
- ;; Non-option. Decide what to do.
- ((or (<= (length arg) 1)
- (and (char/= (char arg 0) #\-)
- (or (char/= (char arg 0) #\+)
- (not (op-negated-p op)))))
- (case (op-non-option op)
- (:skip (skip-arg))
- (:stop (finished))
- (:return (eat-arg)
- (ret :non-option arg))
- (t (eat-arg)
- (funcall (op-non-option op) arg))))
- ;;
- ;; Double-hyphen. Stop right now.
- ((string= arg "--")
- (eat-arg)
- (finished))
- ;;
- ;; Numbers. Check these before long options, since `--43' is
- ;; not a long option.
- ((and (op-numeric-p op)
- (or (char= (char arg 0) #\-)
- (op-negated-numeric-p op))
- (or (and (digit-char-p (char arg 1))
- (every #'digit-char-p (subseq arg 2)))
- (and (or (char= (char arg 1) #\-)
- (char= (char arg 1) #\+))
- (>= (length arg) 3)
- (digit-char-p (char arg 2))
- (every #'digit-char-p (subseq arg 3)))))
- (eat-arg)
- (let ((negp (char= (char arg 0) #\+))
- (num (parse-integer arg :start 1)))
- (when (and negp (eq (op-negated-numeric-p op) :-))
- (setf num (- num))
- (setf negp nil))
- (let ((how (if negp
- (op-negated-numeric-p op)
- (op-numeric-p op))))
- (if (functionp how)
- (funcall how num)
- (ret (if negp :negated-numeric :numeric) num)))))
- ;;
- ;; Long option. Find the matching option-spec and process
- ;; it.
- ((and (char= (char arg 0) #\-)
- (char= (char arg 1) #\-))
- (eat-arg)
- (process-long-option arg 2 nil))
- ;;
- ;; Short options. All that's left.
- (t
- (eat-arg)
- (let ((negp (char= (char arg 0) #\+))
- (ch (char arg 1)))
- (cond ((and (op-long-only-p op)
- (not (member ch (op-options op)
- :key #'opt-short-name)))
- (process-long-option arg 1 negp))
- (t
- (setf (op-short-opt op) arg
- (op-short-opt-index op) 1
- (op-short-opt-neg-p op) negp)))))))))))))
+ optname
+ (mapcar #'opt-long-name matches))))
+ (process-option (car matches)
+ optname
+ negp
+ :arg (and eqpos
+ (subseq arg (1+ eqpos)))))))
+ (catch 'option-parse-return
+ (loop
+ (with-simple-restart (skip-option "Skip this bogus option.")
+ (cond
+ ;;
+ ;; We're embroiled in short options: handle them.
+ ((op-short-opt op)
+ (if (>= (op-short-opt-index op) (length (op-short-opt op)))
+ (setf (op-short-opt op) nil)
+ (let* ((str (op-short-opt op))
+ (i (op-short-opt-index op))
+ (ch (char str i))
+ (negp (op-short-opt-neg-p op))
+ (name (format nil "~C~A" (if negp #\+ #\-) ch))
+ (o (find ch (op-options op) :key #'opt-short-name)))
+ (incf i)
+ (setf (op-short-opt-index op) i)
+ (when (or (not o)
+ (and negp (not (opt-negated-tag o))))
+ (option-parse-error "Unknown option `~A'" name))
+ (process-option o
+ name
+ negp
+ :argfunc
+ (and (< i (length str))
+ (lambda ()
+ (prog1
+ (subseq str i)
+ (setf (op-short-opt op)
+ nil))))))))
+ ;;
+ ;; End of the list. Say we've finished.
+ ((not (more-args-p))
+ (finished))
+ ;;
+ ;; Process the next option.
+ (t
+ (let ((arg (peek-arg)))
+ (cond
+ ;;
+ ;; Non-option. Decide what to do.
+ ((or (<= (length arg) 1)
+ (and (char/= (char arg 0) #\-)
+ (or (char/= (char arg 0) #\+)
+ (not (op-negated-p op)))))
+ (case (op-non-option op)
+ (:skip (skip-arg))
+ (:stop (finished))
+ (:return (eat-arg)
+ (ret :non-option arg))
+ (t (eat-arg)
+ (funcall (op-non-option op) arg))))
+ ;;
+ ;; Double-hyphen. Stop right now.
+ ((string= arg "--")
+ (eat-arg)
+ (finished))
+ ;;
+ ;; Numbers. Check these before long options, since `--43'
+ ;; is not a long option.
+ ((and (op-numeric-p op)
+ (or (char= (char arg 0) #\-)
+ (op-negated-numeric-p op))
+ (or (and (digit-char-p (char arg 1))
+ (every #'digit-char-p (subseq arg 2)))
+ (and (or (char= (char arg 1) #\-)
+ (char= (char arg 1) #\+))
+ (>= (length arg) 3)
+ (digit-char-p (char arg 2))
+ (every #'digit-char-p (subseq arg 3)))))
+ (eat-arg)
+ (let ((negp (char= (char arg 0) #\+))
+ (num (parse-integer arg :start 1)))
+ (when (and negp (eq (op-negated-numeric-p op) :-))
+ (setf num (- num))
+ (setf negp nil))
+ (let ((how (if negp
+ (op-negated-numeric-p op)
+ (op-numeric-p op))))
+ (if (functionp how)
+ (funcall how num)
+ (ret (if negp :negated-numeric :numeric) num)))))
+ ;;
+ ;; Long option. Find the matching option-spec and process
+ ;; it.
+ ((and (char= (char arg 0) #\-)
+ (char= (char arg 1) #\-))
+ (eat-arg)
+ (process-long-option arg 2 nil))
+ ;;
+ ;; Short options. All that's left.
+ (t
+ (eat-arg)
+ (let ((negp (char= (char arg 0) #\+))
+ (ch (char arg 1)))
+ (cond ((and (op-long-only-p op)
+ (not (member ch (op-options op)
+ :key #'opt-short-name)))
+ (process-long-option arg 1 negp))
+ (t
+ (setf (op-short-opt op) arg
+ (op-short-opt-index op) 1
+ (op-short-opt-neg-p op) negp))))))))))))))