+ ,@body
+ (write-string ,close *html-stream*)))
+
+
+(defun attribute-name-string (name)
+ (etypecase name
+ (symbol (string-downcase (symbol-name name)))
+ (string name)))
+
+(defun process-attributes (args)
+ (flet ((write-attribute-name-forms (name)
+ `((write-char #\space *html-stream*)
+ (write-string ,(attribute-name-string name)
+ *html-stream*)))
+ (write-separator-forms ()
+ '((write-char #\= *html-stream*)
+ (write-char #\" *html-stream*))))
+ (do* ((xx args (cddr xx))
+ (res)
+ (name (first xx) (first xx))
+ (value (second xx) (second xx)))
+ ((null xx)
+ (nreverse res))
+ (case name
+ (:fformat
+ (unless (and (listp value)
+ (>= (length value) 2))
+ (error ":fformat must be given a list at least 2 elements"))
+ (mapcar (lambda (f) (push f res))
+ (write-attribute-name-forms (first value)))
+ (mapcar (lambda (f) (push f res))
+ (write-separator-forms))
+ (push `(fformat *html-stream* ,(second value) ,@(cddr value))
+ res)
+ (push `(write-char #\" *html-stream*) res))
+ (:format
+ (unless (and (listp value) (>= (length value) 2))
+ (error ":format must be given a list at least 2 elements"))
+ (mapcar (lambda (f) (push f res))
+ (write-attribute-name-forms (first value)))
+ (push `(prin1-safe-http-string
+ (format nil ,(second value) ,@(cddr value)))
+ res))
+ (:optional
+ (let ((eval-if (gensym "EVAL-IF-")))
+ (push `(let ((,eval-if ,(second value)))
+ (when ,eval-if
+ ,@(write-attribute-name-forms (first value))
+ (prin1-safe-http-string ,eval-if)))
+ res)))
+ (:if
+ (unless (and (listp value)
+ (>= (length value) 3)
+ (<= (length value) 4))
+ (error ":if must be given a list with 3 and 4 elements"))
+ (let ((eval-if (gensym "EVAL-IF-")))
+ (push `(let ((,eval-if ,(second value)))
+ ,@(write-attribute-name-forms (first value))
+ (prin1-safe-http-string
+ (if ,eval-if
+ ,(third value)
+ ,(fourth value))))
+ res)))
+ (:when
+ (unless (and (listp value)
+ (= (length value) 3))
+ (error ":when must be given a list with 3 elements"))
+ (push `(when ,(second value)
+ ,@(write-attribute-name-forms (first value))
+ (prin1-safe-http-string ,(third value)))
+ res))
+ (t
+ (mapcar (lambda (f) (push f res))
+ (write-attribute-name-forms name))
+ (push `(prin1-safe-http-string ,value) res))))))