(defmacro case-it (keyform &body cases)
  `(let ((it ,keyform))
     (case it ,@cases)))

(defun match% (pattern string start end)
  (macrolet ((match%% (i)
               `(match% pattern string ,i end))
             (next-pattern ()
               `(or (pop pattern) (error "Pattern is incorrect"))))
    (cond ((null pattern) (= start end))
          ((= start end)  nil)
          (t
           (case-it (next-pattern)
             (#\? (match%% (1+ start)))
             (#\\ (and (eql (aref string start)
                            (next-pattern))
                       (match%% (1+ start))))
             (#\* (loop :for i :from start :to end
                        :for match-p := (match%% i) :until match-p
                        :finally (return match-p)))
             (t   (and (eql it (aref string start))
                       (match%% (1+ start)))))))))

(defun match (pattern string &key (start 0) (end (length string)))
  (match% (coerce pattern 'list) string start end))

(loop :for (s r) :on '("abcd" nil
                       "aabcd" t
                       "a?bcd" t
                       "aa?bxcxd" t
                       "aa?bxcd" t) :by #'cddr
    :for x := (match "a*?b*c*d" s) :do
    (format t "~:[FAIL~;OK~] ~:S: expected ~:[false~;true~]~%" (eq r x) s r))