<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array">
    <added>
      <filename>src/blog/feed.lisp</filename>
    </added>
    <added>
      <filename>teepeedee2-test.asd</filename>
    </added>
  </added>
  <modified type="array">
    <modified>
      <diff>@@ -22,13 +22,23 @@
     (my set-page))
   me)
 
+(my-defun blog ready-entries (&amp;key (start 0))
+	  (subseq (remove-if-not 'entry-ready (my entries)) start))
+
+(my-defun blog feed-url ()
+	  (byte-vector-cat (my link-base) &quot;feed.atom&quot;))
+
 (my-defun blog set-page ()
   (with-site ((my site))
+    (defpage-lambda (my feed-url)
+	(lambda ()
+	  (my feed)))
+
     (defpage-lambda (my link-base) 
 	(lambda(&amp;key n)
-	  (webapp (my name)
+	  (webapp ((my name) :head-contents (&lt;link :rel &quot;alternate&quot; :type &quot;application/atom+xml&quot; :href (my feed-url)))
 	    (let ((n (byte-vector-parse-integer n)))
-	      (let ((entries (subseq (remove-if-not 'entry-ready (my entries)) n)) (count 10))
+	      (let ((entries (my ready-entries :start n)) (count 10))
 		(&lt;div :class &quot;blog&quot;
 		      (loop while entries
 			    repeat count
@@ -40,3 +50,7 @@
 			(&lt;p :class &quot;next-entries&quot; (&lt;a :href (page-link (my link-base) :n (force-byte-vector (+ n count))) &quot;More entries&quot;))))))))
       ((n (force-byte-vector 0))))))
     
+(my-defun blog last-updated ()
+	  (loop for e in (my entries)
+		when (entry-ready e)
+		maximizing (entry-time e)))
\ No newline at end of file</diff>
      <filename>src/blog/blog.lisp</filename>
    </modified>
    <modified>
      <diff>@@ -37,9 +37,8 @@
 
 (defun time-string (&amp;optional (ut (get-universal-time)))
   (multiple-value-bind
-	(second minute hour date month year day daylight-p zone)
+	(second minute hour date month year)
       (decode-universal-time ut 0)
-    (declare (ignore day daylight-p zone))
     (format nil &quot;~4,'0D-~2,'0D-~2,'0D ~2,'0D:~2,'0D:~2,'0D GMT&quot; year month date hour minute second)))
 
 (my-defun entry filename ()
@@ -104,7 +103,7 @@
   (with-site ((its site (my blog)))
     (defpage-lambda (my url-path)
 	(lambda()
-	  (webapp (my combined-title)
+	  (webapp ((my combined-title))
 	    (output-object-to-ml me))))))
 
 (my-defun entry read-paragraphs-from-buffer (buffer)</diff>
      <filename>src/blog/entry.lisp</filename>
    </modified>
    <modified>
      <diff>@@ -1,7 +1,7 @@
 (in-package #:tpd2.game)
 
 (eval-always
-  (defconstant +suits+ '(:clubs :hearts :spades :diamonds))
+  (define-constant +suits+ '(:clubs :hearts :spades :diamonds) :test 'equal)
   (defconstant +cards-per-suit+ 13))
 
 (defstruct card </diff>
      <filename>src/game/card.lisp</filename>
    </modified>
    <modified>
      <diff>@@ -14,7 +14,6 @@
   (with-sendbuf (response)
     &quot;HTTP/1.1 &quot; code &quot; &quot; banner +newline+
     &quot;Content-Length: &quot; (sendbuf-len body) +newline+
-    &quot;Content-Type: text/html;charset=utf-8&quot; +newline+
     headers
     +newline+
     body))</diff>
      <filename>src/http/dispatcher.lisp</filename>
    </modified>
    <modified>
      <diff>@@ -54,7 +54,8 @@
   (timeout-set (my timeout) delay)
   (values))
 
-(defconstant +newline+ (force-byte-vector #(13 10)))
+(define-constant +newline+ (force-byte-vector #(13 10))
+  :test 'equalp)
 
 (my-defun con set-callback (func)
   (setf (my ready-callback) func))</diff>
      <filename>src/io/con.lisp</filename>
    </modified>
    <modified>
      <diff>@@ -146,8 +146,8 @@
 (def-simple-syscall close
     (fd :int))
 
-(defconstant +SIG_IGN+ (cffi:make-pointer 1))
-(defconstant +SIG_DFL+ (cffi:make-pointer 0))
+(define-constant +SIG_IGN+ (cffi:make-pointer 1) :test 'cffi:pointer-eq)
+(define-constant +SIG_DFL+ (cffi:make-pointer 0)  :test 'cffi:pointer-eq)
 (defconstant +SIGPIPE+ 13)
 
 (cffi:defcfun (&quot;signal&quot; syscall-signal)</diff>
      <filename>src/io/syscalls.lisp</filename>
    </modified>
    <modified>
      <diff>@@ -37,7 +37,7 @@
 	  do (setf (aref ret i) arg))
     ret))
 
-(defconstant +byte-to-digit-table+
+(define-constant +byte-to-digit-table+
   (make-array 256 :element-type '(integer -1 36) 
 	      :initial-contents (loop for i from 0 below 256 
 				      collect 
@@ -52,7 +52,8 @@
 					(or (in-range #\a #\z i 10)
 					    (in-range #\A #\Z i 10)
 					    (in-range #\0 #\9 i 0)
-					    -1)))))
+					    -1))))
+  :test 'equalp)
 
 (declaim-defun-consistent-ftype byte-to-digit ((unsigned-byte 8)) (integer -1 36))
 (defun-consistent byte-to-digit (byte)</diff>
      <filename>src/lib/byte-vector.lisp</filename>
    </modified>
    <modified>
      <diff>@@ -63,3 +63,7 @@
   `(debug-assert (not 'reached-here)))
 
 
+(defmacro defconstant-string (name value &amp;optional documentation)
+  `(define-constant ,name ,value
+     :test 'string=
+     ,@(when documentation `((:documentation ,documentation)))))
\ No newline at end of file</diff>
      <filename>src/lib/one-liners.lisp</filename>
    </modified>
    <modified>
      <diff>@@ -50,4 +50,4 @@
 
 (defun backtrace-description (err)
   (format nil &quot;ERROR ~A:~&amp;~A&quot; (with-output-to-string (*standard-output*) (describe err)) 
-	  (trivial-backtrace:get-backtrace err)))
+	  (trivial-backtrace:backtrace-string)))</diff>
      <filename>src/lib/utils.lisp</filename>
    </modified>
    <modified>
      <diff>@@ -2,7 +2,7 @@
 
 ; From http://www.w3.org/TR/REC-CSS2/propidx.html
 ; if you want more just use &quot;strings&quot;
-(defconstant +css-properties+ '(
+(define-constant +css-properties+ '(
 				:azimuth
 				:background
 				:background-color 
@@ -147,7 +147,8 @@
 				:x-opacity
 				:x-column-width
 				:x-column-gap
-				))
+				)
+  :test 'equalp)
 
 ;; Write CSS like this: ((&quot;p.asdfsaf&quot; &quot;p + p&quot;) :property &quot;value&quot; :property &quot;value&quot;)
 </diff>
      <filename>src/ml/css.lisp</filename>
    </modified>
    <modified>
      <diff>@@ -5,7 +5,7 @@
 (defpackage #:teepeedee2.lib
   (:nicknames #:tpd2.lib)
   (:use #:common-lisp #:iter #:cl-irregsexp.bytestrings)
-  (:import-from #:cl-utilities #:with-unique-names)
+  (:import-from #:alexandria #:with-unique-names #:define-constant)
   (:import-from #:trivial-garbage #:finalize #:cancel-finalization)
   (:import-from #:cl-cont #:call/cc #:with-call/cc)
   (:import-from #:cl-irregsexp 
@@ -48,7 +48,8 @@
 
    #:with-unique-names
    #:once-only
-
+   #:define-constant
+   #:defconstant-string
 
    #:copy-byte-vector
    #:make-byte-vector
@@ -236,6 +237,8 @@
    #:js-html-script
    #:js-attrib
    #:js-to-string
+
+   #:w3c-timestring
 ))
 
 (eval-when (:compile-toplevel :load-toplevel :execute)</diff>
      <filename>src/packages.lisp</filename>
    </modified>
    <modified>
      <diff>@@ -26,7 +26,7 @@
 	      (t my-best-card))))))
 
 
-(defconstant +best-starts+ #(0 0 0 0 0 0 0 0 0 2 2 2 2 2 2 2 0 2 2 2 2 2 2 2 0 2 2 0 2 2 2 2 0 2 2 2
+(define-constant +best-starts+ #(0 0 0 0 0 0 0 0 0 2 2 2 2 2 2 2 0 2 2 2 2 2 2 2 0 2 2 0 2 2 2 2 0 2 2 2
   0 0 2 2 0 2 2 2 0 0 0 2 0 2 2 2 2 0 0 0 0 2 2 2 2 2 0 0 0 2 2 2 2 2 2 2
   2 0 1 1 1 1 1 1 2 1 2 1 1 2 2 2 2 1 1 0 1 1 2 2 2 1 1 1 0 1 1 2 2 1 2 1
   1 0 1 2 2 1 2 2 1 1 0 1 2 1 2 2 2 2 1 0 0 2 2 2 2 2 2 2 2 1 2 1 1 2 2 2
@@ -41,10 +41,11 @@
   0 0 0 0 0 0 0 0 0 1 1 1 1 1 0 0 0 2 2 2 2 2 0 0 2 1 2 2 2 2 1 0 2 2 1 2
   2 1 1 0 2 2 2 1 2 1 1 0 2 2 2 2 1 1 1 0 2 2 1 1 1 1 1 0 0 1 1 1 1 1 0 0
   0 0 0 0 0 0 0 0)
-  &quot;Given the hand described by the index, 0 means play the highest card, 1 the middle card and 2 the lowest card first&quot;)
+  :documentation &quot;Given the hand described by the index, 0 means play the highest card, 1 the middle card and 2 the lowest card first&quot;
+  :test 'equalp)
 
 
-(defconstant +three-card-win-probabilities+ 
+(define-constant +three-card-win-probabilities+ 
   #(0 1/1218 1/522 11/3654 5/1218 19/3654 23/3654 3/406 1/1218 79/3654 44/1827
     71/1827 122/1827 197/1827 296/1827 419/1827 1/522 44/1827 101/3654 82/1827
     5/63 8/63 49/261 478/1827 11/3654 71/1827 82/1827 143/1827 64/609 323/1827
@@ -100,7 +101,8 @@
     298/609 55/87 179/261 1375/1827 1457/1827 1651/1827 1 892/1827 49/87
     170/261 1375/1827 1468/1827 1574/1827 1720/1827 1 373/609 132/203 428/609
     1457/1827 1574/1827 545/609 1765/1827 1 2609/3654 1441/1827 1558/1827
-    1651/1827 1720/1827 1765/1827 3575/3654 1 1 1 1 1 1 1 1 1))
+    1651/1827 1720/1827 1765/1827 3575/3654 1 1 1 1 1 1 1 1 1)
+  :test 'equalp)
 
 (my-defun truc-player win-probability ()
   &quot;Rough and ready win probability not taking into account who starts or anything much&quot;</diff>
      <filename>src/truc/robots.lisp</filename>
    </modified>
    <modified>
      <diff>@@ -1,9 +1,10 @@
 (in-package #:tpd2.game.truc)
 
-(defconstant +truc-ranking+ '(6 7 0 12 11 10 9 8))
-(defconstant +truc-deck+ 
-  (mapcar 'card-number 
-	  (loop for s in +suits+ append (loop for i in +truc-ranking+ collect (make-card :suit s :value i)))))
+(define-constant +truc-ranking+ '(6 7 0 12 11 10 9 8) :test 'equal)
+(define-constant +truc-deck+ 
+  (map 'vector 'card-number 
+	  (loop for s in +suits+ append (loop for i in +truc-ranking+ collect (make-card :suit s :value i))))
+  :test 'equalp)
 (defconstant +truc-winning-stack+ 12)
 
 (defgame truc ()</diff>
      <filename>src/truc/truc.lisp</filename>
    </modified>
    <modified>
      <diff>@@ -1,14 +1,14 @@
 (in-package #:tpd2.webapp)
 
-(defconstant +channel-page-name+ &quot;/*channel*&quot;)
+(defconstant-string +channel-page-name+ &quot;/*channel*&quot;)
 
-(defconstant +action-page-name+ &quot;/*action*&quot;)
+(defconstant-string +action-page-name+ &quot;/*action*&quot;)
 
-(defconstant +action-form-class+ &quot;-action-form-&quot;)
-(defconstant +action-link-class+ &quot;-action-link-&quot;)
-(defconstant +replace-link-class+ &quot;-replace-link-&quot;)
+(defconstant-string +action-form-class+ &quot;-action-form-&quot;)
+(defconstant-string +action-link-class+ &quot;-action-link-&quot;)
+(defconstant-string +replace-link-class+ &quot;-replace-link-&quot;)
 
-(defconstant +html-id-async-status+ &quot;-async-status-&quot;)
-(defconstant +html-class-scroll-to-bottom+ &quot;-scroll-to-bottom-&quot;)
-(defconstant +html-class-collapsed+ &quot;-collapsed-&quot;)
+(defconstant-string +html-id-async-status+ &quot;-async-status-&quot;)
+(defconstant-string +html-class-scroll-to-bottom+ &quot;-scroll-to-bottom-&quot;)
+(defconstant-string +html-class-collapsed+ &quot;-collapsed-&quot;)
 </diff>
      <filename>src/webapp/html-constants.lisp</filename>
    </modified>
    <modified>
      <diff>@@ -1,6 +1,6 @@
 (in-package #:tpd2.webapp)
 
-(defconstant +names+ '(&quot;Mildred&quot;
+(define-constant +names+ #(&quot;Mildred&quot;
 		       &quot;Henry&quot;
 		       &quot;Alice&quot;
 		       &quot;Walter&quot;
@@ -1980,7 +1980,8 @@
 		       &quot;Lenord&quot;
 		       &quot;Macy&quot;
 		       &quot;Arden&quot;
-		       &quot;Paralee&quot;))
+		       &quot;Paralee&quot;)
+  :test 'equalp)
 
 (defun-speedy random-letter ()
   (code-char (+ (char-code #\A) (random 26))))</diff>
      <filename>src/webapp/names.lisp</filename>
    </modified>
    <modified>
      <diff>@@ -1,14 +1,16 @@
 (in-package #:tpd2.webapp)
 
 (defvar *webapp-frame*)
-(defconstant +webapp-frame-id-param+ (force-byte-vector &quot;.webapp-frame.&quot;))
+(define-constant +webapp-frame-id-param+ (force-byte-vector &quot;.webapp-frame.&quot;)
+  :test 'equalp)
 
-(defconstant +web-safe-chars+ 
+(define-constant +web-safe-chars+ 
   (force-byte-vector 
    (append (loop for c from (char-code #\A) to (char-code #\Z) collect c)
 	   (loop for c from (char-code #\a) to (char-code #\z) collect c)
 	   (loop for c from (char-code #\0) to (char-code #\9) collect c)
-	   (mapcar 'char-code '(#\- #\_)))))
+	   (mapcar 'char-code '(#\- #\_))))
+  :test 'equalp)
 
 (defun generate-args-for-defpage-from-params (params-var defaulting-lambda-list)
   (let ((arg-names (mapcar 'force-first defaulting-lambda-list))</diff>
      <filename>src/webapp/page.lisp</filename>
    </modified>
    <modified>
      <diff>@@ -1,8 +1,8 @@
 (in-package #:tpd2.webapp)
 
 (eval-always
-  (defconstant +site-customization-funcs+ '(page-head page-body-start page-body-footer))
-  (defconstant +site-customization-func-args+ '(title)))
+  (define-constant +site-customization-funcs+ '(page-head page-body-start page-body-footer) :test 'equalp)
+  (define-constant +site-customization-func-args+ '(title) :test 'equalp))
 
 (defparameter *current-site* nil)
 
@@ -14,9 +14,9 @@
   (runtime-name '*current-site*)
   (dispatcher *default-dispatcher*)
   (page-head (lambda(title)
-	       `(&lt;head
-		  (&lt;title ,title)
-		  (webapp-default-page-head-contents))))
+	       `(with-ml-output
+		  (&lt;title ,title))
+		  (webapp-default-page-head-contents)))
   (page-body-start 
    (lambda(title)
      `(&lt;h1 ,title)))</diff>
      <filename>src/webapp/site.lisp</filename>
    </modified>
    <modified>
      <diff>@@ -13,32 +13,38 @@
 (defmacro ml-to-byte-vector (ml)
   `(sendbuf-to-byte-vector (with-ml-output-start ,ml)))
 
-(defmacro webapp-ml (title &amp;body body)
+(defmacro webapp-ml (title-and-options &amp;body body)
   (with-unique-names (title-ml)
-    `(let ((,title-ml
-	    (ml-to-byte-vector ,title)))
-       (setf (webapp-frame-var 'actions) nil)
-       (with-frame-site
-	   (with-ml-output-start 
+    (destructuring-bind (title &amp;key head-contents)
+	(force-list title-and-options)
+      `(let ((,title-ml
+	      (ml-to-byte-vector ,title)))
+	 (setf (webapp-frame-var 'actions) nil)
+	 (values
+	  (with-frame-site
+	      (with-ml-output-start 
 	     (output-raw-ml &quot;&lt;!DOCTYPE HTML PUBLIC \&quot;-//W3C//DTD HTML 4.01 Transitional//EN\&quot;&quot; 
-			  &quot; \&quot;http://www.w3.org/TR/html4/loose.dtd\&quot;&gt;&quot;)
-	     (&lt;html
-	       (current-site-call page-head  ,title-ml)
-	       (&lt;body
-		 (current-site-call page-body-start ,title-ml)
-		 ,@body
-		 (current-site-call page-body-footer ,title-ml))))))))
-  
-(defmacro webapp-lambda (title &amp;body body)
+			    &quot; \&quot;http://www.w3.org/TR/html4/loose.dtd\&quot;&gt;&quot;)
+		(&lt;html
+		 (&lt;head
+		  (current-site-call page-head ,title-ml)
+		  ,head-contents)
+		 (&lt;body
+		  (current-site-call page-body-start ,title-ml)
+		  ,@body
+		  (current-site-call page-body-footer ,title-ml)))))
+	  (byte-vector-cat &quot;Content-Type: text/html;charset=utf-8&quot; tpd2.io:+newline+))))))
+
+(defmacro webapp-lambda (title-and-options &amp;body body)
   (with-unique-names (l)
   `(labels ((,l ()
 	      (setf (frame-current-page (webapp-frame)) 
 		    #',l)
-	      (webapp-ml ,title ,@body)))
+	      (webapp-ml ,title-and-options ,@body)))
      #',l)))
 
-(defmacro webapp (title &amp;body body)
-  `(funcall (webapp-lambda ,title ,@body)))
+(defmacro webapp (title-and-options &amp;body body)
+  `(funcall (webapp-lambda ,title-and-options ,@body)))
 
 (defmacro link-to-webapp (title &amp;body body)
   (with-unique-names (title-ml)</diff>
      <filename>src/webapp/webapp.lisp</filename>
    </modified>
    <modified>
      <diff>@@ -13,6 +13,7 @@
 (setf sb-ext:*inline-expansion-limit* 50)
 
 (pushnew &quot;../cl-irregsexp/&quot; asdf:*central-registry* :test #'equal)
+(pushnew &quot;../trivial-backtrace/&quot; asdf:*central-registry* :test #'equal)
 
 #+tpd2-debug
 (progn
@@ -76,7 +77,8 @@
 							   (:file &quot;define-dtd&quot; :depends-on (&quot;object-to-ml&quot;))
 							   (:file &quot;css&quot; :depends-on (&quot;html&quot;))
 							   (:file &quot;js&quot; :depends-on (&quot;html&quot;))
-							   (:file &quot;html&quot; :depends-on (&quot;define-dtd&quot;))))
+							   (:file &quot;html&quot; :depends-on (&quot;define-dtd&quot;))
+							   (:file &quot;atom&quot; :depends-on (&quot;define-dtd&quot;))))
 				     (:module :datastore
 					      :depends-on (:lib)
 					      :components ((:file &quot;datastore&quot;)))
@@ -104,26 +106,19 @@
 				     (:module :blog
 					      :depends-on (:webapp :ml :datastore)
 					      :components ((:file &quot;entry&quot;)
+							   (:file &quot;feed&quot; :depends-on (&quot;blog&quot;))
 							   (:file &quot;blog&quot; :depends-on (&quot;entry&quot;))))
 				     (:module :truc
 					      :depends-on (:game)
 					      :components ( (:file &quot;truc&quot;) (:file &quot;web&quot; :depends-on (&quot;truc&quot;))
-							    (:file &quot;robots&quot; :depends-on (&quot;truc&quot;))))))
-
-	       (:module :t 
-			:depends-on (:src)
-			:components (
-				     (:file &quot;suite&quot;)
-				     (:file &quot;io&quot; :depends-on (&quot;suite&quot;))
-				     (:file &quot;http&quot; :depends-on (&quot;suite&quot;))
-				     )))
+							    (:file &quot;robots&quot; :depends-on (&quot;truc&quot;)))))))
   :depends-on (
 	       :trivial-garbage
 	       :cl-cont
 	       :cffi
 	       :iterate
-	       :fiveam
-	       :cl-utilities
+	       :alexandria
 	       :cl-irregsexp
 	       :trivial-backtrace
 	       :parenscript))
+</diff>
      <filename>teepeedee2.asd</filename>
    </modified>
  </modified>
  <removed type="array"/>
  <parents type="array">
    <parent>
      <id>6ea615648a7c1d945964a72305666c985d3d6cc3</id>
    </parent>
  </parents>
  <author>
    <name>John Fremlin</name>
    <email>john@fremlin.org</email>
  </author>
  <url>http://github.com/vii/teepeedee2/commit/bf7ab7f7e0dc7c060fecac69d90ea0ca0c481ee8</url>
  <id>bf7ab7f7e0dc7c060fecac69d90ea0ca0c481ee8</id>
  <committed-date>2009-05-11T18:35:56-07:00</committed-date>
  <authored-date>2009-05-11T18:35:56-07:00</authored-date>
  <message>added atom feeds (still rather weird)</message>
  <tree>1f99db45574bb3f95fa5441daaadc6d469f4a4ee</tree>
  <committer>
    <name>John Fremlin</name>
    <email>john@fremlin.org</email>
  </committer>
</commit>
