From hhubner at common-lisp.net Fri Feb 1 10:22:15 2008 From: hhubner at common-lisp.net (hhubner at common-lisp.net) Date: Fri, 1 Feb 2008 05:22:15 -0500 (EST) Subject: [bknr-cvs] r2435 - branches/trunk-reorg/projects/quickhoney/src Message-ID: <20080201102215.BFFA8310A3@common-lisp.net> Author: hhubner Date: Fri Feb 1 05:22:06 2008 New Revision: 2435 Modified: branches/trunk-reorg/projects/quickhoney/src/image.lisp branches/trunk-reorg/projects/quickhoney/src/init.lisp Log: Fix default external format, we're using UTF-8. Display image in encoded content of RSS feed. Modified: branches/trunk-reorg/projects/quickhoney/src/image.lisp ============================================================================== --- branches/trunk-reorg/projects/quickhoney/src/image.lisp (original) +++ branches/trunk-reorg/projects/quickhoney/src/image.lisp Fri Feb 1 05:22:06 2008 @@ -6,6 +6,13 @@ :index-reader images-for-client :index-keys all-clients))) +(defmethod rss-item-pub-date ((item quickhoney-image)) + (blob-timestamp item)) + +(defmethod rss-item-encoded-content ((item quickhoney-image)) + (with-output-to-string (s) + (html-stream s ((:img :src (format nil "http://~A/image/~A" (header-in :host) (store-object-id item))))))) + (defvar *last-image-upload-timestamp* 0) (defmethod initialize-transient-instance :after ((image quickhoney-image)) Modified: branches/trunk-reorg/projects/quickhoney/src/init.lisp ============================================================================== --- branches/trunk-reorg/projects/quickhoney/src/init.lisp (original) +++ branches/trunk-reorg/projects/quickhoney/src/init.lisp Fri Feb 1 05:22:06 2008 @@ -8,6 +8,7 @@ "/usr/lib/libssl.so" "/usr/local/lib/libgd.so" "/home/hans/bknr-svn/thirdparty/cl-gd-0.5.6/cl-gd-glue.so")) + (setf *hunchentoot-default-external-format* (flex:make-external-format :utf-8 :eol-style :lf)) (when *store* (close-store)) (make-instance 'store From hhubner at common-lisp.net Fri Feb 1 10:56:53 2008 From: hhubner at common-lisp.net (hhubner at common-lisp.net) Date: Fri, 1 Feb 2008 05:56:53 -0500 (EST) Subject: [bknr-cvs] r2436 - in branches/trunk-reorg: bknr/datastore/src projects/quickhoney/src Message-ID: <20080201105653.B5C481B022@common-lisp.net> Author: hhubner Date: Fri Feb 1 05:56:52 2008 New Revision: 2436 Modified: branches/trunk-reorg/bknr/datastore/src/bknr-utils.asd branches/trunk-reorg/projects/quickhoney/src/load.lisp Log: Quickhoney startup fixes. Modified: branches/trunk-reorg/bknr/datastore/src/bknr-utils.asd ============================================================================== --- branches/trunk-reorg/bknr/datastore/src/bknr-utils.asd (original) +++ branches/trunk-reorg/bknr/datastore/src/bknr-utils.asd Fri Feb 1 05:56:52 2008 @@ -29,7 +29,7 @@ (:file "class" :depends-on ("package" "utils")) #+(or cmu allegro openmcl sbcl) (:file "smbpasswd" :depends-on ("utils")) - (:file "actor" :depends-on ("utils")) + #-sbcl (:file "actor" :depends-on ("utils")) (:file "reader" :depends-on ("utils")) (:file "crypt-md5" :depends-on ("utils")) (:file "capability" :depends-on ("utils")) Modified: branches/trunk-reorg/projects/quickhoney/src/load.lisp ============================================================================== --- branches/trunk-reorg/projects/quickhoney/src/load.lisp (original) +++ branches/trunk-reorg/projects/quickhoney/src/load.lisp Fri Feb 1 05:56:52 2008 @@ -3,6 +3,7 @@ (asdf:oos 'asdf:load-op :quickhoney) (asdf:oos 'asdf:load-op :swank) -(swank::create-swank-server 4085 :spawn #'swank::simple-announce-function t) +(swank::create-server :port 4085) +#+cmu (mp::startup-idle-and-top-level-loops) From hhubner at common-lisp.net Fri Feb 1 12:01:52 2008 From: hhubner at common-lisp.net (hhubner at common-lisp.net) Date: Fri, 1 Feb 2008 07:01:52 -0500 (EST) Subject: [bknr-cvs] r2437 - in branches/trunk-reorg/projects/quickhoney/website: static templates Message-ID: <20080201120152.B613E50009@common-lisp.net> Author: hhubner Date: Fri Feb 1 07:01:51 2008 New Revision: 2437 Modified: branches/trunk-reorg/projects/quickhoney/website/static/javascript.js branches/trunk-reorg/projects/quickhoney/website/static/styles.css branches/trunk-reorg/projects/quickhoney/website/templates/index.xml Log: Fix navigation - This was very simple, and I really regret that using achors to store navigation information had not occured to me two years ago. One can now deep link into the Quickhoney site, a feature that is used by the RSS feed. Also, inner-site navigation updates the anchor now, making it possible to store links to anything. Modified: branches/trunk-reorg/projects/quickhoney/website/static/javascript.js ============================================================================== --- branches/trunk-reorg/projects/quickhoney/website/static/javascript.js (original) +++ branches/trunk-reorg/projects/quickhoney/website/static/javascript.js Fri Feb 1 07:01:51 2008 @@ -531,14 +531,14 @@ if (current_directory) { if (current_subdirectory) { - path_links[0] = '' + current_directory + ''; + path_links[0] = '' + current_directory + ''; } else { path_links[0] = current_directory; } } if (current_subdirectory) { if (current_image) { - path_links[1] = '' + current_subdirectory + ''; + path_links[1] = '' + current_subdirectory + ''; } else { path_links[1] = current_subdirectory; } @@ -646,6 +646,7 @@ } else { buttons[i].style.visibility = 'hidden'; buttons[i].src = new_image; + buttons[i].parentNode.href = '#' + current_directory + '/' + subdirectory_name; eval("button_links[i].onclick = function onclick(event) { subdirectory('" + subdirectory_name + "'); }"); } } @@ -734,13 +735,16 @@ if (query_result_pages.length > 1) { if (current_page > 0) { - push(result_links, '<<'); + push(result_links, + '<<'); } else { push(result_links, '<<'); } var last_page = position_to_page(query_result.length - 1); if (current_page < last_page) { - push(result_links, '>>'); + push(result_links, '>>'); } else { push(result_links, '>>'); } @@ -764,7 +768,8 @@ if (page_number == current_page) { push(result_links, (page_number + 1).toString()); } else { - push(result_links, '' + (page_number + 1) + ''); + push(result_links, '' + (page_number + 1) + ''); } } @@ -795,7 +800,9 @@ for (var image_index = 2; image_index < row.length; image_index++) { var image = row[image_index]; thumbnail_html - += '' + += '' + '' @@ -813,15 +820,20 @@ var result_links = []; if (query_position > 0) { - push(result_links, '<<'); + push(result_links, '<<'); } else { push(result_links, '<<'); } if (query_position < (query_result.length - 1)) { - push(result_links, '>>'); + push(result_links, '>>'); } else { push(result_links, '>>'); } + document.getElementById('back_to_results_link').href = '#' + current_directory + '/' + current_subdirectory + '/' + position_to_page(query_position); document.getElementById("image_navbar").innerHTML = result_links.join(" "); document.getElementById("result_image_count").innerHTML = "result " + (query_position + 1) + " of " + query_result.length; @@ -1012,37 +1024,35 @@ } function init() { - if (document.location.href.indexOf("#debug") != -1) { - want_debugger = true; + var path = (document.location.href + "#").split("#")[1]; + + if (path) { + if (path == "debug") { + + want_debugger = true; - document.getElementById("debugger").style.visibility = 'visible'; - document.getElementById("debugger").style.left = '730px'; - document.getElementById("debugger").style.width = '400px'; - document.getElementById("debugger").style.heigth = '640px'; - } else { - document.getElementById("debugger").style.left = "1px"; - document.getElementById("debugger").style.right = "1px"; - document.getElementById("debugger").style.width = "1px"; - document.getElementById("debugger").style.height = "1px"; - } + document.getElementById("debugger").style.visibility = 'visible'; + document.getElementById("debugger").style.left = '730px'; + document.getElementById("debugger").style.width = '400px'; + document.getElementById("debugger").style.heigth = '640px'; - debug('init - path is ', document.location.href); + } else if (path == "update") { - if (document.location.href.indexOf("#update") != -1) { - if ((navigator.platform == "MacPPC") && (navigator.userAgent.indexOf("MSIE 5.") != -1)) { - alert("CMS functionality not supported on IE5/Mac"); + if ((navigator.platform == "MacPPC") && (navigator.userAgent.indexOf("MSIE 5.") != -1)) { + alert("CMS functionality not supported on IE5/Mac"); + } else { + wants_cms = true; + document.getElementById("login_form").style.visibility = 'visible'; + } + show_cms_window("login_form"); } else { - wants_cms = true; - document.getElementById("login_form").style.visibility = 'visible'; + var jump_to = path; + jump_to = jump_to.replace(/[&#].*/, ""); + document.jump_to = jump_to; } - show_cms_window("login_form"); } - if (document.location.href.indexOf("jumpto=") != -1) { - var jump_to = document.location.href.replace(/.*jumpto=/, ""); - jump_to = jump_to.replace(/[&#].*/, ""); - document.jump_to = jump_to; - } + debug('init - path is ', path); buttons = document.getElementById("directory").getElementsByTagName('img'); button_links = document.getElementById("directory").getElementsByTagName('a'); Modified: branches/trunk-reorg/projects/quickhoney/website/static/styles.css ============================================================================== --- branches/trunk-reorg/projects/quickhoney/website/static/styles.css (original) +++ branches/trunk-reorg/projects/quickhoney/website/static/styles.css Fri Feb 1 07:01:51 2008 @@ -69,10 +69,10 @@ #debugger { visibility: hidden; position: absolute; - left: 0px; - top: 36px; - width: 0px; - height: 0px; + left: 1px; + top: 1px; + width: 1px; + height: 1px; } .debugger { Modified: branches/trunk-reorg/projects/quickhoney/website/templates/index.xml ============================================================================== --- branches/trunk-reorg/projects/quickhoney/website/templates/index.xml (original) +++ branches/trunk-reorg/projects/quickhoney/website/templates/index.xml Fri Feb 1 07:01:51 2008 @@ -15,22 +15,22 @@ - + quickhoney - + pixel - + vector - + photo - + clients - + contact @@ -81,7 +81,7 @@ - back to results + back to results @@ -95,7 +95,7 @@
- + From hhubner at common-lisp.net Sat Feb 2 22:54:17 2008 From: hhubner at common-lisp.net (hhubner at common-lisp.net) Date: Sat, 2 Feb 2008 17:54:17 -0500 (EST) Subject: [bknr-cvs] r2438 - in branches/trunk-reorg: bknr/datastore/src bknr/datastore/src/utils bknr/datastore/src/xml-impex bknr/web/src bknr/web/src/web projects/bos/worldpay-test projects/eboy/src projects/gpn projects/lisp-ecoop/src projects/quickhoney/src projects/quickhoney/website/templates projects/saugnapf/src thirdparty/cl+ssl Message-ID: <20080202225417.9E690461E3@common-lisp.net> Author: hhubner Date: Sat Feb 2 17:54:13 2008 New Revision: 2438 Added: branches/trunk-reorg/bknr/datastore/src/utils/parse-time.lisp branches/trunk-reorg/bknr/web/src/web/template-handler.lisp - copied, changed from r2434, branches/trunk-reorg/bknr/web/src/web/templates.lisp Removed: branches/trunk-reorg/bknr/web/src/web/templates.lisp Modified: branches/trunk-reorg/bknr/datastore/src/bknr-utils.asd branches/trunk-reorg/bknr/datastore/src/utils/package.lisp branches/trunk-reorg/bknr/datastore/src/xml-impex/xml-class.lisp branches/trunk-reorg/bknr/web/src/bknr-web.asd branches/trunk-reorg/bknr/web/src/packages.lisp branches/trunk-reorg/bknr/web/src/web/tags.lisp branches/trunk-reorg/projects/bos/worldpay-test/boi-handlers.lisp branches/trunk-reorg/projects/bos/worldpay-test/sponsor-handlers.lisp branches/trunk-reorg/projects/bos/worldpay-test/tags.lisp branches/trunk-reorg/projects/bos/worldpay-test/web-utils.lisp branches/trunk-reorg/projects/bos/worldpay-test/worldpay-test.lisp branches/trunk-reorg/projects/eboy/src/item-handlers.lisp branches/trunk-reorg/projects/gpn/gpn-tags.lisp branches/trunk-reorg/projects/gpn/import-handler.lisp branches/trunk-reorg/projects/lisp-ecoop/src/config.lisp branches/trunk-reorg/projects/lisp-ecoop/src/handlers.lisp branches/trunk-reorg/projects/lisp-ecoop/src/init.lisp branches/trunk-reorg/projects/lisp-ecoop/src/lisp-ecoop.asd branches/trunk-reorg/projects/lisp-ecoop/src/load.lisp branches/trunk-reorg/projects/lisp-ecoop/src/macros.lisp branches/trunk-reorg/projects/lisp-ecoop/src/packages.lisp branches/trunk-reorg/projects/lisp-ecoop/src/participant.lisp branches/trunk-reorg/projects/lisp-ecoop/src/schedule.lisp branches/trunk-reorg/projects/lisp-ecoop/src/tags.lisp branches/trunk-reorg/projects/lisp-ecoop/src/webserver.lisp branches/trunk-reorg/projects/quickhoney/src/tags.lisp branches/trunk-reorg/projects/quickhoney/src/webserver.lisp branches/trunk-reorg/projects/quickhoney/website/templates/frontpage.xml branches/trunk-reorg/projects/quickhoney/website/templates/index.xml branches/trunk-reorg/projects/saugnapf/src/saugnapf.lisp branches/trunk-reorg/thirdparty/cl+ssl/ffi.lisp branches/trunk-reorg/thirdparty/cl+ssl/reload.lisp Log: Fix templater to work with current CXML. Began porting lisp-ecoop over to the new framework. Modified: branches/trunk-reorg/bknr/datastore/src/bknr-utils.asd ============================================================================== --- branches/trunk-reorg/bknr/datastore/src/bknr-utils.asd (original) +++ branches/trunk-reorg/bknr/datastore/src/bknr-utils.asd Sat Feb 2 17:54:13 2008 @@ -35,5 +35,6 @@ (:file "capability" :depends-on ("utils")) (:file "make-fdf-file" :depends-on ("utils")) (:file "date-calc") + (:file "parse-time") (:file "acl-mp-compat" :depends-on ("package")))))) Modified: branches/trunk-reorg/bknr/datastore/src/utils/package.lisp ============================================================================== --- branches/trunk-reorg/bknr/datastore/src/utils/package.lisp (original) +++ branches/trunk-reorg/bknr/datastore/src/utils/package.lisp Sat Feb 2 17:54:13 2008 @@ -30,6 +30,7 @@ #:month-num-days #:hostname + #:parse-time ;; filesystem functions #:copy-stream Added: branches/trunk-reorg/bknr/datastore/src/utils/parse-time.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/bknr/datastore/src/utils/parse-time.lisp Sat Feb 2 17:54:13 2008 @@ -0,0 +1,635 @@ +(in-package :bknr.utils) + +;;; ********************************************************************** +;;; This code was written as part of the CMU Common Lisp project at +;;; Carnegie Mellon University, and has been placed in the public domain. +;;; + +;;; It was subsequently borrowed and modified slightly by Daniel +;;; Barlow to become part of the net-telent-date +;;; package. Daniel, Tue May 22 05:45:27 BST 2001 + +;;; ********************************************************************** + +;;; Parsing routines for time and date strings. PARSE-TIME returns the +;;; universal time integer for the time and/or date given in the string. + +;;; Written by Jim Healy, June 1987. + +;;; ********************************************************************** + +(defvar whitespace-chars '(#\space #\tab #\newline #\, #\' #\`)) +(defvar time-dividers '(#\: #\.)) +(defvar date-dividers '(#\\ #\/ #\-)) + +(defvar *error-on-mismatch* nil + "If t, an error will be signalled if parse-time is unable + to determine the time/date format of the string.") + +;;; Set up hash tables for month, weekday, zone, and special strings. +;;; Provides quick, easy access to associated information for these items. + +;;; Hashlist takes an association list and hashes each pair into the +;;; specified tables using the car of the pair as the key and the cdr as +;;; the data object. + +(defmacro hashlist (list table) + `(dolist (item ,list) + (setf (gethash (car item) ,table) (cdr item)))) + +(defparameter weekday-table-size 23) +(defparameter month-table-size 31) +(defparameter zone-table-size 11) +(defparameter special-table-size 11) + +(defvar *weekday-strings* (make-hash-table :test #'equal + :size weekday-table-size)) + +(defvar *month-strings* (make-hash-table :test #'equal + :size month-table-size)) + +(defvar *zone-strings* (make-hash-table :test #'equal + :size zone-table-size)) + +(defvar *special-strings* (make-hash-table :test #'equal + :size special-table-size)) + +;;; Load-time creation of the hash tables. + +(hashlist '(("monday" . 0) ("mon" . 0) + ("tuesday" . 1) ("tues" . 1) ("tue" . 1) + ("wednesday" . 2) ("wednes" . 2) ("wed" . 2) + ("thursday" . 3) ("thurs" . 3) ("thu" . 3) + ("friday" . 4) ("fri" . 4) + ("saturday" . 5) ("sat" . 5) + ("sunday" . 6) ("sun" . 6)) + *weekday-strings*) + +(hashlist '(("january" . 1) ("jan" . 1) + ("february" . 2) ("feb" . 2) + ("march" . 3) ("mar" . 3) + ("april" . 4) ("apr" . 4) + ("may" . 5) ("june" . 6) + ("jun" . 6) ("july" . 7) + ("jul" . 7) ("august" . 8) + ("aug" . 8) ("september" . 9) + ("sept" . 9) ("sep" . 9) + ("october" . 10) ("oct" . 10) + ("november" . 11) ("nov" . 11) + ("december" . 12) ("dec" . 12)) + *month-strings*) + +(hashlist '(("gmt" . 0) ("est" . 5) + ("edt" . 4) ("cst" . 6) + ("cdt" . 5) ("mst" . 7) + ("mdt" . 6) ("pst" . 8) + ("pdt" . 7)) + *zone-strings*) + +(hashlist '(("yesterday" . yesterday) ("today" . today) + ("tomorrow" . tomorrow) ("now" . now)) + *special-strings*) + +;;; Time/date format patterns are specified as lists of symbols repre- +;;; senting the elements. Optional elements can be specified by +;;; enclosing them in parentheses. Note that the order in which the +;;; patterns are specified below determines the order of search. + +;;; Choices of pattern symbols are: second, minute, hour, day, month, +;;; year, time-divider, date-divider, am-pm, zone, izone, weekday, +;;; noon-midn, and any special symbol. + +(defparameter *default-date-time-patterns* + '( + ;; Date formats. + ((weekday) month (date-divider) day (date-divider) year (noon-midn)) + ((weekday) day (date-divider) month (date-divider) year (noon-midn)) + ((weekday) month (date-divider) day (noon-midn)) + (year (date-divider) month (date-divider) day (noon-midn)) + (month (date-divider) year (noon-midn)) + (year (date-divider) month (noon-midn)) + + ((noon-midn) (weekday) month (date-divider) day (date-divider) year) + ((noon-midn) (weekday) day (date-divider) month (date-divider) year) + ((noon-midn) (weekday) month (date-divider) day) + ((noon-midn) year (date-divider) month (date-divider) day) + ((noon-midn) month (date-divider) year) + ((noon-midn) year (date-divider) month) + + ;; Time formats. + (hour (time-divider) (minute) (time-divider) (secondp) (am-pm) + (date-divider) (zone)) + (noon-midn) + (hour (noon-midn)) + + ;; Time/date combined formats. + ((weekday) month (date-divider) day (date-divider) year + hour (time-divider) (minute) (time-divider) (secondp) + (am-pm) (date-divider) (zone)) + ((weekday) day (date-divider) month (date-divider) year + hour (time-divider) (minute) (time-divider) (secondp) + (am-pm) (date-divider) (zone)) + ((weekday) month (date-divider) day + hour (time-divider) (minute) (time-divider) (secondp) + (am-pm) (date-divider) (zone)) + (year (date-divider) month (date-divider) day + hour (time-divider) (minute) (time-divider) (secondp) + (am-pm) (date-divider) (zone)) + (month (date-divider) year + hour (time-divider) (minute) (time-divider) (secondp) + (am-pm) (date-divider) (zone)) + (year (date-divider) month + hour (time-divider) (minute) (time-divider) (secondp) + (am-pm) (date-divider) (zone)) + + (hour (time-divider) (minute) (time-divider) (secondp) (am-pm) + (date-divider) (zone) (weekday) month (date-divider) + day (date-divider) year) + (hour (time-divider) (minute) (time-divider) (secondp) (am-pm) + (date-divider) (zone) (weekday) day (date-divider) + month (date-divider) year) + (hour (time-divider) (minute) (time-divider) (secondp) (am-pm) + (date-divider) (zone) (weekday) month (date-divider) + day) + (hour (time-divider) (minute) (time-divider) (secondp) (am-pm) + (date-divider) (zone) year (date-divider) month + (date-divider) day) + (hour (time-divider) (minute) (time-divider) (secondp) (am-pm) + (date-divider) (zone) month (date-divider) year) + (hour (time-divider) (minute) (time-divider) (secondp) (am-pm) + (date-divider) (zone) year (date-divider) month) + + ;; Weird, non-standard formats. + (weekday month day hour (time-divider) minute (time-divider) + secondp (am-pm) + (zone) year) + ((weekday) day (date-divider) month (date-divider) year hour + (time-divider) minute (time-divider) (secondp) (am-pm) + (date-divider) (zone)) + ((weekday) month (date-divider) day (date-divider) year hour + (time-divider) minute (time-divider) (secondp) (am-pm) + (date-divider) (zone)) + + ;; Special-string formats. + (now (yesterday)) + ((yesterday) now) + (now (today)) + ((today) now) + (now (tomorrow)) + ((tomorrow) now) + (yesterday (noon-midn)) + ((noon-midn) yesterday) + (today (noon-midn)) + ((noon-midn) today) + (tomorrow (noon-midn)) + ((noon-midn) tomorrow) +)) + +;;; HTTP header style date/time patterns: RFC1123/RFC822, RFC850, ANSI-C. +(defparameter *http-date-time-patterns* + '( + ;; RFC1123/RFC822 and RFC850. + ((weekday) day (date-divider) month (date-divider) year + hour time-divider minute (time-divider) (secondp) izone) + ((weekday) day (date-divider) month (date-divider) year + hour time-divider minute (time-divider) (secondp) (zone)) + + ;; ANSI-C. + ((weekday) month day + hour time-divider minute (time-divider) (secondp) year))) + + +;;; The decoded-time structure holds the time/date values which are +;;; eventually passed to 'encode-universal-time' after parsing. + +;;; Note: Currently nothing is done with the day of the week. It might +;;; be appropriate to add a function to see if it matches the date. + +(defstruct decoded-time + (second 0 :type integer) ; Value between 0 and 59. + (minute 0 :type integer) ; Value between 0 and 59. + (hour 0 :type integer) ; Value between 0 and 23. + (day 1 :type integer) ; Value between 1 and 31. + (month 1 :type integer) ; Value between 1 and 12. + (year 1900 :type integer) ; Value above 1899 or between 0 and 99. + (zone 0 :type rational) ; Value between -24 and 24 inclusive. + (dotw 0 :type integer)) ; Value between 0 and 6. + +;;; Make-default-time returns a decoded-time structure with the default +;;; time values already set. The default time is currently 00:00 on +;;; the current day, current month, current year, and current time-zone. + +(defun make-default-time (def-sec def-min def-hour def-day + def-mon def-year def-zone def-dotw) + (let ((default-time (make-decoded-time))) + (multiple-value-bind (sec min hour day mon year dotw dst zone) + (get-decoded-time) + (declare (ignore dst)) + (if def-sec + (if (eq def-sec :current) + (setf (decoded-time-second default-time) sec) + (setf (decoded-time-second default-time) def-sec)) + (setf (decoded-time-second default-time) 0)) + (if def-min + (if (eq def-min :current) + (setf (decoded-time-minute default-time) min) + (setf (decoded-time-minute default-time) def-min)) + (setf (decoded-time-minute default-time) 0)) + (if def-hour + (if (eq def-hour :current) + (setf (decoded-time-hour default-time) hour) + (setf (decoded-time-hour default-time) def-hour)) + (setf (decoded-time-hour default-time) 0)) + (if def-day + (if (eq def-day :current) + (setf (decoded-time-day default-time) day) + (setf (decoded-time-day default-time) def-day)) + (setf (decoded-time-day default-time) day)) + (if def-mon + (if (eq def-mon :current) + (setf (decoded-time-month default-time) mon) + (setf (decoded-time-month default-time) def-mon)) + (setf (decoded-time-month default-time) mon)) + (if def-year + (if (eq def-year :current) + (setf (decoded-time-year default-time) year) + (setf (decoded-time-year default-time) def-year)) + (setf (decoded-time-year default-time) year)) + (if def-zone + (if (eq def-zone :current) + (setf (decoded-time-zone default-time) zone) + (setf (decoded-time-zone default-time) def-zone)) + (setf (decoded-time-zone default-time) zone)) + (if def-dotw + (if (eq def-dotw :current) + (setf (decoded-time-dotw default-time) dotw) + (setf (decoded-time-dotw default-time) def-dotw)) + (setf (decoded-time-dotw default-time) dotw)) + default-time))) + +;;; Converts the values in the decoded-time structure to universal time +;;; by calling encode-universal-time. +;;; If zone is in numerical form, tweeks it appropriately. + +(defun convert-to-unitime (parsed-values) + (let ((zone (decoded-time-zone parsed-values))) + (encode-universal-time (decoded-time-second parsed-values) + (decoded-time-minute parsed-values) + (decoded-time-hour parsed-values) + (decoded-time-day parsed-values) + (decoded-time-month parsed-values) + (decoded-time-year parsed-values) + (if (or (> zone 24) (< zone -24)) + (let ((new-zone (/ zone 100))) + (cond ((minusp new-zone) (- new-zone)) + ((plusp new-zone) (- 24 new-zone)) + ;; must be zero (GMT) + (t new-zone))) + zone)))) + +;;; Sets the current values for the time and/or date parts of the +;;; decoded time structure. + +(defun set-current-value (values-structure &key (time nil) (date nil) + (zone nil)) + (multiple-value-bind (sec min hour day mon year dotw dst tz) + (get-decoded-time) + (declare (ignore dst)) + (when time + (setf (decoded-time-second values-structure) sec) + (setf (decoded-time-minute values-structure) min) + (setf (decoded-time-hour values-structure) hour)) + (when date + (setf (decoded-time-day values-structure) day) + (setf (decoded-time-month values-structure) mon) + (setf (decoded-time-year values-structure) year) + (setf (decoded-time-dotw values-structure) dotw)) + (when zone + (setf (decoded-time-zone values-structure) tz)))) + +;;; Special function definitions. To define a special substring, add +;;; a dotted pair consisting of the substring and a symbol in the +;;; *special-strings* hashlist statement above. Then define a function +;;; here which takes one argument- the decoded time structure- and +;;; sets the values of the structure to whatever is necessary. Also, +;;; add a some patterns to the patterns list using whatever combinations +;;; of special and pre-existing symbols desired. + +(defun yesterday (parsed-values) + (set-current-value parsed-values :date t :zone t) + (setf (decoded-time-day parsed-values) + (1- (decoded-time-day parsed-values)))) + +(defun today (parsed-values) + (set-current-value parsed-values :date t :zone t)) + +(defun tomorrow (parsed-values) + (set-current-value parsed-values :date t :zone t) + (setf (decoded-time-day parsed-values) + (1+ (decoded-time-day parsed-values)))) + +(defun now (parsed-values) + (set-current-value parsed-values :time t)) + +;;; Predicates for symbols. Each symbol has a corresponding function +;;; defined here which is applied to a part of the datum to see if +;;; it matches the qualifications. + +(defun am-pm (string) + (and (simple-string-p string) + (cond ((string= string "am") 'am) + ((string= string "pm") 'pm) + (t nil)))) + +(defun noon-midn (string) + (and (simple-string-p string) + (cond ((string= string "noon") 'noon) + ((string= string "midnight") 'midn) + (t nil)))) + +(defun weekday (string) + (and (simple-string-p string) (gethash string *weekday-strings*))) + +(defun month (thing) + (or (and (simple-string-p thing) (gethash thing *month-strings*)) + (and (integerp thing) (<= 1 thing 12)))) + +(defun zone (thing) + (or (and (simple-string-p thing) (gethash thing *zone-strings*)) + (if (integerp thing) + (let ((zone (/ thing 100))) + (and (integerp zone) (<= -24 zone 24)))))) + +;;; Internet numerical time zone, e.g. RFC1123, in hours and minutes. +(defun izone (thing) + (if (integerp thing) + (multiple-value-bind (hours mins) + (truncate thing 100) + (and (<= -24 hours 24) (<= -59 mins 59))))) + +(defun special-string-p (string) + (and (simple-string-p string) (gethash string *special-strings*))) + +(defun secondp (number) + (and (integerp number) (<= 0 number 59))) + +(defun minute (number) + (and (integerp number) (<= 0 number 59))) + +(defun hour (number) + (and (integerp number) (<= 0 number 23))) + +(defun day (number) + (and (integerp number) (<= 1 number 31))) + +(defun year (number) + (and (integerp number) + (or (<= 0 number 99) + (<= 1900 number)))) + +(defun time-divider (character) + (and (characterp character) + (member character time-dividers :test #'char=))) + +(defun date-divider (character) + (and (characterp character) + (member character date-dividers :test #'char=))) + +;;; Match-substring takes a string argument and tries to match it with +;;; the strings in one of the four hash tables: *weekday-strings*, *month- +;;; strings*, *zone-strings*, *special-strings*. It returns a specific +;;; keyword and/or the object it finds in the hash table. If no match +;;; is made then it immediately signals an error. + +(defun match-substring (substring) + (let ((substring (nstring-downcase substring))) + (or (let ((test-value (month substring))) + (if test-value (cons 'month test-value))) + (let ((test-value (weekday substring))) + (if test-value (cons 'weekday test-value))) + (let ((test-value (am-pm substring))) + (if test-value (cons 'am-pm test-value))) + (let ((test-value (noon-midn substring))) + (if test-value (cons 'noon-midn test-value))) + (let ((test-value (zone substring))) + (if test-value (cons 'zone test-value))) + (let ((test-value (special-string-p substring))) + (if test-value (cons 'special test-value))) + (if *error-on-mismatch* + (error "\"~A\" is not a recognized word or abbreviation." + substring) + (return-from match-substring nil))))) + +;;; Decompose-string takes the time/date string and decomposes it into a +;;; list of alphabetic substrings, numbers, and special divider characters. +;;; It matches whatever strings it can and replaces them with a dotted pair +;;; containing a symbol and value. + +(defun decompose-string (string &key (start 0) (end (length string)) (radix 10)) + (do ((string-index start) + (next-negative nil) + (parts-list nil)) + ((eq string-index end) (nreverse parts-list)) + (let ((next-char (char string string-index)) + (prev-char (if (= string-index start) + nil + (char string (1- string-index))))) + (cond ((alpha-char-p next-char) + ;; Alphabetic character - scan to the end of the substring. + (do ((scan-index (1+ string-index) (1+ scan-index))) + ((or (eq scan-index end) + (not (alpha-char-p (char string scan-index)))) + (let ((match-symbol (match-substring + (subseq string string-index scan-index)))) + (if match-symbol + (push match-symbol parts-list) + (return-from decompose-string nil))) + (setf string-index scan-index)))) + ((digit-char-p next-char radix) + ;; Numeric digit - convert digit-string to a decimal value. + (do ((scan-index string-index (1+ scan-index)) + (numeric-value 0 (+ (* numeric-value radix) + (digit-char-p (char string scan-index) radix)))) + ((or (eq scan-index end) + (not (digit-char-p (char string scan-index) radix))) + ;; If next-negative is t, set the numeric value to it's + ;; opposite and reset next-negative to nil. + (when next-negative + (setf next-negative nil) + (setf numeric-value (- numeric-value))) + (push numeric-value parts-list) + (setf string-index scan-index)))) + ((and (char= next-char #\-) + (or (not prev-char) + (member prev-char whitespace-chars :test #'char=))) + ;; If we see a minus sign before a number, but not after one, + ;; it is not a date divider, but a negative offset from GMT, so + ;; set next-negative to t and continue. + (setf next-negative t) + (incf string-index)) + ((member next-char time-dividers :test #'char=) + ;; Time-divider - add it to the parts-list with symbol. + (push (cons 'time-divider next-char) parts-list) + (incf string-index)) + ((member next-char date-dividers :test #'char=) + ;; Date-divider - add it to the parts-list with symbol. + (push (cons 'date-divider next-char) parts-list) + (incf string-index)) + ((member next-char whitespace-chars :test #'char=) + ;; Whitespace character - ignore it completely. + (incf string-index)) + ((char= next-char #\() + ;; Parenthesized string - scan to the end and ignore it. + (do ((scan-index string-index (1+ scan-index))) + ((or (eq scan-index end) + (char= (char string scan-index) #\))) + (setf string-index (1+ scan-index))))) + (t + ;; Unrecognized character - barf voraciously. + (if *error-on-mismatch* + (error + 'simple-error + :format-control "Can't parse time/date string.~%>>> ~A~ + ~%~VT^-- Bogus character encountered here." + :format-arguments (list string (+ string-index 4))) + (return-from decompose-string nil))))))) + +;;; Match-pattern-element tries to match a pattern element with a datum +;;; element and returns the symbol associated with the datum element if +;;; successful. Otherwise nil is returned. + +(defun match-pattern-element (pattern-element datum-element) + (cond ((listp datum-element) + (let ((datum-type (if (eq (car datum-element) 'special) + (cdr datum-element) + (car datum-element)))) + (if (eq datum-type pattern-element) datum-element))) + ((funcall pattern-element datum-element) + (cons pattern-element datum-element)) + (t nil))) + +;;; Match-pattern matches a pattern against a datum, returning the +;;; pattern if successful and nil otherwise. + +(defun match-pattern (pattern datum datum-length) + (if (>= (length pattern) datum-length) + (let ((form-list nil)) + (do ((pattern pattern (cdr pattern)) + (datum datum (cdr datum))) + ((or (null pattern) (null datum)) + (cond ((and (null pattern) (null datum)) + (nreverse form-list)) + ((null pattern) nil) + ((null datum) (dolist (element pattern + (nreverse form-list)) + (if (not (listp element)) + (return nil)))))) + (let* ((pattern-element (car pattern)) + (datum-element (car datum)) + (optional (listp pattern-element)) + (matching (match-pattern-element (if optional + (car pattern-element) + pattern-element) + datum-element))) + (cond (matching (let ((form-type (car matching))) + (unless (or (eq form-type 'time-divider) + (eq form-type 'date-divider)) + (push matching form-list)))) + (optional (push datum-element datum)) + (t (return-from match-pattern nil)))))))) + +;;; Deal-with-noon-midn sets the decoded-time values to either noon +;;; or midnight depending on the argument form-value. Form-value +;;; can be either 'noon or 'midn. + +(defun deal-with-noon-midn (form-value parsed-values) + (cond ((eq form-value 'noon) + (setf (decoded-time-hour parsed-values) 12)) + ((eq form-value 'midn) + (setf (decoded-time-hour parsed-values) 0)) + (t (error "Unrecognized symbol: ~A" form-value))) + (setf (decoded-time-minute parsed-values) 0) + (setf (decoded-time-second parsed-values) 0)) + +;;; Deal-with-am-pm sets the decoded-time values to be in the am +;;; or pm depending on the argument form-value. Form-value can +;;; be either 'am or 'pm. + +(defun deal-with-am-pm (form-value parsed-values) + (let ((hour (decoded-time-hour parsed-values))) + (cond ((eq form-value 'am) + (cond ((eq hour 12) + (setf (decoded-time-hour parsed-values) 0)) + ((not (<= 0 hour 12)) + (if *error-on-mismatch* + (error "~D is not an AM hour, dummy." hour))))) + ((eq form-value 'pm) + (if (<= 0 hour 11) + (setf (decoded-time-hour parsed-values) + (mod (+ hour 12) 24)))) + (t (error "~A isn't AM/PM - this shouldn't happen." form-value))))) + +;;; Internet numerical time zone, e.g. RFC1123, in hours and minutes. +(defun deal-with-izone (form-value parsed-values) + (multiple-value-bind (hours mins) + (truncate form-value 100) + (setf (decoded-time-zone parsed-values) (- (+ hours (/ mins 60)))))) + +;;; Set-time-values uses the association list of symbols and values +;;; to set the time in the decoded-time structure. + +(defun set-time-values (string-form parsed-values) + (dolist (form-part string-form t) + (let ((form-type (car form-part)) + (form-value (cdr form-part))) + (case form-type + (secondp (setf (decoded-time-second parsed-values) form-value)) + (minute (setf (decoded-time-minute parsed-values) form-value)) + (hour (setf (decoded-time-hour parsed-values) form-value)) + (day (setf (decoded-time-day parsed-values) form-value)) + (month (setf (decoded-time-month parsed-values) form-value)) + (year (setf (decoded-time-year parsed-values) form-value)) + (zone (setf (decoded-time-zone parsed-values) form-value)) + (izone (deal-with-izone form-value parsed-values)) + (weekday (setf (decoded-time-dotw parsed-values) form-value)) + (am-pm (deal-with-am-pm form-value parsed-values)) + (noon-midn (deal-with-noon-midn form-value parsed-values)) + (special (funcall form-value parsed-values)) + (t (error "Unrecognized symbol in form list: ~A." form-type)))))) + +(defun parse-time (time-string &key (start 0) (end (length time-string)) + (error-on-mismatch nil) + (patterns *default-date-time-patterns*) + (default-seconds nil) (default-minutes nil) + (default-hours nil) (default-day nil) + (default-month nil) (default-year nil) + (default-zone nil) (default-weekday nil)) + "Tries very hard to make sense out of the argument time-string and + returns a single integer representing the universal time if + successful. If not, it returns nil. If the :error-on-mismatch + keyword is true, parse-time will signal an error instead of + returning nil. Default values for each part of the time/date + can be specified by the appropriate :default- keyword. These + keywords can be given a numeric value or the keyword :current + to set them to the current value. The default-default values + are 00:00:00 on the current date, current time-zone." + (setq *error-on-mismatch* error-on-mismatch) + (let* ((string-parts (decompose-string time-string :start start :end end)) + (parts-length (length string-parts)) + (string-form (dolist (pattern patterns) + (let ((match-result (match-pattern pattern + string-parts + parts-length))) + (if match-result (return match-result)))))) + (if string-form + (let ((parsed-values (make-default-time default-seconds default-minutes + default-hours default-day + default-month default-year + default-zone default-weekday))) + (set-time-values string-form parsed-values) + (convert-to-unitime parsed-values)) + (if *error-on-mismatch* + (error "\"~A\" is not a recognized time/date format." time-string) + nil)))) + + Modified: branches/trunk-reorg/bknr/datastore/src/xml-impex/xml-class.lisp ============================================================================== --- branches/trunk-reorg/bknr/datastore/src/xml-impex/xml-class.lisp (original) +++ branches/trunk-reorg/bknr/datastore/src/xml-impex/xml-class.lisp Sat Feb 2 17:54:13 2008 @@ -158,6 +158,8 @@ direct-slots)) (xml-direct (first xml-directs))) + ;; Commented out this check because I could not determine what it does and it warned me. + #+(or) (when (> (length xml-directs) 1) (dolist (slot-def (class-slots (class-of (first xml-directs)))) (unless (apply #'equal (mapcar #'(lambda (slot) (slot-value slot (slot-definition-name slot-def))) xml-directs)) Modified: branches/trunk-reorg/bknr/web/src/bknr-web.asd ============================================================================== --- branches/trunk-reorg/bknr/web/src/bknr-web.asd (original) +++ branches/trunk-reorg/bknr/web/src/bknr-web.asd Sat Feb 2 17:54:13 2008 @@ -94,7 +94,7 @@ "sessions" "site")) - (:file "templates" + (:file "template-handler" :depends-on ("handlers")) (:file "rss-handlers" :depends-on ("handlers")) @@ -106,7 +106,7 @@ (:file "tags" :depends-on ("handlers" - "templates" + "template-handler" "site" "web-utils"))) :depends-on ("sysclasses" "packages" "rss")) Modified: branches/trunk-reorg/bknr/web/src/packages.lisp ============================================================================== --- branches/trunk-reorg/bknr/web/src/packages.lisp (original) +++ branches/trunk-reorg/bknr/web/src/packages.lisp Sat Feb 2 17:54:13 2008 @@ -270,6 +270,7 @@ #:find-template-pathname #:initial-template-environment #:with-tag-expanders + #:emit-tag-children #:*html-variables* #:*template-dtd-catalog* Modified: branches/trunk-reorg/bknr/web/src/web/tags.lisp ============================================================================== --- branches/trunk-reorg/bknr/web/src/web/tags.lisp (original) +++ branches/trunk-reorg/bknr/web/src/web/tags.lisp Sat Feb 2 17:54:13 2008 @@ -18,7 +18,8 @@ (emit-template-node toplevel))) (define-bknr-tag tag-body () - (mapc #'emit-template-node *toplevel-children*)) + (let ((*tag-children* *toplevel-children*)) + (emit-tag-children))) (define-bknr-tag redirect-request (&key target) (redirect target)) Copied: branches/trunk-reorg/bknr/web/src/web/template-handler.lisp (from r2434, branches/trunk-reorg/bknr/web/src/web/templates.lisp) ============================================================================== --- branches/trunk-reorg/bknr/web/src/web/templates.lisp (original) +++ branches/trunk-reorg/bknr/web/src/web/template-handler.lisp Sat Feb 2 17:54:13 2008 @@ -6,16 +6,19 @@ (defvar *template-expander*) (defvar *template-env*) -(defvar *template-dtd-catalog* `(;; libxml standard - "/etc/xml/catalog" - ;; FreeBSD - "/usr/local/share/xml/catalog.ports")) +(defparameter *template-dtd-catalog* `(;; libxml standard + "/etc/xml/catalog" + ;; FreeBSD + "/usr/local/share/xml/catalog.ports" + "/usr/local/share/xml/catalog")) -#+cmu (eval-when (:load-toplevel :execute) (let ((env-catalog (sb-ext:posix-getenv "XMLCATALOG"))) (when env-catalog - (pushnew env-catalog *template-dtd-catalog* :test #'equal)))) + (pushnew env-catalog *template-dtd-catalog* :test #'equal))) + (setf cxml:*catalog* (cxml:make-catalog (remove-if-not #'probe-file *template-dtd-catalog*)) + cxml:*dtd-cache* (cxml:make-dtd-cache) + cxml:*cache-all-dtds* t)) ;; user-error is supposed to be raised when an error is provoked by ;; the user (i.e. by supplying invalid form data). @@ -37,10 +40,15 @@ (defclass template-expander () ((command-packages :initarg :command-packages :initform nil - :reader template-expander-command-packages))) + :reader template-expander-command-packages) + (destination :initarg :destination + :reader template-expander-destination) + (cached-templates :initform (make-hash-table :test 'equal) + :accessor template-expander-cached-templates))) (defmethod find-tag-function ((expander template-expander) name ns) - (let ((package-name (cdr (assoc (make-keyword-from-string ns) (template-expander-command-packages expander)))) + (let ((package-name (cdr (find ns (template-expander-command-packages expander) + :test #'equal :key #'car))) (function-name (string-upcase name))) (or (gethash function-name (or (gethash (symbol-name package-name) *template-functions*) (error "can't find package ~A in tag function registry" package-name))) @@ -100,23 +108,6 @@ (t (format nil "~A" val)))))) string)) -(defun emit-template (expander stream node env) - (let* ((*template-expander* expander) - (*template-env* env) - (sink (cxml:make-character-stream-sink stream :canonical nil)) - (*html-sink* (cxml:make-recoder sink #'cxml::utf8-string-to-rod))) - (if (node-attribute node "suppress-xml-headers") - (emit-template-node node) - (progn - (sax:start-document *html-sink*) - (sax:start-dtd *html-sink* - "html" - "-//W3C//DTD XHTML 1.0 Transitional//EN" - "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd") - (sax:end-dtd *html-sink*) - (emit-template-node node))) - (sax:end-document *html-sink*))) - (defun xmls-attributes-to-sax (fn attrs) (mapcar (lambda (a) (destructuring-bind (name value) a @@ -131,55 +122,109 @@ :specified-p t)))) attrs)) -(defun emit-template-node (node) +(defun parse-template (template-pathname) + (let ((sax:*include-xmlns-attributes* t)) + (cxml:parse-file (namestring (probe-file template-pathname)) + (cxml-xmls:make-xmls-builder) + :validate nil))) + +(defvar *tag-children*) + +(defun emit-tag-children () + "Function to be called by application defined tags to emit their children." + (mapc (curry #'emit-template-node *template-expander*) *tag-children*)) + +(defun emit-template-node (expander node) (if (stringp node) (sax:characters *html-sink* (expand-variables node)) (let* ((name (node-name node)) (ns (node-ns node)) (children (node-children node)) (attrs (cxml-xmls:node-attrs node))) - ;; XML-technisch waere es korrekter, nicht auf das Praefix zu gucken, - ;; sondern auf die Namespace-URI. (cond - ((and ns - (not (find #\: ns))) - (apply (find-tag-function *template-expander* name ns) - (append (loop for (key name) in (remove-if #'(lambda (attr) (scan "^xmlns" (car attr))) attrs) - collect (make-keyword-from-string key) - collect (expand-variables name)) - (when children - (list :children children))))) + ((find ns (template-expander-command-packages expander) + :test #'equal :key #'car) + (let ((*tag-children* children)) + (apply (find-tag-function expander name ns) + (append (loop for (key name) in attrs + collect (make-keyword-from-string key) + collect (expand-variables name)))))) (t (sax:start-element *html-sink* nil nil name (xmls-attributes-to-sax #'expand-variables attrs)) (dolist (child children) - (emit-template-node child)) + (emit-template-node expander child)) (sax:end-element *html-sink* nil nil name)))))) +(defun emit-parsed-template (expander toplevel) + "Emit the given XMLS compatible structure as XML to *HTML-SINK*." + ;; In order to generate xmlns attributes, we use the internal + ;; CXML-XMLS::COMPUTE-ATTRIBUTES/LNAMES function. This may need to + ;; be revised with newer cxml releases. + (sax:start-element *html-sink* (node-ns toplevel) (node-name toplevel) (node-name toplevel) + (cxml-xmls::compute-attributes/lnames toplevel t)) + (let ((*template-expander* expander)) + (mapc (curry #'emit-template-node expander) (node-children toplevel))) + (sax:end-element *html-sink* (node-ns toplevel) (node-name toplevel) (node-name toplevel))) + +(defun find-template (dir components) + (if (null components) + nil + (let ((next-dir (merge-pathnames (make-pathname :directory (list :relative (first components))) + dir))) + (when (probe-file next-dir) + (let ((result (multiple-value-list (find-template next-dir (cdr components))))) + (when (car result) + (return-from find-template (values-list result))))) + (let ((file (merge-pathnames (make-pathname :type "xml" + :name (first components)) + dir))) + (when (probe-file file) + (values file (cdr components))))))) + +(defmethod find-template-pathname ((expander template-expander) template-name) + (let ((components (remove "" (split "/" template-name) :test #'equal))) + (multiple-value-bind (pathname ret-components) + (find-template (template-expander-destination expander) components) + (unless pathname + (template-not-found template-name)) + (values pathname + ret-components + (with-output-to-string (s) + (dolist (component (subseq components 0 (- (length components) + (length ret-components)))) + (write-char #\/ s) + (write-string component s))))))) + +(defun get-cached-template (pathname expander) + (let* ((table (template-expander-cached-templates expander)) + (namestring (namestring pathname)) + (cache-entry (gethash namestring table)) + (current-write-date (file-write-date namestring))) + (unless (and cache-entry (eql (car cache-entry) current-write-date)) + (setf cache-entry + (cons current-write-date (parse-template pathname))) + (setf (gethash namestring table) cache-entry)) + (cdr cache-entry))) + +(defun emit-template (expander stream node env) + (let* ((*template-env* env) + (*html-sink* (cxml:make-character-stream-sink stream :canonical nil))) + (if (node-attribute node "suppress-xml-headers") + (emit-parsed-template expander node) + (progn + (sax:start-document *html-sink*) + (sax:start-dtd *html-sink* + "html" + "-//W3C//DTD XHTML 1.0 Transitional//EN" + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd") + (sax:end-dtd *html-sink*) + (emit-parsed-template expander node))) + (sax:end-document *html-sink*))) ;; template handler (defclass template-handler (prefix-handler template-expander) - ((destination :initarg :destination - :reader template-handler-destination) - (cached-templates :initform (make-hash-table :test 'equal) - :accessor template-handler-cached-templates) - (dtd-cache :initform (cxml:make-dtd-cache) - :reader template-handler-dtd-cache) - (catalog :initform (cxml:make-catalog *template-dtd-catalog*) - :reader template-handler-catalog))) - -(defconstant +max-template-expansions-per-request+ 100 - "Maximum number of template expansions in one template request (circular dependency safeguard") - -(defun parse-template (handler template-pathname) - (let ((cxml:*dtd-cache* (template-handler-dtd-cache handler)) - (cxml:*cache-all-dtds* t) - (cxml:*catalog* (template-handler-catalog handler)) - (sax:*include-xmlns-attributes* t)) - (cxml:parse-file (namestring (probe-file template-pathname)) - (cxml:make-recoder (cxml-xmls:make-xmls-builder) - #'cxml::rod-to-utf8-string) - :validate nil))) + ()) (defmethod expand-template ((handler template-handler) template-name &key env) @@ -216,46 +261,6 @@ env))) (template-not-found template-pathname)))) -(defun find-template (dir components) - (if (null components) - nil - (let ((next-dir (merge-pathnames (make-pathname :directory (list :relative (first components))) - dir))) - (when (probe-file next-dir) - (let ((result (multiple-value-list (find-template next-dir (cdr components))))) - (when (car result) - (return-from find-template (values-list result))))) - (let ((file (merge-pathnames (make-pathname :type "xml" - :name (first components)) - dir))) - (when (probe-file file) - (values file (cdr components))))))) - -(defmethod find-template-pathname ((handler template-handler) template-name) - (let ((components (remove "" (split "/" template-name) :test #'equal))) - (multiple-value-bind (pathname ret-components) - (find-template (template-handler-destination handler) components) - (unless pathname - (template-not-found template-name)) - (values pathname - ret-components - (with-output-to-string (s) - (dolist (component (subseq components 0 (- (length components) - (length ret-components)))) - (write-char #\/ s) - (write-string component s))))))) - -(defun get-cached-template (pathname handler) - (let* ((table (template-handler-cached-templates handler)) - (namestring (namestring pathname)) - (cache-entry (gethash namestring table)) - (current-write-date (file-write-date namestring))) - (unless (and cache-entry (eql (car cache-entry) current-write-date)) - (setf cache-entry - (cons current-write-date (parse-template handler pathname))) - (setf (gethash namestring table) cache-entry)) - (cdr cache-entry))) - (defun send-error-response (handler message &key (response-code +http-internal-server-error+)) (with-http-response (:content-type "text/html; charset=UTF-8" :response response-code) Modified: branches/trunk-reorg/projects/bos/worldpay-test/boi-handlers.lisp ============================================================================== --- branches/trunk-reorg/projects/bos/worldpay-test/boi-handlers.lisp (original) +++ branches/trunk-reorg/projects/bos/worldpay-test/boi-handlers.lisp Sat Feb 2 17:54:13 2008 @@ -31,7 +31,7 @@ ()) (defmethod authorized-p ((handler boi-handler)) - (let ((user (bknr-request-user))) + (let ((user (bknr-session-user))) (or (admin-p user) (user-has-flag user :boi)))) @@ -91,7 +91,7 @@ (with-transaction (:contract-paid) (contract-set-paidp contract (format nil "~A: manually set paid by ~A" (format-date-time) - (user-login (bknr-request-user)))) + (user-login (bknr-session-user)))) (when name (setf (user-full-name (contract-sponsor contract)) name)))) (with-xml-response () Modified: branches/trunk-reorg/projects/bos/worldpay-test/sponsor-handlers.lisp ============================================================================== --- branches/trunk-reorg/projects/bos/worldpay-test/sponsor-handlers.lisp (original) +++ branches/trunk-reorg/projects/bos/worldpay-test/sponsor-handlers.lisp Sat Feb 2 17:54:13 2008 @@ -96,7 +96,7 @@ (contract (make-contract sponsor (parse-integer numsqm) :paidp (format nil "~A: manually created by ~A" (format-date-time (get-universal-time)) - (user-login (bknr-request-user))) + (user-login (bknr-session-user))) :date (date-to-universal date)))) (contract-issue-cert contract name :address address :language language) (mail-backoffice-sponsor-data contract) @@ -223,7 +223,7 @@ (html (:h2 "Completing square meter sale")) (sponsor-set-country (contract-sponsor contract) country) (contract-set-paidp contract (format nil "~A: wire transfer processed by ~A" - (format-date-time) (user-login (bknr-request-user)))) + (format-date-time) (user-login (bknr-session-user)))) (when email (html (:p "Sending instruction email to " (:princ-safe email))) (mail-instructions-to-sponsor contract email)))) @@ -243,8 +243,8 @@ (sponsor-id-or-x (find-store-object (parse-integer sponsor-id-or-x) :class 'sponsor)) (t - (when (eq (find-class 'sponsor) (class-of (bknr-request-user))) - (bknr-request-user)))))) + (when (eq (find-class 'sponsor) (class-of (bknr-session-user))) + (bknr-session-user)))))) (with-http-response (:content-type "text/html; charset=UTF-8") (with-http-body () (let ((*standard-output* *html-stream*)) @@ -265,7 +265,7 @@ (with-http-body () (format *html-stream* "~%" (cond - ((eq (find-class 'sponsor) (class-of (bknr-request-user))) + ((eq (find-class 'sponsor) (class-of (bknr-session-user))) "logged-in") (__sponsorid "login-failed") Modified: branches/trunk-reorg/projects/bos/worldpay-test/tags.lisp ============================================================================== --- branches/trunk-reorg/projects/bos/worldpay-test/tags.lisp (original) +++ branches/trunk-reorg/projects/bos/worldpay-test/tags.lisp Sat Feb 2 17:54:13 2008 @@ -24,7 +24,7 @@ (define-bknr-tag worldpay-receipt () (emit-without-quoting "")) -(define-bknr-tag process-payment (&key children) +(define-bknr-tag process-payment () (with-template-vars (cartId transId email country) (let* ((contract (get-contract (parse-integer cartId))) (sponsor (contract-sponsor contract))) @@ -34,7 +34,7 @@ (contract-set-paidp contract (format nil "~A: paid via worldpay" (format-date-time))) (setf (get-template-var :master-code) (sponsor-master-code sponsor)) (setf (get-template-var :sponsor-id) (sponsor-id sponsor)))) - (mapc #'emit-template-node children)) + (emit-tag-children)) (define-bknr-tag generate-cert () (with-template-vars (gift email name address) @@ -106,7 +106,7 @@ (if donationcert-yearly "1" "0") (if gift "1" "0") (when *worldpay-test-mode* "&testMode=100")))))) - (mapc #'emit-template-node children))) + (emit-tag-children))) (define-bknr-tag mail-transfer () (with-query-params ((get-template-var :request) @@ -126,16 +126,16 @@ :language (session-variable :language)) (mail-manual-sponsor-data (get-template-var :request))))) -(define-bknr-tag when-certificate (&key children) +(define-bknr-tag when-certificate () (let ((sponsor (bknr-request-user (get-template-var :request)))) (when (some #'contract-pdf-pathname (sponsor-contracts sponsor)) - (mapc #'emit-template-node children)))) + (emit-tag-children)))) -(define-bknr-tag send-info-request (&key children email) +(define-bknr-tag send-info-request (&key email) (mail-info-request email) - (mapc #'emit-template-node children)) + (emit-tag-children)) -(define-bknr-tag save-profile (&key children) +(define-bknr-tag save-profile () (let ((sponsor (bknr-request-user (get-template-var :request)))) (with-template-vars (email name password infotext anonymize) (when anonymize @@ -144,7 +144,7 @@ 'info-text nil 'email nil)) (when name - (change-slot-values sponsor 'full-name name)) + (change-sLot-values sponsor 'full-name name)) (when email (change-slot-values sponsor 'bknr.web::email email)) (when password @@ -160,9 +160,9 @@ (setf (get-template-var :numsqm) (format nil "~D" (apply #'+ (mapcar #'(lambda (contract) (length (contract-m2s contract))) (sponsor-contracts sponsor)))))) - (mapc #'emit-template-node children)) + (emit-tag-children)) -(define-bknr-tag admin-login-page (&key children) +(define-bknr-tag admin-login-page () (if (admin-p (bknr-request-user (get-template-var :request))) (html (:head ((:meta :http-equiv "refresh" :content "0; url=/admin")))) - (mapc #'emit-template-node children))) \ No newline at end of file + (emit-tag-children))) \ No newline at end of file Modified: branches/trunk-reorg/projects/bos/worldpay-test/web-utils.lisp ============================================================================== --- branches/trunk-reorg/projects/bos/worldpay-test/web-utils.lisp (original) +++ branches/trunk-reorg/projects/bos/worldpay-test/web-utils.lisp Sat Feb 2 17:54:13 2008 @@ -27,8 +27,8 @@ ((:p :class "footer") "local time is " (:princ-safe (format-date-time)) " - " - (if (bknr-request-user) - (html "logged in as " (html-link (bknr-request-user))) + (if (bknr-session-user) + (html "logged in as " (html-link (bknr-session-user))) (html "not logged in")) " - current content language is " (cmslink "change-language" Modified: branches/trunk-reorg/projects/bos/worldpay-test/worldpay-test.lisp ============================================================================== --- branches/trunk-reorg/projects/bos/worldpay-test/worldpay-test.lisp (original) +++ branches/trunk-reorg/projects/bos/worldpay-test/worldpay-test.lisp Sat Feb 2 17:54:13 2008 @@ -112,7 +112,7 @@ (defmethod handle-object ((handler certificate-handler) contract) (unless contract - (setf contract (find-if #'contract-pdf-pathname (sponsor-contracts (bknr-request-user))))) + (setf contract (find-if #'contract-pdf-pathname (sponsor-contracts (bknr-session-user))))) (redirect (format nil "/certificates/~D.pdf" (store-object-id contract)))) (defclass statistics-handler (admin-only-handler prefix-handler) Modified: branches/trunk-reorg/projects/eboy/src/item-handlers.lisp ============================================================================== --- branches/trunk-reorg/projects/eboy/src/item-handlers.lisp (original) +++ branches/trunk-reorg/projects/eboy/src/item-handlers.lisp Sat Feb 2 17:54:13 2008 @@ -77,7 +77,7 @@ :confirm "Really delete item?"))))))) (defmethod authorized-p ((handler edit-item-handler)) - (admin-p (bknr-request-user))) + (admin-p (bknr-session-user))) (defmethod handle-object-form ((handler edit-item-handler) action item) Modified: branches/trunk-reorg/projects/gpn/gpn-tags.lisp ============================================================================== --- branches/trunk-reorg/projects/gpn/gpn-tags.lisp (original) +++ branches/trunk-reorg/projects/gpn/gpn-tags.lisp Sat Feb 2 17:54:13 2008 @@ -32,14 +32,14 @@ ((:a :class "headlink" :href (second button)) (:princ-safe (first button)))))) (html (:td)))) - (if (eql (find-user "anonymous") (bknr-request-user)) + (if (eql (find-user "anonymous") (bknr-session-user)) (html ((:td :class "headbar") ((:a :class "headlogin" :href "/login") "LOGIN"))) (html ((:td :class "headbar") ((:a :class "headlogin" :href (format nil "/gpn-user/~a" - (user-login (bknr-request-user)))) + (user-login (bknr-session-user)))) "HOME")) - (when (admin-p (bknr-request-user)) + (when (admin-p (bknr-session-user)) (html ((:td :class "headbar") ((:a :class "headlogin" :href "/admin") "ADMIN")))) ((:td :class "headbar") @@ -71,7 +71,7 @@ (html "ANONYMOUS")) ", " (:princ-safe (format-date-time (article-time item) :show-weekday t)) - (when (equal (article-author item) (bknr-request-user)) + (when (equal (article-author item) (bknr-session-user)) (html ((:a :href (format nil "/edit-article/~A" (store-object-id item))) " (edit)"))) )))) (html ((:a :class "rss" :href (format nil "~a/~a" (handler-url :blog-rss) @@ -154,7 +154,7 @@ (when email (html ((:div :class "email") "EMAIL: " (:princ-safe (string-upcase (user-email user)))))))) - (when (string-equal (user-login user) (user-login (bknr-request-user))) + (when (string-equal (user-login user) (user-login (bknr-session-user))) (html ((:div :class "user-edit") ((:p :class "news") "Zum Importieren von Bildern zuerst die Bilder auf ftp://fiep/ hochladen, @@ -278,11 +278,11 @@ (define-bknr-tag logged-in () (html ((:div :class "logged-in") "logged in as " - (if (string-equal (user-login (bknr-request-user)) "anonymous") + (if (string-equal (user-login (bknr-session-user)) "anonymous") (html "anonymous") (html ((:a :style "color:#cc3333;" - :href (format nil "/gpn-user/~a" (user-login (bknr-request-user)))) - (:princ-safe (user-login (bknr-request-user))))))))) + :href (format nil "/gpn-user/~a" (user-login (bknr-session-user)))) + (:princ-safe (user-login (bknr-session-user))))))))) (define-bknr-tag gpn-fahrplan (&key location) (let ((events (sort (remove-if #'(lambda (event) (< (zeitplan-event-end-time event) (get-universal-time))) @@ -414,5 +414,5 @@ (html "ANONYMOUS")) ", " (:princ-safe (format-date-time (article-time article) :show-weekday t)) - (when (equal (article-author article) (bknr-request-user)) + (when (equal (article-author article) (bknr-session-user)) (html ((:a :href (format nil "/edit-article/~A" (store-object-id article))) " (edit)")))))))))) Modified: branches/trunk-reorg/projects/gpn/import-handler.lisp ============================================================================== --- branches/trunk-reorg/projects/gpn/import-handler.lisp (original) +++ branches/trunk-reorg/projects/gpn/import-handler.lisp Sat Feb 2 17:54:13 2008 @@ -6,7 +6,7 @@ ()) (defmethod import-handler-import-pathname ((handler gpn-import-handler)) - (let* ((user (bknr-request-user)) + (let* ((user (bknr-session-user)) (spool-dir (merge-pathnames (make-pathname :directory (list :relative (user-login user) "images")) @@ -34,7 +34,7 @@ (let* ((keywords (keywords-from-query-param-list (query-param-list "keyword"))) (spool-dir (import-handler-import-pathname handler))) (import-directory spool-dir - :user (bknr-request-user) + :user (bknr-session-user) :keywords (when (admin-p *user*) keywords) :spool (import-handler-spool-dir handler) :keywords-from-dir (if (admin-p *user*) Modified: branches/trunk-reorg/projects/lisp-ecoop/src/config.lisp ============================================================================== --- branches/trunk-reorg/projects/lisp-ecoop/src/config.lisp (original) +++ branches/trunk-reorg/projects/lisp-ecoop/src/config.lisp Sat Feb 2 17:54:13 2008 @@ -7,7 +7,7 @@ (when (probe-file "site.lisp") (load "site.lisp"))) -(defparameter *root-directory* #p"home:bknr-svn/projects/lisp-ecoop/") +(defparameter *root-directory* (merge-pathnames #P"../" *load-pathname*)) (defparameter *store-directory* (merge-pathnames #p"datastore/" *root-directory*)) Modified: branches/trunk-reorg/projects/lisp-ecoop/src/handlers.lisp ============================================================================== --- branches/trunk-reorg/projects/lisp-ecoop/src/handlers.lisp (original) +++ branches/trunk-reorg/projects/lisp-ecoop/src/handlers.lisp Sat Feb 2 17:54:13 2008 @@ -5,8 +5,8 @@ (defun format-object-id (format object &rest args) (apply #'format nil format (store-object-id object) args)) -(defmacro with-lisp-ecoop-page ((req title) &body body) - `(with-bknr-page (,req :title ,title) +(defmacro with-lisp-ecoop-page ((title) &body body) + `(with-bknr-page (:title ,title) , at body)) (defclass edit-participant-handler (edit-object-handler) @@ -14,7 +14,7 @@ (:default-initargs :class 'participant :query-function #'find-user)) (defmethod handle-object-form ((handler edit-participant-handler) (action (eql nil)) (participant participant)) - (with-lisp-ecoop-page (req #?"Edit participant $((user-login participant))") + (with-lisp-ecoop-page (#?"Edit participant $((user-login participant))") ((:form :method "post" :enctype "multipart/form-data") ((:table :border "1") (:tr (:th "Login") @@ -29,7 +29,7 @@ (defmethod handle-object-form ((handler edit-participant-handler) (action (eql :reset-password)) (participant participant)) (participant-reset-password participant) - (with-lisp-ecoop-page (req "Password reset") + (with-lisp-ecoop-page ("Password reset") "The participant's password has been reset and sent by mail")) (defclass pdf-handler (object-handler) @@ -39,7 +39,7 @@ (defmethod handle-object ((handler pdf-handler) (document document)) (let ((pdf (file-contents (blob-pathname document)))) (with-http-response (:content-type "application/pdf") - (setf (request-reply-content-length) (length pdf)) + (setf (content-length) (length pdf)) (with-http-body (:external-format '(unsigned-byte 8)) (write-sequence pdf *html-stream*))))) @@ -49,7 +49,7 @@ (defmethod handle ((handler make-submission-handler)) (with-query-params (type title abstract) (let ((submission (make-object (if (string-equal type "paper") 'paper 'breakout-group-proposal) :title title :abstract abstract))) - (with-lisp-ecoop-page (req #?"Submission created") + (with-lisp-ecoop-page (#?"Submission created") (html ((:script :type "text/javascript") (:princ-safe #?" if (window.opener) { @@ -80,7 +80,9 @@ (let ((document (make-object 'document :info info :submission submission))) (blob-from-file document file-name) (redirect (format-object-id "/upload/~A?success=1" submission))) - (redirect (format-object-id "/upload/~A?failure=~A" submission (uriencode-string "Uploaded file does not appear to be a PDF file"))))))))) + (redirect (format-object-id "/upload/~A?failure=~A" + submission + (url-encode "Uploaded file does not appear to be a PDF file"))))))))) (:get (redirect (format-object-id "/upload/~A" submission))))) @@ -97,7 +99,7 @@ ()) (defmethod handle ((handler page-handler)) - (with-lisp-ecoop-page (req "LISP-ECOOP Administration") + (with-lisp-ecoop-page ("LISP-ECOOP Administration") "Please choose an administrative task from the menu")) (define-bknr-webserver-module participants Modified: branches/trunk-reorg/projects/lisp-ecoop/src/init.lisp ============================================================================== --- branches/trunk-reorg/projects/lisp-ecoop/src/init.lisp (original) +++ branches/trunk-reorg/projects/lisp-ecoop/src/init.lisp Sat Feb 2 17:54:13 2008 @@ -13,6 +13,9 @@ (make-user "admin" :password "wispleb" :full-name "Administrator" :flags '(:admin)) (import-image "bknr-logo.png" :keywords '(:banner :bknr))) + #+(or) (bknr.cron:start-cron) - (publish-lisp-ecoop)) + (publish-lisp-ecoop) + + (start-webserver)) Modified: branches/trunk-reorg/projects/lisp-ecoop/src/lisp-ecoop.asd ============================================================================== --- branches/trunk-reorg/projects/lisp-ecoop/src/lisp-ecoop.asd (original) +++ branches/trunk-reorg/projects/lisp-ecoop/src/lisp-ecoop.asd Sat Feb 2 17:54:13 2008 @@ -18,20 +18,17 @@ :depends-on (:bknr-datastore :bknr-web + :closer-mop + :cl-smtp :cxml) :components ((:file "packages") (:file "config" :depends-on ("packages")) (:file "macros" :depends-on ("config")) - #+(or) (:file "schedule" :depends-on ("macros")) - #+(or) (:file "participant" :depends-on ("macros" "schedule")) - #+(or) (:file "mail" :depends-on ("participant")) - #+(or) (:file "tags" :depends-on ("participant")) - #+(or) (:file "handlers" :depends-on ("participant")) - (:file "webserver" :depends-on (#+(or) "handlers")) + (:file "webserver" :depends-on ("handlers")) (:file "init" :depends-on ("webserver")))) Modified: branches/trunk-reorg/projects/lisp-ecoop/src/load.lisp ============================================================================== --- branches/trunk-reorg/projects/lisp-ecoop/src/load.lisp (original) +++ branches/trunk-reorg/projects/lisp-ecoop/src/load.lisp Sat Feb 2 17:54:13 2008 @@ -3,7 +3,8 @@ (asdf:oos 'asdf:load-op :lisp-ecoop) (asdf:oos 'asdf:load-op :swank) -(swank::create-swank-server 4005 :spawn #'swank::simple-announce-function t) +(swank::create-server :port 4005) (lisp-ecoop::startup) +#+cmu (mp::startup-idle-and-top-level-loops) Modified: branches/trunk-reorg/projects/lisp-ecoop/src/macros.lisp ============================================================================== --- branches/trunk-reorg/projects/lisp-ecoop/src/macros.lisp (original) +++ branches/trunk-reorg/projects/lisp-ecoop/src/macros.lisp Sat Feb 2 17:54:13 2008 @@ -29,13 +29,13 @@ access slot class))) (cons name rest)))) -(defmacro define-lisp-ecoop-class (class (&rest superclasses) slots &rest class-options) +(defmacro define-lisp-ecoop-class (class-name (&rest superclasses) slots &rest class-options) (let ((superclasses (or superclasses '(store-object))) - (slots (mapcar #'(lambda (slot) (compute-slot class slot)) + (slots (mapcar #'(lambda (slot) (compute-slot class-name slot)) slots))) ;; the eval-when is there to create the index access functions at compile time `(eval-when (:compile-toplevel :load-toplevel :execute) - (defclass ,class ,superclasses + (defclass ,class-name ,superclasses ((bknr.datastore::id :attribute t) , at slots) (:metaclass persistent-xml-class) Modified: branches/trunk-reorg/projects/lisp-ecoop/src/packages.lisp ============================================================================== --- branches/trunk-reorg/projects/lisp-ecoop/src/packages.lisp (original) +++ branches/trunk-reorg/projects/lisp-ecoop/src/packages.lisp Sat Feb 2 17:54:13 2008 @@ -77,5 +77,4 @@ :xhtml-generator :lisp-ecoop.config :lisp-ecoop) - (:shadowing-import-from :cl-interpol #:quote-meta-chars) - (:export #:hello)) \ No newline at end of file + (:shadowing-import-from :cl-interpol #:quote-meta-chars)) \ No newline at end of file Modified: branches/trunk-reorg/projects/lisp-ecoop/src/participant.lisp ============================================================================== --- branches/trunk-reorg/projects/lisp-ecoop/src/participant.lisp (original) +++ branches/trunk-reorg/projects/lisp-ecoop/src/participant.lisp Sat Feb 2 17:54:13 2008 @@ -16,7 +16,7 @@ (with-slots (documents) submission (setf documents (remove document documents))))) -(define-lisp-ecoop-class submission () +y(define-lisp-ecoop-class submission () ((title :update :documentation "Title of the submission" :initform nil :attribute t) (abstract :update :documentation "Abstract or short description" :initform nil :element t) (submitters :update :documentation "List of participants who submitted this" :initform nil :element t :containment :+) @@ -38,8 +38,8 @@ "Generic submission") (defun submission-edit-permitted-p (submission) - (or (admin-p (bknr-request-user)) - (find (bknr-request-user) (submission-submitters submission)))) + (or (admin-p (bknr-session-user)) + (find (bknr-session-user) (submission-submitters submission)))) (defmethod submission-add-submitter ((submission submission) submitter) (pushnew submitter (submission-submitters submission)) Modified: branches/trunk-reorg/projects/lisp-ecoop/src/schedule.lisp ============================================================================== --- branches/trunk-reorg/projects/lisp-ecoop/src/schedule.lisp (original) +++ branches/trunk-reorg/projects/lisp-ecoop/src/schedule.lisp Sat Feb 2 17:54:13 2008 @@ -83,7 +83,7 @@ ("/schedule" schedule-handler) ("/edit-timeslot" edit-timeslot-handler)) -(defun show-day-schedule (&key day children) +(defun show-day-schedule (&key day) (let* ((begin (parse-time-spec day)) (end (+ begin (* 24 60 60)))) (labels ((timeslot-wanted (timeslot) @@ -93,15 +93,15 @@ #'< :key #'timeslot-begin-time)) (with-tag-expanders ((time () - (if (admin-p (bknr-request-user)) + (if (admin-p (bknr-session-user)) (html ((:a :href #?"/edit-timeslot/$((store-object-id timeslot))") (:princ-safe (timeslot-time-string timeslot)))) (html (:princ-safe (timeslot-time-string timeslot))))) (content () (print-object-as-html (timeslot-content timeslot)))) - (mapc #'emit-template-node children)))))) + (emit-tag-children)))))) (in-package :lisp-ecoop.tags) -(define-bknr-tag show-day-schedule (&key day children) - (lisp-ecoop::show-day-schedule :day day :children children)) +(define-bknr-tag show-day-schedule (&key day) + (lisp-ecoop::show-day-schedule :day day)) Modified: branches/trunk-reorg/projects/lisp-ecoop/src/tags.lisp ============================================================================== --- branches/trunk-reorg/projects/lisp-ecoop/src/tags.lisp (original) +++ branches/trunk-reorg/projects/lisp-ecoop/src/tags.lisp Sat Feb 2 17:54:13 2008 @@ -3,7 +3,7 @@ (enable-interpol-syntax) (defun object-to-template-vars (object) - (dolist (slot-name (mapcar #'mop:slot-definition-name (mop:class-slots (class-of object)))) + (dolist (slot-name (mapcar #'closer-mop:slot-definition-name (closer-mop:class-slots (class-of object)))) (when (and (slot-boundp object slot-name) (slot-value object slot-name)) (setf (get-template-var (make-keyword-from-string (symbol-name slot-name))) @@ -20,16 +20,16 @@ (if (parse-integer key :junk-allowed t) (find-store-object (parse-integer key :junk-allowed t)) (find-user key)) - (bknr-request-user)))) + (bknr-session-user)))) -(define-bknr-tag profile-editor (&key children) - (when (anonymous-p (bknr-request-user)) +(define-bknr-tag profile-editor () + (when (anonymous-p (bknr-session-user)) (warn "User not logged in") (html (:h2 "Please log in to edit the profile")) (return-from profile-editor)) (let ((participant (participant-from-request))) - (unless (or (admin-p (bknr-request-user)) - (eq participant (bknr-request-user))) + (unless (or (admin-p (bknr-session-user)) + (eq participant (bknr-session-user))) (html (:h2 "can't edit this profile")) (return-from profile-editor)) (when (eq :post (request-method)) @@ -91,7 +91,7 @@ (setf (participant-text participant) text))))) (object-to-template-vars participant) (let ((*participant* participant)) - (mapc #'emit-template-node children)))) + (emit-tag-children)))) (defun document-file-info (document) (with-open-file (document-file (blob-pathname document)) @@ -104,7 +104,7 @@ (defun submission-from-request () (find-store-object (parse-integer (get-template-var :*path-arg*)))) -(define-bknr-tag submission-editor (&key children) +(define-bknr-tag submission-editor () (let ((submission (submission-from-request))) (unless submission (html (:h2 "Invalid submission ID")) @@ -143,10 +143,10 @@ (setf (submission-abstract submission) abstract))))) (object-to-template-vars submission) (let ((*submission* submission)) - (mapc #'emit-template-node children)))) + (emit-tag-children)))) -(define-bknr-tag add-participant (&key children) - (unless (admin-p (bknr-request-user)) +(define-bknr-tag add-participant () + (unless (admin-p (bknr-session-user)) (html "You must be logged in as adminstrator to create new participants") (return-from add-participant)) (with-query-params (action) @@ -159,7 +159,7 @@ (make-participant login :full-name full-name :email email :text text :submission submission) (html (:princ-safe #?"The participant $(login) has been created in the database and a welcome mail has been sent."))))) - (mapc #'emit-template-node children)) + (emit-tag-children)) (define-bknr-tag submission-option-list () (dolist (submission (sort (copy-list (class-instances 'submission)) @@ -193,14 +193,14 @@ (:ul (dolist (participant (set-difference (class-instances 'participant) submitters)) (html (:li ((:a :href (format nil "~A?add-submitter-id=~A" - (puri:uri-path (request-uri)) + (script-name) (store-object-id participant))) (:princ-safe (user-full-name participant))))))))) (remove-submitter (html (:strong "Remove Submitter") (:ul (dolist (participant submitters) - (html (:li ((:a :href (format nil "~A?remove-submitter-id=~A" (puri:uri-path (request-uri)) (store-object-id participant))) + (html (:li ((:a :href (format nil "~A?remove-submitter-id=~A" (script-name) (store-object-id participant))) (:princ-safe (user-full-name participant)))))))))))))) (define-bknr-tag submission-uploader () @@ -252,27 +252,27 @@ (html ((:img :src (format-object-id "/image/~A/cell" image))))) (:span ((:a :href (format-object-id "/profile/~A" participant)) (:princ-safe (user-full-name participant))) - (when (or (eq participant (bknr-request-user)) - (admin-p (bknr-request-user))) + (when (or (eq participant (bknr-session-user)) + (admin-p (bknr-session-user))) (html " " ((:a :href (format-object-id "/edit-profile/~A" participant)) "[Edit]"))))))))) -(define-bknr-tag participants-only (&key children error) - (if (participant-p (bknr-request-user)) - (mapc #'emit-template-node children) +(define-bknr-tag participants-only (&key error) + (if (participant-p (bknr-session-user)) + (emit-tag-children) (when error (html (:princ-safe error))))) -(define-bknr-tag admin-only (&key children error) - (if (admin-p (bknr-request-user)) - (mapc #'emit-template-node children) +(define-bknr-tag admin-only (&key error) + (if (admin-p (bknr-session-user)) + (emit-tag-children) (when error (html (:princ-safe error))))) -(define-bknr-tag profile (&key children) +(define-bknr-tag profile () (let* ((participant (participant-from-request))) (object-to-template-vars participant) (let ((*participant* participant)) - (mapc #'emit-template-node children)))) + (emit-tag-children)))) (define-bknr-tag participant-picture-image (&key (width 20) (height 20)) (when (participant-picture *participant*) @@ -287,7 +287,7 @@ (html "[no submission]"))) (define-bknr-tag login-widget () - (let ((user (bknr-request-user))) + (let ((user (bknr-session-user))) (cond ((anonymous-p user) (html ((:form :method "post") @@ -300,15 +300,15 @@ ((:button :type "submit" :name "action" :value "login") "login")))) (t (html ((:form :method "post" :action (website-make-path *website* "logout")) - ((:input :type "hidden" :name "url" :value (puri:uri-path (request-uri)))) + ((:input :type "hidden" :name "url" :value (script-name))) (:div "Logged in as " :br ((:a :href (format-object-id "/edit-profile/~A" user)) (:princ-safe (user-full-name user)))) (:div ((:button :type "submit" :name "action" :value "logout") "logout")))))))) -(define-bknr-tag admin-only (&key children) - (when (admin-p (bknr-request-user)) - (mapc #'emit-template-node children))) +(define-bknr-tag admin-only () + (when (admin-p (bknr-session-user)) + (emit-tag-children))) (defun parse-duration (string) (ignore-errors @@ -318,7 +318,7 @@ (define-bknr-tag schedule-submission () (when (eq :post (request-method)) (with-query-params (date time duration submission freetext) - (let ((start (ext:parse-time (format nil "~A ~A" date time) :default-zone -2)) ; XXX hardcoded time zone + (let ((start (parse-time (format nil "~A ~A" date time) :default-zone -2)) ; XXX hardcoded time zone (duration (parse-duration duration)) (submission (ignore-errors (store-object-with-id (parse-integer submission :junk-allowed t))))) (cond @@ -380,17 +380,17 @@ (html (:li ((:a :href (format-object-id "/pdf/~A" document) :target "_new") (:princ-safe (document-info document)) " " (:princ-safe (document-file-info document))))))))) -(define-bknr-tag load-argument-object (&key children) +(define-bknr-tag load-argument-object () (let* ((object (object-from-request))) (object-to-template-vars object) (setf (get-template-var :object-id) (store-object-id object)) - (mapc #'emit-template-node children))) + (emit-tag-children))) -(define-bknr-tag page (&key children name) +(define-bknr-tag page (&key name) (setf (get-template-var :title) name) (setf (get-template-var :base) (website-base-href *website*)) (let* ((expander bknr.web::*template-expander*) (pathname (find-template-pathname expander "toplevel")) (toplevel (bknr.web::get-cached-template pathname expander)) - (bknr.web::*toplevel-children* children)) + (bknr.web::*toplevel-children* bknr.web::*tag-children*)) (emit-template-node toplevel))) \ No newline at end of file Modified: branches/trunk-reorg/projects/lisp-ecoop/src/webserver.lisp ============================================================================== --- branches/trunk-reorg/projects/lisp-ecoop/src/webserver.lisp (original) +++ branches/trunk-reorg/projects/lisp-ecoop/src/webserver.lisp Sat Feb 2 17:54:13 2008 @@ -9,8 +9,7 @@ (defun make-daily-statistics () (bknr.stats::make-yesterdays-stats :delete-events t :remove-referer-hosts '("lisp-ecoop.bknr.net"))) -#+(or) -(defun publish-lisp-ecoop (&key (port *webserver-port*) (listeners 20) (base-href *base-path*)) +(defun publish-lisp-ecoop (&key (base-href *base-path*)) (unless (bknr.cron:cron-job-with-name "daily webserver statistics") (bknr.cron:make-cron-job "daily webserver statistics" 'make-daily-statistics @@ -23,24 +22,23 @@ :template-command-packages '((:lisp-ecoop . :lisp-ecoop.tags) (:bknr . :bknr.web) (:menu . :bknr.site-menu)) - :handler-definitions `(("/" redirect-handler + :handler-definitions `(user images + #+(or) stats + #+(or) mailinglist + #+(or) mailinglist-registration + participants schedule + ("/" redirect-handler :to "home") ("/static" directory-handler - :destination ,(unix-namestring (merge-pathnames #p"static/" *website-directory*)))) - :modules '(user images stats mailinglist mailinglist-registration participants schedule) - + :destination ,(probe-file (merge-pathnames #p"static/" *website-directory*)))) :admin-navigation nil :authorizer (make-instance 'bknr-authorizer) :style-sheet-urls (list (format nil "~Astatic/styles.css" base-href)) - :javascript-urls (list (format nil "~Astatic/javascript.js" base-href))) - - (start :port port :listeners listeners)) + :javascript-urls (list (format nil "~Astatic/javascript.js" base-href)))) (defun start-webserver (&key (port 9000)) (when (and (boundp '*server*) *server*) (stop-server *server*)) - (setq *dispatch-table* - (list 'dispatch-easy-handlers - (create-folder-dispatcher-and-handler "/" *website-directory*))) + (publish-lisp-ecoop) (setq *server* (start-server :port port))) \ No newline at end of file Modified: branches/trunk-reorg/projects/quickhoney/src/tags.lisp ============================================================================== --- branches/trunk-reorg/projects/quickhoney/src/tags.lisp (original) +++ branches/trunk-reorg/projects/quickhoney/src/tags.lisp Sat Feb 2 17:54:13 2008 @@ -1,4 +1,7 @@ (in-package :quickhoney.tags) -(define-bknr-tag version-and-last-change () - (html "v1.0 | updated " (:princ-safe (string-downcase (substitute #\Space #\- (format-date-time (last-image-upload-timestamp) :vms-style t :show-time nil)))))) \ No newline at end of file +(define-bknr-tag version-and-last-change (&rest args) + (format *debug-io* "hello world: ~A~%" args) + (html "v1.1 | updated " (:princ-safe (string-downcase + (substitute #\Space #\- + (format-date-time (last-image-upload-timestamp) :vms-style t :show-time nil)))))) \ No newline at end of file Modified: branches/trunk-reorg/projects/quickhoney/src/webserver.lisp ============================================================================== --- branches/trunk-reorg/projects/quickhoney/src/webserver.lisp (original) +++ branches/trunk-reorg/projects/quickhoney/src/webserver.lisp Sat Feb 2 17:54:13 2008 @@ -42,8 +42,8 @@ :content-type "application/x-icon") ("/" template-handler :destination ,(namestring (merge-pathnames "templates/" *website-directory*)) - :command-packages ((:quickhoney . :quickhoney.tags) - (:bknr . :bknr.web)))) + :command-packages (("http://quickhoney.com/" . :quickhoney.tags) + ("http://bknr.net/" . :bknr.web)))) :admin-navigation '(("user" . "/user/") ("images" . "/edit-images") ("import" . "/import") Modified: branches/trunk-reorg/projects/quickhoney/website/templates/frontpage.xml ============================================================================== --- branches/trunk-reorg/projects/quickhoney/website/templates/frontpage.xml (original) +++ branches/trunk-reorg/projects/quickhoney/website/templates/frontpage.xml Sat Feb 2 17:54:13 2008 @@ -8,8 +8,7 @@ > - + QuickHoney - Nana Rausch + Peter Stemmler Modified: branches/trunk-reorg/projects/quickhoney/website/templates/index.xml ============================================================================== --- branches/trunk-reorg/projects/quickhoney/website/templates/index.xml (original) +++ branches/trunk-reorg/projects/quickhoney/website/templates/index.xml Sat Feb 2 17:54:13 2008 @@ -3,8 +3,8 @@ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> @@ -35,7 +35,7 @@

-

+

Modified: branches/trunk-reorg/projects/saugnapf/src/saugnapf.lisp ============================================================================== --- branches/trunk-reorg/projects/saugnapf/src/saugnapf.lisp (original) +++ branches/trunk-reorg/projects/saugnapf/src/saugnapf.lisp Sat Feb 2 17:54:13 2008 @@ -35,7 +35,7 @@ (defmethod authorized-p ((handler saugnapf-track-handler)) (let* ((track (object-handler-get-object handler)) - (user (bknr-request-user)) + (user (bknr-session-user)) (action (query-param "action")) (action-keyword (when action (make-keyword-from-string action)))) (cond ((anonymous-p user) nil) @@ -82,7 +82,7 @@ :artist artist :description description :url url - :submitter (bknr-request-user) + :submitter (bknr-session-user) :date (get-universal-time)))) (redirect (edit-object-url track))))) Modified: branches/trunk-reorg/thirdparty/cl+ssl/ffi.lisp ============================================================================== --- branches/trunk-reorg/thirdparty/cl+ssl/ffi.lisp (original) +++ branches/trunk-reorg/thirdparty/cl+ssl/ffi.lisp Sat Feb 2 17:54:13 2008 @@ -244,5 +244,6 @@ (defun reload () (cffi:load-foreign-library 'libssl) (cffi:load-foreign-library 'libeay32) + (cffi:load-foreign-library 'libcrypto) (setf *ssl-global-context* nil) (setf *ssl-global-method* nil)) Modified: branches/trunk-reorg/thirdparty/cl+ssl/reload.lisp ============================================================================== --- branches/trunk-reorg/thirdparty/cl+ssl/reload.lisp (original) +++ branches/trunk-reorg/thirdparty/cl+ssl/reload.lisp Sat Feb 2 17:54:13 2008 @@ -27,3 +27,8 @@ (:windows "libeay32.dll")) (cffi:use-foreign-library libeay32) + +(cffi:define-foreign-library libcrypto + #+freebsd (:unix "libcrypto.so")) + +(cffi:use-foreign-library libcrypto) \ No newline at end of file From hhubner at common-lisp.net Sat Feb 2 23:30:01 2008 From: hhubner at common-lisp.net (hhubner at common-lisp.net) Date: Sat, 2 Feb 2008 18:30:01 -0500 (EST) Subject: [bknr-cvs] r2439 - in branches/trunk-reorg: bknr/web/src projects/quickhoney/src Message-ID: <20080202233001.5720569155@common-lisp.net> Author: hhubner Date: Sat Feb 2 18:30:00 2008 New Revision: 2439 Modified: branches/trunk-reorg/bknr/web/src/bknr-web.asd branches/trunk-reorg/projects/quickhoney/src/handlers.lisp Log: Commit smaller fixes before trying a merge from the bos branch Modified: branches/trunk-reorg/bknr/web/src/bknr-web.asd ============================================================================== --- branches/trunk-reorg/bknr/web/src/bknr-web.asd (original) +++ branches/trunk-reorg/bknr/web/src/bknr-web.asd Sat Feb 2 18:30:00 2008 @@ -22,7 +22,6 @@ :depends-on (:cl-interpol :cl-ppcre :cl-gd - :kmrcl :alexandria :md5 :cxml Modified: branches/trunk-reorg/projects/quickhoney/src/handlers.lisp ============================================================================== --- branches/trunk-reorg/projects/quickhoney/src/handlers.lisp (original) +++ branches/trunk-reorg/projects/quickhoney/src/handlers.lisp Sat Feb 2 18:30:00 2008 @@ -39,7 +39,7 @@ (get-keywords-intersection-store-images (mapcar #'make-keyword-from-string (decoded-handler-path handler)))) #'< :key #'blob-timestamp)) -(defmethod image-to-javascript ((image quickhoney-image) &optional stream) +(defmethod image-to-javascript ((image quickhoney-image)) (format nil " new parent.ServerImage(~S, ~D, ~S, ~D, ~D, ~S)" (store-image-name image) (store-object-id image) From hhubner at common-lisp.net Sat Feb 2 23:40:28 2008 From: hhubner at common-lisp.net (hhubner at common-lisp.net) Date: Sat, 2 Feb 2008 18:40:28 -0500 (EST) Subject: [bknr-cvs] r2440 - branches/trunk-reorg/projects/bos Message-ID: <20080202234028.82597691CB@common-lisp.net> Author: hhubner Date: Sat Feb 2 18:40:28 2008 New Revision: 2440 Removed: branches/trunk-reorg/projects/bos/ Log: remove bos projects to do a full fetch from the branch From hhubner at common-lisp.net Sat Feb 2 23:43:53 2008 From: hhubner at common-lisp.net (hhubner at common-lisp.net) Date: Sat, 2 Feb 2008 18:43:53 -0500 (EST) Subject: [bknr-cvs] r2441 - branches/trunk-reorg/projects/bos Message-ID: <20080202234353.9C24E69156@common-lisp.net> Author: hhubner Date: Sat Feb 2 18:43:53 2008 New Revision: 2441 Added: branches/trunk-reorg/projects/bos/ - copied from r2440, branches/bos/projects/bos/ Log: copied over bos project from bos branch From hhubner at common-lisp.net Tue Feb 5 20:59:13 2008 From: hhubner at common-lisp.net (hhubner at common-lisp.net) Date: Tue, 5 Feb 2008 15:59:13 -0500 (EST) Subject: [bknr-cvs] r2442 - trunk/projects/lisp-ecoop/website/templates Message-ID: <20080205205913.95BF53C0D0@common-lisp.net> Author: hhubner Date: Tue Feb 5 15:59:12 2008 New Revision: 2442 Modified: trunk/projects/lisp-ecoop/website/templates/lisp-ecoop.xsl Log: Dummy commit to check whether update mechanics work. Modified: trunk/projects/lisp-ecoop/website/templates/lisp-ecoop.xsl ============================================================================== --- trunk/projects/lisp-ecoop/website/templates/lisp-ecoop.xsl (original) +++ trunk/projects/lisp-ecoop/website/templates/lisp-ecoop.xsl Tue Feb 5 15:59:12 2008 @@ -14,7 +14,7 @@ - LISP-ECOOP07 - $(title) + European Lisp Workshop 2008 - $(title) @@ -62,4 +62,4 @@
- \ No newline at end of file + From hhubner at common-lisp.net Tue Feb 5 21:04:48 2008 From: hhubner at common-lisp.net (hhubner at common-lisp.net) Date: Tue, 5 Feb 2008 16:04:48 -0500 (EST) Subject: [bknr-cvs] r2443 - trunk/projects/lisp-ecoop/website/templates Message-ID: <20080205210448.D8B934D042@common-lisp.net> Author: hhubner Date: Tue Feb 5 16:04:47 2008 New Revision: 2443 Modified: trunk/projects/lisp-ecoop/website/templates/lisp-ecoop.xsl Log: another test checkin Modified: trunk/projects/lisp-ecoop/website/templates/lisp-ecoop.xsl ============================================================================== --- trunk/projects/lisp-ecoop/website/templates/lisp-ecoop.xsl (original) +++ trunk/projects/lisp-ecoop/website/templates/lisp-ecoop.xsl Tue Feb 5 16:04:47 2008 @@ -1,6 +1,6 @@ + xmlns:lisp-ecoop="http://elw.bknr.net/"> xml @@ -21,7 +21,7 @@
+ + From hhubner at common-lisp.net Wed Feb 6 13:55:34 2008 From: hhubner at common-lisp.net (hhubner at common-lisp.net) Date: Wed, 6 Feb 2008 08:55:34 -0500 (EST) Subject: [bknr-cvs] r2448 - trunk/projects/lisp-ecoop/website/templates Message-ID: <20080206135534.88E017A029@common-lisp.net> Author: hhubner Date: Wed Feb 6 08:55:33 2008 New Revision: 2448 Modified: trunk/projects/lisp-ecoop/website/templates/lisp-ecoop.xsl trunk/projects/lisp-ecoop/website/templates/toplevel.xml Log: Add link to top-level ELW directory Modified: trunk/projects/lisp-ecoop/website/templates/lisp-ecoop.xsl ============================================================================== --- trunk/projects/lisp-ecoop/website/templates/lisp-ecoop.xsl (original) +++ trunk/projects/lisp-ecoop/website/templates/lisp-ecoop.xsl Wed Feb 6 08:55:33 2008 @@ -33,6 +33,11 @@ +
Modified: trunk/projects/lisp-ecoop/website/templates/toplevel.xml ============================================================================== --- trunk/projects/lisp-ecoop/website/templates/toplevel.xml (original) +++ trunk/projects/lisp-ecoop/website/templates/toplevel.xml Wed Feb 6 08:55:33 2008 @@ -41,6 +41,11 @@
+
From hhubner at common-lisp.net Thu Feb 7 08:16:34 2008 From: hhubner at common-lisp.net (hhubner at common-lisp.net) Date: Thu, 7 Feb 2008 03:16:34 -0500 (EST) Subject: [bknr-cvs] r2449 - in branches/trunk-reorg/thirdparty: hunchentoot-0.14.7 hunchentoot-0.15.0 hunchentoot-0.15.0/doc hunchentoot-0.15.0/test Message-ID: <20080207081634.ED7591203D@common-lisp.net> Author: hhubner Date: Thu Feb 7 03:16:29 2008 New Revision: 2449 Added: branches/trunk-reorg/thirdparty/hunchentoot-0.15.0/ branches/trunk-reorg/thirdparty/hunchentoot-0.15.0/CHANGELOG (contents, props changed) branches/trunk-reorg/thirdparty/hunchentoot-0.15.0/CHANGELOG_TBNL branches/trunk-reorg/thirdparty/hunchentoot-0.15.0/README (contents, props changed) branches/trunk-reorg/thirdparty/hunchentoot-0.15.0/conditions.lisp (contents, props changed) branches/trunk-reorg/thirdparty/hunchentoot-0.15.0/cookie.lisp branches/trunk-reorg/thirdparty/hunchentoot-0.15.0/doc/ branches/trunk-reorg/thirdparty/hunchentoot-0.15.0/doc/LICENSE.txt (contents, props changed) branches/trunk-reorg/thirdparty/hunchentoot-0.15.0/doc/hunchentoot.gif (contents, props changed) branches/trunk-reorg/thirdparty/hunchentoot-0.15.0/doc/index.html (contents, props changed) branches/trunk-reorg/thirdparty/hunchentoot-0.15.0/easy-handlers.lisp (contents, props changed) branches/trunk-reorg/thirdparty/hunchentoot-0.15.0/headers.lisp (contents, props changed) branches/trunk-reorg/thirdparty/hunchentoot-0.15.0/hunchentoot-test.asd (contents, props changed) branches/trunk-reorg/thirdparty/hunchentoot-0.15.0/hunchentoot.asd (contents, props changed) branches/trunk-reorg/thirdparty/hunchentoot-0.15.0/log.lisp branches/trunk-reorg/thirdparty/hunchentoot-0.15.0/mime-types.lisp branches/trunk-reorg/thirdparty/hunchentoot-0.15.0/misc.lisp (contents, props changed) branches/trunk-reorg/thirdparty/hunchentoot-0.15.0/packages.lisp (contents, props changed) branches/trunk-reorg/thirdparty/hunchentoot-0.15.0/port-acl.lisp branches/trunk-reorg/thirdparty/hunchentoot-0.15.0/port-clisp.lisp branches/trunk-reorg/thirdparty/hunchentoot-0.15.0/port-cmu.lisp branches/trunk-reorg/thirdparty/hunchentoot-0.15.0/port-lw.lisp (contents, props changed) branches/trunk-reorg/thirdparty/hunchentoot-0.15.0/port-mcl.lisp branches/trunk-reorg/thirdparty/hunchentoot-0.15.0/port-sbcl.lisp branches/trunk-reorg/thirdparty/hunchentoot-0.15.0/reply.lisp branches/trunk-reorg/thirdparty/hunchentoot-0.15.0/request.lisp branches/trunk-reorg/thirdparty/hunchentoot-0.15.0/server.lisp (contents, props changed) branches/trunk-reorg/thirdparty/hunchentoot-0.15.0/session.lisp branches/trunk-reorg/thirdparty/hunchentoot-0.15.0/specials.lisp (contents, props changed) branches/trunk-reorg/thirdparty/hunchentoot-0.15.0/test/ branches/trunk-reorg/thirdparty/hunchentoot-0.15.0/test/UTF-8-demo.html branches/trunk-reorg/thirdparty/hunchentoot-0.15.0/test/favicon.ico (contents, props changed) branches/trunk-reorg/thirdparty/hunchentoot-0.15.0/test/fz.jpg (contents, props changed) branches/trunk-reorg/thirdparty/hunchentoot-0.15.0/test/packages.lisp (contents, props changed) branches/trunk-reorg/thirdparty/hunchentoot-0.15.0/test/test.lisp branches/trunk-reorg/thirdparty/hunchentoot-0.15.0/unix-acl.lisp branches/trunk-reorg/thirdparty/hunchentoot-0.15.0/unix-clisp.lisp branches/trunk-reorg/thirdparty/hunchentoot-0.15.0/unix-cmu.lisp branches/trunk-reorg/thirdparty/hunchentoot-0.15.0/unix-lw.lisp (contents, props changed) branches/trunk-reorg/thirdparty/hunchentoot-0.15.0/unix-mcl.lisp branches/trunk-reorg/thirdparty/hunchentoot-0.15.0/unix-sbcl.lisp branches/trunk-reorg/thirdparty/hunchentoot-0.15.0/util.lisp (contents, props changed) Removed: branches/trunk-reorg/thirdparty/hunchentoot-0.14.7/ Log: update hunchentoot Added: branches/trunk-reorg/thirdparty/hunchentoot-0.15.0/CHANGELOG ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/hunchentoot-0.15.0/CHANGELOG Thu Feb 7 03:16:29 2008 @@ -0,0 +1,281 @@ +Version 0.15.0 +2007-12-29 +Added support for CLISP (thanks to Anton Vodonosov) + +Version 0.14.7 +2007-11-15 +Replace ENOUGH-NAMESTRING with ENOUGH-URL (patch by Kilian Sprotte and Hans H?bner) + +Version 0.14.6 +2007-11-08 +Fix compilation order (thanks to Tiarnan O'Corrain and Chris Dean) + +Version 0.14.5 +2007-10-21 +Robustified MAKE-SOCKET-STREAM against potential leak (thanks to Alain Picard) +Replaced #-FOO #-FOO constructs for OpenMCL (patch by Michael Weber) +Updated tutorial links + +Version 0.14.4 +2007-10-20 +Made log stream shared on OpenMCL (thanks to Gary Byers) + +Version 0.14.3 +2007-10-07 +Enabled GET-GID-FROM-NAME for newer versions of SBCL (patch by Cyrus Harmon) + +Version 0.14.2 +2007-09-26 +Better handling of PORT parameter in REDIRECT (thanks to Vladimir Sedach) + +Version 0.14.1 +2007-09-24 +Fixed bug where you couldn't set "Server" header (caught by Ralf Mattes) +Documentation clarification for HEADER-OUR function + +Version 0.14.0 +2007-09-18 +Added support for "HttpOnly" cookie attribute + +Version 0.13.0 +2007-09-14 +Added *METHODS-FOR-POST-PARAMETERS* (suggested by Jonathon McKitrick) + +Version 0.12.1 +2007-09-13 +Better support for WITH-TIMEOUT on SBCL/Win32 (thanks to Anton Vodonosov) + +Version 0.12.0 +2007-09-07 +Now uses bound for flexi stream returned by RAW-POST-DATA +Needs FLEXI-STREAMS 0.12.0 or higher + +Version 0.11.2 +2007-09-05 +Fixed typo in docs +Added declaration in server.lisp to appease SBCL + +Version 0.11.1 +2007-05-25 +Fixes for OpenMCL (thanks to Lennart Staflin and Tiarnan O'Corrain) + +Version 0.11.0 +2007-05-25 +Added server names and coupled them with easy handlers (suggested by Mac Chan) +Exported SESSION-COOKIE-VALUE instead of SESSION-STRING (suggested by Slava Akhmechet) +Documentation fixes (thanks to Victor Kryukov and Igor Plekhov) + +Version 0.10.0 +2007-05-12 +Made MAYBE-INVOKE-DEBUGGER a generic function and exported it (suggested by Vladimir Sedach) + +Version 0.9.3 +2007-05-08 +Fixed CREATE-FOLDER-DISPATCHER-AND-HANDLER in the presence of URL-encoded URLs (bug caught by Nicolas Lamirault) + +Version 0.9.2 +2007-05-01 +Made DEF-HTTP-RETURN-CODE more flexible (suggested by Jong-won Choi) + +Version 0.9.1 +2007-04-29 +Added PORT parameter to REDIRECT (suggested by Cyrus Harmon) +Exported REMOVE-SESSION (suggested by Vamsee Kanakala) + +Version 0.9.0 +2007-04-19 +Added socket timeouts for AllegroCL +Catch IO timeout conditions for AllegroCL, SBCL and CMUCL (suggested by Red Daly and others) +Added per-server dispatch tables (suggested by Robert Synnott and Andrei Stebakov) + +Version 0.8.6 +2007-04-18 +USE the CL package explicitly when defining HUNCHENTOOT-MP (bug report by Joel Boehland) + +Version 0.8.5 +2007-04-10 +Correct behaviour for "100 Continue" responses + +Version 0.8.4 +2007-04-09 +Cleanup + +Version 0.8.3 +2007-04-07 +Don't use chunked encoding for empty (NIL) bodies + +Version 0.8.2 +2007-04-05 +Really exported REASON-PHRASE this time (and also *CURRENT-PROCESS*) + +Version 0.8.1 +2007-04-04 +Added HUNCHENTOOT-MP package (suggested by Cyrus Harmon) +Only invoke MARK-AND-SWEEP for 32-bit versions of LW (thanks to Chris Dean) +Exported REASON-PHRASE + +Version 0.8.0 +2007-03-31 +Added *APPROVED-RETURN-CODES*, *HEADER-STREAM*, and +HTTP-FAILED-DEPENDENCY+ +Exported MIME-TYPE and SSL-P +Some minor changes + +Version 0.7.3 +2007-03-28 +Added +HTTP-MULTI-STATUS+ + +Version 0.7.2 +2007-03-09 +Fix test suite to properly handle non-base characters in LW (bug caught by Jong-won Choi) + +Version 0.7.1 +2007-03-09 +Fixed last change (thanks to Marko Kocic) + +Version 0.7.0 +2007-03-09 +Development port (no threads) to SBCL/Win32 (patch by Marko Kocic) +Support for compilation without SSL + +Version 0.6.2 +2007-02-22 +Don't use NSTRING-UPCASE for outgoing headers (bug caught by Saurabh Nanda) +Changed ProxyPass example in docs from /lisp to /hunchentoot + +Version 0.6.1 +2007-01-24 +Reset to "faithful" external format on each iteration (bug caught by Viljo Marrandi and Ury Marshak) + +Version 0.6.0 +2007-01-23 +Accept chunked transfer encoding for mod_lisp request bodies (thanks to Hugh Winkler's mod_lisp additions) +Robustify against erroneous form-data submissions (caught by Ury Marshak) + +Version 0.5.1 +2007-01-18 +Even more flexible behaviour of RAW-POST-DATA + +Version 0.5.0 +2007-01-17 +More flexible behaviour of RAW-POST-DATA +Robustified PARSE-CONTENT-TYPE + +Version 0.4.14 +2007-01-17 +More meaningful results for RAW-POST-DATA + +Version 0.4.13 +2007-01-14 +Added favicon.ico to example website (thanks to Yoni Rabkin Katzenell, Toby, and Uwe von Loh) + +Version 0.4.12 +2006-12-27 +Added Hunchentoot logo by Uwe von Loh + +Version 0.4.11 +2006-12-01 +Exported symbols related to session GC (suggested by Nico de Jager) + +Version 0.4.10 +2006-11-19 +Added *HANDLE-HTTP-ERRORS-P* (thanks to Marijn Haverbeke) +Remove duplicate headers when reading from mod_lisp + +Version 0.4.9 +2006-11-12 +Fixed HEADER-OUT (thanks to Robert J. Macomber) + +Version 0.4.8 +2006-11-06 +Fixed bug in START-OUTPUT which confused mod_lisp + +Version 0.4.7 +2006-11-06 +Changed behaviour of REAL-REMOTE-ADDR (as suggested by Robert J. Macomber) +Fixed COOKIE-OUT (thanks to Robert J. Macomber) + +Version 0.4.6 +2006-11-05 +Don't bind *DISPATCH-TABLE* too early (thanks to Marijn Haverbeke) + +Version 0.4.5 +2006-10-25 +Fixed bug in AUTHORIZATION function (reported by Michael J. Forster) + +Version 0.4.4 +2006-10-12 +Correct SSL check in REDIRECT function +LOG-MESSAGE now checks for (BOUNDP '*SERVER*) + +Version 0.4.3 +2006-10-11 +OpenMCL fixes (by Ralf Stoye) + +Version 0.4.2 +2006-10-10 +No timeouts for mod_lisp servers (as in Hunchentoot 0.3.x) + +Version 0.4.1 +2006-10-10 +Fixed a typo in easy-handlers.lisp (caught by Travis Cross) + +Version 0.4.0 +2006-10-10 +Ported to CMUCL, SBCL, OpenMCL, and AllegroCL +Merged with TBNL +Tons of small changes, too many to list them individually + +Version 0.3.2 +2006-09-14 +Uses TBNL's WITH-DEBUGGER now + +Version 0.3.1 +2006-09-14 +Added *CATCH-ERRORS-P* (from TBNL) + +Version 0.3.0 +2006-09-05 +Accept HTTP requests with chunked transfer encoding +Use Chunga for chunking + +Version 0.2.2 +2006-08-31 +Skip START-OUTPUT advice completely if working for TBNL + +Version 0.2.1 +2006-08-28 +Added write timeouts for LW 5.0 +Updated LW links in documentation + +Version 0.2.0 +2006-08-28 +Serves as infrastructure for TBNL now (to replace KMRCL) +For HTTP/1.1 only send 'Keep-Alive' headers if explicitly requested + +Version 0.1.5 +2006-08-23 +Connection headers are separated by commas, not semicolons + +Version 0.1.4 +2006-08-22 +Refactored streams.lisp to appease LW compiler (thanks to Martin Simmons) +Changed handling of version string +Changed package handling in system definition (thanks to Christophe Rhodes) + +Version 0.1.3 +2006-02-08 +Removed KMRCL workaround + +Version 0.1.2 +2006-01-03 +Mention TBNL version number in server name header + +Version 0.1.1 +2005-12-31 +Fixed package stuff and HYPERDOC support + +Version 0.1.0 +2005-12-31 +Initial public release + +[For earlier changes see the file "CHANGELOG_TBNL" that is included with the release.] Added: branches/trunk-reorg/thirdparty/hunchentoot-0.15.0/CHANGELOG_TBNL ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/hunchentoot-0.15.0/CHANGELOG_TBNL Thu Feb 7 03:16:29 2008 @@ -0,0 +1,340 @@ +Version 0.11.3 +2006-09-30 +Added *FILE-UPLOAD-HOOK* (suggested by Erik Enge) +Fixed DEFINE-EASY-HANDLER for cases where URI is NIL + +Version 0.11.2 +2006-09-20 +DEFINE-EASY-HANDLER: fixed and clarified redefinition +DEFINE-EASY-HANDLER: allow for functions designators as "URIs" +DEFINE-EASY-HANDLER: take file uploads into account +Made logging a little bit more robust +Added mime type for XSL-FO (.fo) + +Version 0.11.1 +2006-09-14 +Cleaner implementation of *CATCH-ERRORS-P* + +Version 0.11.0 +2006-09-14 +Added *CATCH-ERRORS-P* + +Version 0.10.3 +2006-09-05 +Appease SBCL (thanks to Juho Snellman) + +Version 0.10.2 +2006-09-05 +Better reporting of IP addresses and ports if not behind mod_lisp +Improved logging +Fixed REAL-REMOTE-ADDR +Cookies always use UTF-8 encoding (which is opaque to the client anyway) +Read request bodies without 'Content-Length' header (for Hunchentoot) +Removed accented character from test.lisp to appease SBCL (reported by Xristos Kalkanis) + +Version 0.10.1 +2006-08-31 +Only LispWorks: Set read timeout to NIL if connected to mod_lisp + +Version 0.10.0 +2006-08-28 +Based LispWorks version of TBNL on Hunchentoot infrastructure +Added "easy" handlers +Exported GET-BACKTRACE (suggested by Erik Enge) + +Version 0.9.11 +2006-08-16 +Added note about SBCL problems + +Version 0.9.10 +2006-05-24 +Prepare for LW 5.0 release + +Version 0.9.9 +2006-05-12 +Workaround for something like "application/x-www-form-urlencoded;charset=UTF-8" (caught by John Bates) + +Version 0.9.8 +2006-04-25 +For mod_lisp, Lisp-Content-Length header must be sent after Content-Length header + +Version 0.9.7 +2006-02-06 +More robust computation of content length + +Version 0.9.6 +2006-01-22 +Added the missing piece (argh!) + +Version 0.9.5 +2006-01-22 +Made creation of REQUEST object safer (thanks to Robert J. Macomber) +Replaced some erroneous DECLAIMs with DECLAREs (thanks to SBCL's style warnings) +Slight documentation enhancements + +Version 0.9.4 +2006-01-03 +Handle "Expect: 100-continue" for non-Apache front-ends +Re-introduced IGNORE-ERRORS in GET-REQUEST-DATA + +Version 0.9.3 +2006-01-01 +Fixed bug in READ-HTTP-REQUEST + +Version 0.9.2 +2005-12-31 +Protocol of reply is HTTP/1.1 now +Made HTTP/0.9 default protocol of request if none was provided +Some preparations for Hunchentoot +Various minor changes +Small fixes in docs + +Version 0.9.1 +2005-12-25 +Added missing file mime-types.lisp (thanks to Hilverd Reker) + +Version 0.9.0 +2005-12-24 +Experimental support for writing directly to the front-end (see SEND-HEADERS) +Added HANDLE-STATIC-FILE +Changed CREATE-STATIC-FILE-DISPATCHER-AND-HANDLER to use new facilities +Added CREATE-FOLDER-DISPATCHER-AND-HANDLER +Added link to Travis Cross' message w.r.t. SBCL + +Version 0.8.9 +2005-12-16 +Also use :TBNL-BIVALENT-STREAMS if :SB-UNICODE is present + +Version 0.8.8 +2005-12-08 +Made RAW-POST-DATA more useful +Updated docs w.r.t. Araneida (thanks to Alan Shields) + +Version 0.8.7 +2005-11-29 +Made "Content-Length" header SETFable + +Version 0.8.6 +2005-11-18 +Restored original stream-based code for multipart/form-data parsing (got lost somehow) +Wrapped REMOTE-ADDR with IGNORE-ERRORS (just in case) + +Version 0.8.5 +2005-11-14 +Added generic function DISPATCH-REQUEST (thanks to Jeff Caldwell) + +Version 0.8.4 +2005-10-21 +Provide REMOTE-ADDR if connected directly (for LispWorks and AllegroCL) +Show remote user and address (if available) in non-Apache logs +Mention Debian package in docs + +Version 0.8.3 +2005-10-10 +Alert LW users that a patch for OCTETS-TO-STRINGS is available (thanks to LispWorks support) + +Version 0.8.2 +2005-10-06 +Make STRING-TO-OCTETS and OCTETS-TO-STRING safer for LW + +Version 0.8.1 +2005-09-29 +Bugfix in CMUCL version of STRING-TO-OCTETS + +Version 0.8.0 +2005-09-24 +Added the ability to cope with different external formats (incorporating suggestions from Will Glozer and Ivan Shvedunov) +Raw post data is now always saved (so *SAVE-RAW-POST-DATA-P* is gone) + +Version 0.7.0 +2005-09-17 +Added the ability to store arbitrary data within REQUEST objects (suggested by Zach Beane) +Fixed handling of *HTTP-ERROR-HANDLER* +Note: *TBNL-VERSION* was wrong in 0.6.0 and 0.6.1 + +Version 0.6.1 +2005-09-10 +Robustified socket handling code + +Version 0.6.0 +2005-09-08 +Added TBNL-CONTRIB package +Added contrib directory with first entry (from Alceste Scalas) +Updated link to Bill Clementson's blog +Don't redefine what's already there (for LispWorks) + +Version 0.5.5 +2005-04-18 +Make RFC 2388 code an external dependency (thanks to Janis Dzerins) + +Version 0.5.4 +2005-04-03 +Fixed dumb typo (caught by Bob Hutchison) + +Version 0.5.3 +2005-04-03 +Re-introduced automatic front-end selection (originally by Bob Hutchison) + +Version 0.5.2 +2005-03-26 +Fixed bug in modlisp.html where *CLOSE-TBNL-STREAM* could be NIL although it should be T +Set correct content type for 304 replies + +Version 0.5.1 +2005-03-17 +Changed default cookie path in START-SESSION (suggested by Stefan Scholl) +Small bugfixes +More headers from the Araneida front-end +Added *SHOW-ACCESS-LOG-MESSAGES* +Changed "back-end" to "front-end" :) + +Version 0.5.0 +2005-03-17 +Initial support for "stand-alone" version (no front-end) (supplied by Bob Hutchison) +New logging API +Fixes in START-TBNL/STOP-TBNL +Documentation enhancements + +Version 0.4.1 +2005-03-15 +Fixed some typos, removed unused code + +Version 0.4.0 +2005-03-14 +Initial Araneida support (supplied by Bob Hutchison) + +Version 0.3.13 +2005-03-12 +Small bugfix in RFC-1123-DATE (thanks to Bob Hutchison and Stefan Scholl) + +Version 0.3.12 +2005-03-01 +Added *HTTP-ERROR-HANDLER* (suggested and coded by Stefan Scholl) +Exported and documented *SESSION-MAX-TIME* + +Version 0.3.11 +2005-02-21 +Added ability to access raw post data (suggested and coded by Zach Beane) + +Version 0.3.10 +2005-01-24 +Make bivalent streams work with LispWorks 4.4 +UTF-8 demo for LispWorks (thanks to Bob Hutchison) + +Version 0.3.9 +2004-12-31 +Re-compute content length after applying MAYBE-REWRITE-URLS-FOR-SESSION (caught by Stefan Scholl) + +Version 0.3.8 +2004-12-27 +Don't send body for HEAD requests (needs current mod_lisp version) + +Version 0.3.7 +2004-12-22 +Change #\Del to #\Rubout in QUOTE-STRING (AllegroCL complains, #\Del isn't even semi-standard) + +Version 0.3.6 +2004-12-02 +Make REQUIRE-AUTHORIZATION compliant to RFC 2616 (thanks to Stefan Scholl) + +Version 0.3.5 +2004-12-01 +Several small doc fixes (thanks to Stefan Scholl) +Catch requests like "GET http://server/foo.html HTTP/1.0" (suggested by Stefan Scholl) + +Version 0.3.4 +2004-11-29 +Added backtrace code for OpenMCL (provided by Tiarn?n ? Corr?in) + +Version 0.3.3 +2004-11-22 +Cleaner handling of macro variables + +Version 0.3.2 +2004-11-11 +Updated docs for mod_lisp2 + +Version 0.3.1 +2004-11-09 +Slight changes to support Chris Hanson's mod_lisp2 +Changed GET-BACKTRACE for newer SBCL versions (thanks to Nikodemus Siivola) + +Version 0.3.0 +2004-11-09 +Initial support for multipart/form-data (thanks to Michael Weber and Janis Dzerins) +Fixed bug in CREATE-STATIC-FILE-DISPATCHER-AND-HANDLER (caught by Bill Clementson) + +Version 0.2.12 +2004-10-15 +Exported and documented DO-SESSIONS + +Version 0.2.11 +2004-09-02 +FORM-URL-ENCODED-LIST-TO-ALIST now decodes names and values + +Version 0.2.10 +2004-08-28 +Allow non-strings to be cookie values (bug caught by Zach Beane) + +Version 0.2.9 +2004-08-11 +Consistent usage of RFC-1123-DATE (provided by Stefan Scholl) +Added all missing http headers from RFC 2616 (provided by Stefan Scholl) +Added support for mod_lisp version strings (see ) +Don't always add session IDs when redirecting + +Version 0.2.8 +2004-07-24 +Fixed typo in html.lisp and improved docs (both caught by Stefan Scholl) + +Version 0.2.7 +2004-07-24 +Add missing exports and docs + +Version 0.2.6 +2004-07-24 +Make CREATE-STATIC-FILE-DISPATCHER-AND-HANDLER thread-safe (caught by Jeff Caldwell) +Added support for 'If-Modified-Since' request headers (provided by Stefan Scholl) + +Version 0.2.5 +2004-07-21 +Added CREATE-STATIC-FILE-DISPATCHER-AND-HANDLER (provided by Stefan Scholl) +Improved test suite + +Version 0.2.4 +2004-07-19 +New variable *CONTENT-TYPES-FOR-URL-REWRITE* (suggested by Stefan Scholl) +Updated index.html regarding new version of mod_lisp + +Version 0.2.3 +2004-06-12 +Bugfix for FORM-URL-ENCODED-LIST-TO-ALIST (bug caught by Jong-won Choi) + +Version 0.2.2 +2004-06-10 +Bugfix for SESSION-GC and RESET-SESSIONS (bug introduced in 0.2.0) + +Version 0.2.1 +2004-06-10 +Only create backtrace if needed (speeds up AllegroCL considerably) + +Version 0.2.0 +2004-06-07 +Added SESSION-STRING and *SESSION-REMOVAL-HOOK* +Added GET-BACKTRACE for AllegroCL + +Version 0.1.2 +2004-05-12 +Removed some more typos in docs (thanks to Karl A. Krueger) +Changed BASE64 to CL-BASE64 in .asd file (thanks to Frank Sonnemans and Nicolas Lamirault) + +Version 0.1.1 +2004-05-08 +Removed some old files from Jeff's port +Fixed a couple of typos in docs + +Version 0.1.0 +2004-05-07 +First public release +Original code by Edi Weitz +Initial doc strings, port to KMRCL, logging code and various other improvements by Jeff Caldwell Added: branches/trunk-reorg/thirdparty/hunchentoot-0.15.0/README ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/hunchentoot-0.15.0/README Thu Feb 7 03:16:29 2008 @@ -0,0 +1,2 @@ +Complete documentation for Hunchentoot including details about how to +install it can be found in the 'doc' directory. Added: branches/trunk-reorg/thirdparty/hunchentoot-0.15.0/conditions.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/hunchentoot-0.15.0/conditions.lisp Thu Feb 7 03:16:29 2008 @@ -0,0 +1,60 @@ +;;; -*- Mode: LISP; Syntax: COMMON-LISP; Package: HUNCHENTOOT; Base: 10 -*- +;;; $Header: /usr/local/cvsrep/hunchentoot/conditions.lisp,v 1.1 2007/11/08 20:07:58 edi Exp $ + +;;; Copyright (c) 2004-2007, Dr. Edmund Weitz. All rights reserved. + +;;; Redistribution and use in source and binary forms, with or without +;;; modification, are permitted provided that the following conditions +;;; are met: + +;;; * Redistributions of source code must retain the above copyright +;;; notice, this list of conditions and the following disclaimer. + +;;; * Redistributions in binary form must reproduce the above +;;; copyright notice, this list of conditions and the following +;;; disclaimer in the documentation and/or other materials +;;; provided with the distribution. + +;;; THIS SOFTWARE IS PROVIDED BY THE AUTHOR 'AS IS' AND ANY EXPRESSED +;;; OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +;;; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +;;; ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +;;; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +;;; DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +;;; GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +;;; INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +;;; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +;;; NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +;;; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +(in-package :hunchentoot) + +(defvar *catch-errors-p* t + "Whether Hunchentoot should catch and log errors \(or rather +invoke the debugger).") + +(defgeneric maybe-invoke-debugger (condition) + (:documentation "This generic function is called whenever a +condition CONDITION is signaled in Hunchentoot. You might want to +specialize it on specific condition classes for debugging purposes.") + (:method (condition) + "The default method invokes the debugger with CONDITION if +*CATCH-ERRORS-P* is NIL." + (unless *catch-errors-p* + (invoke-debugger condition)))) + +(defmacro with-debugger (&body body) + "Executes BODY and invokes the debugger if an error is signaled and +*CATCH-ERRORS-P* is NIL." + `(handler-bind ((error #'maybe-invoke-debugger)) + , at body)) + +(defmacro ignore-errors (&body body) + "Like CL:IGNORE-ERRORS, but observes *CATCH-ERRORS-P*." + `(cl:ignore-errors (with-debugger , at body))) + +(defmacro handler-case (expression &rest clauses) + "Like CL:HANDLER-CASE, but observes *CATCH-ERRORS-P*." + `(cl:handler-case (with-debugger ,expression) + , at clauses)) + Added: branches/trunk-reorg/thirdparty/hunchentoot-0.15.0/cookie.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/hunchentoot-0.15.0/cookie.lisp Thu Feb 7 03:16:29 2008 @@ -0,0 +1,121 @@ +;;; -*- Mode: LISP; Syntax: COMMON-LISP; Package: HUNCHENTOOT; Base: 10 -*- +;;; $Header: /usr/local/cvsrep/hunchentoot/cookie.lisp,v 1.7 2007/09/18 14:23:23 edi Exp $ + +;;; Copyright (c) 2004-2007, Dr. Edmund Weitz. All rights reserved. + +;;; Redistribution and use in source and binary forms, with or without +;;; modification, are permitted provided that the following conditions +;;; are met: + +;;; * Redistributions of source code must retain the above copyright +;;; notice, this list of conditions and the following disclaimer. + +;;; * Redistributions in binary form must reproduce the above +;;; copyright notice, this list of conditions and the following +;;; disclaimer in the documentation and/or other materials +;;; provided with the distribution. + +;;; THIS SOFTWARE IS PROVIDED BY THE AUTHOR 'AS IS' AND ANY EXPRESSED +;;; OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +;;; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +;;; ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +;;; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +;;; DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +;;; GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +;;; INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +;;; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +;;; NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +;;; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +(in-package :hunchentoot) + +(defclass cookie () + ((name :initarg :name + :reader cookie-name + :type string + :documentation "The name of the cookie - a string.") + (value :initarg :value + :accessor cookie-value + :initform "" + :documentation "The value of the cookie. Will be URL-encoded +when sent to the browser.") + (expires :initarg :expires + :initform nil + :accessor cookie-expires + :documentation "The time \(a universal time) when the +cookie expires \(or NIL).") + (path :initarg :path + :initform nil + :accessor cookie-path + :documentation "The path this cookie is valid for \(or NIL).") + (domain :initarg :domain + :initform nil + :accessor cookie-domain + :documentation "The domain this cookie is valid for \(or NIL).") + (secure :initarg :secure + :initform nil + :accessor cookie-secure + :documentation "A generalized boolean denoting whether this +cookie is a secure cookie.") + (http-only :initarg :http-only + :initform nil + :accessor cookie-http-only + :documentation "A generalized boolean denoting whether +this cookie is a `HttpOnly' cookie. + +This is a Microsoft extension that has been implemented in Firefox as +well. See .")) + (:documentation "Each COOKIE objects describes one outgoing cookie.")) + +(defmethod initialize-instance :around ((cookie cookie) &rest init-args) + "Ensure COOKIE has a correct slot-value for NAME." + (let ((name (getf init-args :name))) + (unless (http-token-p name) + (error "~S is not a legal name for a cookie." name))) + (call-next-method)) + +(defun set-cookie* (cookie &optional (reply *reply*)) + "Adds the COOKIE object COOKIE to the outgoing cookies of the +REPLY object REPLY. If a cookie with the same name +\(case-sensitive) already exists, it is replaced." + (let* ((name (cookie-name cookie)) + (place (assoc name (cookies-out reply) :test #'string=))) + (cond + (place + (setf (cdr place) cookie)) + (t + (push (cons name cookie) (cookies-out reply)) + cookie)))) + +(defun set-cookie (name &key (value "") expires path domain secure http-only (reply *reply*)) + "Creates a cookie object from the parameters provided and adds +it to the outgoing cookies of the REPLY object REPLY. If a cookie +with the name NAME \(case-sensitive) already exists, it is +replaced." + (set-cookie* (make-instance 'cookie + :name name + :value value + :expires expires + :path path + :domain domain + :secure secure + :http-only http-only) + reply)) + +(defun cookie-date (universal-time) + "Converts UNIVERSAL-TIME to cookie date format." + (and universal-time + (rfc-1123-date universal-time))) + +(defmethod stringify-cookie ((cookie cookie)) + "Converts the COOKIE object COOKIE to a string suitable for a +'Set-Cookie' header to be sent to the client." + (format nil + "~A=~A~:[~;~:*; expires=~A~]~:[~;~:*; path=~A~]~:[~;~:*; domain=~A~]~:[~;; secure~]~:[~;; HttpOnly~]" + (cookie-name cookie) + (url-encode (format nil "~A" (cookie-value cookie)) +utf-8+) + (cookie-date (cookie-expires cookie)) + (cookie-path cookie) + (cookie-domain cookie) + (cookie-secure cookie) + (cookie-http-only cookie))) \ No newline at end of file Added: branches/trunk-reorg/thirdparty/hunchentoot-0.15.0/doc/LICENSE.txt ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/hunchentoot-0.15.0/doc/LICENSE.txt Thu Feb 7 03:16:29 2008 @@ -0,0 +1,9 @@ +The Hunchentoot logo (the file `hunchentoot.gif' in this directory) +was created by Uwe von Loh and is available from his website at + + http://www.htg1.de/hunchentoot/hunchentoot.html + +It is licensed under a `Creative Commons Attribution-Share Alike 2.0 +Germany License', see + + http://creativecommons.org/licenses/by-sa/2.0/de/ Added: branches/trunk-reorg/thirdparty/hunchentoot-0.15.0/doc/hunchentoot.gif ============================================================================== Binary file. No diff available. Added: branches/trunk-reorg/thirdparty/hunchentoot-0.15.0/doc/index.html ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/hunchentoot-0.15.0/doc/index.html Thu Feb 7 03:16:29 2008 @@ -0,0 +1,2623 @@ + + + + + + HUNCHENTOOT - The Common Lisp web server formerly known as TBNL + + + + + + +

HUNCHENTOOT - The Common Lisp web server +formerly known as TBNL

+ +
+
 

Abstract

+ +Hunchentoot is a web server written in Common Lisp and at the same +time a toolkit for building dynamic websites. As a +stand-alone web server, Hunchentoot is capable of HTTP/1.1 chunking +(both directions), persistent connections (keep-alive), and SSL, but +it can also sit behind the +popular Apache using +Marc +Battyani's mod_lisp. + +

+ +Hunchentoot provides facilities like automatic session handling (with +and without cookies), logging (to Apache's log files or to a file in +the file system), customizable error handling, and easy access to GET +and POST parameters sent by the client. It does not include +functionality to programmatically generate HTML output. For this task +you can use any library you like, e.g. (shameless +self-plug) CL-WHO +or HTML-TEMPLATE. + +

+ +Hunchentoot talks with its front-end or with the client over TCP/IP +sockets and uses multiprocessing to handle several requests at the +same time. Therefore, it cannot be implemented completely +in portable +Common Lisp. It currently works with +LispWorks (which is the main development and testing platform), +CMUCL (with MP +support), SBCL (with +Unicode and thread support), +OpenMCL, +and Allegro Common +Lisp. (Note: You can use Hunchentoot with CLISP +or with a version of SBCL without threads, for example on Windows, +but this is not recommended except for development purposes.) Porting to other +CL implementations shouldn't be too hard, see the files port-xxx.lisp +and unix-xxx.lisp which comprise all the +implementation-specific code. + +

+ +Hunchentoot comes with a BSD-style +license so you can basically do with it whatever you want. +

+ +Hunchentoot is for example used by clutu, TwitterBuzz, +Jalat, Heike Stephan, +xOs, +and the NIST. + +

+Download shortcut: http://weitz.de/files/hunchentoot.tar.gz. +

+ +
 

Contents

+
    +
  1. Download and installation +
      +
    1. Hunchentoot behind a proxy +
    2. Hunchentoot behind mod_lisp +
    +
  2. Support and mailing lists +
  3. Examples, tutorials, add-ons +
  4. Function and variable reference +
      +
    1. Servers +
    2. Handlers +
    3. Requests +
    4. Replies +
    5. Cookies +
    6. Sessions +
    7. Logging and error handling +
    8. Debugging Hunchentoot applications +
    9. Miscellaneous +
    +
  5. The HUNCHENTOOT-MP package +
  6. Performance +
  7. History +
  8. Symbol index +
  9. Acknowledgements +
+ +
 

Download and installation

+ +Hunchentoot depends on a couple of other Lisp libraries which you'll need +to install first: + +Make sure to use the newest versions of all of these libraries (which might themselves depend on other libraries)! +Note: You can compile Hunchentoot without SSL support - and thus without the need to have CL+SSL - if you add :HUNCHENTOOT-NO-SSL to *FEATURES* before you compile it. +

+The preferred method to compile and load Hunchentoot is via ASDF. +

+Hunchentoot together with this documentation can be downloaded +from http://weitz.de/files/hunchentoot.tar.gz. The +current version is 0.15.0. There's also a port +for Gentoo +Linux thanks to Matthew Kennedy. +

+A Mercurial +repository of older versions is available +at http://arcanes.fr.eu.org/~pierre/2007/02/weitz/ +thanks to Pierre Thierry. +

+Luís Oliveira maintains a darcs +repository of Hunchentoot +at http://common-lisp.net/~loliveira/ediware/. + +

Hunchentoot behind a proxy

+ +If you're feeling unsecure about exposing Hunchentoot to the wild, +wild Internet or if your Lisp web application is part of a larger +website, you can hide it behind +a proxy +server. One approach that I have used several times is to employ +Apache's mod_proxy +module with a configuration that looks like this: +
+ProxyPass /hunchentoot http://127.0.0.1:3000/hunchentoot
+ProxyPassReverse /hunchentoot http://127.0.0.1:3000/hunchentoot
+
+This will tunnel all requests where the URI path begins with "/hunchentoot" to a (Hunchentoot) server listening on port 3000 on the same machine. +

+Of course, there are several other (more lightweight) web proxies that +you could use instead of Apache. + +

Hunchentoot behind mod_lisp

+ +You can also couple Hunchentoot more tightly with Apache +using mod_lisp. +In this case, Apache will not send proxy requests to Hunchentoot, but +communicate with it directly using a simple, line-based protocol. The +downside of this approach is that it makes debugging harder. (Also, +with mod_lisp, +you can't +accept request bodies that use chunked encoding. With the usual +web browsers, this shouldn't be a problem, though.) +

+For this setup you need two things: + +

    +
  • The Apache web server. You can use either 1.3.x or 2.x. It is recommend that you use or build an Apache with DSO support. + +
  • The mod_lisp +Apache module by Marc Battyani. It is beyond the scope of this document to explain the +details of how to install mod_lisp, but if your Apache has DSO support, +it should suffice to issue a command like + +
    +apxs -c -i -a mod_lisp.c
    +
    + +as root (and afterwards restart Apache). +

    +The newest version of mod_lisp is available from http://www.fractalconcept.com:8000/public/open-source/mod_lisp/. For Apache 1.3.x you +must use mod_lisp.c, for Apache 2.x you must use mod_lisp2.c, which is a reimplementation of Marc's mod_lisp by Chris Hanson. +

    +You can get pre-compiled modules for the Win32 version of Apache 2 (but probably not the latest version) from http://www.fractalconcept.com:8000/public/open-source/mod_lisp/windows/. Put the file into Apache's modules folder and add the line +

    +LoadModule lisp_module modules/mod_lisp2.so
    +
    +to your httpd.conf file. + +
+ +Then you will have to configure Apache and mod_lisp to make them aware +of Hunchentoot. First, in your Apache configuration file (usually +called httpd.conf) add these lines + +
+LispServer 127.0.0.1 3000 "foo"
+
+<Location /hunchentoot>
+  SetHandler lisp-handler
+</Location>
+
+ +and afterwards restart Apache. This informs mod_lisp that there's a +Lisp listening on port 3000 and named +"foo" - you can of course use any other name or port or +even put Hunchentoot on another physical machine. (In the latter case you'll +have to replace 127.0.0.1 with the FQDN or IP address of +this machine.) +

+The Location/SetHandler part means that every URL which +starts with /hunchentoot will be handled by mod_lisp (and thus +Hunchentoot) on this server. (Again, you can of course use other locations. See the +Apache documentation for things like virtual hosts or +directives like LocationMatch.) + +

+ +To interface a Hunchentoot server with mod_lisp, you must start it +with the :MOD-LISP-P keyword parameter +of START-SERVER set to a true +value. + +
 

Support and mailing lists

+ +For questions, bug reports, feature requests, improvements, or patches +please use +the tbnl-devel +mailing list. If you want to be notified about future releases +subscribe to +the tbnl-announce +mailing list. These mailing lists were made available thanks to +the services of common-lisp.net. +You can search the devel mailing +list here +(thanks to Tiarn?n ? Corr?in). +

+If you want to send patches, please read this first. + +
 

Examples, tutorials, add-ons

+ +Hunchentoot comes with an example website which you can use to see if +it works and which should also demonstrate a couple of the things you +can do with Hunchentoot. Use it as a kind of "Hello World" code to +get yourself started. +

+To run the example, +enter the following code into your listener: +

+(asdf:oos 'asdf:load-op :hunchentoot-test)
+(hunchentoot:start-server :port 4242)
+
+You should now be able to point your browser +at http://localhost:4242/hunchentoot/test and see +something. +

+Here are some tutorials done by others: +

+Check the dates of these tutorials. Some of them might not be a +perfect fit with the latest release of Hunchentoot. Also, the fact +that these tutorials are listed here doesn't necessarily mean that I +endorse them or think that they show idiomatic Lisp code. You'll have +to decide yourself if they're helpful to you or not. +

+

+Here is some software which extends Hunchentoot or is based on it: +

+ +
 

Function and variable reference

+ +

Servers

+ +If you want Hunchentoot to actually do something, you have +to start a server. You can also run +several servers in one image, each one listening to a different port. + +


[Function] +
start-server &key port address name dispatch-table mod-lisp-p use-apache-log-p input-chunking-p read-timeout write-timeout setuid setgid ssl-certificate-file ssl-privatekey-file ssl-privatekey-password => server + +


Starts a Hunchentoot server instance and returns it. +port ist the port the server will be listening on +- the default is 80 (or 443 if SSL information is provided). +If address is a string denoting an IP address, +then the server only receives connections for that address. This must +be one of the addresses associated with the machine and allowed values +are host names such as "www.zappa.com" and address +strings such as "72.3.247.29". +If address is NIL, then the server +will receive connections to all IP addresses on the machine. This is +the default. +

+dispatch-table can either be +a dispatch table which is to be used +by this server or NIL which means that at request +time *META-DISPATCHER* +will be called to retrieve a dispatch table. +

+name should be a symbol which can be used to name +the server. This name can utilized when +defining easy handlers. The +default name is an uninterned symbol as returned +by GENSYM. +

+If mod-lisp-p is true (the default +is NIL), the server will act as a back-end +for mod_lisp, otherwise it will be a +stand-alone web server. If use-apache-log-p is +true (which is the default), log messages will be written to the +Apache log file - this parameter has no effect +if mod-lisp-p is NIL. +

+If input-chunking-p is true (which is the +default), the server will accept request bodies without +a Content-Length header if the client uses chunked +transfer encoding. If you want to use this feature behind mod_lisp, +you should make sure that your combination of Apache and +mod_lisp can +cope with that. +

+read-timeout is the read timeout (in seconds) for +the socket stream used by the server - the default value +is *DEFAULT-READ-TIMEOUT*. +This parameter is ignored on OpenMCL. write-timeout is the write timeout (in +seconds) for the socket stream used by the server - the default value +is *DEFAULT-WRITE-TIMEOUT*. +This parameter is ignored on all implementations except for +LispWorks 5.0 or higher and AllegroCL. You can use NIL in both +cases to denote that you don't want a timeout. +If mod-lisp-p is true, the timeouts are always set +to NIL. +

+On Unix you can use setuid +and setgid to change the UID and GID of the +process directly after the server has been started. (You might want +to do this if you're using a privileged port like 80.) setuid and +setgid can be integers (the actual IDs) or strings +(for the user and group name respectively). +

+If you want your server to use SSL, you must provide the pathname +designator(s) ssl-certificate-file for the certificate file and +optionally ssl-privatekey-file for the private key file, both files +must be in PEM format. If you only provide the value for +ssl-certificate-file it is assumed that both the +certificate and the private key are in one file. If your private key +needs a password you can provide it through +the ssl-privatekey-password keyword argument. If +you don't use LispWorks, the private key must not be +associated with a password, and the certificate and the private key +must be in separate files. +

+ +


[Function] +
stop-server server => | + +


+Stops a server started with START-SERVER. server must be an object as returned by START-SERVER. +
+ +


[Special variable] +
*server* + +


+During the execution of dispatch functions and handlers this variable +is bound to the server object (as returned by START-SERVER) which processes the request. +
+ +


[Readers] +
server-local-port server => port +
server-address server => address + +


+These methods can be used to query a Hunchentoot server object. The values correspond to the port and address parameters of START-SERVER. +
+ +


[Accessor] +
server-dispatch-table server => dispatch-table +
(setf (server-dispatch-table server) new-value)
+ +


These methods can be used to get and set +the dispatch table of a Hunchentoot +server object. The value corresponds to +the dispatch-table parameter +of START-SERVER and can be +changed at runtime. It can be set to NIL which means that the server +doesn't have its own dispatch table +and *META-DISPATCHER* should be +called instead. +
+ +


[Accessor] +
server-name server => name +
(setf (server-name server) new-value)
+


These methods can be used to get and set the name of a server +which must be a symbol. +
+ +


[Special variable] +
*default-read-timeout* + +


The default value for the read-timeout keyword +argument to START-SERVER. The initial value is 20 (seconds). +
+ +


[Special variable] +
*default-write-timeout* + +


The default value for the write-timeout keyword +argument to START-SERVER. The initial value is 20 (seconds). +
+ +


[Special variable] +
*cleanup-interval* + +


+Should be NIL or a positive integer. The system calls +*CLEANUP-FUNCTION* whenever *CLEANUP-INTERVAL* new worker threads have +been created unless the value is NIL. The initial value is 100. +
+ +


[Special variable] +
*cleanup-function* + +


+The function (with no arguments) which is called if *CLEANUP-INTERVAL* is not NIL. +The initial value is a function which calls +(HCL:MARK-AND-SWEEP 2) on LispWorks and does nothing on other Lisps. +

+On LispWorks this is necessary because each worker (which is +created to handle an incoming http request and which dies afterwards +unless the connection is persistent) is a Lisp process and LispWorks +creates processes in generation 2. +

+Note that you can also set this value to NIL and tune +LispWork's GC yourself, using for +example COLLECT-GENERATION-2. +

+ +

Handlers

+ +Hunchentoot handles each incoming request dynamically depending on the +contents of a global dispatch table. The details can be found +below. (See the file test/test.lisp for examples.) + +


[Special variable] +
*dispatch-table* + +


+ +The return value of the initial value of *META-DISPATCHER*. +

+This is a list of function +designators for dispatch functions each of which should +be a function of one argument which accepts a REQUEST object and, depending on +this object, should either return a handler to handle the +request or NIL which means that the next dispatcher will +be queried. A handler is a designator for a function with no +arguments which usually returns a string or an array of octets to be sent to the client as +the body of the http reply. (Note that if you use symbols as function +designators, you can redefine your handler functions without the need +to change the dispatch functions.) See the section +about replies for more about what handlers can do. +

+The dispatchers in a dispatch table are tried in turn +until one of them returns a handler. If this doesn't happen, Hunchentoot will +return a 404 status code (Not Found) to the client. +

+The initial value of *DISPATCH-TABLE* is a list which +just contains the symbol DEFAULT-DISPATCHER. + +

+ +


[Function] +
default-dispatcher request => handler + +


+ +This is a function which will always unconditionally return the value of *DEFAULT-HANDLER*. It is intended to be the last element of *DISPATCH-TABLE*. + +
+ +


[Special variable] +
*default-handler* + +


+ +This variable holds the handler which is always returned by DEFAULT-DISPATCHER. The +default value is a function which unconditonally shows a short Hunchentoot +info page. + +
+ +


[Special variable] +
*meta-dispatcher* + +


The value of this variable should be a function of +one argument. It is called with the current Hunchentoot server +instance (unless the server has its +own dispatch table) and must return a dispatch table suitable for +Hunchentoot. The initial value is a function which always +unconditionally returns +*DISPATCH-TABLE*. +

+This can obviously be used to assign different dispatch tables to +different servers (and is useless if you only have one server). +

+ +


[Function] +
create-prefix-dispatcher prefix handler => dispatch-fn + +


+ +A convenience function which will return a dispatcher that returns handler whenever the path part of the request URI starts with the string prefix. + +
+ +


[Function] +
create-regex-dispatcher regex handler => dispatch-fn + +


+ +A convenience function which will return a dispatcher that returns handler whenever the path part of the request URI matches the CL-PPCRE regular expression regex (which can be a string, an s-expression, or a scanner). + +
+ +


[Function] +
handle-static-file path &optional content-type => nil + +


+Sends the file denote by the pathname designator +path with content type +content-type to the client. Sets the necessary handlers. In particular the function employs +HANDLE-IF-MODIFIED-SINCE. +

+If content-type is NIL the function +tries to determine the correct content type from the file's suffix or +falls back to "application/octet-stream" as a last resort. +

+Note that this function +calls SEND-HEADERS +internally, so after you've called it, the headers are sent and the +return value of your handler is ignored. +

+ +


[Function] +
create-static-file-dispatcher-and-handler uri path &optional content-type => dispatch-fn + +


+ +A convenience function which will return a dispatcher that dispatches +to a handler which emits the file denoted by the pathname designator +path with content type +content-type +if the SCRIPT-NAME of the +request matches the string uri. Uses HANDLE-STATIC-FILE internally. +

+If content-type is NIL the function tries to determine the correct content type from the file's suffix +or falls back to "application/octet-stream" as a last resort. +*DEFAULT-CONTENT-TYPE*. +

+ +


[Function] +
create-folder-dispatcher-and-handler uri-prefix base-path &optional content-type => dispatch-fn + +


+Creates and returns a dispatch function which will dispatch to a +handler function which emits the file relative to base-path that is +denoted by the URI of the request relative to uri-prefix. uri-prefix +must be a string ending with a slash, base-path must be a pathname +designator for an existing directory. +Uses HANDLE-STATIC-FILE internally. +

+If content-type is not NIL, +it will be used as a the content type for all files in the folder. +Otherwise (which is the default) the content type of each file will be determined as usual. +

+ +


[Generic function] +
dispatch-request dispatch-table => result + +


+This is a generic function so users can customize its behaviour. Look at the source code for details. +
+ +


[Macro] +
define-easy-handler description lambda-list [[declaration* | documentation]] form* + +


+ +Defines a handler as if +by DEFUN +and optionally registers it with a URI so that it will be found +by DISPATCH-EASY-HANDLERS. +

+description is either a symbol name or a list matching the +destructuring lambda list + +

+  (name &key uri server-names default-parameter-type default-request-type).
+
+ +lambda-list is a list the elements of which are either a symbol +var or a list matching the destructuring lambda list + +
+  (var &key real-name parameter-type init-form request-type).
+
+ +The resulting handler will be a Lisp function with the +name name and keyword parameters named by +the var symbols. Each var +will be bound to the value of the GET or POST parameter +called real-name (a string) before the body of the +function is executed. If real-name is not +provided, it will be computed by downcasing the symbol name +of var. +

+If uri (which is evaluated) is provided, then it must be a string or +a function +designator for a unary function. In this case, +the handler will be returned by DISPATCH-EASY-HANDLERS, if uri is a +string and the script name of the current request is uri, or if uri designates a +function and applying this function to the current REQUEST object +returns a true value. +

+ +server-names (which is evaluated) can be a list of +symbols which means that the handler will only be returned +by DISPATCH-EASY-HANDLERS +in servers which have one of these names +(see SERVER-NAME). server-names +can also be the symbol T which means that the handler +will be returned +by DISPATCH-EASY-HANDLERS +in every server. +

+Whether the GET or POST parameter (or both) will be taken into +consideration, depends on request-type which can +be :GET, :POST, :BOTH, or NIL. In the last case, the value of +default-request-type (the default of which +is :BOTH) will be used. +

+The value of var will usually be a string (unless +it resulted from a file upload in which case it won't be converted at +all), but if parameter-type (which is evaluated) +is provided, the string will be converted to another Lisp type by the +following rules: +

+If the corresponding GET or POST parameter wasn't provided by the +client, var's value will be NIL. If parameter-type is 'STRING, +var's value remains as is. If parameter-type is 'INTEGER and the +parameter string consists solely of decimal digits, var's value will be +the corresponding integer, otherwise NIL. If parameter-type is +'KEYWORD, var's value will be the +keyword obtained +by interning +the upcased parameter string into +the keyword +package. If parameter-type +is 'CHARACTER and the parameter string is of length +one, var's value will be the single character of +this string, otherwise NIL. +If parameter-type +is 'BOOLEAN, var's value will always +be T (unless it is NIL by the first rule +above, of course). If parameter-type is any other +atom, it is supposed to be +a function +designator for a unary function which will be called to +convert the string to something else. +

+Those were the rules for simple parameter types, but +parameter-type can also be a list starting with one of the symbols +LIST, ARRAY, or HASH-TABLE. +The second value of the list must always be a simple parameter type as +in the last paragraph - we'll call it the inner type below. +

+In the case of 'LIST, all GET/POST parameters +called real-name will be collected, converted to +the inner type as by the rules above, and assembled into a list which +will be the value of +var. +

+In the case of 'ARRAY, all GET/POST parameters which have +a name like the result of + +

+  (format nil "~A[~A]" real-name n)
+
+ +where n is a non-negative integer, will be +assembled into an array where the nth element will +be set accordingly, after conversion to the inner type. The array, +which will become the value of var, will be big +enough to hold all matching parameters, but not bigger. Array +elements not set as described above will be NIL. Note +that VAR will always be bound to an array, which may be +empty, so it will never be NIL, even if no appropriate +GET/POST parameters are found. +

+The full form of a 'HASH-TABLE parameter type is + +

+  (hash-table inner-type key-type test-function),
+
+ +but key-type and test-function +can be left out in which case they default to 'STRING +and 'EQUAL, respectively. For this parameter type, all +GET/POST parameters which have a name like the result of + +
+  (format nil "~A{~A}" real-name key)
+
+ +(where key is a string that doesn't contain curly brackets) will +become the values (after conversion to inner-type) of a hash +table with test function test-function where key (after +conversion to key-type) will be the corresponding key. Note that +var will always be bound to a hash table, which +may be empty, so it will never be NIL, even if no +appropriate GET/POST parameters are found. +

+To make matters even more complicated, the three compound parameter +types also have an abbreviated form - just one of the +symbols LIST, ARRAY, +or HASH-TABLE. In this case, the inner type will default +to 'STRING. +

+If parameter-type is not provided +or NIL, default-parameter-type (the +default of which is 'STRING) will be used instead. +

+If the result of the computations above would be +that var would be bound to NIL, +then init-form (if provided) will be evaluated +instead, and var will be bound to the result of +this evaluation. +

+Handlers built with this macro are constructed in such a way that the +resulting Lisp function is useful even outside of Hunchentoot. Specifically, +all the parameter computations above will only happen +if *REQUEST* is bound, i.e. if +we're within a Hunchentoot request. Otherwise, var will +always be bound to the result of +evaluating init-form unless a corresponding +keyword argument is provided. +

+The example code that comes with Hunchentoot contains an +example which demonstrates some of the features +of DEFINE-EASY-HANDLER. + +

+ +


[Function] +
dispatch-easy-handlers request => handler + +


+ +This is a dispatcher which returns the appropriate handler defined +with DEFINE-EASY-HANDLER, if +there is one. The newest handlers are checked +first. DEFINE-EASY-HANDLER makes +sure that there's always only one handler per name and one per URI. +URIs are compared +by EQUAL, +so anonymous functions won't be recognized as being identical. + +
+ +

Requests

+ +When a request comes in, Hunchentoot creates a REQUEST object +which is available to the handler via the +special variable *REQUEST*. This object holds +all the information available about the request and can be queried +with the functions described in this chapter. Note that the internal +structure of REQUEST objects should be considered opaque and may change +in future releases of Hunchentoot. +

+In all of the functions below, the default value +for request (which is either an optional or a +keyword argument) is the value of *REQUEST*, +i.e. handlers will usually not need to provide this argument when +calling the function. +

+(Some of the function names in this section might seem a bit strange. +This is because they were initially chosen to be similar to +environment variables in CGI scripts.) + +


[Special variable] +
*request* + +


+ +Holds the current REQUEST object. + +
+ +


[Function] +
host &optional request => string + +


+ +Returns the value of the incoming Host http header. +(This corresponds to +the environment variable HTTP_HOST in CGI +scripts.) + +
+ +


[Function] +
request-method &optional request => keyword + +


+ +Returns the request method as a keyword, i.e. something like :POST. (This corresponds to the environment +variable REQUEST_METHOD in CGI scripts.) + +
+ +


[Function] +
request-uri &optional request => string + +


+ +Returns the URI for request. Note that this not the full URI but only the part behind the +scheme and authority components, so that if the user has typed http://user:password at www.domain.com/xxx/frob.html?foo=bar into his browser, this function will return "/xxx/frob.html?foo=bar". +(This corresponds to +the environment variable REQUEST_URI in CGI +scripts.) + +
+ +


[Function] +
script-name &optional request => string + +


+ +Returns the file name (or path) component of the URI +for request, i.e. the part of the string returned +by REQUEST-URI in front of the +first question mark (if any). +(This corresponds to +the environment variable SCRIPT_NAME in CGI +scripts.) + +
+ +


[Function] +
query-string &optional request => string + +


+ +Returns the query component of the URI +for request, i.e. the part of the string returned +by REQUEST-URI behind the +first question mark (if any). +(This corresponds to +the environment variable QUERY_STRING in CGI +scripts.) See also GET-PARAMETER and GET-PARAMETERS. + +
+ +


[Function] +
get-parameter name &optional request => string + +


+Returns the value of the GET parameter (as provided via the request URI) named by the string name as a string (or NIL if there ain't no GET parameter with this name). Note that only the first value will be returned if the client provided more than one GET parameter with the name name. See also GET-PARAMETERS. +
+ +


[Function] +
get-parameters &optional request => alist + +


+Returns an alist of all GET parameters (as provided via the request URI). The car of each element of this list is the parameter's name while the cdr is its value (as a string). The elements of this list are in the same order as they were within the request URI. See also GET-PARAMETER. +
+ +


[Function] +
post-parameter name &optional request => string + +


+Returns the value of the POST parameter (as provided in the request's body) named by the string name. Note that only the first value will be returned if the client provided more than one POST parameter with the name name. +This value will usually be a string (or NIL if there ain't no POST parameter with this name). If, however, the browser sent a file through a multipart/form-data form, the value of this function is a three-element list +
+(path file-name content-type)
+
+where path is a pathname denoting the place were the uploaded file was stored, file-name (a string) is the file name sent by the browser, and content-type (also a string) is the content type sent by the browser. The file denoted by path will be deleted after the request has been handled - you have to move or copy it somewhere else if you want to keep it. +

+POST parameters will only be computed if the content type of the request body was multipart/form-data +or application/x-www-form-urlencoded. +Although this function is called POST-PARAMETER, you can instruct Hunchentoot to compute these parameters for other request methods by setting *METHODS-FOR-POST-PARAMETERS*. +

+See also POST-PARAMETERS and *TMP-DIRECTORY*. +

+ +


[Function] +
post-parameters &optional request => alist + +


+Returns an alist of all POST parameters (as provided via the request's body). The car of each element of this list is the parameter's name while the cdr is its value. The elements of this list are in the same order as they were within the request's body. +

+See also POST-PARAMETER. +

+ +


[Special variable] +
*methods-for-post-parameters* + +


A list of the request method types (as keywords) for +which Hunchentoot will try to compute "POST" +parameters. The default is the list with the single +element :POST. +
+ +


[Special variable] +
*file-upload-hook* + +


If this is not NIL, it should be +a designator +for a unary function which will be called with a pathname for each +file which is uploaded to Hunchentoot. The pathname +denotes the temporary file to which the uploaded file is written. The +hook is called directly before the file is created. At this +point, *REQUEST* is already +bound to the current REQUEST object, but obviously you +can't access the post parameters yet. +
+ +


[Function] +
raw-post-data &key request external-format force-text force-binary want-stream => raw-body-or-stream + +


Returns the content sent by the client in the request +body if there was any (unless the content type +was multipart/form-data in which case NIL +is returned). By default, the result is a string if the type of +the Content-Type media type +is "text", and a vector of octets otherwise. In the case +of a string, the external format to be used to decode the content will +be determined from the charset parameter sent by the +client (or +otherwise *HUNCHENTOOT-DEFAULT-EXTERNAL-FORMAT* +will be used). +

+You can also provide an external format explicitly (through +external-format) in which case the result will +unconditionally be a string. Likewise, you can provide a true value +for force-text which will force Hunchentoot to act +as if the type of the media type had been "text" +(with external-format taking precedence if +provided). Or you can provide a true value +for force-binary which means that you want a +vector of octets at any rate. (If both +force-text and force-binary +are true, an error will be signaled.) +

+If, however, you provide a true value +for want-stream, the other parameters are ignored +and you'll get the content (flexi) stream to read from it yourself. +It is then your responsibility to read the correct amount of data, +because otherwise you won't be able to return a response to the +client. The stream will have +its octet +position set to 0. If the client provided +a Content-Length header, the stream will also have +a +corresponding bound, +so no matter whether the client used chunked encoding or not, you can +always read until EOF. +

+If the content type of the request +was multipart/form-data +or application/x-www-form-urlencoded, the content has +been read by Hunchentoot already and you can't read from the stream +anymore. +

+You can call RAW-POST-DATA +more than once per request, but you can't mix calls which have +different values for want-stream. +

+Note that this function is slightly misnamed because a client can send +content even if the request method is not POST. +

+ +


[Function] +
parameter name &optional request => string + +


+Returns the value of the GET or POST parameter named by the string name as a string (or NIL if there ain't no parameter with this name). If both a GET and a POST parameter with the name name exist, the GET parameter will be returned. See also GET-PARAMETER and POST-PARAMETER. +
+ +


[Function] +
header-in name &optional request => string + +


Returns the incoming header named by the +keyword name as a string (or NIL if +there ain't no header with this name). Note that this queries the +headers sent to Hunchentoot by the client or by mod_lisp. In +the latter case this may not only include the incoming http headers +but also +some headers sent by +mod_lisp. +

For backwards compatibility, name +can also be a string which is matched case-insensitively. See +also HEADERS-IN. +

+ +


[Function] +
headers-in &optional request => alist + +


+Returns an alist of all incoming headers. The car of each element of this list is the headers's name (a Lisp keyword) while the cdr is its value (as a string). There's no guarantee about the order of this list. See also HEADER-IN and the remark about incoming headers there. +
+ +


[Function] +
authorization &optional request => user, password + +


+Returns as two values the user and password (if any) from the incoming Authorization http header. Returns NIL if there is no such header. +
+ + +


[Function] +
remote-addr &optional request => string + +


+ +Returns the IP address (as a string) of the client which sent the +request. (This corresponds to the environment +variable REMOTE_ADDR in CGI scripts.) See +also REAL-REMOTE-ADDR. + +
+ +


[Function] +
remote-port &optional request => number + +


+ +Returns the IP port (as a number) of the client which sent the request. + +
+ +


[Function] +
real-remote-addr &optional request => string{, list} + +


+ +Returns the value of the +incoming X-Forwarded-For +http header as the second value in the form of a list of IP addresses +and the first element of this list as the first value if this header +exists. Otherwise returns the value +of REMOTE-ADDR as the only +value. + +
+ +


[Function] +
server-addr &optional request => string + +


+ +Returns the IP address (as a string) where the request came in. (This +corresponds to the environment variable SERVER_ADDR in +CGI scripts.) + +
+ +


[Function] +
server-port &optional request => number + +


+ +Returns the IP port (as a number) where the request came in. + +
+ +


[Function] +
server-protocol &optional request => keyword + +


+ +Returns the version of the http protocol which is used by the client as a Lisp keyword - this is usually either :HTTP/1.0 or :HTTP/1.1. +(This corresponds to the environment +variable SERVER_PROTOCOL in CGI scripts.) + +
+ +


[Function] +
mod-lisp-id &optional request => string + +


+ +Returns the 'Server ID' sent by mod_lisp. This corresponds to the +third parameter in the "LispServer" directive in Apache's +configuration file and can be interesting if you deploy several different +Apaches or Hunchentoot instances at once. Returns NIL in stand-alone servers. + +
+ +


[Function] +
ssl-session-id &optional request => string + +


+ +Returns Apache's SSL session ID if it exists. Note that SSL sessions aren't related to Hunchentoot sessions. +(This corresponds to +the environment variable SSL_SESSION_ID in CGI +scripts.) Returns NIL in stand-alone servers. + +
+ +


[Function] +
user-agent &optional request => string + +


+ +Returns the value of the incoming User-Agent http header. +(This corresponds to +the environment variable HTTP_USER_AGENT in CGI +scripts.) + +
+ +


[Function] +
referer &optional request => string + +


+ +Returns the value of the incoming Referer (sic!) http header. +(This corresponds to +the environment variable HTTP_REFERER in CGI +scripts.) + +
+ +


[Function] +
cookie-in name &optional request => string + +


+Returns the value of the incoming cookie named by the string name (or NIL if there ain't no cookie with this name). See also COOKIES-IN. +
+ +


[Function] +
cookies-in &optional request => alist + +


+Returns an alist of all incoming cookies. The car of each element of this list is the cookie's name while the cdr is the cookie's value. See also COOKIE-IN. +
+ +


[Accessor] +
aux-request-value symbol &optional request => value, present-p +
(setf (aux-request-value symbol &optional request) new-value)
+ +


+This accessor can be used to associate arbitrary data with the the symbol symbol in the REQUEST +object request. +present-p is true if such data was found, +otherwise NIL. +
+ +


[Function] +
delete-aux-request-value symbol &optional request => | + +


+Completely removes any data associated with the symbol symbol from the REQUEST +object request. Note that this is different from +using AUX-REQUEST-VALUE to set the data to NIL. +
+ +


[Function] +
recompute-request-parameters &key request external-format => | + +


Recomputes the GET and POST parameters for +the REQUEST object +request. This only makes sense if you've changed +the external format and with POST parameters it will only work if the +request body was sent with +the application/x-www-form-urlencoded content type. +

+The default value for +external-format is *HUNCHENTOOT-DEFAULT-EXTERNAL-FORMAT*. +See test/test.lisp for an example. +

+ +

Replies

+ +It is the responsibility of a handler function to prepare the reply for the client. This is done by + +
    +
  • returning a string or an array of octets which will be the reply's body and +
  • manipulating a REPLY object which will be described in this section. +
+ +For each request there's one REPLY object which is accessible +to the handler via the +special variable *REPLY*. This object holds +all the information available about the reply and can be accessed +with the functions described in this chapter. Note that the internal +structure of REPLY objects should be considered opaque and may change +in future releases of Hunchentoot. +

+In all of the functions below, the default value +for the optional argument reply is the value of *REPLY*, +i.e. handlers will usually not need to provide this argument when +calling the function. +

+While Hunchentoot's preferred way of sending data to the client is the +one described above (i.e. the handler returns the whole payload as a +string or an array of octets) you can, if you really need to (for +example for large content bodies), get a stream you can write to +directly. This is achieved by first setting +up *REPLY* and then +calling SEND-HEADERS. Note +that in this case the usual error handling is +disabled. See the file test/test.lisp for an example. + +


[Special variable] +
*reply* + +


+ +Holds the current REPLY object. + +
+ +


[Accessor] +
header-out name &optional reply => string +
(setf (header-out name &optional reply) new-value)
+ +


+ +HEADER-OUT returns the outgoing http header named by the +keyword name if there is one, +otherwise NIL. SETF +of HEADER-OUT changes the current value of the header +named name. If no header +named name exists it is created. For backwards +compatibility, name can also be a string in which +case the association between a header and its name is +case-insensitive. +

+Note that the +headers Set-Cookie, Content-Length, +and Content-Type cannot be queried +by HEADER-OUT and must not be set +by SETF of HEADER-OUT. Also, there are a +couple of "technical" headers like Connection +or Transfer-Encoding that you're not supposed to set +yourself. If in doubt, consult the source code or ask on +the mailing list. +

+See also HEADERS-OUT, CONTENT-TYPE, CONTENT-LENGTH, COOKIES-OUT, and COOKIE-OUT. + +

+ +


[Function] +
headers-out &optional request => alist + +


+Returns an alist of all outgoing http parameters (except for Set-Cookie, Content-Length, +and Content-Type). The car of each element of this list is the headers's name while the cdr is its value. This alist should not be manipulated directly, use SETF of HEADER-OUT instead. +
+ +


[Function] +
cookie-out name &optional reply => cookie + +


+Returns the outgoing cookie named by the string name (or NIL if there ain't no cookie with this name). See also COOKIES-OUT and the section about cookies. +
+ +


[Function] +
cookies-out &optional reply => alist + +


+Returns an alist of all outgoing cookies. The car of each element of this list is the cookie's name while the cdr is the cookie itself. See also COOKIE-OUT and the section about cookies. +
+ +


[Accessor] +
return-code &optional reply => number +
(setf (return-code &optional reply) new-value)
+ +


+ +RETURN-CODE returns the http return code of the +reply, SETF of RETURN-CODE changes it. The +return code of each REPLY object is initially set to +HTTP-OK+. + +
+ +


[Accessor] +
content-type &optional reply => string +
(setf (content-type &optional reply) new-value)
+ +


+ +CONTENT-TYPE returns the +outgoing Content-Type http header. SETF +of CONTENT-TYPE changes the current value of this header. The content type of each REPLY object is initially set to the value of *DEFAULT-CONTENT-TYPE*. +
+ +


[Accessor] +
content-length &optional reply => length +
(setf (content-length &optional reply) new-value)
+ +


+ +CONTENT-LENGTH returns the outgoing +Content-Length http header. SETF of +CONTENT-LENGTH changes the current value of this +header. The content length of each REPLY object is +initially set to NIL. If you leave it like that, +Hunchentoot will automatically try to compute the correct value +using LENGTH. +If you set the value yourself, you must make sure that it's +the correct length of the body in octets (not in characters). +In this case, Hunchentoot will use the value as is which can lead to +erroneous behaviour if it is wrong - so, use at your own risk. +

+Note that setting this value explicitly doesn't mix well with URL rewriting. + +

+ +


[Function] +
send-headers => stream + +


+Sends the initial status line and all headers as determined by +the REPLY object *REPLY*. Returns a flexi stream to which the body of +the reply can be written. Once this function has been called, +further changes to *REPLY* don't have any effect. Also, +automatic handling of errors (i.e. sending the +corresponding status code to the browser, etc.) is turned off for this +request. Likewise, functions +like REDIRECT or throwing +to HANDLER-DONE +won't have the desired effect once the headers are sent. +

+If your handlers return the full body as a string or as an array of +octets, you should not call this function. If a handler +calls SEND-HEADERS, its return +value is ignored. +

+See also REPLY-EXTERNAL-FORMAT. +

+ +


[Accessor] +
reply-external-format &optional reply => external-format +
(setf (reply-external-format &optional reply) new-value)
+ +


+ +Gets and sets the external format of the REPLY +object reply. This external format is used when +character content is written to the client after the headers have been +sent. In particular, it is the external format of the stream returned by SEND-HEADERS (but of course you can change it because it's a flexi stream). +

The initial value for each request is the value +of *HUNCHENTOOT-DEFAULT-EXTERNAL-FORMAT*. + +

+ +


[Constants] +
+http-continue+ +
+http-switching-protocols+ +
+http-ok+ +
+http-created+ +
+http-accepted+ +
+http-non-authoritative-information+ +
+http-no-content+ +
+http-reset-content+ +
+http-partial-content+ +
+http-multi-status+ +
+http-multiple-choices+ +
+http-moved-permanently+ +
+http-moved-temporarily+ +
+http-see-other+ +
+http-not-modified+ +
+http-use-proxy+ +
+http-temporary-redirect+ +
+http-bad-request+ +
+http-authorization-required+ +
+http-payment-required+ +
+http-forbidden+ +
+http-not-found+ +
+http-method-not-allowed+ +
+http-not-acceptable+ +
+http-proxy-authentication-required+ +
+http-request-time-out+ +
+http-conflict+ +
+http-gone+ +
+http-length-required+ +
+http-precondition-failed+ +
+http-request-entity-too-large+ +
+http-request-uri-too-large+ +
+http-unsupported-media-type+ +
+http-requested-range-not-satisfiable+ +
+http-expectation-failed+ +
+http-failed-dependency+ +
+http-internal-server-error+ +
+http-not-implemented+ +
+http-bad-gateway+ +
+http-service-unavailable+ +
+http-gateway-time-out+ +
+http-version-not-supported+ + +


+The values of these constants are 100, 101, 200, 201, 202, 203, 204, 205, 206, 207, 300, 301, 302, 303, 304, 305, 307, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 424, 500, 501, 502, 503, 504, and 505. See RETURN-CODE. +
+ +


[Special variable] +
*default-content-type* + +


+The value of this variable is used to initialize the content type of each REPLY object. Its initial value is "text/html; charset=iso-8859-1". See CONTENT-TYPE. +
+ +

Cookies

+ +Outgoing cookies are stored in the request's REPLY object (see COOKIE-OUT and COOKIES-OUT). They are CLOS objects defined like this: + +
+(defclass cookie ()
+  ((name :initarg :name
+         :reader cookie-name
+         :type string
+         :documentation "The name of the cookie - a string.")
+   (value :initarg :value
+          :accessor cookie-value
+          :initform ""
+          :documentation "The value of the cookie. Will be URL-encoded when sent to the browser.")
+   (expires :initarg :expires
+            :initform nil
+            :accessor cookie-expires
+            :documentation "The time (a universal time) when the cookie expires (or NIL).")
+   (path :initarg :path
+         :initform nil
+         :accessor cookie-path
+         :documentation "The path this cookie is valid for (or NIL).")
+   (domain :initarg :domain
+           :initform nil
+           :accessor cookie-domain
+           :documentation "The domain this cookie is valid for (or NIL).")
+   (secure :initarg :secure
+           :initform nil
+           :accessor cookie-secure
+           :documentation "A generalized boolean denoting whether this is a secure cookie.")
+   (http-only :initarg :http-only
+              :initform nil
+              :accessor cookie-http-only
+              :documentation "A generalized boolean denoting whether this is a HttpOnly cookie.")))
+
+ +The reader COOKIE-NAME and +the accessors +COOKIE-VALUE, COOKIE-EXPIRES, COOKIE-PATH, COOKIE-DOMAIN, COOKIE-SECURE, and COOKIE-HTTP-ONLY are all exported +from the HUNCHENTOOT package. + +


[Function] +
set-cookie name &key value expires path domain secure http-only reply => cookie + +


Creates a COOKIE object from the +parameters provided to this function and adds it to the outgoing +cookies of the REPLY +object reply. If a cookie with the same name +(case-sensitive) already exists, it is replaced. The default +for reply is *REPLY*. The default for value is the empty string. +
+ +


[Function] +
set-cookie* cookie &optional reply => cookie + +


Adds the COOKIE +object cookie to the outgoing cookies of the REPLY +object reply. If a cookie with the same name +(case-sensitive) already exists, it is replaced. The default for reply is *REPLY*. +
+ +

Sessions

+ +Hunchentoot supports sessions: Once a Hunchentoot page has +called START-SESSION, +Hunchentoot uses either cookies or (if the client doesn't send the +cookies back) rewrites URLs +to keep track of this client, i.e. to provide a kind of 'state' for +the stateless http protocol. The session associated with the client is +an opaque CLOS object which can be used to store arbitrary data +between requests. +

+Hunchentoot makes some reasonable effort to prevent eavesdroppers from +hijacking sessions (see below), but this should not be considered +really secure. Don't store sensitive data in sessions and rely +solely on the session mechanism as a safeguard against malicious users +who want to get at this data! +

+For each request there's one SESSION object which is accessible +to the handler via the +special variable *SESSION*. This object holds +all the information available about the session and can be accessed +with the functions described in this chapter. Note that the internal +structure of SESSION objects should be considered opaque and may change +in future releases of Hunchentoot. +

+Sessions are automatically verified for validity and age when +the REQUEST object is instantiated, i.e. if *SESSION* is not NIL then this +session is valid (as far as Hunchentoot is concerned) and not too old. Old sessions are automatically removed. + +


[Special variable] +
*session* + +


+ +Holds the current SESSION object (if any) or NIL. + +
+ +


[Function] +
start-session => session + +


Returns *SESSION* if it +isn't NIL, otherwise creates a new SESSION +object and returns it. +
+ +


[Accessor] +
session-value symbol &optional session => value, present-p +
(setf (session-value symbol &optional session) new-value)
+ +


+This accessor can be used to associate arbitrary data with the the symbol symbol in the SESSION +object session. +present-p is true if such data was found, +otherwise NIL. The default value +for session is *SESSION*. +

+If SETF of SESSION-VALUE is called with session being NIL then a session is automatically instantiated with START-SESSION. +

+ +


[Function] +
delete-session-value symbol &optional session => | + +


+Completely removes any data associated with the symbol symbol from the SESSION +object session. Note that this is different from +using SESSION-VALUE to set the data to NIL. +The default value +for session is *SESSION*. +
+ + +


[Function] +
remove-session session => | + +


+Completely removes the session session from Hunchentoot's internal session database. See also *SESSION-REMOVAL-HOOK*. +
+ + +


[Function] +
reset-sessions => | + +


+This function unconditionally invalidates and destroys all sessions immediately. +
+ + +


[Function] +
session-cookie-value session => string + +


+Returns a unique string that's associated with +the SESSION object session. This +string is sent to the browser as a cookie value or as a GET parameter, +
+ + +


[Function] +
session-counter session => count + +


+Returns the number of times (requests) the SESSION object session has been used. +
+ + + +


[Accessor] +
session-max-time session => seconds +
(setf (session-max-time session) seconds)
+ +


This gets or sets the maximum time (in seconds) +the SESSION object session should be +valid before it's invalidated: If a request associated with this +session comes in and the last request for the same session was more +than seconds seconds ago +than the session is deleted and a new one is started for this client. The default value is determined by *SESSION-MAX-TIME*. +
+ +


[Function] +
session-remote-addr session => address + +


Returns the 'real' remote address (see REAL-REMOTE-ADDR) of the +client for which the SESSION +object session was initiated. +
+ +


[Function] +
session-user-agent session => address + +


Returns the 'User-Agent' http header (see USER-AGENT) of the +client for which the SESSION +object session was initiated. +
+ +


[Special variable] +
*use-remote-addr-for-sessions* + +


+ +If this value is true (the default is NIL) then +the 'real' remote address (see REAL-REMOTE-ADDR) of the +client will be encoded into the session identifier, i.e. if this value +changes on the client side, the session will automatically be +invalidated. +

+Note that this is not secure, because it's obviously not very hard to +fake an X_FORWARDED_FOR header. On the other hand, +relying on the remote address (see REMOTE-ADDR) of the client isn't +an ideal solution either, because some of your users may connect +through http proxies and the proxy they use may change during the +session. But then again, some proxies don't +send X_FORWARDED_FOR headers anyway. Sigh... + +

+ +


[Special variable] +
*use-user-agent-for-sessions* + +


If this value is true (which is the default) +then the 'User-Agent' http header (see USER-AGENT) of the client will be +encoded into the session identifier, i.e. if this value changes on the +client side the session will automatically be invalidated. +

+While this is intended to make the life of malicious users harder, it +might affect legitimate users as well: I've seen this http +header change with certain browsers when the Java plug-in was used. +

+ +


[Special variable] +
*rewrite-for-session-urls* + +


If this value is true (which is the default) +then content bodies sent by Hunchentoot will be rewritten +(using URL-REWRITE) such +that GET parameters for session handling are appended to all relevant +URLs. This only happens, though, if the body's content type (see CONTENT-TYPE) starts +with one of the strings in *CONTENT-TYPES-FOR-URL-REWRITE* and unless the client has already sent a cookie named *SESSION-COOKIE-NAME*. +

+Note that the function which rewrites the body doesn't understand +Javascript, so you have to take care of URLs in Javascript code yourself. +

+ +


[Special variable] +
*content-types-for-url-rewrite* + +


+This is a list of strings (the initial value is +("text/html" "application/xhtml+xml")) the +content-type of an outgoing body is compared with if *REWRITE-FOR-SESSION-URLS* +is true. If the content-type starts with one of these strings, then +url-rewriting will happen, otherwise it won't. +
+ +


[Special variable] +
*session-cookie-name* + +


+ +This is the name that is used for the session-related cookie or GET +parameter sent to the client. Its default value +is "hunchentoot-session". Note that changing this name while +Hunchentoot is running will invalidate existing sessions. + +
+ +


[Special variable] +
*session-removal-hook* + +


+The value of this variable should be a function of one argument, a SESSION object. This function is called directly before the session is destroyed, either by RESET-SESSIONS, by REMOVE-SESSION, or when it's invalidated because it's too old. + +
+ +


[Special variable] +
*session-max-time* + +


+The default time (in seconds) after which a session times out - see SESSION-MAX-TIME. This value is initially set to 1800. +
+ +


[Macro] +
do-sessions (var &optional result-form) statement* => result + +


+ +Executes the statements with var bound to each +existing SESSION object consecutively. An implicit block +named NIL surrounds the body of this macro. Returns the +values returned by result-form unless +RETURN is executed. The scope of the binding of +var does not include +result-form. + +
+ +


[Special variable] +
*session-gc-frequency* + +


+A session garbage collection (see SESSION-GC) will happen every +*SESSION-GC-FREQUENCY* +requests (counting only requests which use sessions) if the value of +this variable is not NIL. It's default value is 50. +
+ +


[Function] +
session-gc => | + +


+Deletes sessions which are too old - see +SESSION-TOO-OLD-P. +Usually, you don't call this function directly - +see *SESSION-GC-FREQUENCY*. +
+ +


[Function] +
session-too-old-p session => generalized-boolean + +


Returns a true value if the SESSION +object session is too old and would be deleted +during the next session GC. You don't +have to check this manually for sessions +in *SESSION*, but it might be +useful if you want to loop through all +sessions. +
+ + +

Logging and error handling

+ +Hunchentoot provides facilities for writing to Apache's error log +file (when using the mod_lisp front-end) or for logging to an arbitrary file in the file system. Note that, due to the nature of mod_lisp, Apache log mesages don't appear immediately but only after all data has been sent from Hunchentoot to Apache/mod_lisp. +

+Furthermore, all errors happening within a handler which are not +caught by the handler itself are handled by Hunchentoot - see details below. + +


[Accessor] +
log-file => pathname +
(setf (log-file) pathspec)
+ +


+The function LOG-FILE returns a pathname designating the log file which is currently used (unless log messages are forwarded to Apache). This destination for log messages can be changed with (SETF LOG-FILE). The initial location of the log file is implementation-dependent. +
+ +


[Generic function] +
log-message log-level format &rest args => | + +


Schedules a message for the Apache log file or writes +it directly to the current log file depending +on the value of the use-apache-log-p argument +to START-SERVER. log-level +should be one of the +keywords :EMERG, :ALERT, :CRIT, :ERROR, :WARNING, :NOTICE, :INFO, +or :DEBUG which correspond to the various Apache log +levels. log-level can also be NIL (in +which case mod_lisp's default log level is used. If Apache isn't used, the log level is just written +to the log file unless it's NIL. +format and args are used as with +FORMAT. +

+LOG-MESSAGE is a generic function, so you can specialize it or bypass it completely with an around method. +

+ +


[Function] +
log-message* format &rest args => | + +


+Like LOG-MESSAGE but with log-level set to *DEFAULT-LOG-LEVEL*. +
+ +


[Special variable] +
*default-log-level* + +


+The log level used by LOG-MESSAGE*. The initial value is NIL. +
+ +


[Special variable] +
*log-lisp-errors-p* + +


+Whether unhandled errors in handlers should be logged. See also *LISP-ERRORS-LOG-LEVEL*. The default value is T. +
+ +


[Special variable] +
*lisp-errors-log-level* + +


+The log level used to log Lisp errors. See also *LOG-LISP-ERRORS-P*. The default value is :ERROR. +
+ +


[Special variable] +
*log-lisp-warnings-p* + +


+Whether unhandled warnings in handlers should be logged. See also *LISP-WARNINGS-LOG-LEVEL*. The default value is T. +
+ +


[Special variable] +
*lisp-warnings-log-level* + +


+The log level used to log Lisp warnings. See also *LOG-LISP-WARNINGS-P*. The default value is :WARNING. +
+ +


[Special variable] +
*log-lisp-backtraces-p* + +


+Whether backtraces should also be logged in addition to error messages and warnings. This value will only have effect if *LOG-LISP-ERRORS-P* or *LOG-LISP-WARNINGS-P* is true. The default value is NIL. +
+ +


[Special variable] +
*log-prefix* + +


+All messages written to the Apache error log by Hunchentoot are prepended by a string which is the value of this variable enclosed in square brackets. If the value is NIL, however, no such prefix will be written. If the value is T (which is the default), the prefix will be "[Hunchentoot]". +
+ +


[Special variable] +
*show-lisp-errors-p* + +


+Whether unhandled Lisp errors should be shown to the user. If this value is NIL (which is the default), only the message An error has occurred will be shown. +
+ +


[Special variable] +
*show-lisp-backtraces-p* + +


+Whether backtraces should also be shown to the user. This value will only have effect if *SHOW-LISP-ERRORS-P* is true. The default value is NIL. +
+ +


[Special variable] +
*show-access-log-messages* + +


+If this variable is true and if the value of the use-apache-log-p argument to START-SERVER was NIL, then for each request a line somewhat similar to what can be found in Apache's access log will be written to the log file. The default value of this variable is T. +
+ +


[Special variable] +
*http-error-handler* + +


+This variable holds NIL (the default) or a function designator for a function of one argument. The function gets called if the responsible handler has set a return code which is not in *APPROVED-RETURN-CODES* and *HANDLE-HTTP-ERRORS-P* is true. It receives the return code as its argument and can return the contents of an error page or NIL if it refuses to handle the error, i.e. if Hunchentoot's default error page should be shown. (Note that the function can access the request and reply data.) +
+ +


[Special variable] +
*handle-http-errors-p* + +


This variable holds a generalized boolean that +determines whether return codes not in *APPROVED-RETURN-CODES* +are treated specially. When its value is true (the default), either a +default body for the return code or the result of +calling *HTTP-ERROR-HANDLER* is +used. When the value is NIL, no special action is taken +and you are expected to supply your own response body to describe the +error. +
+ +


[Special variable] +
*approved-return-codes* +


+A list of return codes the server should not treat as an error - +see *HANDLE-HTTP-ERRORS-P*. The initial value is the list with the values of ++HTTP-OK+, +HTTP-NO-CONTENT+, +HTTP-MULTI-STATUS+, and +HTTP-NOT-MODIFIED+. +
+ +


[Function] +
get-backtrace condition => backtrace + +


+This is the function that is used internally by Hunchentoot to +show or log backtraces. It accepts a condition object condition and +returns a string with the corresponding backtrace. +
+ +

Debugging Hunchentoot applications

+ +The best option to debug a Hunchentoot application is +probably to use the debugger. +

+One important thing you should try if you're behind mod_lisp is to +use an external log file (as opposed to Apache's +log) because it can reveal error messages that might otherwise get +lost if something's broken in the communication between Hunchentoot +and mod_lisp. +

+Good luck... :) + +


[Special variable] +
*catch-errors-p* + +


If the value of this variable is NIL +(the default is T), then errors which happen while a +request is handled aren't caught as usual, but +instead your +Lisp's debugger +is invoked. +This variable should obviously always be set to a true value +in a production environment. +See MAYBE-INVOKE-DEBUGGER +if you want to fine-tune this behaviour. +
+ +


[Generic function] +
maybe-invoke-debugger condition => | + +


+This generic function is called whenever a +condition condition +is signaled in Hunchentoot. You might want to specialize it on +specific condition classes for debugging purposes. The default +method invokes +the debugger with condition if +*CATCH-ERRORS-P* is NIL. +
+ + +


[Special variable] +
*header-stream* + +


+If this variable is not NIL, it should be bound to a stream to +which incoming and outgoing headers will be written for debugging +purposes. +
+ +

Miscellaneous

+ +Various functions and variables which didn't fit into one of the other categories. + +


[Function] +
ssl-p => generalized-boolean + +


+Whether the current connection to the client is secure. +
+ +


[Symbol] +
handler-done + +


This is a catch +tag which names a catch +which is active during the lifetime of a handler. The handler can at any time throw +the outgoing content body (or NIL) to this catch to immediately abort handling the request. See the source code of REDIRECT for an example. +
+ +


[Function] +
no-cache => | + +


+This function will set appropriate outgoing headers to completely prevent caching on virtually all browsers. +
+ +


[Function] +
handle-if-modified-since time => | + +


+ +This function is designed to be used inside a handler. If the client has sent an +'If-Modified-Since' header (see RFC 2616, +section 14.25) and the time specified matches the universal time +time then the header +HTTP-NOT-MODIFIED+ with +no content is immediately returned to the client. +

+Note that for this function to be useful you should usually send +'Last-Modified' headers back to the client. See the code of CREATE-STATIC-FILE-DISPATCHER-AND-HANDLER +for an example. + +

+ +


[Function] +
rfc-1123-date &optional time => string + +


+ +This function accepts a universal time time +(default is the current time) and returns a string which encodes this time according to RFC 1123. This can be used to send a 'Last-Modified' header - see HANDLE-IF-MODIFIED-SINCE. + +
+ +


[Function] +
redirect target &key host port protocol add-session-id permanently => | + +


Sends back appropriate headers to redirect the client +to target (a string). + +If target is a full URL starting with a scheme, host, port, and protocol +are ignored. Otherwise, target should denote the path part of a +URL, protocol must be one of the keywords :HTTP or :HTTPS, and +the URL to redirect to will be constructed from host, port, protocol, +and target. +

+If permanently +is true (the default is NIL), a 301 status +code will be sent, otherwise a 302 status code. If host +is not provided, the current host (see HOST) will be +used. If protocol is the +keyword :HTTPS, the client will be redirected to a https +URL, if it's :HTTP it'll be sent to a http URL. If +both host and protocol aren't +provided, then the value of protocol will +match the current request. +

+ +


[Function] +
require-authorization &optional realm => | + +


+Sends back appropriate headers to require basic HTTP authentication (see RFC 2617) for the realm realm. The default value for realm is "Hunchentoot". +
+ +


[Function] +
escape-for-html string => escaped-string + +


+Escapes all occurrences of the characters #\<, #\>, #\', #", and #\& within string for HTML output. +
+ +


[Function] +
url-encode string &optional external-format => url-encoded-string + +


+URL-encodes a string using the external format external-format. The default for external-format is the value of *HUNCHENTOOT-DEFAULT-EXTERNAL-FORMAT*. +
+ +


[Function] +
url-decode string &optional external-format => url-encoded-string + +


+URL-decodes a string using the external format external-format, i.e. this is the inverse of URL-ENCODE. +It is assumed that you'll rarely need this function, if ever. But just in case - here it is. +The default for external-format is the value of *HUNCHENTOOT-DEFAULT-EXTERNAL-FORMAT*. +
+ +


[Function] +
http-token-p object => generalized-boolean + +


This function tests +whether object is a non-empty string which is +a token according to RFC 2068 (i.e. whether it may be used +for, say, cookie names). +
+ +


[Special variable] +
*tmp-directory* + +


+This should be a pathname denoting a directory where temporary files can be stored. It is used for file uploads. +
+ +


[Special variable] +
*hunchentoot-default-external-format* + +


The (flexi +stream) external format used when computing +the REQUEST object. The default +value is the result of evaluating +
+(flex:make-external-format :latin1 :eol-style :lf)
+
+
+ +


[Function] +
mime-type pathspec => string + +


+Given a pathname designator pathspec returns the MIME type +(as a string) corresponding to the suffix of the file denoted by +pathspec (or NIL if none can be +found). This is based on the table coming with the Apache +distribution with some additions. +
+ +


[Function] +
reason-phrase return-code => string + +


Returns a reason phrase for the HTTP return +code return-code (which should be an integer) +or NIL for return codes Hunchentoot doesn't know. +
+ +
 

The HUNCHENTOOT-MP package

+ +Hunchentoot creates an +additional package HUNCHENTOOT-MP +which exports a couple of MP-related symbols +(namely *CURRENT-PROCESS*, MAKE-LOCK, WITH-LOCK, PROCESS-RUN-FUNCTION, +and PROCESS-KILL). These functions and macros have to be +in Hunchentoot's small portability shim anyway and even if you don't +spawn your own threads there might be occasions where you want to at +least use the lock-related functionality to write thread-safe portable +code. See the corresponding documentation strings and/or the source +code for more information. + +
 

Performance

+ +If you're concerned about Hunchentoot's performance, you should first +and foremost check if you aren't wasting your time with premature +optimization. Make a reasonable estimate of the amount of traffic +your website should be able to handle and don't try to benchmark for +loads Google would be proud of. Here's a part of an interview with +someone called John Witchel about his experiences with his +company Red Gorilla that can't be quoted often enough (it +seems the original source of the interview has vanished): + +
+Q: If you could go back and change anything, would Red Gorilla still be +in business today? +

+A: Yes. I would start small and grow as the demand grew. That's what I'm +doing now. +

+Back then we planned to be huge from the outset. So we built this +monster platform on BEA, Sun and Oracle. We had huge dedicated +connectivity pipes. We had two full racks clustered and fully +redundant. We had E450's with RAID-5 and all 4 CPU slots filled, +E250s, F5 load balancers... the cost of keeping that system on was +enormous. The headcount to keep it humming was enormous too. +

+The truth is, we could have run the whole company on my laptop using a +cable modem connection. +

+ +Having said that, my experience is that Hunchentoot doesn't have to +hide when it comes to +serving static files. If +you really have performance problems with Hunchentoot, there +are two things I'm aware of you should watch out for. +
    +
  • Check how your Lisp implementation implements multi-processing. +While I write this (April 2007), some Lisps, like CMUCL, still use +their +own green +threads, and some others, like AllegroCL and LispWorks, use +OS-threads but allow only one Lisp thread at a time. Unless you're +using a Lisp that employs "real" symmetric multi-processing like SBCL +(on some platforms) or OpenMCL, you shouldn't compare apples with +oranges. (Note: For CMUCL, you also shouldn't forget to use the +dreaded MP::STARTUP-IDLE-AND-TOP-LEVEL-LOOPS.) +
  • All text output sent from handlers goes +through two layers +of Gray +streams by default +(FLEXI-STREAMS +and Chunga). This isn't an +issue for small to medium-sized pages, but can be for large ones. +There are several ways to cope with this +- return +binary data from +handlers, bypass +FLEXI-STREAMS, sit behind mod_lisp, etc. +Try it, and if you really think that Hunchentoot is too slow +for what you're trying to do and what you'll need, ask on +the mailing list and we'll try to help. +
+ +
 

History

+ +Hunchentoot's predecessor TBNL +(which is short for "To Be Named Later") grew over the years +as a toolkit that I used for various commercial and private +projects. In August 2003, Daniel Barlow started +a review of web +APIs on the lispweb +mailing list and +I described +the API of my hitherto-unreleased bunch of code (and christened it +"TBNL"). +

+It turned out that Jeff +Caldwell had worked on something similar so he emailed me and +proposed to join our efforts. As I had no immediate plans to release +my code (which was poorly organized, undocumented, and mostly +CMUCL-specific), I gave it to Jeff and he worked towards a release. He +added docstrings, refactored, added some stuff, and based it on KMRCL +to make it portable across several Lisp implementations. +

+Unfortunately, Jeff is at least as busy as I am so he didn't find the +time to finish a full release. But in spring 2004 I needed a +documented version of the code for a client of mine who thought +it would be good if the toolkit were publicly available under an open +source license. So I took Jeff's code, refactored again (to sync with +the changes I had done in the meantime), and added documentation. +This resulted in TBNL 0.1.0 (which initially required mod_lisp as its +front-end). Jeff's code (which includes a lot more stuff that I +didn't use) is still available from his own +website tbnl.org. +

+In March 2005, Bob Hutchinson sent patches which enabled TBNL to use +other front-ends than mod_lisp. This made me aware that TBNL was +already almost a full web server, so eventually I wrote +Hunchentoot which was a full web server, implemented as a +wrapper around TBNL. Hunchentoot 0.1.0 was released at the end of +2005 and was originally LispWorks-only. +

+Hunchentoot 0.4.0, released in October 2006, was the first release +which also worked with other Common Lisp implementations. It is a +major rewrite and also incorporates most of TBNL and replaces +it completely. + +
 

Symbol index

+ +Here are all exported symbols of the HUNCHENTOOT package +in alphabetical order linked to their corresponding entries: + + + +
 

Acknowledgements

+ +Thanks to Jeff Caldwell - TBNL would not have been released without +his efforts. Thanks to Marc +Battyani for mod_lisp and +to Chris Hanson for +mod_lisp2. Thanks +to Stefan Scholl +and Travis Cross for various additions and fixes to TBNL, +to Michael Weber for +initial file upload code, and +to Janis Dzerins for +his RFC 2388 +code. Thanks to Bob Hutchison for his code for multiple front-ends +(which made me realize that TBNL was already pretty close to a "real" +web server) and the initial UTF-8 example. Thanks to John +Foderaro's AllegroServe +for inspiration. Thanks +to Uwe von Loh for the Hunchentoot +logo. +

+Hunchentoot originally used code +from ACL-COMPAT, +specifically the chunking code from Jochen Schmidt. (This has been +replaced by Chunga.) When I +ported Hunchentoot to other Lisps than LispWorks, I stole code from +ACL-COMPAT, KMRCL, +and trivial-sockets +for implementation-dependent stuff like sockets and MP. +

+Parts of this documentation were prepared +with DOCUMENTATION-TEMPLATE, no animals were harmed. +

+

+$Header: /usr/local/cvsrep/hunchentoot/doc/index.html,v 1.126 2007/12/29 17:35:03 edi Exp $ +

BACK TO MY HOMEPAGE + + + Added: branches/trunk-reorg/thirdparty/hunchentoot-0.15.0/easy-handlers.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/hunchentoot-0.15.0/easy-handlers.lisp Thu Feb 7 03:16:29 2008 @@ -0,0 +1,319 @@ +;;; -*- Mode: LISP; Syntax: COMMON-LISP; Package: HUNCHENTOOT; Base: 10 -*- +;;; $Header: /usr/local/cvsrep/hunchentoot/easy-handlers.lisp,v 1.12 2007/05/25 11:32:50 edi Exp $ + +;;; Copyright (c) 2004-2007, Dr. Edmund Weitz. All rights reserved. + +;;; Redistribution and use in source and binary forms, with or without +;;; modification, are permitted provided that the following conditions +;;; are met: + +;;; * Redistributions of source code must retain the above copyright +;;; notice, this list of conditions and the following disclaimer. + +;;; * Redistributions in binary form must reproduce the above +;;; copyright notice, this list of conditions and the following +;;; disclaimer in the documentation and/or other materials +;;; provided with the distribution. + +;;; THIS SOFTWARE IS PROVIDED BY THE AUTHOR 'AS IS' AND ANY EXPRESSED +;;; OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +;;; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +;;; ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +;;; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +;;; DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +;;; GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +;;; INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +;;; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +;;; NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +;;; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +(in-package :hunchentoot) + +(defun compute-real-name (symbol) + "Computes the `real' paramater name \(a string) from the Lisp +symbol SYMBOL. Used in cases where no parameter name is +provided." + ;; we just downcase the symbol's name + (string-downcase symbol)) + +(defun convert-parameter (argument type) + "Converts the string ARGUMENT to TYPE where TYPE is one of the +symbols STRING, CHARACTERS, INTEGER, KEYWORD, or BOOLEAN - or +otherwise a function designator for a function of one argument. +ARGUMENT can also be NIL in which case this function also returns +NIL unconditionally." + (when (listp argument) + ;; this if for the case that ARGUMENT is NIL or the result of a + ;; file upload + (return-from convert-parameter argument)) + (case type + (string argument) + (character (and (= (length argument) 1) + (char argument 0))) + (integer (ignore-errors (parse-integer argument :junk-allowed t))) + (keyword (make-keyword argument :destructivep nil)) + (boolean t) + (otherwise (funcall type argument)))) + +(defun compute-simple-parameter (parameter-name type parameter-reader) + "Retrieves the parameter named PARAMETER-NAME using the reader +PARAMETER-READER and converts it to TYPE." + (convert-parameter (funcall parameter-reader parameter-name) type)) + +(defun compute-list-parameter (parameter-name type parameters) + "Retrieves all parameters from PARAMETERS which are named +PARAMETER-NAME, converts them to TYPE, and returns a list of +them." + (loop for (name . value) in parameters + when (string= name parameter-name) + collect (convert-parameter value type))) + +(defun compute-array-parameter (parameter-name type parameters) + "Retrieves all parameters from PARAMETERS which are named like +\"PARAMETER-NAME[N]\" \(where N is a non-negative integer), +converts them to TYPE, and returns an array where the Nth element +is the corresponding value." + ;; see + #+:sbcl (declare (sb-ext:muffle-conditions warning)) + (let* ((index-value-list + (loop for (full-name . value) in parameters + for index = (register-groups-bind (name index-string) + ("^(.*)\\[(\\d+)\\]$" full-name) + (when (string= name parameter-name) + (parse-integer index-string))) + when index + collect (cons index (convert-parameter value type)))) + (array (make-array (1+ (reduce #'max index-value-list + :key #'car + :initial-value -1)) + :initial-element nil))) + (loop for (index . value) in index-value-list + do (setf (aref array index) value)) + array)) + +(defun compute-hash-table-parameter (parameter-name type parameters key-type test-function) + "Retrieves all parameters from PARAMETERS which are named like +\"PARAMETER-NAME{FOO}\" \(where FOO is any sequence of characters +not containing curly brackets), converts them to TYPE, and +returns a hash table with test function TEST-FUNCTION where the +corresponding value is associated with the key FOO \(converted to +KEY-TYPE)." + (let ((hash-table (make-hash-table :test test-function))) + (loop for (full-name . value) in parameters + for key = (register-groups-bind (name key-string) + ("^(.*){([^{}]+)}$" full-name) + (when (string= name parameter-name) + (convert-parameter key-string key-type))) + when key + do (setf (gethash key hash-table) + (convert-parameter value type))) + hash-table)) + +(defun compute-parameter (parameter-name parameter-type request-type) + "Computes and returns the parameter\(s) called PARAMETER-NAME +and converts it/them according to the value of PARAMETER-TYPE. +REQUEST-TYPE is one of :GET, :POST, or :BOTH." + (when (member parameter-type '(list array hash-table)) + (setq parameter-type (list parameter-type 'string))) + (let ((parameter-reader (ecase request-type + (:get #'get-parameter) + (:post #'post-parameter) + (:both #'parameter))) + (parameters (and (listp parameter-type) + (case request-type + (:get (get-parameters)) + (:post (post-parameters)) + (:both (append (get-parameters) (post-parameters))))))) + (cond ((atom parameter-type) + (compute-simple-parameter parameter-name parameter-type parameter-reader)) + ((and (null (cddr parameter-type)) + (eq (first parameter-type) 'list)) + (compute-list-parameter parameter-name (second parameter-type) parameters)) + ((and (null (cddr parameter-type)) + (eq (first parameter-type) 'array)) + (compute-array-parameter parameter-name (second parameter-type) parameters)) + ((and (null (cddddr parameter-type)) + (eq (first parameter-type) 'hash-table)) + (compute-hash-table-parameter parameter-name (second parameter-type) parameters + (or (third parameter-type) 'string) + (or (fourth parameter-type) 'equal))) + (t (error "Don't know what to do with parameter type ~S." parameter-type))))) + +(defun make-defun-parameter (description default-parameter-type default-request-type) + "Creates a keyword parameter to be used by DEFINE-EASY-HANDLER. +DESCRIPTION is one of the elements of DEFINE-EASY-HANDLER's +LAMBDA-LIST and DEFAULT-PARAMETER-TYPE and DEFAULT-REQUEST-TYPE +are the global default values." + (when (atom description) + (setq description (list description))) + (destructuring-bind (parameter-name &key (real-name (compute-real-name parameter-name)) + parameter-type init-form request-type) + description + `(,parameter-name (or (and (boundp '*request*) + (compute-parameter ,real-name + ,(or parameter-type default-parameter-type) + ,(or request-type default-request-type))) + ,init-form)))) + +(defmacro define-easy-handler (description lambda-list &body body) + "Defines a handler with the body BODY and optionally registers +it with a URI so that it will be found by DISPATCH-EASY-HANDLERS. +DESCRIPTION is either a symbol NAME or a list matching the +destructuring lambda list + + (name &key uri server-names default-parameter-type default-request-type). + +LAMBDA-LIST is a list the elements of which are either a symbol +VAR or a list matching the destructuring lambda list + + (var &key real-name parameter-type init-form request-type). + +The resulting handler will be a Lisp function with the name NAME +and keyword parameters named by the VAR symbols. Each VAR will +be bound to the value of the GET or POST parameter called +REAL-NAME \(a string) before BODY is executed. If REAL-NAME is +not provided, it will be computed by downcasing the symbol name +of VAR. + +If URI \(which is evaluated) is provided, then it must be a string or +a function designator for a function of one argument. In this case, +the handler will be returned by DISPATCH-EASY-HANDLERS, if URI is a +string and the script name of a request is URI, or if URI designates a +function and applying this function to the current request object +returns a true value. + +SERVER-NAMES \(which is evaluated) can be a list of symbols which +means that the handler will be returned by DISPATCH-EASY-HANDLERS in +servers which have one of these names \(see SERVER-NAME). +SERVER-NAMES can also be the symbol T which means that the handler +will be returned by DISPATCH-EASY-HANDLERS in every server. + +Whether the GET or POST parameter \(or both) will be taken into +consideration, depends on REQUEST-TYPE which can +be :GET, :POST, :BOTH, or NIL. In the last case, the value of +DEFAULT-REQUEST-TYPE \(the default of which is :BOTH) will be +used. + +The value of VAR will usually be a string \(unless it resulted from a +file upload in which case it won't be converted at all), but if +PARAMETER-TYPE \(which is evaluated) is provided, the string will be +converted to another Lisp type by the following rules: + +If the corresponding GET or POST parameter wasn't provided by the +client, VAR's value will be NIL. If PARAMETER-TYPE is 'STRING, VAR's +value remains as is. If PARAMETER-TYPE is 'INTEGER and the parameter +string consists solely of decimal digits, VAR's value will be the +corresponding integer, otherwise NIL. If PARAMETER-TYPE is 'KEYWORD, +VAR's value will be the keyword obtained by interning the upcased +parameter string into the keyword package. If PARAMETER-TYPE is +'CHARACTER and the parameter string is of length one, VAR's value will +be the single character of this string, otherwise NIL. If +PARAMETER-TYPE is 'BOOLEAN, VAR's value will always be T \(unless it +is NIL by the first rule above, of course). If PARAMETER-TYPE is any +other atom, it is supposed to be a function designator for a unary +function which will be called to convert the string to something else. + +Those were the rules for `simple' types, but PARAMETER-TYPE can +also be a list starting with one of the symbols LIST, ARRAY, or +HASH-TABLE. The second value of the list must always be a simple +parameter type as in the last paragraph - we'll call it the +`inner type' below. + +In the case of 'LIST, all GET/POST parameters called REAL-NAME +will be collected, converted to the inner type, and assembled +into a list which will be the value of VAR. + +In the case of 'ARRAY, all GET/POST parameters which have a name +like the result of + + (format nil \"~A[~A]\" real-name n) + +where N is a non-negative integer, will be assembled into an +array where the Nth element will be set accordingly, after +conversion to the inner type. The array, which will become the +value of VAR, will be big enough to hold all matching parameters, +but not bigger. Array elements not set as described above will +be NIL. Note that VAR will always be bound to an array, which +may be empty, so it will never be NIL, even if no appropriate +GET/POST parameters are found. + +The full form of a 'HASH-TABLE parameter type is + + (hash-table inner-type key-type test-function), + +but KEY-TYPE and TEST-FUNCTION can be left out in which case they +default to 'STRING and 'EQUAL, respectively. For this parameter +type, all GET/POST parameters which have a name like the result +of + + (format nil \"~A{~A}\" real-name key) + +\(where KEY is a string that doesn't contain curly brackets) will +become the values \(after conversion to INNER-TYPE) of a hash +table with test function TEST-FUNCTION where KEY \(after +conversion to KEY-TYPE) will be the corresponding key. Note that +VAR will always be bound to a hash table, which may be empty, so +it will never be NIL, even if no appropriate GET/POST parameters +are found. + +To make matters even more complicated, the three compound +parameter types also have an abbreviated form - just one of the +symbols LIST, ARRAY, or HASH-TABLE. In this case, the inner type +will default to 'STRING. + +If PARAMETER-TYPE is not provided or NIL, DEFAULT-PARAMETER-TYPE +\(the default of which is 'STRING) will be used instead. + +If the result of the computations above would be that VAR would +be bound to NIL, then INIT-FORM \(if provided) will be evaluated +instead, and VAR will be bound to the result of this evaluation. + +Handlers built with this macro are constructed in such a way that +the resulting Lisp function is useful even outside of +Hunchentoot. Specifically, all the parameter computations above +will only happen if *REQUEST* is bound, i.e. if we're within a +Hunchentoot request. Otherwise, VAR will always be bound to the +result of evaluating INIT-FORM unless a corresponding keyword +argument is provided." + (when (atom description) + (setq description (list description))) + (destructuring-bind (name &key uri (server-names t) + (default-parameter-type ''string) + (default-request-type :both)) + description + `(progn + ,@(when uri + (list + (with-rebinding (uri) + `(progn + (setq *easy-handler-alist* + (delete-if (lambda (list) + (or (equal ,uri (first list)) + (eq ',name (third list)))) + *easy-handler-alist*)) + (push (list ,uri ,server-names ',name) *easy-handler-alist*))))) + (defun ,name (&key ,@(loop for part in lambda-list + collect (make-defun-parameter part + default-parameter-type + default-request-type))) + , at body)))) + +;; help the LispWorks IDE to find these definitions +#+:lispworks +(dspec:define-form-parser define-easy-handler (description) + `(,define-easy-handler ,(if (atom description) description (first description)))) + +#+:lispworks +(dspec:define-dspec-alias define-easy-handler (name) + `(defun ,name)) + +(defun dispatch-easy-handlers (request) + "This is a dispatcher which returns the appropriate handler +defined with DEFINE-EASY-HANDLER, if there is one." + (loop for (uri server-names easy-handler) in *easy-handler-alist* + when (and (or (eq server-names t) + (find (server-name *server*) server-names :test #'eq)) + (cond ((stringp uri) + (string= (script-name request) uri)) + (t (funcall uri request)))) + do (return easy-handler))) Added: branches/trunk-reorg/thirdparty/hunchentoot-0.15.0/headers.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/hunchentoot-0.15.0/headers.lisp Thu Feb 7 03:16:29 2008 @@ -0,0 +1,323 @@ +;;; -*- Mode: LISP; Syntax: COMMON-LISP; Package: HUNCHENTOOT; Base: 10 -*- +;;; $Header: /usr/local/cvsrep/hunchentoot/headers.lisp,v 1.25 2007/12/29 17:35:00 edi Exp $ + +;;; Copyright (c) 2004-2007, Dr. Edmund Weitz. All rights reserved. + +;;; Redistribution and use in source and binary forms, with or without +;;; modification, are permitted provided that the following conditions +;;; are met: + +;;; * Redistributions of source code must retain the above copyright +;;; notice, this list of conditions and the following disclaimer. + +;;; * Redistributions in binary form must reproduce the above +;;; copyright notice, this list of conditions and the following +;;; disclaimer in the documentation and/or other materials +;;; provided with the distribution. + +;;; THIS SOFTWARE IS PROVIDED BY THE AUTHOR 'AS IS' AND ANY EXPRESSED +;;; OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +;;; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +;;; ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +;;; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +;;; DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +;;; GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +;;; INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +;;; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +;;; NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +;;; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +(in-package :hunchentoot) + +(defun maybe-write-to-header-stream (key &optional value) + (when *header-stream* + (format *header-stream* "~A~@[: ~A~]~%" key + (and value (regex-replace-all "[\\r\\n]" value " "))) + (force-output *header-stream*))) + +(defun compute-length (content) + "Computes and returns the length of CONTENT in octets. Returns as a +second value CONTENT as a vector of octets. The result depends on the +external format of *REPLY*." + (when (null content) + (return-from compute-length)) + (when (stringp content) + (setq content + (string-to-octets content :external-format (reply-external-format)))) + (values (length content) content)) + +(defmethod write-header-line ((mod-lisp-p (eql nil)) key value) + "Accepts strings KEY and VALUE and writes them directly to the +client as an HTTP header line." + (write-string key *hunchentoot-stream*) + (write-string ": " *hunchentoot-stream*) + ;; remove line breaks + (write-string (regex-replace-all "[\\r\\n]" value " ") *hunchentoot-stream*) + (write-string +crlf+ *hunchentoot-stream*)) + +(defmethod write-header-line (mod-lisp-p key value) + "Accepts strings KEY and VALUE and writes them, one line at a time, +to the mod_lisp socket stream." + (write-line key *hunchentoot-stream*) + ;; remove line breaks + (write-line (regex-replace-all "[\\r\\n]" value " ") *hunchentoot-stream*)) + +(defmethod write-header-line :after (mod-lisp-p key value) + (declare (ignorable mod-lisp-p)) + (maybe-write-to-header-stream key value)) + +(defun start-output (&optional (content nil content-provided-p)) + "Sends all headers and maybe the content body to +*HUNCHENTOOT-STREAM*. Returns immediately and does nothing if called +more than once per request. Handles the supported return codes +accordingly. Called by PROCESS-REQUEST and/or SEND-HEADERS. Returns +the stream to write to." + ;; send headers only once + (when *headers-sent* + (return-from start-output)) + (setq *headers-sent* t) + ;; read post data to clear stream + (raw-post-data) + (let* ((mod-lisp-p (server-mod-lisp-p *server*)) + (return-code (return-code)) + (chunkedp (and (server-output-chunking-p *server*) + (eq (server-protocol) :http/1.1) + ;; only turn chunking on if the content + ;; length is unknown at this point... + (null (or (content-length) content-provided-p)) + ;; ...AND if the return code isn't one where + ;; Hunchentoot (or a user error handler) sends its + ;; own content + (member return-code *approved-return-codes*))) + (reason-phrase (reason-phrase return-code)) + (request-method (request-method)) + (head-request-p (eq request-method :head)) + content-modified-p) + (unless mod-lisp-p + (multiple-value-bind (keep-alive-p keep-alive-requested-p) + (keep-alive-p) + (when keep-alive-p + (setq keep-alive-p + ;; use keep-alive if there's a way for the client to + ;; determine when all content is sent (or if there + ;; is no content) + (or chunkedp + head-request-p + (eq (return-code) +http-not-modified+) + (content-length) + content))) + ;; now set headers for keep-alive and chunking + (when chunkedp + (setf (header-out "Transfer-Encoding") "chunked")) + (cond (keep-alive-p + (setf *close-hunchentoot-stream* nil) + (when (or (not (eq (server-protocol) :http/1.1)) + keep-alive-requested-p) + ;; persistent connections are implicitly assumed for + ;; HTTP/1.1, but we return a 'Keep-Alive' header if the + ;; client has explicitly asked for one + (setf (header-out "Connection") "Keep-Alive" + (header-out "Keep-Alive") + (format nil "timeout=~D" (server-read-timeout *server*))))) + (t (setf (header-out "Connection") "Close")))) + (unless (and (header-out-set-p "Server") + (null (header-out "Server"))) + (setf (header-out "Server") (or (header-out "Server") + (server-name-header)))) + (setf (header-out "Date") (rfc-1123-date))) + (unless reason-phrase + (setq content (escape-for-html + (format nil "Unknown http return code: ~A" return-code)) + content-modified-p t + return-code +http-internal-server-error+ + reason-phrase (reason-phrase return-code))) + (unless (or (not *handle-http-errors-p*) + (member return-code *approved-return-codes*)) + ;; call error handler, if any - should return NIL if it can't + ;; handle the error + (let (error-handled-p) + (when *http-error-handler* + (setq error-handled-p (funcall *http-error-handler* return-code) + content (or error-handled-p content) + content-modified-p (or content-modified-p error-handled-p))) + ;; handle common return codes other than 200, which weren't + ;; handled by the error handler + (unless error-handled-p + (setf (content-type) + "text/html; charset=iso-8859-1" + content-modified-p t + content + (format nil "~D ~A

~:*~A

~A


~A

" + return-code reason-phrase + (case return-code + ((#.+http-internal-server-error+) content) + ((#.+http-moved-temporarily+ #.+http-moved-permanently+) + (format nil "The document has moved here" + (header-out "Location"))) + ((#.+http-authorization-required+) + "The server could not verify that you are authorized to access the document requested. Either you supplied the wrong credentials \(e.g., bad password), or your browser doesn't understand how to supply the credentials required.") + ((#.+http-forbidden+) + (format nil "You don't have permission to access ~A on this server." + (script-name))) + ((#.+http-not-found+) + (format nil "The requested URL ~A was not found on this server." + (script-name))) + ((#.+http-bad-request+) + "Your browser sent a request that this server could not understand.") + (otherwise "")) + (address-string)))))) + ;; start with status line + (cond (mod-lisp-p + (write-header-line t "Status" (format nil "~D ~A" return-code reason-phrase))) + (t + (let ((first-line + (format nil "HTTP/1.1 ~D ~A" return-code reason-phrase))) + (write-string first-line *hunchentoot-stream*) + (write-string +crlf+ *hunchentoot-stream*) + (maybe-write-to-header-stream first-line)))) + (when (and (stringp content) + (not content-modified-p) + (starts-with-one-of-p (or (content-type) "") + *content-types-for-url-rewrite*)) + ;; if the Content-Type header starts with one of the strings + ;; in *CONTENT-TYPES-FOR-URL-REWRITE* then maybe rewrite the + ;; content + (setq content (maybe-rewrite-urls-for-session content))) + (let ((content-length (content-length))) + (unless content-length + (multiple-value-setq (content-length content) (compute-length content))) + ;; write the corresponding headers for the content + (when content-length + (write-header-line mod-lisp-p "Content-Length" (format nil "~D" content-length)) + (when mod-lisp-p + (write-header-line t "Lisp-Content-Length" + (cond (head-request-p "0") + (t (format nil "~D" content-length)))) + (write-header-line t "Keep-Socket" "1") + (setq *close-hunchentoot-stream* nil))) + (when-let (content-type (content-type)) + (write-header-line mod-lisp-p "Content-Type" content-type)) + ;; write all headers from the REPLY object + (loop for (key . value) in (headers-out) + when value + do (write-header-line mod-lisp-p (string-capitalize key) value)) + ;; now the cookies + (loop for (nil . cookie) in (cookies-out) + do (write-header-line mod-lisp-p "Set-Cookie" (stringify-cookie cookie))) + (when mod-lisp-p + ;; send log messages to mod_lisp + (loop for (log-level . message) in (reverse (log-messages *reply*)) + do (write-header-line t (case log-level + ((:emerg) "Log-Emerg") + ((:alert) "Log-Alert") + ((:crit) "Log-Crit") + ((:error) "Log-Error") + ((:warning) "Log-Warning") + ((:notice) "Log-Notice") + ((:info) "Log-Info") + ((:debug) "Log-Debug") + (otherwise "Log")) + message))) + ;; all headers sent + (cond (mod-lisp-p + (write-line "end" *hunchentoot-stream*) + (maybe-write-to-header-stream "end")) + (t + (write-string +crlf+ *hunchentoot-stream*) + (maybe-write-to-header-stream ""))) + ;; access log message + (when (and *show-access-log-messages* + (not (server-use-apache-log-p *server*))) + (ignore-errors + (log-message nil "~:[-~@[ (~A)~]~;~:*~A~@[ (~A)~]~] ~:[-~;~:*~A~] \"~A ~A~@[?~A~] ~A\" ~A ~:[~*-~;~D~] \"~:[-~;~:*~A~]\" \"~:[-~;~:*~A~]\"" + (remote-addr) (header-in :x-forwarded-for) + (authorization) request-method (script-name) + (query-string) (server-protocol) + return-code content content-length + (referer) (user-agent))))) + (setf (flexi-stream-external-format *hunchentoot-stream*) (reply-external-format)) + ;; now optional content + (unless (or (null content) head-request-p) + (ignore-errors + #+:clisp + (unless (stringp content) + (setf (flexi-stream-element-type *hunchentoot-stream*) 'octet)) + (write-sequence content *hunchentoot-stream*))) + (when chunkedp + ;; turn chunking on after the headers have been sent + (setf (chunked-stream-output-chunking-p + (flexi-stream-stream *hunchentoot-stream*)) t)) + *hunchentoot-stream*)) + +(defun send-headers () + "Sends the initial status line and all headers as determined by +the REPLY object *REPLY*. Returns a stream to which the body of +the reply can be written. Once this function has been called, +further changes to *REPLY* don't have any effect. Also, +automatic handling of errors \(i.e. sending the corresponding +status code to the browser, etc.) is turned off for this request. +If your handlers return the full body as a string or as an array +of octets you should NOT call this function." + (start-output)) + +(defun get-request-data () + "Reads incoming headers from mod_lisp or directly from the client +via *HUNCHENTOOT-STREAM*. Returns as multiple values the headers as +an alist, the stream to read the request body from, the method, the +URI, and the protocol of the request. The last three values are only +returned if we're not behind mod_lisp." + (ignore-errors + (let* ((mod-lisp-p (server-mod-lisp-p *server*)) + (first-line (if mod-lisp-p + (read-line *hunchentoot-stream* nil nil) + (cl:handler-case + (read-line* *hunchentoot-stream*) + ((or end-of-file + #+:sbcl sb-sys:io-timeout + #+:cmu sys:io-timeout + #+:allegro excl:socket-error) () + nil))))) + (cond ((null first-line) + ;; socket closed - return immediately + nil) + (mod-lisp-p + ;; we're behind mod_lisp, so we read alternating + ;; key/value lines + (let ((second-line (read-line *hunchentoot-stream* t))) + (maybe-write-to-header-stream first-line second-line) + (let* ((headers + (loop for key = (read-line *hunchentoot-stream* nil nil) + while (and key (string-not-equal key "end")) + for value = (read-line *hunchentoot-stream* t) + collect (cons (make-keyword key) value) + do (maybe-write-to-header-stream key value))) + (content-length (cdr (assoc :content-length headers)))) + ;; add contents of first two lines + (push (cons (make-keyword first-line) second-line) headers) + (values (delete-duplicates headers :test #'eq :key #'car) + (and (or content-length + (server-input-chunking-p *server*)) + *hunchentoot-stream*))))) + (t + ;; we're a stand-alone web server, so we use Chunga to + ;; read the headers + (destructuring-bind (method url-string &optional protocol) + (split "\\s+" first-line :limit 3) + (maybe-write-to-header-stream first-line) + (let ((headers (and protocol (read-http-headers *hunchentoot-stream* + *header-stream*)))) + (unless protocol (setq protocol "HTTP/0.9")) + (when (equalp (cdr (assoc :expect headers)) "100-continue") + ;; handle 'Expect: 100-continue' header + (let ((continue-line + (format nil "HTTP/1.1 ~D ~A" + +http-continue+ + (reason-phrase +http-continue+)))) + (write-string continue-line *hunchentoot-stream*) + (write-string +crlf+ *hunchentoot-stream*) + (write-string +crlf+ *hunchentoot-stream*) + (force-output *hunchentoot-stream*) + (maybe-write-to-header-stream continue-line) + (maybe-write-to-header-stream ""))) + (values headers *hunchentoot-stream* (make-keyword method) url-string + (make-keyword (string-trim '(#\Space #\Tab #\NewLine #\Return) protocol)))))))))) \ No newline at end of file Added: branches/trunk-reorg/thirdparty/hunchentoot-0.15.0/hunchentoot-test.asd ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/hunchentoot-0.15.0/hunchentoot-test.asd Thu Feb 7 03:16:29 2008 @@ -0,0 +1,35 @@ +;;; -*- Mode: LISP; Syntax: COMMON-LISP; Package: CL-USER; Base: 10 -*- +;;; $Header: /usr/local/cvsrep/hunchentoot/hunchentoot-test.asd,v 1.2 2007/01/01 23:50:30 edi Exp $ + +;;; Copyright (c) 2004-2007, Dr. Edmund Weitz. All rights reserved. + +;;; Redistribution and use in source and binary forms, with or without +;;; modification, are permitted provided that the following conditions +;;; are met: + +;;; * Redistributions of source code must retain the above copyright +;;; notice, this list of conditions and the following disclaimer. + +;;; * Redistributions in binary form must reproduce the above +;;; copyright notice, this list of conditions and the following +;;; disclaimer in the documentation and/or other materials +;;; provided with the distribution. + +;;; THIS SOFTWARE IS PROVIDED BY THE AUTHOR 'AS IS' AND ANY EXPRESSED +;;; OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +;;; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +;;; ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +;;; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +;;; DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +;;; GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +;;; INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +;;; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +;;; NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +;;; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +(asdf:defsystem :hunchentoot-test + :components ((:module "test" + :serial t + :components ((:file "packages") + (:file "test")))) + :depends-on (:hunchentoot :cl-who)) Added: branches/trunk-reorg/thirdparty/hunchentoot-0.15.0/hunchentoot.asd ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/hunchentoot-0.15.0/hunchentoot.asd Thu Feb 7 03:16:29 2008 @@ -0,0 +1,81 @@ +;;; -*- Mode: LISP; Syntax: COMMON-LISP; Package: CL-USER; Base: 10 -*- +;;; $Header: /usr/local/cvsrep/hunchentoot/hunchentoot.asd,v 1.53 2007/12/29 17:35:01 edi Exp $ + +;;; Copyright (c) 2004-2007, Dr. Edmund Weitz. All rights reserved. + +;;; Redistribution and use in source and binary forms, with or without +;;; modification, are permitted provided that the following conditions +;;; are met: + +;;; * Redistributions of source code must retain the above copyright +;;; notice, this list of conditions and the following disclaimer. + +;;; * Redistributions in binary form must reproduce the above +;;; copyright notice, this list of conditions and the following +;;; disclaimer in the documentation and/or other materials +;;; provided with the distribution. + +;;; THIS SOFTWARE IS PROVIDED BY THE AUTHOR 'AS IS' AND ANY EXPRESSED +;;; OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +;;; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +;;; ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +;;; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +;;; DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +;;; GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +;;; INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +;;; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +;;; NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +;;; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +(in-package :cl-user) + +(defpackage :hunchentoot-asd + (:use :cl :asdf)) + +(in-package :hunchentoot-asd) + +(defvar *hunchentoot-version* "0.15.0" + "A string denoting the current version of Hunchentoot. Used +for diagnostic output.") + +(export '*hunchentoot-version*) + +(asdf:defsystem :hunchentoot + :serial t + :version #.*hunchentoot-version* + :depends-on (:chunga + :cl-base64 + :cl-ppcre + #-(or :lispworks :hunchentoot-no-ssl) :cl+ssl + :md5 + :rfc2388 + #+:sbcl :sb-bsd-sockets + #+:sbcl :sb-posix + #+:openmcl :acl-compat + :url-rewrite) + :components ((:file "packages") + (:file "conditions") + #+:allegro (:file "port-acl") + #+:clisp (:file "port-clisp") + #+:cmu (:file "port-cmu") + #+:lispworks (:file "port-lw") + #+:openmcl (:file "port-mcl") + #+:sbcl (:file "port-sbcl") + (:file "specials") + (:file "mime-types") + (:file "util") + (:file "log") + (:file "cookie") + (:file "reply") + (:file "request") + (:file "session") + (:file "misc") + (:file "easy-handlers") + (:file "headers") + #+(and :allegro :unix) (:file "unix-acl") + #+(and :clisp :unix) (:file "unix-clisp") + #+(and :cmu :unix) (:file "unix-cmu") + #+(and :lispworks :unix) (:file "unix-lw") + #+(and :openmcl :unix) (:file "unix-mcl") + #+(and :sbcl :unix (not :win32)) (:file "unix-sbcl") + (:file "server"))) Added: branches/trunk-reorg/thirdparty/hunchentoot-0.15.0/log.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/hunchentoot-0.15.0/log.lisp Thu Feb 7 03:16:29 2008 @@ -0,0 +1,93 @@ +;;; -*- Mode: LISP; Syntax: COMMON-LISP; Package: HUNCHENTOOT; Base: 10 -*- +;;; $Header: /usr/local/cvsrep/hunchentoot/log.lisp,v 1.9 2007/10/19 23:51:32 edi Exp $ + +;;; Copyright (c) 2004-2007, Dr. Edmund Weitz. All rights reserved. + +;;; Redistribution and use in source and binary forms, with or without +;;; modification, are permitted provided that the following conditions +;;; are met: + +;;; * Redistributions of source code must retain the above copyright +;;; notice, this list of conditions and the following disclaimer. + +;;; * Redistributions in binary form must reproduce the above +;;; copyright notice, this list of conditions and the following +;;; disclaimer in the documentation and/or other materials +;;; provided with the distribution. + +;;; THIS SOFTWARE IS PROVIDED BY THE AUTHOR 'AS IS' AND ANY EXPRESSED +;;; OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +;;; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +;;; ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +;;; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +;;; DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +;;; GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +;;; INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +;;; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +;;; NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +;;; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +(in-package :hunchentoot) + +(defgeneric log-message (log-level fmt &rest args)) + +(defmethod log-message (log-level fmt &rest args) + "Sends a formatted message to Apache's error log when the data gets +sent to Apache/mod_lisp and SERVER-USE-APACHE-LOG-P is true, otherwise +logs to the file denoted by LOG-FILE. FMT and ARGS are as in FORMAT. +LOG-LEVEL is a keyword denoting the corresponding Apache error level." + (let ((message (apply #'format nil fmt args))) + (cond ((and (boundp '*server*) + (server-mod-lisp-p *server*) + (server-use-apache-log-p *server*)) + (with-input-from-string (s message) + (loop with prolog = (case *log-prefix* + ((nil) "") + ((t) "[Hunchentoot] ") + (otherwise (format nil "[~A] " *log-prefix*))) + for line = (read-line s nil nil) + while line + do (push (cons log-level + (format nil "~A~A" prolog line)) + (slot-value *reply* 'log-messages))))) + (t (with-lock (*log-file-lock*) + (ignore-errors + (unless *log-file-stream* + (let ((log-file-stream + (open (ensure-directories-exist *log-file*) + :direction :output + :element-type 'octet + :if-does-not-exist :create + :if-exists :append + #+:openmcl #+:openmcl + :sharing :lock))) + (setq *log-file-stream* + (make-flexi-stream log-file-stream + :external-format +utf-8+)))) + (handler-case + (format *log-file-stream* + "[~A~@[ [~A]~]] ~A~%" (iso-time) log-level message) + (error () + (format *log-file-stream* "[~A [EMERG]] A message could not be logged!" + (iso-time)))) + (force-output *log-file-stream*)))))) + (values)) + +(defun log-message* (fmt &rest args) + "Same as LOG-MESSAGE* but with the default log level \(as +defined by *DEFAULT-LOG-LEVEL*)." + (apply #'log-message *default-log-level* fmt args)) + +(defun log-file () + "Returns the log file which is currently used." + *log-file*) + +(defun (setf log-file) (pathspec) + "Sets the log file which is to be used." + (with-lock (*log-file-lock*) + (when *log-file-stream* + (ignore-errors + (close *log-file-stream*)) + (setq *log-file-stream* nil)) + (setq *log-file* pathspec))) + \ No newline at end of file Added: branches/trunk-reorg/thirdparty/hunchentoot-0.15.0/mime-types.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/hunchentoot-0.15.0/mime-types.lisp Thu Feb 7 03:16:29 2008 @@ -0,0 +1,362 @@ +;;; -*- Mode: LISP; Syntax: COMMON-LISP; Package: HUNCHENTOOT; Base: 10 -*- +;;; $Header: /usr/local/cvsrep/hunchentoot/mime-types.lisp,v 1.3 2007/01/01 23:50:30 edi Exp $ + +;;; Copyright (c) 2004-2007, Dr. Edmund Weitz. All rights reserved. + +;;; Redistribution and use in source and binary forms, with or without +;;; modification, are permitted provided that the following conditions +;;; are met: + +;;; * Redistributions of source code must retain the above copyright +;;; notice, this list of conditions and the following disclaimer. + +;;; * Redistributions in binary form must reproduce the above +;;; copyright notice, this list of conditions and the following +;;; disclaimer in the documentation and/or other materials +;;; provided with the distribution. + +;;; THIS SOFTWARE IS PROVIDED BY THE AUTHOR 'AS IS' AND ANY EXPRESSED +;;; OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +;;; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +;;; ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +;;; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +;;; DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +;;; GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +;;; INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +;;; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +;;; NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +;;; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +(in-package :hunchentoot) + +(defparameter *mime-type-list* '(("application/andrew-inset" "ez") + ("application/cu-seeme" "cu") + ("application/dsptype" "tsp") + ("application/futuresplash" "spl") + ("application/hta" "hta") + ("application/java-archive" "jar") + ("application/java-serialized-object" "ser") + ("application/java-vm" "class") + ("application/mac-binhex40" "hqx") + ("application/mac-compactpro" "cpt") + ("application/mathematica" "nb") + ("application/msaccess" "mdb") + ("application/msword" "doc" "dot") + ("application/octet-stream" "bin") + ("application/oda" "oda") + ("application/ogg" "ogg") + ("application/pdf" "pdf") + ("application/pgp-keys" "key") + ("application/pgp-signature" "pgp") + ("application/pics-rules" "prf") + ("application/postscript" "ps" "ai" "eps") + ("application/rar" "rar") + ("application/rdf+xml" "rdf") + ("application/rss+xml" "rss") + ("application/smil" "smi" "smil") + ("application/wordperfect" "wpd") + ("application/wordperfect5.1" "wp5") + ("application/xhtml+xml" "xhtml" "xht") + ("application/xml" "fo" "xml" "xsl") + ("application/zip" "zip") + ("application/vnd.cinderella" "cdy") + ("application/vnd.mozilla.xul+xml" "xul") + ("application/vnd.ms-excel" "xls" "xlb" "xlt") + ("application/vnd.ms-pki.seccat" "cat") + ("application/vnd.ms-pki.stl" "stl") + ("application/vnd.ms-powerpoint" "ppt" "pps") + ("application/vnd.oasis.opendocument.chart" "odc") + ("application/vnd.oasis.opendocument.database" "odb") + ("application/vnd.oasis.opendocument.formula" "odf") + ("application/vnd.oasis.opendocument.graphics" "odg") + ("application/vnd.oasis.opendocument.graphics-template" "otg") + ("application/vnd.oasis.opendocument.image" "odi") + ("application/vnd.oasis.opendocument.presentation" "odp") + ("application/vnd.oasis.opendocument.presentation-template" "otp") + ("application/vnd.oasis.opendocument.spreadsheet" "ods") + ("application/vnd.oasis.opendocument.spreadsheet-template" "ots") + ("application/vnd.oasis.opendocument.text" "odt") + ("application/vnd.oasis.opendocument.text-master" "odm") + ("application/vnd.oasis.opendocument.text-template" "ott") + ("application/vnd.oasis.opendocument.text-web" "oth") + ("application/vnd.rim.cod" "cod") + ("application/vnd.smaf" "mmf") + ("application/vnd.stardivision.calc" "sdc") + ("application/vnd.stardivision.draw" "sda") + ("application/vnd.stardivision.impress" "sdd" "sdp") + ("application/vnd.stardivision.math" "smf") + ("application/vnd.stardivision.writer" "sdw" "vor") + ("application/vnd.stardivision.writer-global" "sgl") + ("application/vnd.sun.xml.calc" "sxc") + ("application/vnd.sun.xml.calc.template" "stc") + ("application/vnd.sun.xml.draw" "sxd") + ("application/vnd.sun.xml.draw.template" "std") + ("application/vnd.sun.xml.impress" "sxi") + ("application/vnd.sun.xml.impress.template" "sti") + ("application/vnd.sun.xml.math" "sxm") + ("application/vnd.sun.xml.writer" "sxw") + ("application/vnd.sun.xml.writer.global" "sxg") + ("application/vnd.sun.xml.writer.template" "stw") + ("application/vnd.symbian.install" "sis") + ("application/vnd.visio" "vsd") + ("application/vnd.wap.wbxml" "wbxml") + ("application/vnd.wap.wmlc" "wmlc") + ("application/vnd.wap.wmlscriptc" "wmlsc") + ("application/x-123" "wk") + ("application/x-abiword" "abw") + ("application/x-apple-diskimage" "dmg") + ("application/x-bcpio" "bcpio") + ("application/x-bittorrent" "torrent") + ("application/x-cdf" "cdf") + ("application/x-cdlink" "vcd") + ("application/x-chess-pgn" "pgn") + ("application/x-cpio" "cpio") + ("application/x-csh" "csh") + ("application/x-debian-package" "deb" "udeb") + ("application/x-director" "dcr" "dir" "dxr") + ("application/x-dms" "dms") + ("application/x-doom" "wad") + ("application/x-dvi" "dvi") + ("application/x-flac" "flac") + ("application/x-font" "pfa" "pfb" "gsf" "pcf") + ("application/x-freemind" "mm") + ("application/x-futuresplash" "spl") + ("application/x-gnumeric" "gnumeric") + ("application/x-go-sgf" "sgf") + ("application/x-graphing-calculator" "gcf") + ("application/x-gtar" "gtar" "tgz" "taz") + ("application/x-hdf" "hdf") + ("application/x-httpd-php" "phtml" "pht" "php") + ("application/x-httpd-php-source" "phps") + ("application/x-httpd-php3" "php3") + ("application/x-httpd-php3-preprocessed" "php3p") + ("application/x-httpd-php4" "php4") + ("application/x-ica" "ica") + ("application/x-internet-signup" "ins" "isp") + ("application/x-iphone" "iii") + ("application/x-iso9660-image" "iso") + ("application/x-java-jnlp-file" "jnlp") + ("application/x-javascript" "js") + ("application/x-jmol" "jmz") + ("application/x-kchart" "chrt") + ("application/x-killustrator" "kil") + ("application/x-koan" "skp" "skd" "skt" "skm") + ("application/x-kpresenter" "kpr" "kpt") + ("application/x-kspread" "ksp") + ("application/x-kword" "kwd" "kwt") + ("application/x-latex" "latex") + ("application/x-lha" "lha") + ("application/x-lzh" "lzh") + ("application/x-lzx" "lzx") + ("application/x-maker" "frm" "maker" "frame" "fm" "fb" "book" "fbdoc") + ("application/x-mif" "mif") + ("application/x-ms-wmd" "wmd") + ("application/x-ms-wmz" "wmz") + ("application/x-msdos-program" "com" "exe" "bat" "dll") + ("application/x-msi" "msi") + ("application/x-netcdf" "nc") + ("application/x-ns-proxy-autoconfig" "pac") + ("application/x-nwc" "nwc") + ("application/x-object" "o") + ("application/x-oz-application" "oza") + ("application/x-pkcs7-certreqresp" "p7r") + ("application/x-pkcs7-crl" "crl") + ("application/x-python-code" "pyc" "pyo") + ("application/x-quicktimeplayer" "qtl") + ("application/x-redhat-package-manager" "rpm") + ("application/x-sh" "sh") + ("application/x-shar" "shar") + ("application/x-shockwave-flash" "swf" "swfl") + ("application/x-stuffit" "sit") + ("application/x-sv4cpio" "sv4cpio") + ("application/x-sv4crc" "sv4crc") + ("application/x-tar" "tar") + ("application/x-tcl" "tcl") + ("application/x-tex-gf" "gf") + ("application/x-tex-pk" "pk") + ("application/x-texinfo" "texinfo" "texi") + ("application/x-trash" "~%" "" "bak" "old" "sik") + ("application/x-troff" "tt" "r" "roff") + ("application/x-troff-man" "man") + ("application/x-troff-me" "me") + ("application/x-troff-ms" "ms") + ("application/x-ustar" "ustar") + ("application/x-wais-source" "src") + ("application/x-wingz" "wz") + ("application/x-x509-ca-cert" "crt") + ("application/x-xcf" "xcf") + ("application/x-xfig" "fig") + ("application/x-xpinstall" "xpi") + ("audio/basic" "au" "snd") + ("audio/midi" "mid" "midi" "kar") + ("audio/mpeg" "mpga" "mpega" "mp2" "mp3" "m4a") + ("audio/mpegurl" "m3u") + ("audio/prs.sid" "sid") + ("audio/x-aiff" "aif" "aiff" "aifc") + ("audio/x-gsm" "gsm") + ("audio/x-mpegurl" "m3u") + ("audio/x-ms-wma" "wma") + ("audio/x-ms-wax" "wax") + ("audio/x-pn-realaudio" "ra" "rm" "ram") + ("audio/x-realaudio" "ra") + ("audio/x-scpls" "pls") + ("audio/x-sd2" "sd2") + ("audio/x-wav" "wav") + ("chemical/x-alchemy" "alc") + ("chemical/x-cache" "cac" "cache") + ("chemical/x-cache-csf" "csf") + ("chemical/x-cactvs-binary" "cbin" "cascii" "ctab") + ("chemical/x-cdx" "cdx") + ("chemical/x-cerius" "cer") + ("chemical/x-chem3d" "c3d") + ("chemical/x-chemdraw" "chm") + ("chemical/x-cif" "cif") + ("chemical/x-cmdf" "cmdf") + ("chemical/x-cml" "cml") + ("chemical/x-compass" "cpa") + ("chemical/x-crossfire" "bsd") + ("chemical/x-csml" "csml" "csm") + ("chemical/x-ctx" "ctx") + ("chemical/x-cxf" "cxf" "cef") + ("chemical/x-embl-dl-nucleotide" "emb" "embl") + ("chemical/x-galactic-spc" "spc") + ("chemical/x-gamess-input" "inp" "gam" "gamin") + ("chemical/x-gaussian-checkpoint" "fch" "fchk") + ("chemical/x-gaussian-cube" "cub") + ("chemical/x-gaussian-input" "gau" "gjc" "gjf") + ("chemical/x-gaussian-log" "gal") + ("chemical/x-gcg8-sequence" "gcg") + ("chemical/x-genbank" "gen") + ("chemical/x-hin" "hin") + ("chemical/x-isostar" "istr" "ist") + ("chemical/x-jcamp-dx" "jdx" "dx") + ("chemical/x-kinemage" "kin") + ("chemical/x-macmolecule" "mcm") + ("chemical/x-macromodel-input" "mmd" "mmod") + ("chemical/x-mdl-molfile" "mol") + ("chemical/x-mdl-rdfile" "rd") + ("chemical/x-mdl-rxnfile" "rxn") + ("chemical/x-mdl-sdfile" "sd" "sdf") + ("chemical/x-mdl-tgf" "tgf") + ("chemical/x-mmcif" "mcif") + ("chemical/x-mol2" "mol2") + ("chemical/x-molconn-Z" "b") + ("chemical/x-mopac-graph" "gpt") + ("chemical/x-mopac-input" "mop" "mopcrt" "mpc" "dat" "zmt") + ("chemical/x-mopac-out" "moo") + ("chemical/x-mopac-vib" "mvb") + ("chemical/x-ncbi-asn1" "asn") + ("chemical/x-ncbi-asn1-ascii" "prt" "ent") + ("chemical/x-ncbi-asn1-binary" "val" "aso") + ("chemical/x-ncbi-asn1-spec" "asn") + ("chemical/x-pdb" "pdb" "ent") + ("chemical/x-rosdal" "ros") + ("chemical/x-swissprot" "sw") + ("chemical/x-vamas-iso14976" "vms") + ("chemical/x-vmd" "vmd") + ("chemical/x-xtel" "xtel") + ("chemical/x-xyz" "xyz") + ("image/gif" "gif") + ("image/ief" "ief") + ("image/jpeg" "jpeg" "jpg" "jpe") + ("image/pcx" "pcx") + ("image/png" "png") + ("image/svg+xml" "svg" "svgz") + ("image/tiff" "tiff" "tif") + ("image/vnd.djvu" "djvu" "djv") + ("image/vnd.wap.wbmp" "wbmp") + ("image/x-cmu-raster" "ras") + ("image/x-coreldraw" "cdr") + ("image/x-coreldrawpattern" "pat") + ("image/x-coreldrawtemplate" "cdt") + ("image/x-corelphotopaint" "cpt") + ("image/x-icon" "ico") + ("image/x-jg" "art") + ("image/x-jng" "jng") + ("image/x-ms-bmp" "bmp") + ("image/x-photoshop" "psd") + ("image/x-portable-anymap" "pnm") + ("image/x-portable-bitmap" "pbm") + ("image/x-portable-graymap" "pgm") + ("image/x-portable-pixmap" "ppm") + ("image/x-rgb" "rgb") + ("image/x-xbitmap" "xbm") + ("image/x-xpixmap" "xpm") + ("image/x-xwindowdump" "xwd") + ("model/iges" "igs" "iges") + ("model/mesh" "msh" "mesh" "silo") + ("model/vrml" "wrl" "vrml") + ("text/calendar" "ics" "icz") + ("text/comma-separated-values" "csv") + ("text/css" "css") + ("text/h323" "323") + ("text/html" "html" "htm" "shtml") + ("text/iuls" "uls") + ("text/mathml" "mml") + ("text/plain" "asc" "txt" "text" "diff" "pot") + ("text/richtext" "rtx") + ("text/rtf" "rtf") + ("text/scriptlet" "sct" "wsc") + ("text/texmacs" "tm" "ts") + ("text/tab-separated-values" "tsv") + ("text/vnd.sun.j2me.app-descriptor" "jad") + ("text/vnd.wap.wml" "wml") + ("text/vnd.wap.wmlscript" "wmls") + ("text/x-bibtex" "bib") + ("text/x-boo" "boo") + ("text/x-c++hdr" "h++" "hpp" "hxx" "hh") + ("text/x-c++src" "c++" "cpp" "cxx" "cc") + ("text/x-chdr" "h") + ("text/x-component" "htc") + ("text/x-csh" "csh") + ("text/x-csrc" "c") + ("text/x-dsrc" "d") + ("text/x-haskell" "hs") + ("text/x-java" "java") + ("text/x-literate-haskell" "lhs") + ("text/x-moc" "moc") + ("text/x-pascal" "pp" "as") + ("text/x-pcs-gcd" "gcd") + ("text/x-perl" "pl" "pm") + ("text/x-python" "py") + ("text/x-setext" "etx") + ("text/x-sh" "sh") + ("text/x-tcl" "tcl" "tk") + ("text/x-tex" "tex" "ltx" "sty" "cls") + ("text/x-vcalendar" "vcs") + ("text/x-vcard" "vcf") + ("video/dl" "dl") + ("video/dv" "dif" "dv") + ("video/fli" "fli") + ("video/gl" "gl") + ("video/mpeg" "mpeg" "mpg" "mpe") + ("video/mp4" "mp4") + ("video/quicktime" "qt" "mov") + ("video/vnd.mpegurl" "mxu") + ("video/x-la-asf" "lsf" "lsx") + ("video/x-mng" "mng") + ("video/x-ms-asf" "asf" "asx") + ("video/x-ms-wm" "wm") + ("video/x-ms-wmv" "wmv") + ("video/x-ms-wmx" "wmx") + ("video/x-ms-wvx" "wvx") + ("video/x-msvideo" "avi") + ("video/x-sgi-movie" "movie") + ("x-conference/x-cooltalk" "ice") + ("x-world/x-vrml" "vrm" "vrml" "wrl")) + "An alist where the cars are MIME types and the cdrs are list +of file suffixes for the corresponding type.") + +(defparameter *mime-type-hash* + (let ((hash (make-hash-table :test #'equalp))) + (loop for (type . suffixes) in *mime-type-list* do + (loop for suffix in suffixes do + (setf (gethash suffix hash) type))) + hash) + "A hash table which maps file suffixes to MIME types.") + +(defun mime-type (pathspec) + "Given a pathname designator PATHSPEC returns the MIME type +\(as a string) corresponding to the suffix of the file denoted by +PATHSPEC \(or NIL)." + (gethash (pathname-type pathspec) *mime-type-hash*)) \ No newline at end of file Added: branches/trunk-reorg/thirdparty/hunchentoot-0.15.0/misc.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/hunchentoot-0.15.0/misc.lisp Thu Feb 7 03:16:29 2008 @@ -0,0 +1,276 @@ +;;; -*- Mode: LISP; Syntax: COMMON-LISP; Package: HUNCHENTOOT; Base: 10 -*- +;;; $Header: /usr/local/cvsrep/hunchentoot/misc.lisp,v 1.13 2007/12/29 17:35:01 edi Exp $ + +;;; Copyright (c) 2004-2007, Dr. Edmund Weitz. All rights reserved. + +;;; Redistribution and use in source and binary forms, with or without +;;; modification, are permitted provided that the following conditions +;;; are met: + +;;; * Redistributions of source code must retain the above copyright +;;; notice, this list of conditions and the following disclaimer. + +;;; * Redistributions in binary form must reproduce the above +;;; copyright notice, this list of conditions and the following +;;; disclaimer in the documentation and/or other materials +;;; provided with the distribution. + +;;; THIS SOFTWARE IS PROVIDED BY THE AUTHOR 'AS IS' AND ANY EXPRESSED +;;; OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +;;; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +;;; ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +;;; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +;;; DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +;;; GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +;;; INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +;;; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +;;; NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +;;; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +(in-package :hunchentoot) + +(let ((scanner-hash (make-hash-table :test #'equal))) + (defun scanner-for-get-param (param-name) + "Returns a CL-PPCRE scanner which matches a GET parameter in a +URL. Scanners are memoized in SCANNER-HASH once they are created." + (or (gethash param-name scanner-hash) + (setf (gethash param-name scanner-hash) + (create-scanner + `(:alternation + ;; session=value at end of URL + (:sequence + (:char-class #\? #\&) + ,param-name + #\= + (:greedy-repetition 0 nil (:inverted-char-class #\&)) + :end-anchor) + ;; session=value with other parameters following + (:sequence + (:register (:char-class #\? #\&)) + ,param-name + #\= + (:greedy-repetition 0 nil (:inverted-char-class #\&)) + #\&)))))) + (defun add-cookie-value-to-url (url &key (cookie-name *session-cookie-name*) + (value (session-cookie-value)) + (replace-ampersands-p t)) + "Removes all GET parameters named COOKIE-NAME from URL and then +adds a new GET parameter with the name COOKIE-NAME and the value +VALUE. If REPLACE-AMPERSANDS-P is true all literal ampersands in URL +are replaced with '&'. The resulting URL is returned." + (unless url + ;; see URL-REWRITE:*URL-REWRITE-FILL-TAGS* + (setq url (request-uri *request*))) + (setq url (regex-replace-all (scanner-for-get-param cookie-name) url "\\1")) + (when value + (setq url (format nil "~A~:[?~;&~]~A=~A" + url + (find #\? url) + cookie-name + (url-encode value)))) + (when replace-ampersands-p + (setq url (regex-replace-all "&" url "&"))) + url)) + +(defun maybe-rewrite-urls-for-session (html &key (cookie-name *session-cookie-name*) + (value (session-cookie-value))) + "Rewrites the HTML page HTML such that the name/value pair +COOKIE-NAME/COOKIE-VALUE is inserted if the client hasn't sent a +cookie of the same name but only if *REWRITE-FOR-SESSION-URLS* is +true. See the docs for URL-REWRITE:REWRITE-URLS." + (cond ((or (not *rewrite-for-session-urls*) + (null value) + (cookie-in cookie-name)) + html) + (t + (with-input-from-string (*standard-input* html) + (with-output-to-string (*standard-output*) + (url-rewrite:rewrite-urls + (lambda (url) + (add-cookie-value-to-url url + :cookie-name cookie-name + :value value)))))))) + +(defmethod dispatch-request (dispatch-table) + "Dispatches *REQUEST* based upon rules in the DISPATCH-TABLE. +This method provides the default Hunchentoot behavior." + (loop for dispatcher in dispatch-table + for action = (funcall dispatcher *request*) + when action return (funcall action) + finally (setf (return-code *reply*) +http-not-found+))) + +(defun default-dispatcher (request) + "Default dispatch function which handles every request with the +function stored in *DEFAULT-HANDLER*." + (declare (ignore request)) + *default-handler*) + +(defun default-handler () + "The handler that is supposed to serve the request if no other +handler is called." + (log-message :info "Default handler called for script ~A" (script-name)) + (format nil "Hunchentoot

Hunchentoot Default Page

This the Hunchentoot default page. You're most likely seeing it because the server administrator hasn't set up a custom default page yet.

Hunchentoot is a web server written in Common Lisp. More info about Hunchentoot can be found at http://weitz.de/hunchentoot/.


~A

" + (address-string))) + +(defun create-prefix-dispatcher (prefix page-function) + "Creates a dispatch function which will dispatch to the +function denoted by PAGE-FUNCTION if the file name of the current +request starts with the string PREFIX." + (lambda (request) + (let ((mismatch (mismatch (script-name request) prefix + :test #'char=))) + (and (or (null mismatch) + (>= mismatch (length prefix))) + page-function)))) + +(defun create-regex-dispatcher (regex page-function) + "Creates a dispatch function which will dispatch to the +function denoted by PAGE-FUNCTION if the file name of the current +request matches the CL-PPCRE regular expression REGEX." + (let ((scanner (create-scanner regex))) + (lambda (request) + (and (scan scanner (script-name request)) + page-function)))) + +(defun handle-static-file (path &optional content-type) + "A function which acts like a Hunchentoot handler for the file +denoted by PATH. Send a content type header corresponding to +CONTENT-TYPE or \(if that is NIL) tries to determine the content +type via the file's suffix." + (unless (or (pathname-name path) + (pathname-type path)) + ;; not a file + (setf (return-code) +http-bad-request+) + (throw 'handler-done nil)) + (unless (probe-file path) + ;; does not exist + (setf (return-code) +http-not-found+) + (throw 'handler-done nil)) + (let ((time (or (file-write-date path) (get-universal-time)))) + (setf (content-type) (or content-type + (mime-type path) + "application/octet-stream")) + (handle-if-modified-since time) + (with-open-file (file path + :direction :input + :element-type 'octet + :if-does-not-exist nil) + (setf (header-out "Last-Modified") (rfc-1123-date time) + (content-length) (file-length file)) + (let ((out (send-headers))) + #+:clisp + (setf (flexi-stream-element-type *hunchentoot-stream*) 'octet) + (loop with buf = (make-array +buffer-length+ :element-type 'octet) + for pos = (read-sequence buf file) + until (zerop pos) + do (write-sequence buf out :end pos) + (finish-output out)))))) + +(defun create-static-file-dispatcher-and-handler (uri path &optional content-type) + "Creates and returns a dispatch function which will dispatch to a +handler function which emits the file denoted by the pathname +designator PATH with content type CONTENT-TYPE if the SCRIPT-NAME of +the request matches the string URI. If CONTENT-TYPE is NIL tries to +determine the content type via the file's suffix." + ;; the dispatcher + (lambda (request) + (when (equal (script-name request) uri) + ;; the handler + (lambda () + (handle-static-file path content-type))))) + +(defun enough-url (url url-prefix) + "Returns the relative portion of URL relative to URL-PREFIX, similar +to what ENOUGH-NAMESTRING does for pathnames." + (subseq url (mismatch url url-prefix))) + +(defun create-folder-dispatcher-and-handler (uri-prefix base-path &optional content-type) + "Creates and returns a dispatch function which will dispatch to a +handler function which emits the file relative to BASE-PATH that is +denoted by the URI of the request relative to URI-PREFIX. URI-PREFIX +must be a string ending with a slash, BASE-PATH must be a pathname +designator for an existing directory. If CONTENT-TYPE is not NIL, +it'll be the content type used for all files in the folder." + (unless (and (stringp uri-prefix) + (plusp (length uri-prefix)) + (char= (char uri-prefix (1- (length uri-prefix))) #\/)) + (error "~S must be string ending with a slash." uri-prefix)) + (when (or (pathname-name base-path) + (pathname-type base-path)) + (error "~S is supposed to denote a directory." base-path)) + (flet ((handler () + (let* ((script-name (url-decode (script-name))) + (script-path (enough-url (regex-replace-all "\\\\" script-name "/") + uri-prefix)) + (script-path-directory (pathname-directory script-path))) + (unless (or (stringp script-path-directory) + (null script-path-directory) + (and (listp script-path-directory) + (eq (first script-path-directory) :relative) + (loop for component in (rest script-path-directory) + always (stringp component)))) + (setf (return-code) +http-forbidden+) + (throw 'handler-done nil)) + (handle-static-file (merge-pathnames script-path base-path) content-type)))) + (create-prefix-dispatcher uri-prefix #'handler))) + +(defun no-cache () + "Adds appropriate headers to completely prevent caching on most browsers." + (setf (header-out "Expires") + "Mon, 26 Jul 1997 05:00:00 GMT" + (header-out "Cache-Control") + "no-store, no-cache, must-revalidate, post-check=0, pre-check=0" + (header-out "Pragma") + "no-cache" + (header-out "Last-Modified") + (rfc-1123-date)) + (values)) + +(defun ssl-p () + "Whether the current connection to the client is secure." + (cond ((server-mod-lisp-p *server*) (ssl-session-id *request*)) + (t #-:hunchentoot-no-ssl (server-ssl-certificate-file *server*) + #+:hunchentoot-no-ssl nil))) + +(defun redirect (target &key (host (host *request*) host-provided-p) + port + (protocol (if (ssl-p) :https :http)) + (add-session-id (not (or host-provided-p + (starts-with-scheme-p target) + (cookie-in *session-cookie-name*)))) + permanently) + "Redirects the browser to TARGET which should be a string. If +TARGET is a full URL starting with a scheme, HOST, PORT and PROTOCOL +are ignored. Otherwise, TARGET should denote the path part of a URL, +PROTOCOL must be one of the keywords :HTTP or :HTTPS, and the URL to +redirect to will be constructed from HOST, PORT, PROTOCOL, and TARGET. +Adds a session ID if ADD-SESSION-ID is true. If PERMANENTLY is true, +a 301 request is sent to the browser, otherwise a 302." + (let ((url (if (starts-with-scheme-p target) + target + (format nil "~A://~A~@[:~A~]~A" + (ecase protocol + ((:http) "http") + ((:https) "https")) + (if port + (first (ppcre:split ":" (or host ""))) + host) + port target)))) + (when add-session-id + (setq url (add-cookie-value-to-url url :replace-ampersands-p nil))) + (setf (header-out :location) + url + (return-code *reply*) + (if permanently + +http-moved-permanently+ + +http-moved-temporarily+)) + (throw 'handler-done nil))) + +(defun require-authorization (&optional (realm "Hunchentoot")) + "Sends back appropriate headers to require basic HTTP authentication +\(see RFC 2617) for the realm REALM." + (setf (header-out "WWW-Authenticate") + (format nil "Basic realm=\"~A\"" (quote-string realm)) + (return-code *reply*) + +http-authorization-required+) + (throw 'handler-done nil)) Added: branches/trunk-reorg/thirdparty/hunchentoot-0.15.0/packages.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/hunchentoot-0.15.0/packages.lisp Thu Feb 7 03:16:29 2008 @@ -0,0 +1,228 @@ +;;; -*- Mode: LISP; Syntax: COMMON-LISP; Package: CL-USER; Base: 10 -*- +;;; $Header: /usr/local/cvsrep/hunchentoot/packages.lisp,v 1.33 2007/09/18 14:23:23 edi Exp $ + +;;; Copyright (c) 2004-2007, Dr. Edmund Weitz. All rights reserved. + +;;; Redistribution and use in source and binary forms, with or without +;;; modification, are permitted provided that the following conditions +;;; are met: + +;;; * Redistributions of source code must retain the above copyright +;;; notice, this list of conditions and the following disclaimer. + +;;; * Redistributions in binary form must reproduce the above +;;; copyright notice, this list of conditions and the following +;;; disclaimer in the documentation and/or other materials +;;; provided with the distribution. + +;;; THIS SOFTWARE IS PROVIDED BY THE AUTHOR 'AS IS' AND ANY EXPRESSED +;;; OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +;;; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +;;; ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +;;; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +;;; DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +;;; GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +;;; INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +;;; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +;;; NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +;;; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +(in-package :cl-user) + +(defpackage :hunchentoot-mp + (:nicknames :tbnl-mp) + (:use :cl) + (:export :*current-process* + :make-lock + :with-lock + :process-run-function + :process-kill)) + +(defpackage :hunchentoot + (:nicknames :tbnl) + (:use :cl :cl-ppcre :chunga :flexi-streams :url-rewrite :hunchentoot-mp) + (:shadow :assoc + #+:sbcl :defconstant + :handler-case + :ignore-errors + :url-encode) + ;; see ASDF system definition + (:import-from :hunchentoot-asd :*hunchentoot-version*) + #+:lispworks + (:import-from :lw :with-unique-names :when-let) + (:export :*approved-return-codes* + :*catch-errors-p* + :*cleanup-function* + :*cleanup-interval* + :*content-types-for-url-rewrite* + :*default-content-type* + :*default-handler* + :*default-log-level* + :*default-read-timeout* + :*default-write-timeout* + :*dispatch-table* + :*file-upload-hook* + :*handle-http-errors-p* + :*header-stream* + :*http-error-handler* + :*hunchentoot-default-external-format* + :*lisp-errors-log-level* + :*lisp-warnings-log-level* + :*listener* + :*log-lisp-backtraces-p* + :*log-lisp-errors-p* + :*log-lisp-warnings-p* + :*log-prefix* + :*meta-dispatcher* + :*methods-for-post-parameters* + :*reply* + :*request* + :*rewrite-for-session-urls* + :*server* + :*session* + :*session-cookie-name* + :*session-gc-frequency* + :*session-max-time* + :*session-removal-hook* + :*show-access-log-messages* + :*show-lisp-backtraces-p* + :*show-lisp-errors-p* + :*tmp-directory* + :*use-remote-addr-for-sessions* + :*use-user-agent-for-sessions* + :+http-accepted+ + :+http-authorization-required+ + :+http-bad-gateway+ + :+http-bad-request+ + :+http-conflict+ + :+http-continue+ + :+http-created+ + :+http-expectation-failed+ + :+http-failed-dependency+ + :+http-forbidden+ + :+http-gateway-time-out+ + :+http-gone+ + :+http-internal-server-error+ + :+http-length-required+ + :+http-method-not-allowed+ + :+http-moved-permanently+ + :+http-moved-temporarily+ + :+http-multiple-choices+ + :+http-multi-status+ + :+http-no-content+ + :+http-non-authoritative-information+ + :+http-not-acceptable+ + :+http-not-found+ + :+http-not-implemented+ + :+http-not-modified+ + :+http-ok+ + :+http-partial-content+ + :+http-payment-required+ + :+http-precondition-failed+ + :+http-proxy-authentication-required+ + :+http-request-entity-too-large+ + :+http-request-time-out+ + :+http-request-uri-too-large+ + :+http-requested-range-not-satisfiable+ + :+http-reset-content+ + :+http-see-other+ + :+http-service-unavailable+ + :+http-switching-protocols+ + :+http-temporary-redirect+ + :+http-unsupported-media-type+ + :+http-use-proxy+ + :+http-version-not-supported+ + :authorization + :aux-request-value + :content-length + :content-type + :cookie-domain + :cookie-expires + :cookie-http-only + :cookie-in + :cookie-name + :cookie-out + :cookie-path + :cookie-secure + :cookie-value + :cookies-in + :cookies-out + :create-folder-dispatcher-and-handler + :create-prefix-dispatcher + :create-regex-dispatcher + :create-static-file-dispatcher-and-handler + :default-dispatcher + :define-easy-handler + :delete-aux-request-value + :delete-session-value + :dispatch-easy-handlers + :dispatch-request + :do-sessions + :escape-for-html + :get-backtrace + :get-parameter + :get-parameters + :handle-if-modified-since + :handle-static-file + :handler-done + :header-in + :header-out + :headers-in + :headers-out + :host + :http-token-p + :log-file + :log-message + :log-message* + :maybe-invoke-debugger + :mime-type + :mod-lisp-id + :no-cache + :parameter + :post-parameter + :post-parameters + :query-string + :raw-post-data + :real-remote-addr + :reason-phrase + :recompute-request-parameters + :redirect + :referer + :remote-addr + :remote-port + :remove-session + :reply-external-format + :request-method + :request-uri + :require-authorization + :reset-sessions + :return-code + :rfc-1123-date + :script-name + :send-headers + :server-addr + :server-address + :server-dispatch-table + :server-local-port + :server-name + :server-port + :server-protocol + :session-counter + :session-gc + :session-max-time + :session-too-old-p + :session-remote-addr + :session-cookie-value + :session-user-agent + :session-value + :set-cookie + :set-cookie* + :ssl-p + :ssl-session-id + :start-server + :start-session + :stop-server + :url-decode + :url-encode + :user-agent)) + Added: branches/trunk-reorg/thirdparty/hunchentoot-0.15.0/port-acl.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/hunchentoot-0.15.0/port-acl.lisp Thu Feb 7 03:16:29 2008 @@ -0,0 +1,145 @@ +;;; -*- Mode: LISP; Syntax: COMMON-LISP; Package: HUNCHENTOOT; Base: 10 -*- +;;; $Header: /usr/local/cvsrep/hunchentoot/port-acl.lisp,v 1.10 2007/11/03 21:46:18 edi Exp $ + +;;; Copyright (c) 2004-2007, Dr. Edmund Weitz. All rights reserved. + +;;; Redistribution and use in source and binary forms, with or without +;;; modification, are permitted provided that the following conditions +;;; are met: + +;;; * Redistributions of source code must retain the above copyright +;;; notice, this list of conditions and the following disclaimer. + +;;; * Redistributions in binary form must reproduce the above +;;; copyright notice, this list of conditions and the following +;;; disclaimer in the documentation and/or other materials +;;; provided with the distribution. + +;;; THIS SOFTWARE IS PROVIDED BY THE AUTHOR 'AS IS' AND ANY EXPRESSED +;;; OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +;;; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +;;; ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +;;; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +;;; DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +;;; GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +;;; INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +;;; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +;;; NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +;;; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +(in-package :hunchentoot) + +(eval-when (:compile-toplevel :load-toplevel :execute) + #-(and :allegro-version>= (version>= 7 0)) + (error "You need at least version 7.0 of AllegroCL.") + ;; make sure code for sockets and OS interface is loaded + (require :sock) + (require :osi)) + +(defun make-lock (name) + "See AllegroCL documentation for MP:MAKE-PROCESS-LOCK." + (mp:make-process-lock :name name)) + +(defmacro with-lock ((lock) &body body) + "See AllegroCL documentation for MP:WITH-PROCESS-LOCK." + `(mp:with-process-lock (,lock) , at body)) + +(defmacro atomic-incf (place &optional (delta 1)) + "Like INCF but wrapped with SYS:WITHOUT-SCHEDULING so other +threads can't interfer." + `(sys:without-scheduling (incf ,place ,delta))) + +(defmacro with-timeout ((seconds &body timeout-forms) &body body) + "See AllegroCL documentation for SYS:WITH-TIMEOUT." + `(sys:with-timeout (,seconds , at timeout-forms) , at body)) + +(defun process-run-function (name function &rest args) + "See AllegroCL documentation for MP:PROCESS-RUN-FUNCTION." + (apply #'mp:process-run-function name function args)) + +(defun process-kill (process) + "See AllegroCL documentation for MP:PROCESS-KILL." + (mp:process-kill process)) + +(define-symbol-macro *current-process* + mp:*current-process*) + +(defun process-allow-scheduling () + "See AllegroCL documentation for MP:PROCESS-ALLOW-SCHEDULE." + (mp:process-allow-schedule)) + +(defun start-up-server (&key service address process-name announce function &allow-other-keys) + "Tries to \(partly) emulate LispWorks' COMM:START-UP-SERVER. See + +for more info." + (let (done) + (flet ((open-socket-and-accept () + (handler-bind ((error (lambda (condition) + (funcall announce nil condition) + (setq done condition) + (return-from open-socket-and-accept)))) + (let (socket) + (unwind-protect + (progn + (setf socket (socket:make-socket :address-family :internet + :type :hiper + :format :bivalent + :connect :passive + :local-host address + :local-port service + :reuse-address t + :backlog 5)) + (funcall announce socket) + (setq done socket) + (loop (funcall function (socket:accept-connection socket :wait t)))) + (when socket + (cl:ignore-errors (close socket)))))))) + (let ((listener-thread (process-run-function process-name #'open-socket-and-accept))) + (mp:process-wait "Waiting for server to start" (lambda () done)) + (typecase done + (socket:socket listener-thread) + (t (values nil done))))))) + +(defun make-socket-stream (socket read-timeout write-timeout) + "Accepts a socket `handle' SOCKET and creates and returns a +corresponding stream, setting its read and write timeout if +applicable. Returns three other values - the address the request +arrived at, and the address and port of the remote host." + ;; in the case of AllegroCL, SOCKET:ACCEPT-CONNECTION already + ;; returned a stream + (socket:set-socket-options socket :nodelay t) + (socket:socket-control socket + :read-timeout read-timeout + :write-timeout write-timeout) + (values socket + (ignore-errors + (socket:ipaddr-to-dotted (socket:local-host socket))) + (ignore-errors + (socket:ipaddr-to-dotted (socket:remote-host socket))) + (ignore-errors + (socket:remote-port socket)))) + +(defun get-backtrace (error) + "This is the function that is used internally by Hunchentoot to +show or log backtraces. It accepts a condition object ERROR and +returns a string with the corresponding backtrace." + (with-output-to-string (s) + (with-standard-io-syntax + (let ((*print-readably* nil) + (*print-miser-width* 40) + (*print-pretty* t) + (tpl:*zoom-print-circle* t) + (tpl:*zoom-print-level* nil) + (tpl:*zoom-print-length* nil)) + (cl:ignore-errors + (format *terminal-io* "~ +~@~%~%" + error)) + (cl:ignore-errors + (let ((*terminal-io* s) + (*standard-output* s)) + (tpl:do-command "zoom" + :from-read-eval-print-loop nil + :count t + :all t))))))) + Added: branches/trunk-reorg/thirdparty/hunchentoot-0.15.0/port-clisp.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/hunchentoot-0.15.0/port-clisp.lisp Thu Feb 7 03:16:29 2008 @@ -0,0 +1,131 @@ +;;; -*- Mode: LISP; Syntax: COMMON-LISP; Package: HUNCHENTOOT; Base: 10; -*- +;;; $Header: /usr/local/cvsrep/hunchentoot/port-clisp.lisp,v 1.1 2007/12/29 17:35:01 edi Exp $ + +;;; Copyright (c) 2006, Luis Ol?veira . +;;; Copyright (c) 2007, Anton Vodonosov . +;;; Copyright (c) 2007, Dr. Edmund Weitz. +;;; All rights reserved. + +;;; Redistribution and use in source and binary forms, with or without +;;; modification, are permitted provided that the following conditions +;;; are met: + +;;; * Redistributions of source code must retain the above copyright +;;; notice, this list of conditions and the following disclaimer. + +;;; * Redistributions in binary form must reproduce the above +;;; copyright notice, this list of conditions and the following +;;; disclaimer in the documentation and/or other materials +;;; provided with the distribution. + +;;; THIS SOFTWARE IS PROVIDED BY THE AUTHOR 'AS IS' AND ANY EXPRESSED +;;; OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +;;; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +;;; ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +;;; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +;;; DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +;;; GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +;;; INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +;;; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +;;; NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +;;; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +(in-package :hunchentoot) + +(defmacro with-lock ((lock) &body body) + "Executes the BODY. LOCK is ignored because CLISP doesn't support +threads." + (declare (ignore lock)) + `(progn , at body)) + +(defmacro atomic-incf (place &optional (delta 1)) + "Expands to INCF. No special semantics because CLISP doesn't support threads." + `(incf ,place ,delta)) + +(defmacro with-timeout ((seconds &body timeout-forms) &body body) + "Executes the code BODY and returns the results of the last form. +SECONDS and TIMEOUT-FORMS are ignored since CLISP doesn't support +threads." + (declare (ignore seconds timeout-forms)) + `(progn , at body)) + +(defun make-lock (lock) + "CLISP doesn't support threads, so the function just returns its +argument LOCK." + lock) + +(defvar *current-process* "*CURRENT-PROCESS*" + "CLISP doesn't support threads, so this value is just a dummy stub.") + +(defun process-run-function (name function &rest args) + "In a multithreaded environment, this would run FUNCTION in a new +thread, but in CLISP we just apply FUNCTION to ARGS." + (declare (ignore name)) + (apply function args)) + +(defun process-allow-scheduling () + "Does nothing because CLISP doesn't support threads." + ) + +(defun process-kill (process) + "Does nothing because CLISP doesn't support threads." + (declare (ignore process)) + ) + +(defun start-up-server (&key service address process-name announce function &allow-other-keys) + "Tries to \(partly) emulate LispWorks' COMM:START-UP-SERVER. See + +for more info." + (declare (ignore process-name)) + (cl:ignore-errors + (let ((socket (socket:socket-server service :interface address :backlog 5))) + (funcall announce socket) + (unwind-protect + (loop (funcall function + (socket:socket-accept socket + :buffered t + :element-type 'octet))) + (cl:ignore-errors + (socket:socket-server-close socket)))))) + +(defun make-socket-stream (socket read-timeout write-timeout) + "Accepts a socket `handle' HANDLE and creates and returns a +corresponding stream, setting its read and write timeout if +applicable. Returns three other values - the address the request +arrived at, and the address and port of the remote host." + (socket:socket-options socket + :SO-RCVTIMEO read-timeout + :SO-SNDTIMEO write-timeout) + (multiple-value-bind (remote-host remote-port) + (socket:socket-stream-peer socket) + (values socket + (nth-value 1 (socket:socket-stream-local socket)) + remote-host + remote-port))) + +;;; the following code is from swank-clisp.lisp (SLIME): + +(defun format-frame (frame) + "Returns a string describing the call stack frame object FRAME." + (string-trim #(#\Newline #\Space #\Tab) + (with-output-to-string (out) + (sys::describe-frame out frame)))) + +(defun function-frame-p (formatted-frame) + "Determines whether the frame described by FORMATTED-FRAME +is a function frame." + (char= #\< (aref formatted-frame 0))) + +(defun get-backtrace (error) + "This is the function that is used internally by Hunchentoot to +show or log backtraces." + (declare (ignore error)) + (with-output-to-string (stream) + (do ((last nil frame) + (frame (sys::the-frame) (sys::frame-up-1 frame 1))) + ((eq frame last)) + (let ((formatted-frame (format-frame frame))) + (when (function-frame-p formatted-frame) + (write-line (subseq formatted-frame (+ (position #\> formatted-frame) 2) + (position #\Newline formatted-frame)) + stream)))))) Added: branches/trunk-reorg/thirdparty/hunchentoot-0.15.0/port-cmu.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/hunchentoot-0.15.0/port-cmu.lisp Thu Feb 7 03:16:29 2008 @@ -0,0 +1,137 @@ +;;; -*- Mode: LISP; Syntax: COMMON-LISP; Package: HUNCHENTOOT; Base: 10 -*- +;;; $Header: /usr/local/cvsrep/hunchentoot/port-cmu.lisp,v 1.10 2007/12/29 17:35:01 edi Exp $ + +;;; Copyright (c) 2004-2007, Dr. Edmund Weitz. All rights reserved. + +;;; Redistribution and use in source and binary forms, with or without +;;; modification, are permitted provided that the following conditions +;;; are met: + +;;; * Redistributions of source code must retain the above copyright +;;; notice, this list of conditions and the following disclaimer. + +;;; * Redistributions in binary form must reproduce the above +;;; copyright notice, this list of conditions and the following +;;; disclaimer in the documentation and/or other materials +;;; provided with the distribution. + +;;; THIS SOFTWARE IS PROVIDED BY THE AUTHOR 'AS IS' AND ANY EXPRESSED +;;; OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +;;; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +;;; ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +;;; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +;;; DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +;;; GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +;;; INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +;;; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +;;; NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +;;; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +(in-package :hunchentoot) + +#-:mp +(eval-when (:compile-toplevel :load-toplevel :execute) + (error "This library needs a version of CMUCL with MP support.")) + +(defun make-lock (name) + "See CMUCL documentation for MP:MAKE-LOCK." + (mp:make-lock name)) + +(defmacro with-lock ((lock) &body body) + "See CMUCL documentation for MP:WITH-LOCK-HELD." + `(mp:with-lock-held (,lock) , at body)) + +(defmacro atomic-incf (place &optional (delta 1)) + "Like INCF but wrapped with MP:WITHOUT-SCHEDULING so other +threads can't interfer." + `(mp:without-scheduling (incf ,place ,delta))) + +(defmacro with-timeout ((seconds &body timeout-forms) &body body) + "See CMUCL documentation for MP:WITH-TIMEOUT." + `(mp:with-timeout (,seconds , at timeout-forms) , at body)) + +(defun process-run-function (name function &rest args) + "See CMUCL documentation for MP:MAKE-PROCESS." + (mp:make-process (lambda () + (apply function args)) + :name name)) + +(defun process-kill (process) + "See CMUCL documentation for MP:DESTROY-PROCESS." + (mp:destroy-process process)) + +(define-symbol-macro *current-process* + mp:*current-process*) + +(defun process-allow-scheduling () + "See CMUCL documentation for MP:PROCESS-YIELD." + (mp:process-yield)) + +(defun start-up-server (&key service address process-name announce function &allow-other-keys) + "Tries to \(partly) emulate LispWorks' COMM:START-UP-SERVER. See + +for more info." + (let (done) + (flet ((open-socket-and-accept () + (handler-bind ((error (lambda (condition) + (funcall announce nil condition) + (setq done condition) + (return-from open-socket-and-accept)))) + (let (socket) + (unwind-protect + (progn + (setf socket (ext:create-inet-listener service :stream + :reuse-address t + :backlog 5 + :host (or address 0))) + (funcall announce socket) + (setq done socket) + (loop (funcall function (ext:accept-tcp-connection socket)))) + (when socket + (cl:ignore-errors + (ext:close-socket socket)))))))) + (let ((listener-thread (process-run-function process-name #'open-socket-and-accept))) + (mp:process-wait "Waiting for server to start" (lambda () done)) + (typecase done + (condition (values nil done)) + (t listener-thread)))))) + +(defun format-address (address) + "Converts an integer in network byte order denoting an IP +address into the corresponding string representation." + (format nil "~A.~A.~A.~A" + (ash address -24) + (logand (ash address -16) #xFF) + (logand (ash address -8) #xFF) + (logand address #xFF))) + +(defun make-socket-stream (handle read-timeout write-timeout) + "Accepts a socket `handle' HANDLE and creates and returns a +corresponding stream, setting its read and write timeout if +applicable. Returns three other values - the address the request +arrived at, and the address and port of the remote host." + (declare (ignore write-timeout)) + (let ((local-host (ext:get-socket-host-and-port handle))) + (multiple-value-bind (remote-host remote-port) + (ext:get-peer-host-and-port handle) + (values (sys:make-fd-stream handle + :input t :output t + :element-type 'octet + :auto-close t + :buffering :full + :timeout read-timeout + :name (format nil "~A:~A" (format-address remote-host) remote-port)) + (format-address local-host) + (format-address remote-host) + remote-port)))) + +(defun get-backtrace (error) + "This is the function that is used internally by Hunchentoot to +show or log backtraces. It accepts a condition object ERROR and +returns a string with the corresponding backtrace." + (declare (ignore error)) + (with-output-to-string (s) + (let ((debug:*debug-print-level* nil) + (debug:*debug-print-length* nil)) + (debug:backtrace most-positive-fixnum s)))) + Added: branches/trunk-reorg/thirdparty/hunchentoot-0.15.0/port-lw.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/hunchentoot-0.15.0/port-lw.lisp Thu Feb 7 03:16:29 2008 @@ -0,0 +1,173 @@ +;;; -*- Mode: LISP; Syntax: COMMON-LISP; Package: HUNCHENTOOT; Base: 10 -*- +;;; $Header: /usr/local/cvsrep/hunchentoot/port-lw.lisp,v 1.12 2007/12/29 17:35:01 edi Exp $ + +;;; Copyright (c) 2004-2007, Dr. Edmund Weitz. All rights reserved. + +;;; Redistribution and use in source and binary forms, with or without +;;; modification, are permitted provided that the following conditions +;;; are met: + +;;; * Redistributions of source code must retain the above copyright +;;; notice, this list of conditions and the following disclaimer. + +;;; * Redistributions in binary form must reproduce the above +;;; copyright notice, this list of conditions and the following +;;; disclaimer in the documentation and/or other materials +;;; provided with the distribution. + +;;; THIS SOFTWARE IS PROVIDED BY THE AUTHOR 'AS IS' AND ANY EXPRESSED +;;; OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +;;; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +;;; ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +;;; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +;;; DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +;;; GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +;;; INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +;;; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +;;; NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +;;; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +(in-package :hunchentoot) + +#+(and :lispworks4.4 (or :win32 :linux)) +(let ((id :system-cons-free-chain)) + (unless (scm::patch-id-loaded-p id) + (error "You need a patch to improve the performance of this code. Request patch ~S for ~A for ~A from lisp-support at lispworks.com using the Report Bug command." + id (lisp-implementation-type) + #+:win32 "Windows" + #+:linux "Linux"))) + +(eval-when (:compile-toplevel :load-toplevel :execute) + ;; make sure socket code is loaded + (require "comm")) + +(defun make-lock (name) + "See LispWorks documentation for MP:MAKE-LOCK." + (mp:make-lock :name name)) + +(defmacro with-lock ((lock) &body body) + "See LispWorks documentation for MP:WITH-LOCK." + `(mp:with-lock (,lock) , at body)) + +(defmacro atomic-incf (place &optional (delta 1)) + "Like INCF but wrapped with MP:WITHOUT-PREEMPTION so other +threads can't interfer." + `(mp:without-preemption (incf ,place ,delta))) + +(defun invoke-with-timeout (duration body-fn timeout-fn) + "Executes the function \(with no arguments) BODY-FN and returns +its results but stops execution after DURATION seconds and then +instead calls TIMEOUT-FN and returns its values." + ;; from Portable AllegroServe + (block timeout + (let* ((process mp:*current-process*) + (unsheduledp nil) + (timer (mp:make-timer + #'(lambda () + (mp:process-interrupt process + #'(lambda () + (unless unsheduledp + (return-from timeout + (funcall timeout-fn))))))))) + (mp:schedule-timer-relative timer duration) + (unwind-protect + (funcall body-fn) + (mp:without-interrupts + (mp:unschedule-timer timer) + (setf unsheduledp t)))))) + +(defmacro with-timeout ((seconds &body timeout-forms) &body body) + "Executes the code BODY and returns the results of the last +form but stops execution after SECONDS seconds and then instead +executes the code in TIMEOUT-FORMS." + ;; from Portable AllegroServe + `(invoke-with-timeout ,seconds + #'(lambda () + , at body) + #'(lambda () + , at timeout-forms))) + +(defun process-run-function (name function &rest args) + "See LispWorks documentation for MP:PROCESS-RUN-FUNCTION." + (apply #'mp:process-run-function name nil function args)) + +(defun process-kill (process) + "See LispWorks documentation for MP:PROCESS-KILL." + (mp:process-kill process)) + +(define-symbol-macro *current-process* + mp:*current-process*) + +(defun process-allow-scheduling () + "See LispWorks documentation for MP:PROCESS-ALLOW-SCHEDULING." + (mp:process-allow-scheduling)) + +(defun start-up-server (&rest args) + "See LispWorks documentation for COMM:START-UP-SERVER." + (apply #'comm:start-up-server args)) + +(defun make-socket-stream (socket read-timeout write-timeout) + "Accepts a socket `handle' SOCKET and creates and returns a +corresponding stream, setting its read and write timeout if +applicable. Returns three other values - the address the request +arrived at, and the address and port of the remote host." + #-:lispworks5 (declare (ignore write-timeout)) + (let ((local-host (comm:get-socket-address socket))) + (multiple-value-bind (remote-host remote-port) + (comm:get-socket-peer-address socket) + (values (make-instance 'comm:socket-stream + :socket socket + :direction :io + :read-timeout read-timeout + #+:lispworks5 #+:lispworks5 + :write-timeout write-timeout + :element-type 'octet) + (ignore-errors + (comm:ip-address-string local-host)) + (ignore-errors + (comm:ip-address-string remote-host)) + remote-port)))) + +#-:hunchentoot-no-ssl +(defun make-ssl-server-stream (socket-stream &key certificate-file privatekey-file privatekey-password) + "Given the server socket stream SOCKET-STREAM attaches SSL to the +stream using the certificate file CERTIFICATE-FILE and the private key +file PRIVATEKEY-FILE. Both of these values must be namestrings +denoting the location of the files. If PRIVATEKEY-PASSWORD is not NIL +then it should be the password for the private key file \(if +necessary)." + (flet ((ctx-configure-callback (ctx) + (when privatekey-password + (comm:set-ssl-ctx-password-callback ctx :password privatekey-password)) + (comm:ssl-ctx-use-certificate-file ctx + certificate-file + comm:ssl_filetype_pem) + (comm:ssl-ctx-use-privatekey-file ctx + privatekey-file + comm:ssl_filetype_pem))) + (comm:attach-ssl socket-stream + :ctx-configure-callback #'ctx-configure-callback))) + +(defun get-backtrace (error) + "This is the function that is used internally by Hunchentoot to +show or log backtraces. It accepts a condition object ERROR and +returns a string with the corresponding backtrace." + (declare (ignore error)) + (with-output-to-string (s) + (let ((dbg::*debugger-stack* (dbg::grab-stack nil :how-many most-positive-fixnum)) + (*debug-io* s) + (dbg:*debug-print-level* nil) + (dbg:*debug-print-length* nil)) + (dbg:bug-backtrace nil)))) + +;; some help for the IDE +(dspec:define-dspec-alias defvar-unbound (name) + `(defparameter ,name)) + +(dspec:define-dspec-alias def-http-return-code (name) + `(defconstant ,name)) + +(editor:setup-indent "defvar-unbound" 1 2 4) + +(editor:setup-indent "def-http-return-code" 1 2 4) + Added: branches/trunk-reorg/thirdparty/hunchentoot-0.15.0/port-mcl.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/hunchentoot-0.15.0/port-mcl.lisp Thu Feb 7 03:16:29 2008 @@ -0,0 +1,136 @@ +;;; -*- Mode: LISP; Syntax: COMMON-LISP; Package: HUNCHENTOOT; Base: 10 -*- +;;; $Header: /usr/local/cvsrep/hunchentoot/port-mcl.lisp,v 1.9 2007/11/03 21:46:19 edi Exp $ + +;;; Copyright (c) 2004-2007, Dr. Edmund Weitz. All rights reserved. + +;;; Redistribution and use in source and binary forms, with or without +;;; modification, are permitted provided that the following conditions +;;; are met: + +;;; * Redistributions of source code must retain the above copyright +;;; notice, this list of conditions and the following disclaimer. + +;;; * Redistributions in binary form must reproduce the above +;;; copyright notice, this list of conditions and the following +;;; disclaimer in the documentation and/or other materials +;;; provided with the distribution. + +;;; THIS SOFTWARE IS PROVIDED BY THE AUTHOR 'AS IS' AND ANY EXPRESSED +;;; OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +;;; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +;;; ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +;;; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +;;; DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +;;; GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +;;; INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +;;; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +;;; NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +;;; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +(in-package :hunchentoot) + +(defun make-lock (name) + "See OpenMCL documentation for CCL:MAKE-LOCK." + (ccl:make-lock name)) + +(defmacro with-lock ((lock) &body body) + "See OpenMCL documentation for CCL:WITH-LOCK-GRABBED." + `(ccl:with-lock-grabbed (,lock) , at body)) + +(defmacro atomic-incf (place &optional (delta 1)) + "Like INCF, but other threads can't interfer." + `(ccl::atomic-incf-decf ,place ,delta)) + +(defun invoke-with-timeout (seconds bodyfn timeoutfn) + "Executes the function \(with no arguments) BODY-FN and returns +its results but stops execution after DURATION seconds and then +instead calls TIMEOUT-FN and returns its values." + ;; from Portable AllegroServe + (block timeout + (let* ((timer (ccl::make-timer-request seconds + #'(lambda () + (return-from timeout (funcall timeoutfn)))))) + (ccl::enqueue-timer-request timer) + (unwind-protect (funcall bodyfn) + (ccl::dequeue-timer-request timer))))) + +(defmacro with-timeout ((seconds &body timeout-forms) &body body) + "Executes the code BODY and returns the results of the last +form but stops execution after SECONDS seconds and then instead +executes the code in TIMEOUT-FORMS." + ;; from Portable AllegroServe + `(invoke-with-timeout ,seconds + #'(lambda () , at body) + #'(lambda () , at timeout-forms))) + +(defun process-run-function (name function &rest args) + "See OpenMCL documentation for CCL:PROCESS-RUN-FUNCTION." + (apply #'ccl:process-run-function name function args)) + +(defun process-kill (process) + "See OpenMCL documentation for CCL:PROCESS-KILL." + (ccl:process-kill process)) + +(define-symbol-macro *current-process* + ccl:*current-process*) + +(defun process-allow-scheduling () + "See OpenMCL documentation for CCL:PROCESS-ALLOW-SCHEDULE" + (ccl:process-allow-schedule)) + +(defun start-up-server (&key service address process-name announce function &allow-other-keys) + "Tries to \(partly) emulate LispWorks' COMM:START-UP-SERVER. See + +for more info." + (let (done) + (flet ((open-socket-and-accept () + (handler-bind ((error (lambda (condition) + (funcall announce nil condition) + (setq done condition) + (return-from open-socket-and-accept)))) + (let (socket) + (unwind-protect + (progn + (setf socket (ccl:make-socket :address-family :internet + :type :stream + :connect :passive + :local-host address + :local-port service + :reuse-address t + :backlog 5)) + (funcall announce socket) + (setq done socket) + (loop (funcall function (ccl:accept-connection socket :wait t)))) + (when socket + (cl:ignore-errors + (close socket)))))))) + (let ((listener-thread (process-run-function process-name #'open-socket-and-accept))) + (ccl:process-wait "Waiting for server to start" (lambda () done)) + (typecase done + (condition (values nil done)) + (t listener-thread)))))) + +(defun make-socket-stream (socket read-timeout write-timeout) + "Accepts a socket `handle' SOCKET and creates and returns a +corresponding stream, setting its read and write timeout if +applicable. Returns three other values - the address the request +arrived at, and the address and port of the remote host." + (declare (ignore read-timeout write-timeout)) + (values socket + (ignore-errors + (ccl:ipaddr-to-dotted (ccl:local-host socket))) + (ignore-errors + (ccl:ipaddr-to-dotted (ccl:remote-host socket))) + (ignore-errors + (ccl:remote-port socket)))) + +(defun get-backtrace (error) + "This is the function that is used internally by Hunchentoot to +show or log backtraces. It accepts a condition object ERROR and +returns a string with the corresponding backtrace." + (with-output-to-string (s) + (let ((*debug-io* s)) + (format *terminal-io* "~ +~@~%~%" + error) + (ccl:print-call-history :detailed-p nil)))) Added: branches/trunk-reorg/thirdparty/hunchentoot-0.15.0/port-sbcl.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/hunchentoot-0.15.0/port-sbcl.lisp Thu Feb 7 03:16:29 2008 @@ -0,0 +1,205 @@ +;;; -*- Mode: LISP; Syntax: COMMON-LISP; Package: HUNCHENTOOT; Base: 10 -*- +;;; $Header: /usr/local/cvsrep/hunchentoot/port-sbcl.lisp,v 1.13 2007/12/29 17:35:01 edi Exp $ + +;;; Copyright (c) 2004-2007, Dr. Edmund Weitz. All rights reserved. + +;;; Redistribution and use in source and binary forms, with or without +;;; modification, are permitted provided that the following conditions +;;; are met: + +;;; * Redistributions of source code must retain the above copyright +;;; notice, this list of conditions and the following disclaimer. + +;;; * Redistributions in binary form must reproduce the above +;;; copyright notice, this list of conditions and the following +;;; disclaimer in the documentation and/or other materials +;;; provided with the distribution. + +;;; THIS SOFTWARE IS PROVIDED BY THE AUTHOR 'AS IS' AND ANY EXPRESSED +;;; OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +;;; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +;;; ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +;;; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +;;; DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +;;; GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +;;; INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +;;; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +;;; NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +;;; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +(in-package :hunchentoot) + +#-:sb-unicode +(eval-when (:compile-toplevel :load-toplevel :execute) + (error "This library needs a version of SBCL with Unicode support.")) + +#-:sb-thread +(eval-when (:compile-toplevel :load-toplevel :execute) + (warn "Without thread support, this library is only useful for development.")) + +(defmacro defconstant (name value &optional doc) + "Make sure VALUE is evaluated only once \(to appease SBCL)." + `(cl:defconstant ,name (if (boundp ',name) (symbol-value ',name) ,value) + ,@(when doc (list doc)))) + +(defun make-lock (name) + "See SBCL documentation for SB-THREAD:MAKE-MUTEX." + (sb-thread:make-mutex :name name)) + +(defmacro with-lock ((lock) &body body) + "See SBCL documentation for SB-THREAD:WITH-RECURSIVE-LOCK." + `(sb-thread:with-recursive-lock (,lock) , at body)) + +(defvar *incf-mutex* (sb-thread:make-mutex :name "incf-mutex") + "The mutex used for ATOMIC-INCF.") + +(defmacro atomic-incf (place &optional (delta 1)) + "Like INCF but protected by a mutex, so other threads can't +interfer." + `(with-lock (*incf-mutex*) (incf ,place ,delta))) + +;; determine whether SB-EXT:WITH-TIMEOUT is supported; we can't just +;; use (FIND-SYMBOL "WITH-TIMEOUT" "SB-EXT") because sometimes (for +;; example in SBCL 1.0.6 for Win32) the function is present, but +;; doesn't work +(eval-when (:compile-toplevel :load-toplevel :execute) + (defun ensured-sleep-millis (milliseconds) + "Sleeps \(in fact loops) not less then MILLISECONDS number of +milliseconds; the minimal sleep time is one internal time unit. Don't +use this function for large time values, because it eats processor +power." + (do ((start-time (get-internal-real-time))) + ((< (+ start-time (ceiling (* internal-time-units-per-second + (/ milliseconds 1000)))) + (get-internal-real-time))))) + (cl:handler-case + (sb-ext:with-timeout 0.0000001 (ensured-sleep-millis 5)) + (sb-ext:timeout () + (pushnew :hunchentoot-sbcl-with-timeout *features*)) + (t ()))) + +(defmacro with-timeout ((seconds &body timeout-forms) &body body) + "Executes the code BODY and returns the results of the last +form but stops execution after SECONDS seconds and then instead +executes the code in TIMEOUT-FORMS." + (declare (ignorable seconds timeout-forms body)) + #-:hunchentoot-sbcl-with-timeout `(cl:progn , at body) + #+:hunchentoot-sbcl-with-timeout + `(cl:handler-case + (sb-ext:with-timeout ,seconds , at body) + (sb-ext:timeout () , at timeout-forms))) + +(defun process-run-function (name function &rest args) + "See SBCL documentation for SB-THREAD:MAKE-THREAD." + (declare (ignorable name)) + #+:sb-thread + (sb-thread:make-thread (lambda () + (apply function args)) + :name name) + #-:sb-thread + (apply function args)) + +(defun process-kill (process) + "See SBCL documentation for SB-THREAD:TERMINATE-THREAD." + (sb-thread:terminate-thread process)) + +(define-symbol-macro *current-process* + sb-thread:*current-thread*) + +(defun process-allow-scheduling () + "Used to simulate a function like PROCESS-ALLOW-SCHEDULING +which can be found in most other Lisps." + (sleep .1)) + +(defun resolve-hostname (name) + "Converts from different types to represent an IP address to +the canonical representation which is an array with four +integers." + (typecase name + (null #(0 0 0 0)) + (string (car (sb-bsd-sockets:host-ent-addresses + (sb-bsd-sockets:get-host-by-name name)))) + (integer (make-array 4 :initial-contents (list (ash name -24) + (logand (ash name -16) #xFF) + (logand (ash name -8) #xFF) + (logand name #xFF)))) + (t name))) + +(defun start-up-server (&key service address process-name announce function &allow-other-keys) + "Tries to \(partly) emulate LispWorks' COMM:START-UP-SERVER. See + +for more info." + (let (done) + (flet ((open-socket-and-accept () + (handler-bind ((error (lambda (condition) + (funcall announce nil condition) + (setq done condition) + (return-from open-socket-and-accept)))) + (let (socket) + (unwind-protect + (progn + (setf socket (make-instance 'sb-bsd-sockets:inet-socket + :type :stream + :protocol :tcp) + (sb-bsd-sockets:sockopt-reuse-address socket) t) + (sb-bsd-sockets:socket-bind socket (resolve-hostname address) service) + (sb-bsd-sockets:socket-listen socket 5) + (funcall announce socket) + (setq done socket) + (loop (funcall function (sb-bsd-sockets:socket-accept socket)))) + (when socket + (cl:ignore-errors + (sb-bsd-sockets:socket-close socket)))))))) + (let ((listener-thread (process-run-function process-name #'open-socket-and-accept))) + (loop until done do (sleep .1)) + (typecase done + (sb-bsd-sockets:inet-socket listener-thread) + (t (values nil done))))))) + +(defun format-address (address) + "Converts an array of four integers denoting an IP address into +the corresponding string representation." + (format nil "~{~A~^.~}" (coerce address 'list))) + +(defun make-socket-stream (socket read-timeout write-timeout) + "Accepts a socket `handle' SOCKET and creates and returns a +corresponding stream, setting its read and write timeout if +applicable. Returns three other values - the address the request +arrived at, and the address and port of the remote host." + (declare (ignore write-timeout)) + (let ((local-host (sb-bsd-sockets:socket-name socket))) + (multiple-value-bind (remote-host remote-port) + (sb-bsd-sockets:socket-peername socket) + (values (sb-bsd-sockets:socket-make-stream socket + :input t + :output t + :element-type 'octet + :timeout read-timeout + :buffering :full) + (format-address local-host) + (format-address remote-host) + remote-port)))) + +;; determine how we're going to access the backtrace in the next +;; function +(eval-when (:compile-toplevel :load-toplevel :execute) + (when (find-symbol "*DEBUG-PRINT-VARIABLE-ALIST*" :sb-debug) + (pushnew :hunchentoot-sbcl-debug-print-variable-alist *features*))) + +(defun get-backtrace (error) + "This is the function that is used internally by Hunchentoot to +show or log backtraces. It accepts a condition object ERROR and +returns a string with the corresponding backtrace." + (declare (ignore error)) + (with-output-to-string (s) + #+:hunchentoot-sbcl-debug-print-variable-alist + (let ((sb-debug:*debug-print-variable-alist* + (list* '(*print-level* . nil) + '(*print-length* . nil) + sb-debug:*debug-print-variable-alist*))) + (sb-debug:backtrace most-positive-fixnum s)) + #-:hunchentoot-sbcl-debug-print-variable-alist + (let ((sb-debug:*debug-print-level* nil) + (sb-debug:*debug-print-length* nil)) + (sb-debug:backtrace most-positive-fixnum s)))) + Added: branches/trunk-reorg/thirdparty/hunchentoot-0.15.0/reply.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/hunchentoot-0.15.0/reply.lisp Thu Feb 7 03:16:29 2008 @@ -0,0 +1,144 @@ +;;; -*- Mode: LISP; Syntax: COMMON-LISP; Package: HUNCHENTOOT; Base: 10 -*- +;;; $Header: /usr/local/cvsrep/hunchentoot/reply.lisp,v 1.19 2007/09/24 13:43:45 edi Exp $ + +;;; Copyright (c) 2004-2007, Dr. Edmund Weitz. All rights reserved. + +;;; Redistribution and use in source and binary forms, with or without +;;; modification, are permitted provided that the following conditions +;;; are met: + +;;; * Redistributions of source code must retain the above copyright +;;; notice, this list of conditions and the following disclaimer. + +;;; * Redistributions in binary form must reproduce the above +;;; copyright notice, this list of conditions and the following +;;; disclaimer in the documentation and/or other materials +;;; provided with the distribution. + +;;; THIS SOFTWARE IS PROVIDED BY THE AUTHOR 'AS IS' AND ANY EXPRESSED +;;; OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +;;; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +;;; ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +;;; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +;;; DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +;;; GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +;;; INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +;;; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +;;; NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +;;; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +(in-package :hunchentoot) + +(defclass reply () + ((content-type :initform *default-content-type* + :documentation "The outgoing 'Content-Type' http +header which defaults to the value of *DEFAULT-CONTENT-TYPE*.") + (content-length :initform nil + :documentation "The outgoing 'Content-Length' +http header which defaults NIL. If this is NIL, Hunchentoot will +compute the content length.") + (headers-out :initform nil + :documentation "An alist of the outgoing http headers +not including the 'Set-Cookie', 'Content-Length', and 'Content-Type' +headers. Use the functions HEADER-OUT and \(SETF HEADER-OUT) to +modify this slot.") + (return-code :initform +http-ok+ + :documentation "The http return code of this +reply. The return codes Hunchentoot can handle are defined in +specials.lisp.") + (external-format :initform *hunchentoot-default-external-format* + :documentation "The external format of the reply - +used for character output.") + (log-messages :initform nil + :reader log-messages + :documentation "A list \(in reverse chronological +order) of the messages which are to be written to the Apache error +log. This slot's value should only be modified by the functions +defined in log.lisp.") + (cookies-out :initform nil + :documentation "The outgoing cookies. This slot's +value should only be modified by the functions defined in +cookies.lisp.")) + (:documentation "Objects of this class hold all the information +about an outgoing reply. They are created automatically by +Hunchentoot and can be accessed and modified by the corresponding +handler.")) + +(defun headers-out (&optional (reply *reply*)) + "Returns an alist of the outgoing headers associated with the +REPLY object REPLY." + (slot-value reply 'headers-out)) + +(defun cookies-out (&optional (reply *reply*)) + "Returns an alist of the outgoing cookies associated with the +REPLY object REPLY." + (slot-value reply 'cookies-out)) + +(defun (setf cookies-out) (new-value &optional (reply *reply*)) + "Returns an alist of the outgoing cookies associated with the +REPLY object REPLY." + (setf (slot-value reply 'cookies-out) new-value)) + +(defun content-type (&optional (reply *reply*)) + "The outgoing 'Content-Type' http header of REPLY." + (slot-value reply 'content-type)) + +(defun (setf content-type) (new-value &optional (reply *reply*)) + "Sets the outgoing 'Content-Type' http header of REPLY." + (setf (slot-value reply 'content-type) new-value)) + +(defun content-length (&optional (reply *reply*)) + "The outgoing 'Content-Length' http header of REPLY." + (slot-value reply 'content-length)) + +(defun (setf content-length) (new-value &optional (reply *reply*)) + "Sets the outgoing 'Content-Length' http header of REPLY." + (setf (slot-value reply 'content-length) new-value)) + +(defun return-code (&optional (reply *reply*)) + "The http return code of REPLY. The return codes Hunchentoot can +handle are defined in specials.lisp." + (slot-value reply 'return-code)) + +(defun (setf return-code) (new-value &optional (reply *reply*)) + "Sets the http return code of REPLY." + (setf (slot-value reply 'return-code) new-value)) + +(defun reply-external-format (&optional (reply *reply*)) + "The external format of REPLY which is used for character output." + (slot-value reply 'external-format)) + +(defun (setf reply-external-format) (new-value &optional (reply *reply*)) + "Sets the external format of REPLY." + (setf (slot-value reply 'external-format) new-value)) + +(defun header-out-set-p (name &optional (reply *reply*)) + "Returns a true value if the outgoing http header named NAME has +been specified already. NAME should be a keyword or a string." + (assoc name (headers-out reply))) + +(defun header-out (name &optional (reply *reply*)) + "Returns the current value of the outgoing http header named NAME. +NAME should be a keyword or a string." + (cdr (assoc name (headers-out reply)))) + +(defun cookie-out (name &optional (reply *reply*)) + "Returns the current value of the outgoing cookie named +NAME. Search is case-sensitive." + (cdr (assoc name (cookies-out reply) :test #'string=))) + +(defsetf header-out (name &optional (reply '*reply*)) + (new-value) + "Changes the current value of the outgoing http header named NAME (a +keyword or a string). If a header with this name doesn't exist, it is +created." + (with-rebinding (name reply) + (with-unique-names (symbol place) + `(let* ((,symbol (if (stringp ,name) (make-keyword ,name :destructivep nil) ,name)) + (,place (assoc ,symbol (headers-out ,reply) :test #'string-equal))) + (cond + (,place + (setf (cdr ,place) ,new-value)) + (t + (push (cons ,symbol ,new-value) (slot-value ,reply 'headers-out)) + ,new-value)))))) \ No newline at end of file Added: branches/trunk-reorg/thirdparty/hunchentoot-0.15.0/request.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/hunchentoot-0.15.0/request.lisp Thu Feb 7 03:16:29 2008 @@ -0,0 +1,475 @@ +;;; -*- Mode: LISP; Syntax: COMMON-LISP; Package: HUNCHENTOOT; Base: 10 -*- +;;; $Header: /usr/local/cvsrep/hunchentoot/request.lisp,v 1.34 2007/12/29 17:35:01 edi Exp $ + +;;; Copyright (c) 2004-2007, Dr. Edmund Weitz. All rights reserved. + +;;; Redistribution and use in source and binary forms, with or without +;;; modification, are permitted provided that the following conditions +;;; are met: + +;;; * Redistributions of source code must retain the above copyright +;;; notice, this list of conditions and the following disclaimer. + +;;; * Redistributions in binary form must reproduce the above +;;; copyright notice, this list of conditions and the following +;;; disclaimer in the documentation and/or other materials +;;; provided with the distribution. + +;;; THIS SOFTWARE IS PROVIDED BY THE AUTHOR 'AS IS' AND ANY EXPRESSED +;;; OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +;;; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +;;; ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +;;; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +;;; DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +;;; GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +;;; INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +;;; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +;;; NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +;;; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +(in-package :hunchentoot) + +(defclass request () + ((headers-in :initarg :headers-in + :documentation "An alist of the incoming headers. Note +that these might be the headers coming in from mod_lisp which are +different from the headers sent by the client.") + (method :initarg :method + :documentation "The request method as a keyword. This slot +is only filled if we're not behind mod_lisp.") + (uri :initarg :uri + :documentation "The request URI as a string. This slot is +only filled if we're not behind mod_lisp.") + (server-protocol :initarg :server-protocol + :documentation "The HTTP protocol as a keyword. +This slot is only filled if we're not behind mod_lisp.") + (content-stream :initarg :content-stream + :reader content-stream + :documentation "A stream from which the request +body can be read if there is one.") + (cookies-in :initform nil + :documentation "An alist of the cookies sent by the client.") + (get-parameters :initform nil + :documentation "An alist of the GET parameters sent +by the client.") + (post-parameters :initform nil + :documentation "An alist of the POST parameters +sent by the client.") + (script-name :initform nil + :documentation "The URI requested by the client without +the query string.") + (query-string :initform nil + :documentation "The query string of this request.") + (session :initform nil + :accessor session + :documentation "The session object associated with this +request.") + (aux-data :initform nil + :accessor aux-data + :documentation "Used to keep a user-modifiable alist with +arbitrary data during the request.") + (raw-post-data :initform nil + :documentation "The raw string sent as the body of a +POST request, populated only if not a multipart/form-data request.")) + (:documentation "Objects of this class hold all the information +about an incoming request. They are created automatically by +Hunchentoot and can be accessed by the corresponding handler.")) + +(defun parse-rfc2388-form-data (stream content-type-header) + "Creates an alist of POST parameters from the stream STREAM which is +supposed to be of content type 'multipart/form-data'." + (let* ((parsed-content-type-header (rfc2388:parse-header content-type-header :value)) + (boundary (or (cdr (rfc2388:find-parameter + "BOUNDARY" + (rfc2388:header-parameters parsed-content-type-header))) + (return-from parse-rfc2388-form-data)))) + (loop for part in (rfc2388:parse-mime stream boundary) + for headers = (rfc2388:mime-part-headers part) + for content-disposition-header = (rfc2388:find-content-disposition-header headers) + for name = (cdr (rfc2388:find-parameter + "NAME" + (rfc2388:header-parameters content-disposition-header))) + when name + collect (cons name + (let ((contents (rfc2388:mime-part-contents part))) + (if (pathnamep contents) + (list contents + (rfc2388:get-file-name headers) + (rfc2388:content-type part :as-string t)) + contents)))))) + +(defun get-post-data (&key (request *request*) want-stream (already-read 0)) + "Reads the request body from the stream and stores the raw contents +\(as an array of octets) in the corresponding slot of the REQUEST +object. Returns just the stream if WANT-STREAM is true. If there's a +Content-Length header, it is assumed, that ALREADY-READ octets have +already been read." + (let* ((headers-in (headers-in request)) + (content-length (when-let (content-length-header (cdr (assoc :content-length headers-in))) + (parse-integer content-length-header :junk-allowed t))) + (content-stream (content-stream request))) + (setf (slot-value request 'raw-post-data) + (cond (want-stream + (setf (flexi-stream-position *hunchentoot-stream*) 0) + (when content-length + (setf (flexi-stream-bound content-stream) content-length)) + content-stream) + ((and content-length (> content-length already-read)) + (decf content-length already-read) + (when (input-chunking-p) + ;; see RFC 2616, section 4.4 + (log-message :warn "Got Content-Length header although input chunking is on.")) + (let ((content (make-array content-length :element-type 'octet))) + #+:clisp (setf (flexi-stream-element-type content-stream) 'octet) + (read-sequence content content-stream) + content)) + ((input-chunking-p) + (loop with buffer = (make-array +buffer-length+ :element-type 'octet) + with content = (make-array 0 :element-type 'octet :adjustable t) + for index = 0 then (+ index pos) + for pos = (read-sequence buffer content-stream) + do (adjust-array content (+ index pos)) + (replace content buffer :start1 index :end2 pos) + while (= pos +buffer-length+) + finally (return content))))))) + +(defmethod initialize-instance :after ((request request) &rest init-args) + "The only initarg for a REQUEST object is :HEADERS-IN. All other +slot values are computed in this :AFTER method." + (declare (ignore init-args)) + (with-slots (headers-in cookies-in get-parameters post-parameters script-name query-string session) + request + (handler-case + (progn + (when (server-mod-lisp-p *server*) + ;; convert these two values to keywords + (let ((method-pair (assoc :method headers-in))) + (setf (cdr method-pair) (make-keyword (cdr method-pair)))) + (let ((protocol-pair (assoc :server-protocol headers-in))) + (setf (cdr protocol-pair) (make-keyword (cdr protocol-pair)))) + ;; and convert these two values to integers + (let ((remote-ip-port-pair (assoc :remote-ip-port headers-in))) + (setf (cdr remote-ip-port-pair) (parse-integer (cdr remote-ip-port-pair) + :junk-allowed t))) + (let ((server-ip-port-pair (assoc :server-ip-port headers-in))) + (setf (cdr server-ip-port-pair) (parse-integer (cdr server-ip-port-pair) + :junk-allowed t)))) + ;; compute SCRIPT-NAME and QUERY-STRING slots from + ;; REQUEST_URI environment variable + (let* ((uri (request-uri request)) + (match-start (position #\? uri))) + (cond + (match-start + (setq script-name (subseq uri 0 match-start) + query-string (subseq uri (1+ match-start)))) + (t (setq script-name uri)))) + ;; some clients (e.g. ASDF-INSTALL) send requests like + ;; "GET http://server/foo.html HTTP/1.0"... + (setq script-name (regex-replace "^https?://[^/]+" script-name "")) + ;; compute GET parameters from query string and cookies from + ;; the incoming 'Cookie' header + (setq get-parameters + (form-url-encoded-list-to-alist (split "&" query-string)) + cookies-in + (form-url-encoded-list-to-alist (split "\\s*[,;]\\s*" (cdr (assoc :cookie headers-in))) + +utf-8+) + session (session-verify request) + *session* session) + ;; if the content-type is 'application/x-www-form-urlencoded' + ;; or 'multipart/form-data', compute the post parameters from + ;; the content body + (when (member (request-method request) *methods-for-post-parameters* :test #'eq) + (when-let (content-type (cdr (assoc :content-type headers-in))) + (multiple-value-bind (type subtype external-format) + (parse-content-type content-type t) + (setq post-parameters + (cond ((and (string-equal type "application") + (string-equal subtype "x-www-form-urlencoded")) + (unless (or (assoc :content-length headers-in) + (input-chunking-p)) + (error "Can't read request body because there's no~ +Content-Length header and input chunking is off.")) + (form-url-encoded-list-to-alist + (split "&" (raw-post-data :request request + ;; ASCII would suffice according to RFC... + :external-format +latin-1+)) + external-format)) + ((and (string-equal type "multipart") + (string-equal subtype "form-data")) + (setf (slot-value request 'raw-post-data) t) + (handler-case + (let* ((*request* request) + (content-stream (content-stream request)) + (start (flexi-stream-position content-stream))) + (prog1 + (parse-rfc2388-form-data content-stream content-type) + (let* ((end (flexi-stream-position content-stream)) + (stray-data (get-post-data :already-read (- end start)))) + (when (and stray-data (plusp (length stray-data))) + (warn "~A octets of stray data after form-data sent by client." + (length stray-data)))) + (setf (slot-value request 'raw-post-data) t))) + (error (msg) + (log-message :error + "While parsing multipart/form-data parameters: ~A" + msg) + nil))))))))) + (error (cond) + (log-message* "Error when creating REQUEST object: ~A" cond) + ;; we assume it's not our fault... + (setf (return-code) +http-bad-request+))))) + +(defun recompute-request-parameters (&key (request *request*) + (external-format *hunchentoot-default-external-format*)) + "Recomputes the GET and POST parameters for the REQUEST object +REQUEST. This only makes sense if you're switching external formats +during the request." + (with-slots (headers-in get-parameters post-parameters query-string) + request + (setq get-parameters + (form-url-encoded-list-to-alist (split "&" query-string) external-format) + post-parameters + (when-let (raw-post-data (raw-post-data :request request + :external-format +latin-1+)) + (and (when-let (content-type (cdr (assoc :content-type headers-in))) + (multiple-value-bind (type subtype) + (parse-content-type content-type) + (and (string-equal type "application") + (string-equal subtype "x-www-form-urlencoded")))) + (form-url-encoded-list-to-alist (split "&" raw-post-data) external-format))))) + (values)) + +(defun script-name (&optional (request *request*)) + "Returns the file name of the REQUEST object REQUEST. That's the +requested URI without the query string \(i.e the GET parameters)." + (slot-value request 'script-name)) + +(defun query-string (&optional (request *request*)) + "Returns the query string of the REQUEST object REQUEST. That's +the part behind the question mark \(i.e. the GET parameters)." + (slot-value request 'query-string)) + +(defun get-parameters (&optional (request *request*)) + "Returns an alist of the GET parameters associated with the REQUEST +object REQUEST." + (slot-value request 'get-parameters)) + +(defun post-parameters (&optional (request *request*)) + "Returns an alist of the POST parameters associated with the REQUEST +object REQUEST." + (slot-value request 'post-parameters)) + +(defun headers-in (&optional (request *request*)) + "Returns an alist of the incoming headers associated with the +REQUEST object REQUEST." + (slot-value request 'headers-in)) + +(defun cookies-in (&optional (request *request*)) + "Returns an alist of all cookies associated with the REQUEST object +REQUEST." + (slot-value request 'cookies-in)) + +(defun header-in (name &optional (request *request*)) + "Returns the incoming header with name NAME. NAME can be a keyword +\(recommended) or a string." + (cdr (assoc name (headers-in request)))) + +(defun authorization (&optional (request *request*)) + "Returns as two values the user and password \(if any) as encoded in +the 'AUTHORIZATION' header. Returns NIL if there is no such header." + (let* ((authorization (header-in :authorization request)) + (start (and authorization + (> (length authorization) 5) + (string-equal "Basic" authorization :end2 5) + (scan "\\S" authorization :start 5)))) + (when start + (destructuring-bind (&optional user password) + (split ":" (base64:base64-string-to-string (subseq authorization start))) + (values user password))))) + +(defun remote-addr (&optional (request *request*)) + "Returns the address the current request originated from." + (cond ((server-mod-lisp-p *server*) (header-in :remote-ip-addr request)) + (t *remote-host*))) + +(defun real-remote-addr (&optional (request *request*)) + "Returns the 'X-Forwarded-For' incoming http header as the +second value in the form of a list of IP addresses and the first +element of this list as the first value if this header exists. +Otherwise returns the value of REMOTE-ADDR as the only value." + (let ((x-forwarded-for (header-in :x-forwarded-for request))) + (cond (x-forwarded-for (let ((addresses (split "\\s*,\\s*" x-forwarded-for))) + (values (first addresses) addresses))) + (t (remote-addr request))))) + +(defun server-addr (&optional (request *request*)) + "Returns the address at which the current request arrived." + (cond ((server-mod-lisp-p *server*) (header-in :server-ip-addr request)) + (t *local-host*))) + +(defun remote-port (&optional (request *request*)) + "Returns the port the current request originated from." + (cond ((server-mod-lisp-p *server*) (header-in :remote-ip-port request)) + (t *remote-port*))) + +(defun server-port (&optional (request *request*)) + "Returns the port at which the current request arrived." + (cond ((server-mod-lisp-p *server*) (header-in :server-ip-port request)) + (t (server-local-port *server*)))) + +(defun host (&optional (request *request*)) + "Returns the 'Host' incoming http header value." + (header-in :host request)) + +(defun request-uri (&optional (request *request*)) + "Returns the request URI." + (cond ((server-mod-lisp-p *server*) (header-in :url request)) + (t (slot-value request 'uri)))) + +(defun request-method (&optional (request *request*)) + "Returns the request method as a Lisp keyword." + (cond ((server-mod-lisp-p *server*) (header-in :method request)) + (t (slot-value request 'method)))) + +(defun server-protocol (&optional (request *request*)) + "Returns the request protocol as a Lisp keyword." + (cond ((server-mod-lisp-p *server*) (header-in :server-protocol request)) + (t (slot-value request 'server-protocol)))) + +(defun mod-lisp-id (&optional (request *request*)) + "Returns the 'Server ID' sent by mod_lisp. This value is set in +Apache's server configuration file and is of course only available if +mod_lisp is the front-end." + (and (or (server-mod-lisp-p *server*) + (warn "Calling MOD-LISP-ID although ~S is a stand-alone server." + *server*)) + (header-in :server-id request))) + +(defun ssl-session-id (&optional (request *request*)) + "Returns the 'SSL_SESSION_ID' header sent my mod_lisp and is of +course only available if mod_lisp is the front-end." + (and (or (server-mod-lisp-p *server*) + (warn "Calling SSL-SESSION-ID although ~S is a stand-alone server." + *server*)) + (header-in :ssl-session-id request))) + +(defun user-agent (&optional (request *request*)) + "Returns the 'User-Agent' http header." + (header-in :user-agent request)) + +(defun cookie-in (name &optional (request *request*)) + "Returns the cookie with the name NAME \(a string) as sent by the +browser - or NIL if there is none." + (cdr (assoc name (cookies-in request) :test #'string=))) + +(defun referer (&optional (request *request*)) + "Returns the 'Referer' \(sic!) http header." + (header-in :referer request)) + +(defun get-parameter (name &optional (request *request*)) + "Returns the GET parameter with name NAME \(a string) - or NIL if +there is none. Search is case-sensitive." + (cdr (assoc name (get-parameters request) :test #'string=))) + +(defun post-parameter (name &optional (request *request*)) + "Returns the POST parameter with name NAME \(a string) - or NIL if +there is none. Search is case-sensitive." + (cdr (assoc name (post-parameters request) :test #'string=))) + +(defun parameter (name &optional (request *request*)) + "Returns the GET or the POST parameter with name NAME \(a string) - +or NIL if there is none. If both a GET and a POST parameter with the +same name exist the GET parameter is returned. Search is +case-sensitive." + (or (get-parameter name request) + (post-parameter name request))) + +(defun handle-if-modified-since (time &optional (request *request*)) + "Handles the 'If-Modified-Since' header of REQUEST. The date string +is compared to the one generated from the supplied universal time +TIME." + (let ((if-modified-since (header-in :if-modified-since request)) + (time-string (rfc-1123-date time))) + ;; simple string comparison is sufficient; see RFC 2616 14.25 + (when (and if-modified-since + (equal if-modified-since time-string)) + (setf (return-code) +http-not-modified+) + (throw 'handler-done nil)) + (values))) + +(defun raw-post-data (&key (request *request*) external-format force-binary force-text want-stream) + "Returns the content sent by the client if there was any \(unless +the content type was \"multipart/form-data\"). By default, the result +is a string if the type of the `Content-Type' media type is \"text\", +and a vector of octets otherwise. In the case of a string, the +external format to be used to decode the content will be determined +from the `charset' parameter sent by the client \(or otherwise +*HUNCHENTOOT-DEFAULT-EXTERNAL-FORMAT* will be used). + +You can also provide an external format explicitly \(through +EXTERNAL-FORMAT) in which case the result will unconditionally be a +string. Likewise, you can provide a true value for FORCE-TEXT which +will force Hunchentoot to act as if the type of the media type had +been \"text\". Or you can provide a true value for FORCE-BINARY which +means that you want a vector of octets at any rate. + +If, however, you provide a true value for WANT-STREAM, the other +parameters are ignored and you'll get the content \(flexi) stream to +read from it yourself. It is then your responsibility to read the +correct amount of data, because otherwise you won't be able to return +a response to the client. If the content type of the request was +`multipart/form-data' or `application/x-www-form-urlencoded', the +content has been read by Hunchentoot already and you can't read from +the stream anymore. + +You can call RAW-POST-DATA more than once per request, but you can't +mix calls which have different values for WANT-STREAM. + +Note that this function is slightly misnamed because a client can send +content even if the request method is not POST." + (when (and force-binary force-text) + (error "It doesn't make sense to set both FORCE-BINARY and FORCE-TEXT to a true value.")) + (unless (or external-format force-binary) + (setq external-format + (when-let (content-type (cdr (assoc :content-type (headers-in request)))) + (nth-value 2 (parse-content-type content-type force-text))))) + (let ((raw-post-data (or (slot-value request 'raw-post-data) + (get-post-data :request request :want-stream want-stream)))) + (cond ((typep raw-post-data 'stream) raw-post-data) + ((member raw-post-data '(t nil)) nil) + (external-format (octets-to-string raw-post-data :external-format external-format)) + (t raw-post-data)))) + +(defun aux-request-value (symbol &optional (request *request*)) + "Returns the value associated with SYMBOL from the request object +REQUEST \(the default is the current request) if it exists. The +second return value is true if such a value was found." + (when request + (let ((found (assoc symbol (aux-data request)))) + (values (cdr found) found)))) + +(defsetf aux-request-value (symbol &optional request) + (new-value) + "Sets the value associated with SYMBOL from the request object +REQUEST \(default is *REQUEST*). If there is already a value +associated with SYMBOL it will be replaced." + (with-rebinding (symbol) + (with-unique-names (place %request) + `(let* ((,%request (or ,request *request*)) + (,place (assoc ,symbol (aux-data ,%request)))) + (cond + (,place + (setf (cdr ,place) ,new-value)) + (t + (push (cons ,symbol ,new-value) + (aux-data ,%request)) + ,new-value)))))) + +(defun delete-aux-request-value (symbol &optional (request *request*)) + "Removes the value associated with SYMBOL from the request object +REQUEST." + (when request + (setf (aux-data request) + (delete symbol (aux-data request) + :key #'car :test #'eq))) + (values)) Added: branches/trunk-reorg/thirdparty/hunchentoot-0.15.0/server.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/hunchentoot-0.15.0/server.lisp Thu Feb 7 03:16:29 2008 @@ -0,0 +1,440 @@ +;;; -*- Mode: LISP; Syntax: COMMON-LISP; Package: CL-USER; Base: 10 -*- +;;; $Header: /usr/local/cvsrep/hunchentoot/server.lisp,v 1.38 2007/11/03 21:46:19 edi Exp $ + +;;; Copyright (c) 2004-2007, Dr. Edmund Weitz. All rights reserved. + +;;; Redistribution and use in source and binary forms, with or without +;;; modification, are permitted provided that the following conditions +;;; are met: + +;;; * Redistributions of source code must retain the above copyright +;;; notice, this list of conditions and the following disclaimer. + +;;; * Redistributions in binary form must reproduce the above +;;; copyright notice, this list of conditions and the following +;;; disclaimer in the documentation and/or other materials +;;; provided with the distribution. + +;;; THIS SOFTWARE IS PROVIDED BY THE AUTHOR 'AS IS' AND ANY EXPRESSED +;;; OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +;;; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +;;; ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +;;; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +;;; DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +;;; GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +;;; INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +;;; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +;;; NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +;;; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +(in-package :hunchentoot) + +(defclass server () + ((socket :accessor server-socket + :documentation "The socket the server is listening on.") + (port :initarg :port + :reader server-local-port + :documentation "The port the server is listening on. +See START-SERVER.") + (address :initarg :address + :reader server-address + :documentation "The address the server is listening +on. See START-SERVER.") + (name :initarg :name + :accessor server-name + :documentation "The optional name of the server, a symbol.") + (dispatch-table :initarg :dispatch-table + :accessor server-dispatch-table + :documentation "The dispatch-table used by this +server. Can be NIL to denote that *META-DISPATCHER* should be called +instead.") + (output-chunking-p :initarg :output-chunking-p + :reader server-output-chunking-p + :documentation "Whether the server may use output chunking.") + (input-chunking-p :initarg :input-chunking-p + :reader server-input-chunking-p + :documentation "Whether the server may use input chunking.") + (read-timeout :initarg :read-timeout + :reader server-read-timeout + :documentation "The read-timeout of the server.") + (write-timeout :initarg :write-timeout + :reader server-write-timeout + :documentation "The write-timeout of the server.") + (listener :accessor server-listener + :documentation "The Lisp process which listens for +incoming requests and starts new worker threads for each new +connection.") + (workers :initform nil + :accessor server-workers + :documentation "A list of currently active worker threads.") + (mod-lisp-p :initform nil + :initarg :mod-lisp-p + :reader server-mod-lisp-p + :documentation "Whether this is a genuine +Hunchentoot server or \"just\" infrastructure for mod_lisp.") + (use-apache-log-p :initarg :use-apache-log-p + :reader server-use-apache-log-p + :documentation "Whether the server should use +Apache's log file. Only applicable if MOD-LISP-P is true.") + #-:hunchentoot-no-ssl + (ssl-certificate-file :initarg :ssl-certificate-file + :reader server-ssl-certificate-file + :documentation "The namestring of a +certificate file if SSL is used, NIL otherwise.") + #-:hunchentoot-no-ssl + (ssl-privatekey-file :initarg :ssl-privatekey-file + :reader server-ssl-privatekey-file + :documentation "The namestring of a +private key file if SSL is used, NIL otherwise.") + #-:hunchentoot-no-ssl + (ssl-privatekey-password :initarg :ssl-privatekey-password + :reader server-ssl-privatekey-password + :documentation "The password for the +private key file or NIL.") + (lock :initform (make-lock (format nil "hunchentoot-lock-~A" + *server-counter*)) + :reader server-lock + :documentation "A lock which is used to make sure that +we can shutdown the server cleanly.")) + (:documentation "An object of this class contains all relevant +information about a running Hunchentoot server instance.")) + +(defun start-server (&key (port 80 port-provided-p) + address + dispatch-table + (name (gensym)) + (mod-lisp-p nil) + (use-apache-log-p mod-lisp-p) + (input-chunking-p t) + (read-timeout *default-read-timeout*) + (write-timeout *default-write-timeout*) + #+(and :unix (not :win32)) setuid + #+(and :unix (not :win32)) setgid + #-:hunchentoot-no-ssl ssl-certificate-file + #-:hunchentoot-no-ssl (ssl-privatekey-file ssl-certificate-file) + #-:hunchentoot-no-ssl ssl-privatekey-password) + "Starts a Hunchentoot server and returns the SERVER object \(which +can be stopped with STOP-SERVER). PORT is the port the server will be +listening on - the default is 80 \(or 443 if SSL information is +provided). If ADDRESS is a string denoting an IP address, then the +server only receives connections for that address. This must be one +of the addresses associated with the machine and allowed values are +host names such as \"www.nowhere.com\" and address strings like +\"204.71.177.75\". If ADDRESS is NIL, then the server will receive +connections to all IP addresses on the machine. This is the default. + +DISPATCH-TABLE can either be a dispatch table which is to be used by +this server or NIL which means that at request time *META-DISPATCHER* +will be called to retrieve a dispatch table. + +NAME should be a symbol which can be used to name the server. This +name can utilized when defining \"easy handlers\" - see +DEFINE-EASY-HANDLER. The default name is an uninterned symbol as +returned by GENSYM. + +If MOD-LISP-P is true, the server will act as a back-end for mod_lisp, +otherwise it will be a stand-alone web server. If USE-APACHE-LOG-P is +true, log messages will be written to the Apache log file - this +parameter has no effect if MOD-LISP-P is NIL. + +If INPUT-CHUNKING-P is true, the server will accept request bodies +without a `Content-Length' header if the client uses chunked transfer +encoding. If you want to use this feature together with mod_lisp, you +should make sure that your combination of Apache and mod_lisp can do +that - see: + + . + +On LispWorks 5.0 or higher and AllegroCL, READ-TIMEOUT and +WRITE-TIMEOUT are the read and write timeouts \(in seconds) of +the server - use NIL for no timeout at all. (See the LispWorks +documentation for STREAM:SOCKET-STREAM for details.) On +LispWorks 4.4.6 or lower, SBCL, and CMUCL WRITE-TIMEOUT is +ignored. On OpenMCL both parameters are ignored. + +On Unix you can use SETUID and SETGID to change the UID and GID of the +process directly after the server has been started. \(You might want +to do this if you're using a privileged port like 80.) SETUID and +SETGID can be integers \(the actual IDs) or strings \(for the user and +group name respectively). + +If you want your server to use SSL you must provide the pathname +designator\(s) SSL-CERTIFICATE-FILE for the certificate file and +optionally SSL-PRIVATEKEY-FILE for the private key file, both files +must be in PEM format. If you only provide the value for +SSL-CERTIFICATE-FILE it is assumed that both the certificate and the +private key are in one file. If your private key needs a password you +can provide it through the SSL-PRIVATEKEY-PASSWORD keyword argument, +but this works only on LispWorks - for other Lisps the key must not be +associated with a password." + (declare (ignorable port-provided-p)) + ;; initialize the session secret if needed + (unless (boundp '*session-secret*) + (reset-session-secret)) + (let ((output-chunking-p t)) + #-:hunchentoot-no-ssl + (when ssl-certificate-file + ;; disable output chunking for SSL connections + (setq output-chunking-p nil) + (unless port-provided-p (setq port 443))) + ;; no timeouts if behind mod_lisp + (when mod-lisp-p + (setq read-timeout nil + write-timeout nil)) + ;; use a new process/lock name for each server + (atomic-incf *server-counter*) + ;; create the SERVER object + (let ((server (make-instance 'server + :port port + :address address + :name name + :dispatch-table dispatch-table + :output-chunking-p (and output-chunking-p (not mod-lisp-p)) + :input-chunking-p input-chunking-p + #-:hunchentoot-no-ssl :ssl-certificate-file + #-:hunchentoot-no-ssl(and ssl-certificate-file + (namestring ssl-certificate-file)) + #-:hunchentoot-no-ssl :ssl-privatekey-file + #-:hunchentoot-no-ssl (and ssl-privatekey-file + (namestring ssl-privatekey-file)) + #-:hunchentoot-no-ssl :ssl-privatekey-password + #-:hunchentoot-no-ssl ssl-privatekey-password + :mod-lisp-p mod-lisp-p + :use-apache-log-p (and mod-lisp-p use-apache-log-p) + :read-timeout read-timeout + :write-timeout write-timeout))) + (multiple-value-bind (process condition) + ;; start up the actual server + (start-up-server :service port + :address address + :process-name (format nil "hunchentoot-listener-~A" *server-counter*) + ;; this function is called once on + ;; startup - we use it to record the + ;; socket + :announce (lambda (socket &optional condition) + (cond (socket + (setf (server-socket server) socket)) + (condition + (error condition)))) + ;; this function is called whenever a + ;; connection is made + :function (lambda (handle) + (with-lock ((server-lock server)) + (incf *worker-counter*) + ;; check if we need to + ;; perform a global GC + (when (and *cleanup-interval* + (zerop (mod *worker-counter* *cleanup-interval*))) + (when *cleanup-function* + (funcall *cleanup-function*))) + ;; start a worker thread + ;; for this connection + ;; and remember it + (push (process-run-function (format nil "hunchentoot-worker-~A" + *worker-counter*) + #'process-connection + server handle) + (server-workers server)))) + ;; wait until the server was + ;; successfully started or an error + ;; condition is returned + :wait t) + (cond (process + ;; remember the listener so we can kill it later + (setf (server-listener server) process)) + (condition + (error condition)))) + #+(and :unix (not :win32)) + (when setgid + ;; we must make sure to call setgid before we call setuid or + ;; suddenly we aren't root anymore... + (etypecase setgid + (integer (setgid setgid)) + (string (setgid (get-gid-from-name setgid))))) + #+(and :unix (not :win32)) + (when setuid + (etypecase setuid + (integer (setuid setuid)) + (string (setuid (get-uid-from-name setuid))))) + server))) + +(defun stop-server (server) + "Stops the Hunchentoot server SERVER." + ;; use lock so that the listener can't start new workers + (with-lock ((server-lock server)) + ;; kill all worker threads + (dolist (worker (server-workers server)) + (ignore-errors (process-kill worker)) + (process-allow-scheduling)) + ;; finally, kill main listener + (when-let (listener (server-listener server)) + (process-kill listener))) + (values)) + +(defun process-connection (server handle) + "This function is called by the server in a newly-created thread +with the SERVER object itself and a socket 'handle' from which a +stream can be created. It reads the request headers and hands over to +PROCESS-REQUEST. This is done in a loop until the stream has to be +closed or until a read timeout occurs." + (handler-bind ((error + ;; abort if there's an error which isn't caught inside + (lambda (cond) + (log-message *lisp-errors-log-level* + "Error while processing connection: ~A" cond) + (return-from process-connection))) + (warning + ;; log all warnings which aren't caught inside + (lambda (cond) + (log-message *lisp-warnings-log-level* + "Warning while processing connection: ~A" cond)))) + (with-debugger + (let (*hunchentoot-stream* *local-host* *remote-host* *remote-port*) + (unwind-protect + ;; bind important special variables + (let ((*server* server)) + ;; create binary stream from socket handle + (multiple-value-setq (*hunchentoot-stream* *local-host* *remote-host* *remote-port*) + (make-socket-stream handle + (server-read-timeout server) + (server-write-timeout server))) + ;; attach SSL to the stream if necessary + #-:hunchentoot-no-ssl + (when (server-ssl-certificate-file server) + #+:lispworks + (make-ssl-server-stream *hunchentoot-stream* + :certificate-file (server-ssl-certificate-file server) + :privatekey-file (server-ssl-privatekey-file server) + :privatekey-password (server-ssl-privatekey-password server)) + #-:lispworks + (setq *hunchentoot-stream* + (cl+ssl:make-ssl-server-stream *hunchentoot-stream* + :certificate (server-ssl-certificate-file server) + :key (server-ssl-privatekey-file server)))) + ;; wrap with chunking-enabled stream if necessary + (when (or (server-input-chunking-p server) + (server-output-chunking-p server)) + (setq *hunchentoot-stream* (make-chunked-stream *hunchentoot-stream*))) + ;; now wrap with flexi stream with "faithful" external format + (setq *hunchentoot-stream* + (make-flexi-stream *hunchentoot-stream* :external-format +latin-1+)) + ;; loop until we have to close the stream - as + ;; determined by *CLOSE-HUNCHENTOOT-STREAM* + (unwind-protect + (loop + (let ((*close-hunchentoot-stream* t)) + ;; reset to "faithful" format on each iteration + ;; and reset bound of stream as well + (setf (flexi-stream-external-format *hunchentoot-stream*) +latin-1+ + (flexi-stream-bound *hunchentoot-stream*) nil) + (multiple-value-bind (headers-in content-stream method url-string server-protocol) + (get-request-data) + (unless (and ;; check if there was a request at all + (cond ((server-mod-lisp-p server) headers-in) + (t method)) + (prog1 + (process-request headers-in content-stream method + url-string server-protocol) + ;; always turn chunking off at this point + (when (or (server-input-chunking-p server) + (server-output-chunking-p server)) + (setf (chunked-stream-output-chunking-p + (flexi-stream-stream *hunchentoot-stream*)) nil + (chunked-stream-input-chunking-p + (flexi-stream-stream *hunchentoot-stream*)) nil)) + (force-output* *hunchentoot-stream*)) + ;; continue until we have to close + ;; the stream + (not *close-hunchentoot-stream*)) + (return))))) + (ignore-errors (force-output* *hunchentoot-stream*)))) + (when *hunchentoot-stream* + (ignore-errors (close *hunchentoot-stream* :abort t))) + (ignore-errors + (with-lock ((server-lock server)) + ;; remove this worker from the list of all workers + (setf (server-workers server) + (delete *current-process* (server-workers server)))))))))) + +(defun process-request (headers-in content-stream method url-string server-protocol) + "This function is called by PROCESS-CONNECTION after the incoming +headers have been read. It sets up the REQUEST and REPLY objects, +dispatches to a handler, and finally sends the output to the client +using START-OUTPUT. If all goes as planned, the function returns T." + (let (*tmp-files* *headers-sent*) + (unwind-protect + (progn + (when (server-input-chunking-p *server*) + (let ((transfer-encodings (cdr (assoc :transfer-encoding headers-in)))) + (when transfer-encodings + (setq transfer-encodings + (split "\\s*,\\*" transfer-encodings))) + (when (member "chunked" transfer-encodings :test #'equalp) + ;; turn chunking on before we read the request body + (setf (chunked-stream-input-chunking-p + (flexi-stream-stream *hunchentoot-stream*)) t)))) + (let* ((*session* nil) + ;; first create a REPLY object so we can immediately start + ;; logging \(in case we're logging to mod_lisp) + (*reply* (make-instance 'reply)) + (*request* (make-instance 'request + :headers-in headers-in + :content-stream content-stream + :method method + :uri url-string + :server-protocol server-protocol)) + (*dispatch-table* (or (server-dispatch-table *server*) + (funcall *meta-dispatcher* *server*))) + backtrace) + (multiple-value-bind (body error) + (catch 'handler-done + (handler-bind ((error + (lambda (cond) + ;; only generate backtrace if needed + (setq backtrace + (and (or (and *show-lisp-errors-p* + *show-lisp-backtraces-p*) + (and *log-lisp-errors-p* + *log-lisp-backtraces-p*)) + (get-backtrace cond))) + (when *log-lisp-errors-p* + (log-message *lisp-errors-log-level* + "~A~:[~*~;~%~A~]" + cond + *log-lisp-backtraces-p* + backtrace)) + ;; if the headers were already sent + ;; the error happens within the body + ;; and we have to close the stream + (when *headers-sent* + (setq *close-hunchentoot-stream* t)) + (throw 'handler-done + (values nil cond)))) + (warning + (lambda (cond) + (when *log-lisp-warnings-p* + (log-message *lisp-warnings-log-level* + "~A~:[~*~;~%~A~]" + cond + *log-lisp-backtraces-p* + backtrace))))) + (with-debugger + ;; skip dispatch if bad request + (when (eq (return-code) +http-ok+) + ;; now do the work + (dispatch-request *dispatch-table*))))) + (when error + (setf (return-code *reply*) + +http-internal-server-error+)) + (start-output (cond ((and error *show-lisp-errors-p*) + (format nil "
~A~:[~*~;~%~%~A~]
" + (escape-for-html (format nil "~A" error)) + *show-lisp-backtraces-p* + (escape-for-html (format nil "~A" backtrace)))) + (error + "An error has occured") + (t body)))) + t)) + (dolist (path *tmp-files*) + (when (and (pathnamep path) (probe-file path)) + (ignore-errors (delete-file path))))))) Added: branches/trunk-reorg/thirdparty/hunchentoot-0.15.0/session.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/hunchentoot-0.15.0/session.lisp Thu Feb 7 03:16:29 2008 @@ -0,0 +1,286 @@ +;;; -*- Mode: LISP; Syntax: COMMON-LISP; Package: HUNCHENTOOT; Base: 10 -*- +;;; $Header: /usr/local/cvsrep/hunchentoot/session.lisp,v 1.11 2007/06/04 19:24:12 edi Exp $ + +;;; Copyright (c) 2004-2007, Dr. Edmund Weitz. All rights reserved. + +;;; Redistribution and use in source and binary forms, with or without +;;; modification, are permitted provided that the following conditions +;;; are met: + +;;; * Redistributions of source code must retain the above copyright +;;; notice, this list of conditions and the following disclaimer. + +;;; * Redistributions in binary form must reproduce the above +;;; copyright notice, this list of conditions and the following +;;; disclaimer in the documentation and/or other materials +;;; provided with the distribution. + +;;; THIS SOFTWARE IS PROVIDED BY THE AUTHOR 'AS IS' AND ANY EXPRESSED +;;; OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +;;; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +;;; ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +;;; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +;;; DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +;;; GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +;;; INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +;;; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +;;; NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +;;; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +(in-package :hunchentoot) + +(let ((session-id-counter 0)) + (defun get-next-session-id () + "Returns the next sequential session id." + (incf session-id-counter))) + +(let ((global-session-usage-counter 0)) + (defun count-session-usage () + "Counts session usage globally and triggers session gc if necessary." + (when (and *session-gc-frequency* + (zerop (mod (incf global-session-usage-counter) + *session-gc-frequency*))) + (session-gc)))) + + +(defclass session () + ((session-id :initform (get-next-session-id) + :reader session-id + :type integer + :documentation "The unique ID \(an INTEGER) of the session.") + (session-string :reader session-string + :documentation "The session strings encodes enough +data to safely retrieve this session. It is sent to the browser as a +cookie value or as a GET parameter.") + (user-agent :initform (user-agent *request*) + :reader session-user-agent + :documentation "The incoming 'User-Agent' header that +was sent when this session was created.") + (remote-addr :initform (real-remote-addr *request*) + :reader session-remote-addr + :documentation "The remote IP address of the client when +this sessions was started as returned by REAL-REMOTE-ADDR.") + (session-start :initform (get-universal-time) + :reader session-start + :documentation "The time this session was started.") + (last-click :initform (get-universal-time) + :reader session-last-click + :documentation "The last time this session was used.") + (session-data :initarg :session-data + :initform nil + :reader session-data + :documentation "Data associated with this session - +see SESSION-VALUE.") + (session-counter :initform 0 + :reader session-counter + :documentation "The number of times this session +has been used.") + (max-time :initarg :max-time + :initform *session-max-time* + :accessor session-max-time + :type fixnum + :documentation "The time \(in seconds) after which this +session expires if it's not used.")) + (:documentation "SESSION objects are automatically maintained +by Hunchentoot. They should not be created explicitly with +MAKE-INSTANCE but implicitly with START-SESSION. Note that +SESSION objects can only be created when the special variable +*REQUEST* is bound to a REQUEST object.")) + +(defun encode-session-string (id user-agent remote-addr start) + "Create a uniquely encoded session string based on the values ID, +USER-AGENT, REMOTE-ADDR, and START" + ;; *SESSION-SECRET* is used twice due to known theoretical + ;; vulnerabilities of MD5 encoding + (md5-hex (concatenate 'string + *session-secret* + (md5-hex (format nil "~A~A~@[~A~]~@[~A~]~A" + *session-secret* + id + (and *use-user-agent-for-sessions* + user-agent) + (and *use-remote-addr-for-sessions* + remote-addr) + start))))) + +(defun stringify-session (session) + "Creates a string representing the SESSION object SESSION. See +ENCODE-SESSION-STRING." + (encode-session-string (session-id session) + (session-user-agent session) + (session-remote-addr session) + (session-start session))) + +(defmethod initialize-instance :after ((session session) &rest init-args) + "Set SESSION-STRING slot after the session has been initialized." + (declare (ignore init-args)) + (setf (slot-value session 'session-string) (stringify-session session))) + +(defun session-gc () + "Removes sessions from *session-data* which are too old - see +SESSION-TOO-OLD-P." + (with-lock (*session-data-lock*) + (setq *session-data* + (loop for id-session-pair in *session-data* + for (nil . session) = id-session-pair + when (session-too-old-p session) + do (funcall *session-removal-hook* session) + else + collect id-session-pair))) + (values)) + +(defun session-value (symbol &optional (session *session*)) + "Returns the value associated with SYMBOL from the session object +SESSION \(the default is the current session) if it exists." + (when session + (let ((found (assoc symbol (session-data session)))) + (values (cdr found) found)))) + +(defsetf session-value (symbol &optional session) + (new-value) + "Sets the value associated with SYMBOL from the session object +SESSION. If there is already a value associated with SYMBOL it will be +replaced. Will automatically start a session if none was supplied and +there's no session for the current request." + (with-rebinding (symbol) + (with-unique-names (place %session) + `(with-lock (*session-data-lock*) + (let* ((,%session (or ,session (start-session))) + (,place (assoc ,symbol (session-data ,%session)))) + (cond + (,place + (setf (cdr ,place) ,new-value)) + (t + (push (cons ,symbol ,new-value) + (slot-value ,%session 'session-data)) + ,new-value))))))) + +(defun delete-session-value (symbol &optional (session *session*)) + "Removes the value associated with SYMBOL from the current session +object if there is one." + (when session + (setf (slot-value session 'session-data) + (delete symbol (session-data session) + :key #'car :test #'eq))) + (values)) + +(defun session-cookie-value (&optional (session (session *request*))) + "Returns a string which can be used to safely restore the +session if as session has already been established. This is used +as the value stored in the session cookie or in the corresponding +GET parameter." + (and session + (format nil + "~A:~A" + (session-id session) + (session-string session)))) + +(defun start-session () + "Returns the current SESSION object. If there is no current session, +creates one and updates the corresponding data structures. In this +case the function will also send a session cookie to the browser." + (count-session-usage) + (let ((session (session *request*))) + (when session + (return-from start-session session)) + (setf session (make-instance 'session) + (session *request*) session) + (with-lock (*session-data-lock*) + (setq *session-data* (acons (session-id session) session *session-data*))) + (set-cookie *session-cookie-name* + :value (session-cookie-value session) + :path "/") + (setq *session* session))) + +(defun remove-session (session) + "Completely removes the SESSION object SESSION from Hunchentoot's +internal session database." + (with-lock (*session-data-lock*) + (funcall *session-removal-hook* session) + (setq *session-data* + (delete (session-id session) *session-data* + :key #'car :test #'=))) + (values)) + +(defun session-too-old-p (session) + "Returns true if the SESSION object SESSION has not been active in +the last \(SESSION-MAX-TIME SESSION) seconds." + (< (+ (session-last-click session) (session-max-time session)) + (get-universal-time))) + +(defun get-stored-session (id) + "Returns the SESSION object corresponding to the number ID if the +session has not expired. Will remove the session if it has expired but +will not create a new one." + (let ((session + (cdr (assoc id *session-data* :test #'=)))) + (when (and session + (session-too-old-p session)) + (when *reply* + (log-message :notice "Session with ID ~A too old" id)) + (remove-session session) + (setq session nil)) + session)) + +(defun session-verify (request) + "Tries to get a session identifier from the cookies \(or +alternatively from the GET parameters) sent by the client. This +identifier is then checked for validity against the REQUEST object +REQUEST. On success the corresponding session object \(if not too old) +is returned \(and updated). Otherwise NIL is returned." + (let ((session-identifier (or (cookie-in *session-cookie-name* request) + (get-parameter *session-cookie-name* request)))) + (unless (and session-identifier + (stringp session-identifier) + (plusp (length session-identifier))) + (return-from session-verify nil)) + (destructuring-bind (id-string session-string) + (split ":" session-identifier :limit 2) + (let* ((id (and (scan "^\\d+$" id-string) + (parse-integer id-string + :junk-allowed t))) + (session (and id + (get-stored-session id))) + (user-agent (user-agent request)) + (remote-addr (remote-addr request))) + (unless (and session + session-string + (string= session-string + (session-string session)) + (string= session-string + (encode-session-string id + user-agent + (real-remote-addr request) + (session-start session)))) + (when *reply* + (cond ((null session) + (log-message :notice "No session for session identifier '~A' (User-Agent: '~A', IP: '~A')" + session-identifier user-agent remote-addr)) + (t + (log-message :warning "Fake session identifier '~A' (User-Agent: '~A', IP: '~A')" + session-identifier user-agent remote-addr)))) + (when session + (remove-session session)) + (return-from session-verify nil)) + (incf (slot-value session 'session-counter)) + (setf (slot-value session 'last-click) (get-universal-time)) + session)))) + +(defun reset-sessions () + "Removes ALL stored sessions and creates a new session secret." + (reset-session-secret) + (with-lock (*session-data-lock*) + (loop for (nil . session) in *session-data* + do (funcall *session-removal-hook* session)) + (setq *session-data* nil)) + (values)) + +(defmacro do-sessions ((var &optional result-form) &body body) + "Executes BODY with VAR bound to each existing SESSION object +consecutively. Returns the values returned by RESULT-FORM unless +RETURN is executed. The scope of the binding of VAR does not include +RESULT-FORM." + (let ((=temp= (gensym))) + `(dolist (,=temp= *session-data* ,result-form) + (let ((,var (cdr ,=temp=))) + , at body)))) \ No newline at end of file Added: branches/trunk-reorg/thirdparty/hunchentoot-0.15.0/specials.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/hunchentoot-0.15.0/specials.lisp Thu Feb 7 03:16:29 2008 @@ -0,0 +1,385 @@ +;;; -*- Mode: LISP; Syntax: COMMON-LISP; Package: HUNCHENTOOT; Base: 10 -*- +;;; $Header: /usr/local/cvsrep/hunchentoot/specials.lisp,v 1.31 2007/11/08 20:07:58 edi Exp $ + +;;; Copyright (c) 2004-2007, Dr. Edmund Weitz. All rights reserved. + +;;; Redistribution and use in source and binary forms, with or without +;;; modification, are permitted provided that the following conditions +;;; are met: + +;;; * Redistributions of source code must retain the above copyright +;;; notice, this list of conditions and the following disclaimer. + +;;; * Redistributions in binary form must reproduce the above +;;; copyright notice, this list of conditions and the following +;;; disclaimer in the documentation and/or other materials +;;; provided with the distribution. + +;;; THIS SOFTWARE IS PROVIDED BY THE AUTHOR 'AS IS' AND ANY EXPRESSED +;;; OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +;;; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +;;; ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +;;; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +;;; DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +;;; GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +;;; INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +;;; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +;;; NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +;;; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +(in-package :hunchentoot) + +(eval-when (:compile-toplevel :execute :load-toplevel) + (defmacro defvar-unbound (name &optional (doc-string "")) + "Convenience macro to declare unbound special variables with a +documentation string." + `(progn + (defvar ,name) + (setf (documentation ',name 'variable) ,doc-string))) + + (defvar *http-reason-phrase-map* (make-hash-table) + "Used to map numerical return codes to reason phrases.") + + (defmacro def-http-return-code (name value reason-phrase) + "Shortcut to define constants for return codes. NAME is a +Lisp symbol, VALUE is the numerical value of the return code, and +REASON-PHRASE is the phrase \(a string) to be shown in the +server's status line." + `(eval-when (:compile-toplevel :execute :load-toplevel) + (defconstant ,name ,value ,(format nil "HTTP return code \(~A) for '~A'." + value reason-phrase)) + (setf (gethash ,value *http-reason-phrase-map*) ,reason-phrase)))) + +(defconstant +crlf+ #.(format nil "~C~C" #\Return #\Linefeed) + "A constant string consisting of the two ASCII characters CR and LF.") + +(def-http-return-code +http-continue+ 100 "Continue") +(def-http-return-code +http-switching-protocols+ 101 "Switching Protocols") +(def-http-return-code +http-ok+ 200 "OK") +(def-http-return-code +http-created+ 201 "Created") +(def-http-return-code +http-accepted+ 202 "Accepted") +(def-http-return-code +http-non-authoritative-information+ 203 "Non-Authoritative Information") +(def-http-return-code +http-no-content+ 204 "No Content") +(def-http-return-code +http-reset-content+ 205 "Reset Content") +(def-http-return-code +http-partial-content+ 206 "Partial Content") +(def-http-return-code +http-multi-status+ 207 "Multi-Status") +(def-http-return-code +http-multiple-choices+ 300 "Multiple Choices") +(def-http-return-code +http-moved-permanently+ 301 "Moved Permanently") +(def-http-return-code +http-moved-temporarily+ 302 "Moved Temporarily") +(def-http-return-code +http-see-other+ 303 "See Other") +(def-http-return-code +http-not-modified+ 304 "Not Modified") +(def-http-return-code +http-use-proxy+ 305 "Use Proxy") +(def-http-return-code +http-temporary-redirect+ 307 "Temporary Redirect") +(def-http-return-code +http-bad-request+ 400 "Bad Request") +(def-http-return-code +http-authorization-required+ 401 "Authorization Required") +(def-http-return-code +http-payment-required+ 402 "Payment Required") +(def-http-return-code +http-forbidden+ 403 "Forbidden") +(def-http-return-code +http-not-found+ 404 "Not Found") +(def-http-return-code +http-method-not-allowed+ 405 "Method Not Allowed") +(def-http-return-code +http-not-acceptable+ 406 "Not Acceptable") +(def-http-return-code +http-proxy-authentication-required+ 407 "Proxy Authentication Required") +(def-http-return-code +http-request-time-out+ 408 "Request Time-out") +(def-http-return-code +http-conflict+ 409 "Conflict") +(def-http-return-code +http-gone+ 410 "Gone") +(def-http-return-code +http-length-required+ 411 "Length Required") +(def-http-return-code +http-precondition-failed+ 412 "Precondition Failed") +(def-http-return-code +http-request-entity-too-large+ 413 "Request Entity Too Large") +(def-http-return-code +http-request-uri-too-large+ 414 "Request-URI Too Large") +(def-http-return-code +http-unsupported-media-type+ 415 "Unsupported Media Type") +(def-http-return-code +http-requested-range-not-satisfiable+ 416 "Requested range not satisfiable") +(def-http-return-code +http-expectation-failed+ 417 "Expectation Failed") +(def-http-return-code +http-failed-dependency+ 424 "Failed Dependency") +(def-http-return-code +http-internal-server-error+ 500 "Internal Server Error") +(def-http-return-code +http-not-implemented+ 501 "Not Implemented") +(def-http-return-code +http-bad-gateway+ 502 "Bad Gateway") +(def-http-return-code +http-service-unavailable+ 503 "Service Unavailable") +(def-http-return-code +http-gateway-time-out+ 504 "Gateway Time-out") +(def-http-return-code +http-version-not-supported+ 505 "Version not supported") + +(defvar *approved-return-codes* '(#.+http-ok+ #.+http-no-content+ + #.+http-multi-status+ + #.+http-not-modified+) + "A list of return codes the server should not treat as an error - +see *HANDLE-HTTP-ERRORS-P*.") + +(defconstant +day-names+ + #("Mon" "Tue" "Wed" "Thu" "Fri" "Sat" "Sun") + "The three-character names of the seven days of the week - needed +for cookie date format.") + +(defconstant +month-names+ + #("Jan" "Feb" "Mar" "Apr" "May" "Jun" "Jul" "Aug" "Sep" "Oct" "Nov" "Dec") + "The three-character names of the twelve months - needed for cookie +date format.") + +(defvar *session-cookie-name* "hunchentoot-session" + "The name of the cookie \(or the GET parameter) which is used to +store the session on the client side.") + +(defvar *rewrite-for-session-urls* t + "Whether HTML pages should possibly be rewritten for cookie-less +session-management.") + +(defvar *content-types-for-url-rewrite* + '("text/html" "application/xhtml+xml") + "The content types for which url-rewriting is OK. See +*REWRITE-FOR-SESSION-URLS*.") + +(defparameter *the-random-state* (make-random-state t) + "A fresh random state.") + +(defvar-unbound *session-secret* + "A random value that's used to encode the public session data.") + +(defvar-unbound *hunchentoot-stream* + "The stream representing the socket Hunchentoot is listening on.") + +(defvar *close-hunchentoot-stream* nil + "Will be set to T if the Hunchentoot socket stream has to be +closed at the end of the request.") + +(defvar *headers-sent* nil + "Used internally to check whether the reply headers have +already been sent for this request.") + +(defvar *file-upload-hook* nil + "If this is not NIL, it should be a unary function which will +be called with a pathname for each file which is uploaded to +Hunchentoot. The pathname denotes the temporary file to which +the uploaded file is written. The hook is called directly before +the file is created.") + +(defvar *session-data* nil + "All sessions of all users currently using Hunchentoot. An +alist where the car is the session's ID and the cdr is the +SESSION object itself.") + +(defvar *session-max-time* #.(* 30 60) + "The default time \(in seconds) after which a session times out.") + +(defvar *session-gc-frequency* 50 + "A session GC \(see function SESSION-GC) will happen every +*SESSION-GC-FREQUENCY* requests \(counting only requests which +use a session) if this variable is not NIL.") + +(defvar *use-user-agent-for-sessions* t + "Whether the 'User-Agent' header should be encoded into the session +string. If this value is true, a session will cease to be accessible +if the client sends a different 'User-Agent' header.") + +(defvar *use-remote-addr-for-sessions* nil + "Whether the client's remote IP \(as returned by REAL-REMOTE-ADDR) +should be encoded into the session string. If this value is true, a +session will cease to be accessible if the client's remote IP changes. + +This might for example be an issue if the client uses a proxy server +which doesn't send correct 'X_FORWARDED_FOR' headers.") + +(defvar *default-content-type* "text/html; charset=iso-8859-1" + "The default content-type header which is returned to the client.") + +(defvar *methods-for-post-parameters* '(:post) + "A list of the request method types \(as keywords) for which +Hunchentoot will try to compute POST-PARAMETERS.") + +(defvar *header-stream* nil + "If this variable is not NIL, it should be bound to a stream to +which incoming and outgoing headers will be written for debugging +purposes.") + +(defvar *show-lisp-errors-p* nil + "Whether Lisp errors should be shown in HTML output.") + +(defvar *show-lisp-backtraces-p* nil + "Whether Lisp backtraces should be shown in HTML output when an +error occurs. Will only have an effect if *SHOW-LISP-ERRORS-P* is +also true.") + +(defvar *log-lisp-errors-p* t + "Whether Lisp errors should be logged.") + +(defvar *log-lisp-warnings-p* t + "Whether Lisp warnings should be logged.") + +(defvar *log-lisp-backtraces-p* nil + "Whether Lisp backtraces should be logged when an error or warning +occurs. Will only have an effect if *LOG-LISP-ERRORS-P* or +*LOG-LISP-BACKTRACES* are also true.") + +(defvar *lisp-errors-log-level* :error + "Log level for Lisp errors.") + +(defvar *lisp-warnings-log-level* :warning + "Log level for Lisp warnings.") + +(defvar *show-access-log-messages* t + "Whether routine messages about each request should be logged. This +will only be done if SERVER-USE-APACHE-LOG-P is NIL.") + +(defvar *log-file* + (load-time-value + (let ((tmp-dir + #+:allegro (system:temporary-directory) + #+:lispworks (pathname (or (lw:environment-variable "TEMP") + (lw:environment-variable "TMP") + #+:win32 "C:/" + #-:win32 "/tmp/")) + #-(or :allegro :lispworks) #p"/tmp/")) + (merge-pathnames "hunchentoot.log" tmp-dir))) + "The log file to use \(unless the Apache log is used).") + +(defvar *log-file-stream* nil + "The stream corresponding to the log file.") + +(defvar *log-file-lock* (make-lock "log-file-lock") + "A lock to prevent two threads from writing to the log file at +same time.") + +(defvar-unbound *session* + "The current SESSION object.") + +(defvar-unbound *request* + "The current REQUEST object.") + +(defvar-unbound *reply* + "The current REPLY object.") + +(defvar *log-prefix* t + "The prefix which is printed in front of Apache log +messages. This should be a string or T \(for \"Hunchentoot\", the +default) or NIL \(meaning no prefix).") + +(defconstant +implementation-link+ + #+:cmu "http://www.cons.org/cmucl/" + #+:sbcl "http://www.sbcl.org/" + #+:allegro "http://www.franz.com/products/allegrocl/" + #+:lispworks "http://www.lispworks.com/" + #+:openmcl "http://openmcl.clozure.com/" + "A link to the website of the underlying Lisp implementation.") + +(defvar *dispatch-table* (list 'default-dispatcher) + "A list of dispatch functions - see *META-DISPATCHER*.") + +(defvar *default-handler* 'default-handler + "The name of the function which is always returned by +DEFAULT-DISPATCHER.") + +(defvar *easy-handler-alist* nil + "An alist of \(URI server-names function) lists defined by +DEFINE-EASY-HANDLER.") + +(defvar *http-error-handler* nil + "Contains NIL \(the default) or a function of one argument which is +called if the content handler has set a return code which is not in +*APPROVED-RETURN-CODES* and *HANDLE-HTTP-ERRORS* is true.") + +(defvar *handle-http-errors-p* t + "A generalized boolean that determines whether return codes which +are not in *APPROVED-HEADERS* are treated specially. When its value +is true \(the default), either a default body for the return code or +the result of calling *HTTP-ERROR-HANDLER* is used. When the value is +NIL, no special action is taken and you are expected to supply your +own response body to describe the error.") + +(defvar *default-log-level* nil + "The default log level for LOG-MESSAGE*.") + +(defvar *session-data-lock* (make-lock "session-data-lock") + "A lock to prevent two threads from modifying *SESSION-DATA* at the +same time.") + +(defvar *session-removal-hook* (constantly nil) + "A function of one argument \(a session object) which is called +whenever a session is garbage-collected.") + +(defvar *tmp-directory* + #+(or :win32 :mswindows) "c:\\hunchentoot-temp\\" + #-(or :win32 :mswindows) "/tmp/hunchentoot/" + "Directory for temporary files created by MAKE-TMP-FILE-NAME.") + +(defvar *tmp-files* nil + "A list of temporary files created while a request was handled.") + +(defconstant +latin-1+ + (make-external-format :latin1 :eol-style :lf) + "A FLEXI-STREAMS external format used for `faithful' input and +output of binary data.") + +(defconstant +utf-8+ + (make-external-format :utf8 :eol-style :lf) + "A FLEXI-STREAMS external format used internally for logging and to +encode cookie values.") + +(defvar *hunchentoot-default-external-format* +latin-1+ + "The external format used to compute the REQUEST object.") + +(defconstant +buffer-length+ 8192 + "Length of buffers used for internal purposes.") + +(defvar-unbound *server* + "During the execution of dispatchers and handlers this variable +is bound to the SERVER object which processes the request.") + +(defvar *meta-dispatcher* (lambda (server) + (declare (ignore server)) + *dispatch-table*) + "The value of this variable should be a function of one argument. +It is called with the current Hunchentoot server instance \(unless the +server has its own dispatch table) and must return a suitable dispatch +table. The initial value is a function which always unconditionally +returns *DISPATCH-TABLE*.") + +(defvar *server-counter* 0 + "Internal counter used to generate meaningful names for +listener threads.") + +(defvar *worker-counter* 0 + "Internal counter used to generate meaningful names for worker +threads.") + +(defvar *default-read-timeout* 20 + "The default read-timeout used when a Hunchentoot server is +reading from a socket stream.") + +(defvar *default-write-timeout* 20 + "The default write-timeout used when a Hunchentoot server is +writing to a socket stream.") + +(defvar *force-output-timeout* 30 + "The maximal time Hunchentoot waits for FORCE-OUTPUT to +return.") + +(defvar *cleanup-interval* 100 + "Should be NIL or a positive integer. The system calls +*CLEANUP-FUNCTION* whenever *CLEANUP-INTERVAL* new worker threads have +been created unless the value is NIL.") + +(defvar *cleanup-function* 'cleanup-function + "The function which is called if *CLEANUP-INTERVAL* is not NIL.") + +(defvar-unbound *local-host* + "Bound to a string denoting the address at which the current +request arrived.") + +(defvar-unbound *remote-host* + "Bound to a string denoting the address the current request +originated from.") + +(defvar-unbound *remote-port* + "Bound to an integer denoting the port the current request +originated from.") + +(pushnew :hunchentoot *features*) + +;; stuff for Nikodemus Siivola's HYPERDOC +;; see +;; and + +(defvar *hyperdoc-base-uri* "http://weitz.de/hunchentoot/") + +(let ((exported-symbols-alist + (loop for symbol being the external-symbols of :hunchentoot + collect (cons symbol (concatenate 'string "#" (string-downcase symbol)))))) + (defun hyperdoc-lookup (symbol type) + (declare (ignore type)) + (cdr (assoc symbol exported-symbols-alist :test #'eq)))) Added: branches/trunk-reorg/thirdparty/hunchentoot-0.15.0/test/UTF-8-demo.html ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/hunchentoot-0.15.0/test/UTF-8-demo.html Thu Feb 7 03:16:29 2008 @@ -0,0 +1,213 @@ + + + UTF-8 test file + +

Original by Markus Kuhn, adapted for HTML by Martin Dürst.

+
+UTF-8 encoded sample plain-text file
+????????????????????????????????????????????????????????????????????????????????????????????????????????????
+
+Markus Kuhn [??ma??k??s ku??n] <mkuhn at acm.org> ??? 1999-08-20
+
+
+The ASCII compatible UTF-8 encoding of ISO 10646 and Unicode
+plain-text files is defined in RFC 2279 and in ISO 10646-1 Annex R.
+
+
+Using Unicode/UTF-8, you can write in emails and source code things such as
+
+Mathematics and Sciences:
+
+  ??? E???da = Q,  n ??? ???, ??? f(i) = ??? g(i), ???x??????: ???x??? = ?????????x???, ?? ??? ???? = ??(???? ??? ??),
+
+  ??? ??? ?????? ??? ??? ??? ??? ??? ??? ??? ???, ??? < a ??? b ??? c ??? d ??? ??? ??? (A ??? B),
+
+  2H??? + O??? ??? 2H???O, R = 4.7 k??, ??? 200 mm
+
+Linguistics and dictionaries:
+
+  ??i ??nt????n??????n??l f????n??t??k ??so??si??e????n
+  Y [????psil??n], Yen [j??n], Yoga [??jo??g??]
+
+APL:
+
+  ((V???V)=??????V)/V???,V    ????????????????????????????????????
+
+Nicer typography in plain text files:
+
+  ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
+  ???                                          ???
+  ???   ??? ???single??? and ???double??? quotes         ???
+  ???                                          ???
+  ???   ??? Curly apostrophes: ???We???ve been here??? ???
+  ???                                          ???
+  ???   ??? Latin-1 apostrophe and accents: '??`  ???
+  ???                                          ???
+  ???   ??? ???deutsche??? ???Anf??hrungszeichen???       ???
+  ???                                          ???
+  ???   ??? ???, ???, ???, ???, 3???4, ???, ???5/+5, ???, ???      ???
+  ???                                          ???
+  ???   ??? ASCII safety test: 1lI|, 0OD, 8B     ???
+  ???                      ?????????????????????????????????         ???
+  ???   ??? the euro symbol: ??? 14.95 ??? ???         ???
+  ???                      ?????????????????????????????????         ???
+  ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
+
+Greek (in Polytonic):
+
+  The Greek anthem:
+
+  ????? ??????????????? ???????? ??????? ?????????
+  ??????? ??????????????? ??????? ???????????????,
+  ????? ??????????????? ???????? ??????? ???????
+  ??????? ????? ??????? ??????????????? ????? ?????.
+
+  ?????????? ????? ??????????????? ?????????????????
+  ??????? ?????????????????? ????? ??????????
+  ??????? ??????? ??????????? ????????????????????????
+  ???????????, ??? ???????????, ??????????????????????!
+
+  From a speech of Demosthenes in the 4th century BC:
+
+  ?????????? ???????????? ?????????????????????? ?????? ?????????????????????, ??? ????????????? ????????????????????,
+  ????????? ????? ??????? ????? ????????????????? ?????????????????? ??????? ????????? ????????? ?????????
+  ????????????? ??????? ?????????????? ????????? ??????? ??????? ????????????? ????????? ???????
+  ????????????????????????? ????????????????? ???????? ???????????????????????, ????? ????? ?????????????????? 
+  ??????? ??????????? ???????????????????,  ?????????? ????????? ????? ???????????????????? ????????????
+  ????????????????? ??????????? ??????????????????? ?????????. ???????????? ??????? ????????? ?????? ?????????????????
+  ????? ????? ??????????????? ????????????????? ??? ??????? ??????????????????, ????????? ????? ???????????????????????,
+  ?????????? ??????? ??????????? ??????????????????????? ?????????? ??????????????????????. ???????? ?????, ??????? ???????
+  ????????? ?????????? ????? ??????????? ??????? ????? ???????????? ??????????? ???????????????? ??????? ?????????????????
+  ?????????????????????????, ??????? ?????????? ???????????????? ??????????? ???????? ?????????? ???????, ????? ???????????
+  ??????????????? ???????????? ???????????????????? ??????? ????????????? ??????????????????? ???????????? ??????????????
+  ??????????????????? ?????????? ??????????? ??????? ?????????????, ????????? ????????? ???????????????????
+  ???????????????. ???????? ??????? ??????????? ??????????????? ???????????????, ????????? ??????? ????????? ???????
+  ????????? ???????????????????????? ?????? ??????? ????? ????????????? ???????????????? ????????????????? ????????? ?????
+  ??????? ???????????? ???????????? ????????????????????, ??????????????? ???????????????? ????????? ???????
+  ????????????????? ?????????????????? ??????????????????? ???????????.
+
+  ???????????????????????, ????? ????????????????????????
+
+Georgian:
+
+  From a Unicode conference invitation:
+
+  ?????????????????? ?????????????????? ????????????????????? ????????????????????????????????? Unicode-?????? ??????????????? ????????????????????????????????????
+  ??????????????????????????????????????? ?????????????????????????????????, ????????????????????? ?????????????????????????????? 10-12 ???????????????,
+  ???. ?????????????????????, ??????????????????????????????. ????????????????????????????????? ???????????????????????? ??????????????? ????????????????????????
+  ?????????????????????????????? ???????????? ???????????????????????? ??????????????????????????? ??????????????????????????? ?????? Unicode-???,
+  ????????????????????????????????????????????????????????? ?????? ?????????????????????????????????, Unicode-?????? ??????????????????????????????
+  ??????????????????????????? ??????????????????????????????, ?????? ????????????????????????????????? ?????????????????????????????????, ???????????????????????????,
+  ??????????????????????????? ???????????????????????????????????? ?????? ???????????????????????????????????? ????????????????????????????????? ??????????????????????????????.
+
+Russian:
+
+  From a Unicode conference invitation:
+
+  ?????????????????????????????????? ???????????? ???? ?????????????? ?????????????????????????? ?????????????????????? ????
+  Unicode, ?????????????? ?????????????????? 10-12 ?????????? 1997 ???????? ?? ???????????? ?? ????????????????.
+  ?????????????????????? ?????????????? ?????????????? ???????? ?????????????????? ????  ???????????????? ??????????????????????
+  ?????????????????? ?? Unicode, ?????????????????????? ?? ??????????????????????????????????????, ???????????????????? ??
+  ???????????????????? Unicode ?? ?????????????????? ???????????????????????? ???????????????? ?? ??????????????????????
+  ??????????????????????, ??????????????, ?????????????? ?? ???????????????????????? ???????????????????????? ????????????????.
+
+Thai (UCS Level 2):
+
+  Excerpt from a poetry on The Romance of The Three Kingdoms (a Chinese
+  classic 'San Gua'):
+
+  [----------------------------|------------------------]
+    ??? ??????????????????????????????????????????????????????????????????????????????????????????  ???????????????????????????????????????????????????????????????????????????
+  ???????????????????????????????????????????????????????????????????????????????????????       ??????????????????????????????????????????????????????????????????????????????
+    ???????????????????????????????????????????????????????????????????????????           ????????????????????????????????????????????????????????????????????????????????????
+  ????????????????????????????????????????????????????????????????????????????????????         ?????????????????????????????????????????????????????????????????????
+    ???????????????????????????????????????????????????????????????????????????      ?????????????????????????????????????????????????????????????????????
+  ??????????????????????????????????????????????????????????????????????????????          ?????????????????????????????????????????????????????????????????????????????????
+    ???????????????????????????????????????????????????????????????????????????          ??????????????????????????????????????????????????????????????????????????????
+  ??????????????????????????????????????????????????????????????????           ????????????????????????????????????????????????????????????????????? ???
+
+  (The above is a two-column text. If combining characters are handled
+  correctly, the lines of the second column should be aligned with the
+  | character above.)
+
+Ethiopian:
+
+  Proverbs in the Amharic language:
+
+  ????????? ??????????????? ????????? ??????????????????
+  ?????? ????????? ?????????????????? ??????????????????
+  ?????? ???????????? ???????????? ?????????
+  ?????? ???????????? ?????? ???????????? ????????? ??????????????????
+  ????????? ???????????? ????????? ??????????????????
+  ????????? ????????? ?????? ????????????
+  ??????????????? ??????????????????
+  ?????? ???????????? ??????????????? ???????????? ???????????????
+  ?????? ???????????? ???????????? ????????????
+  ?????? ??????????????? ????????? ????????? ???????????? ????????????????????????
+  ???????????? ?????????????????? ????????? ??????????????? ??????????????????
+  ??????????????? ????????? ???????????? ????????? ???????????? ???????????????
+  ?????? ??????????????? ????????? ???????????????
+  ????????? ???????????? ???????????? ????????? ?????? ???????????????
+  ??????????????? ????????? ?????? ???????????? ????????? ????????????
+  ???????????? ????????? ???????????? ?????????
+  ???????????? ?????? ????????? ???????????? ??????????????????
+  ??????????????? ??????????????? ?????? ????????????
+
+Runes:
+
+  ?????? ???????????? ????????? ?????? ???????????? ?????? ????????? ??????????????? ????????????????????????????????? ????????? ?????? ????????????
+
+  (Old English, which transcribed into Latin reads 'He cwaeth that he
+  bude thaem lande northweardum with tha Westsae.' and means 'He said
+  that he lived in the northern land near the Western Sea.')
+
+Braille:
+
+  ???????????? ?????????  ????????????????????? ?????????
+
+  ??????????????? ????????? ??????????????? ?????? ???????????? ???????????? ????????? ?????? ?????? ????????????
+  ?????????????????? ???????????? ???????????? ?????? ?????????????????? ?????? ????????? ?????????????????? ?????????
+  ??????????????? ?????? ?????? ??????????????????????????? ?????? ??????????????? ?????? ???????????????????????????
+  ????????? ?????? ???????????? ?????????????????? ????????????????????? ??????????????? ????????? ?????????
+  ??????????????????????????? ???????????? ????????? ???????????? ???????????? ????????????????????? ????????? ?????????????????? ?????? 
+  ???????????? ?????? ????????? ????????? ???????????? ?????????
+
+  ????????? ??????????????? ????????? ?????? ???????????? ?????? ??? ??????????????????????????????
+
+  ???????????? ??? ??????????????? ???????????? ?????? ????????? ????????? ??? ???????????? ?????? ??????
+  ?????? ???????????????????????? ????????? ????????? ?????? ?????????????????????????????? ???????????? ????????????
+  ??? ?????????????????????????????? ??? ???????????? ???????????? ????????? ?????????????????? ????????????????????? ??????
+  ??????????????? ??? ?????????????????????????????? ?????? ?????? ?????????????????? ??????????????? ?????? ?????????????????????????????? 
+  ??? ?????? ?????????????????? ????????? ?????? ?????????????????? ?????? ?????? ???????????????????????? 
+  ?????? ??? ?????? ????????????????????? ????????? ?????? ???????????????????????? ???????????????
+  ???????????? ????????? ?????????????????? ????????? ?????? ?????? ???????????????????????? ???????????? ???????????? ??????
+  ???????????? ????????????????????? ??????????????? ?????? ?????? ????????????????????? ??????????????????????????????????????? ?????????
+  ??????????????? ????????? ?????? ???????????? ?????? ??? ??????????????????????????????
+
+  (The first couple of paragraphs of "A Christmas Carol" by Dickens)
+
+Compact font selection example text:
+
+  ABCDEFGHIJKLMNOPQRSTUVWXYZ /0123456789
+  abcdefghijklmnopqrstuvwxyz ??????????????????????
+  ???????????????????????????????????????????? ???????????????????? ????????????????????
+  ???????????????????????? ??????????????? ???????????????????????? ?????????????????????????????????????
+
+Greetings in various languages:
+
+  Hello world, ????????????????? ???????????, ???????????????
+
+Box drawing alignment tests:                                          ???
+                                                                      ???
+  ?????????????????????  ?????????????????????  ?????????????????????  ?????????????????????  ?????????????????????  ????????????   ???  ??? ????????? ?????????    ??? ?????????????????????
+  ?????????????????????  ?????????????????????  ?????????????????????  ?????????????????????  ?????????????????????  ????????????  ??????????????????????????? ?????????    ??? ?????????????????????
+  ????????? ?????????  ??????   ??????  ?????? ??? ??????  ?????? ??? ??????  ?????? ??? ??????  ????????????   ???  ??? ????????? ?????????    ??? ?????????????????????
+  ?????? ??? ??????  ??????   ??????  ?????????????????????  ?????????????????????  ?????????????????????  ????????????     ???????????? ??? ???????????? ??? ??? ?????????????????????
+  ????????? ?????????  ??????   ??????  ?????? ??? ??????  ?????? ??? ??????  ?????? ??? ??????  ???????????????????????? ???  ??? ??? ???  ??? ??? ???
+  ?????????????????????  ?????????????????????  ?????????????????????  ?????????????????????  ?????????????????????  ???????????????????????? ???  ??? ??? ???  ??? ??? ???
+  ?????????????????????  ?????????????????????  ?????????????????????  ?????????????????????  ?????????????????????           ???????????? ??? ???????????? ???  ????????????????????????
+
+
+ + Added: branches/trunk-reorg/thirdparty/hunchentoot-0.15.0/test/favicon.ico ============================================================================== Binary file. No diff available. Added: branches/trunk-reorg/thirdparty/hunchentoot-0.15.0/test/fz.jpg ============================================================================== Binary file. No diff available. Added: branches/trunk-reorg/thirdparty/hunchentoot-0.15.0/test/packages.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/hunchentoot-0.15.0/test/packages.lisp Thu Feb 7 03:16:29 2008 @@ -0,0 +1,37 @@ +;;; -*- Mode: LISP; Syntax: COMMON-LISP; Package: CL-USER; Base: 10 -*- +;;; $Header: /usr/local/cvsrep/hunchentoot/test/packages.lisp,v 1.4 2007/01/01 23:50:32 edi Exp $ + +;;; Copyright (c) 2004-2007, Dr. Edmund Weitz. All rights reserved. + +;;; Redistribution and use in source and binary forms, with or without +;;; modification, are permitted provided that the following conditions +;;; are met: + +;;; * Redistributions of source code must retain the above copyright +;;; notice, this list of conditions and the following disclaimer. + +;;; * Redistributions in binary form must reproduce the above +;;; copyright notice, this list of conditions and the following +;;; disclaimer in the documentation and/or other materials +;;; provided with the distribution. + +;;; THIS SOFTWARE IS PROVIDED BY THE AUTHOR 'AS IS' AND ANY EXPRESSED +;;; OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +;;; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +;;; ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +;;; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +;;; DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +;;; GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +;;; INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +;;; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +;;; NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +;;; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +(in-package :cl-user) + +(defpackage :hunchentoot-test + (:nicknames :tbnl-test) + (:use :cl :cl-who :hunchentoot)) + +(defpackage :hunchentoot-test-user + (:use :cl :hunchentoot)) \ No newline at end of file Added: branches/trunk-reorg/thirdparty/hunchentoot-0.15.0/test/test.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/hunchentoot-0.15.0/test/test.lisp Thu Feb 7 03:16:29 2008 @@ -0,0 +1,584 @@ +;;; -*- Mode: LISP; Syntax: COMMON-LISP; Package: HUNCHENTOOT; Base: 10 -*- +;;; $Header: /usr/local/cvsrep/hunchentoot/test/test.lisp,v 1.21 2007/12/29 17:35:05 edi Exp $ + +;;; Copyright (c) 2004-2007, Dr. Edmund Weitz. All rights reserved. + +;;; Redistribution and use in source and binary forms, with or without +;;; modification, are permitted provided that the following conditions +;;; are met: + +;;; * Redistributions of source code must retain the above copyright +;;; notice, this list of conditions and the following disclaimer. + +;;; * Redistributions in binary form must reproduce the above +;;; copyright notice, this list of conditions and the following +;;; disclaimer in the documentation and/or other materials +;;; provided with the distribution. + +;;; THIS SOFTWARE IS PROVIDED BY THE AUTHOR 'AS IS' AND ANY EXPRESSED +;;; OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +;;; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +;;; ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +;;; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +;;; DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +;;; GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +;;; INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +;;; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +;;; NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +;;; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +(in-package :hunchentoot-test) + +(defvar *this-file* (load-time-value + (or #.*compile-file-pathname* *load-pathname*))) + +(defmacro with-html (&body body) + `(with-html-output-to-string (*standard-output* nil :prologue t) + , at body)) + +(defun hunchentoot-link () + (with-html-output (*standard-output*) + (:a :href "http://weitz.de/hunchentoot/" "Hunchentoot"))) + +(defun menu-link () + (with-html-output (*standard-output*) + (:p (:hr + (:a :href "/hunchentoot/test" "Back to menu"))))) + +(defmacro with-lisp-output ((var) &body body) + `(let ((*package* (find-package :hunchentoot-test-user))) + (with-output-to-string (,var #+:lispworks nil + #+:lispworks :element-type + #+:lispworks 'lw:simple-char) + , at body))) + +(defmacro info-table (&rest forms) + (let ((=value= (gensym)) + (=first= (gensym))) + `(with-html-output (*standard-output*) + (:p (:table :border 1 :cellpadding 2 :cellspacing 0 + (:tr (:td :colspan 2 + "Some Information " + (hunchentoot-link) + " provides about this request:")) + ,@(loop for form in forms + collect `(:tr (:td :valign "top" + (:pre :style "padding: 0px" + (esc (with-lisp-output (s) (pprint ',form s))))) + (:td :valign "top" + (:pre :style "padding: 0px" + (esc (with-lisp-output (s) + (loop for ,=value= in (multiple-value-list ,form) + for ,=first= = t then nil + unless ,=first= + do (princ ", " s) + do (pprint ,=value= s)))))))))) + (menu-link)))) + +(defun authorization-page () + (multiple-value-bind (user password) + (authorization) + (cond ((and (equal user "nanook") + (equal password "igloo")) + (with-html + (:html + (:head (:title "Hunchentoot page with Basic Authentication")) + (:body + (:h2 (hunchentoot-link) + " page with Basic Authentication") + (info-table (header-in "Authorization") + (authorization)))))) + (t + (require-authorization))))) + +(defparameter *test-image* + (load-time-value + (with-open-file (in (make-pathname :name "fz" :type "jpg" :version nil + :defaults *this-file*) + :element-type 'flex:octet) + (let ((image-data (make-array (file-length in) + :element-type 'flex:octet))) + (read-sequence image-data in) + image-data)))) + +(defun image-ram-page () + (setf (content-type) + "image/jpeg") + *test-image*) + +(let ((count 0)) + (defun info () + (with-html + (:html + (:head (:title "Hunchentoot Information")) + (:body + (:h2 (hunchentoot-link) " Information Page") + (:p "This page has been called " + (:b + (fmt "~[~;once~;twice~:;~:*~R times~]" (incf count))) + " since its handler was compiled.") + (info-table (host) + (server-address *server*) + (server-addr) + (server-port) + (remote-addr) + (remote-port) + (real-remote-addr) + (request-method) + (script-name) + (query-string) + (get-parameters) + (headers-in) + (cookies-in) + (user-agent) + (referer) + (request-uri) + (server-protocol) + (mod-lisp-id) + (ssl-session-id))))))) + +(defun oops () + (with-html + (dotimes (i 3) + (log-message* "Oops (default) # ~a" i)) + (log-message :emerg "Oops emergency") + (log-message :alert "Oops alert") + (log-message :crit "Oops critical") + (log-message :error "Oops error") + (log-message :warning "Oops warning") + (log-message :notice "Oops notice") + (log-message :info "Oops info") + (log-message :debug "Oops debug") + (error "An error was triggered on purpose. Check your ~ +Apache error log. Up to 12 messages where logged depending on ~ +the Apache log level set in httpd.conf.") + (:html + (:body "You'll never see this sentence...")))) + +(defun redir () + (redirect "/hunchentoot/test/info.html?redirected=1")) + +(defun forbidden () + (setf (return-code *reply*) +http-forbidden+) + nil) + +(defun cookie-test () + (set-cookie "pumpkin" :value "barking") + (no-cache) + (with-html + (:html + (:head (:title "Hunchentoot cookie test")) + (:body + (:h2 (hunchentoot-link) + " cookie test") + (:p "You might have to reload this page to see the cookie value.") + (info-table (cookie-in "pumpkin") + (mapcar #'car (cookies-in))))))) + +(defun session-test () + (let ((new-foo-value (post-parameter "new-foo-value"))) + (when new-foo-value + (setf (session-value 'foo) new-foo-value))) + (let ((new-bar-value (post-parameter "new-bar-value"))) + (when new-bar-value + (setf (session-value 'bar) new-bar-value))) + (no-cache) + (with-html + (:html + (:head (:title "Hunchentoot session test")) + (:body + (:h2 (hunchentoot-link) + " session test") + (:p "Use the forms below to set new values for " + (:code "FOO") + " or " + (:code "BAR") + ". You can later return to this page to check if +they're still set. Also, try to use another browser at the same +time or try with cookies disabled.") + (:p (:form :method :post + "New value for " + (:code "FOO") + ": " + (:input :type :text + :name "new-foo-value" + :value (or (session-value 'foo) "")))) + (:p (:form :method :post + "New value for " + (:code "BAR") + ": " + (:input :type :text + :name "new-bar-value" + :value (or (session-value 'bar) "")))) + (info-table *session-cookie-name* + (cookie-in *session-cookie-name*) + (mapcar #'car (cookies-in)) + (session-value 'foo) + (session-value 'bar)))))) + +(defun parameter-test (&key (method :get) (charset :iso-8859-1)) + (no-cache) + (recompute-request-parameters :external-format + (flex:make-external-format charset :eol-style :lf)) + (setf (content-type) + (format nil "text/html; charset=~A" charset)) + (with-html + (:html + (:head (:title (fmt "Hunchentoot ~A parameter test" method))) + (:body + (:h2 (hunchentoot-link) + (fmt " ~A parameter test with charset ~A" method charset)) + (:p "Enter some non-ASCII characters in the input field below +and see what's happening.") + (:p (:form + :method method + "Enter a value: " + (:input :type :text + :name "foo"))) + (case method + (:get (info-table (query-string) + (map 'list #'char-code (get-parameter "foo")) + (get-parameter "foo"))) + (:post (info-table (raw-post-data) + (map 'list #'char-code (post-parameter "foo")) + (post-parameter "foo")))))))) + +(defun parameter-test-latin1-get () + (parameter-test :method :get :charset :iso-8859-1)) + +(defun parameter-test-latin1-post () + (parameter-test :method :post :charset :iso-8859-1)) + +(defun parameter-test-utf8-get () + (parameter-test :method :get :charset :utf-8)) + +(defun parameter-test-utf8-post () + (parameter-test :method :post :charset :utf-8)) + +;; this should not be the same directory as *TMP-DIRECTORY* and it +;; should be initially empty (or non-existent) +(defvar *tmp-test-directory* + #+(or :win32 :mswindows) #p"c:\\hunchentoot-temp\\test\\" + #-(or :win32 :mswindows) #p"/tmp/hunchentoot/test/") + +(defvar *tmp-test-files* nil) + +(let ((counter 0)) + (defun handle-file (post-parameter) + (when (and post-parameter + (listp post-parameter)) + (destructuring-bind (path file-name content-type) + post-parameter + (let ((new-path (make-pathname :name (format nil "hunchentoot-test-~A" + (incf counter)) + :type nil + :defaults *tmp-test-directory*))) + ;; strip directory info sent by Windows browsers + (when (search "Windows" (user-agent) :test #'char-equal) + (setq file-name (cl-ppcre:regex-replace ".*\\\\" file-name ""))) + (rename-file path (ensure-directories-exist new-path)) + (push (list new-path file-name content-type) *tmp-test-files*)))))) + +(defun clean-tmp-dir () + (loop for (path . nil) in *tmp-test-files* + when (probe-file path) + do (ignore-errors (delete-file path))) + (setq *tmp-test-files* nil)) + +(defun upload-test () + (let (post-parameter-p) + (when (post-parameter "file1") + (handle-file (post-parameter "file1")) + (setq post-parameter-p t)) + (when (post-parameter "file2") + (handle-file (post-parameter "file2")) + (setq post-parameter-p t)) + (when (post-parameter "clean") + (clean-tmp-dir) + (setq post-parameter-p t)) + (when post-parameter-p + ;; redirect so user can safely use 'Back' button + (redirect (script-name)))) + (no-cache) + (with-html + (:html + (:head (:title "Hunchentoot file upload test")) + (:body + (:h2 (hunchentoot-link) + " file upload test") + (:form :method :post :enctype "multipart/form-data" + (:p "First file: " + (:input :type :file + :name "file1")) + (:p "Second file: " + (:input :type :file + :name "file2")) + (:p (:input :type :submit))) + (when *tmp-test-files* + (htm + (:p + (:table :border 1 :cellpadding 2 :cellspacing 0 + (:tr (:td :colspan 3 (:b "Uploaded files"))) + (loop for (path file-name nil) in *tmp-test-files* + for counter from 1 + do (htm + (:tr (:td :align "right" (str counter)) + (:td (:a :href (format nil "files/~A?path=~A" + (url-encode file-name) + (url-encode (namestring path))) + (esc file-name))) + (:td :align "right" + (str (ignore-errors + (with-open-file (in path) + (file-length in)))) + " Bytes")))))) + (:form :method :post + (:p (:input :type :submit :name "clean" :value "Delete uploaded files"))))) + (menu-link))))) + +(defun send-file () + (let* ((path (get-parameter "path")) + (file-info (and path + (find (pathname path) *tmp-test-files* + :key #'first :test #'equal)))) + (unless file-info + (setf (return-code *reply*) + +http-not-found+) + (return-from send-file)) + (handle-static-file path (third file-info)))) + +(defparameter *headline* + (load-time-value + (format nil "Hunchentoot test menu (see file ~A)" + (merge-pathnames (make-pathname :type "lisp") *this-file*)))) + +(defvar *utf-8* (flex:make-external-format :utf-8 :eol-style :lf)) + +(defvar *utf-8-file* (merge-pathnames "UTF-8-demo.html" *this-file*) + "Demo file stolen from .") + +(defun stream-direct () + (setf (content-type) "text/html; charset=utf-8") + (let ((stream (send-headers)) + (buffer (make-array 1024 :element-type 'flex:octet))) + #+:clisp + (setf (flex:flexi-stream-element-type stream) 'flex:octet) + (with-open-file (in *utf-8-file* + :element-type 'flex:octet) + (loop for pos = (read-sequence buffer in) + until (zerop pos) + do (write-sequence buffer stream :end pos))))) + +(defun stream-direct-utf-8 () + (setf (content-type) "text/html; charset=utf-8") + (let ((stream (send-headers))) + (setf (flex:flexi-stream-external-format stream) *utf-8*) + (with-open-file (in (merge-pathnames "UTF-8-demo.html" *this-file*) + :element-type 'flex:octet) + (setq in (flex:make-flexi-stream in :external-format *utf-8*)) + (loop for line = (read-line in nil nil) + while line + do (write-line line stream))))) + +(defun stream-direct-utf-8-string () + (setf (content-type) "text/html; charset=utf-8" + (reply-external-format) *utf-8*) + (with-open-file (in (merge-pathnames "UTF-8-demo.html" *this-file*) + :element-type 'flex:octet) + (let ((string (make-array (file-length in) + :element-type #-:lispworks 'character #+:lispworks 'lw:simple-char + :fill-pointer t))) + (setf in (flex:make-flexi-stream in :external-format *utf-8*) + (fill-pointer string) (read-sequence string in)) + string))) + +(define-easy-handler (easy-demo :uri "/hunchentoot/test/easy-demo.html" + :default-request-type :post) + (first-name last-name + (age :parameter-type 'integer) + (implementation :parameter-type 'keyword) + (meal :parameter-type '(hash-table boolean)) + (team :parameter-type 'list)) + (with-html + (:html + (:head (:title "Hunchentoot \"easy\" handler example")) + (:body + (:h2 (hunchentoot-link) + " \"Easy\" handler example") + (:p (:form :method :post + (:table :border 1 :cellpadding 2 :cellspacing 0 + (:tr + (:td "First Name:") + (:td (:input :type :text + :name "first-name" + :value (or first-name "Donald")))) + (:tr + (:td "Last name:") + (:td (:input :type :text + :name "last-name" + :value (or last-name "Duck")))) + (:tr + (:td "Age:") + (:td (:input :type :text + :name "age" + :value (or age 42)))) + (:tr + (:td "Implementation:") + (:td (:select :name "implementation" + (loop for (value option) in '((:lispworks "LispWorks") + (:allegro "AllegroCL") + (:cmu "CMUCL") + (:sbcl "SBCL") + (:openmcl "OpenMCL")) + do (htm + (:option :value value + :selected (eq value implementation) + (str option))))))) + (:tr + (:td :valign :top "Meal:") + (:td (loop for choice in '("Burnt weeny sandwich" + "Canard du jour" + "Easy meat" + "Muffin" + "Twenty small cigars" + "Yellow snow") + do (htm + (:input :type "checkbox" + :name (format nil "meal{~A}" choice) + :checked (gethash choice meal) + (esc choice)) + (:br))))) + (:tr + (:td :valign :top "Team:") + (:td (loop for player in '("Beckenbauer" + "Cruyff" + "Maradona" + ;; without accent (for SBCL) + "Pele" + "Zidane") + do (htm + (:input :type "checkbox" + :name "team" + :value player + :checked (member player team :test #'string=) + (esc player)) + (:br))))) + (:tr + (:td :colspan 2 + (:input :type "submit")))))) + (info-table first-name + last-name + age + implementation + (loop :for choice :being :the :hash-keys :of meal :collect choice) + (gethash "Yellow snow" meal) + team))))) + + +(defun menu () + (with-html + (:html + (:head + (:link :rel "shortcut icon" + :href "/hunchentoot/test/favicon.ico" :type "image/x-icon") + (:title "Hunchentoot test menu")) + (:body + (:h2 (str *headline*)) + (:table :border 0 :cellspacing 4 :cellpadding 4 + (:tr (:td (:a :href "/hunchentoot/test/info.html?foo=bar" + "Info provided by Hunchentoot"))) + (:tr (:td (:a :href "/hunchentoot/test/cookie.html" + "Cookie test"))) + (:tr (:td (:a :href "/hunchentoot/test/session.html" + "Session test"))) + (:tr (:td (:a :href "/hunchentoot/test/parameter_latin1_get.html" + "GET parameter handling with LATIN-1 charset"))) + (:tr (:td (:a :href "/hunchentoot/test/parameter_latin1_post.html" + "POST parameter handling with LATIN-1 charset"))) + (:tr (:td (:a :href "/hunchentoot/test/parameter_utf8_get.html" + "GET parameter handling with UTF-8 charset"))) + (:tr (:td (:a :href "/hunchentoot/test/parameter_utf8_post.html" + "POST parameter handling with UTF-8 charset"))) + (:tr (:td (:a :href "/hunchentoot/test/redir.html" + "Redirect \(302) to info page above"))) + (:tr (:td (:a :href "/hunchentoot/test/authorization.html" + "Authorization") + " (user 'nanook', password 'igloo')")) + (:tr (:td (:a :href "/hunchentoot/code/test.lisp" + "The source code of this test"))) + (:tr (:td (:a :href "/hunchentoot/test/image.jpg" + "Binary data, delivered from file") + " \(a picture)")) + (:tr (:td (:a :href "/hunchentoot/test/image-ram.jpg" + "Binary data, delivered from RAM") + " \(same picture)")) + (:tr (:td (:a :href "/hunchentoot/test/easy-demo.html" + "\"Easy\" handler example"))) + (:tr (:td (:a :href "/hunchentoot/test/utf8-binary.txt" + "UTF-8 demo") + " \(writing octets directly to the stream)")) + (:tr (:td (:a :href "/hunchentoot/test/utf8-character.txt" + "UTF-8 demo") + " \(writing UTF-8 characters directly to the stream)")) + (:tr (:td (:a :href "/hunchentoot/test/utf8-string.txt" + "UTF-8 demo") + " \(returning a string)")) + (:tr (:td (:a :href "/hunchentoot/test/upload.html" + "File uploads"))) + (:tr (:td (:a :href "/hunchentoot/test/forbidden.html" + "Forbidden \(403) page"))) + (:tr (:td (:a :href "/hunchentoot/test/oops.html" + "Error handling") + " \(output depends on settings like " + (:a :href "http://weitz.de/hunchentoot/#*show-lisp-errors-p*" + (:code "*SHOW-LISP-ERRORS-P*")) + (fmt " \(currently ~S) and " *show-lisp-errors-p*) + (:a :href "http://weitz.de/hunchentoot/#*show-lisp-backtraces-p*" + (:code "*SHOW-LISP-BACKTRACES-P*")) + (fmt " \(currently ~S)" *show-lisp-backtraces-p*) + ")")) + (:tr (:td (:a :href "/hunchentoot/foo" + "URI handled by") + " " + (:a :href "http://weitz.de/hunchentoot/#*default-handler*" + (:code "*DEFAULT-HANDLER*"))))))))) + +(setq *dispatch-table* + (nconc + (list 'dispatch-easy-handlers + (create-static-file-dispatcher-and-handler + "/hunchentoot/test/image.jpg" + (make-pathname :name "fz" :type "jpg" :version nil + :defaults *this-file*) + "image/jpeg") + (create-static-file-dispatcher-and-handler + "/hunchentoot/test/favicon.ico" + (make-pathname :name "favicon" :type "ico" :version nil + :defaults *this-file*)) + (create-folder-dispatcher-and-handler + "/hunchentoot/code/" + (make-pathname :name nil :type nil :version nil + :defaults *this-file*) + "text/plain")) + (mapcar (lambda (args) + (apply #'create-prefix-dispatcher args)) + '(("/hunchentoot/test/form-test.html" form-test) + ("/hunchentoot/test/forbidden.html" forbidden) + ("/hunchentoot/test/info.html" info) + ("/hunchentoot/test/authorization.html" authorization-page) + ("/hunchentoot/test/image-ram.jpg" image-ram-page) + ("/hunchentoot/test/cookie.html" cookie-test) + ("/hunchentoot/test/session.html" session-test) + ("/hunchentoot/test/parameter_latin1_get.html" parameter-test-latin1-get) + ("/hunchentoot/test/parameter_latin1_post.html" parameter-test-latin1-post) + ("/hunchentoot/test/parameter_utf8_get.html" parameter-test-utf8-get) + ("/hunchentoot/test/parameter_utf8_post.html" parameter-test-utf8-post) + ("/hunchentoot/test/upload.html" upload-test) + ("/hunchentoot/test/redir.html" redir) + ("/hunchentoot/test/oops.html" oops) + ("/hunchentoot/test/utf8-binary.txt" stream-direct) + ("/hunchentoot/test/utf8-character.txt" stream-direct-utf-8) + ("/hunchentoot/test/utf8-string.txt" stream-direct-utf-8-string) + ("/hunchentoot/test/files/" send-file) + ("/hunchentoot/test" menu))) + (list #'default-dispatcher))) Added: branches/trunk-reorg/thirdparty/hunchentoot-0.15.0/unix-acl.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/hunchentoot-0.15.0/unix-acl.lisp Thu Feb 7 03:16:29 2008 @@ -0,0 +1,53 @@ +;;; -*- Mode: LISP; Syntax: COMMON-LISP; Package: HUNCHENTOOT; Base: 10 -*- +;;; $Header: /usr/local/cvsrep/hunchentoot/unix-acl.lisp,v 1.5 2007/01/01 23:50:30 edi Exp $ + +;;; Copyright (c) 2004-2007, Dr. Edmund Weitz. All rights reserved. + +;;; Redistribution and use in source and binary forms, with or without +;;; modification, are permitted provided that the following conditions +;;; are met: + +;;; * Redistributions of source code must retain the above copyright +;;; notice, this list of conditions and the following disclaimer. + +;;; * Redistributions in binary form must reproduce the above +;;; copyright notice, this list of conditions and the following +;;; disclaimer in the documentation and/or other materials +;;; provided with the distribution. + +;;; THIS SOFTWARE IS PROVIDED BY THE AUTHOR 'AS IS' AND ANY EXPRESSED +;;; OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +;;; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +;;; ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +;;; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +;;; DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +;;; GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +;;; INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +;;; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +;;; NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +;;; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +(in-package :hunchentoot) + +(eval-when (:compile-toplevel :load-toplevel :execute) + (require "osi")) + +(defun setuid (uid) + "Sets the effective user ID of the current process to UID - see +setuid\(2)." + (excl.osi:setuid uid)) + +(defun setgid (gid) + "Sets the effective group ID of the current process to GID - +see setgid\(2)." + (excl.osi:setgid gid)) + +(defun get-uid-from-name (name) + "Returns the UID for the user named NAME." + (excl.osi:pwent-uid (or (excl.osi:getpwnam name) + (error "User ~S not found." name)))) + +(defun get-gid-from-name (name) + "Returns the GID for the group named NAME." + (excl.osi:grent-gid (or (excl.osi:getgrnam name) + (error "Group ~S not found." name)))) Added: branches/trunk-reorg/thirdparty/hunchentoot-0.15.0/unix-clisp.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/hunchentoot-0.15.0/unix-clisp.lisp Thu Feb 7 03:16:29 2008 @@ -0,0 +1,51 @@ +;;; -*- Mode: LISP; Syntax: COMMON-LISP; Package: HUNCHENTOOT; Base: 10; -*- +;;; $Header: /usr/local/cvsrep/hunchentoot/unix-clisp.lisp,v 1.1 2007/12/29 17:35:01 edi Exp $ + +;;; Copyright (c) 2006, Lu?s Oliveira . +;;; Copyright (c) 2007, Anton Vodonosov . +;;; Copyright (c) 2007, Dr. Edmund Weitz. +;;; All rights reserved. + +;;; Redistribution and use in source and binary forms, with or without +;;; modification, are permitted provided that the following conditions +;;; are met: + +;;; * Redistributions of source code must retain the above copyright +;;; notice, this list of conditions and the following disclaimer. + +;;; * Redistributions in binary form must reproduce the above +;;; copyright notice, this list of conditions and the following +;;; disclaimer in the documentation and/or other materials +;;; provided with the distribution. + +;;; THIS SOFTWARE IS PROVIDED BY THE AUTHOR 'AS IS' AND ANY EXPRESSED +;;; OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +;;; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +;;; ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +;;; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +;;; DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +;;; GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +;;; INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +;;; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +;;; NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +;;; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +(in-package :hunchentoot) + +(defun setuid (uid) + "Sets the effective user ID of the current process to UID - see +setuid\(2)." + (setf (posix:getuid) uid)) + +(defun setgid (gid) + "Sets the effective group ID of the current process to GID - +see setgid\(2)." + (setf (posix:getgid) gid)) + +(defun get-uid-from-name (name) + "Returns the UID for the user named NAME." + (posix:user-info-uid (posix:user-info name))) + +(defun get-gid-from-name (name) + "Returns the GID for the group named NAME." + (posix:user-info-gid (posix:user-info name))) Added: branches/trunk-reorg/thirdparty/hunchentoot-0.15.0/unix-cmu.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/hunchentoot-0.15.0/unix-cmu.lisp Thu Feb 7 03:16:29 2008 @@ -0,0 +1,54 @@ +;;; -*- Mode: LISP; Syntax: COMMON-LISP; Package: HUNCHENTOOT; Base: 10 -*- +;;; $Header: /usr/local/cvsrep/hunchentoot/unix-cmu.lisp,v 1.5 2007/01/01 23:50:30 edi Exp $ + +;;; Copyright (c) 2004-2007, Dr. Edmund Weitz. All rights reserved. + +;;; Redistribution and use in source and binary forms, with or without +;;; modification, are permitted provided that the following conditions +;;; are met: + +;;; * Redistributions of source code must retain the above copyright +;;; notice, this list of conditions and the following disclaimer. + +;;; * Redistributions in binary form must reproduce the above +;;; copyright notice, this list of conditions and the following +;;; disclaimer in the documentation and/or other materials +;;; provided with the distribution. + +;;; THIS SOFTWARE IS PROVIDED BY THE AUTHOR 'AS IS' AND ANY EXPRESSED +;;; OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +;;; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +;;; ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +;;; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +;;; DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +;;; GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +;;; INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +;;; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +;;; NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +;;; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +(in-package :hunchentoot) + +(defun setuid (uid) + "Sets the effective user ID of the current process to UID - see +setuid\(2)." + (multiple-value-bind (return-value errno) + (unix:unix-setuid uid) + (unless (and return-value (zerop return-value)) + (error "setuid failed: ~A" (unix:get-unix-error-msg errno))))) + +(defun setgid (gid) + "Sets the effective group ID of the current process to GID - +see setgid\(2)." + (multiple-value-bind (return-value errno) + (unix:unix-setgid gid) + (unless (and return-value (zerop return-value)) + (error "setgid failed: ~A" (unix:get-unix-error-msg errno))))) + +(defun get-uid-from-name (name) + "Returns the UID for the user named NAME." + (unix:user-info-uid (unix:unix-getpwnam name))) + +(defun get-gid-from-name (name) + "Returns the GID for the group named NAME." + (unix:group-info-gid (unix:unix-getgrnam name))) Added: branches/trunk-reorg/thirdparty/hunchentoot-0.15.0/unix-lw.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/hunchentoot-0.15.0/unix-lw.lisp Thu Feb 7 03:16:29 2008 @@ -0,0 +1,93 @@ +;;; -*- Mode: LISP; Syntax: COMMON-LISP; Package: HUNCHENTOOT; Base: 10 -*- +;;; $Header: /usr/local/cvsrep/hunchentoot/unix-lw.lisp,v 1.4 2007/01/01 23:50:30 edi Exp $ + +;;; Copyright (c) 2004-2007, Dr. Edmund Weitz. All rights reserved. + +;;; Redistribution and use in source and binary forms, with or without +;;; modification, are permitted provided that the following conditions +;;; are met: + +;;; * Redistributions of source code must retain the above copyright +;;; notice, this list of conditions and the following disclaimer. + +;;; * Redistributions in binary form must reproduce the above +;;; copyright notice, this list of conditions and the following +;;; disclaimer in the documentation and/or other materials +;;; provided with the distribution. + +;;; THIS SOFTWARE IS PROVIDED BY THE AUTHOR 'AS IS' AND ANY EXPRESSED +;;; OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +;;; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +;;; ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +;;; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +;;; DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +;;; GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +;;; INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +;;; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +;;; NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +;;; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +(in-package :hunchentoot) + +(fli:define-foreign-function (%setuid "setuid") + ((uid :int)) + :result-type :int) + +(defun setuid (uid) + "Sets the effective user ID of the current process to UID - see +setuid\(2)." + (unless (zerop (%setuid uid)) + (error "setuid failed: ~A" (lw:get-unix-error (lw:errno-value))))) + +(fli:define-foreign-function (%setgid "setgid") + ((gid :int)) + :result-type :int) + +(defun setgid (gid) + "Sets the effective group ID of the current process to GID - +see setgid\(2)." + (unless (zerop (%setgid gid)) + (error "setgid failed: ~A" (lw:get-unix-error (lw:errno-value))))) + +(fli:define-c-struct passwd + (name (:pointer :char)) + (passwd (:pointer :char)) + (uid :int) + (gid :int) + (gecos (:pointer :char)) + (dir (:pointer :char)) + (shell (:pointer :char))) + +(fli:define-foreign-function (getpwnam "getpwnam") + ((name (:reference-pass :ef-mb-string))) + :result-type (:pointer passwd)) + +(defun get-uid-from-name (name) + "Returns the UID for the user named NAME." + (let ((passwd (getpwnam name))) + (when (fli:null-pointer-p passwd) + (let ((errno (lw:errno-value))) + (cond ((zerop errno) + (error "User ~S not found." name)) + (t (error "getpwnam failed: ~A" (lw:get-unix-error errno)))))) + (fli:foreign-slot-value passwd 'uid))) + +(fli:define-c-struct group + (name (:pointer :char)) + (passwd (:pointer :char)) + (gid :int) + (mem (:pointer (:pointer :char)))) + +(fli:define-foreign-function (getgrnam "getgrnam") + ((name (:reference-pass :ef-mb-string))) + :result-type (:pointer group)) + +(defun get-gid-from-name (name) + "Returns the GID for the group named NAME." + (let ((group (getgrnam name))) + (when (fli:null-pointer-p group) + (let ((errno (lw:errno-value))) + (cond ((zerop errno) + (error "Group ~S not found." name)) + (t (error "getgrnam failed: ~A" (lw:get-unix-error errno)))))) + (fli:foreign-slot-value group 'gid))) \ No newline at end of file Added: branches/trunk-reorg/thirdparty/hunchentoot-0.15.0/unix-mcl.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/hunchentoot-0.15.0/unix-mcl.lisp Thu Feb 7 03:16:29 2008 @@ -0,0 +1,54 @@ +;;; -*- Mode: LISP; Syntax: COMMON-LISP; Package: HUNCHENTOOT; Base: 10 -*- +;;; $Header: /usr/local/cvsrep/hunchentoot/unix-mcl.lisp,v 1.6 2007/01/01 23:50:30 edi Exp $ + +;;; Copyright (c) 2004-2007, Dr. Edmund Weitz. All rights reserved. + +;;; Redistribution and use in source and binary forms, with or without +;;; modification, are permitted provided that the following conditions +;;; are met: + +;;; * Redistributions of source code must retain the above copyright +;;; notice, this list of conditions and the following disclaimer. + +;;; * Redistributions in binary form must reproduce the above +;;; copyright notice, this list of conditions and the following +;;; disclaimer in the documentation and/or other materials +;;; provided with the distribution. + +;;; THIS SOFTWARE IS PROVIDED BY THE AUTHOR 'AS IS' AND ANY EXPRESSED +;;; OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +;;; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +;;; ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +;;; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +;;; DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +;;; GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +;;; INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +;;; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +;;; NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +;;; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +(in-package :hunchentoot) + +(defun setuid (uid) + "Sets the effective user ID of the current process to UID - see +setuid\(2)." + (let ((errno (ccl::setuid uid))) + (unless (zerop errno) + (error "setuid failed with errno ~A." errno)))) + +(defun setgid (gid) + "Sets the effective group ID of the current process to GID - +see setgid\(2)." + (let ((errno (ccl::setgid gid))) + (unless (zerop errno) + (error "setgid failed with errno ~A." errno)))) + +(defun get-uid-from-name (name) + "Returns the UID for the user named NAME." + (declare (ignore name)) + (error "GET-UID-FROM-NAME not yet implemented for OpenMCL. Please send patches...")) + +(defun get-gid-from-name (name) + "Returns the GID for the group named NAME." + (declare (ignore name)) + (error "GET-GID-FROM-NAME not yet implemented for OpenMCL. Please send patches...")) Added: branches/trunk-reorg/thirdparty/hunchentoot-0.15.0/unix-sbcl.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/hunchentoot-0.15.0/unix-sbcl.lisp Thu Feb 7 03:16:29 2008 @@ -0,0 +1,57 @@ +;;; -*- Mode: LISP; Syntax: COMMON-LISP; Package: HUNCHENTOOT; Base: 10 -*- +;;; $Header: /usr/local/cvsrep/hunchentoot/unix-sbcl.lisp,v 1.7 2007/10/06 22:44:06 edi Exp $ + +;;; Copyright (c) 2004-2007, Dr. Edmund Weitz. All rights reserved. + +;;; Redistribution and use in source and binary forms, with or without +;;; modification, are permitted provided that the following conditions +;;; are met: + +;;; * Redistributions of source code must retain the above copyright +;;; notice, this list of conditions and the following disclaimer. + +;;; * Redistributions in binary form must reproduce the above +;;; copyright notice, this list of conditions and the following +;;; disclaimer in the documentation and/or other materials +;;; provided with the distribution. + +;;; THIS SOFTWARE IS PROVIDED BY THE AUTHOR 'AS IS' AND ANY EXPRESSED +;;; OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +;;; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +;;; ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +;;; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +;;; DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +;;; GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +;;; INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +;;; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +;;; NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +;;; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +(in-package :hunchentoot) + +(eval-when (:compile-toplevel :load-toplevel :execute) + (when (and (eq (nth-value 1 (find-symbol "GETGRNAM" :sb-posix)) :external) + (eq (nth-value 1 (find-symbol "GROUP-GID" :sb-posix)) :external)) + (pushnew :sb-posix-has-getgrnam *features*))) + +(defun setuid (uid) + "Sets the effective user ID of the current process to UID - see +setuid\(2)." + (sb-posix:setuid uid)) + +(defun setgid (gid) + "Sets the effective group ID of the current process to GID - +see setgid\(2)." + (sb-posix:setgid gid)) + +(defun get-uid-from-name (name) + "Returns the UID for the user named NAME." + (sb-posix:passwd-uid (sb-posix:getpwnam name))) + +(defun get-gid-from-name (name) + "Returns the GID for the group named NAME." + (declare (ignorable name)) + #+:sb-posix-has-getgrnam + (sb-posix:group-gid (sb-posix:getgrnam name)) + #-:sb-posix-has-getgrnam + (error "You need a version of SBCL with SB-POSIX:GETGRNAM \(1.0.10.31 or higher).")) Added: branches/trunk-reorg/thirdparty/hunchentoot-0.15.0/util.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/hunchentoot-0.15.0/util.lisp Thu Feb 7 03:16:29 2008 @@ -0,0 +1,406 @@ +;;; -*- Mode: LISP; Syntax: COMMON-LISP; Package: HUNCHENTOOT; Base: 10 -*- +;;; $Header: /usr/local/cvsrep/hunchentoot/util.lisp,v 1.33 2007/12/29 17:35:02 edi Exp $ + +;;; Copyright (c) 2004-2007, Dr. Edmund Weitz. All rights reserved. + +;;; Redistribution and use in source and binary forms, with or without +;;; modification, are permitted provided that the following conditions +;;; are met: + +;;; * Redistributions of source code must retain the above copyright +;;; notice, this list of conditions and the following disclaimer. + +;;; * Redistributions in binary form must reproduce the above +;;; copyright notice, this list of conditions and the following +;;; disclaimer in the documentation and/or other materials +;;; provided with the distribution. + +;;; THIS SOFTWARE IS PROVIDED BY THE AUTHOR 'AS IS' AND ANY EXPRESSED +;;; OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +;;; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +;;; ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +;;; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +;;; DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +;;; GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +;;; INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +;;; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +;;; NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +;;; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +(in-package :hunchentoot) + +#-:lispworks +(defmacro when-let ((var form) &body body) + "Evaluates FORM and binds VAR to the result, then executes BODY +if VAR has a true value." + `(let ((,var ,form)) + (when ,var , at body))) + +#-:lispworks +(defmacro with-unique-names ((&rest bindings) &body body) + "Syntax: WITH-UNIQUE-NAMES ( { var | (var x) }* ) declaration* form* + +Executes a series of forms with each VAR bound to a fresh, +uninterned symbol. The uninterned symbol is as if returned by a call +to GENSYM with the string denoted by X - or, if X is not supplied, the +string denoted by VAR - as argument. + +The variable bindings created are lexical unless special declarations +are specified. The scopes of the name bindings and declarations do not +include the Xs. + +The forms are evaluated in order, and the values of all but the last +are discarded \(that is, the body is an implicit PROGN)." + ;; reference implementation posted to comp.lang.lisp as + ;; by Vebjorn Ljosa - see also + ;; + `(let ,(mapcar #'(lambda (binding) + (check-type binding (or cons symbol)) + (if (consp binding) + (destructuring-bind (var x) binding + (check-type var symbol) + `(,var (gensym ,(etypecase x + (symbol (symbol-name x)) + (character (string x)) + (string x))))) + `(,binding (gensym ,(symbol-name binding))))) + bindings) + , at body)) + +#+:lispworks +(defmacro with-rebinding (bindings &body body) + "Renaming LW:REBINDING for better indentation." + `(lw:rebinding ,bindings , at body)) + +#-:lispworks +(defmacro with-rebinding (bindings &body body) + "Syntax: WITH-REBINDING ( { var | (var prefix) }* ) form* + +Evaluates a series of forms in the lexical environment that is +formed by adding the binding of each VAR to a fresh, uninterned +symbol, and the binding of that fresh, uninterned symbol to VAR's +original value, i.e., its value in the current lexical environment. + +The uninterned symbol is created as if by a call to GENSYM with the +string denoted by PREFIX - or, if PREFIX is not supplied, the string +denoted by VAR - as argument. + +The forms are evaluated in order, and the values of all but the last +are discarded \(that is, the body is an implicit PROGN)." + ;; reference implementation posted to comp.lang.lisp as + ;; by Vebjorn Ljosa - see also + ;; + (loop for binding in bindings + for var = (if (consp binding) (car binding) binding) + for name = (gensym) + collect `(,name ,var) into renames + collect ``(,,var ,,name) into temps + finally (return `(let ,renames + (with-unique-names ,bindings + `(let (,, at temps) + ,, at body)))))) + +(defun starts-with-p (seq subseq &key (test 'eql)) + "Tests whether the sequence SEQ starts with the sequence +SUBSEQ. Individual elements are compared with TEST." + (let* ((length (length subseq)) + (mismatch (mismatch subseq seq + :test test))) + (or (null mismatch) + (<= length mismatch)))) + +(defun starts-with-one-of-p (seq subseq-list &key (test 'eql)) + "Tests whether the sequence SEQ starts with one of the +sequences in SUBSEQ-LIST. Individual elements are compared with +TEST." + (some (lambda (subseq) + (starts-with-p seq subseq :test test)) + subseq-list)) + +(defun create-random-string (&optional (n 10) (base 16)) + "Returns a random number \(as a string) with base BASE and N +digits." + (with-output-to-string (s) + (dotimes (i n) + (format s "~VR" base + (random base *the-random-state*))))) + +(defun reset-session-secret () + "Sets *SESSION-SECRET* to a new random value. All old sessions will +cease to be valid." + (setq *session-secret* (create-random-string 10 36))) + +(defun reason-phrase (return-code) + "Returns a reason phrase for the HTTP return code RETURN-CODE +\(which should be an integer) or NIL for return codes Hunchentoot +doesn't know." + (gethash return-code *http-reason-phrase-map*)) + +(defun make-keyword (string &key (destructivep t)) + "Interns the upcased version of STRING into the KEYWORD package. +Uses NSTRING-UPCASE if DESTRUCTIVEP is true. Returns NIL if STRING is +not a string." + (and (stringp string) + (intern (if destructivep + (nstring-upcase string) + (string-upcase string)) :keyword))) + +(defgeneric assoc (thing alist &key &allow-other-keys) + (:documentation "LIKE CL:ASSOC, but \'does the right thing\' if +THING is a string or a symbol.")) + +(defmethod assoc ((thing symbol) alist &key &allow-other-keys) + "Version of ASSOC for symbols, always uses EQ as test function." + (cl:assoc thing alist :test #'eq)) + +(defmethod assoc ((thing string) alist &key (test #'string-equal)) + "Version of ASSOC for strings, uses STRING-EQUAL as default test +function." + (cl:assoc thing alist :test test)) + +(defmethod assoc (thing alist &key (test #'eql)) + "Default method - uses EQL as default test like CL:ASSOC." + (cl:assoc thing alist :test test)) + +(defun md5-hex (string) + "Calculates the md5 sum of the string STRING and returns it as a hex string." + (with-output-to-string (s) + (loop for code across (md5:md5sum-sequence string) + do (format s "~2,'0x" code)))) + +(defun escape-for-html (string) + "Escapes the characters #\\<, #\\>, #\\', #\\\", and #\\& for HTML output." + (with-output-to-string (out) + (with-input-from-string (in string) + (loop for char = (read-char in nil nil) + while char + do (case char + ((#\<) (write-string "<" out)) + ((#\>) (write-string ">" out)) + ((#\") (write-string """ out)) + ((#\') (write-string "'" out)) + ((#\&) (write-string "&" out)) + (otherwise (write-char char out))))))) + +(defun http-token-p (token) + "Tests whether TOKEN is a string which is a valid 'token' +according to HTTP/1.1 \(RFC 2068)." + (and (stringp token) + (plusp (length token)) + (every (lambda (char) + (and ;; CHAR is US-ASCII but not control character or ESC + (< 31 (char-code char) 127) + ;; CHAR is not 'tspecial' + (not (find char "()<>@,;:\\\"/[]?={} " :test #'char=)))) + token))) + + +(defun rfc-1123-date (&optional (time (get-universal-time))) + "Generates a time string according to RFC 1123. Default is current time." + (multiple-value-bind + (second minute hour date month year day-of-week) + (decode-universal-time time 0) + (format nil "~A, ~2,'0d ~A ~4d ~2,'0d:~2,'0d:~2,'0d GMT" + (svref +day-names+ day-of-week) + date + (svref +month-names+ (1- month)) + year + hour + minute + second))) + +(defun iso-time (&optional (time (get-universal-time))) + "Returns the universal time TIME as a string in full ISO format." + (multiple-value-bind (second minute hour date month year) + (decode-universal-time time) + (format nil "~4,'0d-~2,'0d-~2,'0d ~2,'0d:~2,'0d:~2,'0d" + year month date hour minute second))) + +(let ((counter 0)) + (declare (ignorable counter)) + (defun make-tmp-file-name (&optional (prefix "hunchentoot")) + "Generates a unique name for a temporary file. This function is +called from the RFC2388 library when a file is uploaded." + (let ((tmp-file-name + #+:allegro + (pathname (system:make-temp-file-name prefix *tmp-directory*)) + #-:allegro + (loop for pathname = (make-pathname :name (format nil "~A-~A" + prefix (incf counter)) + :type nil + :defaults *tmp-directory*) + unless (probe-file pathname) + return pathname))) + (push tmp-file-name *tmp-files*) + ;; maybe call hook for file uploads + (when *file-upload-hook* + (funcall *file-upload-hook* tmp-file-name)) + tmp-file-name))) + +(defun quote-string (string) + "Quotes string according to RFC 2616's definition of `quoted-string'." + (with-output-to-string (out) + (with-input-from-string (in string) + (loop for char = (read-char in nil nil) + while char + unless (or (char< char #\Space) + (char= char #\Rubout)) + do (case char + ((#\\) (write-string "\\\\" out)) + ((#\") (write-string "\\\"" out)) + (otherwise (write-char char out))))))) + +(defun url-decode (string &optional (external-format *hunchentoot-default-external-format*)) + "Decodes a URL-encoded STRING which is assumed to be encoded using +the external format EXTERNAL-FORMAT." + (let ((vector (make-array (length string) + :element-type 'octet + :fill-pointer 0))) + (loop with percent-p and buff + for char of-type character across string + for i from 0 + when buff do + (vector-push (parse-integer string + :start (1- i) + :end (1+ i) + :radix 16) + vector) + (setq buff nil) + else when percent-p + do (setq buff t + percent-p nil) + else when (char= char #\%) + do (setq percent-p t) + else do (vector-push (char-code (case char + ((#\+) #\Space) + (otherwise char))) + vector)) + (octets-to-string vector :external-format external-format))) + +(defun form-url-encoded-list-to-alist (form-url-encoded-list + &optional (external-format *hunchentoot-default-external-format*)) + "Converts a list FORM-URL-ENCODED-LIST of name/value pairs into an +alist. Both names and values are url-decoded while doing this." + (mapcar #'(lambda (entry) + (destructuring-bind (name &optional value) + (split "=" entry :limit 2) + (cons (string-trim " " (url-decode name external-format)) + (url-decode (or value "") external-format)))) + form-url-encoded-list)) + +(defun url-encode (string &optional (external-format *hunchentoot-default-external-format*)) + "URL-encodes a string using the external format EXTERNAL-FORMAT." + (with-output-to-string (s) + (loop for c across string + for index from 0 + do (cond ((or (char<= #\0 c #\9) + (char<= #\a c #\z) + (char<= #\A c #\Z) + ;; note that there's no comma in there - because of cookies + (find c "$-_.!*'()" :test #'char=)) + (write-char c s)) + (t (loop for octet across (string-to-octets string + :start index + :end (1+ index) + :external-format external-format) + do (format s "%~2,'0x" octet))))))) + +(defun force-output* (stream) + "Like FORCE-OUTPUT but aborts execution after +*FORCE-OUTPUT-TIMEOUT* seconds." + (with-timeout (*force-output-timeout* + (warn "FORCE-OUTPUT didn't return after ~A seconds." + *force-output-timeout*)) + (force-output stream))) + +(defun parse-content-type (content-type-header &optional want-external-format-p) + "Reads and parses a `Content-Type' header and returns it as three +values - the type, the subtype, and an external format corresponding +to the 'charset' parameter in the header \(or +*HUNCHENTOOT-DEFAULT-EXTERNAL-FORMAT*), if there is one and if the +content type is \"text\" or WANT-EXTERNAL-FORMAT-P is true. +CONTENT-TYPE-HEADER is supposed to be the corresponding header value +as a string." + (with-input-from-string (stream content-type-header) + (let* ((*current-error-message* "Corrupted Content-Type header:") + (type (read-token stream)) + (subtype (and (or (ignore-errors (assert-char stream #\/)) + (return-from parse-content-type + ;; try to return something meaningful + (values "application" "octet-stream" + (and want-external-format-p + *hunchentoot-default-external-format*)))) + (read-token stream))) + (parameters (read-name-value-pairs stream)) + (charset (cdr (assoc "charset" parameters))) + (external-format + (and (or want-external-format-p + (string-equal type "text")) + (or (when charset + (handler-case + (make-external-format (make-keyword charset) :eol-style :lf) + (error (condition) + (warn "Ignoring external format of name ~S~ +because of error:~%~A" + charset condition)))) + *hunchentoot-default-external-format*)))) + (values type subtype external-format)))) + +(defun get-token-and-parameters (header) + (with-input-from-string (stream header) + (let* ((*current-error-message* (format nil "Corrupted header ~S:" header)) + (token (read-token stream)) + (parameters (read-name-value-pairs stream))) + (values token parameters)))) + +(defun keep-alive-p () + "Returns a true value unless the incoming request obviates a +keep-alive reply. The second return value denotes whether the client +has explicitly asked for a persistent connection." + (let ((connection-values + ;; the header might consist of different values separated by commas + (when-let (connection-header (header-in :connection)) + (split "\\s*,\\s*" connection-header)))) + (flet ((connection-value-p (value) + "Checks whether the string VALUE is one of the +values of the `Connection' header." + (member value connection-values :test #'string-equal))) + (let ((keep-alive-requested-p (connection-value-p "keep-alive"))) + (values (and (or (and (eq (server-protocol) :http/1.1) + (not (connection-value-p "close"))) + (and (eq (server-protocol) :http/1.0) + keep-alive-requested-p))) + keep-alive-requested-p))))) + +(defun address-string () + "Returns a string with information about Hunchentoot suitable for +inclusion in HTML output." + (format nil "
~:[~3*~;~A / mod_lisp~A~@[/~A~] / ~]Hunchentoot ~A (~A ~A)~@[ at ~A~:[ (port ~D)~;~]~]
" + (server-mod-lisp-p *server*) + (or (header-in :server-baseversion) "Apache") + (or (header-in :modlisp-major-version) "") + (header-in :modlisp-version) + *hunchentoot-version* + +implementation-link+ + (escape-for-html (lisp-implementation-type)) + (escape-for-html (lisp-implementation-version)) + (or (host *request*) (server-address *server*)) + (scan ":\\d+$" (or (host *request*) "")) + (server-port))) + +(defun server-name-header () + "Returns a string which can be used for 'Server' headers." + (format nil "Hunchentoot ~A" *hunchentoot-version*)) + +(defun input-chunking-p () + "Whether input chunking is currently switched on for \(the socket +stream underlying) *HUNCHENTOOT-STREAM* - note that this will return +NIL if the underlying stream of the flexi stream is not a chunked +stream." + (chunked-stream-input-chunking-p (flexi-stream-stream *hunchentoot-stream*))) + +(defun cleanup-function () + "The default for *CLEANUP-FUNCTION*. Invokes a GC on 32-bit +LispWorks and does nothing on other Lisps." + #+(and :lispworks (not :lispworks-64bit)) + (hcl:mark-and-sweep 2)) From hhubner at common-lisp.net Thu Feb 7 08:21:53 2008 From: hhubner at common-lisp.net (hhubner at common-lisp.net) Date: Thu, 7 Feb 2008 03:21:53 -0500 (EST) Subject: [bknr-cvs] r2450 - in branches/trunk-reorg/thirdparty/acl-compat: . allegro clisp cmucl lispworks mcl sbcl scl Message-ID: <20080207082153.3EC933C047@common-lisp.net> Author: hhubner Date: Thu Feb 7 03:21:48 2008 New Revision: 2450 Added: branches/trunk-reorg/thirdparty/acl-compat/ branches/trunk-reorg/thirdparty/acl-compat/CREDITS branches/trunk-reorg/thirdparty/acl-compat/ChangeLog branches/trunk-reorg/thirdparty/acl-compat/README branches/trunk-reorg/thirdparty/acl-compat/acl-compat-cmu.system branches/trunk-reorg/thirdparty/acl-compat/acl-compat-common-lisp-lw.lisp branches/trunk-reorg/thirdparty/acl-compat/acl-compat-corman.lisp branches/trunk-reorg/thirdparty/acl-compat/acl-compat.asd branches/trunk-reorg/thirdparty/acl-compat/acl-excl-common.lisp branches/trunk-reorg/thirdparty/acl-compat/acl-excl-corman.lisp branches/trunk-reorg/thirdparty/acl-compat/acl-mp-corman.lisp branches/trunk-reorg/thirdparty/acl-compat/acl-mp-package.lisp branches/trunk-reorg/thirdparty/acl-compat/acl-socket-corman.lisp branches/trunk-reorg/thirdparty/acl-compat/acl-ssl-streams.lisp branches/trunk-reorg/thirdparty/acl-compat/acl-ssl.lisp branches/trunk-reorg/thirdparty/acl-compat/allegro/ branches/trunk-reorg/thirdparty/acl-compat/allegro/acl-excl.lisp branches/trunk-reorg/thirdparty/acl-compat/allegro/acl-mp.lisp branches/trunk-reorg/thirdparty/acl-compat/allegro/acl-socket.lisp branches/trunk-reorg/thirdparty/acl-compat/allegro/acl-sys.lisp branches/trunk-reorg/thirdparty/acl-compat/chunked-stream-mixin.lisp branches/trunk-reorg/thirdparty/acl-compat/chunked.lisp (contents, props changed) branches/trunk-reorg/thirdparty/acl-compat/clisp/ branches/trunk-reorg/thirdparty/acl-compat/clisp/acl-excl.lisp branches/trunk-reorg/thirdparty/acl-compat/clisp/acl-mp.lisp branches/trunk-reorg/thirdparty/acl-compat/clisp/acl-socket.lisp branches/trunk-reorg/thirdparty/acl-compat/clisp/acl-sys.lisp branches/trunk-reorg/thirdparty/acl-compat/cmucl/ branches/trunk-reorg/thirdparty/acl-compat/cmucl/acl-excl.lisp branches/trunk-reorg/thirdparty/acl-compat/cmucl/acl-mp.lisp branches/trunk-reorg/thirdparty/acl-compat/cmucl/acl-socket.lisp branches/trunk-reorg/thirdparty/acl-compat/cmucl/acl-sys.lisp branches/trunk-reorg/thirdparty/acl-compat/defsys.lisp branches/trunk-reorg/thirdparty/acl-compat/lispworks/ branches/trunk-reorg/thirdparty/acl-compat/lispworks/acl-excl.lisp branches/trunk-reorg/thirdparty/acl-compat/lispworks/acl-mp.lisp branches/trunk-reorg/thirdparty/acl-compat/lispworks/acl-socket.lisp branches/trunk-reorg/thirdparty/acl-compat/lispworks/acl-sys.lisp branches/trunk-reorg/thirdparty/acl-compat/lw-buffering.lisp branches/trunk-reorg/thirdparty/acl-compat/mcl/ branches/trunk-reorg/thirdparty/acl-compat/mcl/acl-excl.lisp branches/trunk-reorg/thirdparty/acl-compat/mcl/acl-mp.lisp branches/trunk-reorg/thirdparty/acl-compat/mcl/acl-socket-mcl.lisp branches/trunk-reorg/thirdparty/acl-compat/mcl/acl-socket-openmcl.lisp branches/trunk-reorg/thirdparty/acl-compat/mcl/acl-sys.lisp branches/trunk-reorg/thirdparty/acl-compat/mcl/mcl-stream-fix.lisp branches/trunk-reorg/thirdparty/acl-compat/mcl/mcl-timers.lisp branches/trunk-reorg/thirdparty/acl-compat/packages.lisp branches/trunk-reorg/thirdparty/acl-compat/sbcl/ branches/trunk-reorg/thirdparty/acl-compat/sbcl/acl-excl.lisp branches/trunk-reorg/thirdparty/acl-compat/sbcl/acl-mp.lisp branches/trunk-reorg/thirdparty/acl-compat/sbcl/acl-socket.lisp branches/trunk-reorg/thirdparty/acl-compat/sbcl/acl-sys.lisp branches/trunk-reorg/thirdparty/acl-compat/scl/ branches/trunk-reorg/thirdparty/acl-compat/scl/acl-excl.lisp branches/trunk-reorg/thirdparty/acl-compat/scl/acl-mp.lisp branches/trunk-reorg/thirdparty/acl-compat/scl/acl-socket.lisp branches/trunk-reorg/thirdparty/acl-compat/scl/acl-sys.lisp branches/trunk-reorg/thirdparty/acl-compat/test-acl-socket.lisp (contents, props changed) Log: add acl-compat Added: branches/trunk-reorg/thirdparty/acl-compat/CREDITS ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/acl-compat/CREDITS Thu Feb 7 03:21:48 2008 @@ -0,0 +1,59 @@ +-*- text -*- + +CREDITS; a.k.a. the history of Portable AllegroServe + +This was written by Rudi Schlatte, who (knowing himself) is sure he +forgot some important contributors. Please mail me (rudi at +constantly.at) to point out any inconsistencies, don't be shy! + +* Corman Lisp + +The code that started it all. Chris Double took Allegro's +open-sourced code, got it to run on Corman Lisp and released the +code.. After Portable AllegroServe got off the ground, he re-arranged +his port so that it fit in the structure of acl-compat. + +* Xanalys LispWorks + +Jochen Schmidt ported Chris Double's AllegroServe port to LispWorks, +laid the groundwork for the "Portable" part of paserve and started +the SourceForge project. + +* cmucl + +cmucl was the third Lisp implementation to run Portable +AllegroServe. The port was done by Rudi Schlatte during his military +service out of sheer boredom. + +* Digitool MCL + +John DeSoi contributed this port and kept it working when the antics +of other developers broke his code once again. + +* OpenMCL + +Also done by John DeSoi. Gary Byers himself later contributed code to +support OpenMCL's OS-level threads (OpenMCL version 14 and up) in an +efficient way. + +* sbcl + +This port was done by Rudi Schlatte, using Daniel Barlow's sbcl +multiprocessing code in the McCLIM GUI project as inspiration. + +* clisp + +Also by Rudi Schlatte. Since clisp has no support for threads, +neither does acl-compat on this platform. Code can still be +compiled, however. + +* Scieneer Common Lisp + +This port was contributed by Douglas Crosher. + +* Allegro Common Lisp + +It may seem strange to implement an API on top of itself, but Kevin +Rosenberg's implementation makes it possible to run systems that use +acl-compat on ACL itself without source changes. + Added: branches/trunk-reorg/thirdparty/acl-compat/ChangeLog ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/acl-compat/ChangeLog Thu Feb 7 03:21:48 2008 @@ -0,0 +1,354 @@ +2006-01-22 Rudi Schlatte + + * sbcl/acl-mp.lisp (defun/sb-thread): silence compilation style + warning on single-threaded sbcl + + * sbcl/acl-excl.lisp (filesys-type): Fix bogus variable name :( + +2006-01-21 Rudi Schlatte + + * sbcl/acl-excl.lisp (filesys-type, filesys-inode): use sb-posix + instead of sbcl internals + +2005-08-05 Gabor Melis + + * sbcl/acl-mp.lisp: updated to use the thread object api + available since sbcl 0.9.2 + +2004-02-17 Rudi Schlatte + + * acl-excl-common.lisp (match-regexp): Make :return :index return + values same as ACL + +2004-02-16 Rudi Schlatte + + * acl-compat.asd: + - Add some meta-information to system definition + - Fix bug: all but the first :depends-on arguments are silently + ignored. :/ + +2004-02-16 Rudi Schlatte + + * packages.lisp: Remove references to nregex package. + + * acl-excl-common.lisp (match-regexp, compile-regexp): Implement + using cl-ppcre. + + * acl-compat.asd: Eliminate meta and nregex, use cl-ppcre instead. + +2004-02-14 Rudi Schlatte + + * acl-compat.asd: Make Gray streams loading on cmucl a little bit + saner (but only a little bit) + + * chunked-stream-mixin.lisp: Don't add to *features*, remove + provide form. + +2004-02-08 Rudi Schlatte + + * acl-compat.asd: Introduce dependency on puri, remove meta and + uri.lisp + +2004-02-02 Rudi Schlatte + + * cmucl/acl-mp.lisp (process-run-function): Give the new process + a run reason, so that it doesn't hang from the start. + + * cmucl/acl-socket.lisp (get-fd): Added method for server-socket. + +2004-01-28 Rudi Schlatte + + * packages.lisp: excl -> acl-compat.excl + + * lispworks/acl-socket.lisp: ditto. + +2004-01-27 Rudi Schlatte + + * chunked-stream-mixin.lisp: replace excl: package prefix with + acl-compat.excl: + +2004-01-26 Rudi Schlatte + + * mcl/acl-excl.lisp (fixnump): new function. + + * packages.lisp (:acl-compat.excl): Remove "excl" nickname. + + * clisp/acl-excl.lisp (fixnump): new function. + +2004-01-24 Rudi Schlatte + + * acl-excl-common.lisp (string-to-octets): null-terminate vector + when asked to. + + * cmucl/acl-excl.lisp, lispworks/acl-excl.lisp, mcl/acl-excl.lisp, + sbcl/acl-excl.lisp, scl/acl-excl.lisp: Move write-vector, + string-to-octets to commmon file. + + * acl-excl-common.lisp: Moved write-vector, string-to-octets from + implementation-specific files. + +2004-01-19 Rudi Schlatte + + * scl/acl-excl.lisp, sbcl/acl-excl.lisp, mcl/acl-excl.lisp, + lispworks/acl-excl.lisp, cmucl/acl-excl.lisp, + clisp/acl-excl.lisp: Remove common functionality from + implementation-specific files, dammit! + + * acl-compat.asd: Added acl-excl-common. + + * acl-excl-common.lisp: New file. + +2004-01-18 Rudi Schlatte + + * acl-excl-corman.lisp (intern*), sbcl/acl-excl.lisp (intern*), + mcl/acl-excl.lisp (intern*), lispworks/acl-excl.lisp (intern*), + cmucl/acl-excl.lisp (intern*), clisp/acl-excl.lisp (intern*), + scl/acl-excl.lisp (intern*): Don't upcase symbol before interning + (thanks to Marco Baringer, whose code was broken by this). Now + I'm motivated to factor out common code from all the backends ... + + * cmucl/acl-mp.lisp (apply-with-bindings): Fix "How did this ever + work" typo; thanks to Marco Baringer. + +2004-01-11 Rudi Schlatte + + * sbcl/acl-socket.lisp (make-socket): Handle :local-port nil, + don't bind socket in that case (let os choose a port) + +2004-01-11 Rudi Schlatte + + * packages.lisp (defpackage acl-compat.excl): Export some symbols + for mcl, too + + * mcl/acl-excl.lisp (run-shell-command): Implement (largely + untested for now, needed for cgi support) + + * mcl/acl-sys.lisp (command-line-argument, + command-line-arguments): Implement for OpenMCL + + * mcl/acl-mp.lisp (wait-for-input-available): Implement. Needed + for cgi support. + + * mcl/acl-socket-openmcl.lisp (server-socket): Remove :type slot + argument. + + * sbcl/acl-socket.lisp (make-socket): Add reuse-address argument. + + * cmucl/acl-socket.lisp (make-socket): Add reuse-address argument. + + * acl-compat.asd: Load sb-posix for sbcl. + +2003-12-15 Rudi Schlatte + + NOTE: this checkin has a reasonable chance of breaking (and mcl + (not openmcl)) + + * mcl/acl-socket-openmcl.lisp: Remove package definition, + implement chunked transfer encoding (accepting a speed loss in the + process) + + * mcl/acl-excl.lisp, mcl/acl-mp.lisp, mcl/acl-sys.lisp: remove + package definitions + + * uri.lisp: deftype also at load time; openmcl breaks otherwise + + * packages.lisp: mcl doesn't have stream-(read,write)-sequence + + * lw-buffering.lisp: formatting frobs. + + * acl-compat.asd: Merge mcl defsystem with the others. + + * sbcl/acl-socket.lisp: Use acl-compat.socket package name. + +2003-12-02 Rudi Schlatte + + * meta.lisp (enable-meta-syntax): Save current readtable before + installing *meta-readtable*. + +2003-12-01 Rudi Schlatte + + * chunked-stream-mixin.lisp: Merge Lispworks patch from Edi Weitz + (paserve-help 2003-11-28) + +2003-11-27 Rudi Schlatte + + * chunked-stream-mixin.lisp (gray-stream:stream-fill-buffer): + LispWorks refill-buffer does not always return the amount of + bytes read (reported by Edi Weitz to paserve-discuss + 2003-11-26). Treat its return value as a boolean. + + * lw-buffering.lisp (stream-fill-buffer): Remove cmucl-specific + read-n-bytes call because it does block after all :( + + * chunked-stream-mixin.lisp (gray-stream:stream-fill-buffer): Fix + for Lispworks client mode contributed by Edi Weitz to + paserve-discuss list on 2003-11-25 + + * sbcl/acl-mp.lisp: Single-threaded "implementation" of process-name + +2003-09-19 Rudi Schlatte + + * sbcl/acl-mp.lisp: Merged threading patch from Brian Downing + (posted to portableaserve-discuss 2003-09-12) + + * clisp/acl-excl.lisp, clisp/acl-socket.lisp: Eliminate compile + failures, activate chunked support for clisp (forwarded by Kevin + M. Rosenberg from Debian) + +2003-08-31 Rudi Schlatte + + * acl-compat.asd: Remove old cmu-read-sequence cruft, bug is fixed + in reasonably recent cmucl + + * lw-buffering.lisp (stream-fill-buffer): Use package-external + symbol that doesn't break on CVS cmucl + +2003-08-30 Rudi Schlatte + + * cmucl/acl-socket.lisp (make-socket): set reuse-address option. + + * lw-buffering.lisp (stream-fill-buffer): Implement b/nb semantics + for cmucl as well. client mode should now neither hang trying to + read closed streams nor give spurious errors for slow servers. + +2003-08-17 Rudi Schlatte + + * sbcl/acl-mp.lisp (with-timeout): Eliminate unused-variable + warning. + +2003-05-13 Rudi Schlatte + + * cmucl/acl-sys.lisp, cmucl/acl-socket.lisp, cmucl/acl-excl.lisp: + Use correct package names in in-package forms (Reported by Johan + Parin) + + * packages.lisp (acl-compat.system): Add nickname acl-compat.sys, + remove commented-out nicknames. + + * lispworks/acl-sys.lisp: push MSWINDOWS onto *features* if + appropriate (Thanks to Alain Picard for the report). + +2003-05-11 Rudi Schlatte + + * acl-compat.asd: Don't load read-/write-sequence patches on cmucl + 18e. + +2003-05-06 Rudi Schlatte + + * lw-buffering.lisp (stream-fill-buffer): Implement + blocking/non-blocking semantics (read at least one byte per + fill-buffer call). Otherwise we'd get spurious EOFs with slow + servers. + + * chunked-stream-mixin.lisp (gray-stream:stream-fill-buffer): + Return a sensible value (amount of bytes that can be read before + next call to fill-buffer). + +2003-05-03 Rudi Schlatte + + * chunked-stream-mixin.lisp (gray-stream:stream-fill-buffer): Make + input-chunking work, refactor somewhat to make all slot changes in + one place. + +2003-05-02 Rudi Schlatte + + * acl-compat.asd (acl-compat): Current cmucl versions handle Gray + streams in (read,write)-sequence -- remove hack + +2003-04-30 Rudi Schlatte + + * sbcl/acl-mp.lisp (with-timeout): Use timeout symbols from the + ext package; latest cvs exports them + + * cmucl/acl-mp.lisp: Use acl-compat.mp package name. + + * acl-compat.asd et al: The Great Renaming: begin move of + implementation-dependent files into subdirectories + +2003-04-27 Rudi Schlatte + + * acl-socket-sbcl.lisp: Implemented peername lookup (by storing + the socket in the plist of the bivalent stream object for now) + +2003-04-26 Rudi Schlatte + + * acl-mp-sbcl.lisp: Add initial support for multi-threaded sbcl + +2003-04-08 Rudi Schlatte + + * uri.lisp (render-uri): Reinstate with-output-to-string logic; + render-uri has to handle nil as a stream value. + +2003-04-03 Rudi Schlatte + + * uri.lisp (render-uri, print-object): Further frob printing of + URIs, inspired by patch of Harley Gorrell + +2003-04-02 Rudi Schlatte + + * uri.lisp (render-uri): Fix printing URIs in the presence of #\~ + (Thanks to Harley Gorrell) + +2003-03-24 Rudi Schlatte + + * lw-buffering.lisp (stream-write-buffer, stream-flush-buffer): + Eliminate "wait" parameter to regain api-compatibility with lispworks + (stream-finish-output, stream-force-output): Call (finish|force)-output + here instead of using "wait" parameter of stream-flush-buffer + + * chunked-stream-mixin.lisp: some documentation added, formatting, + eliminate use of "wait" parameter on stream-write-buffer etc. + +2003-02-28 Rudi Schlatte + + * acl-socket-sbcl.lisp: + (remote-host, remote-port, local-host, local-port): Change return + value to something convertible to an (invalid) inet address + + * acl-compat.asd, packages.lisp: Support sbcl 0.7.13 single-threaded + +2002-12-26 Rudi Schlatte + + * lw-buffering.lisp (write-elements): end argument value can be + nil (fix contributed by Simon Andras 2002-12-24) + + * meta.lisp: Switch to new-style eval-when times + + * lw-buffering.lisp: Switch to new-style eval-when times + (defstruct buffer-state): Add type declarations + (stream-fill-buffer): Remove bug for non-cmucl case (need + unblocking read-sequence) + + * chunked-stream-mixin.lisp: Add defgeneric forms + + * acl-socket-sbcl.lisp: Enable chunked transfer encoding support + +2002-12-23 Rudi Schlatte + + * packages.lisp, acl-sys-sbcl.lisp: Various sbcl fixes + +2002-12-18 Rudi Schlatte + + * packages.lisp: Add package definition of + de.dataheaven.chunked-stream-mixin, remove nicknames for + acl-compat.system + +2002-12-17 Rudi Schlatte + + * (Module): Added first stab at sbcl support (some stub + functions, basic page serving works) + +2002-12-13 Rudi Schlatte + + * lw-buffering.lisp (stream-write-sequence): Make publish-multi + work (provide default value for start arg). + + * acl-excl-cmu.lisp (write-vector): ditto. + +2002-12-03 Rudi Schlatte + + * acl-compat.asd: load lw-buffering in every implementation except + lispworks + + * packages.lisp: define gray-stream package for every + implementation Added: branches/trunk-reorg/thirdparty/acl-compat/README ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/acl-compat/README Thu Feb 7 03:21:48 2008 @@ -0,0 +1,33 @@ +-*- text -*- + +acl-compat is a library that implements parts of the Allegro Common +Lisp (ACL) API for areas that are not covered by the ANSI Common Lisp +standard itself (e.g. sockets, threading). The motivation for +creating and maintaining acl-compat is to get the web server +AllegroServe (that was released by Franz Inc under the LLGPL) running +on a wide range of Lisp implementations, with as few source changes to +its core code as possible. + +acl-compat names its packages by prepending the corresponding ACL +package name with the string "ACL-COMPAT.". For example, the ACL +threading API symbols are exported from the package ACL-COMPAT.MP. +Ideally, ACL-specific code could run on any supported Lisp +implementation only by changing package references. + +Of course, the present situation is not ideal. :( Functionality is +only implemented on an as-needed basis, implemented functions don't +handle all argument combinations properly, etc. On the other hand, +enough is implemented to support a web and application server that +exercises a wide range of functionality (client and server sockets, +threading, etc.). + + +To load acl-compat: + +- install asdf (see < http://www.cliki.net/asdf >) and make sure it's + loaded. + +- load acl-compat.asd + +- evaluate (asdf:operate 'asdf:load-op :acl-compat) + Added: branches/trunk-reorg/thirdparty/acl-compat/acl-compat-cmu.system ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/acl-compat/acl-compat-cmu.system Thu Feb 7 03:21:48 2008 @@ -0,0 +1,36 @@ +;;; -*- mode: lisp -*- + +(in-package :CL-USER) + +;; Stig: we're a debian-package if clc is present +;; Rudi: Not if kludge-no-cclan is also present +#+(and common-lisp-controller (not kludge-no-cclan)) +(setf (logical-pathname-translations "acl-compat") + '(("**;*.*.*" "cl-library:;acl-compat;**;*.*.*"))) + +(mk:defsystem "ACL-COMPAT" + :source-pathname (make-pathname :directory + (pathname-directory *load-truename*)) ;"acl-compat:" +; :source-extension "lisp" +; :binary-pathname nil +; :binary-extension nil + :components ((:file "nregex") + (:file "packages" :depends-on ("nregex")) + (:file "lw-buffering" :depends-on ("packages")) + (:file "acl-mp-cmu" :depends-on ("packages")) + (:file "acl-excl-cmu" :depends-on ("packages" "nregex")) + (:file "cmu-read-sequence") + (:file "acl-socket-cmu" + :depends-on ("packages" "acl-excl-cmu" + "chunked-stream-mixin" + "cmu-read-sequence")) + (:file "acl-sys-cmu" :depends-on ("packages")) + (:file "meta") + (:file "uri" :depends-on ("meta")) + (:file "chunked-stream-mixin" + :depends-on ("packages" "acl-excl-cmu" + "lw-buffering"))) + ;; Stig: if we're CMU and a debian-package, we need graystreams + #+(and cmu common-lisp-controller) + :depends-on + #+(and cmu common-lisp-controller) (cmucl-graystream)) Added: branches/trunk-reorg/thirdparty/acl-compat/acl-compat-common-lisp-lw.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/acl-compat/acl-compat-common-lisp-lw.lisp Thu Feb 7 03:21:48 2008 @@ -0,0 +1,21 @@ +(defpackage acl-compat-common-lisp + (:use common-lisp) + (:shadow make-hash-table) + (:export make-hash-table)) + +(in-package :acl-compat-common-lisp) + +(defun make-hash-table (&rest args &key test size rehash-size rehash-threshold (hash-function nil h-f-p) + (values t) weak-keys) + (declare (ignore hash-function)) + (when h-f-p (error "User defined hash-functions are not supported.")) + (let ((table (apply #'cl:make-hash-table :allow-other-keys t args))) + (hcl:set-hash-table-weak table + (if weak-keys + (if (eq values :weak) + :both + :key) + (if (eq values :weak) + :value + nil))) + table)) \ No newline at end of file Added: branches/trunk-reorg/thirdparty/acl-compat/acl-compat-corman.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/acl-compat/acl-compat-corman.lisp Thu Feb 7 03:21:48 2008 @@ -0,0 +1,13 @@ +(require 'gray-streams) +(in-package :cl-user) + +(defvar *acl-compat-directory* "d:/projects/lisp/portableaserve/acl-compat/") +(load (concatenate 'string *acl-compat-directory* "nregex.lisp")) +(load (concatenate 'string *acl-compat-directory* "meta.lisp")) +(load (concatenate 'string *acl-compat-directory* "acl-excl-corman.lisp")) +(load (concatenate 'string *acl-compat-directory* "acl-mp-corman.lisp")) +(load (concatenate 'string *acl-compat-directory* "acl-socket-corman.lisp")) +(load (concatenate 'string *acl-compat-directory* "uri.lisp")) +(load (concatenate 'string *acl-compat-directory* "packages.lisp")) + +(pushnew :acl-compat *features*) \ No newline at end of file Added: branches/trunk-reorg/thirdparty/acl-compat/acl-compat.asd ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/acl-compat/acl-compat.asd Thu Feb 7 03:21:48 2008 @@ -0,0 +1,182 @@ +;;;; -*- mode: lisp -*- +;;;; +;;;; This as an ASDF system for ACL-COMPAT, meant to replace +;;;; acl-compat-cmu.system, but could replace all other systems, too. +;;;; (hint, hint) + +(defpackage #:acl-compat-system + (:use #:cl #:asdf)) +(in-package #:acl-compat-system) + +;;;; gray stream support for cmucl: Debian/common-lisp-controller has +;;;; a `cmucl-graystream' system; if this is not found, we assume a +;;;; cmucl downloaded from cons.org, where Gray stream support resides +;;;; in the subsystems/ directory. + + +#+cmu +(progn + +(defclass precompiled-file (static-file) + ()) + +(defmethod perform ((operation load-op) (c precompiled-file)) + (load (component-pathname c))) + +(defmethod operation-done-p ((operation load-op) (c precompiled-file)) + nil) + +#-gray-streams +(eval-when (:compile-toplevel :load-toplevel :execute) + (unless (asdf:find-system :cmucl-graystream nil) + (asdf:defsystem cmucl-graystream + :pathname (make-pathname + :name nil :type nil :version nil + :defaults (truename "library:subsystems/gray-streams-library.x86f")) + :components ((:precompiled-file "gray-streams-library.x86f"))))) +) + +;;;; ignore warnings +;;;; +;;;; FIXME: should better fix warnings instead of ignoring them +;;;; FIXME: (perform legacy-cl-sourcefile) duplicates ASDF code + +(defclass legacy-cl-source-file (cl-source-file) + () + (:documentation + "Common Lisp source code module with (non-style) warnings. +In contrast to CL-SOURCE-FILE, this class does not think that such warnings +indicate failure.")) + +(defmethod perform ((operation compile-op) (c legacy-cl-source-file)) + (let ((source-file (component-pathname c)) + (output-file (car (output-files operation c))) + (warnings-p nil) + (failure-p nil)) + (setf (asdf::component-property c 'last-compiled) nil) + (handler-bind ((warning (lambda (c) + (declare (ignore c)) + (setq warnings-p t))) + ;; _not_ (or error (and warning (not style-warning))) + (error (lambda (c) + (declare (ignore c)) + (setq failure-p t)))) + (compile-file source-file + :output-file output-file)) + ;; rest of this method is as for CL-SOURCE-FILE + (setf (asdf::component-property c 'last-compiled) (file-write-date output-file)) + (when warnings-p + (case (asdf::operation-on-warnings operation) + (:warn (warn "COMPILE-FILE warned while performing ~A on ~A" + c operation)) + (:error (error 'compile-warned :component c :operation operation)) + (:ignore nil))) + (when failure-p + (case (asdf::operation-on-failure operation) + (:warn (warn "COMPILE-FILE failed while performing ~A on ~A" + c operation)) + (:error (error 'compile-failed :component c :operation operation)) + (:ignore nil))))) + +;;; +;;; This is thought to reduce reader-conditionals in the system definition +;;; +(defclass unportable-cl-source-file (cl-source-file) () + (:documentation + "This is for files which contain lisp-system dependent code. Until now those +are marked by a -system postfix but we could later change that to a directory per +lisp-system")) + +(defmethod perform ((op load-op) (c unportable-cl-source-file)) + (#+cmu ext:without-package-locks + #-(or cmu) progn + (call-next-method))) + +(defmethod perform ((op compile-op) (c unportable-cl-source-file)) + (#+cmu ext:without-package-locks + #-(or cmu) progn + (call-next-method))) + +(defmethod source-file-type ((c unportable-cl-source-file) (s module)) + "lisp") + + +(defun lisp-system-shortname () + #+allegro :allegro #+lispworks :lispworks #+cmu :cmucl + #+(or mcl openmcl) :mcl #+clisp :clisp #+scl :scl #+sbcl :sbcl) ;mcl/openmcl use the same directory + +(defmethod component-pathname ((component unportable-cl-source-file)) + (let ((pathname (call-next-method)) + (name (string-downcase (lisp-system-shortname)))) + (merge-pathnames + (make-pathname :directory (list :relative name)) + pathname))) + +;;;; system + +#+(and mcl (not openmcl)) (require :ansi-make-load-form) + +(defsystem acl-compat + :name "acl-compat" + :author "The acl-compat team" + :version "0.1.1" + :description + "A reimplementation of parts of the ACL API, mainly to get + AllegroServe running on various machines, but might be useful + in other projects as well." + :properties + ((("system" "author" "email") . "portableaserve-discuss at lists.sourceforge.net") + (("albert" "presentation" "output-dir") . "docs/") + (("albert" "presentation" "formats") . "docbook") + (("albert" "docbook" "dtd") . "/Users/Shared/DocBook/lib/docbook/docbook-dtd-412/docbookx.dtd") + (("albert" "docbook" "template") . "book")) + :components + ( + ;; packages + (:file "packages") + ;; Our stream class; support for buffering, chunking and (in the + ;; future) unified stream exceptions + #-(or lispworks (and mcl (not openmcl))) + (:file "lw-buffering" :depends-on ("packages")) + #-(or allegro (and mcl (not openmcl))) + (:legacy-cl-source-file "chunked-stream-mixin" + :depends-on ("packages" "acl-excl" + #-lispworks "lw-buffering")) + ;; Multiprocessing + #+(or mcl openmcl) (:unportable-cl-source-file "mcl-timers") + (:unportable-cl-source-file "acl-mp" + :depends-on ("packages" #+(or mcl openmcl) "mcl-timers")) + ;; Sockets, networking; TODO: de-frob this a bit + #-(or mcl openmcl) + (:unportable-cl-source-file + "acl-socket" :depends-on ("packages" "acl-excl" + #-(or allegro (and mcl (not openmcl))) "chunked-stream-mixin")) + #+(and mcl (not openmcl)) + (:unportable-cl-source-file "acl-socket-mcl" :depends-on ("packages")) + #+(and mcl (not openmcl) (not carbon-compat)) + (:unportable-cl-source-file + "mcl-stream-fix" :depends-on ("acl-socket-mcl")) + #+openmcl + (:unportable-cl-source-file + "acl-socket-openmcl" :depends-on ("packages" "chunked-stream-mixin")) + ;; Diverse macros, utility functions + #-allegro (:file "acl-excl-common" :depends-on ("packages")) + (:unportable-cl-source-file "acl-excl" :depends-on + #-allegro ("acl-excl-common") + #+allegro ("packages")) + (:unportable-cl-source-file "acl-sys" :depends-on ("packages")) + ;; SSL + #+(and ssl-available (not (or allegro mcl openmcl clisp))) + (:file "acl-ssl" :depends-on ("acl-ssl-streams" "acl-socket")) + #+(and ssl-available (not (or allegro mcl openmcl clisp))) + (:file "acl-ssl-streams" :depends-on ("packages"))) + ;; Dependencies + :depends-on (:puri + :cl-ppcre + #+sbcl :sb-bsd-sockets + #+sbcl :sb-posix + #+(and cmu (not gray-streams)) :cmucl-graystream + #+(and (or cmu lispworks) ssl-available) :cl-ssl + ) + :perform (load-op :after (op acl-compat) + (pushnew :acl-compat cl:*features*))) Added: branches/trunk-reorg/thirdparty/acl-compat/acl-excl-common.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/acl-compat/acl-excl-common.lisp Thu Feb 7 03:21:48 2008 @@ -0,0 +1,194 @@ +;;;; +;;;; ACL-COMPAT - EXCL +;;;; +;;;; This is a modified version of Chris Doubles ACL excl wrapper library +;;;; As stated in the changelogs of his original this file includes the +;;;; IF* macro placed in the public domain by John Foderaro. +;;;; See: http://www.franz.com/~jkf/ifstar.txt +;;;; + +;;;; This file was made by Rudi Schlatte to gather +;;;; not-implementation-specific parts of acl-compat in one place. + +;;;; This is the header of Chris Doubles original file. (but without Changelog) +;;;; +;;;; ACL excl wrapper library for Corman Lisp - Version 1.1 +;;;; +;;;; Copyright (C) 2000 Christopher Double. All Rights Reserved. +;;;; +;;;; License +;;;; ======= +;;;; This software is provided 'as-is', without any express or implied +;;;; warranty. In no event will the author be held liable for any damages +;;;; arising from the use of this software. +;;;; +;;;; Permission is granted to anyone to use this software for any purpose, +;;;; including commercial applications, and to alter it and redistribute +;;;; it freely, subject to the following restrictions: +;;;; +;;;; 1. The origin of this software must not be misrepresented; you must +;;;; not claim that you wrote the original software. If you use this +;;;; software in a product, an acknowledgment in the product documentation +;;;; would be appreciated but is not required. +;;;; +;;;; 2. Altered source versions must be plainly marked as such, and must +;;;; not be misrepresented as being the original software. +;;;; +;;;; 3. This notice may not be removed or altered from any source +;;;; distribution. +;;;; + +(in-package :acl-compat.excl) + +(defvar if*-keyword-list '("then" "thenret" "else" "elseif")) + +;this is not used in aserve, but is needed to use the franz xmlutils package with acl-compat +(defvar *current-case-mode* :case-insensitive-upper) + +(defmacro if* (&rest args) + (do ((xx (reverse args) (cdr xx)) + (state :init) + (elseseen nil) + (totalcol nil) + (lookat nil nil) + (col nil)) + ((null xx) + (cond ((eq state :compl) + `(cond , at totalcol)) + (t (error "if*: illegal form ~s" args)))) + (cond ((and (symbolp (car xx)) + (member (symbol-name (car xx)) + if*-keyword-list + :test #'string-equal)) + (setq lookat (symbol-name (car xx))))) + + (cond ((eq state :init) + (cond (lookat (cond ((string-equal lookat "thenret") + (setq col nil + state :then)) + (t (error + "if*: bad keyword ~a" lookat)))) + (t (setq state :col + col nil) + (push (car xx) col)))) + ((eq state :col) + (cond (lookat + (cond ((string-equal lookat "else") + (cond (elseseen + (error + "if*: multiples elses"))) + (setq elseseen t) + (setq state :init) + (push `(t , at col) totalcol)) + ((string-equal lookat "then") + (setq state :then)) + (t (error "if*: bad keyword ~s" + lookat)))) + (t (push (car xx) col)))) + ((eq state :then) + (cond (lookat + (error + "if*: keyword ~s at the wrong place " (car xx))) + (t (setq state :compl) + (push `(,(car xx) , at col) totalcol)))) + ((eq state :compl) + (cond ((not (string-equal lookat "elseif")) + (error "if*: missing elseif clause "))) + (setq state :init))))) + +(defvar *initial-terminal-io* *terminal-io*) +(defvar *cl-default-special-bindings* nil) + +(defun filesys-size (stream) + (file-length stream)) + +(defun filesys-write-date (stream) + (file-write-date stream)) + +(defun frob-regexp (regexp) + "This converts from ACL regexps to Perl regexps. The escape + status of (, ) and | is toggled." + (let ((escapees '(#\) #\( #\| ))) + (with-input-from-string (in regexp) + (with-output-to-string (out) + (loop for c = (read-char in nil nil nil) + while c + do (cond ((and (char= c #\\) + (member (peek-char nil in nil nil nil) escapees)) + (setf c (read-char in))) + ((member c escapees) + (princ #\\ out))) + (princ c out)))))) + +;; TODO: a compiler macro for constant string regexps would be nice, +;; so that the create-scanner call at runtime can be evaded. +(defun match-regexp (string-or-regexp string-to-match + &key newlines-special case-fold return + (start 0) end shortest) + "Note: if a regexp compiled with compile-regexp is passed, the + options newlines-special and case-fold shouldn't be used, since + the underlying engine uses them when generating the scanner, + not when executing it." + (when shortest (error "match-regexp: shortest option not supported yet.")) + (unless end (setf end (length string-to-match))) + (let ((scanner (cl-ppcre:create-scanner (frob-regexp string-or-regexp) + :case-insensitive-mode case-fold + :single-line-mode newlines-special))) + (ecase return + (:string ; return t, list of strings + (multiple-value-bind (match regs) + (cl-ppcre:scan-to-strings scanner string-to-match + :start start :end end) + (if match + (apply #'values t match (coerce regs 'list)) + nil))) + (:index ; return (cons start end) + (multiple-value-bind (start end reg-starts reg-ends) + (cl-ppcre:scan scanner string-to-match :start start :end end) + (and start (apply #'values t (cons start end) + (map 'list #'cons reg-starts reg-ends))))) + ((nil) ; return t + (not (not (cl-ppcre:scan scanner string-to-match + :start start :end end))))))) + + +;; Caution Incompatible APIs! cl-ppcre has options case-insensitive, +;; single-line for create-scanner, ACL has it in match-regexp. +(defun compile-regexp (regexp) + "Note: Take care when using scanners compiled with this option + to not depend on options case-fold and newlines-special in match-regexp." + (cl-ppcre:create-scanner (frob-regexp regexp))) + +(defvar *current-case-mode* :case-insensitive-upper) + +(defun intern* (s len package) + (intern (subseq s 0 len) package)) + +(defmacro errorset (form &optional (announce nil) (catch-breaks nil)) + "This macro is incomplete. It was hacked to get AllegroServe +running, but the announce and catch-breaks arguments are ignored. See +documentation at +http://franz.com/support/documentation/6.1/doc/pages/operators/excl/errorset.htm +An implementation of the catch-breaks argument will necessarily be +implementation-dependent, since Ansi does not allow any +program-controlled interception of a break." + (declare (ignore announce catch-breaks)) + `(let* ((ok nil) + (results (ignore-errors + (prog1 (multiple-value-list ,form) + (setq ok t))))) + (if ok + (apply #'values t results) + nil))) + +(defmacro fast (&body forms) + `(locally (declare (optimize (speed 3) (safety 0) (debug 0))) + , at forms)) + +#-cmu +(defun write-vector (sequence stream &key (start 0) end endian-swap) + (declare (ignore endian-swap)) + (check-type sequence (or string (array (unsigned-byte 8) 1) + (array (signed-byte 8) 1))) + (write-sequence sequence stream :start start :end end)) + Added: branches/trunk-reorg/thirdparty/acl-compat/acl-excl-corman.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/acl-compat/acl-excl-corman.lisp Thu Feb 7 03:21:48 2008 @@ -0,0 +1,233 @@ +;;;; +;;;; ACL-COMPAT - EXCL +;;;; +;;;; This is a modified version of Chris Doubles ACL excl wrapper library +;;;; As stated in the changelogs of his original this file includes the +;;;; IF* macro placed in the public domain by John Foderaro. +;;;; See: http://www.franz.com/~jkf/ifstar.txt +;;;; +;;;; It is not clear to this point if future releases will lead to a combined +;;;; effort - So you may find newer versions of *this* file at +;;;; http://www.dataheaven.de +;;;; + +;;;; This is the header of Chris Doubles original file. (but without Changelog) +;;;; +;;;; ACL excl wrapper library for Corman Lisp - Version 1.1 +;;;; +;;;; Copyright (C) 2000 Christopher Double. All Rights Reserved. +;;;; +;;;; License +;;;; ======= +;;;; This software is provided 'as-is', without any express or implied +;;;; warranty. In no event will the author be held liable for any damages +;;;; arising from the use of this software. +;;;; +;;;; Permission is granted to anyone to use this software for any purpose, +;;;; including commercial applications, and to alter it and redistribute +;;;; it freely, subject to the following restrictions: +;;;; +;;;; 1. The origin of this software must not be misrepresented; you must +;;;; not claim that you wrote the original software. If you use this +;;;; software in a product, an acknowledgment in the product documentation +;;;; would be appreciated but is not required. +;;;; +;;;; 2. Altered source versions must be plainly marked as such, and must +;;;; not be misrepresented as being the original software. +;;;; +;;;; 3. This notice may not be removed or altered from any source +;;;; distribution. +;;;; +;;;; Notes +;;;; ===== +;;;; A simple implementation of some of the EXCL package from Allegro +;;;; Common Lisp. Intended to be used for porting various ACL packages, +;;;; like AllegroServe. +;;;; +;;;; More recent versions of this software may be available at: +;;;; http://www.double.co.nz/cl +;;;; +;;;; Comments, suggestions and bug reports to the author, +;;;; Christopher Double, at: chris at double.co.nz + +(require 'nregex) +(require 'mp) + +(defpackage :excl + (:use :common-lisp :nregex) + (:import-from :common-lisp "FIXNUMP") + (:export + "IF*" + "*INITIAL-TERMINAL-IO*" + "*CL-DEFAULT-SPECIAL-BINDINGS*" + "FILESYS-SIZE" + "FILESYS-WRITE-DATE" + "STREAM-INPUT-FN" + "MATCH-REGEXP" + "COMPILE-REGEXP" + "*CURRENT-CASE-MODE*" + "INTERN*" + "FILESYS-TYPE" + "ERRORSET" + "ATOMICALLY" + "FAST" + "WITHOUT-PACKAGE-LOCKS" + "SOCKET-ERROR" + "RUN-SHELL-COMMAND" + "FIXNUMP" + )) + +(in-package :excl) + +(defvar if*-keyword-list '("then" "thenret" "else" "elseif")) + +(defmacro if* (&rest args) + (do ((xx (reverse args) (cdr xx)) + (state :init) + (elseseen nil) + (totalcol nil) + (lookat nil nil) + (col nil)) + ((null xx) + (cond ((eq state :compl) + `(cond , at totalcol)) + (t (error "if*: illegal form ~s" args)))) + (cond ((and (symbolp (car xx)) + (member (symbol-name (car xx)) + if*-keyword-list + :test #'string-equal)) + (setq lookat (symbol-name (car xx))))) + + (cond ((eq state :init) + (cond (lookat (cond ((string-equal lookat "thenret") + (setq col nil + state :then)) + (t (error + "if*: bad keyword ~a" lookat)))) + (t (setq state :col + col nil) + (push (car xx) col)))) + ((eq state :col) + (cond (lookat + (cond ((string-equal lookat "else") + (cond (elseseen + (error + "if*: multiples elses"))) + (setq elseseen t) + (setq state :init) + (push `(t , at col) totalcol)) + ((string-equal lookat "then") + (setq state :then)) + (t (error "if*: bad keyword ~s" + lookat)))) + (t (push (car xx) col)))) + ((eq state :then) + (cond (lookat + (error + "if*: keyword ~s at the wrong place " (car xx))) + (t (setq state :compl) + (push `(,(car xx) , at col) totalcol)))) + ((eq state :compl) + (cond ((not (string-equal lookat "elseif")) + (error "if*: missing elseif clause "))) + (setq state :init))))) + +(defvar *initial-terminal-io* *terminal-io*) +(defvar *cl-default-special-bindings* nil) + +(defun filesys-size (stream) + (file-length stream)) + +(defun filesys-write-date (stream) + (file-write-date stream)) + +#+obsolete +(defun stream-input-fn (stream) + stream) + +(defmethod stream-input-fn ((stream stream)) + stream) + + +(defun match-regexp (pattern string &key (return :string)) + (let ((res (cond ((stringp pattern) + (regex pattern string)) + ((functionp pattern) (funcall pattern string)) + (t (error "Wrong type for pattern"))))) + (case return + (:string + (values-list (cons (not (null res)) + res))) + (:index (error "REGEXP: INDEX Not implemented")) + (otherwise (not (null res)))))) + +(defun compile-regexp (regexp) + (compile nil (regex-compile regexp))) + +(defvar *current-case-mode* :case-insensitive-upper) + +(defun intern* (s len package) + (intern (subseq s 0 len) package)) + +(defun filesys-type (file-or-directory-name) + (if (ccl::directory-p file-or-directory-name) + :directory + (if (probe-file file-or-directory-name) + :file + nil))) + +(defmacro errorset (form &optional (announce nil) (catch-breaks nil)) + "This macro is incomplete. It was hacked to get AllegroServe +running, but the announce and catch-breaks arguments are ignored. See +documentation at +http://franz.com/support/documentation/6.1/doc/pages/operators/excl/errorset.htm +An implementation of the catch-breaks argument will necessarily be +implementation-dependent, since Ansi does not allow any +program-controlled interception of a break." + (declare (ignore announce catch-breaks)) + `(let* ((ok nil) + (results (ignore-errors + (prog1 (multiple-value-list ,form) + (setq ok t))))) + (if ok + (apply #'values t results) + nil))) + + +(defmacro atomically (&body forms) + `(mp:without-scheduling , at forms)) + +(defmacro fast (&body forms) + `(locally (declare (optimize (speed 3) (safety 0) (debug 0))) + , at forms)) + +(defmacro without-package-locks (&body forms) + `(progn , at forms)) + +(define-condition socket-error (error) + ((stream :initarg :stream) + (code :initarg :code :initform nil) + (action :initarg :action) + (identifier :initarg :identifier :initform nil)) + (:report (lambda (e s) + (with-slots (identifier code action stream) e + (format s "~S (errno ~A) occured while ~A" + (case identifier + (:connection-refused "Connection refused") + (t identifier)) + code action) + (when stream + (prin1 stream s)) + (format s "."))))) + +#| +(defun run-shell-command () + (with-open-stream (s (open-pipe "/bin/sh" + :direction :io + :buffered nil)) + (loop for var in environment + do (format stream "~A=~A~%" (car var) (cdr var))) +|# + + +(provide 'acl-excl) Added: branches/trunk-reorg/thirdparty/acl-compat/acl-mp-corman.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/acl-compat/acl-mp-corman.lisp Thu Feb 7 03:21:48 2008 @@ -0,0 +1,52 @@ +;;; This file implements the process functions for AllegroServe in Corman Lisp. + +(require 'mp) + +(defpackage :acl-compat-mp + (:use :common-lisp :mp :sys) + (:export + #:process-interrrupt + #:make-process + #:make-process-lock + #:process-add-run-reason + #:process-kill + #:process-property-list + #:process-revoke-run-reason + #:process-run-function + #:with-process-lock + #:with-timeout + #:without-scheduling + #:*current-process* + #:lock + #:process-allow-schedule + #:process-name + #:process-preset + #:process-run-reasons + #:process-wait + #:without-interrupts + )) + +(in-package :acl-compat-mp) + +; existing stuff from ccl we can reuse directly +;; The following process-property-list implementation was taken from +;; the acl-mp-scl.lisp implementation. +(defvar *process-plists* (make-hash-table :test #'eq) + "maps processes to their plists. +See the functions process-plist, (setf process-plist).") + +(defun process-property-list (process) + (gethash process *process-plists*)) + +(defun (setf process-property-list) (new-value process) + (setf (gethash process *process-plists*) new-value)) + +;; Dummy implementation of process-wait +(defun process-wait (whostate function &rest args) + "This function suspends the current process (the value of sys:*current-process*) + until applying function to arguments yields true. The whostate argument must be a + string which temporarily replaces the process' whostate for the duration of the wait. + This function returns nil." + (loop until (apply function args) do (sleep 0)) + nil) + Added: branches/trunk-reorg/thirdparty/acl-compat/acl-mp-package.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/acl-compat/acl-mp-package.lisp Thu Feb 7 03:21:48 2008 @@ -0,0 +1,80 @@ +;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Package: CL-USER; -*- +;;;; ; +;;;; (c) 2001 by Jochen Schmidt. +;;;; +;;;; File: acl-mp-package.lisp +;;;; Revision: 1.0.0 +;;;; Description: Package definition for ACL-COMPAT-MP +;;;; Date: 02.02.2002 +;;;; Authors: Jochen Schmidt +;;;; Tel: (+49 9 11) 47 20 603 +;;;; Email: jsc at dataheaven.de +;;;; +;;;; Redistribution and use in source and binary forms, with or without +;;;; modification, are permitted provided that the following conditions +;;;; are met: +;;;; 1. Redistributions of source code must retain the above copyright +;;;; notice, this list of conditions and the following disclaimer. +;;;; 2. Redistributions in binary form must reproduce the above copyright +;;;; notice, this list of conditions and the following disclaimer in the +;;;; documentation and/or other materials provided with the distribution. +;;;; +;;;; THIS SOFTWARE IS PROVIDED "AS IS" AND THERE ARE NEITHER +;;;; EXPRESSED NOR IMPLIED WARRANTIES - THIS INCLUDES, BUT +;;;; IS NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY +;;;; AND FITNESS FOR A PARTICULAR PURPOSE.IN NO WAY ARE THE +;;;; AUTHORS LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +;;;; SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +;;;; NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES ; +;;;; LOSS OF USE, DATA, OR PROFITS ; OR BUSINESS INTERRUPTION) +;;;; +;;;; For further details contact the authors of this software. +;;;; +;;;; Jochen Schmidt +;;;; Zuckmantelstr. 11 +;;;; 91616 Neusitz +;;;; GERMANY +;;;; +;;;; + +(defpackage :acl-compat-mp + (:use :common-lisp) + (:export + #:*current-process* ;* + #:process-kill ;* + #:process-preset ;* + #:process-name ;* + + #:process-wait-function + #:process-run-reasons + #:process-arrest-reasons + #:process-whostate + #:without-interrupts + #:process-wait + #:process-enable + #:process-disable + #:process-reset + #:process-interrupt + + #:process-run-function ;* + #:process-property-list ;* + #:without-scheduling ;* + #:process-allow-schedule ;* + #:make-process ;* + #:process-add-run-reason ;* + #:process-revoke-run-reason ;* + #:process-add-arrest-reason ;* + #:process-revoke-arrest-reason ;* + #:process-allow-schedule ;* + #:with-timeout ;* + #:make-process-lock ;* + #:with-process-lock ;* + #:process-active-p ; required by webactions + #:current-process + #:process-name-to-process + #:process-wait-with-timeout + #:wait-for-input-available + ) + (:nicknames :acl-mp)) + +;; * marked ones are used in Portable Allegroserve Added: branches/trunk-reorg/thirdparty/acl-compat/acl-socket-corman.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/acl-compat/acl-socket-corman.lisp Thu Feb 7 03:21:48 2008 @@ -0,0 +1,194 @@ +;;;; ACL socket wrapper library for Corman Lisp - Version 1.1 +;;;; +;;;; Copyright (C) 2000 Christopher Double. All Rights Reserved. +;;;; +;;;; License +;;;; ======= +;;;; This software is provided 'as-is', without any express or implied +;;;; warranty. In no event will the author be held liable for any damages +;;;; arising from the use of this software. +;;;; +;;;; Permission is granted to anyone to use this software for any purpose, +;;;; including commercial applications, and to alter it and redistribute +;;;; it freely, subject to the following restrictions: +;;;; +;;;; 1. The origin of this software must not be misrepresented; you must +;;;; not claim that you wrote the original software. If you use this +;;;; software in a product, an acknowledgment in the product documentation +;;;; would be appreciated but is not required. +;;;; +;;;; 2. Altered source versions must be plainly marked as such, and must +;;;; not be misrepresented as being the original software. +;;;; +;;;; 3. This notice may not be removed or altered from any source +;;;; distribution. +;;;; +;;;; Notes +;;;; ===== +;;;; A simple wrapper around the SOCKETS package to present an interface +;;;; similar to the Allegro Common Lisp SOCKET package. Based on a package +;;;; by David Bakhash for LispWorks. For documentation on the ACL SOCKET +;;;; package see: +;;;; +;;;; http://www.franz.com/support/documentation/5.0.1/doc/cl/socket.htm +;;;; +;;;; More recent versions of this software may be available at: +;;;; http://www.double.co.nz/cl +;;;; +;;;; Comments, suggestions and bug reports to the author, +;;;; Christopher Double, at: chris at double.co.nz +;;;; +;;;; 17/09/2000 - 1.0 +;;;; Initial release. +;;;; +;;;; 20/09/2000 - 1.1 +;;;; Added SOCKET-CONTROL function. +;;;; +;;;; 27/02/2001 - 1.2 +;;;; Added ability to create SSL sockets. Doesn't use +;;;; same interface as Allegro 6 - need to look into +;;;; how that works. +;;;; +;;;; 03/01/2003 - 1.3 +;;;; Added to PortableAllegroServe. + +(eval-when (:compile-toplevel :load-toplevel :execute) + (require :sockets) + (require :ssl-sockets)) + +(sockets:start-sockets) +(ssl-sockets:start-ssl-sockets) + +(defpackage socket + (:use "COMMON-LISP") + (:export + "MAKE-SOCKET" + "ACCEPT-CONNECTION" + "DOTTED-TO-IPADDR" + "IPADDR-TO-DOTTED" + "IPADDR-TO-HOSTNAME" + "LOOKUP-HOSTNAME" + "REMOTE-HOST" + "LOCAL-HOST" + "LOCAL-PORT" + "SOCKET-CONTROL" + )) + +(in-package :socket) + +(defmethod accept-connection ((server-socket sockets::server-socket) + &key (wait t)) + (unless wait + (error "WAIT keyword to ACCEPT-CONNECTION not implemented.")) + (sockets:make-socket-stream + (sockets:accept-socket server-socket))) + +(defun make-socket (&key + (remote-host "0.0.0.0") ;;localhost? + type + local-port + remote-port + (connect :active) + (format :text) + ssl + &allow-other-keys) + (check-type remote-host string) + (when (eq type :datagram) + (error ":DATAGRAM keyword to MAKE-SOCKET not implemented.")) + (when (eq format :binary) + (warn ":BINARY keyword to MAKE-SOCKET partially implemented.")) + + (ecase connect + (:passive + (sockets:make-server-socket + :host remote-host + :port local-port)) + (:active + (sockets:make-socket-stream + (if ssl + (ssl-sockets:make-client-ssl-socket + :host remote-host + :port remote-port) + (sockets:make-client-socket + :host remote-host + :port remote-port)))))) + + +(defun dotted-to-ipaddr (dotted &key errorp) + (when errorp + (warn ":ERRORP keyword to DOTTED-TO-IPADDR not supported.")) + (sockets:host-to-ipaddr dotted)) + +(defun ipaddr-to-dotted (ipaddr &key values) + (when values + (error ":VALUES keyword to IPADDR-TO-DOTTED not supported.")) + (sockets:ipaddr-to-dotted ipaddr)) + +(defun ipaddr-to-hostname (ipaddr &key ignore-cache) + (when ignore-cache + (warn ":IGNORE-CACHE keyword to IPADDR-TO-HOSTNAME not supported.")) + (sockets:ipaddr-to-name ipaddr)) + +(defun lookup-hostname (host &key ignore-cache) + (when ignore-cache + (warn ":IGNORE-CACHE keyword to IPADDR-TO-HOSTNAME not supported.")) + (if (stringp host) + (sockets:host-to-ipaddr host) + (dotted-to-ipaddr (ipaddr-to-dotted host)))) + +(defun remote-host (socket-or-stream) + (let ((socket (if (typep socket-or-stream 'sockets:base-socket) + socket-or-stream + (sockets:stream-socket-handle socket-or-stream)))) + (sockets::remote-socket-ipaddr socket))) + +(defun local-host (socket-or-stream) + (let ((socket (if (typep socket-or-stream 'sockets:base-socket) + socket-or-stream + (sockets:stream-socket-handle socket-or-stream)))) + (if (not (typep socket 'sockets:local-socket)) + 16777343 + (sockets::socket-host-ipaddr socket)))) + +(defun local-port (socket-or-stream) + (let ((socket (if (typep socket-or-stream 'sockets:base-socket) + socket-or-stream + (sockets:stream-socket-handle socket-or-stream)))) + (sockets:socket-port socket))) + +(defun socket-control (stream &key output-chunking output-chunking-eof input-chunking) + (declare (ignore stream output-chunking output-chunking-eof input-chunking)) + (warn "SOCKET-CONTROL function not implemented.")) + +;; Some workarounds to get combined text/binary socket streams working +(defvar old-read-byte #'cl::read-byte) + +(defun new-read-byte (stream &optional (eof-error-p t) (eof-value nil)) + "Replacement for Corman Lisp READ-BYTE to work with socket streams correctly." + (if (eq (cl::stream-subclass stream) 'sockets::socket-stream) + (char-int (read-char stream eof-error-p eof-value)) + (funcall old-read-byte stream eof-error-p eof-value))) + +(setf (symbol-function 'common-lisp::read-byte) #'new-read-byte) + +(in-package :cl) + +(defun write-sequence (sequence stream &key start end) + (let ((element-type (stream-element-type stream)) + (start (if start start 0)) + (end (if end end (length sequence)))) + (if (eq element-type 'character) + (do ((n start (+ n 1))) + ((= n end)) + (write-char (if (typep (elt sequence n) 'number) (ccl:int-char (elt sequence n)) (elt sequence n)) stream)) + (do ((n start (+ n 1))) + ((= n end)) + (write-byte (elt sequence n) stream)))) ;; recoded to avoid LOOP, because it isn't loaded yet + ;(loop for n from start below end do + ; (write-char (elt sequence n) stream)) + ;(loop for n from start below end do + ; (write-byte (elt sequence n) stream)) + (force-output stream)) + +(provide 'acl-socket) + Added: branches/trunk-reorg/thirdparty/acl-compat/acl-ssl-streams.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/acl-compat/acl-ssl-streams.lisp Thu Feb 7 03:21:48 2008 @@ -0,0 +1,293 @@ +;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Package: CL-USER; -*- +;;; +;;; Filename: gray-streams-integration.lisp +;;; Author: Jochen Schmidt +;;; Description: Integrate ssl-sockets with the lisp +;;; stream system using gray-streams. +;;; + +(in-package :ssl) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; Gray Streams integration ;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(defclass ssl-stream-mixin () + ((ssl-socket :accessor ssl-socket :initarg :ssl-socket))) + +(defclass binary-ssl-stream + (ssl-stream-mixin + gray-stream:fundamental-binary-input-stream + gray-stream:fundamental-binary-output-stream) + ()) + +(defclass character-ssl-stream + (ssl-stream-mixin + gray-stream:fundamental-character-input-stream + gray-stream:fundamental-character-output-stream) + ()) + +(defmethod #-cormanlisp gray-stream::stream-element-type #+cormanlisp gray-stream::stream-stream-element-type ((socket-stream binary-ssl-stream)) + '(unsigned-byte 8)) + +(defmethod #-cormanlisp gray-stream::stream-element-type #+cormanlisp gray-stream::stream-stream-element-type ((socket-stream character-ssl-stream)) + 'character) + +(defmethod gray-stream:stream-line-column ((socket-stream character-ssl-stream)) + nil) + +(defmethod gray-stream:stream-line-column ((socket-stream binary-ssl-stream)) + nil) + +(defmethod gray-stream:stream-listen ((socket-stream ssl-stream-mixin)) + (with-slots (ssl-socket) socket-stream + (> (ssl-internal:ssl-pending (ssl-internal:ssl-socket-handle ssl-socket)) 0))) + +(defmethod gray-stream:stream-read-byte ((socket-stream binary-ssl-stream)) + (with-slots (ssl-socket) socket-stream + (ssl-internal:ssl-socket-read-byte ssl-socket))) + +(defmethod gray-stream:stream-write-byte ((socket-stream binary-ssl-stream) byte) + (with-slots (ssl-socket) socket-stream + (ssl-internal:ssl-socket-write-byte byte ssl-socket))) + +#| +(defmethod gray-stream:stream-read-char ((socket-stream character-ssl-stream)) + (with-slots (ssl-socket) socket-stream + (ssl-internal:ssl-socket-read-char ssl-socket))) + +(defmethod gray-stream:stream-read-char ((socket-stream binary-ssl-stream)) + (with-slots (ssl-socket) socket-stream + (ssl-internal:ssl-socket-read-char ssl-socket))) +|# + +; Bivalent +(defmethod gray-stream:stream-read-char ((socket-stream ssl-stream-mixin)) + (with-slots (ssl-socket) socket-stream + (ssl-internal:ssl-socket-read-char ssl-socket))) + + +(defmethod gray-stream:stream-read-char-no-hang ((socket-stream character-ssl-stream)) + (when (listen socket-stream) + (with-slots (ssl-socket) socket-stream + (ssl-internal:ssl-socket-read-char ssl-socket)))) + +#| +(defmethod gray-stream:stream-write-char ((socket-stream character-ssl-stream) char) + (with-slots (ssl-socket) socket-stream + (ssl-internal:ssl-socket-write-char char ssl-socket))) + +(defmethod gray-stream:stream-write-char ((socket-stream binary-ssl-stream) char) + (with-slots (ssl-socket) socket-stream + (ssl-internal:ssl-socket-write-char char ssl-socket))) +|# + +; Bivalent +(defmethod gray-stream:stream-write-char ((socket-stream ssl-stream-mixin) char) + (with-slots (ssl-socket) socket-stream + (ssl-internal:ssl-socket-write-char char ssl-socket))) + + + +; Bivalent +(defmethod gray-stream:stream-force-output ((socket-stream ssl-stream-mixin)) + (with-slots (ssl-socket) socket-stream + (ssl-internal:flush-output-buffer ssl-socket))) + +(defmethod gray-stream:stream-finish-output ((socket-stream ssl-stream-mixin)) + (with-slots (ssl-socket) socket-stream + (ssl-internal:flush-output-buffer ssl-socket))) + +(defmethod gray-stream:stream-clear-output ((socket-stream ssl-stream-mixin)) + (with-slots (ssl-socket) socket-stream + (with-slots (ssl-internal::output-offset) ssl-socket + (setf ssl-internal::output-offset 0)))) + +(defmethod gray-stream:stream-clear-input ((socket-stream ssl-stream-mixin)) + (with-slots (ssl-socket) socket-stream + (with-slots (ssl-internal::input-avail ssl-internal::input-offset) ssl-socket + (setf ssl-internal::input-avail 0) + (setf ssl-internal::input-offset 0)))) + +(defmethod #-cormanlisp common-lisp:close #+cormanlisp gray-stream:stream-close ((socket-stream ssl-stream-mixin) &key abort) + (with-slots (ssl-socket) socket-stream + (unless abort + (ssl-internal:flush-output-buffer ssl-socket)) + (ssl-internal:close-ssl-socket ssl-socket))) + +#| +(defmethod gray-stream:stream-force-output ((socket-stream character-ssl-stream)) + (with-slots (ssl-socket) socket-stream + (ssl-internal:flush-output-buffer ssl-socket))) + +(defmethod gray-stream:stream-finish-output ((socket-stream character-ssl-stream)) + (with-slots (ssl-socket) socket-stream + (ssl-internal:flush-output-buffer ssl-socket))) + +(defmethod gray-stream:stream-clear-output ((socket-stream character-ssl-stream)) + (with-slots (ssl-socket) socket-stream + (with-slots (ssl-internal::output-offset) ssl-socket + (setf ssl-internal::output-offset 0)))) + +(defmethod gray-stream:stream-clear-input ((socket-stream character-ssl-stream)) + (with-slots (ssl-socket) socket-stream + (with-slots (ssl-internal::input-avail ssl-internal::input-offset) ssl-socket + (setf ssl-internal::input-avail 0) + (setf ssl-internal::input-offset 0)))) + +(defmethod gray-stream:stream-read-sequence ((socket-stream character-ssl-stream) sequence start end) + (let* ((len (length sequence)) + (chars (- (min (or end len) len) start))) + ;(format t "Read ~A chars from index ~A on.~%" chars start) (force-output t) + (loop for i upfrom start + repeat chars + for char = (progn ;(format t "Read char on index ~A~%" i) + ;(force-output t) + (let ((c (gray-streams:stream-read-char socket-stream))) + ;(format t "The element read was ~A~%" c) + c)) + if (eq char :eof) do (progn ;(format t "premature return on index ~A~%" i) + ;(force-output t) + (return-from gray-streams:stream-read-sequence i)) + do (setf (elt sequence i) char)) + ;(format t "Normal return on index ~A~%" (+ start chars)) (force-output t) + (+ start chars))) + +|# + +;; +;; Why this argument ordering in CMUCL? LW has (stream sequence start end) +;; It would be interesting to know why it is a particular good idea to +;; reinvent APIs every second day in an incompatible way.... *grrr* +;; + +#+cmu +(defmethod gray-stream:stream-read-sequence ((socket-stream character-ssl-stream) (sequence sequence) &optional start end) + (let* ((len (length sequence)) + (chars (- (min (or end len) len) start))) + (loop for i upfrom start + repeat chars + for char = (gray-stream:stream-read-char socket-stream) + if (eq char :eof) do (return-from gray-stream:stream-read-sequence i) + do (setf (elt sequence i) char)) + (+ start chars))) + +#+cmu +(defmethod gray-stream:stream-read-sequence ((socket-stream binary-ssl-stream) (sequence sequence) &optional start end) + (let* ((len (length sequence)) + (chars (- (min (or end len) len) start))) + (loop for i upfrom start + repeat chars + for char = (gray-stream:stream-read-byte socket-stream) + if (eq char :eof) do (return-from gray-stream:stream-read-sequence i) + do (setf (elt sequence i) char)) + (+ start chars))) + +#| +(defmethod gray-stream:stream-read-sequence ((socket-stream binary-ssl-stream) sequence start end) + (let* ((len (length sequence)) + (chars (- (min (or end len) len) start))) + ;(format t "Read ~A chars from index ~A on.~%" chars start) (force-output t) + (loop for i upfrom start + repeat chars + for char = (progn ;(format t "Read char on index ~A~%" i) + ;(force-output t) + (let ((c (gray-streams:stream-read-byte socket-stream))) + ;(format t "The element read was ~A~%" c) + c)) + if (eq char :eof) do (progn ;(format t "premature return on index ~A~%" i) + ;(force-output t) + (return-from gray-streams:stream-read-sequence i)) + do (setf (elt sequence i) char)) + ;(format t "Normal return on index ~A~%" (+ start chars)) (force-output t) + (+ start chars))) +|# + +#| Alternative implementation? +(defmethod stream:stream-read-sequence ((socket-stream character-ssl-stream) sequence start end) + (let* ((len (length sequence)) + (chars (- (min (or end len) len) start))) + (format t "Read ~A chars from index ~A on.~%" chars start) (force-output t) + (loop for i upfrom start + repeat chars + for char = (progn (format t "Read char on index ~A~%" i) + (force-output t) + (let ((c (stream:stream-read-char socket-stream))) + (format t "The element read was ~A~%" c) c)) + if (eq char :eof) do (progn (format t "premature return on index ~A~%" i) + (force-output t) + (return-from stream:stream-read-sequence i)) + do (setf (elt sequence i) char)) + (format t "Normal return on index ~A~%" (+ start chars)) (force-output t) + (+ start chars))) +|# + +#| +(defmethod common-lisp:close ((socket-stream character-ssl-stream) &key abort) + (with-slots (ssl-socket) socket-stream + (unless abort + (ssl-internal:flush-output-buffer ssl-socket)) + (ssl-internal:close-ssl-socket ssl-socket))) +|# + +#+lispworks +(declaim (inline %reader-function-for-sequence)) +#+lispworks +(defun %reader-function-for-sequence (sequence) + (typecase sequence + (string #'read-char) + ((array unsigned-byte (*)) #'read-byte) + ((array signed-byte (*)) #'read-byte) + (otherwise #'read-byte))) + +#+lispworks +(declaim (inline %writer-function-for-sequence)) +#+lispworks +(defun %writer-function-for-sequence (sequence) + (typecase sequence + (string #'write-char) + ((array unsigned-byte (*)) #'write-byte) + ((array signed-byte (*)) #'write-byte) + (otherwise #'write-byte))) + +;; Bivalent socket support for READ-SEQUENCE / WRITE-SEQUENCE +#+lispworks +(defmethod gray-stream:stream-read-sequence ((stream ssl-stream-mixin) sequence start end) + (stream::read-elements stream sequence start end (%reader-function-for-sequence sequence))) + +#+lispworks +(defmethod gray-stream:stream-write-sequence ((stream ssl-stream-mixin) sequence start end) + (stream::write-elements stream sequence start end (typecase sequence + (string t) + ((array unsigned-byte (*)) nil) + ((array signed-byte (*)) nil) + (otherwise nil)))) + +#+lispworks +(in-package :acl-socket) + +#+lispworks +(defmethod remote-host ((socket ssl::ssl-stream-mixin)) + (comm:get-socket-peer-address (ssl-internal::ssl-socket-fd (ssl::ssl-socket socket)))) + +#+lispworks +(defmethod remote-port ((socket ssl::ssl-stream-mixin)) + (multiple-value-bind (host port) + (comm:get-socket-peer-address (ssl-internal::ssl-socket-fd (ssl::ssl-socket socket))) + (declare (ignore host)) + port)) + +#+lispworks +(defmethod local-host ((socket ssl::ssl-stream-mixin)) + (multiple-value-bind (host port) + (comm:get-socket-address (ssl-internal::ssl-socket-fd (ssl::ssl-socket socket))) + (declare (ignore port)) + host)) + +#+lispworks +(defmethod local-port ((socket ssl::ssl-stream-mixin)) + (multiple-value-bind (host port) + (comm:get-socket-address (ssl-internal::ssl-socket-fd (ssl::ssl-socket socket))) + (declare (ignore host)) + port)) + Added: branches/trunk-reorg/thirdparty/acl-compat/acl-ssl.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/acl-compat/acl-ssl.lisp Thu Feb 7 03:21:48 2008 @@ -0,0 +1,58 @@ +(in-package :ssl) +;;;;;;;;;;;;;;;;;;;;; +;;; ACL style API ;;; +;;;;;;;;;;;;;;;;;;;;; + +(defmethod make-ssl-client-stream ((socket integer) &rest options) + (destructuring-bind (&key (format :binary)) options + (when (minusp socket) + (error "not a proper socket descriptor")) + (let ((ssl-socket (make-instance 'ssl-internal:ssl-client-socket :fd socket))) + (case format + (:binary (make-instance 'binary-ssl-stream + :ssl-socket ssl-socket)) + (:text (make-instance 'character-ssl-stream + :ssl-socket ssl-socket)) + (otherwise (error "Unknown ssl-stream format")))))) + +#+lispworks +(defmethod make-ssl-client-stream ((lw-socket-stream comm:socket-stream) &rest options) + (apply #'make-ssl-client-stream (comm:socket-stream-socket lw-socket-stream) options)) + +#+cormanlisp +(defmethod make-ssl-client-stream (stream &rest options) + (apply #'make-ssl-client-stream (sockets:socket-descriptor (cl::stream-handle stream)) options)) + +(defmethod make-ssl-server-stream ((socket integer) &rest options) + (destructuring-bind (&key certificate key other-certificates (format :binary)) options + (when (minusp socket) + (error "not a proper socket descriptor")) + (let ((ssl-socket (make-instance 'ssl-internal:ssl-server-socket + :fd socket + :rsa-privatekey-file (or key certificate) + :certificate-file (or certificate key)))) + (case format + (:binary (make-instance 'binary-ssl-stream + :ssl-socket ssl-socket)) + (:text (make-instance 'character-ssl-stream + :ssl-socket ssl-socket)) + (otherwise (error "Unknown ssl-stream format")))))) + +(defmethod make-ssl-server-stream ((socket ssl-stream-mixin) &rest options) + (warn "SSL socket ~A reused" socket) + socket) + +#+lispworks +(defmethod make-ssl-server-stream ((lw-socket-stream comm:socket-stream) &rest options) + (apply #'make-ssl-server-stream (comm:socket-stream-socket lw-socket-stream) options)) + + +#+ignore +(defmethod make-ssl-server-stream ((acl-socket acl-socket::server-socket) &rest options) + (apply #'make-ssl-server-stream + (comm::get-fd-from-socket (acl-socket::passive-socket acl-socket)) options)) + +#+ignore +(defmethod make-ssl-server-stream ((lw-socket-stream acl-socket::chunked-socket-stream) &rest options) + (apply #'make-ssl-server-stream (comm:socket-stream-socket lw-socket-stream) options)) + Added: branches/trunk-reorg/thirdparty/acl-compat/allegro/acl-excl.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/acl-compat/allegro/acl-excl.lisp Thu Feb 7 03:21:48 2008 @@ -0,0 +1,3 @@ +;;;; ACL-COMPAT - EXCL +;;;; +;;;; Nothing needs to be done Added: branches/trunk-reorg/thirdparty/acl-compat/allegro/acl-mp.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/acl-compat/allegro/acl-mp.lisp Thu Feb 7 03:21:48 2008 @@ -0,0 +1,3 @@ +;;; This file implements the process functions for AllegroServe in MCL. + +(in-package :acl-compat.mp) Added: branches/trunk-reorg/thirdparty/acl-compat/allegro/acl-socket.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/acl-compat/allegro/acl-socket.lisp Thu Feb 7 03:21:48 2008 @@ -0,0 +1,6 @@ +;;; Allegro layer for ACL sockets. +;;; +(in-package :acl-compat.socket) + + + Added: branches/trunk-reorg/thirdparty/acl-compat/allegro/acl-sys.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/acl-compat/allegro/acl-sys.lisp Thu Feb 7 03:21:48 2008 @@ -0,0 +1,4 @@ +;;; Allegro System Package Compatibility file + +;;; Nothing to do +(in-package :acl-compat.system) Added: branches/trunk-reorg/thirdparty/acl-compat/chunked-stream-mixin.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/acl-compat/chunked-stream-mixin.lisp Thu Feb 7 03:21:48 2008 @@ -0,0 +1,275 @@ +;;;; ; +;;;; (c) 2002 by Jochen Schmidt. +;;;; +;;;; File: chunked-stream-mixin.lisp +;;;; Revision: 0.1 +;;;; Description: ACL style HTTP1.1 I/O chunking +;;;; Date: 08.04.2002 +;;;; Authors: Jochen Schmidt +;;;; Tel: (+49 9 11) 47 20 603 +;;;; Email: jsc at dataheaven.de +;;;; +;;;; Redistribution and use in source and binary forms, with or without +;;;; modification, are permitted provided that the following conditions +;;;; are met: +;;;; 1. Redistributions of source code must retain the above copyright +;;;; notice, this list of conditions and the following disclaimer. +;;;; 2. Redistributions in binary form must reproduce the above copyright +;;;; notice, this list of conditions and the following disclaimer in the +;;;; documentation and/or other materials provided with the distribution. +;;;; +;;;; THIS SOFTWARE IS PROVIDED "AS IS" AND THERE ARE NEITHER +;;;; EXPRESSED NOR IMPLIED WARRANTIES - THIS INCLUDES, BUT +;;;; IS NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY +;;;; AND FITNESS FOR A PARTICULAR PURPOSE.IN NO WAY ARE THE +;;;; AUTHORS LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +;;;; SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +;;;; NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES ; +;;;; LOSS OF USE, DATA, OR PROFITS ; OR BUSINESS INTERRUPTION) +;;;; +;;;; For further details contact the authors of this software. +;;;; +;;;; Jochen Schmidt +;;;; Zuckmantelstr. 11 +;;;; 91616 Neusitz +;;;; GERMANY +;;;; +;;;; Nuernberg, 08.Apr.2002 Jochen Schmidt +;;;; + +(in-package :de.dataheaven.chunked-stream-mixin) + +(defun buffer-ref (buffer index) + #+lispworks (schar buffer index) + #-lispworks (aref buffer index)) + +(defun (setf buffer-ref) (new-value buffer index) + #-lispworks (setf (aref buffer index) (char-code new-value)) + #+lispworks (setf (schar buffer index) new-value)) + +(defclass chunked-stream-mixin () + ((output-chunking-p :initform nil :accessor output-chunking-p) + (chunk-input-avail :initform nil + :documentation + "Number of octets of the current chunk that are +not yet read into the buffer, or nil if input chunking is disabled") + (real-input-limit :initform 0 + :documentation + "Index of last octet read into buffer +(input-limit points to index of last octet in the current chunk)"))) + +(defgeneric input-chunking-p (stream)) +(defmethod input-chunking-p ((stream chunked-stream-mixin)) + (not (null (slot-value stream 'chunk-input-avail)))) + +(defgeneric (setf input-chunking-p) (new-value stream)) +(defmethod (setf input-chunking-p) (new-value (stream chunked-stream-mixin)) + (setf (slot-value stream 'chunk-input-avail) (and new-value 0))) + +(define-condition acl-compat.excl::socket-chunking-end-of-file (condition) + ((acl-compat.excl::format-arguments :initform nil :initarg :format-arguments) + (acl-compat.excl::format-control :initform "A chunking end of file occured" + :initarg :format-control))) + + +;;;;;;;;;;;;;;;;;;;;;; +;;; Input chunking ;;; +;;;;;;;;;;;;;;;;;;;;;; + +;; Input chunking is not tested so far! + +(defgeneric initialize-input-chunking (stream)) +(defmethod initialize-input-chunking ((stream chunked-stream-mixin)) + "This method initializes input chunking. The real-input-limit is nil +in the beginnings because it got not saved yet. Chunk-input-avail is +obviously 0 because no chunk-data got read so far." + (gray-stream:with-stream-input-buffer (input-buffer input-index input-limit) + stream + (with-slots (real-input-limit chunk-input-avail) stream + (setf + ;; Bytes read from stream (valid data in buffer up to here) + real-input-limit input-limit + ;; Bytes available in current chunk block after buffer contents + ;; runs out (trivially zero before first chunk block read) + chunk-input-avail 0 + ;; Last buffer position that can be read before new data has to + ;; be fetched from stream (we must begin with parsing a chunk + ;; immediately; hence set to a value that guarantees this) + input-limit 0 ; or input-index? + )))) + +;; Lispworks fix by Edi Weitz (paserve-help 2003-11-28) +#+lispworks +(defmacro %with-stream-input-buffer ((input-buffer input-index input-limit) stream &body body) + `(with-slots ((,input-buffer stream::input-buffer) + (,input-index stream::input-index) + (,input-limit stream::input-limit)) + (slot-value ,stream 'stream::buffer-state) + , at body)) + +(defmethod gray-stream:stream-fill-buffer ((stream chunked-stream-mixin)) + "Refill buffer from stream." + ;; STREAM-FILL-BUFFER gets called when the input-buffer contains no + ;; more data (the index is bigger than the limit). We call out to + ;; the real buffer filling mechanism by calling the next specialized + ;; method. This method is responsible to update the buffer state in + ;; coordination with the chunk-header. + (with-slots (chunk-input-avail real-input-limit) stream + (#-lispworks gray-stream:with-stream-input-buffer + #+lispworks %with-stream-input-buffer + (input-buffer input-index input-limit) stream + (labels + ((pop-char () + (when (and (>= input-index input-limit) ; need new data + (not (call-next-method))) ; couldn't get it + (error "Unexpected end-of-file while reading chunk block")) + (prog1 #-lispworks (code-char (buffer-ref input-buffer input-index)) + #+lispworks (buffer-ref input-buffer input-index) + (incf input-index))) + (read-chunk-header () + (let ((chunk-length 0)) + (tagbody + initial-crlf (let ((char (pop-char))) + (cond ((digit-char-p char 16) + (decf input-index) ; unread char + (go chunk-size)) + ((eq #\Return char) + (if (eq (pop-char) #\Linefeed) + (go chunk-size) + (error "End of chunk-header corrupted: Expected Linefeed"))) + (t (error "End of chunk-header corrupted: Expected Carriage Return or a digit")))) + + chunk-size (let ((char (pop-char))) + (cond ((digit-char-p char 16) + (setf chunk-length + (+ (* 16 chunk-length) + (digit-char-p char 16))) + (go chunk-size)) + (t (decf input-index) ; unread char + (go skip-rest)))) + + skip-rest (if (eq #\Return (pop-char)) + (go check-linefeed) + (go skip-rest)) + + check-linefeed (let ((char (pop-char))) + (case char + (#\Linefeed (go accept)) + (t (error "End of chunk-header corrupted: LF expected, ~A read." char)))) + + accept) + chunk-length))) + + (cond ((not (input-chunking-p stream)) + ;; Chunking not active; just fill buffer normally + (call-next-method)) + ((zerop chunk-input-avail) + ;; We are at the beginning of a new chunk. + (when real-input-limit (setf input-limit real-input-limit)) + (let* ((chunk-length (read-chunk-header)) + (end-of-chunk (+ input-index chunk-length))) + (if (zerop chunk-length) + ;; rfc2616 indicates that input chunking is + ;; turned off after zero-length chunk is read + ;; (see section 19.4.6) -- turn off chunking + (progn (signal 'acl-compat.excl::socket-chunking-end-of-file + :format-arguments stream) + (setf (input-chunking-p stream) nil) + ;; TODO: whoever handles + ;; socket-chunking-end-of-file (client.cl + ;; in AllegroServe's case) should read the + ;; trailer (see section 3.6). All we can + ;; reasonably do here is turn off + ;; chunking, or throw information away. + ) + ;; Now set up stream attributes so that read methods + ;; call refill-buffer both at end of chunk and end of + ;; buffer + (progn + (setf real-input-limit input-limit + input-limit (min real-input-limit end-of-chunk) + chunk-input-avail (max 0 (- end-of-chunk + real-input-limit))) + input-limit)))) + (t + ;; We are in the middle of a chunk; re-fill buffer + (if (call-next-method) + (progn + (setf real-input-limit input-limit) + (setf input-limit + (min real-input-limit chunk-input-avail)) + (setf chunk-input-avail + (max 0 (- chunk-input-avail real-input-limit))) + input-limit) + (error "Unexpected end-of-file in the middle of a chunk")))))))) + + +;;;;;;;;;;;;;;;;;;;;;;; +;;; Output chunking ;;; +;;;;;;;;;;;;;;;;;;;;;;; + +;; This constant is the amount of bytes the system reserves for the chunk-header +;; It is calculated as 4 bytes for the chunk-size in hexadecimal digits and a CR followed +;; by a LF +(defconstant +chunk-header-buffer-offset+ 6) + +(defgeneric initialize-output-chunking (stream)) +(defmethod initialize-output-chunking ((stream chunked-stream-mixin)) + "This method initializes output chunking. Actual contents in the output-buffer + get flushed first. A chunk has a header at the start and a CRLF at the end. + The header is the length of the (data) content in the chunk as a string in hexadecimal + digits and a trailing CRLF before the real content begins. We assume that the content + of a chunk is never bigger than #xFFFF and therefore reserve 6 bytes at the beginning + of the buffer for the header. We reduce the buffer limit by 2 so that we have always + room left in the buffer to attach a CRLF." + (unless (output-chunking-p stream) + (force-output stream) + (gray-stream:with-stream-output-buffer (buffer index limit) stream + (setf index +chunk-header-buffer-offset+) + (setf (buffer-ref buffer (- +chunk-header-buffer-offset+ 2)) #\Return + (buffer-ref buffer (1- +chunk-header-buffer-offset+)) #\Linefeed) + (decf limit 2) + (setf (output-chunking-p stream) t)))) + +(defmethod gray-stream:stream-flush-buffer ((stream chunked-stream-mixin)) + "When there is pending content in the output-buffer then compute the chunk-header and flush + the buffer" + (if (output-chunking-p stream) + (gray-stream:with-stream-output-buffer (output-buffer output-index output-limit) stream + (when (> output-index +chunk-header-buffer-offset+) + (let* ((chunk-header (format nil "~X" (- output-index +chunk-header-buffer-offset+))) + (start (- +chunk-header-buffer-offset+ 2 (length chunk-header)))) + (loop for c across chunk-header + for i upfrom start + do (setf (buffer-ref output-buffer i) c)) + (setf (buffer-ref output-buffer output-index) #\Return + (buffer-ref output-buffer (1+ output-index)) #\Linefeed) + (gray-stream:stream-write-buffer stream output-buffer start (+ output-index 2)) + (setf output-index +chunk-header-buffer-offset+)))) + (call-next-method))) + + +(defmethod close ((stream chunked-stream-mixin) &key abort) + (unless abort + (disable-output-chunking stream)) + (call-next-method)) + + +(defgeneric disable-output-chunking (stream)) +(defmethod disable-output-chunking ((stream chunked-stream-mixin)) + "When we disable chunking we first try to write out a last pending chunk and after that + reset the buffer-state to normal mode. To end the game we write out a chunk-header with + a chunk-size of zero to notify the peer that chunking ends." + (when (output-chunking-p stream) + (force-output stream) + (gray-stream:with-stream-output-buffer (buffer index limit) stream + (setf index 0) + (incf limit 2)) + (setf (output-chunking-p stream) nil + (input-chunking-p stream) nil) + (format stream "0~A~A~A~A" #\Return #\Linefeed #\Return #\Linefeed) + (force-output stream))) + + + + Added: branches/trunk-reorg/thirdparty/acl-compat/chunked.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/acl-compat/chunked.lisp Thu Feb 7 03:21:48 2008 @@ -0,0 +1,211 @@ +;;; +;;; Streams with support for "chunked" transfer coding. This module +;;; emulates the support for chunking found in Allegro Common Lisp's +;;; streams. See RFC 2616 for a description of the "chunked" transfer +;;; coding. +;;; +;;; TODO: +;;; - + +(defpackage :com.ljosa.chunked + (:use :common-lisp #+LISPWORKS :stream) + (:export :chunked-mixin :make-chunked-stream :*buffer-size* + :output-chunking :input-chunking :close-chunk)) + +(in-package :com.ljosa.chunked) + +(defparameter *buffer-size* 1024 "Maximum chunk size") + +(defvar *recursive* nil) + +(defclass chunked-mixin () + ((output-chunking :initform nil :accessor output-chunking) + (input-chunking :initform nil :accessor input-chunking) + (output-buffer) + (remaining-input :initform nil))) + +(defmethod shared-initialize :after ((stream chunked-mixin) slots-for-initform + &rest initargs) + (declare (ignore initargs slots-for-initform)) + (with-slots (output-buffer) stream + (setf output-buffer (make-array (list *buffer-size*) + :element-type 'unsigned-byte + :fill-pointer 0)))) + +(define-condition excl::socket-chunking-end-of-file (condition) + ((excl::format-arguments :initform nil) + (excl::format-control :initform "~1@"))) + +;; (defmethod stream-element-type ((stream chunked-mixin)) +;; (call-next-method)) + +(defun read-chunk-header (stream &aux (x 0) (*recursive* t)) + (tagbody + s0 (let ((char (read-char stream))) + (cond ((digit-char-p char 16) (setf x (+ (* 16 x) (digit-char-p char 16))) + (go s0)) + ((eq #\; char) (go s1)) + ((eq #\; char) (go s2)) + (t (error "Parse error in state s0: ~S." char)))) + s1 (if (eq #\Return (read-char stream)) + (go s2) + (go s1)) + s2 (let ((char (read-char stream))) + (case char + (#\Linefeed (go accept)) + (t (error "Parse error in state s2: ~S." char)))) + accept) + x) + +;; FIXME: What do do when the chunked input stream can't be parsed? + +(defun gobble-crlf (stream &aux (*recursive* t)) + (flet ((expect (expected-char) + (let ((char (read-char stream))) + (unless (eq expected-char char) + (error "Expected ~C, got ~C." expected-char char))))) + (expect #\Return) + (expect #\Linefeed))) + +(defmethod stream-read-char ((stream chunked-mixin)) + (with-slots (input-chunking remaining-input output-chunking) stream + (cond (*recursive* (call-next-method)) + ((not input-chunking) (call-next-method)) + ((not remaining-input) (handler-case + (progn + (setf remaining-input (read-chunk-header stream)) + (stream-read-char stream)) + (end-of-file () :eof))) + ((> remaining-input 0) (decf remaining-input) + (call-next-method)) + ((zerop remaining-input) (handler-case + (progn + (gobble-crlf stream) + (setf remaining-input (read-chunk-header stream)) + (cond ((zerop remaining-input) + (setf input-chunking nil + output-chunking nil) + (signal 'excl::socket-chunking-end-of-file :format-arguments stream) + :eof) + (t (stream-read-char stream)))) + (end-of-file () :eof)))))) + +(defmethod stream-unread-char ((stream chunked-mixin) character) + (with-slots (input-chunking remaining-input) stream + (cond (*recursive* (call-next-method)) + (input-chunking (incf remaining-input) + (call-next-method)) + (t (call-next-method))))) + +(defmethod stream-read-line ((stream chunked-mixin)) + (loop + with chars = nil + for char = (stream-read-char stream) + until (eq char #\Linefeed) + do + (if (eq char :eof) + (if (null chars) + (error 'end-of-file :stream stream) + (return (coerce chars 'string))) + (push char chars)) + finally (return (coerce (nreverse chars) 'string)))) + +(defmethod stream-read-sequence ((stream chunked-mixin) sequence start end) + (loop + for i from start below end + do + (let ((char (stream-read-char stream))) + (case char + (:eof (return i)) + (t (setf (elt sequence i) char)))) + finally (return i))) + +(defmethod stream-clear-input ((stream chunked-mixin)) + (with-slots (input-chunking) stream + (cond (*recursive* (call-next-method)) + (input-chunking nil) + (t (call-next-method))))) + +(defmethod stream-write-byte ((stream chunked-mixin) byte) + (check-type byte unsigned-byte) + (if *recursive* + (call-next-method) + (with-slots (output-buffer) stream + (or (vector-push byte output-buffer) + (progn + (stream-force-output stream) + (stream-write-byte stream byte)))))) + +(defmethod stream-write-char ((stream chunked-mixin) character) + (if *recursive* + (call-next-method) + (stream-write-byte stream (char-code character)))) + +(defmethod stream-write-sequence ((stream chunked-mixin) sequence start end) + (loop + for i from start below end + do + (let ((e (elt sequence i))) + (etypecase e + (integer (stream-write-byte stream e)) + (character (stream-write-char stream e)))))) + +(defmethod stream-write-string ((stream chunked-mixin) string &optional + (start 0) (end (length string))) + (stream-write-sequence stream string start end)) + +(defmethod write-crlf ((stream stream)) + (let ((*recursive* t)) + (write-char #\Return stream) + (write-char #\Linefeed stream))) + +(defmethod stream-force-output ((stream chunked-mixin)) + (with-slots (output-chunking output-buffer) stream + (when (> (fill-pointer output-buffer) 0) + (let ((*recursive* t)) + (when output-chunking + (let ((*print-base* 16)) + (princ (fill-pointer output-buffer) stream)) + (write-crlf stream)) + (write-sequence output-buffer stream) + (setf (fill-pointer output-buffer) 0) + (when output-chunking + (write-crlf stream))))) + (call-next-method)) + +(defmethod stream-finish-output ((stream chunked-mixin)) + (unless *recursive* + (force-output stream)) + (call-next-method)) + +(defmethod stream-clear-output ((stream chunked-mixin)) + (with-slots (output-chunking output-buffer) stream + (if (and output-chunking (not *recursive*)) + (setf (fill-pointer output-buffer) 0) + (call-next-method)))) + +(defmethod close ((stream chunked-mixin) &key abort) + (unless abort + (finish-output stream)) + (with-slots (output-chunking output-buffer) stream + (when (and output-chunking + (> (fill-pointer output-buffer) 0)) + (close-chunk stream))) + (call-next-method)) + +(defmethod close-chunk ((stream chunked-mixin)) + (finish-output stream) + (with-slots (output-chunking input-chunking) stream + (if output-chunking + (let ((*recursive* t)) + (princ 0 stream) + (write-crlf stream) + (write-crlf stream) + (finish-output stream) + (setf output-chunking nil + input-chunking nil)) + (error "Chunking is not enabled for output on this stream: ~S." + stream)))) + +(provide :com.ljosa.chunked) + Added: branches/trunk-reorg/thirdparty/acl-compat/clisp/acl-excl.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/acl-compat/clisp/acl-excl.lisp Thu Feb 7 03:21:48 2008 @@ -0,0 +1,70 @@ +;;;; +;;;; ACL-COMPAT - EXCL +;;;; + +;;;; Implementation-specific parts of acl-compat.excl (see +;;;; acl-excl-common.lisp) + +(in-package :acl-compat.excl) + +(defun fixnump (x) + (sys::fixnump x)) + +(defun stream-input-fn (stream) + stream) + +(defun filesys-type (file-or-directory-name) + ;; Taken from clocc's port library, with thanks to Sam Steingold + (if (values + (ignore-errors + (#+lisp=cl ext:probe-directory #-lisp=cl lisp:probe-directory + file-or-directory-name))) + :directory + (if (probe-file file-or-directory-name) + :file + nil))) + +(defmacro atomically (&body forms) + ;; No multiprocessing here, move along... + `(progn , at forms)) + +(defun unix-signal (signal pid) + (declare (ignore signal pid)) + (error "clisp unix-signal not implemented yet.")) + +(defmacro without-package-locks (&body forms) + `(ext:without-package-lock ,(list-all-packages) , at forms)) + +(defun fixnump (x) + (sys::fixnump x)) + +(defun string-to-octets (string &key (null-terminate t) (start 0) + end mb-vector make-mb-vector? + (external-format :default)) + "This function returns a lisp-usb8-vector and the number of bytes copied." + (declare (ignore external-format)) + ;; The end parameter is different in ACL's lambda list, but this + ;; variant lets us give an argument :end nil explicitly, and the + ;; right thing will happen + (unless end (setf end (length string))) + (let* ((number-of-octets (if null-terminate (1+ (- end start)) + (- end start))) + (mb-vector (cond + ((and mb-vector (>= (length mb-vector) number-of-octets)) + mb-vector) + ((or (not mb-vector) make-mb-vector?) + (make-array (list number-of-octets) + :element-type '(unsigned-byte 8) + :initial-element 0)) + (t (error "Was given a vector of length ~A, ~ + but needed at least length ~A." + (length mb-vector) number-of-octets))))) + (declare (type (simple-array (unsigned-byte 8) (*)) mb-vector)) + (loop for from-index from start below end + for to-index upfrom 0 + do (progn + (setf (aref mb-vector to-index) + (char-code (aref string from-index))))) + (when null-terminate + (setf (aref mb-vector (1- number-of-octets)) 0)) + (values mb-vector number-of-octets))) Added: branches/trunk-reorg/thirdparty/acl-compat/clisp/acl-mp.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/acl-compat/clisp/acl-mp.lisp Thu Feb 7 03:21:48 2008 @@ -0,0 +1,74 @@ +;; Stubs for multiprocessing functions under clisp. Clisp does not +;; provide threads at the time of writing, so these functions are here +;; only to compile aserve with a minimum of changes in the main code. +;; +;; Written by Rudi Schlatte + + +(in-package :acl-compat-mp) + +(defvar *current-process*) + +(defun process-allow-schedule () + (values)) + +(defun process-allow-scheduling () + (values)) + +(defun process-plist (process) + (declare (ignore process)) + (error "Attempting to use multithreading with clisp.")) + +(defun (setf process-plist) (new-value process) + (declare (ignore new-value process)) + (error "Attempting to use multithreading with clisp.")) + +(defun process-run-reasons (process) + (declare (ignore process)) + (error "Attempting to use multithreading with clisp.")) + +(defun (setf process-run-reasons) (new-value process) + (declare (ignore new-value process)) + (error "Attempting to use multithreading with clisp.")) + +(defun process-revoke-run-reason (process object) + (declare (ignore process object)) + (error "Attempting to use multithreading with clisp.")) + +(defun process-add-run-reason (process object) + (declare (ignore process object)) + (error "Attempting to use multithreading with clisp.")) + +(defun process-run-function (name function &rest arguments) + (declare (ignore name function arguments)) + (error "Attempting to use multithreading with clisp.")) + +(defun process-kill (process) + (declare (ignore process)) + (error "Attempting to use multithreading with clisp.")) + +(defmacro with-gensyms (syms &body body) + "Bind symbols to gensyms. First sym is a string - `gensym' prefix. +Inspired by Paul Graham, , p. 145." + `(let (,@(mapcar (lambda (sy) `(,sy (gensym ,(car syms)))) (cdr syms))) + , at body)) + +(defun interrupt-process (process function &rest args) + (declare (ignore process function args)) + (error "Attempting to use multithreading with clisp.")) + +(defun make-process-lock (&key name) + (declare (ignore name)) + (error "Attempting to use multithreading with clisp.")) + +(defmacro with-process-lock ((lock &key norecursive whostate timeout) + &body forms) + (declare (ignore lock norecursive whostate timeout)) + `(progn , at forms)) + +(defmacro with-timeout ((seconds &body timeout-forms) &body body) + (declare (ignore seconds timeout-forms)) + `(progn , at body)) + +(defmacro without-scheduling (&body body) + `(progn , at body)) Added: branches/trunk-reorg/thirdparty/acl-compat/clisp/acl-socket.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/acl-compat/clisp/acl-socket.lisp Thu Feb 7 03:21:48 2008 @@ -0,0 +1,174 @@ +;; This package is designed for clisp. It implements the +;; ACL-style socket interface on top of clisp. +;; +;; Written by Rudi Schlatte, based on the work done by Jochen Schmidt +;; for Lispworks and net.lisp in the port library of CLOCC. + +(in-package :acl-socket) + +(defclass server-socket () + ((port :type fixnum + :initarg :port + :reader port) + (stream-type :type (member :text :binary :bivalent) + :initarg :stream-type + :reader stream-type + :initform (error "No value supplied for stream-type")) + (clisp-socket-server :initarg :clisp-socket-server + :reader clisp-socket-server))) + +(defmethod print-object ((server-socket server-socket) stream) + (print-unreadable-object (server-socket stream :type t :identity nil) + (format stream "@port ~d" (port server-socket)))) + +(defun %get-element-type (format) + (ecase format + (:text 'character) + (:binary '(unsigned-byte 8)) + (:bivalent '(unsigned-byte 8))) ) + +(defgeneric accept-connection (server-socket &key wait)) +(defmethod accept-connection ((server-socket server-socket) + &key (wait t)) + "Return a bidirectional stream connected to socket, or nil if no +client wanted to initiate a connection and wait is nil." + (when (cond ((numberp wait) + (socket-wait (clisp-socket-server server-socket) wait)) + (wait (socket-wait (clisp-socket-server server-socket))) + (t (socket-wait (clisp-socket-server server-socket) 0))) + (let ((stream (socket-accept (clisp-socket-server server-socket) + :element-type (%get-element-type + (stream-type server-socket)) + ))) + (if (eq (stream-type server-socket) :bivalent) + (make-bivalent-stream stream) + stream)))) + + +(defun make-socket (&key (remote-host "localhost") + local-port + remote-port + (connect :active) + (format :text) + &allow-other-keys) + "Return a stream connected to remote-host if connect is :active, or +something listening on local-port that can be fed to accept-connection +if connect is :passive." + (check-type remote-host string) + (ecase connect + (:passive + (make-instance 'server-socket + :port local-port + :clisp-socket-server (socket-server local-port) + :stream-type format)) + (:active + (let ((stream (socket-connect + remote-port remote-host + :element-type (%get-element-type format) + ))) + (if (eq format :bivalent) + (make-bivalent-stream stream) + stream))))) + +(defmethod close ((server-socket server-socket) &key abort) + "Kill a passive (listening) socket. (Active sockets are actually +streams and handled by their close methods." + (declare (ignore abort)) + (socket-server-close (clisp-socket-server server-socket))) + +(declaim (ftype (function ((unsigned-byte 32)) (values simple-string)) + ipaddr-to-dotted)) +(defun ipaddr-to-dotted (ipaddr &key values) + (declare (type (unsigned-byte 32) ipaddr)) + (let ((a (logand #xff (ash ipaddr -24))) + (b (logand #xff (ash ipaddr -16))) + (c (logand #xff (ash ipaddr -8))) + (d (logand #xff ipaddr))) + (if values + (values a b c d) + (format nil "~d.~d.~d.~d" a b c d)))) + +(defun string-tokens (string) + (labels ((get-token (str pos1 acc) + (let ((pos2 (position #\Space str :start pos1))) + (if (not pos2) + (nreverse acc) + (get-token str (1+ pos2) (cons (read-from-string (subseq str pos1 pos2)) + acc)))))) + (get-token (concatenate 'string string " ") 0 nil))) + +(declaim (ftype (function (string &key (:errorp t)) + (values (unsigned-byte 32))) + dotted-to-ipaddr)) +(defun dotted-to-ipaddr (dotted &key (errorp t)) + (declare (string dotted)) + (if errorp + (let ((ll (string-tokens (substitute #\Space #\. dotted)))) + (+ (ash (first ll) 24) (ash (second ll) 16) + (ash (third ll) 8) (fourth ll))) + (ignore-errors + (let ((ll (string-tokens (substitute #\Space #\. dotted)))) + (+ (ash (first ll) 24) (ash (second ll) 16) + (ash (third ll) 8) (fourth ll)))))) + + +(defun ipaddr-to-hostname (ipaddr &key ignore-cache) + (when ignore-cache + (warn ":IGNORE-CACHE keyword in IPADDR-TO-HOSTNAME not supported.")) + (posix::hostent-name (posix:resolve-host-ipaddr ipaddr))) + +(defun lookup-hostname (host &key ignore-cache) + (when ignore-cache + (warn ":IGNORE-CACHE keyword in LOOKUP-HOSTNAME not supported.")) + (if (stringp host) + (car (posix::hostent-addr-list (posix:resolve-host-ipaddr host))) + (dotted-to-ipaddr (ipaddr-to-dotted host)))) + +(defgeneric get-clisp-stream (stream)) + +(defmethod get-clisp-stream ((stream gray-stream::native-lisp-stream-mixin)) + (gray-stream::native-lisp-stream stream)) + +(defmethod get-clisp-stream ((stream t)) + (the stream stream)) + +(defun remote-host (socket-stream) + (dotted-to-ipaddr + (nth-value 0 (socket-stream-peer (get-clisp-stream socket-stream) t)))) + +(defun remote-port (socket-stream) + (nth-value 1 (socket-stream-peer (get-clisp-stream socket-stream) t))) + +(defun local-host (socket-stream) + (dotted-to-ipaddr + (nth-value 0 (socket-stream-local (get-clisp-stream socket-stream) t)))) + +(defun local-port (socket-stream) + (nth-value 1 (socket-stream-local (get-clisp-stream socket-stream) t))) + +;; Now, throw chunking in the mix + +(defclass chunked-stream (de.dataheaven.chunked-stream-mixin::chunked-stream-mixin + gray-stream::buffered-bivalent-stream) + ((plist :initarg :plist :accessor stream-plist))) + + +(defun make-bivalent-stream (lisp-stream &key plist) + (make-instance 'chunked-stream :lisp-stream lisp-stream :plist plist)) + + +(defun socket-control (stream &key (output-chunking nil oc-p) output-chunking-eof (input-chunking nil ic-p)) + (when oc-p + (when output-chunking + (de.dataheaven.chunked-stream-mixin::initialize-output-chunking stream)) + (setf (de.dataheaven.chunked-stream-mixin::output-chunking-p stream) + output-chunking)) + (when output-chunking-eof + (de.dataheaven.chunked-stream-mixin::disable-output-chunking stream)) + (when ic-p + (when input-chunking + (de.dataheaven.chunked-stream-mixin::initialize-input-chunking stream)) + (setf (de.dataheaven.chunked-stream-mixin::input-chunking-p stream) + input-chunking))) + +(provide 'acl-socket) Added: branches/trunk-reorg/thirdparty/acl-compat/clisp/acl-sys.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/acl-compat/clisp/acl-sys.lisp Thu Feb 7 03:21:48 2008 @@ -0,0 +1,22 @@ + +(eval-when (:compile-toplevel :load-toplevel :execute) + (ext:without-package-lock () + (let ((sys-package (find-package "SYSTEM"))) + (export (list (intern "COMMAND-LINE-ARGUMENTS" sys-package) + (intern "COMMAND-LINE-ARGUMENT" sys-package) + (intern "REAP-OS-SUBPROCESS" sys-package)) + sys-package)))) + +(ext:without-package-lock () + (defun sys:command-line-arguments () + ext:*args*)) + +(ext:without-package-lock () + (defun sys:command-line-argument (n) + (nth n ext:*args*))) + +(ext:without-package-lock () + (defun sys:reap-os-subprocess (&key (wait nil)) + (declare (ignore wait)) + nil)) + Added: branches/trunk-reorg/thirdparty/acl-compat/cmucl/acl-excl.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/acl-compat/cmucl/acl-excl.lisp Thu Feb 7 03:21:48 2008 @@ -0,0 +1,71 @@ +;;;; +;;;; ACL-COMPAT - EXCL +;;;; + +;;;; Implementation-specific parts of acl-compat.excl (see +;;;; acl-excl-common.lisp) + +(in-package :acl-compat.excl) + +(defun stream-input-fn (stream) + stream) + +(defun filesys-type (file-or-directory-name) + (if (eq :directory (unix:unix-file-kind + (namestring file-or-directory-name))) + :directory + (if (probe-file file-or-directory-name) + :file + nil))) + +(defmacro atomically (&body forms) + `(mp:without-scheduling , at forms)) + +(defun unix-signal (signal pid) + ;; fixxme: did I get the arglist right? only invocation I have seen + ;; is (excl::unix-signal 15 0) in net.aserve:start + (unix:unix-kill pid signal)) + +(defmacro without-package-locks (&body forms) + `(progn , at forms)) + +(defun filesys-inode (path) + (multiple-value-bind (found ign inode) + (unix:unix-lstat path) + (if found + inode + (error "path ~s does not exist" path)))) + +(defun cl-internal-real-time () + (round (/ (get-internal-real-time) internal-time-units-per-second))) + +(defun string-to-octets (string &key (null-terminate t) (start 0) + end mb-vector make-mb-vector? + (external-format :default)) + "This function returns a lisp-usb8-vector and the number of bytes copied." + (declare (ignore external-format)) + ;; The end parameter is different in ACL's lambda list, but this + ;; variant lets us give an argument :end nil explicitly, and the + ;; right thing will happen + (unless end (setf end (length string))) + (let* ((number-of-octets (if null-terminate (1+ (- end start)) + (- end start))) + (mb-vector (cond + ((and mb-vector (>= (length mb-vector) number-of-octets)) + mb-vector) + ((or (not mb-vector) make-mb-vector?) + (make-array (list number-of-octets) + :element-type '(unsigned-byte 8) + :initial-element 0)) + (t (error "Was given a vector of length ~A, ~ + but needed at least length ~A." + (length mb-vector) number-of-octets))))) + (declare (type (simple-array (unsigned-byte 8) (*)) mb-vector)) + (loop for from-index from start below end + for to-index upfrom 0 + do (progn + (setf (aref mb-vector to-index) + (char-code (aref string from-index))))) + (when null-terminate + (setf (aref mb-vector (1- number-of-octets)) 0)) + (values mb-vector number-of-octets))) Added: branches/trunk-reorg/thirdparty/acl-compat/cmucl/acl-mp.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/acl-compat/cmucl/acl-mp.lisp Thu Feb 7 03:21:48 2008 @@ -0,0 +1,170 @@ +;; This package is designed for cmucl. It implements ACL-style +;; multiprocessing on top of cmucl (basically, process run reasons and +;; some function renames). +;; +;; Written by Rudi Schlatte, based on the work done by Jochen Schmidt +;; for Lispworks. + +(in-package :acl-compat.mp) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Import equivalent parts from the CMU MP package ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(shadowing-import '(mp:*current-process* + ;; mp::process-preset + mp::process-reset + mp:process-interrupt + mp::process-name + mp::process-wait-function + mp:process-run-reasons + mp:process-add-run-reason + mp:process-revoke-run-reason + mp:process-arrest-reasons + mp:process-add-arrest-reason + mp:process-revoke-arrest-reason + mp:process-whostate + ; mp:without-interrupts + mp:process-wait + mp:with-timeout + mp:without-scheduling + mp:process-active-p + )) + +(export '(*current-process* + ;; process-preset + process-reset + process-interrupt + process-name + process-wait-function + process-whostate + process-wait + with-timeout + without-scheduling + process-run-reasons + process-add-run-reason + process-revoke-run-reason + process-arrest-reasons + process-add-arrest-reason + process-revoke-arrest-reason + process-active-p + )) + + +(defun process-allow-schedule () + (mp:process-yield)) + +(defvar *process-plists* (make-hash-table :test #'eq) + "maps processes to their plists. +See the functions process-plist, (setf process-plist).") + +(defun process-property-list (process) + (gethash process *process-plists*)) + +(defun (setf process-property-list) (new-value process) + (setf (gethash process *process-plists*) new-value)) + +#|| + +;;; rudi 2002-06-09: This is not needed as of cmucl 18d, thanks to Tim +;;; Moore who added run reasons to cmucl's multithreading. Left in +;;; for the time being just in case someone wants to get acl-compat +;;; running on older cmucl's. Can be deleted safely. + +(defvar *process-run-reasons* (make-hash-table :test #'eq) + "maps processes to their run-reasons. +See the functions process-run-reasons, (setf process-run-reasons), +process-add-run-reason, process-revoke-run-reason.") + +(defun process-run-reasons (process) + (gethash process *process-run-reasons*)) + +(defun (setf process-run-reasons) (new-value process) + (mp:without-scheduling + (prog1 + (setf (gethash process *process-run-reasons*) new-value) + (if new-value + (mp:enable-process process) + (mp:disable-process process))))) + +(defun process-revoke-run-reason (process object) + (without-scheduling + (setf (process-run-reasons process) + (remove object (process-run-reasons process)))) + (when (and (eq process mp:*current-process*)) + (mp:process-yield))) + +(defun process-add-run-reason (process object) + (setf (process-run-reasons process) + (pushnew object (process-run-reasons process)))) +||# + +(defun process-run-function (name-or-options preset-function + &rest preset-arguments) + (let ((process (etypecase name-or-options + (string (make-process :name name-or-options + :run-reasons '(t))) + (list (apply #'make-process :run-reasons '(t) + name-or-options))))) + (apply #'acl-mp::process-preset process preset-function preset-arguments) + process)) + +(defun process-preset (process preset-function &rest arguments) + (mp:process-preset process + #'(lambda () + (apply-with-bindings preset-function + arguments + (process-initial-bindings process))))) + +(defvar *process-initial-bindings* (make-hash-table :test #'eq)) + +(defun process-initial-bindings (process) + (gethash process *process-initial-bindings*)) + +(defun (setf process-initial-bindings) (bindings process) + (setf (gethash process *process-initial-bindings*) bindings)) + + +;;; ;;; +;;; Contributed by Tim Moore ;;; +;;; ;;; +(defun apply-with-bindings (function args bindings) + (if bindings + (progv + (mapcar #'car bindings) + (mapcar #'(lambda (binding) + (eval (cdr binding))) + bindings) + (apply function args)) + (apply function args))) + +(defun make-process (&key (name "Anonymous") reset-action run-reasons + arrest-reasons (priority 0) quantum resume-hook + suspend-hook initial-bindings run-immediately) + (declare (ignore priority quantum reset-action resume-hook suspend-hook + run-immediately)) + (mp:make-process nil :name name + :run-reasons run-reasons + :arrest-reasons arrest-reasons + :initial-bindings initial-bindings)) + +(defun process-kill (process) + (mp:destroy-process process)) + + +(defun make-process-lock (&key name) + (mp:make-lock name)) + +(defun process-lock (lock) + (mp::lock-wait lock (mp:process-whostate mp:*current-process*))) + +(defun process-unlock (lock) + (setf (mp::lock-process lock) nil)) + + +(defmacro with-process-lock ((lock &key norecursive whostate timeout) &body forms) + (declare (ignore norecursive)) + `(mp:with-lock-held (,lock + ,@(when whostate (list :whostate whostate)) + ,@(when timeout (list :timeout timeout))) + , at forms)) Added: branches/trunk-reorg/thirdparty/acl-compat/cmucl/acl-socket.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/acl-compat/cmucl/acl-socket.lisp Thu Feb 7 03:21:48 2008 @@ -0,0 +1,208 @@ +;; This package is designed for cmucl. It implements the +;; ACL-style socket interface on top of cmucl. +;; +;; Written by Rudi Schlatte, based on the work done by Jochen Schmidt +;; for Lispworks and net.lisp in the port library of CLOCC. + +(in-package acl-compat.socket) + +(defclass socket () + ((fd :type fixnum + :initarg :fd + :reader fd))) + +(defmethod print-object ((socket socket) stream) + (print-unreadable-object (socket stream :type t :identity t) + (format stream "@~d" (fd socket)))) + +(defclass server-socket (socket) + ((element-type :type (member signed-byte unsigned-byte base-char) + :initarg :element-type + :reader element-type + :initform (error "No value supplied for element-type")) + (port :type fixnum + :initarg :port + :reader port + :initform (error "No value supplied for port")) + (stream-type :type (member :text :binary :bivalent) + :initarg :stream-type + :reader stream-type + :initform (error "No value supplied for stream-type")))) + +#+cl-ssl +(defmethod make-ssl-server-stream ((lisp-stream system:lisp-stream) + &rest options) + (apply #'make-ssl-server-stream (system:fd-stream-fd lisp-stream) options)) + +(defmethod print-object ((socket server-socket) stream) + (print-unreadable-object (socket stream :type t :identity nil) + (format stream "@~d on port ~d" (fd socket) (port socket)))) + +(defmethod accept-connection ((server-socket server-socket) + &key (wait t)) + "Return a bidirectional stream connected to socket, or nil if no +client wanted to initiate a connection and wait is nil." + ;; fixxme: perhaps check whether we run multiprocessing and use + ;; sys:wait-until-fd-usable instead of + ;; mp:process-wait-until-fd-usable here? + + ;; api pipe fitting: wait t ==> timeout nil + (when (mp:process-wait-until-fd-usable (fd server-socket) :input + (if wait nil 0)) + (let ((stream (sys:make-fd-stream + (ext:accept-tcp-connection (fd server-socket)) + :input t :output t + :element-type (element-type server-socket) + :auto-close t))) + (if (eq (stream-type server-socket) :bivalent) + (make-bivalent-stream stream) + stream)))) + +(defun make-socket (&key (remote-host "localhost") + local-port + remote-port + (connect :active) + (format :text) + (reuse-address t) + &allow-other-keys) + "Return a stream connected to remote-host if connect is :active, or +something listening on local-port that can be fed to accept-connection +if connect is :passive. + +This is an incomplete implementation of ACL's make-socket function! +It was written to provide the functionality necessary to port +AllegroServe. Refer to +http://franz.com/support/documentation/6.1/doc/pages/operators/socket/make-socket.htm +to read about the missing parts." + (check-type remote-host string) + (let ((element-type (ecase format + (:text 'base-char) + (:binary 'signed-byte) + (:bivalent 'unsigned-byte)))) + (ecase connect + (:passive + (make-instance 'server-socket + :port local-port + :fd (ext:create-inet-listener local-port :stream :reuse-address reuse-address) + :element-type element-type + :stream-type format)) + (:active + (let ((stream (sys:make-fd-stream + (ext:connect-to-inet-socket remote-host remote-port) + :input t :output t :element-type element-type))) + (if (eq :bivalent format) + (make-bivalent-stream stream) + stream)))))) + +(defmethod close ((server server-socket) &key abort) + "Kill a passive (listening) socket. (Active sockets are actually +streams and handled by their close methods." + (declare (ignore abort)) + (unix:unix-close (fd server))) + +(declaim (ftype (function ((unsigned-byte 32) &key (:values t)) + (values simple-string)) + ipaddr-to-dotted)) +(defun ipaddr-to-dotted (ipaddr &key values) + (declare (type (unsigned-byte 32) ipaddr)) + (let ((a (logand #xff (ash ipaddr -24))) + (b (logand #xff (ash ipaddr -16))) + (c (logand #xff (ash ipaddr -8))) + (d (logand #xff ipaddr))) + (if values + (values a b c d) + (format nil "~d.~d.~d.~d" a b c d)))) + +(defun string-tokens (string) + (labels ((get-token (str pos1 acc) + (let ((pos2 (position #\Space str :start pos1))) + (if (not pos2) + (nreverse acc) + (get-token str (1+ pos2) (cons (read-from-string (subseq str pos1 pos2)) + acc)))))) + (get-token (concatenate 'string string " ") 0 nil))) + +(declaim (ftype (function (string &key (:errorp t)) + (values (unsigned-byte 32))) + dotted-to-ipaddr)) +(defun dotted-to-ipaddr (dotted &key (errorp t)) + (declare (string dotted)) + (if errorp + (let ((ll (string-tokens (substitute #\Space #\. dotted)))) + (+ (ash (first ll) 24) (ash (second ll) 16) + (ash (third ll) 8) (fourth ll))) + (ignore-errors + (let ((ll (string-tokens (substitute #\Space #\. dotted)))) + (+ (ash (first ll) 24) (ash (second ll) 16) + (ash (third ll) 8) (fourth ll)))))) + +(defun ipaddr-to-hostname (ipaddr &key ignore-cache) + (when ignore-cache + (warn ":IGNORE-CACHE keyword in IPADDR-TO-HOSTNAME not supported.")) + (ext:host-entry-name (ext:lookup-host-entry ipaddr))) + +(defun lookup-hostname (host &key ignore-cache) + (when ignore-cache + (warn ":IGNORE-CACHE keyword in LOOKUP-HOSTNAME not supported.")) + (if (stringp host) + (car (ext:host-entry-addr-list (ext:lookup-host-entry host))) + (dotted-to-ipaddr (ipaddr-to-dotted host)))) + +(defgeneric get-fd (stream)) + +(defmethod get-fd ((stream gray-stream::native-lisp-stream-mixin)) + (system:fd-stream-fd (gray-stream::native-lisp-stream stream))) + +(defmethod get-fd ((stream system:lisp-stream)) + (system:fd-stream-fd stream)) + +(defmethod get-fd ((stream server-socket)) + (fd stream)) + +(defun remote-host (socket-stream) + (ext:get-peer-host-and-port (get-fd socket-stream))) + +(defun remote-port (socket-stream) + (multiple-value-bind (host port) + (ext:get-peer-host-and-port (get-fd socket-stream)) + (declare (ignore host)) + port)) + +(defun local-host (socket-stream) + (ext:get-socket-host-and-port (get-fd socket-stream))) + +(defun local-port (socket-stream) + (if (typep socket-stream 'socket::server-socket) + (port socket-stream) + (multiple-value-bind (host port) + (ext:get-socket-host-and-port (get-fd socket-stream)) + (declare (ignore host)) + port))) + +;; Now, throw chunking in the mix + +(defclass chunked-stream (de.dataheaven.chunked-stream-mixin::chunked-stream-mixin + gray-stream::buffered-bivalent-stream) + ()) + + +(defun make-bivalent-stream (lisp-stream) + (make-instance 'chunked-stream :lisp-stream lisp-stream)) + + +(defun socket-control (stream &key (output-chunking nil oc-p) output-chunking-eof (input-chunking nil ic-p)) + (when oc-p + (when output-chunking + (de.dataheaven.chunked-stream-mixin::initialize-output-chunking stream)) + (setf (de.dataheaven.chunked-stream-mixin::output-chunking-p stream) + output-chunking)) + (when output-chunking-eof + (de.dataheaven.chunked-stream-mixin::disable-output-chunking stream)) + (when ic-p + (when input-chunking + (de.dataheaven.chunked-stream-mixin::initialize-input-chunking stream)) + (setf (de.dataheaven.chunked-stream-mixin::input-chunking-p stream) + input-chunking))) + + +(provide 'acl-socket) Added: branches/trunk-reorg/thirdparty/acl-compat/cmucl/acl-sys.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/acl-compat/cmucl/acl-sys.lisp Thu Feb 7 03:21:48 2008 @@ -0,0 +1,18 @@ +(in-package :acl-compat.system) + +(ignore-errors +(export 'command-line-arguments) +(export 'command-line-argument) +(export 'reap-os-subprocess) + +(defun command-line-arguments () + ext:*command-line-strings*) + +(defun command-line-argument (n) + (nth n ext:*command-line-strings*)) + +(defun reap-os-subprocess (&key (wait nil)) + (declare (ignore wait)) + nil) + +) Added: branches/trunk-reorg/thirdparty/acl-compat/defsys.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/acl-compat/defsys.lisp Thu Feb 7 03:21:48 2008 @@ -0,0 +1,50 @@ +(in-package "CL-USER") + +(defsystem "ACL-COMPAT" + (:default-pathname "ACL-COMPAT:") + :members + ("acl-compat-common-lisp-lw" + "nregex" + "acl-excl-lw" + "acl-mp-package" + "acl-mp-lw" + "gray-stream-package" + "acl-socket-lw" + "acl-sys-lw" + "meta" + "uri" + "chunked-stream-mixin") + + :rules + ((:in-order-to :compile "acl-excl-lw" + (:caused-by (:compile "nregex")) + (:requires (:load "nregex"))) + (:in-order-to :load "acl-excl-lw" + (:requires (:load "nregex"))) + + (:in-order-to :compile "acl-mp-lw" + (:caused-by (:compile "acl-mp-package" "acl-socket-lw")) + (:requires (:load "acl-mp-package" "acl-socket-lw"))) + (:in-order-to :load "acl-mp-lw" + (:requires (:load "acl-mp-package" "acl-socket-lw"))) + + (:in-order-to :compile "acl-socket-lw" + (:caused-by (:compile "chunked-stream-mixin")) + (:requires (:load "chunked-stream-mixin"))) + (:in-order-to :load "acl-socket-lw" + (:requires (:load "chunked-stream-mixin"))) + + (:in-order-to :compile "chunked-stream-mixin" + (:caused-by (:compile "acl-excl-lw" "gray-stream-package")) + (:requires (:load "acl-excl-lw" "gray-stream-package"))) + (:in-order-to :load "chunked-stream-mixin" + (:requires (:load "acl-excl-lw" "gray-stream-package"))) + + (:in-order-to :compile "uri" + (:caused-by (:compile "meta")) + (:requires (:load "meta"))) + (:in-order-to :load "uri" + (:requires (:load "meta"))))) + +(eval-when (:load-toplevel :execute) + (pushnew :acl-compat *features*)) Added: branches/trunk-reorg/thirdparty/acl-compat/lispworks/acl-excl.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/acl-compat/lispworks/acl-excl.lisp Thu Feb 7 03:21:48 2008 @@ -0,0 +1,85 @@ +;;;; +;;;; ACL-COMPAT - EXCL +;;;; + +;;;; Implementation-specific parts of acl-compat.excl (see +;;;; acl-excl-common.lisp) + +(in-package :acl-compat.excl) + +#+obsolete +(defun stream-input-fn (stream) + stream) + +(defmethod stream-input-fn ((stream stream)) + stream) + +(defun filesys-type (file-or-directory-name) + (if (lw::file-directory-p file-or-directory-name) + :directory + (if (probe-file file-or-directory-name) + :file + nil))) + +#-:win32 +(defun filesys-inode (path) + (let ((checked-path (probe-file path))) + (cond + (checked-path (let ((stat (system:get-file-stat checked-path))) + (system:file-stat-inode stat))) + (t (error "path ~a does not exist." path))))) + +(defmacro atomically (&body forms) + `(mp:without-preemption , at forms)) + +(defmacro without-package-locks (&body forms) + `(progn , at forms)) + + +#| +(defun run-shell-command () + (with-open-stream (s (open-pipe "/bin/sh" + :direction :io + :buffered nil)) + (loop for var in environment + do (format stream "~A=~A~%" (car var) (cdr var))) +|# + +;; NDL 2004-06-04 -- Missing definition & a package, to allow LispWorks to load webactions + +(defun cl-internal-real-time () + (round (/ (get-internal-real-time) 1000))) + +(defun string-to-octets (string &key (null-terminate t) (start 0) + end mb-vector make-mb-vector? + (external-format :default)) + "This function returns a lisp-usb8-vector and the number of bytes copied." + (declare (ignore external-format)) + ;; The end parameter is different in ACL's lambda list, but this + ;; variant lets us give an argument :end nil explicitly, and the + ;; right thing will happen + (unless end (setf end (length string))) + (let* ((number-of-octets (if null-terminate (1+ (- end start)) + (- end start))) + (mb-vector (cond + ((and mb-vector (>= (length mb-vector) number-of-octets)) + mb-vector) + ((or (not mb-vector) make-mb-vector?) + (make-array (list number-of-octets) + :element-type '(unsigned-byte 8) + :initial-element 0)) + (t (error "Was given a vector of length ~A, ~ + but needed at least length ~A." + (length mb-vector) number-of-octets))))) + (declare (type (simple-array (unsigned-byte 8) (*)) mb-vector)) + (loop for from-index from start below end + for to-index upfrom 0 + do (progn + (setf (aref mb-vector to-index) + (char-code (aref string from-index))))) + (when null-terminate + (setf (aref mb-vector (1- number-of-octets)) 0)) + (values mb-vector number-of-octets))) + + +(provide 'acl-excl) Added: branches/trunk-reorg/thirdparty/acl-compat/lispworks/acl-mp.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/acl-compat/lispworks/acl-mp.lisp Thu Feb 7 03:21:48 2008 @@ -0,0 +1,209 @@ +;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Package: CL-USER; -*- +;;;; ; +;;;; (c) 2001 by Jochen Schmidt. +;;;; +;;;; File: acl-mp-lw.lisp +;;;; Revision: 1.0.0 +;;;; Description: LispWorks implementation for ACL-COMPAT-MP +;;;; Date: 02.02.2002 +;;;; Authors: Jochen Schmidt +;;;; Tel: (+49 9 11) 47 20 603 +;;;; Email: jsc at dataheaven.de +;;;; +;;;; Redistribution and use in source and binary forms, with or without +;;;; modification, are permitted provided that the following conditions +;;;; are met: +;;;; 1. Redistributions of source code must retain the above copyright +;;;; notice, this list of conditions and the following disclaimer. +;;;; 2. Redistributions in binary form must reproduce the above copyright +;;;; notice, this list of conditions and the following disclaimer in the +;;;; documentation and/or other materials provided with the distribution. +;;;; +;;;; THIS SOFTWARE IS PROVIDED "AS IS" AND THERE ARE NEITHER +;;;; EXPRESSED NOR IMPLIED WARRANTIES - THIS INCLUDES, BUT +;;;; IS NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY +;;;; AND FITNESS FOR A PARTICULAR PURPOSE.IN NO WAY ARE THE +;;;; AUTHORS LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +;;;; SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +;;;; NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES ; +;;;; LOSS OF USE, DATA, OR PROFITS ; OR BUSINESS INTERRUPTION) +;;;; +;;;; For further details contact the authors of this software. +;;;; +;;;; Jochen Schmidt +;;;; Zuckmantelstr. 11 +;;;; 91616 Neusitz +;;;; GERMANY +;;;; +;;;; + +(eval-when (:compile-toplevel :load-toplevel :execute) + (require "comm")) + +(in-package :acl-compat-mp) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Import equivalent parts from the LispWorks MP package ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(shadowing-import '( + mp:*current-process* + mp:process-kill + mp:process-enable + mp:process-disable + mp::process-preset + mp:process-reset + mp:process-interrupt + mp::process-name + mp:process-wait-function + mp:process-run-reasons + mp:process-arrest-reasons + mp:process-whostate + mp:without-interrupts + mp:process-wait + mp::process-active-p + )) + +(export '( *current-process* + process-kill + process-enable + process-disable + process-preset + process-reset + process-interrupt + process-name + process-wait-function + process-run-reasons + process-arrest-reasons + process-whostate + without-interrupts + process-wait + process-active-p + )) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Implement missing (and differing) functions ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(defun make-process (&key (name "Anonymous") reset-action run-reasons arrest-reasons (priority 0) quantum + resume-hook suspend-hook initial-bindings run-immediately) + (declare (ignore priority quantum reset-action resume-hook suspend-hook run-immediately)) + (let ((mp:*process-initial-bindings* initial-bindings)) + (mp:create-process name :run-reasons run-reasons :arrest-reasons arrest-reasons))) + +(defun process-run-function (name-or-options preset-function &rest preset-arguments) + (let ((process (ctypecase name-or-options + (string (make-process :name name-or-options)) + (list (apply #'make-process name-or-options))))) + (apply #'mp::process-preset process preset-function preset-arguments) + (push :enable (mp:process-run-reasons process)) + process)) + +(defun process-property-list (process) + (mp:process-plist process)) + +(defun (setf process-property-list) (new-value process) + (setf (mp:process-plist process) new-value)) + +(defun process-name-to-process (name &optional abbrev) + (if abbrev + (let ((length (length name))) + (dolist (process (mp:list-all-processes)) + (when (and (>= (length (process-name process)) length) + (string= name (process-name process) :end2 length)) + (return process)))) + (mp:find-process-from-name (ctypecase name + (symbol (symbol-name name)) + (string name))))) + +(defun process-wait-with-timeout (whostate seconds function &rest args) + (apply #'mp:process-wait-with-timeout whostate seconds function args)) + +(defun wait-for-input-available (streams &key (wait-function #'socket::stream-input-available) whostate timeout) + (let ((collected-fds nil)) + (flet ((fd (stream-or-fd) + (typecase stream-or-fd + (comm:socket-stream (comm:socket-stream-socket stream-or-fd)) + (socket::passive-socket (socket::socket-os-fd stream-or-fd)) + (fixnum stream-or-fd))) + (collect-fds () + (setf collected-fds + (remove-if-not wait-function streams)))) + + #+unix + (unwind-protect + (progn + (dolist (stream-or-fd streams) + (mp:notice-fd (fd stream-or-fd))) + (if timeout + (mp:process-wait-with-timeout (or whostate "Waiting for input") timeout #'collect-fds) + (mp:process-wait (or whostate "Waiting for input") #'collect-fds))) + (dolist (stream-or-fd streams) + (mp:unnotice-fd (fd stream-or-fd)))) + #-unix + (if timeout + (mp:process-wait-with-timeout (or whostate "Waiting for input") timeout #'collect-fds) + (mp:process-wait (or whostate "Waiting for input") #'collect-fds))) + collected-fds)) + +(defmacro without-scheduling (&body forms) + `(mp:without-preemption , at forms)) + +(defun process-allow-schedule (&optional process) + (declare (ignore process)) + (mp:process-allow-scheduling)) + +(defun process-revoke-run-reason (process object) + (mp:without-preemption + (setf (mp:process-run-reasons process) + (remove object (mp:process-run-reasons process)))) + (when (and (eq process mp:*current-process*) + (not mp:*inhibit-scheduling-flag*)) + (mp:process-allow-scheduling))) + +(defun process-add-run-reason (process object) + (setf (mp:process-run-reasons process) (pushnew object (mp:process-run-reasons process)))) + +;revised version from alain picard +(defun invoke-with-timeout (timeout bodyfn timeoutfn) + (block timeout + (let* ((process mp:*current-process*) + (unsheduled? nil) + (timer (mp:make-timer + #'(lambda () + (mp:process-interrupt process + #'(lambda () + (unless unsheduled? + (return-from timeout + (funcall timeoutfn))))))))) + (mp:schedule-timer-relative timer timeout) + (unwind-protect (funcall bodyfn) + (without-interrupts + (mp:unschedule-timer timer) + (setf unsheduled? t)))))) + + +(defmacro with-timeout ((seconds &body timeout-forms) &body body) + "Execute BODY; if execution takes more than SECONDS seconds, terminate +and evaluate TIMEOUT-FORMS." + `(invoke-with-timeout ,seconds #'(lambda () , at body) + #'(lambda () , at timeout-forms))) + +(defun current-process () + "The current process." + mp:*current-process*) + +(defun interrupt-process (process function &rest args) + "Run FUNCTION in PROCESS." + (apply #'mp:process-interrupt process function args)) + +(defun make-process-lock (&key name) + (mp:make-lock :name name)) + +(defmacro with-process-lock ((lock &key norecursive timeout whostate) &body forms) + (declare (ignore norecursive)) + `(mp:with-lock (,lock + ,@(when whostate (list :whostate whostate)) + ,@(when timeout (list :timeout timeout))) + , at forms)) + Added: branches/trunk-reorg/thirdparty/acl-compat/lispworks/acl-socket.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/acl-compat/lispworks/acl-socket.lisp Thu Feb 7 03:21:48 2008 @@ -0,0 +1,311 @@ +;; This package is designed for LispWorks. It implements the +;; ACL-style socket interface on top of LispWorks. + +(eval-when (:compile-toplevel :load-toplevel :execute) + (require "comm")) + +#+cl-ssl +(eval-when (:compile-toplevel :load-toplevel :execute) +(ssl-internal::initialize-ssl-library) +) + +(in-package acl-compat.socket) + +(define-condition stream-error (error) + ((acl-compat.excl::stream :initarg :stream + :reader stream-error-stream) + (acl-compat.excl::action :initarg :action + :reader stream-error-action) + (acl-compat.excl::code :initarg :code + :reader stream-error-code) + (acl-compat.excl::identifier :initarg :identifier + :reader stream-error-identifier)) + (:report (lambda (condition stream) + (format stream "A stream error occured (action=~A identifier=~A code=~A stream=~S)." + (stream-error-action condition) + (stream-error-identifier condition) + (stream-error-code condition) + (stream-error-stream condition))))) + +(define-condition socket-error (stream-error) + () + (:report (lambda (condition stream) + (format stream "A socket error occured (action=~A identifier=~A code=~A stream=~S)." + (stream-error-action condition) + (stream-error-identifier condition) + (stream-error-code condition) + (stream-error-stream condition))))) + +#+unix +(defun %socket-error-identifier (code) + (case code + (32 :x-broken-pipe) + (98 :address-in-use) + (99 :address-not-available) + (100 :network-down) + (102 :network-reset) + (103 :connection-aborted) + (104 :connection-reset) + (105 :no-buffer-space) + (108 :shutdown) + (110 :connection-timed-out) + (111 :connection-refused) + (112 :host-down) + (113 :host-unreachable) + (otherwise :unknown))) + +#+win32 +(defun %socket-error-identifier (code) + (case code + (10048 :address-in-use) + (10049 :address-not-available) + (10050 :network-down) + (10052 :network-reset) + (10053 :connection-aborted) + (10054 :connection-reset) + (10055 :no-buffer-space) + (10058 :shutdown) + (10060 :connection-timed-out) + (10061 :connection-refused) + (10064 :host-down) + (10065 :host-unreachable) + (otherwise :unknown))) + +(defun socket-error (stream error-code action format-string &rest format-args) + (declare (ignore format-string format-args)) ;no valid initargs for this with socket-error + (let ((code (if (numberp error-code) error-code #+unix(lw:errno-value)))) + (error 'socket-error :stream stream :code code + :identifier (if (keywordp error-code) + error-code + (%socket-error-identifier error-code)) + :action action))) + + +(defclass socket () + ((passive-socket :type fixnum + :initarg :passive-socket + :reader socket-os-fd))) + +(defclass passive-socket (socket) + ((element-type :type (member signed-byte unsigned-byte base-char) + :initarg :element-type + :reader element-type) + (port :type fixnum + :initarg :port + :reader local-port))) + +(defclass binary-socket-stream (de.dataheaven.chunked-stream-mixin:chunked-stream-mixin comm:socket-stream) ()) +(defclass input-binary-socket-stream (binary-socket-stream)()) +(defclass output-binary-socket-stream (binary-socket-stream)()) +(defclass bidirectional-binary-socket-stream (input-binary-socket-stream output-binary-socket-stream)()) + + +(defmethod comm::socket-error ((stream binary-socket-stream) error-code format-string &rest format-args) + (apply #'socket-error stream error-code :IO format-string format-args)) + + +(declaim (inline %reader-function-for-sequence)) +(defun %reader-function-for-sequence (sequence) + (typecase sequence + (string #'read-char) + ((array unsigned-byte (*)) #'read-byte) + ((array signed-byte (*)) #'read-byte) + (otherwise #'read-byte))) + +;; Bivalent socket support for READ-SEQUENCE +(defmethod gray-stream:stream-read-sequence ((stream input-binary-socket-stream) sequence start end) + (stream::read-elements stream sequence start end (%reader-function-for-sequence sequence))) + +;; NDL 2004-06-06 -- without this, emit-clp-entity tries writing a string down a binary stream, and LW barfs +(defmethod gray-stream:stream-write-sequence ((stream output-binary-socket-stream) (sequence string) start end) + (write-string sequence stream :start start :end end)) + +;; ACL Gray-Streams Enhancment Generic Functions + +(defmethod stream-input-fn ((stream input-binary-socket-stream)) + (comm:socket-stream-socket stream)) + +(defmethod stream-output-fn ((stream output-binary-socket-stream)) + (comm:socket-stream-socket stream)) + +(defmethod socket-os-fd ((socket comm:socket-stream)) + (comm:socket-stream-socket socket)) + +(defmethod print-object ((passive-socket passive-socket) stream) + (print-unreadable-object (passive-socket stream :type t :identity nil) + (format stream "@~d on port ~d" (socket-os-fd passive-socket) (local-port passive-socket)))) + +(defmethod stream-input-available ((fd fixnum)) + (comm::socket-listen fd)) + +(defmethod stream-input-available ((stream stream::os-file-handle-stream)) + (stream-input-available (stream::os-file-handle-stream-file-handle stream))) + +(defmethod stream-input-available ((stream comm:socket-stream)) + (or (comm::socket-listen (comm:socket-stream-socket stream)) + (listen stream))) + +(defmethod stream-input-available ((stream socket::passive-socket)) + (comm::socket-listen (socket::socket-os-fd stream))) + + +(defmethod accept-connection ((passive-socket passive-socket) + &key (wait t)) + (if (or wait (stream-input-available passive-socket)) + (make-instance 'bidirectional-binary-socket-stream + :socket (comm::get-fd-from-socket (socket-os-fd passive-socket)) + :direction :io + :element-type (element-type passive-socket)))) + +(defun %new-passive-socket (local-port) + (multiple-value-bind (socket error-location error-code) + (comm::create-tcp-socket-for-service local-port) + (cond (socket socket) + (t (error 'socket-error :action error-location :code error-code :identifier :unknown))))) + +(defun make-socket (&key (remote-host "localhost") + local-port + remote-port + (connect :active) + (format :text) + (reuse-address t) + &allow-other-keys) + (declare (ignore format)) + (check-type remote-host string) + (ecase connect + (:passive + (let ((comm::*use_so_reuseaddr* reuse-address)) + (make-instance 'passive-socket + :port local-port + :passive-socket (%new-passive-socket local-port) + :element-type '(unsigned-byte 8)))) + (:active + (handler-case + (let ((stream (comm:open-tcp-stream remote-host remote-port + :direction :io + :element-type '(unsigned-byte 8) + :errorp t))) + (change-class stream 'bidirectional-binary-socket-stream)) + (simple-error (condition) + (let ((code (first (last (simple-condition-format-arguments condition))))) + (socket-error condition code + :connect "~A occured while connecting (~?)" (simple-condition-format-arguments condition)))))))) + + +(defmethod close ((passive-socket passive-socket) &key abort) + (declare (ignore abort)) + (comm::close-socket (socket-os-fd passive-socket))) + +;(declaim (ftype (function ((unsigned-byte 32)) (values simple-string)) +; ipaddr-to-dotted)) +(defun ipaddr-to-dotted (ipaddr &key values) + ;(declare (type (unsigned-byte 32) ipaddr)) + (if ipaddr ;sometimes ipaddr is nil in the log call if client has broken the connection + (let ((a (logand #xff (ash ipaddr -24))) + (b (logand #xff (ash ipaddr -16))) + (c (logand #xff (ash ipaddr -8))) + (d (logand #xff ipaddr))) + (if values + (values a b c d) + (format nil "~d.~d.~d.~d" a b c d))) + (if values (values 0 0 0 0) "0.0.0.0"))) + +(defun string-tokens (string) + (labels ((get-token (str pos1 acc) + (let ((pos2 (position #\Space str :start pos1))) + (if (not pos2) + (nreverse acc) + (get-token str (1+ pos2) (cons (read-from-string (subseq str pos1 pos2)) + acc)))))) +(get-token (concatenate 'string string " ") 0 nil))) + +(declaim (ftype (function (string &key (:errorp t)) + (values (unsigned-byte 32))) + dotted-to-ipaddr)) +(defun dotted-to-ipaddr (dotted &key (errorp t)) + (declare (string dotted)) + (if errorp + (let ((ll (string-tokens (substitute #\Space #\. dotted)))) + (+ (ash (first ll) 24) (ash (second ll) 16) + (ash (third ll) 8) (fourth ll))) + (ignore-errors + (let ((ll (string-tokens (substitute #\Space #\. dotted)))) + (+ (ash (first ll) 24) (ash (second ll) 16) + (ash (third ll) 8) (fourth ll)))))) + +(defun ipaddr-to-hostname (ipaddr &key ignore-cache) + (declare (ignore ignore-cache)) + (multiple-value-bind (name) + (comm:get-host-entry (ipaddr-to-dotted ipaddr) :fields '(:name)) + name)) + +(defun lookup-hostname (host &key ignore-cache) + (when ignore-cache + (warn ":IGNORE-CACHE keyword in LOOKUP-HOSTNAME not supported.")) + (if (stringp host) + (multiple-value-bind (addr) + (comm:get-host-entry host :fields '(:address)) + addr) + (dotted-to-ipaddr (ipaddr-to-dotted host)))) + +(defmethod remote-host ((socket comm:socket-stream)) + (comm:socket-stream-peer-address socket)) + +(defmethod remote-port ((socket comm:socket-stream)) + (multiple-value-bind (host port) + (comm:socket-stream-peer-address socket) + (declare (ignore host)) + port)) + +(defmethod local-host ((socket comm:socket-stream)) + (multiple-value-bind (host port) + (comm:socket-stream-address socket) + (declare (ignore port)) + host)) + +(defmethod local-port ((socket comm:socket-stream)) + (multiple-value-bind (host port) + (comm:socket-stream-address socket) + (declare (ignore host)) + port)) + +(defun socket-control (stream &key (output-chunking nil oc-p) output-chunking-eof (input-chunking nil ic-p)) + (when oc-p + (when output-chunking + (de.dataheaven.chunked-stream-mixin::initialize-output-chunking stream)) + (setf (de.dataheaven.chunked-stream-mixin:output-chunking-p stream) output-chunking)) + (when output-chunking-eof + (de.dataheaven.chunked-stream-mixin::disable-output-chunking stream)) + (when ic-p + (when input-chunking + (de.dataheaven.chunked-stream-mixin::initialize-input-chunking stream)) + (setf (de.dataheaven.chunked-stream-mixin:input-chunking-p stream) input-chunking))) + +#+(and :lispworks4.4 (not :cl-ssl)) +(defmethod make-ssl-client-stream ((socket-stream bidirectional-binary-socket-stream) &rest options) + (declare (ignore options)) + (comm:attach-ssl socket-stream :ssl-ctx t :ssl-side :client) + socket-stream) + +#+(and :lispworks4.4 (not :cl-ssl)) +(defun initialize-ssl-library () + ;; Dunno how to force load yet + (comm:ensure-ssl)) + +#+(and :lispworks4.4 (not :cl-ssl)) +(defmethod make-ssl-server-stream ((socket-stream bidirectional-binary-socket-stream) &key certificate certificate-password) + (flet ((ctx-configure-callback (ctx) + (comm:ssl-ctx-use-privatekey-file ctx + certificate-password + comm:SSL_FILETYPE_PEM)) + (ssl-configure-callback (ssl) + (comm:ssl-use-certificate-file ssl + certificate + comm:SSL_FILETYPE_PEM))) + (comm:attach-ssl socket-stream + :ssl-side :server + :ctx-configure-callback #'ctx-configure-callback + :ssl-configure-callback #'ssl-configure-callback)) + socket-stream) + +(provide 'acl-socket) Added: branches/trunk-reorg/thirdparty/acl-compat/lispworks/acl-sys.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/acl-compat/lispworks/acl-sys.lisp Thu Feb 7 03:21:48 2008 @@ -0,0 +1,24 @@ +(in-package :sys) +(let ((*handle-warn-on-redefinition* :warn)) +; (*packages-for-warn-on-redefinition* nil)) + + (defun command-line-arguments () + system:*line-arguments-list*) + + (defun command-line-argument (n) + (nth n system:*line-arguments-list*)) + + (defun reap-os-subprocess (&key (wait nil)) + (declare (ignore wait)) + nil) + + (export 'command-line-arguments) + (export 'command-line-argument) + (export 'reap-os-subprocess)) + +;; Franz uses the MSWINDOWS feature conditional in some of their code; +;; thus, under Windows, ACL-COMPAT should probably push MSWINDOWS +;; onto the *features* list when it detects the presence of WIN32 +;; under Lispworks. +#+WIN32 (eval-when (:compile-toplevel :load-toplevel :execute) + (pushnew :mswindows *features*)) Added: branches/trunk-reorg/thirdparty/acl-compat/lw-buffering.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/acl-compat/lw-buffering.lisp Thu Feb 7 03:21:48 2008 @@ -0,0 +1,261 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; LW Style Buffer Protocol for other Lisps ;;; +;;; So far only 8bit byte and character IO works ;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(in-package :gray-stream) + +(defvar *default-input-buffer-size* 8192) +(defvar *default-output-buffer-size* 8192) + +(eval-when (:compile-toplevel :load-toplevel :execute) + (defstruct buffer-state + (input-buffer (make-array *default-input-buffer-size* :element-type '(unsigned-byte 8)) :type (simple-array (unsigned-byte 8) (*))) + (input-index nil) + (input-limit *default-input-buffer-size* :type fixnum) + (output-buffer (make-array *default-output-buffer-size* :element-type '(unsigned-byte 8)) :type (simple-array (unsigned-byte 8) (*))) + (output-index 0) + (output-limit *default-output-buffer-size* :type fixnum))) + +;; Can be used to implement resourcing of buffers later +(defun %allocate-buffer-state (&optional (input-limit *default-input-buffer-size*) (output-limit *default-output-buffer-size*)) + (declare (ignore input-limit output-limit)) + (make-buffer-state)) + +(defun %deallocate-buffer-state (state) + (declare (ignore state))) + +;; Can be used to implement unbuffered encapsulating streams later +(defclass native-lisp-stream-mixin () + ((lisp-stream :initarg :lisp-stream + :reader native-lisp-stream)) + (:documentation "Stream mixin that encapsulates a native stream.")) + +(defclass buffered-stream-mixin (native-lisp-stream-mixin) + ((buffer-state :initform (%allocate-buffer-state))) + (:documentation "Stream mixin that provides buffering for a native lisp stream.")) + +;; fundamental-bivalent-xxx-streams can be used to implement buffered +;; and unbuffered bivalent streams. At the moment, we only implement +;; buffered ones. +(defclass fundamental-bivalent-input-stream + (fundamental-character-input-stream fundamental-binary-input-stream) + ()) + +(defclass fundamental-bivalent-output-stream + (fundamental-character-output-stream fundamental-binary-output-stream) + ()) + +(defclass buffered-bivalent-input-stream + (buffered-stream-mixin fundamental-bivalent-input-stream) + ()) + +(defclass buffered-bivalent-output-stream + (buffered-stream-mixin fundamental-bivalent-output-stream) + ()) + +(defclass buffered-bivalent-stream + (buffered-bivalent-input-stream buffered-bivalent-output-stream) + ()) + +(defmacro with-stream-output-buffer ((buffer index limit) stream &body forms) + (let ((state (gensym "BUFFER-STATE-"))) + `(let ((,state (slot-value ,stream 'buffer-state))) + (symbol-macrolet ((,buffer ,(list 'buffer-state-output-buffer state)) + (,index ,(list 'buffer-state-output-index state)) + (,limit ,(list 'buffer-state-output-limit state))) + , at forms)))) + +;;; Encapsulated native streams + +(defmethod close ((stream native-lisp-stream-mixin) &key abort) + (close (native-lisp-stream stream) :abort abort)) + +(defmethod stream-listen ((stream native-lisp-stream-mixin)) + (listen (native-lisp-stream stream))) + +(defmethod open-stream-p ((stream native-lisp-stream-mixin)) + (common-lisp::open-stream-p (native-lisp-stream stream))) + +(defmethod stream-clear-output ((stream native-lisp-stream-mixin)) + (clear-output (native-lisp-stream stream))) + +;;; Input streams + +(declaim (inline %reader-function-for-sequence)) +(defun %reader-function-for-sequence (sequence) + (typecase sequence + (string #'read-char) + ((array unsigned-byte (*)) #'read-byte) + ((array signed-byte (*)) #'read-byte) + (otherwise #'read-byte))) + +(defun read-elements (socket-stream sequence start end reader-fn) + (let* ((len (length sequence)) + (chars (- (min (or end len) len) start))) + (loop for i upfrom start + repeat chars + for char = (funcall reader-fn socket-stream) + if (eq char :eof) do (return-from read-elements i) + do (setf (elt sequence i) char)) + (+ start chars))) + +(defmacro with-stream-input-buffer ((buffer index limit) stream &body forms) + (let ((state (gensym "BUFFER-STATE-"))) + `(let ((,state (slot-value ,stream 'buffer-state))) + (symbol-macrolet ((,buffer ,(list 'buffer-state-input-buffer state)) + (,index ,(list 'buffer-state-input-index state)) + (,limit ,(list 'buffer-state-input-limit state))) + , at forms)))) + +(defgeneric stream-fill-buffer (stream)) +(defmethod stream-fill-buffer ((stream buffered-stream-mixin)) + ;; Implement b/nb semantics: block until at least one byte is read, + ;; but not until the whole buffer is filled. This means it takes at + ;; most n calls to this function to fill a buffer of length n, even + ;; with a slow connection. + (with-stream-input-buffer (buffer index limit) stream + (let* ((the-stream (native-lisp-stream stream)) + (read-bytes + (loop with byte + for n-read from 0 below limit + while (and (if (< 0 n-read) (listen the-stream) t) + (setf byte (read-byte the-stream nil nil))) + do (setf (aref buffer n-read) byte) + count t))) + (if (zerop read-bytes) + nil + (setf index 0 + limit read-bytes))))) + +(defmethod stream-read-byte ((stream buffered-bivalent-input-stream)) + (with-stream-input-buffer (buffer index limit) stream + (unless (and index (< index limit)) + (when (null (stream-fill-buffer stream)) + (return-from stream-read-byte :eof))) + (prog1 (aref buffer index) + (incf index)))) + +(defmethod stream-read-char ((stream buffered-bivalent-input-stream)) + (let ((byte (stream-read-byte stream))) + (if (eq byte :eof) + :eof + (code-char byte)))) + +(defmethod stream-read-char-no-hang ((stream buffered-bivalent-input-stream)) + (if (listen stream) + (read-char stream) + nil)) + +(defmethod stream-unread-char ((stream buffered-bivalent-input-stream) character) + (with-stream-input-buffer (buffer index limit) stream + (let ((new-index (1- index))) + (when (minusp new-index) + (error "Cannot unread char ~A" character)) + (setf (aref buffer new-index) (char-code character) + index new-index))) + nil) + +(defmethod stream-peek-char ((stream buffered-bivalent-input-stream)) + (let ((char (stream-read-char stream))) + (unless (eq char :eof) + (stream-unread-char stream char)) + char)) + + +(defmethod stream-read-line ((stream buffered-bivalent-input-stream)) + (let ((res (make-array 80 :element-type 'character :fill-pointer 0))) + (loop + (let ((ch (stream-read-char stream))) + (cond ((eq ch :eof) + (return (values (copy-seq res) t))) + ((char= ch #\Linefeed) + (return (values (copy-seq res) nil))) + (t + (vector-push-extend ch res))))))) + + +(defmethod stream-read-sequence ((stream buffered-bivalent-input-stream) sequence &optional start end) + (read-elements stream sequence start end (%reader-function-for-sequence sequence))) + +;;(defmethod stream-clear-input ((stream buffered-bivalent-input-stream)) +;; (clear-input (native-lisp-stream stream))) + +(defmethod stream-element-type ((stream fundamental-bivalent-input-stream)) + '(or character (unsigned-byte 8))) + +;;; Output streams + +(declaim (inline %writer-function-for-sequence)) +(defun %writer-function-for-sequence (sequence) + (typecase sequence + (string #'stream-write-char) + ((array unsigned-byte (*)) #'stream-write-byte) + ((array signed-byte (*)) #'stream-write-byte) + (otherwise #'stream-write-byte))) + +(defun write-elements (stream sequence start end writer-fn) + (let* ((len (length sequence)) + (start (or start 0)) + (end (or end len))) + (assert (<= 0 start end len)) + (etypecase sequence + (simple-vector (loop for i from start below end + do (funcall writer-fn stream (svref sequence i)))) + (vector (loop for i from start below end + do (funcall writer-fn stream (aref sequence i)))) + (list (loop for i from start below end + for c in (nthcdr start sequence) + do (funcall writer-fn stream c)))))) + +(defgeneric stream-write-buffer (stream buffer start end)) +(defmethod stream-write-buffer ((stream buffered-stream-mixin) buffer start end) + (let ((lisp-stream (native-lisp-stream stream))) + (write-sequence buffer lisp-stream :start start :end end))) + +(defgeneric stream-flush-buffer (stream)) +(defmethod stream-flush-buffer ((stream buffered-stream-mixin)) + (with-stream-output-buffer (buffer index limit) stream + (when (plusp index) + (stream-write-buffer stream buffer 0 index) + (setf index 0)))) + +(defmethod stream-write-byte ((stream buffered-bivalent-output-stream) byte) + (with-stream-output-buffer (buffer index limit) stream + (unless (< index limit) + (stream-flush-buffer stream)) + (setf (aref buffer index) byte) + (incf index))) + +(defmethod stream-write-char ((stream buffered-bivalent-output-stream) character) + (stream-write-byte stream (char-code character))) + +(defmethod stream-write-string ((stream buffered-bivalent-output-stream) string &optional (start 0) end) + (write-elements stream string start end #'stream-write-char)) + +(defmethod stream-write-sequence ((stream buffered-stream-mixin) sequence + &optional (start 0) end) + (write-elements stream sequence start end (%writer-function-for-sequence sequence))) + +(defmethod stream-element-type ((stream fundamental-bivalent-output-stream)) + '(or character (unsigned-byte 8))) + +(defmethod stream-line-column ((stream fundamental-bivalent-output-stream)) + nil) + +(defmethod stream-finish-output ((stream buffered-bivalent-output-stream)) + (stream-flush-buffer stream) + (finish-output (native-lisp-stream stream))) + +(defmethod stream-force-output ((stream buffered-bivalent-output-stream)) + (stream-flush-buffer stream) + (force-output (native-lisp-stream stream))) + +(defmethod stream-clear-output ((stream buffered-bivalent-output-stream)) + (with-stream-output-buffer (buffer index limit) stream + (setf index 0 + limit 0)) + (call-next-method) ; Clear native stream also + ) + + Added: branches/trunk-reorg/thirdparty/acl-compat/mcl/acl-excl.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/acl-compat/mcl/acl-excl.lisp Thu Feb 7 03:21:48 2008 @@ -0,0 +1,168 @@ +;;;; +;;;; ACL-COMPAT - EXCL +;;;; + +;;;; Implementation-specific parts of acl-compat.excl (see +;;;; acl-excl-common.lisp) + +(in-package :acl-compat.excl) + +;#-openmcl +;(defun fixnump (x) +; (ccl::fixnump x)) + +#-openmcl +(import 'ccl::fixnump) + +#+openmcl +(defun filesys-inode (path) + (or (nth-value 4 (ccl::%stat (ccl::native-translated-namestring path))) + (error "path ~s does not exist" path))) + +(defun cl-internal-real-time () + (round (/ (get-internal-real-time) 1000))) + +(defun stream-input-fn (stream) + stream) + +(defun filesys-type (file-or-directory-name) + (if (ccl:directory-pathname-p file-or-directory-name) + :directory + (if (probe-file file-or-directory-name) + :file + nil))) + +(defmacro atomically (&body forms) + `(ccl:without-interrupts , at forms)) + +(defmacro without-package-locks (&body forms) + `(progn , at forms)) + +(define-condition stream-error (error) + ((stream :initarg :stream + :reader stream-error-stream) + (action :initarg :action + :initform nil + :reader stream-error-action) + (code :initarg :code + :initform nil + :reader stream-error-code) + (identifier :initarg :identifier + :initform nil + :reader stream-error-identifier)) + (:report (lambda (condition stream) + (format stream "A stream error occured (action=~A identifier=~A code=~A stream=~S)." + (stream-error-action condition) + (stream-error-identifier condition) + (stream-error-code condition) + (stream-error-stream condition))))) + +(define-condition socket-error (stream-error) + () + (:report (lambda (condition stream) + (format stream "A socket error occured (action=~A identifier=~A code=~A stream=~S)." + (stream-error-action condition) + (stream-error-identifier condition) + (stream-error-code condition) + (stream-error-stream condition))))) + + + +;! Need to figure out what to do here +(defun fasl-read (filename) + (declare (ignore filename)) + (error "fasl-read not implemented for MCL.") ) + +(defun fasl-write (data stream opt) + (declare (ignore data stream opt)) + (error "fasl-write not implemented for MCL.") ) + + +(defmacro schedule-finalization (object function) + `(ccl:terminate-when-unreachable ,object ,function)) + +(defun run-shell-command (program + &key input output error-output separate-streams + if-input-does-not-exist if-output-exists + if-error-output-exists wait environment show-window) + (declare (ignore show-window)) + ;; KLUDGE: split borrowed from asdf, this shouldn't be done -- it + ;; would be better to use split-sequence or define one ourselves ... + ;; TODO: On Unix, acl also handles a vector of simple-strings as + ;; value for program, with different semantics. + (let* ((program-and-arguments + (delete "" (asdf::split program) :test #'string=)) + (program (car program-and-arguments)) + (arguments (cdr program-and-arguments))) + (when environment + #-unix (error "Don't know how to run program in an environment.") + (setf arguments (append + (list "-i") + (loop for (name . value) in environment + collecting (concatenate 'string name "=" value)) + (list program) + arguments)) + (setf program "env")) + + (let* ((process (run-program program arguments + :input input + :if-input-does-not-exist + if-input-does-not-exist + :output output + :if-output-exists if-output-exists + :error error-output + :if-error-exists if-error-output-exists + :wait wait)) + (in-stream (external-process-input-stream process)) + (out-stream (external-process-output-stream process)) + (err-stream (external-process-error-stream process)) + (pid (external-process-id process))) + (cond + ;; one value: exit status + (wait (nth-value 1 (external-process-status process))) + ;; four values: i/o/e stream, pid + (separate-streams + (values (if (eql input :stream) in-stream nil) + (if (eql output :stream) out-stream nil) + (if (eql error-output :stream) err-stream nil) + pid)) + ;; three values: normal stream, error stream, pid + (t (let ((normal-stream + (cond ((and (eql input :stream) (eql output :stream)) + (make-two-way-stream in-stream out-stream)) + ((eql input :stream) in-stream) + ((eql output :stream) out-stream) + (t nil))) + (error-stream (if (eql error-output :stream) err-stream nil))) + (values normal-stream error-stream pid))))))) + +(defun string-to-octets (string &key (null-terminate t) (start 0) + end mb-vector make-mb-vector? + (external-format :default)) + "This function returns a lisp-usb8-vector and the number of bytes copied." + (declare (ignore external-format)) + ;; The end parameter is different in ACL's lambda list, but this + ;; variant lets us give an argument :end nil explicitly, and the + ;; right thing will happen + (unless end (setf end (length string))) + (let* ((number-of-octets (if null-terminate (1+ (- end start)) + (- end start))) + (mb-vector (cond + ((and mb-vector (>= (length mb-vector) number-of-octets)) + mb-vector) + ((or (not mb-vector) make-mb-vector?) + (make-array (list number-of-octets) + :element-type '(unsigned-byte 8) + :initial-element 0)) + (t (error "Was given a vector of length ~A, ~ + but needed at least length ~A." + (length mb-vector) number-of-octets))))) + (declare (type (simple-array (unsigned-byte 8) (*)) mb-vector)) + (loop for from-index from start below end + for to-index upfrom 0 + do (progn + (setf (aref mb-vector to-index) + (char-code (aref string from-index))))) + (when null-terminate + (setf (aref mb-vector (1- number-of-octets)) 0)) + (values mb-vector number-of-octets))) Added: branches/trunk-reorg/thirdparty/acl-compat/mcl/acl-mp.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/acl-compat/mcl/acl-mp.lisp Thu Feb 7 03:21:48 2008 @@ -0,0 +1,183 @@ +;;; This file implements the process functions for AllegroServe in MCL. +;;; Based on the the work done for cmucl and Lispworks. +;;; +;;; John DeSoi, Ph.D. desoi at users.sourceforge.net + + +(in-package :acl-compat.mp) + +(eval-when (:compile-toplevel :load-toplevel :execute) + +; existing stuff from ccl we can reuse directly +(shadowing-import + '(ccl:*current-process* + ccl::lock + ccl:process-allow-schedule + ccl:process-name + ccl:process-preset + #-openmcl-native-threads ccl:process-run-reasons + ccl:process-wait + ccl:process-wait-with-timeout + ccl:without-interrupts)) +) + +(eval-when (:compile-toplevel :load-toplevel :execute) + +(export + '(*current-process* + lock + process-allow-schedule + process-name + process-preset + process-run-reasons + process-wait + process-wait-with-timeout + without-interrupts)) +) + +(eval-when (:compile-toplevel :load-toplevel :execute) + +(defmacro without-scheduling (&body forms) + `(ccl:without-interrupts , at forms)) + +#| +; more ideas stolen from acl-mp-lw.lisp +(defun invoke-with-timeout (seconds bodyfn timeoutfn) + (block timeout + (let* ((process *current-process*) + (timer (ccl:process-run-function "with-timeout-timer" + #'(lambda () + (sleep seconds) + (ccl:process-interrupt process + #'(lambda () + (return-from timeout + (funcall timeoutfn)))))))) + (unwind-protect (funcall bodyfn) + (ccl:process-kill timer))))) + +|# + + + +(defun invoke-with-timeout (seconds bodyfn timeoutfn) + (block timeout + (let* ((timer (ccl::make-timer-request + seconds + #'(lambda () (return-from timeout (funcall timeoutfn)))))) + (ccl::enqueue-timer-request timer) + (unwind-protect (funcall bodyfn) + (ccl::dequeue-timer-request timer))))) + + +(defmacro with-timeout ((seconds &body timeout-forms) &body body) + "Execute BODY; if execution takes more than SECONDS seconds, terminate and evaluate TIMEOUT-FORMS." + `(invoke-with-timeout ,seconds #'(lambda () , at body) + #'(lambda () , at timeout-forms))) + + +#+openmcl-native-threads +(progn + +;;; The :INITIAL-BINDINGS arg to process creation functions seems to be +;;; quoted, even when it appears in a list (as in the case of +;;; (process-run-function )) By the time that percolates down +;;; to OpenMCL's process creation functions, it should lose the quote. +;;; +;;; Perhaps I imagined that ... +;;; + +(defun ccl::openmcl-fix-initial-bindings (initial-bindings) + (if (and (consp initial-bindings) + (eq (car initial-bindings) 'quote)) + (cadr initial-bindings) + initial-bindings)) + +) + + +#-openmcl-native-threads +(defmacro process-revoke-run-reason (process reason) + `(ccl:process-disable-run-reason ,process ,reason) ) + +#-openmcl-native-threads +(defmacro process-add-run-reason (process reason) + `(ccl:process-enable-run-reason ,process ,reason) ) + + +(defmacro make-process-lock (&key name) + (if name + `(ccl:make-lock ,name) + `(ccl:make-lock))) + +(defmacro with-process-lock ((lock &key norecursive timeout whostate) &body forms) + (declare (ignore norecursive whostate timeout)) + `(ccl:with-lock-grabbed (,lock) , at forms)) + + +(defmacro process-kill (process) + `(progn + #-openmcl-native-threads + (unless (ccl:process-active-p ,process) ;won't die unless enabled + (ccl:process-reset-and-enable ,process) ) + (ccl:process-kill ,process))) +) + +(defun process-active-p (process) + (ccl::process-active-p process)) + +(defun interrupt-process (process function &rest args) + "Run FUNCTION in PROCESS." +(apply #'ccl:process-interrupt process function args)) + +(defun current-process () + "The current process." + ccl:*current-process*) + + +;property list implementation from acl-mp-cmu.lisp +(defvar *process-plists* (make-hash-table :test #'eq) + "maps processes to their plists. +See the functions process-plist, (setf process-plist).") + +(defun process-property-list (process) + (gethash process *process-plists*)) + +(defun (setf process-property-list) (new-value process) + (setf (gethash process *process-plists*) new-value)) + +; from acl-mp-lw.lisp +(defun make-process (&key (name "Anonymous") reset-action run-reasons arrest-reasons (priority 0) quantum + resume-hook suspend-hook initial-bindings run-immediately) + (declare (ignore priority quantum reset-action resume-hook suspend-hook run-immediately)) + #-openmcl-native-threads + (declare (ignore initial-bindings)) ;! need separate lexical bindings for each process? + #+openmcl-native-threads + (declare (ignore run-reasons arrest-reasons)) + ;(let ((acl-mp:*process-initial-bindings* initial-bindings)) + #-openmcl-native-threads + (ccl:make-process name :run-reasons run-reasons :arrest-reasons arrest-reasons) + #+openmcl-native-threads + (ccl:make-process name :initial-bindings (ccl::openmcl-fix-initial-bindings initial-bindings))) + +(defun process-run-function (name-or-options preset-function &rest preset-arguments) + (let ((process (ctypecase name-or-options + (string (acl-mp:make-process :name name-or-options)) + (list (apply #'acl-mp:make-process name-or-options))))) + (apply #'acl-mp:process-preset process preset-function preset-arguments) + #+openmcl-native-threads (ccl:process-enable process) + #-openmcl-native-threads (process-add-run-reason process :enable) + process)) + +;;; Busy-waiting ... +(defun wait-for-input-available (streams + &key (wait-function #'ccl:stream-listen) + whostate timeout) + (let ((collected-fds nil)) + (flet ((collect-fds () + (setf collected-fds + (remove-if-not wait-function streams)))) + + (if timeout + (process-wait-with-timeout (or whostate "Waiting for input") timeout #'collect-fds) + (process-wait (or whostate "Waiting for input") #'collect-fds))) + collected-fds)) Added: branches/trunk-reorg/thirdparty/acl-compat/mcl/acl-socket-mcl.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/acl-compat/mcl/acl-socket-mcl.lisp Thu Feb 7 03:21:48 2008 @@ -0,0 +1,268 @@ +;;; MCL layer for ACL sockets. +;;; Based on acl-socket-cmu.lisp and acl-socket-lw.lisp. +;;; +;;; John DeSoi, Ph.D. desoi at users.sourceforge.net + + +(defpackage :acl-compat.socket + (:nicknames :socket :acl-socket) + (:use :common-lisp) + (:export #:make-socket + #:accept-connection + #:ipaddr-to-dotted + #:dotted-to-ipaddr + #:ipaddr-to-hostname + #:lookup-hostname + #:remote-host + #:remote-port + #:local-host + #:local-port + #:socket-control + )) + +(in-package :socket) + +(eval-when (:compile-toplevel :load-toplevel :execute) + +(require :opentransport) + +;OpenTransport.lisp does not export anything, so do this to make it look a bit cleaner. +(import '(ccl::open-tcp-stream + ccl::opentransport-tcp-stream + ccl::opentransport-binary-tcp-stream + ccl::stream-local-port + ccl::stream-local-host + ccl::stream-local-port + ccl::stream-remote-host + ccl::stream-remote-port + ccl::inet-host-name + ccl::tcp-host-address + ) ) + +(defmacro connection-state (s) + `(ccl::opentransport-stream-connection-state ,s)) + +(defmacro connection-established (s) + `(eq :dataxfer (connection-state ,s)) ) + +) + + +;;; There is a bug in MCL (4.3.1 tested) where read-sequence and +;;; write-sequence fail with binary tcp streams. These two methods +;;; provide a work-around. +#-carbon-compat ;should be fixed starting with first carbon version (4.3.5) +(defmethod ccl:stream-write-sequence ((s opentransport-binary-tcp-stream) + (sequence ccl::simple-unsigned-byte-vector) + &key (start 0) end) + (ccl::stream-write-vector s sequence start (or end (length sequence))) + s) + + + +#-carbon-compat ;should be fixed starting with first carbon version (4.3.5) +(defmethod ccl:stream-read-sequence ((s opentransport-binary-tcp-stream) + (sequence ccl::simple-unsigned-byte-vector) + &key (start 0) (end (length sequence))) + (ccl::stream-read-bytes-to-vector s sequence (- end start) start) + end) + + + +(defmethod port ((stream opentransport-tcp-stream)) + (stream-local-port stream) ) + +(defmethod local-host ((s opentransport-tcp-stream)) + (stream-local-host s)) + +(defmethod local-port ((s opentransport-tcp-stream)) + (stream-local-port s)) + +(defmethod remote-host ((s opentransport-tcp-stream)) + (stream-remote-host s)) + +(defmethod remote-port ((s opentransport-tcp-stream)) + (stream-remote-port s)) + +;? copied from lispworks - don't think it applies to mcl +(defmethod fd ((s opentransport-tcp-stream)) + (declare (ignore s)) + 42) + + + +(defvar *passive-socket-listener-count* 10 + "Default number of listen streams to use.") + +; With ACL, an unlimited number of connections can be made to the same passive +; socket instance. Nothing like that here, so we have to create our own stream +; listener to create the "real" sockets as connections are made. + + +; Create a class to monitor streams so we have a data structure to pass to process-wait +(defclass passive-socket (stream) ;inherit stream so we can handle close + ((port + :documentation "Port we are listening on." + :initform 80 + :initarg :port + :reader local-port) + (element-type + :documentation "Stream element type." + :initarg :element-type + :initform '(unsigned-byte 8)) + (count + :documentation "Number of listening streams to monitor." + :initform *passive-socket-listener-count*) + (streams + :documentation "Array of listen streams." + :initform nil) + (index + :documentation "Index of the last listen stream checked." + :initform *passive-socket-listener-count*) + (connect-index + :documentation "Index of a connected stream, next for processing." + :initform nil) + ) + (:documentation "Class used to manage listening streams and connections.") ) + + + +(defmethod initialize-instance :after ((listener passive-socket) &rest initargs) + (declare (ignore initargs)) + (with-slots (streams count port element-type) listener + (setf streams (make-array count :initial-element nil :adjustable t)) + (dotimes (i count) + (setf (elt streams i) (new-listen-stream listener)) ) ) ) + + +(defmethod ccl:stream-close ((listener passive-socket)) + (with-slots (streams count) listener + (dotimes (i count) + (close (elt streams i))) + (setf count 0))) + + +(defmethod new-listen-stream ((listener passive-socket)) + (with-slots (port element-type) listener + (open-tcp-stream nil port ;use nil host to get a passive connection + :element-type element-type) ) ) + + +(defmethod local-host ((listener passive-socket)) + (with-slots (streams count) listener + (when (> count 0) + (local-host (elt streams 0))))) + + + +; See if one of the streams is established. +(defmethod find-connection-index ((listener passive-socket)) + (with-slots (count streams index connect-index) listener + (let ((next (if (< (1+ index) count) (1+ index) 0))) + (when (connection-established (elt streams next)) + (setf index next + connect-index next) + connect-index)))) + + +(defmethod process-connected-stream ((listener passive-socket)) + (with-slots (streams connect-index) listener + (if (null connect-index) nil + (let ((s (elt streams connect-index))) ;return the connected stream and set a new one + (setf (elt streams connect-index) (new-listen-stream listener)) + (setf connect-index nil) + s) ) ) ) + + +;! future - determine how many connects we are getting an dynamically increase the number +; of listeners if necessary. +(defmethod accept-connection ((listener passive-socket) &key (wait t)) + (if wait + (ccl:process-wait "accept connection..." #'find-connection-index listener) ;apply repeatedly with process wait + (find-connection-index listener) ) + (process-connected-stream listener) ) + + +(defun make-socket (&key (remote-host "localhost") + local-port + remote-port + (connect :active) + (format :text) + &allow-other-keys) + (let ((element-type (ecase format + (:text 'base-char) + (:binary 'signed-byte) + (:bivalent 'unsigned-byte)))) + (ecase connect + (:passive + (make-instance 'passive-socket :port local-port :element-type element-type :direction :io)) + (:active + (let ((host (if (integerp remote-host) ;aparently the acl version also accepts an integer + (ipaddr-to-dotted remote-host) + remote-host))) + (check-type host string) + (open-tcp-stream host remote-port + :element-type element-type)))))) + + + +(declaim (ftype (function ((unsigned-byte 32)) (values simple-string)) + ipaddr-to-dotted)) + +(defun ipaddr-to-dotted (ipaddr &key values) + (declare (type (unsigned-byte 32) ipaddr)) + (let ((a (logand #xff (ash ipaddr -24))) + (b (logand #xff (ash ipaddr -16))) + (c (logand #xff (ash ipaddr -8))) + (d (logand #xff ipaddr))) + (if values + (values a b c d) + (format nil "~d.~d.~d.~d" a b c d)))) + +(defun string-tokens (string) + (labels ((get-token (str pos1 acc) + (let ((pos2 (position #\Space str :start pos1))) + (if (not pos2) + (nreverse acc) + (get-token str (1+ pos2) (cons (read-from-string (subseq str pos1 pos2)) + acc)))))) + (get-token (concatenate 'string string " ") 0 nil))) + +(declaim (ftype (function (string &key (:errorp t)) + (values (unsigned-byte 32))) + dotted-to-ipaddr)) + +(defun dotted-to-ipaddr (dotted &key (errorp t)) + (declare (string dotted)) + (if errorp + (let ((ll (string-tokens (substitute #\Space #\. dotted)))) + (+ (ash (first ll) 24) (ash (second ll) 16) + (ash (third ll) 8) (fourth ll))) + (ignore-errors + (let ((ll (string-tokens (substitute #\Space #\. dotted)))) + (+ (ash (first ll) 24) (ash (second ll) 16) + (ash (third ll) 8) (fourth ll)))))) + +(defun ipaddr-to-hostname (ipaddr &key ignore-cache) + (declare (ignore ignore-cache)) + (inet-host-name ipaddr) ) + +(defun lookup-hostname (host &key ignore-cache) + (when ignore-cache + (warn ":IGNORE-CACHE keyword in LOOKUP-HOSTNAME not supported.")) + (if (stringp host) + (tcp-host-address host) + (dotted-to-ipaddr (ipaddr-to-dotted host)))) + + +(defun socket-control (stream &key output-chunking output-chunking-eof input-chunking) + (declare (ignore stream)) + (warn "SOCKET-CONTROL function not implemented.") + (when (or output-chunking output-chunking-eof input-chunking) + (error "Chunking is not yet supported in MCL. Restart the server with argument :chunking nil (turns chunking off).") ) ) + + +(provide 'acl-socket) + + + Added: branches/trunk-reorg/thirdparty/acl-compat/mcl/acl-socket-openmcl.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/acl-compat/mcl/acl-socket-openmcl.lisp Thu Feb 7 03:21:48 2008 @@ -0,0 +1,145 @@ +;;; OpenMCL layer for ACL sockets. +;;; Most everything is already there, just needs to be in the socket package. +;;; +;;; John DeSoi, Ph.D. desoi at users.sourceforget.net + +(in-package :acl-compat.socket) + +(eval-when (:compile-toplevel :load-toplevel :execute) + (shadowing-import + '(;ccl:make-socket ; use our own version + ccl:accept-connection + ccl:dotted-to-ipaddr + ccl:ipaddr-to-hostname + ccl:lookup-hostname + ccl:remote-host + ccl:remote-port + ccl:local-host + ccl:local-port)) +) + +(eval-when (:compile-toplevel :load-toplevel :execute) + (export + '(accept-connection + ipaddr-to-dotted + dotted-to-ipaddr + ipaddr-to-hostname + lookup-hostname + remote-host + remote-port + local-host + local-port + socket-control)) + ) + + +(defclass server-socket () + ((socket :initarg :socket :reader socket + :initform (error "No value supplied for socket")) + (port :initarg :port + :reader port + :initform (error "No value supplied for port")))) + + +(defmethod print-object ((socket server-socket) stream) + (print-unreadable-object (socket stream :type t :identity nil) + (format stream "listening on port ~d" (port socket)))) + + +(defmethod accept-connection ((server-socket server-socket) + &key (wait t)) + "Return a bidirectional stream connected to socket." + (let ((stream (accept-connection (socket server-socket) :wait wait))) + (when stream (make-chunked-stream stream)))) + + +(defun make-socket (&rest args + &key (connect :active) port + &allow-other-keys) + "Return a stream connected to remote-host if connect is :active, or +something listening on local-port that can be fed to accept-connection +if connect is :passive. +" + (let ((socket-or-stream (apply #'ccl:make-socket args))) + (if (eq connect :active) + (make-chunked-stream socket-or-stream) + (make-instance 'server-socket :socket socket-or-stream :port port)))) + + +(defmethod close ((server-socket server-socket) &key abort) + "Kill a passive (listening) socket. (Active sockets are actually +streams and handled by their close methods." + (declare (ignore abort)) + (close (socket server-socket))) + +(defmethod local-host ((server-socket server-socket)) + (local-host (socket server-socket))) + +(defmethod local-port ((server-socket server-socket)) + (local-port (socket server-socket))) + +(defmethod ccl:stream-write-vector + ((stream gray-stream::buffered-bivalent-stream) vector start end) + (declare (fixnum start end)) + (let ((fn (gray-stream::%writer-function-for-sequence vector))) + (do* ((i start (1+ i))) + ((= i end)) + (declare (fixnum i)) + (funcall fn stream (ccl:uvref vector i))))) + +(defmethod ccl:stream-read-vector + ((stream gray-stream::buffered-bivalent-stream) vector start end) + (declare (fixnum start end)) + (let ((fn (gray-stream::%reader-function-for-sequence vector))) + (do* ((i start (1+ i))) + ((= i end) end) + (declare (fixnum i)) + (let* ((b (funcall fn stream))) + (if (eq b :eof) + (return i) + (setf (ccl:uvref vector i) b)))))) + +(defclass chunked-stream (de.dataheaven.chunked-stream-mixin::chunked-stream-mixin + gray-stream::buffered-bivalent-stream) + ((plist :initarg :plist :accessor stream-plist))) + +(defun make-chunked-stream (lisp-stream &key plist) + (make-instance 'chunked-stream :lisp-stream lisp-stream :plist plist)) + +(defmethod local-host ((chunked-stream chunked-stream)) + (local-host (gray-stream::native-lisp-stream chunked-stream))) + +(defmethod local-port ((chunked-stream chunked-stream)) + (local-port (gray-stream::native-lisp-stream chunked-stream))) + +(defmethod remote-host ((chunked-stream chunked-stream)) + (remote-host (gray-stream::native-lisp-stream chunked-stream))) + +(defmethod remote-port ((chunked-stream chunked-stream)) + (remote-port (gray-stream::native-lisp-stream chunked-stream))) + + +(defun socket-control (stream &key (output-chunking nil oc-p) output-chunking-eof (input-chunking nil ic-p)) + (when oc-p + (when output-chunking + (de.dataheaven.chunked-stream-mixin::initialize-output-chunking stream)) + (setf (de.dataheaven.chunked-stream-mixin::output-chunking-p stream) + output-chunking)) + (when output-chunking-eof + (de.dataheaven.chunked-stream-mixin::disable-output-chunking stream)) + (when ic-p + (when input-chunking + (de.dataheaven.chunked-stream-mixin::initialize-input-chunking stream)) + (setf (de.dataheaven.chunked-stream-mixin::input-chunking-p stream) + input-chunking))) + +; OpenMCL has a built-in ipaddr-to-dotted. But it appears that sometimes +; the log function is being called after the connection is closed and +; it causes nil to be passed to ipaddr-to-dotted. So we wrap ipaddr-to-dotten +; to ensure only non-nil values are passed. + +(defun ipaddr-to-dotted (ipaddr &key values) + (unless (null ipaddr) + (ccl:ipaddr-to-dotted ipaddr :values values))) + +(provide 'acl-socket) Added: branches/trunk-reorg/thirdparty/acl-compat/mcl/acl-sys.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/acl-compat/mcl/acl-sys.lisp Thu Feb 7 03:21:48 2008 @@ -0,0 +1,20 @@ + +(in-package :acl-compat.system) + + +(defun command-line-arguments () + #+openmcl (ccl::command-line-arguments) + #-openmcl nil) + +(defun command-line-argument (n) + #+openmcl (nth n (command-line-arguments)) + #-openmcl nil) + +;;; On acl, reap-os-subprocess is needed for (run-shell-command ... +;;; :wait nil), but not on OpenMCL. +(defun reap-os-subprocess (&key (wait nil)) + (declare (ignore wait)) + nil) + +#+nil +(export '(command-line-arguments command-line-argument reap-os-subprocess)) Added: branches/trunk-reorg/thirdparty/acl-compat/mcl/mcl-stream-fix.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/acl-compat/mcl/mcl-stream-fix.lisp Thu Feb 7 03:21:48 2008 @@ -0,0 +1,44 @@ + + +(in-package :ccl) + +;;; There are several bugs in MCL functions to read sequences prior to 4.3.5; this fixes them + + + +(eval-when (:compile-toplevel :load-toplevel :execute) + +(let ((ccl:*warn-if-redefine* nil)) + +(defun %io-buffer-read-bytes-to-vector (io-buffer vector bytes start) + (loop with fill-pointer = start + with bytes-remaining = bytes + until (eql 0 bytes-remaining) + while (if (eql 0 (io-buffer-incount io-buffer)) + (%io-buffer-advance io-buffer t t) ; eof may be signalled through this -- JCMa 5/13/1999. + t) + for buffer = (io-buffer-inptr io-buffer) + for read-bytes = (min (io-buffer-incount io-buffer) bytes-remaining) + do (%copy-ptr-to-ivector buffer 0 vector fill-pointer read-bytes) + (incf fill-pointer read-bytes) + (%incf-ptr (io-buffer-inptr io-buffer) read-bytes) ;; bug fix from akh on 7/28/2002 + (decf bytes-remaining read-bytes) + (decf (io-buffer-incount io-buffer) read-bytes) + (incf (io-buffer-bytes-read io-buffer) read-bytes))) + + +;This function is unchanged, but kept for completeness +(defun io-buffer-read-bytes-to-vector (io-buffer vector bytes &optional (start 0)) + (require-type io-buffer 'io-buffer) + (with-io-buffer-locked (io-buffer) + (multiple-value-bind (v v-offset) + (array-data-and-offset vector) + (%io-buffer-read-bytes-to-vector io-buffer v bytes (+ start v-offset))))) + + +(defmethod stream-read-bytes-to-vector ((stream buffered-output-stream-mixin) vector bytes &optional (start 0)) + (io-buffer-read-bytes-to-vector (stream-io-buffer stream) vector bytes start)) ;original fuction did not get the buffer from the stream + + +) +) \ No newline at end of file Added: branches/trunk-reorg/thirdparty/acl-compat/mcl/mcl-timers.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/acl-compat/mcl/mcl-timers.lisp Thu Feb 7 03:21:48 2008 @@ -0,0 +1,112 @@ +;;; mcl-timers contributed by Gary Byers + +(in-package "CCL") + + +;;; A simple timer mechanism for MCL/OpenMCL, which uses a +;;; PERIODIC-TASK to check for expired "timer requests". +;;; In MCL and OpenMCL, PERIODIC-TASKS run at specified +;;; intervals via the same preemption mechanism that the +;;; scheduler uses; they run in the execution context of +;;; whatever thread was preempted, and they're assumed to +;;; run pretty quickly. +;;; This code uses doubly-linked-list elements (DLL-NODEs) +;;; to represent a sorted list of "timer requests"; client +;;; processes use timer requests to schedule an interrupt +;;; action at a specified time. A periodic task walks this +;;; list once a second (by default), removing those requests +;;; whose time isn't in the future and interrupting the +;;; corresponding processes. + + +;;; The number of timer interrupts (ticks) per second. +(defmacro ticks-per-second () + #+OpenMCL '*ticks-per-second* + #-OpenMCL 60) + + +(defun expiration-tick-count (seconds) + (+ (round (* seconds (ticks-per-second))) + (get-tick-count))) + +(defstruct (timer-request (:include dll-node) + (:constructor %make-timer-request)) + expiration-tick ; when the timer expires + process ; what process to interrupt + function) ; how to interrupt it + + +(defun make-timer-request (seconds-from-now function) + (check-type seconds-from-now (and unsigned-byte fixnum)) + (check-type function function) + (%make-timer-request + :expiration-tick (expiration-tick-count seconds-from-now) + :process *current-process* + :function function)) + + +;;; the CCL::DEFLOADVAR construct ensures that the variable +;;; will be reinitialized when a saved image is restarted +(defloadvar *timer-request-queue* + #-openmcl-native-threads (make-dll-header) + #+openmcl-native-threads (make-locked-dll-header)) + +;;; Insert the timer request before the first element with a later +;;; expiration time (or at the end of the queue if there's no such +;;; element.) +(defun enqueue-timer-request (r) + (#-openmcl-native-threads without-interrupts + #+openmcl-native-threads with-locked-dll-header + #+openmcl-native-threads (*timer-request-queue*) + (if (dll-node-succ r) ; Already enqueued. + r ; Or signal an error. + (let* ((r-date (timer-request-expiration-tick r))) + (do* ((node *timer-request-queue* next) + (next (dll-node-succ node) (dll-node-succ next))) + ((or (eq next *timer-request-queue*) + (> (timer-request-expiration-tick next) r-date)) + (insert-dll-node-after r node))))))) + +;;; Remove a timer request. (It's a no-op if the request has already +;;; been removed.) +(defun dequeue-timer-request (r) + (#-openmcl-native-threads without-interrupts + #+openmcl-native-threads with-locked-dll-header + #+openmcl-native-threads (*timer-request-queue*) + (when (dll-node-succ r) ;enqueued + (remove-dll-node r)) + r)) + +;;; Since this runs in an arbitrary process, it tries to be a little +;;; careful with requests made by the current process (since running +;;; the interrupt function will probably transfer control out of the +;;; periodic task function.) The oldest (hopefully only) request for +;;; the current process is handled after all other pending requests. +(defun process-timer-requests () + (let* ((now (get-tick-count)) + (current-process *current-process*) + (current-process-action ())) + (#-openmcl-native-threads progn + #+openmcl-native-threads with-locked-dll-header + #+openmcl-native-threads (*timer-request-queue*) + + (do-dll-nodes (r *timer-request-queue*) + (when (> (timer-request-expiration-tick r) now) + (return)) ; Anything remaining is + ; in the future. + (dequeue-timer-request r) + (let* ((proc (timer-request-process r)) + (func (timer-request-function r))) + (if (eq proc current-process) + (if (null current-process-action) + (setq current-process-action func)) + (process-interrupt (timer-request-process r) + (timer-request-function r))))) + (when current-process-action + (funcall current-process-action))))) + +(%install-periodic-task + 'process-timer-requests ; Name of periodic task + 'process-timer-requests ; function to call + (ticks-per-second) ; Run once per second + ) Added: branches/trunk-reorg/thirdparty/acl-compat/packages.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/acl-compat/packages.lisp Thu Feb 7 03:21:48 2008 @@ -0,0 +1,272 @@ +;;;; -*- mode: lisp -*- +;;;; +;;;; Package definitions for acl-compat. +;;;; +;;;; Package names follow their Allegro CL counterparts -- for an ACL +;;;; package foo, acl-compat defines a package acl-compat.foo +;;;; +;;;; Some packages have nicknames, which were used as package names by +;;;; previous versions of paserve and acl-compat. The nicknames are +;;;; deprecated, but are kept for the benefit of people using +;;;; acl-compat in other projects. New projects should use the +;;;; package names starting with "acl-compat.". +;;;; + +(in-package :common-lisp-user) + +;;; general +(defpackage :acl-compat.excl + (:use #:common-lisp + #+cmu #:ext + #+clisp #:ext + #+sbcl #:sb-ext #+sbcl #:sb-gray + #+(or allegro cormanlisp) :excl + #+(or mcl openmcl) :ccl + ) + #+lispworks (:import-from :common-lisp #:fixnump) + #+sbcl (:import-from :sb-int #:fixnump) + #+sbcl (:import-from :sb-ext #:without-package-locks) + #+cmu (:import-from :ext #:without-package-locks) + #+allegro (:shadowing-import-from :excl #:filesys-size + #:filesys-write-date #:intern* #:filesys-type #:atomically #:fast) + (:export + #:if* + #:*initial-terminal-io* + #:*cl-default-special-bindings* + #:filesys-size + #:filesys-write-date + #:stream-input-fn + #:match-regexp + #:compile-regexp + #:*current-case-mode* + #:intern* + #:filesys-type + #:errorset + #:atomically + #:fast + #:without-package-locks + #:fixnump + #+(or lispworks mcl openmcl) #:socket-error + #+(or allegro lispworks mcl openmcl) #:run-shell-command + #+(or allegro mcl openmcl) #:fasl-read + #+(or allegro mcl openmcl) #:fasl-write + #+(or allegro cmu scl mcl lispworks openmcl) #:string-to-octets + #+(or allegro cmu scl mcl lispworks openmcl) #:write-vector + )) + + +;; general +(defpackage :acl-compat.mp + (:use :common-lisp #+cormanlisp :acl-compat-mp #+allegro :mp) + (:nicknames :acl-mp #-cormanlisp :acl-compat-mp) + #+allegro (:shadowing-import-from :mp #:process-interrupt #:lock) + #+allegro (:shadowing-import-from :excl #:without-interrupts) + (:export + #:*current-process* ;* + #:process-kill ;* + #:process-preset ;* + #:process-name ;* + + #:process-wait-function + #:process-run-reasons + #:process-arrest-reasons + #:process-whostate + #:without-interrupts + #:process-wait + #:process-enable + #:process-disable + #:process-reset + #:process-interrupt + + #:process-run-function ;* + #:process-property-list ;* + #:without-scheduling ;* + #:process-allow-schedule ;* + #:make-process ;* + #:process-add-run-reason ;* + #:process-revoke-run-reason ;* + #:process-add-arrest-reason ;* + #:process-revoke-arrest-reason ;* + #:process-allow-schedule ;* + #:with-timeout ;* + #:make-process-lock ;* + #:with-process-lock ;* + #:process-lock + #:process-unlock + + #:current-process + #:process-name-to-process + #:process-wait-with-timeout + #:wait-for-input-available + #:process-active-p + )) + +(defpackage :de.dataheaven.chunked-stream-mixin + (:use :common-lisp) + (:export #:chunked-stream-mixin + #:output-chunking-p #:input-chunking-p)) + +;; general +(defpackage acl-compat.socket + (:use #:common-lisp + #+(or cmu lispworks scl) #:acl-mp + #+(or lispworks cmu)#:acl-compat.excl + #+clisp #:socket + #+sbcl #:sb-bsd-sockets + #+(or lispworks cmu) #:de.dataheaven.chunked-stream-mixin + #+cormanlisp #:socket + ) + #+cl-ssl (:import-from :ssl #:MAKE-SSL-CLIENT-STREAM #:MAKE-SSL-SERVER-STREAM) + #+lispworks (:shadow socket-stream stream-error) + (:export + #+(or lispworks cmu) #:socket + #:make-socket + #:accept-connection + #:ipaddr-to-dotted + #:dotted-to-ipaddr + #:ipaddr-to-hostname + #:lookup-hostname + #:remote-host + #:remote-port + #:local-host + #:local-port + #:socket-control + #+cl-ssl #:make-ssl-client-stream + #+cl-ssl #:make-ssl-server-stream + #+(and :lispworks4.4 (not :cl-ssl)) #:make-ssl-client-stream + #+(and :lispworks4.4 (not :cl-ssl)) #:make-ssl-server-stream + #+lispworks #:socket-os-fd + ) + #-cormanlisp (:nicknames #-(or clisp allegro) socket #-allegro acl-socket)) + + +(defpackage acl-compat.system + (:nicknames :acl-compat.sys) + (:use :common-lisp) + (:export + #:command-line-arguments + #:command-line-argument + #:reap-os-subprocess + )) + + +; these are not all in the ccl package which causes an error +#+(and mcl (not openmcl)) +(shadowing-import '( + fundamental-binary-input-stream + fundamental-binary-output-stream + fundamental-character-input-stream + fundamental-character-output-stream + stream-element-type + stream-listen + stream-read-byte + stream-read-char + stream-peek-char + stream-write-byte + stream-write-char + stream-read-char-no-hang + stream-force-output + stream-finish-output + stream-clear-input + stream-clear-output + stream-line-column + stream-read-sequence + stream-unread-char + stream-read-line + stream-write-sequence + stream-write-string) + :ccl) + +#-cormanlisp +(defpackage :gray-stream + (:use #:common-lisp) + (:import-from #+lispworks :stream #+cmu :lisp #+clisp :gray #+cormanlisp :gray-streams + #+(or mcl openmcl) :ccl #+allegro :excl #+sbcl :sb-gray + #:fundamental-binary-input-stream + #:fundamental-binary-output-stream + #:fundamental-character-input-stream + #:fundamental-character-output-stream + #:stream-element-type + #:stream-listen + #:stream-read-byte + #:stream-read-char + #:stream-peek-char + #:stream-write-byte + #:stream-write-char + #:stream-read-char-no-hang + #:stream-force-output + #:stream-finish-output + #:stream-clear-input + #:stream-clear-output + #:stream-line-column + #-(or clisp openmcl) #:stream-read-sequence + #:stream-unread-char + #:stream-read-line + #-(or clisp openmcl) #:stream-write-sequence + #:stream-write-string + #+lispworks #:stream-write-buffer + #+lispworks #:stream-read-buffer + #+lispworks #:stream-fill-buffer + #+lispworks #:stream-flush-buffer + #+lispworks #:with-stream-input-buffer + #+lispworks #:with-stream-output-buffer) + (:export + #:fundamental-binary-input-stream + #:fundamental-binary-output-stream + #:fundamental-character-input-stream + #:fundamental-character-output-stream + #:stream-element-type + #:stream-listen + #:stream-read-byte + #:stream-read-char + #:stream-write-byte + #:stream-write-char + #:stream-read-char-no-hang + #:stream-force-output + #:stream-finish-output + #:stream-clear-input + #:stream-clear-output + #:stream-line-column + #-clisp #:stream-read-sequence + #:stream-unread-char + #:stream-read-line + #-clisp #:stream-write-sequence + #:stream-write-string + #:stream-write-buffer + #:stream-read-buffer + #:stream-fill-buffer + #:stream-flush-buffer + #:with-stream-input-buffer + #:with-stream-output-buffer)) + +#+cormanlisp +(defpackage :gray-stream + (:use #:common-lisp :gray-streams) + (:export + #:fundamental-binary-input-stream + #:fundamental-binary-output-stream + #:fundamental-character-input-stream + #:fundamental-character-output-stream + #:stream-element-type + #:stream-listen + #:stream-read-byte + #:stream-read-char + #:stream-write-byte + #:stream-write-char + #:stream-read-char-no-hang + #:stream-force-output + #:stream-finish-output + #:stream-clear-input + #:stream-clear-output + #:stream-line-column + #:stream-read-sequence + #:stream-unread-char + #:stream-read-line + #:stream-write-sequence + #:stream-write-string + #:stream-write-buffer + #:stream-read-buffer + #:stream-fill-buffer + #:stream-flush-buffer + #:with-stream-input-buffer + #:with-stream-output-buffer)) Added: branches/trunk-reorg/thirdparty/acl-compat/sbcl/acl-excl.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/acl-compat/sbcl/acl-excl.lisp Thu Feb 7 03:21:48 2008 @@ -0,0 +1,32 @@ +;;;; +;;;; ACL-COMPAT - EXCL +;;;; + +;;;; Implementation-specific parts of acl-compat.excl (see +;;;; acl-excl-common.lisp) + +(in-package :acl-compat.excl) + +(defun stream-input-fn (stream) + stream) + +(defun filesys-type (file-or-directory-name) + (let ((mode (sb-posix:stat-mode (sb-posix:stat file-or-directory-name)))) + (cond + ((sb-posix:s-isreg mode) :file) + ((sb-posix:s-isdir mode) :directory) + (t nil)))) + +(defmacro atomically (&body forms) + `(acl-mp:without-scheduling , at forms)) + +(defun unix-signal (signal pid) + (declare (ignore signal pid)) + (error "unix-signal not implemented in acl-excl-sbcl.lisp")) + +(defun filesys-inode (path) + (sb-posix:stat-ino (sb-posix:lstat path))) + +(defun cl-internal-real-time () + (round (/ (get-internal-real-time) internal-time-units-per-second))) + Added: branches/trunk-reorg/thirdparty/acl-compat/sbcl/acl-mp.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/acl-compat/sbcl/acl-mp.lisp Thu Feb 7 03:21:48 2008 @@ -0,0 +1,294 @@ +;; Threading for sbcl, or stub functions for single-threaded sbcl. +;; +;; Written by Rudi Schlatte, intended to be distributed along with the +;; acl-compat library, under the same license as the rest of it. + +;; Inspirations taken from Dan Barlow's work for +;; McCLIM; cut, pasted and mutilated with permission. + +(in-package :acl-compat.mp) + +(defstruct (process + (:constructor %make-process) + (:predicate processp)) + name + state + whostate + function ; function wot will be run + arguments ; arguments to the function + id ; pid of unix thread or nil + %lock ; lock for process structure mutators + run-reasons ; primitive mailbox for IPC + %queue ; queue for condition-wait + initial-bindings ; special variable bindings + property-list) + +(defparameter *current-process* + #-sb-thread + (%make-process) + #+sb-thread + ;; We don't fill in the process id, so the process compiling this + ;; (the REPL, in most cases) can't be killed by accident. (loop for + ;; p in (all-processes) do (kill-process p)), anyone? + (%make-process :name "initial process" :function nil)) + +(defparameter *all-processes-lock* + (sb-thread:make-mutex :name "all processes lock")) + +(defparameter *all-processes* + (list *current-process*)) + +#-sb-thread +(defun make-process (&key (name "Anonymous") reset-action run-reasons + arrest-reasons (priority 0) quantum resume-hook + suspend-hook initial-bindings run-immediately) + (declare (ignore reset-action arrest-reasons priority quantum resume-hook + suspend-hook run-immediately)) + (%make-process :name "the only process" + :run-reasons run-reasons + :initial-bindings initial-bindings)) + +#+sb-thread +(defun make-process (&key (name "Anonymous") reset-action run-reasons + arrest-reasons (priority 0) quantum resume-hook + suspend-hook initial-bindings run-immediately) + (declare (ignore reset-action arrest-reasons priority quantum resume-hook + suspend-hook run-immediately)) + (let ((p (%make-process + :name name + :run-reasons run-reasons + :initial-bindings initial-bindings + :%lock (sb-thread:make-mutex + :name (format nil "Internal lock for ~A" name)) + :%queue (sb-thread:make-waitqueue + :name (format nil "Blocking queue for ~A" name))))) + (sb-thread:with-mutex (*all-processes-lock*) + (push p *all-processes*)) + p)) + +(defmacro defun/sb-thread (name args &body body) + #-sb-thread (declare (ignore body)) + `(defun ,name ,args + #-sb-thread + (declare (ignore ,@(remove-if + (lambda (x) + (member x '(&optional &rest &key &allow-other-keys + &aux))) + (mapcar (lambda (x) (if (consp x) (car x) x)) + args)))) + #-sb-thread + (error + "~A: Calling a multiprocessing function on a single-threaded sbcl build" + ',name) + #+sb-thread + , at body)) + +(defun/sb-thread process-interrupt (process function) + (sb-thread:interrupt-thread (process-id process) function)) + +;; TODO: why no such function was in +sb-thread part? +(defun/sb-thread process-wait-function (process) + (declare (ignore process))) + +(defun/sb-thread process-wait (reason predicate &rest arguments) + (declare (type function predicate)) + (let ((old-state (process-whostate *current-process*))) + (unwind-protect + (progn + (setf old-state (process-whostate *current-process*) + (process-whostate *current-process*) reason) + (loop + (let ((it (apply predicate arguments))) + (when it (return it))) + (process-allow-schedule))) + (setf (process-whostate *current-process*) old-state)))) + +(defun/sb-thread process-allow-schedule (&optional process) + (declare (ignore process)) + (sleep .01)) + +(defun/sb-thread process-revoke-run-reason (process object) + (sb-thread:with-recursive-lock ((process-%lock process)) + (prog1 + (setf (process-run-reasons process) + (delete object (process-run-reasons process))) + (when (and (process-id process) (not (process-run-reasons process))) + (disable-process process))))) + +(defun/sb-thread process-add-run-reason (process object) + (sb-thread:with-recursive-lock ((process-%lock process)) + (prog1 + (push object (process-run-reasons process)) + (if (process-id process) + (enable-process process) + (restart-process process))))) + +(defun/sb-thread process-run-function (name-or-options preset-function + &rest preset-arguments) + (let* ((make-process-args (etypecase name-or-options + (list name-or-options) + (string (list :name name-or-options)))) + (process (apply #'make-process make-process-args))) + (apply #'process-preset process preset-function preset-arguments) + (setf (process-run-reasons process) :enable) + (restart-process process) + process)) + +(defun/sb-thread process-preset (process function &rest arguments) + (setf (process-function process) function + (process-arguments process) arguments) + (when (process-id process) (restart-process process))) + +(defun/sb-thread process-kill (process) + (when (process-id process) + (sb-thread:destroy-thread (process-id process)) + (setf (process-id process) nil)) + (sb-thread:with-mutex (*all-processes-lock*) + (setf *all-processes* (delete process *all-processes*)))) + +#+sb-thread +(defun make-process-lock (&key name) + (sb-thread:make-mutex :name name)) +#-sb-thread +(defun make-process-lock (&key name) + (declare (ignore name)) + nil) + +(defun/sb-thread process-lock (lock &optional lock-value whostate timeout) + (declare (ignore whostate timeout)) + (sb-thread:get-mutex lock lock-value)) + +(defun/sb-thread process-unlock (lock &optional lock-value) + (declare (ignore lock-value)) + (sb-thread:release-mutex lock)) + +#-sb-thread +(defmacro with-process-lock ((lock &key norecursive timeout whostate) + &body forms) + (declare (ignore lock norecursive timeout whostate)) + `(progn , at forms)) + +#+sb-thread +(defmacro with-process-lock ((place &key timeout whostate norecursive) + &body body) + (declare (ignore norecursive timeout)) + (let ((old-whostate (gensym "OLD-WHOSTATE"))) + `(sb-thread:with-recursive-lock (,place) + (let (,old-whostate) + (unwind-protect + (progn + (when ,whostate + (setf ,old-whostate (process-whostate *current-process*)) + (setf (process-whostate *current-process*) ,whostate)) + , at body) + (setf (process-whostate *current-process*) ,old-whostate)))))) + + +#-sb-thread +(defmacro without-scheduling (&body forms) + `(progn , at forms)) ; * + +;;; FIXME but, of course, we can't. Fix whoever wants to use it, +;;; instead +#+sb-thread +(defmacro without-scheduling (&body body) + `(progn , at body)) + +;;; Same implementation for multi- and uni-thread +(defmacro with-timeout ((seconds &body timeout-forms) &body body) + (let ((c (gensym "TIMEOUT-"))) + `(handler-case + (sb-ext::with-timeout ,seconds (progn , at body)) + (sb-ext::timeout (,c) (declare (ignore ,c)) , at timeout-forms)))) + +(defun/sb-thread restart-process (process) + (labels ((boing () + (let ((*current-process* process) + (bindings (process-initial-bindings process)) + (function (process-function process)) + (arguments (process-arguments process))) + (declare (type function function)) + (if bindings + (progv + (mapcar #'car bindings) + (mapcar #'(lambda (binding) + (eval (cdr binding))) + bindings) + (apply function arguments)) + (apply function arguments))))) + (when (process-id process) + (sb-thread:terminate-thread (process-id process))) + ;; XXX handle run-reasons in some way? Should a process continue + ;; running if all run reasons are taken away before + ;; restart-process is called? (process-revoke-run-reason handles + ;; this, so let's say (setf (process-run-reasons process) nil) is + ;; not guaranteed to do the Right Thing.) + (when (setf (process-id process) + (sb-thread:make-thread #'boing :name (process-name process))) + process))) + +(defun current-process () + *current-process*) + +(defun all-processes () + (copy-list *all-processes*)) + +(defun/sb-thread process-wait-with-timeout (reason timeout predicate) + (declare (type function predicate)) + (let ((old-state (process-whostate *current-process*)) + (end-time (+ (get-universal-time) timeout))) + (unwind-protect + (progn + (setf old-state (process-whostate *current-process*) + (process-whostate *current-process*) reason) + (loop + (let ((it (funcall predicate))) + (when (or (> (get-universal-time) end-time) it) + (return it))) + (sleep .01))) + (setf (process-whostate *current-process*) old-state)))) + +(defun/sb-thread disable-process (process) + ;; TODO: set process-whostate + ;; Can't figure out how to safely block a thread from a different one + ;; and handle all the locking nastiness. So punt for now. + (if (eq sb-thread:*current-thread* (process-id process)) + ;; Keep waiting until we have a reason to run. GC and other + ;; things can break a wait prematurely. Don't know if this is + ;; expected or not. + (do () + ((process-run-reasons process) nil) + (sb-thread:with-recursive-lock ((process-%lock process)) + (sb-thread:condition-wait (process-%queue process) + (process-%lock process)))) + (error "Can't safely disable-process from another thread"))) + +(defun/sb-thread enable-process (process) + ;; TODO: set process-whostate + (sb-thread:with-recursive-lock ((process-%lock process)) + (sb-thread:condition-notify (process-%queue process)))) + +;;; TODO: integrate with McCLIM / system-wide queue for such things +#+sb-thread +(defvar *atomic-spinlock* (sb-thread::make-spinlock)) + +#-sb-thread +(defmacro atomic-incf (place) + `(incf ,place)) + +#+sb-thread +(defmacro atomic-incf (place) + `(sb-thread::with-spinlock (*atomic-spinlock*) + (incf ,place))) + +#-sb-thread +(defmacro atomic-decf (place) + `(decf ,place)) + +#+sb-thread +(defmacro atomic-decf (place) + `(sb-thread::with-spinlock (*atomic-spinlock*) + (decf ,place))) + +(defun process-active-p (process) + (sb-thread:thread-alive-p (process-id process))) Added: branches/trunk-reorg/thirdparty/acl-compat/sbcl/acl-socket.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/acl-compat/sbcl/acl-socket.lisp Thu Feb 7 03:21:48 2008 @@ -0,0 +1,283 @@ +;; This package is designed for sbcl. It implements the +;; ACL-style socket interface on top of sbcl. +;; +;; Written by Rudi Schlatte, based on the work done by Jochen Schmidt +;; for Lispworks and net.lisp in the port library of CLOCC. + +(in-package #:acl-compat.socket) + +(defclass server-socket () + ((socket :initarg :socket :reader socket + :initform (error "No value supplied for socket")) + (element-type :type (member signed-byte unsigned-byte base-char) + :initarg :element-type + :reader element-type + :initform (error "No value supplied for element-type")) + (port :type fixnum + :initarg :port + :reader port + :initform (error "No value supplied for port")) + (stream-type :type (member :text :binary :bivalent) + :initarg :stream-type + :reader stream-type + :initform (error "No value supplied for stream-type")))) + +(defclass datagram-socket (server-socket) + ()) + + +(defmethod print-object ((socket server-socket) stream) + (print-unreadable-object (socket stream :type t :identity nil) + (format stream "listening on port ~d" (port socket)))) + +(defmethod print-object ((socket datagram-socket) stream) + (print-unreadable-object (socket stream :type t :identity nil) + (format stream "datagram socket listening on port ~d" (port socket)))) + +(defgeneric accept-connection (socket &key wait)) +(defmethod accept-connection ((server-socket server-socket) + &key (wait t)) + "Return a bidirectional stream connected to socket." + (if (sb-sys:wait-until-fd-usable (socket-file-descriptor (socket server-socket)) + :input (if (numberp wait) wait nil)) + (let* ((socket (socket-accept (socket server-socket))) + (stream (socket-make-stream socket + :input t :output t + ; :buffering :none + :element-type + (element-type server-socket) + :auto-close t))) + (if (eq (stream-type server-socket) :bivalent) + ;; HACK: remember socket, so we can do peer lookup + (make-bivalent-stream stream :plist `(:socket ,socket)) + stream)) + nil)) + +(defmethod receive-from ((socket datagram-socket) size &key buffer extract) + (multiple-value-bind (rbuf len address port) + (socket-receive (socket socket) buffer size) + (declare (ignore port)) + (let ((buf + (if (not extract) + rbuf + (subseq rbuf 0 len)))) ;; FIXME: am I right? + (when buffer + (replace buffer buf :end2 len)) + (values + (if buffer buffer buf) + len + address)))) + +(defmethod send-to ((socket datagram-socket) buffer size &key remote-host remote-port) + (let* ((rhost (typecase remote-host + (string (lookup-hostname remote-host)) + (otherwise remote-host))) + (s (socket socket)) + (stream (progn + (socket-connect s rhost remote-port) + (socket-make-stream s :input t :output t :buffering :none)))) + (write-sequence buffer stream) + size)) + + + +(defun make-socket (&key + (type :stream) + (remote-host "localhost") + local-port + remote-port + (connect :active) + (format :text) + (reuse-address t) + &allow-other-keys) + "Return a stream connected to remote-host if connect is :active, or +something listening on local-port that can be fed to accept-connection +if connect is :passive. + +This is an incomplete implementation of ACL's make-socket function! +It was written to provide the functionality necessary to port +AllegroServe. Refer to +http://franz.com/support/documentation/6.1/doc/pages/operators/socket/make-socket.htm +to read about the missing parts." + (check-type remote-host string) + (let ((element-type (ecase format + (:text 'base-char) + (:binary 'signed-byte) + (:bivalent 'unsigned-byte))) + (socket + (if (eq type :datagram) + (progn + (setf connect :passive-udp) + (make-instance 'inet-socket :type :datagram :protocol :udp)) + (make-instance 'inet-socket :type :stream :protocol :tcp)))) + (ecase connect + (:passive-udp + (setf (sockopt-reuse-address socket) reuse-address) + (if local-port + (socket-bind socket #(0 0 0 0) local-port)) + (make-instance 'datagram-socket + :port (nth-value 1 (socket-name socket)) + :socket socket + :element-type element-type + :stream-type format)) + (:passive + (setf (sockopt-reuse-address socket) reuse-address) + (if local-port + (socket-bind socket #(0 0 0 0) local-port)) + (socket-listen socket 10) ;Arbitrarily chosen backlog value + (make-instance 'server-socket + :port (nth-value 1 (socket-name socket)) + :socket socket + :element-type element-type + :stream-type format)) + (:active + (socket-connect socket (lookup-hostname remote-host) remote-port) + (let ((stream (socket-make-stream socket :input t :output t + :element-type element-type + ; :buffering :none + ))) + (if (eq :bivalent format) + ;; HACK: remember socket, so we can do peer lookup + (make-bivalent-stream stream :plist `(:socket ,socket)) + stream)))))) + +(defmethod close ((server server-socket) &key abort) + "Kill a passive (listening) socket. (Active sockets are actually +streams and handled by their close methods." + (declare (ignore abort)) + (socket-close (socket server))) + +#+ignore +(declaim (ftype (function ((unsigned-byte 32) &key (:values t)) + (or (values fixnum fixnum fixnum fixnum) + (values simple-string))) + ipaddr-to-dotted)) +(defun ipaddr-to-dotted (ipaddr &key values) + "Convert from 32-bit integer to dotted string." + (declare (type (unsigned-byte 32) ipaddr)) + (let ((a (logand #xff (ash ipaddr -24))) + (b (logand #xff (ash ipaddr -16))) + (c (logand #xff (ash ipaddr -8))) + (d (logand #xff ipaddr))) + (if values + (values a b c d) + (format nil "~d.~d.~d.~d" a b c d)))) + +(defun ipaddr-to-vector (ipaddr) + "Convert from 32-bit integer to a vector of octets." + (declare (type (unsigned-byte 32) ipaddr)) + (let ((a (logand #xff (ash ipaddr -24))) + (b (logand #xff (ash ipaddr -16))) + (c (logand #xff (ash ipaddr -8))) + (d (logand #xff ipaddr))) + (make-array 4 :initial-contents (list a b c d)))) + +(declaim (ftype (function (vector) + (values (unsigned-byte 32))) + vector-to-ipaddr)) +(defun vector-to-ipaddr (sensible-ipaddr) + "Convert from 4-integer vector to 32-bit integer." + (loop with result = 0 + for component across sensible-ipaddr + do (setf result (+ (ash result 8) component)) + finally (return result))) + +(defun string-tokens (string) + (labels ((get-token (str pos1 acc) + (let ((pos2 (position #\Space str :start pos1))) + (if (not pos2) + (nreverse acc) + (get-token str (1+ pos2) (cons (read-from-string (subseq str pos1 pos2)) + acc)))))) + (get-token (concatenate 'string string " ") 0 nil))) + +(declaim (ftype (function (string &key (:errorp t)) + (or null (unsigned-byte 32))) + dotted-to-ipaddr)) +(defun dotted-to-ipaddr (dotted &key (errorp t)) + "Convert from dotted string to 32-bit integer." + (declare (string dotted)) + (if errorp + (let ((ll (string-tokens (substitute #\Space #\. dotted)))) + (+ (ash (first ll) 24) (ash (second ll) 16) + (ash (third ll) 8) (fourth ll))) + (ignore-errors + (let ((ll (string-tokens (substitute #\Space #\. dotted)))) + (+ (ash (first ll) 24) (ash (second ll) 16) + (ash (third ll) 8) (fourth ll)))))) + +(defun ipaddr-to-hostname (ipaddr &key ignore-cache) + (when ignore-cache + (warn ":IGNORE-CACHE keyword in IPADDR-TO-HOSTNAME not supported.")) + (host-ent-name (get-host-by-address (ipaddr-to-vector ipaddr)))) + +(defun lookup-hostname (host &key ignore-cache) + (when ignore-cache + (warn ":IGNORE-CACHE keyword in LOOKUP-HOSTNAME not supported.")) + (if (stringp host) + (host-ent-address (get-host-by-name host)) + (dotted-to-ipaddr (ipaddr-to-dotted host)))) + +(defun remote-host (socket-stream) + (let (socket) + (if (and (typep socket-stream 'chunked-stream) + (setf socket (getf (stream-plist socket-stream) :socket))) + (vector-to-ipaddr (socket-peername socket)) + (progn (warn "Could not get remote host for ~S" socket-stream) + 0)))) + +(defun remote-port (socket-stream) + (let (socket) + (if (and (typep socket-stream 'chunked-stream) + (setq socket (getf (stream-plist socket-stream) :socket))) + (nth-value 1 (socket-peername socket)) + (progn (warn "Could not get remote port for ~S" socket-stream) + 0)))) + +(defun local-host (thing) + (typecase thing + (chunked-stream (let ((socket (getf (stream-plist thing) :socket))) + (if socket (vector-to-ipaddr (socket-name socket)) + (progn (warn "Socket not in plist of ~S -- could not get local host" thing) + 0)))) + (server-socket (vector-to-ipaddr #(127 0 0 1))) + (t (progn (warn "Could not get local host for ~S" thing) + 0)))) + +(defun local-port (thing) + (typecase thing + (chunked-stream (let ((socket (getf (stream-plist thing) :socket))) + (if socket (nth-value 1 (socket-name socket)) + (progn (warn "Socket not in plist of ~S -- could not get local port" thing) + 0)))) + (server-socket (port thing)) + (t (progn (warn "Could not get local port for ~S" thing) + 0)))) + +;; Now, throw chunking in the mix + +(defclass chunked-stream (de.dataheaven.chunked-stream-mixin::chunked-stream-mixin + gray-stream::buffered-bivalent-stream) + ((plist :initarg :plist :accessor stream-plist))) + + +(defun make-bivalent-stream (lisp-stream &key plist) + (make-instance 'chunked-stream :lisp-stream lisp-stream :plist plist)) + + +(defun socket-control (stream &key (output-chunking nil oc-p) output-chunking-eof (input-chunking nil ic-p)) + (when oc-p + (when output-chunking + (de.dataheaven.chunked-stream-mixin::initialize-output-chunking stream)) + (setf (de.dataheaven.chunked-stream-mixin::output-chunking-p stream) + output-chunking)) + (when output-chunking-eof + (de.dataheaven.chunked-stream-mixin::disable-output-chunking stream)) + (when ic-p + (when input-chunking + (de.dataheaven.chunked-stream-mixin::initialize-input-chunking stream)) + (setf (de.dataheaven.chunked-stream-mixin::input-chunking-p stream) + input-chunking))) + + +(provide 'acl-socket) Added: branches/trunk-reorg/thirdparty/acl-compat/sbcl/acl-sys.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/acl-compat/sbcl/acl-sys.lisp Thu Feb 7 03:21:48 2008 @@ -0,0 +1,11 @@ +(in-package :acl-compat.system) + +(defun command-line-arguments () + sb-ext:*posix-argv*) + +(defun command-line-argument (n) + (nth n sb-ext:*posix-argv*)) + +(defun reap-os-subprocess (&key (wait nil)) + (declare (ignore wait)) + nil) Added: branches/trunk-reorg/thirdparty/acl-compat/scl/acl-excl.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/acl-compat/scl/acl-excl.lisp Thu Feb 7 03:21:48 2008 @@ -0,0 +1,264 @@ +;;;; +;;;; ACL-COMPAT - EXCL +;;;; + +;;;; Implementation-specific parts of acl-compat.excl (see +;;;; acl-excl-common.lisp) + +(defpackage :acl-compat.excl + (:use #:common-lisp #:ext) + (:export + #:if* + #:*initial-terminal-io* + #:*cl-default-special-bindings* + #:filesys-size + #:filesys-write-date + #:stream-input-fn + #:match-regexp + #:compile-regexp + #:*current-case-mode* + #:intern* + #:filesys-type + #:errorset + #:atomically + #:fast + #:without-package-locks + #:string-to-octets + #:write-vector + + ;; TODO: find better place for bivalent stream classes + #:bivalent-input-stream + #:bivalent-output-stream + #:bivalent-stream + #:make-bivalent-input-stream + #:make-bivalent-output-stream + #:make-bivalent-stream + )) + +(in-package :acl-compat.excl) + +(defun stream-input-fn (stream) + stream) + +(defun filesys-type (file-or-directory-name) + (if (eq :directory (unix:unix-file-kind + (namestring file-or-directory-name))) + :directory + (if (probe-file file-or-directory-name) + :file + nil))) + +(defmacro atomically (&body forms) + `(mp:without-scheduling , at forms)) + +(defun unix-signal (signal pid) + ;; fixxme: did I get the arglist right? only invocation I have seen + ;; is (excl::unix-signal 15 0) in net.aserve:start + (unix:unix-kill pid signal)) + +(defmacro without-package-locks (&body forms) + `(progn , at forms)) + + +;;; Bivalent Gray streams + + +(defclass lisp-stream-mixin () + ;; For bivalent streams, lisp-stream must be a stream of type + ;; unsigned-byte + ((lisp-stream :initarg :lisp-stream + :accessor lisp-stream))) + +(defclass bivalent-input-stream (lisp-stream-mixin + fundamental-character-input-stream + fundamental-binary-input-stream)) + +(defclass bivalent-output-stream (lisp-stream-mixin + fundamental-character-output-stream + fundamental-binary-output-stream)) + +(defclass bivalent-stream (bivalent-input-stream bivalent-output-stream)) + + +(defun make-bivalent-input-stream (lisp-stream) + (declare (type system:lisp-stream lisp-stream)) + (make-instance 'bivalent-input-stream :lisp-stream lisp-stream)) + +(defun make-bivalent-output-stream (lisp-stream) + (declare (type system:lisp-stream lisp-stream)) + (make-instance 'bivalent-output-stream :lisp-stream lisp-stream)) + +(defun make-bivalent-stream (lisp-stream) + (declare (type system:lisp-stream lisp-stream)) + (make-instance 'bivalent-stream :lisp-stream lisp-stream)) + + +(defmethod open-stream-p ((stream lisp-stream-mixin)) + (common-lisp::open-stream-p (lisp-stream stream))) + +(defmethod close ((stream lisp-stream-mixin) &key abort) + (close (lisp-stream stream) :abort abort)) + +(defmethod input-stream-p ((stream lisp-stream-mixin)) + (input-stream-p (lisp-stream stream))) + +(defmethod output-stream-p ((stream lisp-stream-mixin)) + (output-stream-p (lisp-stream stream))) + +(defmethod stream-element-type ((stream bivalent-input-stream)) + '(or character (unsigned-byte 8))) + +(defmethod stream-read-char ((stream bivalent-input-stream)) + (code-char (read-byte (lisp-stream stream) nil :eof))) + +(defmethod stream-read-byte ((stream bivalent-input-stream)) + (read-byte (lisp-stream stream) nil :eof)) + +;; stream-unread-char + +(defmethod stream-read-char-no-hang ((stream bivalent-input-stream)) + (if (listen (lisp-stream stream)) + (code-char (read-byte (lisp-stream stream))) + nil)) + +;; stream-peek-char + +(defmethod stream-listen ((stream bivalent-input-stream)) + (listen (lisp-stream stream))) + +(defmethod stream-clear-input ((stream bivalent-input-stream)) + (clear-input (lisp-stream stream))) + +(defmethod stream-read-sequence ((stream bivalent-input-stream) + (seq vector) &optional start end) + (unless start (setf start 0)) + (unless end (setf end (length seq))) + (assert (<= end (length seq))) + (if (subtypep (array-element-type seq) 'character) + (loop for count upfrom start + for i from start below end + do (setf (aref seq i) (code-char (read-byte stream))) + finally (return count)) + (read-sequence seq (lisp-stream stream) + :start start :end end))) + +(defmethod stream-read-sequence ((stream bivalent-input-stream) + (seq cons) &optional (start 0) end) + (unless start (setf start 0)) + (unless end (setf end (length seq))) + (let ((seq (nthcdr start seq))) + (loop for count upfrom start + for head on seq + for i below (- end start) + while head + do (setf (car head) (read-byte stream)) + finally (return count)))) + +(defmethod stream-read-sequence ((stream bivalent-input-stream) + (seq null) &optional (start 0) end) + (declare (ignore end)) + start) + +(defmethod stream-element-type ((stream bivalent-output-stream)) + '(or character (unsigned-byte 8))) + +(defmethod stream-write-char ((stream bivalent-output-stream) character) + (write-byte (char-code character) (lisp-stream stream))) + +(defmethod stream-write-byte ((stream bivalent-output-stream) byte) + (write-byte byte (lisp-stream stream))) + +(defmethod stream-line-column ((stream bivalent-output-stream)) + nil) + +(defmethod stream-finish-output ((stream bivalent-output-stream)) + (finish-output (lisp-stream stream))) + +(defmethod stream-force-output ((stream bivalent-output-stream)) + (force-output (lisp-stream stream))) + +(defmethod stream-clear-output ((stream bivalent-output-stream)) + (clear-output (lisp-stream stream))) + +(defmethod stream-write-sequence ((stream bivalent-output-stream) + (seq vector) &optional (start 0) end) + (let ((length (length seq))) + (unless end (setf end length)) + (assert (<= end length))) + (unless start (setf start 0)) + (when (< end start) + (cerror "Continue with switched start and end ~s <-> ~s" + "Stream-write-sequence: start (~S) and end (~S) exchanged." + start end seq) + (rotatef start end)) + (cond + ((subtypep (array-element-type seq) '(unsigned-byte 8)) + (write-sequence seq (lisp-stream stream) :start start :end end)) + ((subtypep (array-element-type seq) 'character) + (loop for i from start below end + do (stream-write-char stream (aref seq i)))) + ((subtypep (array-element-type seq) 'integer) + (loop for i from start below end + do (stream-write-byte stream (aref seq i))))) + seq) + +(defmethod stream-write-sequence ((stream bivalent-output-stream) + (seq cons) &optional (start 0) end) + (let ((length (length seq))) + (unless end (setf end length)) + (assert (<= end length))) + (unless start (setf start 0)) + (when (< end start) + (cerror "Continue with switched start and end ~s <-> ~s" + "Stream-write-sequence: start (~S) and end (~S) exchanged." + start end seq) + (rotatef start end)) + (let ((seq (nthcdr start seq))) + (loop for element in seq + for i below (- end start) + while seq + do (etypecase element + (character (stream-write-char stream element)) + (integer (stream-write-byte stream element))))) + seq) + +(defmethod stream-write-sequence ((stream bivalent-output-stream) + (seq null) &optional (start 0) end) + (declare (ignore start end)) + seq) + +;;; End bivalent Gray streams + +(defun string-to-octets (string &key (null-terminate t) (start 0) + end mb-vector make-mb-vector? + (external-format :default)) + "This function returns a lisp-usb8-vector and the number of bytes copied." + (declare (ignore external-format)) + ;; The end parameter is different in ACL's lambda list, but this + ;; variant lets us give an argument :end nil explicitly, and the + ;; right thing will happen + (unless end (setf end (length string))) + (let* ((number-of-octets (if null-terminate (1+ (- end start)) + (- end start))) + (mb-vector (cond + ((and mb-vector (>= (length mb-vector) number-of-octets)) + mb-vector) + ((or (not mb-vector) make-mb-vector?) + (make-array (list number-of-octets) + :element-type '(unsigned-byte 8) + :initial-element 0)) + (t (error "Was given a vector of length ~A, ~ + but needed at least length ~A." + (length mb-vector) number-of-octets))))) + (declare (type (simple-array (unsigned-byte 8) (*)) mb-vector)) + (loop for from-index from start below end + for to-index upfrom 0 + do (progn + (setf (aref mb-vector to-index) + (char-code (aref string from-index))))) + (when null-terminate + (setf (aref mb-vector (1- number-of-octets)) 0)) + (values mb-vector number-of-octets))) + + +(provide 'acl-excl) Added: branches/trunk-reorg/thirdparty/acl-compat/scl/acl-mp.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/acl-compat/scl/acl-mp.lisp Thu Feb 7 03:21:48 2008 @@ -0,0 +1,155 @@ +;; This package is designed for cmucl. It implements ACL-style +;; multiprocessing on top of cmucl (basically, process run reasons and +;; some function renames). +;; +;; Written by Rudi Schlatte, based on the work done by Jochen Schmidt +;; for Lispworks. + +(in-package :acl-compat-mp) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Import equivalent parts from the CMU MP package ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(shadowing-import '(mp:*current-process* + ;; mp::process-preset + mp::process-reset + mp:process-interrupt + mp::process-name + mp::process-wait-function + mp:process-run-reasons + mp:process-add-run-reason + mp:process-revoke-run-reason + mp:process-arrest-reasons + mp:process-add-arrest-reason + mp:process-revoke-arrest-reason + mp:process-whostate + ; mp:without-interrupts + mp:process-wait + mp:with-timeout + mp:without-scheduling + )) + +(export '(*current-process* + ;; process-preset + process-reset + process-interrupt + process-name + process-wait-function + process-whostate + process-wait + with-timeout + without-scheduling + process-run-reasons + process-add-run-reason + process-revoke-run-reason + process-arrest-reasons + process-add-arrest-reason + process-revoke-arrest-reason + )) + + +(defun process-allow-schedule () + (mp:process-yield)) + +(defvar *process-plists* (make-hash-table :test #'eq) + "maps processes to their plists. +See the functions process-plist, (setf process-plist).") + +(defun process-property-list (process) + (gethash process *process-plists*)) + +(defun (setf process-property-list) (new-value process) + (setf (gethash process *process-plists*) new-value)) + +#|| + +;;; rudi 2002-06-09: This is not needed as of cmucl 18d, thanks to Tim +;;; Moore who added run reasons to cmucl's multithreading. Left in +;;; for the time being just in case someone wants to get acl-compat +;;; running on older cmucl's. Can be deleted safely. + +(defvar *process-run-reasons* (make-hash-table :test #'eq) + "maps processes to their run-reasons. +See the functions process-run-reasons, (setf process-run-reasons), +process-add-run-reason, process-revoke-run-reason.") + +(defun process-run-reasons (process) + (gethash process *process-run-reasons*)) + +(defun (setf process-run-reasons) (new-value process) + (mp:without-scheduling + (prog1 + (setf (gethash process *process-run-reasons*) new-value) + (if new-value + (mp:enable-process process) + (mp:disable-process process))))) + +(defun process-revoke-run-reason (process object) + (without-scheduling + (setf (process-run-reasons process) + (remove object (process-run-reasons process)))) + (when (and (eq process mp:*current-process*)) + (mp:process-yield))) + +(defun process-add-run-reason (process object) + (setf (process-run-reasons process) + (pushnew object (process-run-reasons process)))) +||# + +(defun process-run-function (name-or-options preset-function + &rest preset-arguments) + (let ((process (ctypecase name-or-options + (string (make-process :name name-or-options)) + (list (apply #'make-process name-or-options))))) + (apply #'acl-mp::process-preset process preset-function preset-arguments) + process)) + +(defun process-preset (process preset-function &rest arguments) + (mp:process-preset process + #'(lambda () + (apply-with-bindings preset-function + arguments + (process-initial-bindings process))))) + +(defvar *process-initial-bindings* (make-hash-table :test #'eq)) + +(defun process-initial-bindings (process) + (gethash process *process-initial-bindings*)) + +(defun (setf process-initial-bindings) (bindings process) + (setf (gethash process *process-initial-bindings*) bindings)) + + +;;; ;;; +;;; Contributed by Tim Moore ;;; +;;; ;;; +(defun apply-with-bindings (function args bindings) + (if bindings + (progv + (mapcar #'car bindings) + (mapcar #'(lambda (binding) + (eval (cdr binding)))) + (apply function args)) + (apply function args))) + +(defun make-process (&key (name "Anonymous") reset-action run-reasons + arrest-reasons (priority 0) quantum resume-hook + suspend-hook initial-bindings run-immediately) + (declare (ignore priority quantum reset-action resume-hook suspend-hook + run-immediately)) + (mp:make-process nil :name name + :run-reasons run-reasons + :arrest-reasons arrest-reasons + :initial-bindings initial-bindings)) + +(defun process-kill (process) + (mp:destroy-process process)) + + +(defun make-process-lock (&key name) + (mp:make-lock name)) + +(defmacro with-process-lock ((lock &key norecursive) &body forms) + (declare (ignore norecursive)) + `(mp:with-lock-held (,lock) , at forms)) Added: branches/trunk-reorg/thirdparty/acl-compat/scl/acl-socket.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/acl-compat/scl/acl-socket.lisp Thu Feb 7 03:21:48 2008 @@ -0,0 +1,196 @@ +;; This package is designed for scl. It implements the +;; ACL-style socket interface on top of scl. +;; +;; Written by Rudi Schlatte, based on the work done by Jochen Schmidt +;; for Lispworks and net.lisp in the port library of CLOCC. +;; +;; This was modified for SCL by Kevin Rosenberg + +(defpackage acl-socket + (:use "MP" "COMMON-LISP") + #+cl-ssl (:import-from :ssl "MAKE-SSL-CLIENT-STREAM" "MAKE-SSL-SERVER-STREAM") + (:export #:socket #:make-socket #:accept-connection + #:ipaddr-to-dotted #:dotted-to-ipaddr #:ipaddr-to-hostname #:lookup-hostname + #:remote-host #:remote-port #:local-host #:local-port #:socket-control + #+cl-ssl #:make-ssl-client-stream #+cl-ssl #:make-ssl-server-stream) + (:nicknames socket)) + +(in-package socket) + +(defclass socket () + ((fd :type fixnum + :initarg :fd + :reader fd))) + +(defmethod print-object ((socket socket) stream) + (print-unreadable-object (socket stream :type t :identity t) + (format stream "@~d" (fd socket)))) + +(defclass server-socket (socket) + ((element-type :type (member signed-byte unsigned-byte base-char) + :initarg :element-type + :reader element-type + :initform (error "No value supplied for element-type")) + (port :type fixnum + :initarg :port + :reader port + :initform (error "No value supplied for port")) + (stream-type :type (member :text :binary :bivalent) + :initarg :stream-type + :reader stream-type + :initform (error "No value supplied for stream-type")))) + +#+cl-ssl +(defmethod make-ssl-server-stream ((lisp-stream system:lisp-stream) + &rest options) + (apply #'make-ssl-server-stream (system:fd-stream-fd lisp-stream) options)) + +(defmethod print-object ((socket server-socket) stream) + (print-unreadable-object (socket stream :type t :identity nil) + (format stream "@~d on port ~d" (fd socket) (port socket)))) + +(defmethod accept-connection ((server-socket server-socket) + &key (wait t)) + "Return a bidirectional stream connected to socket, or nil if no +client wanted to initiate a connection and wait is nil." + ;; fixxme: perhaps check whether we run multiprocessing and use + ;; sys:wait-until-fd-usable instead of + ;; mp:process-wait-until-fd-usable here? + + ;; api pipe fitting: wait t ==> timeout nil + (when (mp:process-wait-until-fd-usable (fd server-socket) :input + (if wait nil 0)) + (let ((stream (sys:make-fd-stream + (ext:accept-tcp-connection (fd server-socket)) + :input t :output t + :element-type (element-type server-socket) + :auto-close t))) + (if (eq (stream-type server-socket) :bivalent) + (excl:make-bivalent-stream stream) + stream)))) + +(defun make-socket (&key (remote-host "localhost") + local-port + remote-port + (connect :active) + (format :text) + &allow-other-keys) + "Return a stream connected to remote-host if connect is :active, or +something listening on local-port that can be fed to accept-connection +if connect is :passive. + +This is an incomplete implementation of ACL's make-socket function! +It was written to provide the functionality necessary to port +AllegroServe. Refer to +http://franz.com/support/documentation/6.1/doc/pages/operators/socket/make-socket.htm +to read about the missing parts." + (check-type remote-host string) + (let ((element-type (ecase format + (:text 'base-char) + (:binary 'signed-byte) + (:bivalent 'unsigned-byte)))) + (ecase connect + (:passive + (make-instance 'server-socket + :port local-port + :fd (ext:create-inet-listener local-port) + :element-type element-type + :stream-type format)) + (:active + (let ((stream (sys:make-fd-stream + (ext:connect-to-inet-socket remote-host remote-port) + :input t :output t :element-type element-type))) + (if (eq :bivalent format) + (excl:make-bivalent-stream stream) + stream)))))) + +(defmethod close ((server server-socket) &key abort) + "Kill a passive (listening) socket. (Active sockets are actually +streams and handled by their close methods." + (declare (ignore abort)) + (unix:unix-close (fd server))) + +(declaim (ftype (function ((unsigned-byte 32) &key (:values t)) + (values simple-string)) + ipaddr-to-dotted)) +(defun ipaddr-to-dotted (ipaddr &key values) + (declare (type (unsigned-byte 32) ipaddr)) + (let ((a (logand #xff (ash ipaddr -24))) + (b (logand #xff (ash ipaddr -16))) + (c (logand #xff (ash ipaddr -8))) + (d (logand #xff ipaddr))) + (if values + (values a b c d) + (format nil "~d.~d.~d.~d" a b c d)))) + +(defun string-tokens (string) + (labels ((get-token (str pos1 acc) + (let ((pos2 (position #\Space str :start pos1))) + (if (not pos2) + (nreverse acc) + (get-token str (1+ pos2) (cons (read-from-string (subseq str pos1 pos2)) + acc)))))) + (get-token (concatenate 'string string " ") 0 nil))) + +(declaim (ftype (function (string &key (:errorp t)) + (values (unsigned-byte 32))) + dotted-to-ipaddr)) +(defun dotted-to-ipaddr (dotted &key (errorp t)) + (declare (string dotted)) + (if errorp + (let ((ll (string-tokens (substitute #\Space #\. dotted)))) + (+ (ash (first ll) 24) (ash (second ll) 16) + (ash (third ll) 8) (fourth ll))) + (ignore-errors + (let ((ll (string-tokens (substitute #\Space #\. dotted)))) + (+ (ash (first ll) 24) (ash (second ll) 16) + (ash (third ll) 8) (fourth ll)))))) + +(defun ipaddr-to-hostname (ipaddr &key ignore-cache) + (when ignore-cache + (warn ":IGNORE-CACHE keyword in IPADDR-TO-HOSTNAME not supported.")) + (ext:host-entry-name (ext:lookup-host-entry ipaddr))) + +(defun lookup-hostname (host &key ignore-cache) + (when ignore-cache + (warn ":IGNORE-CACHE keyword in LOOKUP-HOSTNAME not supported.")) + (if (stringp host) + (car (ext:host-entry-addr-list (ext:lookup-host-entry host))) + (dotted-to-ipaddr (ipaddr-to-dotted host)))) + +(defgeneric get-fd (stream)) + +(defmethod get-fd ((stream excl::lisp-stream-mixin)) + (system:fd-stream-fd (excl::lisp-stream stream))) + +(defmethod get-fd ((stream system:lisp-stream)) + (system:fd-stream-fd stream)) + +(defun remote-host (socket-stream) + (ext:get-peer-host-and-port (get-fd socket-stream))) + +(defun remote-port (socket-stream) + (multiple-value-bind (host port) + (ext:get-peer-host-and-port (get-fd socket-stream)) + (declare (ignore host)) + port)) + +(defun local-host (socket-stream) + (ext:get-socket-host-and-port (get-fd socket-stream))) + +(defun local-port (socket-stream) + (if (typep socket-stream 'socket::server-socket) + (port socket-stream) + (multiple-value-bind (host port) + (ext:get-socket-host-and-port (get-fd socket-stream)) + (declare (ignore host)) + port))) + +(defun socket-control (stream &key output-chunking output-chunking-eof input-chunking) + (declare (ignore stream)) + (warn "SOCKET-CONTROL function not implemented.") + (when (or output-chunking output-chunking-eof input-chunking) + (error "Chunking is not yet supported in scl. Restart the server with chunking off."))) + + +(provide 'acl-socket) Added: branches/trunk-reorg/thirdparty/acl-compat/scl/acl-sys.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/acl-compat/scl/acl-sys.lisp Thu Feb 7 03:21:48 2008 @@ -0,0 +1,18 @@ +(in-package :sys) + +(ignore-errors +(export 'command-line-arguments) +(export 'command-line-argument) +(export 'reap-os-subprocess) + +(defun command-line-arguments () + ext:*command-line-strings*) + +(defun command-line-argument (n) + (nth n ext:*command-line-strings*)) + +(defun reap-os-subprocess (&key (wait nil)) + (declare (ignore wait)) + nil) + +) Added: branches/trunk-reorg/thirdparty/acl-compat/test-acl-socket.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/acl-compat/test-acl-socket.lisp Thu Feb 7 03:21:48 2008 @@ -0,0 +1,61 @@ +;;; Unit tests for the ACL-SOCKET compatibility package. + +(in-package cl-user) + +(require :acl-socket) + +(use-package '(acl-socket)) + +(defun test1 () + (let ((stream (make-socket :connect :active :remote-host "127.0.0.1" :remote-port 2500))) + (when stream + (read-line stream) + (format stream "helo foo") + (write-char #\Return stream) + (write-char #\Linefeed stream) + (finish-output stream) + (read-line stream) + (close stream)))) + +(defun test2 () + (let ((stream (make-socket :connect :active :remote-host "127.0.0.1" :remote-port 2500))) + (when stream + (socket-control stream :output-chunking t) + (read-line stream) + (format stream "helo foo") + (write-char #\Return stream) + (write-char #\Linefeed stream) + (finish-output stream) + (read-line stream) + (close stream)))) + +(defun test3 () + (let ((stream (make-socket :connect :active :remote-host "127.0.0.1" :remote-port 2500))) + (when stream + (socket-control stream :input-chunking t) + (prog1 + (read-line stream) + (close stream))))) + +(defun test4 () + (let ((stream (or (make-socket :connect :active :remote-host "127.0.0.1" :remote-port 2500) + (error "Failed to connect.")))) + (socket-control stream :input-chunking t) + (format t "File number 1: ") + #1=(handler-case + (loop + for char = (read-char stream nil stream) + until (eq char stream) + do (write-char char)) + (excl::socket-chunking-end-of-file (e) (socket-control stream :input-chunking t))) + (format t "~%File number 2: ") + #1# + (terpri) + (values))) + + + + + + + From hhubner at common-lisp.net Thu Feb 7 08:30:36 2008 From: hhubner at common-lisp.net (hhubner at common-lisp.net) Date: Thu, 7 Feb 2008 03:30:36 -0500 (EST) Subject: [bknr-cvs] r2451 - in branches/trunk-reorg/bknr: datastore/src/data datastore/src/utils web/src web/src/rss web/src/web Message-ID: <20080207083036.654327C051@common-lisp.net> Author: hhubner Date: Thu Feb 7 03:30:34 2008 New Revision: 2451 Modified: branches/trunk-reorg/bknr/datastore/src/data/object.lisp branches/trunk-reorg/bknr/datastore/src/utils/utils.lisp branches/trunk-reorg/bknr/web/src/bknr-web.asd branches/trunk-reorg/bknr/web/src/packages.lisp branches/trunk-reorg/bknr/web/src/rss/rss.lisp branches/trunk-reorg/bknr/web/src/web/handlers.lisp branches/trunk-reorg/bknr/web/src/web/host.lisp branches/trunk-reorg/bknr/web/src/web/template-handler.lisp Log: save current state Modified: branches/trunk-reorg/bknr/datastore/src/data/object.lisp ============================================================================== --- branches/trunk-reorg/bknr/datastore/src/data/object.lisp (original) +++ branches/trunk-reorg/bknr/datastore/src/data/object.lisp Thu Feb 7 03:30:34 2008 @@ -574,8 +574,7 @@ (if restoring (remove-transient-slot-initargs (find-class class-name) initargs) initargs))) - (unless restoring - (initialize-persistent-instance obj)) + (initialize-persistent-instance obj) (initialize-transient-instance obj) (setf error nil) obj) Modified: branches/trunk-reorg/bknr/datastore/src/utils/utils.lisp ============================================================================== --- branches/trunk-reorg/bknr/datastore/src/utils/utils.lisp (original) +++ branches/trunk-reorg/bknr/datastore/src/utils/utils.lisp Thu Feb 7 03:30:34 2008 @@ -511,7 +511,7 @@ (with-open-file (s pathname :element-type '(unsigned-byte 8)) (let ((result (make-array (file-length s) :element-type '(unsigned-byte 8)))) - (read-sequence result s ) + (read-sequence result s) result))) (defun class-subclasses (class) Modified: branches/trunk-reorg/bknr/web/src/bknr-web.asd ============================================================================== --- branches/trunk-reorg/bknr/web/src/bknr-web.asd (original) +++ branches/trunk-reorg/bknr/web/src/bknr-web.asd Thu Feb 7 03:30:34 2008 @@ -31,6 +31,7 @@ :hunchentoot :xhtmlgen :puri + :usocket :bknr-datastore :bknr-data-impex :parenscript) Modified: branches/trunk-reorg/bknr/web/src/packages.lisp ============================================================================== --- branches/trunk-reorg/bknr/web/src/packages.lisp (original) +++ branches/trunk-reorg/bknr/web/src/packages.lisp Thu Feb 7 03:30:34 2008 @@ -263,6 +263,7 @@ ;; templates #:expand-template + #:expand-variables #:get-template-var #:with-template-vars #:emit-template-node @@ -313,6 +314,7 @@ #:object-handler #:edit-object-handler #:template-handler + #:template-handler-destination #:page-handler #:page-handler-prefix #:page-handler-site Modified: branches/trunk-reorg/bknr/web/src/rss/rss.lisp ============================================================================== --- branches/trunk-reorg/bknr/web/src/rss/rss.lisp (original) +++ branches/trunk-reorg/bknr/web/src/rss/rss.lisp Thu Feb 7 03:30:34 2008 @@ -129,7 +129,7 @@ (remove-item (rss-item-channel rss-item) rss-item)) (defun item-slot-element (item slot-name) - (let ((accessor (kmrcl:concat-symbol-pkg (find-package :bknr.rss) 'rss-item- slot-name))) + (let ((accessor (find-symbol (format nil "RSS-ITEM-~A" slot-name) (find-package :bknr.rss)))) (aif (funcall accessor item) (with-element (string-downcase (symbol-name slot-name)) (text it))))) Modified: branches/trunk-reorg/bknr/web/src/web/handlers.lisp ============================================================================== --- branches/trunk-reorg/bknr/web/src/web/handlers.lisp (original) +++ branches/trunk-reorg/bknr/web/src/web/handlers.lisp Thu Feb 7 03:30:34 2008 @@ -557,4 +557,4 @@ (defun unpublish () (setf *dispatch-table* (remove 'bknr-handler *dispatch-table*) - *handlers* nil)) \ No newline at end of file + *handlers* nil)) Modified: branches/trunk-reorg/bknr/web/src/web/host.lisp ============================================================================== --- branches/trunk-reorg/bknr/web/src/web/host.lisp (original) +++ branches/trunk-reorg/bknr/web/src/web/host.lisp Thu Feb 7 03:30:34 2008 @@ -46,11 +46,11 @@ (host-ip-address host))) (defmethod host-ipaddr ((host host)) - (kmrcl::dotted-to-ipaddr (host-ip-address host))) + (usocket:host-byte-order (host-ip-address host))) (defun find-host (&key ip-address create ipaddr) (when ipaddr - (setf ip-address (kmrcl::ipaddr-to-dotted ipaddr))) + (setf ip-address (usocket:hbo-to-dotted-quad ipaddr))) (or (host-with-ipaddress ip-address) (and create (make-object 'host :ip-address ip-address)))) Modified: branches/trunk-reorg/bknr/web/src/web/template-handler.lisp ============================================================================== --- branches/trunk-reorg/bknr/web/src/web/template-handler.lisp (original) +++ branches/trunk-reorg/bknr/web/src/web/template-handler.lisp Thu Feb 7 03:30:34 2008 @@ -92,7 +92,7 @@ ,(intern (symbol-name var) :keyword))))) , at body)) -(defun expand-variables (string) +(defun expand-variables (string lookup-variable) (if (find #\$ string) (regex-replace-all #?r"\$\(([\*_-\w]+)\)" string @@ -101,7 +101,7 @@ (let* ((var (make-keyword-from-string (subseq target-string (aref reg-starts 0) (aref reg-ends 0)))) - (val (get-template-var var))) + (val (funcall lookup-variable var))) (cond ((stringp val) val) ((null val) "") @@ -136,7 +136,7 @@ (defun emit-template-node (expander node) (if (stringp node) - (sax:characters *html-sink* (expand-variables node)) + (sax:characters *html-sink* (expand-variables node #'get-template-var)) (let* ((name (node-name node)) (ns (node-ns node)) (children (node-children node)) @@ -148,10 +148,10 @@ (apply (find-tag-function expander name ns) (append (loop for (key name) in attrs collect (make-keyword-from-string key) - collect (expand-variables name)))))) + collect (expand-variables name #'get-template-var)))))) (t (sax:start-element *html-sink* nil nil name - (xmls-attributes-to-sax #'expand-variables attrs)) + (xmls-attributes-to-sax (rcurry #'expand-variables #'get-template-var) attrs)) (dolist (child children) (emit-template-node expander child)) (sax:end-element *html-sink* nil nil name)))))) From hhubner at common-lisp.net Thu Feb 7 08:33:05 2008 From: hhubner at common-lisp.net (hhubner at common-lisp.net) Date: Thu, 7 Feb 2008 03:33:05 -0500 (EST) Subject: [bknr-cvs] r2452 - in branches/trunk-reorg/thirdparty/slime: . CVS contrib contrib/CVS doc/CVS Message-ID: <20080207083305.02DD4554B9@common-lisp.net> Author: hhubner Date: Thu Feb 7 03:32:58 2008 New Revision: 2452 Removed: branches/trunk-reorg/thirdparty/slime/CVS/Entries.Log Modified: branches/trunk-reorg/thirdparty/slime/CVS/Entries branches/trunk-reorg/thirdparty/slime/ChangeLog branches/trunk-reorg/thirdparty/slime/contrib/CVS/Entries branches/trunk-reorg/thirdparty/slime/contrib/ChangeLog branches/trunk-reorg/thirdparty/slime/contrib/swank-arglists.lisp branches/trunk-reorg/thirdparty/slime/contrib/swank-fancy-inspector.lisp branches/trunk-reorg/thirdparty/slime/contrib/swank-presentation-streams.lisp branches/trunk-reorg/thirdparty/slime/doc/CVS/Entries branches/trunk-reorg/thirdparty/slime/slime-autoloads.el branches/trunk-reorg/thirdparty/slime/slime.el branches/trunk-reorg/thirdparty/slime/swank-abcl.lisp branches/trunk-reorg/thirdparty/slime/swank-allegro.lisp branches/trunk-reorg/thirdparty/slime/swank-backend.lisp branches/trunk-reorg/thirdparty/slime/swank-clisp.lisp branches/trunk-reorg/thirdparty/slime/swank-cmucl.lisp branches/trunk-reorg/thirdparty/slime/swank-corman.lisp branches/trunk-reorg/thirdparty/slime/swank-ecl.lisp branches/trunk-reorg/thirdparty/slime/swank-lispworks.lisp branches/trunk-reorg/thirdparty/slime/swank-loader.lisp branches/trunk-reorg/thirdparty/slime/swank-openmcl.lisp branches/trunk-reorg/thirdparty/slime/swank-sbcl.lisp branches/trunk-reorg/thirdparty/slime/swank-scl.lisp branches/trunk-reorg/thirdparty/slime/swank.lisp Log: delete unwanted file Modified: branches/trunk-reorg/thirdparty/slime/CVS/Entries ============================================================================== --- branches/trunk-reorg/thirdparty/slime/CVS/Entries (original) +++ branches/trunk-reorg/thirdparty/slime/CVS/Entries Thu Feb 7 03:32:58 2008 @@ -1,35 +1,35 @@ D/contrib//// D/doc//// -/.cvsignore/1.5/Sun Apr 8 19:23:57 2007// -/ChangeLog/1.1274/Sun Jan 27 22:03:20 2008// -/HACKING/1.8/Sun Jan 27 22:03:20 2008// -/NEWS/1.9/Sun Jan 27 22:03:20 2008// -/PROBLEMS/1.8/Sun Jan 27 22:03:20 2008// -/README/1.14/Sun Jan 27 22:03:20 2008// -/hyperspec.el/1.11/Sun Jan 27 22:03:20 2008// -/metering.lisp/1.4/Sun Jan 27 22:03:20 2008// -/mkdist.sh/1.7/Sun Jan 27 22:03:20 2008// -/nregex.lisp/1.4/Sun Jan 27 22:03:20 2008// -/sbcl-pprint-patch.lisp/1.1/Sun Jan 27 22:03:20 2008// -/slime-autoloads.el/1.3/Sun Jan 27 22:03:20 2008// -/slime.el/1.896/Sun Jan 27 22:03:20 2008// -/swank-abcl.lisp/1.44/Sun Jan 27 22:03:20 2008// -/swank-allegro.lisp/1.98/Sun Jan 27 22:03:20 2008// -/swank-backend.lisp/1.126/Sun Jan 27 22:03:21 2008// -/swank-clisp.lisp/1.64/Sun Jan 27 22:03:21 2008// -/swank-cmucl.lisp/1.175/Sun Jan 27 22:03:21 2008// -/swank-corman.lisp/1.11/Sun Jan 27 22:03:21 2008// -/swank-ecl.lisp/1.11/Sun Jan 27 22:03:21 2008// -/swank-gray.lisp/1.10/Sun Jan 27 22:03:21 2008// -/swank-lispworks.lisp/1.93/Sun Jan 27 22:03:21 2008// -/swank-loader.lisp/1.75/Sun Jan 27 22:03:21 2008// -/swank-openmcl.lisp/1.120/Sun Jan 27 22:03:21 2008// -/swank-sbcl.lisp/1.187/Sun Jan 27 22:03:21 2008// -/swank-scl.lisp/1.14/Sun Jan 27 22:03:21 2008// -/swank-source-file-cache.lisp/1.8/Sun Jan 27 22:03:21 2008// -/swank-source-path-parser.lisp/1.18/Sun Jan 27 22:03:21 2008// -/swank.asd/1.5/Sun Jan 27 22:03:21 2008// -/swank.lisp/1.523/Sun Jan 27 22:03:21 2008// -/test-all.sh/1.2/Sun Jan 27 22:03:21 2008// -/test.sh/1.9/Sun Jan 27 22:03:21 2008// -/xref.lisp/1.2/Sun Jan 27 22:03:21 2008// +/.cvsignore/1.5/Thu Oct 11 14:10:25 2007// +/ChangeLog/1.1282/Thu Feb 7 08:07:30 2008// +/HACKING/1.8/Thu Oct 11 14:10:25 2007// +/NEWS/1.9/Sun Dec 2 04:22:09 2007// +/PROBLEMS/1.8/Thu Oct 11 14:10:25 2007// +/README/1.14/Thu Oct 11 14:10:25 2007// +/hyperspec.el/1.11/Thu Oct 11 14:10:25 2007// +/metering.lisp/1.4/Thu Oct 11 14:10:25 2007// +/mkdist.sh/1.7/Thu Oct 11 14:10:25 2007// +/nregex.lisp/1.4/Thu Oct 11 14:10:25 2007// +/sbcl-pprint-patch.lisp/1.1/Thu Oct 11 14:10:25 2007// +/slime-autoloads.el/1.4/Thu Feb 7 08:07:30 2008// +/slime.el/1.901/Thu Feb 7 08:07:31 2008// +/swank-abcl.lisp/1.45/Thu Feb 7 08:07:31 2008// +/swank-allegro.lisp/1.99/Thu Feb 7 08:07:31 2008// +/swank-backend.lisp/1.127/Thu Feb 7 08:07:31 2008// +/swank-clisp.lisp/1.65/Thu Feb 7 08:07:31 2008// +/swank-cmucl.lisp/1.176/Thu Feb 7 08:07:31 2008// +/swank-corman.lisp/1.13/Thu Feb 7 08:07:31 2008// +/swank-ecl.lisp/1.12/Thu Feb 7 08:07:31 2008// +/swank-gray.lisp/1.10/Thu Oct 11 14:10:25 2007// +/swank-lispworks.lisp/1.94/Thu Feb 7 08:07:31 2008// +/swank-loader.lisp/1.77/Thu Feb 7 08:07:31 2008// +/swank-openmcl.lisp/1.122/Thu Feb 7 08:07:31 2008// +/swank-sbcl.lisp/1.189/Thu Feb 7 08:07:31 2008// +/swank-scl.lisp/1.15/Thu Feb 7 08:07:31 2008// +/swank-source-file-cache.lisp/1.8/Thu Oct 11 14:10:25 2007// +/swank-source-path-parser.lisp/1.18/Thu Feb 7 07:59:36 2008// +/swank.asd/1.5/Thu Oct 11 14:10:25 2007// +/swank.lisp/1.527/Thu Feb 7 08:07:31 2008// +/test-all.sh/1.2/Thu Oct 11 14:10:25 2007// +/test.sh/1.9/Thu Oct 11 14:10:25 2007// +/xref.lisp/1.2/Thu Oct 11 14:10:25 2007// Modified: branches/trunk-reorg/thirdparty/slime/ChangeLog ============================================================================== --- branches/trunk-reorg/thirdparty/slime/ChangeLog (original) +++ branches/trunk-reorg/thirdparty/slime/ChangeLog Thu Feb 7 03:32:58 2008 @@ -1,7 +1,73 @@ +2008-02-05 Marco Baringer + + * slime.el (slime-search-buffer-package): Ask the lisp to read the + in-package form so that we properly deal with #+foo and |WHATEVER| + package names. + (slime-repl-set-package): Only prompt with a default package if + the repl's package is different from the current package. + +2008-02-04 Marco Baringer + + * swank-openmcl.lisp (ccl::advise ccl::break): advise the + lower-level ccl::cbreak-loop instead of cl:break. + (frame-locals): If the value is a value-cell (a closed over value) + show the closed over value and not the value cell. + (disassemble-frame): add in x86-64 code. + + * slime-autoloads.el (slime-setup-contribs): Add contribs + directory to load-path. + + * slime.el (slime-setup): Add contribs directory to load-path. + + * swank-abcl.lisp, swank-allegro.lisp, swank-backend.lisp, + swank-clisp.lisp, swank-cmucl.lisp, swank-corman.lisp, + swank-ecl.lisp, swank-lispworks.lisp, swank-openmcl.lisp, + swank-sbcl.lisp, swank-scl.lisp, swank.lisp, + contrib/swank-fancy-inspector.lisp: Remove second argument from + swank:inspect-for-emacs. This functionality, choosing an inspector + at runtime, was never actually used and is, now, needless + complexity. + +2008-02-04 Helmut Eller + + Simpler code to bind 0-9 in the debugger. + + * slime.el (sldb-mode-map): When binding the keys 0-9, use eval + instead of two macros. + +2008-02-04 Helmut Eller + + Move some functions to swank-arglist.lisp. + + * swank.lisp (length=, ensure-list, recursively-empty-p) + (maybecall, exactly-one-p, read-softly-from-string) + (unintern-in-home-package, valid-function-name-p): Moved to + contrib/swank-arglist.lisp. + +2008-02-03 Marco Baringer + + * swank.lisp (*sldb-condition-printer*): New variable. + (safe-condition-message): Use the current binding + of *sldb-condition-printer* to print the condition to a string. + + * slime.el (sldb-invoke-restart-by-name): New function. Invokes a + restart by name, uses completion to read restart's name. + (slime-define-keys sldb-mode-map): Bind + sldb-invoke-restart-by-name to I in sldb buffers. + + * swank-loader.lisp: When loading swank delete all swank packages + first. This protects the lisp from broken reloads of swank. Leave + the swank-loader package so that users can set *fasl-directory* + and *source-directory* as per the documentation. + (lisp-version-string): On openmcl use the full + cl:lisp-implementation-version, ccl::*openmcl-major-version* and + ccl::*openmcl-minor-version* aren't sufficently precise to notice + changes in openmcl's cvs. + 2008-01-27 Helmut Eller Make it easier to start a non-default Lisp from ELisp code. - + * slime.el (slime): If the argument is a symbol start the corresponding entry in slime-lisp-implementations. Typical use is something like: @@ -15,7 +81,7 @@ (suppress-sharp-dot): unused, delete it. * slime.el (test compile-defun): test with #+#.'(:and). - + 2008-01-21 Helmut Eller * slime.el (sldb-mode): Don't throw to toplevel in the Modified: branches/trunk-reorg/thirdparty/slime/contrib/CVS/Entries ============================================================================== --- branches/trunk-reorg/thirdparty/slime/contrib/CVS/Entries (original) +++ branches/trunk-reorg/thirdparty/slime/contrib/CVS/Entries Thu Feb 7 03:32:58 2008 @@ -1,33 +1,37 @@ -/ChangeLog/1.82/Sun Jan 27 22:03:21 2008// -/README/1.3/Sun Jan 27 22:03:21 2008// -/bridge.el/1.1/Sun Jan 27 22:03:22 2008// -/inferior-slime.el/1.2/Sun Jan 27 22:03:22 2008// -/slime-asdf.el/1.3/Sun Jan 27 22:03:22 2008// -/slime-autodoc.el/1.7/Sun Jan 27 22:03:22 2008// -/slime-banner.el/1.4/Sun Jan 27 22:03:22 2008// -/slime-c-p-c.el/1.8/Sun Jan 27 22:03:22 2008// -/slime-editing-commands.el/1.6/Sun Jan 27 22:03:22 2008// -/slime-fancy-inspector.el/1.2/Sun Jan 27 22:03:22 2008// -/slime-fancy.el/1.4/Sun Jan 27 22:03:22 2008// -/slime-fuzzy.el/1.6/Sun Jan 27 22:03:22 2008// -/slime-highlight-edits.el/1.3/Sun Jan 27 22:03:22 2008// -/slime-parse.el/1.10/Sun Jan 27 22:03:22 2008// -/slime-presentation-streams.el/1.2/Sun Jan 27 22:03:22 2008// -/slime-presentations.el/1.12/Sun Jan 27 22:03:22 2008// -/slime-references.el/1.4/Sun Jan 27 22:03:22 2008// -/slime-scheme.el/1.1/Wed Jan 9 18:30:26 2008// -/slime-scratch.el/1.4/Sun Jan 27 22:03:22 2008// -/slime-tramp.el/1.2/Sun Jan 27 22:03:22 2008// -/slime-typeout-frame.el/1.6/Sun Jan 27 22:03:22 2008// -/slime-xref-browser.el/1.1/Sun Jan 27 22:03:22 2008// -/swank-arglists.lisp/1.18/Sun Jan 27 22:03:22 2008// -/swank-asdf.lisp/1.1/Sun Jan 27 22:03:22 2008// -/swank-c-p-c.lisp/1.2/Sun Jan 27 22:03:22 2008// -/swank-fancy-inspector.lisp/1.5/Sun Jan 27 22:03:22 2008// -/swank-fuzzy.lisp/1.7/Sun Jan 27 22:03:22 2008// -/swank-goo.goo/1.1/Sat Jan 19 14:08:27 2008// -/swank-kawa.scm/1.1/Sat Jan 19 14:08:27 2008// -/swank-listener-hooks.lisp/1.1/Sun Jan 27 22:03:22 2008// -/swank-presentation-streams.lisp/1.4/Sun Jan 27 22:03:22 2008// -/swank-presentations.lisp/1.4/Sun Jan 27 22:03:22 2008// +/ChangeLog/1.87/Thu Feb 7 08:07:31 2008// +/README/1.3/Thu Oct 11 14:10:25 2007// +/bridge.el/1.1/Thu Oct 11 14:10:25 2007// +/inferior-slime.el/1.2/Thu Oct 11 14:10:25 2007// +/slime-asdf.el/1.3/Thu Oct 11 14:10:25 2007// +/slime-autodoc.el/1.7/Thu Feb 7 07:59:35 2008// +/slime-banner.el/1.4/Thu Oct 11 14:10:25 2007// +/slime-c-p-c.el/1.8/Thu Oct 11 14:10:25 2007// +/slime-editing-commands.el/1.6/Thu Feb 7 07:59:35 2008// +/slime-fancy-inspector.el/1.2/Thu Oct 11 14:10:25 2007// +/slime-fancy.el/1.4/Thu Oct 11 14:10:25 2007// +/slime-fuzzy.el/1.6/Thu Feb 7 07:59:35 2008// +/slime-highlight-edits.el/1.3/Thu Oct 11 14:10:25 2007// +/slime-indentation.el/1.1/Sun Feb 3 18:45:14 2008// +/slime-motd.el/1.1/Sun Feb 3 18:39:23 2008// +/slime-parse.el/1.10/Thu Feb 7 07:59:35 2008// +/slime-presentation-streams.el/1.2/Thu Oct 11 14:10:25 2007// +/slime-presentations.el/1.12/Thu Feb 7 07:59:35 2008// +/slime-references.el/1.4/Thu Oct 11 14:10:25 2007// +/slime-scheme.el/1.1/Thu Feb 7 08:07:31 2008// +/slime-scratch.el/1.4/Thu Oct 11 14:10:25 2007// +/slime-tramp.el/1.2/Thu Oct 11 14:10:25 2007// +/slime-typeout-frame.el/1.6/Thu Feb 7 07:59:35 2008// +/slime-xref-browser.el/1.1/Thu Oct 11 14:10:25 2007// +/swank-arglists.lisp/1.20/Thu Feb 7 08:07:31 2008// +/swank-asdf.lisp/1.1/Thu Oct 11 14:10:25 2007// +/swank-c-p-c.lisp/1.2/Thu Oct 11 14:10:25 2007// +/swank-fancy-inspector.lisp/1.7/Thu Feb 7 08:07:32 2008// +/swank-fuzzy.lisp/1.7/Thu Feb 7 07:59:35 2008// +/swank-goo.goo/1.1/Thu Feb 7 08:07:32 2008// +/swank-indentation.lisp/1.1/Sun Feb 3 18:45:14 2008// +/swank-kawa.scm/1.1/Thu Feb 7 08:07:32 2008// +/swank-listener-hooks.lisp/1.1/Thu Oct 11 14:10:25 2007// +/swank-motd.lisp/1.1/Sun Feb 3 18:39:23 2008// +/swank-presentation-streams.lisp/1.5/Thu Feb 7 08:07:32 2008// +/swank-presentations.lisp/1.4/Thu Oct 11 14:10:25 2007// D Modified: branches/trunk-reorg/thirdparty/slime/contrib/ChangeLog ============================================================================== --- branches/trunk-reorg/thirdparty/slime/contrib/ChangeLog (original) +++ branches/trunk-reorg/thirdparty/slime/contrib/ChangeLog Thu Feb 7 03:32:58 2008 @@ -1,7 +1,37 @@ +2008-02-04 Marco Baringer + + * swank-presentation-streams.lisp (presenting-object-1): Add + declare special *record-repl-results* to silence compiler + warnings. + + * swank-arglists.lisp (arglist-dispatch): Specialize operator-type + so openmcl doesn't warn about unused arguments. + (arglist-dispatch): add declare ignore form. + +2008-02-04 Helmut Eller + + Move some functions to swank-arglist.lisp. + + * swank-arglist.lisp (length=, ensure-list, recursively-empty-p) + (maybecall, exactly-one-p, read-softly-from-string) + (unintern-in-home-package, valid-function-name-p): Moved from + swank.lisp. to contrib/swank-arglist.lisp. + +2008-02-03 Marco Baringer + + * swank-motd.lisp, slime-motd.el: Message Of The Day printing for + slime. + + * slime-indentation.el: Integrate cl-indent.el into slime's + contrib infrastructure. Fix bug in &rest. + + * swank-indentation.lisp: Allow an application runnig under slime + to update emacs' indentation notes. + 2008-01-27 Helmut Eller Make autodoc use the correct width of the typeout-window. - + * slime-autodoc.el (slime-autodoc-dimensions-function): New variable. (slime-autodoc-message-dimensions): Use it. @@ -13,7 +43,7 @@ 2008-01-27 Helmut Eller Use slime-require instead of a connected-hook. - + * slime-autodoc.el (slime-autodoc-on-connect): Deleted. 2008-01-20 Matthias Koeppe Modified: branches/trunk-reorg/thirdparty/slime/contrib/swank-arglists.lisp ============================================================================== --- branches/trunk-reorg/thirdparty/slime/contrib/swank-arglists.lisp (original) +++ branches/trunk-reorg/thirdparty/slime/contrib/swank-arglists.lisp Thu Feb 7 03:32:58 2008 @@ -12,6 +12,40 @@ (eval-when (:compile-toplevel :load-toplevel :execute) (swank-require :swank-c-p-c)) +(defun length= (seq n) + "Test for whether SEQ contains N number of elements. I.e. it's equivalent + to (= (LENGTH SEQ) N), but besides being more concise, it may also be more + efficiently implemented." + (etypecase seq + (list (do ((i n (1- i)) + (list seq (cdr list))) + ((or (<= i 0) (null list)) + (and (zerop i) (null list))))) + (sequence (= (length seq) n)))) + +(defun ensure-list (thing) + (if (listp thing) thing (list thing))) + +(defun recursively-empty-p (list) + "Returns whether LIST consists only of arbitrarily nested empty lists." + (cond ((not (listp list)) nil) + ((null list) t) + (t (every #'recursively-empty-p list)))) + +(defun maybecall (bool fn &rest args) + "Call FN with ARGS if BOOL is T. Otherwise return ARGS as multiple values." + (if bool (apply fn args) (values-list args))) + +(defun exactly-one-p (&rest values) + "If exactly one value in VALUES is non-NIL, this value is returned. +Otherwise NIL is returned." + (let ((found nil)) + (dolist (v values) + (when v (if found + (return-from exactly-one-p nil) + (setq found v)))) + found)) + (defun valid-operator-symbol-p (symbol) "Is SYMBOL the name of a function, a macro, or a special-operator?" (or (fboundp symbol) @@ -24,6 +58,14 @@ (let ((symbol (parse-symbol string))) (valid-operator-symbol-p symbol))) +(defun valid-function-name-p (form) + (or (symbolp form) + (and (consp form) + (second form) + (not (third form)) + (eq (first form) 'setf) + (symbolp (second form))))) + (defslimefun arglist-for-echo-area (raw-specs &key arg-indices print-right-margin print-lines) "Return the arglist for the first valid ``form spec'' in @@ -243,6 +285,29 @@ (assert (= pos (length string))) (values sexp interned?))) +(defun read-softly-from-string (string) + "Returns three values: + + 1. the object resulting from READing STRING. + + 2. The index of the first character in STRING that was not read. + + 3. T if the object is a symbol that had to be newly interned + in some package. (This does not work for symbols in + compound forms like lists or vectors.)" + (multiple-value-bind (symbol found? symbol-name package) (parse-symbol string) + (if found? + (values symbol (length string) nil) + (multiple-value-bind (sexp pos) (read-from-string string) + (values sexp pos + (when (symbolp sexp) + (prog1 t + ;; assert that PARSE-SYMBOL didn't parse incorrectly. + (assert (and (equal symbol-name (symbol-name sexp)) + (eq package (symbol-package sexp))))))))))) + +(defun unintern-in-home-package (symbol) + (unintern symbol (symbol-package symbol))) (defstruct (arglist (:conc-name arglist.) (:predicate arglist-p)) provided-args ; list of the provided actual arguments @@ -1022,7 +1087,7 @@ (defgeneric arglist-dispatch (operator-type operator arguments &key remove-args)) -(defmethod arglist-dispatch (operator-type operator arguments &key (remove-args t)) +(defmethod arglist-dispatch ((operator-type t) operator arguments &key (remove-args t)) (when (and (symbolp operator) (valid-operator-symbol-p operator)) (multiple-value-bind (decoded-arglist determining-args any-enrichment) @@ -1075,7 +1140,7 @@ (defmethod arglist-dispatch ((operator-type (eql :function)) (operator (eql 'declare)) arguments &key (remove-args t)) ;; Catching 'DECLARE before SWANK-BACKEND:ARGLIST can barf. - (declare (ignore remove-args)) + (declare (ignore remove-args arguments)) (make-arglist :rest '#:decl-specifiers)) (defmethod arglist-dispatch ((operator-type (eql :declaration)) Modified: branches/trunk-reorg/thirdparty/slime/contrib/swank-fancy-inspector.lisp ============================================================================== --- branches/trunk-reorg/thirdparty/slime/contrib/swank-fancy-inspector.lisp (original) +++ branches/trunk-reorg/thirdparty/slime/contrib/swank-fancy-inspector.lisp Thu Feb 7 03:32:58 2008 @@ -6,12 +6,7 @@ (in-package :swank) -;; Subclass `backend-inspector' so that backend specific methods are -;; also considered. -(defclass fancy-inspector (backend-inspector) ()) - -(defmethod inspect-for-emacs ((symbol symbol) (inspector fancy-inspector)) - (declare (ignore inspector)) +(defmethod inspect-for-emacs ((symbol symbol)) (let ((package (symbol-package symbol))) (multiple-value-bind (_symbol status) (and package (find-symbol (string symbol) package)) @@ -94,8 +89,7 @@ (t (list label ": " '(:newline) " " docstring '(:newline)))))) -(defmethod inspect-for-emacs ((f function) inspector) - (declare (ignore inspector)) +(defmethod inspect-for-emacs ((f function)) (values "A function." (append (label-value-line "Name" (function-name f)) @@ -128,12 +122,11 @@ (swank-mop:method-qualifiers method) (method-specializers-for-inspect method))) -(defmethod inspect-for-emacs ((object standard-object) - (inspector fancy-inspector)) +(defmethod inspect-for-emacs ((object standard-object)) (let ((class (class-of object))) (values "An object." `("Class: " (:value ,class) (:newline) - ,@(all-slots-for-inspector object inspector))))) + ,@(all-slots-for-inspector object))))) (defvar *gf-method-getter* 'methods-by-applicability "This function is called to get the methods of a generic function. @@ -193,8 +186,8 @@ `(" " (:action "[make unbound]" ,(lambda () (swank-mop:slot-makunbound-using-class class object slot))))))))) -(defgeneric all-slots-for-inspector (object inspector) - (:method ((object standard-object) inspector) +(defgeneric all-slots-for-inspector (object) + (:method ((object standard-object)) (declare (ignore inspector)) (append '("--------------------" (:newline) "All Slots:" (:newline)) @@ -231,8 +224,7 @@ append slot-presentation collect '(:newline)))))) -(defmethod inspect-for-emacs ((gf standard-generic-function) - (inspector fancy-inspector)) +(defmethod inspect-for-emacs ((gf standard-generic-function)) (flet ((lv (label value) (label-value-line label value))) (values "A generic function." @@ -255,10 +247,9 @@ (remove-method gf m)))) (:newline))) `((:newline)) - (all-slots-for-inspector gf inspector))))) + (all-slots-for-inspector gf))))) -(defmethod inspect-for-emacs ((method standard-method) - (inspector fancy-inspector)) +(defmethod inspect-for-emacs ((method standard-method)) (values "A method." `("Method defined on the generic function " (:value ,(swank-mop:method-generic-function method) @@ -276,10 +267,9 @@ (:newline) "Method function: " (:value ,(swank-mop:method-function method)) (:newline) - ,@(all-slots-for-inspector method inspector)))) + ,@(all-slots-for-inspector method)))) -(defmethod inspect-for-emacs ((class standard-class) - (inspector fancy-inspector)) +(defmethod inspect-for-emacs ((class standard-class)) (values "A class." `("Name: " (:value ,(class-name class)) (:newline) @@ -336,10 +326,9 @@ `(:value ,(swank-mop:class-prototype class)) '"#") (:newline) - ,@(all-slots-for-inspector class inspector)))) + ,@(all-slots-for-inspector class)))) -(defmethod inspect-for-emacs ((slot swank-mop:standard-slot-definition) - (inspector fancy-inspector)) +(defmethod inspect-for-emacs ((slot swank-mop:standard-slot-definition)) (values "A slot." `("Name: " (:value ,(swank-mop:slot-definition-name slot)) (:newline) @@ -353,7 +342,7 @@ "#") (:newline) "Init function: " (:value ,(swank-mop:slot-definition-initfunction slot)) (:newline) - ,@(all-slots-for-inspector slot inspector)))) + ,@(all-slots-for-inspector slot)))) ;; Wrapper structure over the list of symbols of a package that should @@ -445,9 +434,7 @@ (:newline) ))))) -(defmethod inspect-for-emacs ((%container %package-symbols-container) - (inspector fancy-inspector)) - (declare (ignore inspector)) +(defmethod inspect-for-emacs ((%container %package-symbols-container)) (with-struct (%container. title description symbols grouping-kind) %container (values title `(, at description @@ -464,10 +451,7 @@ (:newline) (:newline) ,@(make-symbols-listing grouping-kind symbols))))) - -(defmethod inspect-for-emacs ((package package) - (inspector fancy-inspector)) - (declare (ignore inspector)) +(defmethod inspect-for-emacs ((package package)) (let ((package-name (package-name package)) (package-nicknames (package-nicknames package)) (package-use-list (package-use-list package)) @@ -561,9 +545,7 @@ :description nil))))))) -(defmethod inspect-for-emacs ((pathname pathname) - (inspector fancy-inspector)) - (declare (ignore inspector)) +(defmethod inspect-for-emacs ((pathname pathname)) (values (if (wild-pathname-p pathname) "A wild pathname." "A pathname.") @@ -579,9 +561,7 @@ (not (probe-file pathname))) (label-value-line "Truename" (truename pathname)))))) -(defmethod inspect-for-emacs ((pathname logical-pathname) - (inspector fancy-inspector)) - (declare (ignore inspector)) +(defmethod inspect-for-emacs ((pathname logical-pathname)) (values "A logical pathname." (append (label-value-line* @@ -601,9 +581,7 @@ ("Truename" (if (not (wild-pathname-p pathname)) (probe-file pathname))))))) -(defmethod inspect-for-emacs ((n number) - (inspector fancy-inspector)) - (declare (ignore inspector)) +(defmethod inspect-for-emacs ((n number)) (values "A number." `("Value: " ,(princ-to-string n)))) (defun format-iso8601-time (time-value &optional include-timezone-p) @@ -626,9 +604,7 @@ year month day hour minute second include-timezone-p (format-iso8601-timezone zone))))) -(defmethod inspect-for-emacs ((i integer) - (inspector fancy-inspector)) - (declare (ignore inspector)) +(defmethod inspect-for-emacs ((i integer)) (values "A number." (append `(,(format nil "Value: ~D = #x~8,'0X = #o~O = #b~,,' ,8:B~@[ = ~E~]" @@ -640,26 +616,20 @@ (ignore-errors (label-value-line "Universal-time" (format-iso8601-time i t)))))) -(defmethod inspect-for-emacs ((c complex) - (inspector fancy-inspector)) - (declare (ignore inspector)) +(defmethod inspect-for-emacs ((c complex)) (values "A complex number." (label-value-line* ("Real part" (realpart c)) ("Imaginary part" (imagpart c))))) -(defmethod inspect-for-emacs ((r ratio) - (inspector fancy-inspector)) - (declare (ignore inspector)) +(defmethod inspect-for-emacs ((r ratio)) (values "A non-integer ratio." (label-value-line* ("Numerator" (numerator r)) ("Denominator" (denominator r)) ("As float" (float r))))) -(defmethod inspect-for-emacs ((f float) - (inspector fancy-inspector)) - (declare (ignore inspector)) +(defmethod inspect-for-emacs ((f float)) (values "A floating point number." (cond ((> f most-positive-long-float) @@ -679,9 +649,7 @@ (label-value-line "Digits" (float-digits f)) (label-value-line "Precision" (float-precision f)))))))) -(defmethod inspect-for-emacs ((stream file-stream) - (inspector fancy-inspector)) - (declare (ignore inspector)) +(defmethod inspect-for-emacs ((stream file-stream)) (multiple-value-bind (title content) (call-next-method) (declare (ignore title)) @@ -699,9 +667,7 @@ (:newline)) content)))) -(defmethod inspect-for-emacs ((condition stream-error) - (inspector fancy-inspector)) - (declare (ignore inspector)) +(defmethod inspect-for-emacs ((condition stream-error)) (multiple-value-bind (title content) (call-next-method) (let ((stream (stream-error-stream condition))) @@ -724,14 +690,10 @@ (defvar *fancy-inpector-undo-list* nil) (defslimefun fancy-inspector-init () - (let ((i *default-inspector*)) - (push (lambda () (setq *default-inspector* i)) - *fancy-inpector-undo-list*)) - (setq *default-inspector* (make-instance 'fancy-inspector)) t) (defslimefun fancy-inspector-unload () (loop while *fancy-inpector-undo-list* do (funcall (pop *fancy-inpector-undo-list*)))) -(provide :swank-fancy-inspector) \ No newline at end of file +(provide :swank-fancy-inspector) Modified: branches/trunk-reorg/thirdparty/slime/contrib/swank-presentation-streams.lisp ============================================================================== --- branches/trunk-reorg/thirdparty/slime/contrib/swank-presentation-streams.lisp (original) +++ branches/trunk-reorg/thirdparty/slime/contrib/swank-presentation-streams.lisp Thu Feb 7 03:32:58 2008 @@ -210,6 +210,9 @@ (defun presenting-object-1 (object stream continue) "Uses the bridge mechanism with two messages >id and " 'sldb-end-of-backtrace) ("t" 'sldb-toggle-details) ("r" 'sldb-restart-frame) + ("I" 'sldb-invoke-restart-by-name) ("R" 'sldb-return-from-frame) ("c" 'sldb-continue) ("s" 'sldb-step) @@ -6573,23 +6587,14 @@ (define-key sldb-mode-map key command))))) ;; Keys 0-9 are shortcuts to invoke particular restarts. -(defmacro define-sldb-invoke-restart-key (number key) +(dotimes (number 10) (let ((fname (intern (format "sldb-invoke-restart-%S" number))) (docstring (format "Invoke restart numbered %S." number))) - `(progn - (defun ,fname () - ,docstring - (interactive) - (sldb-invoke-restart ,number)) - (define-key sldb-mode-map ,key ',fname)))) - -(defmacro define-sldb-invoke-restart-keys (from to) - `(progn - ,@(loop for n from from to to - collect `(define-sldb-invoke-restart-key ,n - ,(number-to-string n))))) - -(define-sldb-invoke-restart-keys 0 9) + (eval `(defun ,fname () + ,docstring + (interactive) + (sldb-invoke-restart ,number))) + (define-key sldb-mode-map (number-to-string number) fname))) ;;;;; SLDB buffer creation & update @@ -7223,6 +7228,14 @@ ((:ok value) (message "Restart returned: %s" value)) ((:abort))))) +(defun sldb-invoke-restart-by-name (restart-name) + (interactive (list (completing-read "Restart: " + sldb-restarts nil t + "" + 'sldb-invoke-restart-by-name))) + (sldb-invoke-restart (position restart-name sldb-restarts + :test 'string= :key 'first))) + (defun sldb-break-with-default-debugger () "Enter default debugger." (interactive) Modified: branches/trunk-reorg/thirdparty/slime/swank-abcl.lisp ============================================================================== --- branches/trunk-reorg/thirdparty/slime/swank-abcl.lisp (original) +++ branches/trunk-reorg/thirdparty/slime/swank-abcl.lisp Thu Feb 7 03:32:58 2008 @@ -421,14 +421,7 @@ ;;;; Inspecting -(defclass abcl-inspector (backend-inspector) ()) - -(defimplementation make-default-inspector () - (make-instance 'abcl-inspector)) - -(defmethod inspect-for-emacs ((slot mop::slot-definition) - (inspector backend-inspector)) - (declare (ignore inspector)) +(defmethod inspect-for-emacs ((slot mop::slot-definition)) (values "A slot." `("Name: " (:value ,(mop::%slot-definition-name slot)) (:newline) @@ -443,8 +436,7 @@ " Function: " (:value ,(mop::%slot-definition-initfunction slot)) (:newline)))) -(defmethod inspect-for-emacs ((f function) (inspector backend-inspector)) - (declare (ignore inspector)) +(defmethod inspect-for-emacs ((f function)) (values "A function." `(,@(when (function-name f) `("Name: " @@ -461,7 +453,7 @@ #| -(defmethod inspect-for-emacs ((o t) (inspector backend-inspector)) +(defmethod inspect-for-emacs ((o t)) (let* ((class (class-of o)) (slots (mop::class-slots class))) (values (format nil "~A~% is a ~A" o class) Modified: branches/trunk-reorg/thirdparty/slime/swank-allegro.lisp ============================================================================== --- branches/trunk-reorg/thirdparty/slime/swank-allegro.lisp (original) +++ branches/trunk-reorg/thirdparty/slime/swank-allegro.lisp Thu Feb 7 03:32:58 2008 @@ -564,13 +564,7 @@ ;;;; Inspecting -(defclass acl-inspector (backend-inspector) ()) - -(defimplementation make-default-inspector () - (make-instance 'acl-inspector)) - -(defmethod inspect-for-emacs ((f function) inspector) - inspector +(defmethod inspect-for-emacs ((f function)) (values "A function." (append (label-value-line "Name" (function-name f)) @@ -579,17 +573,13 @@ (when doc `("Documentation:" (:newline) ,doc)))))) -(defmethod inspect-for-emacs ((o t) (inspector backend-inspector)) - inspector +(defmethod inspect-for-emacs ((o t)) (values "A value." (allegro-inspect o))) -(defmethod inspect-for-emacs ((o function) (inspector backend-inspector)) - inspector +(defmethod inspect-for-emacs ((o function)) (values "A function." (allegro-inspect o))) -(defmethod inspect-for-emacs ((o standard-object) - (inspector backend-inspector)) - inspector +(defmethod inspect-for-emacs ((o standard-object)) (values (format nil "~A is a standard-object." o) (allegro-inspect o))) (defun allegro-inspect (o) Modified: branches/trunk-reorg/thirdparty/slime/swank-backend.lisp ============================================================================== --- branches/trunk-reorg/thirdparty/slime/swank-backend.lisp (original) +++ branches/trunk-reorg/thirdparty/slime/swank-backend.lisp Thu Feb 7 03:32:58 2008 @@ -840,26 +840,10 @@ ;;;; Inspector -(defclass inspector () - () - (:documentation "Super class of inspector objects. - -Implementations should sub class in order to dispatch off of the -inspect-for-emacs method.")) - -(defclass backend-inspector (inspector) ()) - -(definterface make-default-inspector () - "Return an inspector object suitable for passing to inspect-for-emacs.") - -(defgeneric inspect-for-emacs (object inspector) +(defgeneric inspect-for-emacs (object) (:documentation "Explain to Emacs how to inspect OBJECT. -The argument INSPECTOR is an object representing how to get at -the internals of OBJECT, it is usually an implementation specific -class used simply for dispatching to the proper method. - Returns two values: a string which will be used as the title of the inspector buffer and a list specifying how to render the object for inspection. @@ -880,12 +864,11 @@ NIL - do nothing.")) -(defmethod inspect-for-emacs ((object t) (inspector t)) +(defmethod inspect-for-emacs ((object t)) "Generic method for inspecting any kind of object. Since we don't know how to deal with OBJECT we simply dump the output of CL:DESCRIBE." - (declare (ignore inspector)) (values "A value." `("Type: " (:value ,(type-of object)) (:newline) Modified: branches/trunk-reorg/thirdparty/slime/swank-clisp.lisp ============================================================================== --- branches/trunk-reorg/thirdparty/slime/swank-clisp.lisp (original) +++ branches/trunk-reorg/thirdparty/slime/swank-clisp.lisp Thu Feb 7 03:32:58 2008 @@ -627,12 +627,7 @@ ;;;; Inspecting -(defclass clisp-inspector (backend-inspector) ()) - -(defimplementation make-default-inspector () (make-instance 'clisp-inspector)) - -(defmethod inspect-for-emacs ((o t) (inspector backend-inspector)) - (declare (ignore inspector)) +(defmethod inspect-for-emacs ((o t)) (let* ((*print-array* nil) (*print-pretty* t) (*print-circle* t) (*print-escape* t) (*print-lines* custom:*inspect-print-lines*) Modified: branches/trunk-reorg/thirdparty/slime/swank-cmucl.lisp ============================================================================== --- branches/trunk-reorg/thirdparty/slime/swank-cmucl.lisp (original) +++ branches/trunk-reorg/thirdparty/slime/swank-cmucl.lisp Thu Feb 7 03:32:58 2008 @@ -1869,7 +1869,7 @@ :key #'symbol-value))) (format t ", type: ~A" type-symbol)))))) -(defmethod inspect-for-emacs ((o t) (inspector backend-inspector)) +(defmethod inspect-for-emacs ((o t)) (cond ((di::indirect-value-cell-p o) (values (format nil "~A is a value cell." o) `("Value: " (:value ,(c:value-cell-ref o))))) @@ -1887,8 +1887,7 @@ (loop for value in parts for i from 0 append (label-value-line i value)))))) -(defmethod inspect-for-emacs ((o function) (inspector backend-inspector)) - (declare (ignore inspector)) +(defmethod inspect-for-emacs ((o function)) (let ((header (kernel:get-type o))) (cond ((= header vm:function-header-type) (values (format nil "~A is a function." o) @@ -1915,9 +1914,7 @@ (t (call-next-method))))) -(defmethod inspect-for-emacs ((o kernel:funcallable-instance) - (i backend-inspector)) - (declare (ignore i)) +(defmethod inspect-for-emacs ((o kernel:funcallable-instance)) (values (format nil "~A is a funcallable-instance." o) (append (label-value-line* @@ -1926,8 +1923,7 @@ (:layout (kernel:%funcallable-instance-layout o))) (nth-value 1 (cmucl-inspect o))))) -(defmethod inspect-for-emacs ((o kernel:code-component) (_ backend-inspector)) - (declare (ignore _)) +(defmethod inspect-for-emacs ((o kernel:code-component)) (values (format nil "~A is a code data-block." o) (append (label-value-line* @@ -1954,8 +1950,7 @@ (ash (kernel:%code-code-size o) vm:word-shift) :stream s)))))))) -(defmethod inspect-for-emacs ((o kernel:fdefn) (inspector backend-inspector)) - (declare (ignore inspector)) +(defmethod inspect-for-emacs ((o kernel:fdefn)) (values (format nil "~A is a fdenf object." o) (label-value-line* ("name" (kernel:fdefn-name o)) @@ -1964,8 +1959,7 @@ (sys:int-sap (kernel:get-lisp-obj-address o)) (* vm:fdefn-raw-addr-slot vm:word-bytes)))))) -(defmethod inspect-for-emacs ((o array) (inspector backend-inspector)) - inspector +(defmethod inspect-for-emacs ((o array)) (if (typep o 'simple-array) (call-next-method) (values (format nil "~A is an array." o) @@ -1980,8 +1974,7 @@ (:displaced-p (kernel:%array-displaced-p o)) (:dimensions (array-dimensions o)))))) -(defmethod inspect-for-emacs ((o simple-vector) (inspector backend-inspector)) - inspector +(defmethod inspect-for-emacs ((o simple-vector)) (values (format nil "~A is a simple-vector." o) (append (label-value-line* Modified: branches/trunk-reorg/thirdparty/slime/swank-corman.lisp ============================================================================== --- branches/trunk-reorg/thirdparty/slime/swank-corman.lisp (original) +++ branches/trunk-reorg/thirdparty/slime/swank-corman.lisp Thu Feb 7 03:32:58 2008 @@ -387,21 +387,13 @@ ;; Hack to make swank.lisp load, at least (defclass file-stream ()) -(defclass corman-inspector (backend-inspector) - ()) - -(defimplementation make-default-inspector () - (make-instance 'corman-inspector)) - (defun comma-separated (list &optional (callback (lambda (v) `(:value ,v)))) (butlast (loop for e in list collect (funcall callback e) collect ", "))) -(defmethod inspect-for-emacs ((class standard-class) - (inspector backend-inspector)) - (declare (ignore inspector)) +(defmethod inspect-for-emacs ((class standard-class)) (values "A class." `("Name: " (:value ,(class-name class)) (:newline) @@ -438,9 +430,8 @@ '("#")) (:newline)))) -(defmethod inspect-for-emacs ((slot cons) (inspector backend-inspector)) +(defmethod inspect-for-emacs ((slot cons)) ;; Inspects slot definitions - (declare (ignore inspector)) (if (eq (car slot) :name) (values "A slot." `("Name: " (:value ,(swank-mop:slot-definition-name slot)) @@ -457,9 +448,7 @@ (:newline))) (call-next-method))) -(defmethod inspect-for-emacs ((pathname pathnames::pathname-internal) - inspector) - (declare (ignore inspector)) +(defmethod inspect-for-emacs ((pathname pathnames::pathname-internal)) (values (if (wild-pathname-p pathname) "A wild pathname." "A pathname.") @@ -475,7 +464,7 @@ (not (probe-file pathname))) (label-value-line "Truename" (truename pathname)))))) -(defmethod inspect-for-emacs ((o t) (inspector backend-inspector)) +(defmethod inspect-for-emacs ((o t)) (cond ((cl::structurep o) (inspect-structure o)) (t (call-next-method)))) Modified: branches/trunk-reorg/thirdparty/slime/swank-ecl.lisp ============================================================================== --- branches/trunk-reorg/thirdparty/slime/swank-ecl.lisp (original) +++ branches/trunk-reorg/thirdparty/slime/swank-ecl.lisp Thu Feb 7 03:32:58 2008 @@ -248,13 +248,7 @@ ;;;; Inspector -(defclass ecl-inspector (inspector) - ()) - -(defimplementation make-default-inspector () - (make-instance 'ecl-inspector)) - -(defmethod inspect-for-emacs ((o t) (inspector backend-inspector)) +(defmethod inspect-for-emacs ((o t)) ; ecl clos support leaves some to be desired (cond ((streamp o) Modified: branches/trunk-reorg/thirdparty/slime/swank-lispworks.lisp ============================================================================== --- branches/trunk-reorg/thirdparty/slime/swank-lispworks.lisp (original) +++ branches/trunk-reorg/thirdparty/slime/swank-lispworks.lisp Thu Feb 7 03:32:58 2008 @@ -629,20 +629,15 @@ (defimplementation make-default-inspector () (make-instance 'lispworks-inspector)) -(defmethod inspect-for-emacs ((o t) (inspector backend-inspector)) - (declare (ignore inspector)) +(defmethod inspect-for-emacs ((o t)) (lispworks-inspect o)) -(defmethod inspect-for-emacs ((o function) - (inspector backend-inspector)) - (declare (ignore inspector)) +(defmethod inspect-for-emacs ((o function)) (lispworks-inspect o)) ;; FIXME: slot-boundp-using-class in LW works with names so we can't ;; use our method in swank.lisp. -(defmethod inspect-for-emacs ((o standard-object) - (inspector backend-inspector)) - (declare (ignore inspector)) +(defmethod inspect-for-emacs ((o standard-object)) (lispworks-inspect o)) (defun lispworks-inspect (o) Modified: branches/trunk-reorg/thirdparty/slime/swank-loader.lisp ============================================================================== --- branches/trunk-reorg/thirdparty/slime/swank-loader.lisp (original) +++ branches/trunk-reorg/thirdparty/slime/swank-loader.lisp Thu Feb 7 03:32:58 2008 @@ -18,6 +18,12 @@ ;; (defparameter swank-loader::*fasl-directory* "/tmp/fasl/") ;; (load ".../swank-loader.lisp") +(eval-when (:compile-toplevel :load-toplevel :execute) + (when (find-package :swank) + (delete-package :swank) + (delete-package :swank-io-package) + (delete-package :swank-backend))) + (cl:defpackage :swank-loader (:use :cl) (:export :load-swank @@ -60,14 +66,9 @@ :sparc64 :sparc :hppa64 :hppa)) (defun lisp-version-string () - #+cmu (substitute-if #\_ (lambda (x) (find x " /")) + #+(or openmcl cmu) (substitute-if #\_ (lambda (x) (find x " /")) (lisp-implementation-version)) - #+scl (lisp-implementation-version) - #+sbcl (lisp-implementation-version) - #+ecl (lisp-implementation-version) - #+openmcl (format nil "~d.~d" - ccl::*openmcl-major-version* - ccl::*openmcl-minor-version*) + #+(or cormanlisp scl sbcl ecl) (lisp-implementation-version) #+lispworks (lisp-implementation-version) #+allegro (format nil "~A~A~A" @@ -76,8 +77,7 @@ (if (member :64bit *features*) "-64bit" "")) #+clisp (let ((s (lisp-implementation-version))) (subseq s 0 (position #\space s))) - #+armedbear (lisp-implementation-version) - #+cormanlisp (lisp-implementation-version)) + #+armedbear (lisp-implementation-version)) (defun unique-directory-name () "Return a name that can be used as a directory name that is Modified: branches/trunk-reorg/thirdparty/slime/swank-openmcl.lisp ============================================================================== --- branches/trunk-reorg/thirdparty/slime/swank-openmcl.lisp (original) +++ branches/trunk-reorg/thirdparty/slime/swank-openmcl.lisp Thu Feb 7 03:32:58 2008 @@ -211,14 +211,18 @@ (defvar *break-in-sldb* t) + (let ((ccl::*warn-if-redefine-kernel* nil)) - (ccl::advise - cl::break + (ccl::advise + ccl::cbreak-loop (if (and *break-in-sldb* - (find ccl::*current-process* (symbol-value (intern "*CONNECTIONS*" 'swank)) - :key (intern "CONNECTION.REPL-THREAD" 'swank))) + (find ccl::*current-process* + (symbol-value (intern (string :*connections*) :swank)) + :key (intern (string :connection.repl-thread) :swank))) (apply 'break-in-sldb ccl::arglist) - (:do-it)) :when :around :name sldb-break)) + (:do-it)) + :when :around + :name sldb-break)) (defun break-in-sldb (&optional string &rest args) (let ((c (make-condition 'simple-condition @@ -335,8 +339,7 @@ for (value nil name) = (multiple-value-list (ccl::nth-value-in-frame p count context lfun pc vsp parent-vsp)) when name do (incf varcount) until (= varcount var) - finally (return value)) - ))))))) + finally (return value))))))))) (defun xref-locations (relation name &optional (inverse nil)) (flet ((function-source-location (entry) @@ -345,8 +348,8 @@ (ccl::%db-key-from-xref-entry entry) (if (eql (ccl::xref-entry-type entry) 'macro) - 'function - (ccl::xref-entry-type entry))) + 'function + (ccl::xref-entry-type entry))) (cond ((not info) (list :error (format nil "No source info available for ~A" @@ -466,7 +469,8 @@ (setq ccl::*fasl-save-definitions* nil) (setq ccl::*fasl-save-doc-strings* t) (setq ccl::*fasl-save-local-symbols* t) - (setq ccl::*ppc2-compiler-register-save-label* t) + #+ppc (setq ccl::*ppc2-compiler-register-save-label* t) + #+x86-64 (setq ccl::*x862-compiler-register-save-label* t) (setq ccl::*save-arglist-info* t) (setq ccl::*save-definitions* nil) (setq ccl::*save-doc-strings* t) @@ -513,9 +517,8 @@ (defun frame-arguments (p context lfun pc) "Returns a string representing the arguments of a frame." - (multiple-value-bind (args types names count nclosed) + (multiple-value-bind (args types names) (ccl::frame-supplied-args p lfun pc nil context) - (declare (ignore count nclosed)) (let ((result nil)) (loop named loop for var = (cond @@ -575,7 +578,9 @@ (push (list :name name :id 0 - :value var) + :value (if (typep var 'ccl::value-cell) + (ccl::uvref var 0) + var)) result)))) (return-from frame-locals (nreverse result))))))))) @@ -610,19 +615,24 @@ (when (= frame-number the-frame-number) (setq function-to-disassemble lfun) (return-from find-frame))))) - (ccl::print-ppc-instructions - *standard-output* - (ccl::function-to-dll-header function-to-disassemble) nil))) + #+ppc (ccl::print-ppc-instructions + *standard-output* + (ccl::function-to-dll-header function-to-disassemble) + nil) + #+x86-64 (ccl::x8664-xdisassemble function-to-disassemble))) ;;; -(defun canonicalize-location (file symbol) +(defun canonicalize-location (file symbol &optional snippet) (etypecase file ((or string pathname) (multiple-value-bind (truename c) (ignore-errors (namestring (truename file))) (cond (c (list :error (princ-to-string c))) (t (make-location (list :file (remove-filename-quoting truename)) - (list :function-name (princ-to-string symbol))))))))) + (list :function-name (princ-to-string symbol)) + (if snippet + (list :snippet snippet) + '())))))))) (defun remove-filename-quoting (string) (if (search "\\" string) @@ -644,20 +654,20 @@ (list (list type symbol) (canonicalize-location file symbol)))))) - (defun function-source-location (function) - (multiple-value-bind (info name) (ccl::edit-definition-p function) + (multiple-value-bind (info name) + (ccl::edit-definition-p function) (cond ((not info) (list :error (format nil "No source info available for ~A" function))) ((typep (caar info) 'ccl::method) `(:location (:file ,(remove-filename-quoting (namestring (translate-logical-pathname (cdr (car info))) ))) (:method ,(princ-to-string (ccl::method-name (caar info))) - ,(mapcar 'princ-to-string - (mapcar #'specializer-name - (ccl::method-specializers (caar info)))) - ,@(mapcar 'princ-to-string (ccl::method-qualifiers (caar info)))) + ,(mapcar 'princ-to-string + (mapcar #'specializer-name + (ccl::method-specializers (caar info)))) + ,@(mapcar 'princ-to-string (ccl::method-qualifiers (caar info)))) nil)) - (t (canonicalize-location (cdr (first info)) name))))) + (t (canonicalize-location (second (first info)) name (third (first info))))))) (defimplementation frame-source-location-for-emacs (index) "Return to Emacs the location of the source code for the @@ -693,6 +703,7 @@ ,form))) ))))))) +#+ppc (defimplementation return-from-frame (index form) (let ((values (multiple-value-list (eval-in-frame form index)))) (map-backtrace @@ -700,7 +711,8 @@ (declare (ignore context lfun pc)) (when (= frame-number index) (ccl::apply-in-frame p #'values values)))))) - + +#+ppc (defimplementation restart-frame (index) (map-backtrace (lambda (frame-number p context lfun pc) @@ -784,19 +796,13 @@ ;;;; Inspection -(defclass openmcl-inspector (backend-inspector) ()) - -(defimplementation make-default-inspector () - (make-instance 'openmcl-inspector)) - (defimplementation describe-primitive-type (thing) (let ((typecode (ccl::typecode thing))) (if (gethash typecode *value2tag*) (string (gethash typecode *value2tag*)) (string (nth typecode '(tag-fixnum tag-list tag-misc tag-imm)))))) -(defmethod inspect-for-emacs ((o t) (inspector backend-inspector)) - (declare (ignore inspector)) +(defmethod inspect-for-emacs ((o t)) (let* ((i (inspector::make-inspector o)) (count (inspector::compute-line-count i)) (lines @@ -814,7 +820,7 @@ (pprint o s))) lines))) -(defmethod inspect-for-emacs :around ((o t) (inspector backend-inspector)) +(defmethod inspect-for-emacs :around ((o t)) (if (or (uvector-inspector-p o) (not (ccl:uvectorp o))) (call-next-method) @@ -834,8 +840,7 @@ (:method ((object t)) nil) (:method ((object uvector-inspector)) t)) -(defmethod inspect-for-emacs ((uv uvector-inspector) - (inspector backend-inspector)) +(defmethod inspect-for-emacs ((uv uvector-inspector)) (with-slots (object) uv (values (format nil "The UVECTOR for ~S." object) @@ -855,8 +860,7 @@ (cellp (ccl::closed-over-value-p value))) (list label (if cellp (ccl::closed-over-value value) value)))))) -(defmethod inspect-for-emacs ((c ccl::compiled-lexical-closure) (inspector t)) - (declare (ignore inspector)) +(defmethod inspect-for-emacs ((c ccl::compiled-lexical-closure)) (values (format nil "A closure: ~a" c) `(,@(if (arglist c) Modified: branches/trunk-reorg/thirdparty/slime/swank-sbcl.lisp ============================================================================== --- branches/trunk-reorg/thirdparty/slime/swank-sbcl.lisp (original) +++ branches/trunk-reorg/thirdparty/slime/swank-sbcl.lisp Thu Feb 7 03:32:58 2008 @@ -1001,13 +1001,7 @@ ;;;; Inspector -(defclass sbcl-inspector (backend-inspector) ()) - -(defimplementation make-default-inspector () - (make-instance 'sbcl-inspector)) - -(defmethod inspect-for-emacs ((o t) (inspector backend-inspector)) - (declare (ignore inspector)) +(defmethod inspect-for-emacs ((o t)) (cond ((sb-di::indirect-value-cell-p o) (values "A value cell." (label-value-line* (:value (sb-kernel:value-cell-ref o))))) @@ -1019,8 +1013,7 @@ (values text (loop for value in parts for i from 0 append (label-value-line i value)))))))) -(defmethod inspect-for-emacs ((o function) (inspector backend-inspector)) - (declare (ignore inspector)) +(defmethod inspect-for-emacs ((o function)) (let ((header (sb-kernel:widetag-of o))) (cond ((= header sb-vm:simple-fun-header-widetag) (values "A simple-fun." @@ -1041,8 +1034,7 @@ i (sb-kernel:%closure-index-ref o i)))))) (t (call-next-method o))))) -(defmethod inspect-for-emacs ((o sb-kernel:code-component) (_ backend-inspector)) - (declare (ignore _)) +(defmethod inspect-for-emacs ((o sb-kernel:code-component)) (values (format nil "~A is a code data-block." o) (append (label-value-line* @@ -1070,22 +1062,18 @@ (ash (sb-kernel:%code-code-size o) sb-vm:word-shift) :stream s)))))))) -(defmethod inspect-for-emacs ((o sb-ext:weak-pointer) (inspector backend-inspector)) - (declare (ignore inspector)) +(defmethod inspect-for-emacs ((o sb-ext:weak-pointer)) (values "A weak pointer." (label-value-line* (:value (sb-ext:weak-pointer-value o))))) -(defmethod inspect-for-emacs ((o sb-kernel:fdefn) (inspector backend-inspector)) - (declare (ignore inspector)) +(defmethod inspect-for-emacs ((o sb-kernel:fdefn)) (values "A fdefn object." (label-value-line* (:name (sb-kernel:fdefn-name o)) (:function (sb-kernel:fdefn-fun o))))) -(defmethod inspect-for-emacs :around ((o generic-function) - (inspector backend-inspector)) - (declare (ignore inspector)) +(defmethod inspect-for-emacs :around ((o generic-function)) (multiple-value-bind (title contents) (call-next-method) (values title (append Modified: branches/trunk-reorg/thirdparty/slime/swank-scl.lisp ============================================================================== --- branches/trunk-reorg/thirdparty/slime/swank-scl.lisp (original) +++ branches/trunk-reorg/thirdparty/slime/swank-scl.lisp Thu Feb 7 03:32:58 2008 @@ -1740,7 +1740,7 @@ :key #'symbol-value))) (format t ", type: ~A" type-symbol)))))) -(defmethod inspect-for-emacs ((o t) (inspector backend-inspector)) +(defmethod inspect-for-emacs ((o t)) (cond ((di::indirect-value-cell-p o) (values (format nil "~A is a value cell." o) `("Value: " (:value ,(c:value-cell-ref o))))) @@ -1759,8 +1759,7 @@ (loop for value in parts for i from 0 append (label-value-line i value)))))) -(defmethod inspect-for-emacs ((o function) (inspector backend-inspector)) - (declare (ignore inspector)) +(defmethod inspect-for-emacs ((o function)) (let ((header (kernel:get-type o))) (cond ((= header vm:function-header-type) (values (format nil "~A is a function." o) @@ -1789,8 +1788,7 @@ (call-next-method))))) -(defmethod inspect-for-emacs ((o kernel:code-component) (_ backend-inspector)) - (declare (ignore _)) +(defmethod inspect-for-emacs ((o kernel:code-component)) (values (format nil "~A is a code data-block." o) (append (label-value-line* @@ -1817,8 +1815,7 @@ (ash (kernel:%code-code-size o) vm:word-shift) :stream s)))))))) -(defmethod inspect-for-emacs ((o kernel:fdefn) (inspector backend-inspector)) - (declare (ignore inspector)) +(defmethod inspect-for-emacs ((o kernel:fdefn)) (values (format nil "~A is a fdenf object." o) (label-value-line* ("name" (kernel:fdefn-name o)) @@ -1827,8 +1824,7 @@ (sys:int-sap (kernel:get-lisp-obj-address o)) (* vm:fdefn-raw-addr-slot vm:word-bytes)))))) -(defmethod inspect-for-emacs ((o array) (inspector backend-inspector)) - inspector +(defmethod inspect-for-emacs ((o array)) (cond ((kernel:array-header-p o) (values (format nil "~A is an array." o) (label-value-line* @@ -1847,8 +1843,7 @@ (:header (describe-primitive-type o)) (:length (length o))))))) -(defmethod inspect-for-emacs ((o simple-vector) (inspector backend-inspector)) - inspector +(defmethod inspect-for-emacs ((o simple-vector)) (values (format nil "~A is a vector." o) (append (label-value-line* Modified: branches/trunk-reorg/thirdparty/slime/swank.lisp ============================================================================== --- branches/trunk-reorg/thirdparty/slime/swank.lisp (original) +++ branches/trunk-reorg/thirdparty/slime/swank.lisp Thu Feb 7 03:32:58 2008 @@ -415,43 +415,6 @@ (<= (char-code c) 127)) -;;;;; Misc - -(defun length= (seq n) - "Test for whether SEQ contains N number of elements. I.e. it's equivalent - to (= (LENGTH SEQ) N), but besides being more concise, it may also be more - efficiently implemented." - (etypecase seq - (list (do ((i n (1- i)) - (list seq (cdr list))) - ((or (<= i 0) (null list)) - (and (zerop i) (null list))))) - (sequence (= (length seq) n)))) - -(defun ensure-list (thing) - (if (listp thing) thing (list thing))) - -(defun recursively-empty-p (list) - "Returns whether LIST consists only of arbitrarily nested empty lists." - (cond ((not (listp list)) nil) - ((null list) t) - (t (every #'recursively-empty-p list)))) - -(defun maybecall (bool fn &rest args) - "Call FN with ARGS if BOOL is T. Otherwise return ARGS as multiple values." - (if bool (apply fn args) (values-list args))) - -(defun exactly-one-p (&rest values) - "If exactly one value in VALUES is non-NIL, this value is returned. -Otherwise NIL is returned." - (let ((found nil)) - (dolist (v values) - (when v (if found - (return-from exactly-one-p nil) - (setq found v)))) - found)) - - ;;;;; Symbols (defun symbol-status (symbol &optional (package (symbol-package symbol))) @@ -1569,30 +1532,6 @@ (let ((*read-suppress* nil)) (read-from-string string)))) -(defun read-softly-from-string (string) - "Returns three values: - - 1. the object resulting from READing STRING. - - 2. The index of the first character in STRING that was not read. - - 3. T if the object is a symbol that had to be newly interned - in some package. (This does not work for symbols in - compound forms like lists or vectors.)" - (multiple-value-bind (symbol found? symbol-name package) (parse-symbol string) - (if found? - (values symbol (length string) nil) - (multiple-value-bind (sexp pos) (read-from-string string) - (values sexp pos - (when (symbolp sexp) - (prog1 t - ;; assert that PARSE-SYMBOL didn't parse incorrectly. - (assert (and (equal symbol-name (symbol-name sexp)) - (eq package (symbol-package sexp))))))))))) - -(defun unintern-in-home-package (symbol) - (unintern symbol (symbol-package symbol))) - ;; FIXME: deal with #\| etc. hard to do portably. (defun tokenize-symbol (string) "STRING is interpreted as the string representation of a symbol @@ -1755,7 +1694,7 @@ (with-buffer-syntax () (let ((*print-readably* nil)) (cond ((null values) "; No value") - ((and (length= values 1) (integerp (car values))) + ((and (integerp (car values)) (null (cdr values))) (let ((i (car values))) (format nil "~A~D (#x~X, #o~O, #b~B)" *echo-area-prefix* i i i i))) @@ -2056,12 +1995,15 @@ ,(princ-to-string real-condition)))) (throw 'sldb-loop-catcher nil)) +(defvar *sldb-condition-printer* #'format-sldb-condition + "Function called to print a condition to an SLDB buffer.") + (defun safe-condition-message (condition) "Safely print condition to a string, handling any errors during printing." (let ((*print-pretty* t) (*print-right-margin* 65)) (handler-case - (format-sldb-condition condition) + (funcall *sldb-condition-printer* condition) (error (cond) ;; Beware of recursive errors in printing, so only use the condition ;; if it is printable itself: @@ -2750,8 +2692,7 @@ (set-pprint-dispatch '(cons (member function)) nil) (princ-to-string list))) -(defmethod inspect-for-emacs ((object cons) inspector) - (declare (ignore inspector)) +(defmethod inspect-for-emacs ((object cons)) (if (consp (cdr object)) (inspect-for-emacs-list object) (inspect-for-emacs-simple-cons object))) @@ -2811,8 +2752,7 @@ a hash table or array to show by default. If table has more than this then offer actions to view more. Set to nil for no limit." ) -(defmethod inspect-for-emacs ((ht hash-table) inspector) - (declare (ignore inspector)) +(defmethod inspect-for-emacs ((ht hash-table)) (values (prin1-to-string ht) (append (label-value-line* @@ -2864,8 +2804,7 @@ (progn (format t "How many elements should be shown? ") (read)))) (swank::inspect-object thing))))) -(defmethod inspect-for-emacs ((array array) inspector) - (declare (ignore inspector)) +(defmethod inspect-for-emacs ((array array)) (values "An array." (append (label-value-line* @@ -2883,8 +2822,7 @@ (loop for i below (or *slime-inspect-contents-limit* (array-total-size array)) append (label-value-line i (row-major-aref array i)))))) -(defmethod inspect-for-emacs ((char character) inspector) - (declare (ignore inspector)) +(defmethod inspect-for-emacs ((char character)) (values "A character." (append (label-value-line* @@ -2903,7 +2841,6 @@ (defvar *inspector-history* (make-array 10 :adjustable t :fill-pointer 0)) (declaim (type vector *inspector-history*)) (defvar *inspect-length* 30) -(defvar *default-inspector* (make-default-inspector)) (defun reset-inspector () (setq *inspectee* nil @@ -2912,14 +2849,6 @@ *inspectee-actions* (make-array 10 :adjustable t :fill-pointer 0) *inspector-history* (make-array 10 :adjustable t :fill-pointer 0))) -(defun valid-function-name-p (form) - (or (symbolp form) - (and (consp form) - (second form) - (not (third form)) - (eq (first form) 'setf) - (symbolp (second form))))) - (defslimefun init-inspector (string) (with-buffer-syntax () (reset-inspector) @@ -2960,14 +2889,14 @@ (list :action label (assign-index (list lambda refreshp) *inspectee-actions*))) -(defun inspect-object (object &optional (inspector *default-inspector*)) +(defun inspect-object (object) (push (setq *inspectee* object) *inspector-stack*) (unless (find object *inspector-history*) (vector-push-extend object *inspector-history*)) (let ((*print-pretty* nil) ; print everything in the same line (*print-circle* t) (*print-readably* nil)) - (multiple-value-bind (_ content) (inspect-for-emacs object inspector) + (multiple-value-bind (_ content) (inspect-for-emacs object) (declare (ignore _)) (list :title (with-output-to-string (s) (print-unreadable-object (object s :type t :identity t))) From ksprotte at common-lisp.net Fri Feb 8 14:45:58 2008 From: ksprotte at common-lisp.net (ksprotte at common-lisp.net) Date: Fri, 8 Feb 2008 09:45:58 -0500 (EST) Subject: [bknr-cvs] r2453 - branches/bos/projects/bos/m2 Message-ID: <20080208144558.A23F6610BD@common-lisp.net> Author: ksprotte Date: Fri Feb 8 09:45:54 2008 New Revision: 2453 Modified: branches/bos/projects/bos/m2/geometry.lisp Log: added new function: FORMAT-LON-LAT Modified: branches/bos/projects/bos/m2/geometry.lisp ============================================================================== --- branches/bos/projects/bos/m2/geometry.lisp (original) +++ branches/bos/projects/bos/m2/geometry.lisp Fri Feb 8 09:45:54 2008 @@ -214,3 +214,56 @@ (traverse boundary-point initial-direction) (nreverse polygon)))) + +;;; formatting +;; proposed by Michael Weber on alexandria-devel +(defun format-mixed-radix-number (stream number radix-list format-list + &key lsb-first leading-zeros + (trailing-zeros t)) + "Prints NUMBER to STREAM in mixed-radix RADIX. +representation-LIST is a list of radixes, least-significant first. +FORMAT-LIST is a list of format directives, one for each digit. +When LSB-FIRST is nil (default), print most-significant digit first, +otherwise least-significant digit first. +When LEADING-ZEROS and TRAILING-ZEROS are nil, leading and +trailing zero digits are not printed, respectively. \(default: remove +leading zeros, keep trailing zeros)" + (let ((format-pairs + (loop with digit and fraction + initially (setf (values number fraction) + (truncate number)) + for f-list on format-list + and r-list = radix-list then (rest r-list) + collect (list (first f-list) + (cond ((endp r-list) + (shiftf number 0)) + ((rest f-list) + (setf (values number digit) + (truncate number (first r-list))) + digit) + (t number))) + into list + finally (progn + (incf (cadar list) fraction) + (return (nreverse list)))))) + (unless trailing-zeros + (setf format-pairs (member-if #'plusp format-pairs :key + #'second))) + (when lsb-first + (setf format-pairs (nreverse format-pairs))) + (unless leading-zeros + (setf format-pairs (member-if #'plusp format-pairs :key + #'second))) + (format stream "~{~{~@?~}~}" format-pairs))) + + +(defun format-decimal-degree (degree) + (format-mixed-radix-number nil (* 60 degree) '(60 360) '("~,2F?" "~D?"))) + +(defun format-lon-lat (lon lat) + (format nil "~A ~:[S~;N~], ~A~:[W~;E~]" + (format-decimal-degree (abs lat)) + (plusp lat) + (format-decimal-degree (abs lon)) + (plusp lon))) + From ksprotte at common-lisp.net Fri Feb 8 15:36:04 2008 From: ksprotte at common-lisp.net (ksprotte at common-lisp.net) Date: Fri, 8 Feb 2008 10:36:04 -0500 (EST) Subject: [bknr-cvs] r2454 - branches/bos/projects/bos/m2 Message-ID: <20080208153604.D76111C003@common-lisp.net> Author: ksprotte Date: Fri Feb 8 10:36:04 2008 New Revision: 2454 Modified: branches/bos/projects/bos/m2/geometry.lisp branches/bos/projects/bos/m2/make-certificate.lisp branches/bos/projects/bos/m2/packages.lisp Log: Geo-Koordinaten im PDF anzeigen #5 done (Template still needs to be changed in Acrobat for larger font) Modified: branches/bos/projects/bos/m2/geometry.lisp ============================================================================== --- branches/bos/projects/bos/m2/geometry.lisp (original) +++ branches/bos/projects/bos/m2/geometry.lisp Fri Feb 8 10:36:04 2008 @@ -258,10 +258,10 @@ (defun format-decimal-degree (degree) - (format-mixed-radix-number nil (* 60 degree) '(60 360) '("~,2F?" "~D?"))) + (format-mixed-radix-number nil (* 60 60 degree) '(60 60 360) '(" ~,2F????" " ~D??" "~D??"))) -(defun format-lon-lat (lon lat) - (format nil "~A ~:[S~;N~], ~A~:[W~;E~]" +(defun format-lon-lat (stream lon lat) + (format stream "~A ~:[S~;N~], ~A ~:[W~;E~]" (format-decimal-degree (abs lat)) (plusp lat) (format-decimal-degree (abs lon)) Modified: branches/bos/projects/bos/m2/make-certificate.lisp ============================================================================== --- branches/bos/projects/bos/m2/make-certificate.lisp (original) +++ branches/bos/projects/bos/m2/make-certificate.lisp Fri Feb 8 10:36:04 2008 @@ -42,8 +42,19 @@ :sponsor-id (sponsor-id sponsor) :master-code (sponsor-master-code sponsor) :sqm-count (length (contract-m2s contract)) - :sqm-ids (with-output-to-string (s) - (loop for group in (group-by (mapcar #'m2-num-string (contract-m2s contract)) *num-coords-per-line*) - do (loop for nums on group - do (princ (car nums) s) - do (princ (if (cdr nums) #\Tab #\Newline) s))))))) + ;; :sqm-ids (with-output-to-string (s) + ;; (loop for group in (group-by (mapcar #'m2-num-string (contract-m2s contract)) *num-coords-per-line*) + ;; do (loop for nums on group + ;; do (princ (car nums) s) + ;; do (princ (if (cdr nums) #\Tab #\Newline) s)))) + ;; should later be called :sqm-coordinates + :sqm-ids + (flet ((format-point (stream x y) + (apply #'geometry:format-lon-lat stream + (geo-utm:utm-x-y-to-lon-lat (+ +nw-utm-x+ x) + (- +nw-utm-y+ y) +utm-zone+ t)))) + (destructuring-bind (left top width height) + (contract-bounding-box contract) + (with-output-to-string (out) + (format-point out left top) (terpri out) + (format-point out (+ left width) (+ top height)) (terpri out))))))) Modified: branches/bos/projects/bos/m2/packages.lisp ============================================================================== --- branches/bos/projects/bos/m2/packages.lisp (original) +++ branches/bos/projects/bos/m2/packages.lisp Fri Feb 8 10:36:04 2008 @@ -9,7 +9,8 @@ #:point-in-polygon-p #:point-in-circle-p #:find-boundary-point - #:region-to-polygon)) + #:region-to-polygon + #:format-lon-lat)) (defpackage :geo-utm (:use :cl) From hhubner at common-lisp.net Sun Feb 10 09:02:46 2008 From: hhubner at common-lisp.net (hhubner at common-lisp.net) Date: Sun, 10 Feb 2008 04:02:46 -0500 (EST) Subject: [bknr-cvs] r2455 - branches/trunk-reorg/bknr/web/src/web Message-ID: <20080210090246.8D2BF2F069@common-lisp.net> Author: hhubner Date: Sun Feb 10 04:02:46 2008 New Revision: 2455 Modified: branches/trunk-reorg/bknr/web/src/web/handlers.lisp Log: fix syntax error that has not been detected by cmucl Modified: branches/trunk-reorg/bknr/web/src/web/handlers.lisp ============================================================================== --- branches/trunk-reorg/bknr/web/src/web/handlers.lisp (original) +++ branches/trunk-reorg/bknr/web/src/web/handlers.lisp Sun Feb 10 04:02:46 2008 @@ -406,8 +406,8 @@ (defgeneric object-date-list-handler-grouped-objects (handler object)) -(defmethod object-date-list-handler-date ((handler object-date-list-handler object-list-handler) - object) +(defmethod object-date-list-handler-date ((handler object-date-list-handler) + object) (with-query-params (date) (get-daytime (if date (or (parse-integer date :junk-allowed t) From hhubner at common-lisp.net Sun Feb 10 22:35:24 2008 From: hhubner at common-lisp.net (hhubner at common-lisp.net) Date: Sun, 10 Feb 2008 17:35:24 -0500 (EST) Subject: [bknr-cvs] r2456 - branches/trunk-reorg/bknr/datastore/src/skip-list Message-ID: <20080210223524.848A62D07C@common-lisp.net> Author: hhubner Date: Sun Feb 10 17:35:23 2008 New Revision: 2456 Modified: branches/trunk-reorg/bknr/datastore/src/skip-list/skip-list.lisp Log: Fix bug in skip-list random number generator that caused skip list insertion performance to drop drastically on SBCL with 64bits. It appears as if the original algorithm returned NIL to approximately half the invocations, despite the comment claiming that NIL would be returned in 3/4 of the times. I replaced the explicit random number generator by a call to (RANDOM) with a separate random state for skip-lists. Modified: branches/trunk-reorg/bknr/datastore/src/skip-list/skip-list.lisp ============================================================================== --- branches/trunk-reorg/bknr/datastore/src/skip-list/skip-list.lisp (original) +++ branches/trunk-reorg/bknr/datastore/src/skip-list/skip-list.lisp Sun Feb 10 17:35:23 2008 @@ -6,23 +6,14 @@ ;;; Pseudo-random number generator from FreeBSD -(defparameter *random-n* - (the fixnum (get-internal-real-time)) - "Internal status of the pseudo-random number generator.") - -(defun random-seed (seed) - "Seed the pseudo-random number generator." - (setf *random-n* seed)) +(defparameter *sl-random-state* + (make-random-state) + "Internal status of the random number generator.") (defun sl-random () - "Pseudo-random number generator from FreeBSD, returns NIL 3/4 of the time." - (declare (optimize (speed 3)) - (type integer *random-n*)) - (logtest (logand most-positive-fixnum - (setf *random-n* - (mod (+ (the number (* *random-n* 1103515245)) 12345) - 2147483648))) - (ash 1 (- (integer-length most-positive-fixnum) 1)))) + "Pseudo-random number generator, returns NIL 3/4 of the time." + (declare (optimize (speed 3))) + (< 2 (random 4 *sl-random-state*))) (defconstant +max-level+ (the fixnum 32) "Maximum level of skip-list, should be enough for 2^32 elements.") From hhubner at common-lisp.net Sun Feb 10 22:47:13 2008 From: hhubner at common-lisp.net (hhubner at common-lisp.net) Date: Sun, 10 Feb 2008 17:47:13 -0500 (EST) Subject: [bknr-cvs] r2457 - branches/trunk-reorg/thirdparty/hunchentoot-0.15.0 Message-ID: <20080210224713.AE42549087@common-lisp.net> Author: hhubner Date: Sun Feb 10 17:47:10 2008 New Revision: 2457 Modified: branches/trunk-reorg/thirdparty/hunchentoot-0.15.0/hunchentoot.asd Log: acl-compat does not actually seem to be needed with current CCL and Hunchentoot. Modified: branches/trunk-reorg/thirdparty/hunchentoot-0.15.0/hunchentoot.asd ============================================================================== --- branches/trunk-reorg/thirdparty/hunchentoot-0.15.0/hunchentoot.asd (original) +++ branches/trunk-reorg/thirdparty/hunchentoot-0.15.0/hunchentoot.asd Sun Feb 10 17:47:10 2008 @@ -51,7 +51,7 @@ :rfc2388 #+:sbcl :sb-bsd-sockets #+:sbcl :sb-posix - #+:openmcl :acl-compat + ; #+:openmcl :acl-compat :url-rewrite) :components ((:file "packages") (:file "conditions") From hhubner at common-lisp.net Sun Feb 10 22:47:54 2008 From: hhubner at common-lisp.net (hhubner at common-lisp.net) Date: Sun, 10 Feb 2008 17:47:54 -0500 (EST) Subject: [bknr-cvs] r2458 - in branches/trunk-reorg/bknr: datastore/src/utils modules/bug web/src/images web/src/web Message-ID: <20080210224754.9EB1049087@common-lisp.net> Author: hhubner Date: Sun Feb 10 17:47:54 2008 New Revision: 2458 Modified: branches/trunk-reorg/bknr/datastore/src/utils/actor.lisp branches/trunk-reorg/bknr/datastore/src/utils/package.lisp branches/trunk-reorg/bknr/modules/bug/package.lisp branches/trunk-reorg/bknr/web/src/images/image.lisp branches/trunk-reorg/bknr/web/src/web/template-handler.lisp Log: openmcl fixes. Modified: branches/trunk-reorg/bknr/datastore/src/utils/actor.lisp ============================================================================== --- branches/trunk-reorg/bknr/datastore/src/utils/actor.lisp (original) +++ branches/trunk-reorg/bknr/datastore/src/utils/actor.lisp Sun Feb 10 17:47:54 2008 @@ -18,15 +18,15 @@ (defmethod actor-start ((actor bknr-actor)) (actor-stop actor) (setf (slot-value actor 'process) - (mp:make-process (lambda () - (funcall #'run-function actor)) - :name (bknr-actor-name actor)))) + (make-process (lambda () + (funcall #'run-function actor)) + :name (bknr-actor-name actor)))) (defmethod actor-running-p ((actor bknr-actor)) (and (slot-boundp actor 'process) - (mp:process-active-p (bknr-actor-process actor)))) + (process-active-p (bknr-actor-process actor)))) (defmethod actor-stop ((actor bknr-actor)) (when (slot-boundp actor 'process) - (mp:destroy-process (bknr-actor-process actor)) + (destroy-process (bknr-actor-process actor)) (slot-makunbound actor 'process))) Modified: branches/trunk-reorg/bknr/datastore/src/utils/package.lisp ============================================================================== --- branches/trunk-reorg/bknr/datastore/src/utils/package.lisp (original) +++ branches/trunk-reorg/bknr/datastore/src/utils/package.lisp Sun Feb 10 17:47:54 2008 @@ -2,140 +2,144 @@ (defpackage :bknr.utils (:use :cl - :cl-ppcre - :cl-interpol - :md5 + :cl-ppcre + :cl-interpol + :md5 #+cmu :extensions - #+sbcl :sb-ext) + #+sbcl :sb-ext + #+cmu :mp + #+openmcl :ccl) + #+openmcl + (:shadow :ccl #:copy-file) (:shadowing-import-from :cl-interpol quote-meta-chars) (:export #:define-bknr-class ;; byte size formatting #:scale-bytes - ;; date format - #:format-date-time - #:format-time-interval - #:format-duration - #:year-interval - #:month-interval - #:day-interval - #:timetag - #:daytag - #:get-daytime - #:get-hourtime - #:get-monthtime - #:previous-day - #:next-day - #:month-num-days + ;; date format + #:format-date-time + #:format-time-interval + #:format-duration + #:year-interval + #:month-interval + #:day-interval + #:timetag + #:daytag + #:get-daytime + #:get-hourtime + #:get-monthtime + #:previous-day + #:next-day + #:month-num-days - #:hostname + #:hostname #:parse-time - ;; filesystem functions - #:copy-stream - #:copy-file - #:move-file - #:directory-empty-p - #:subdir-p - #:temporary-file - #:with-temp-file - #:file-contents - #:parent-directory + ;; filesystem functions + #:copy-stream + #:copy-file + #:move-file + #:directory-empty-p + #:subdir-p + #:temporary-file + #:with-temp-file + #:file-contents + #:parent-directory - ;; list functions - #:delete-first - #:make-keyword-from-string - - #:assoc-values - #:assoc-to-keywords - #:insert-at-index - #:find-neighbourhood - #:group-by - #:group-on - #:find-all - #:genlist - #:nrotate - #:shift-until - #:count-multiple - - ;; hash table - #:hash-to-list - #:hash-values - #:hash-keys - #:incf-hash - - ;; randomize - #:random-elts - #:randomize-list - - ;; md5 - #:hash-to-hex - #:md5-string - - ;; capabilty - #:make-capability-string - - ;; content-types - #:pathname-type-symbol - #:image-content-type - #:pathname-content-type - #:image-type-symbol - - ;; utf-8 - #:convert-utf8-to-latin1 - - ;; strings - #:find-matching-strings - #:make-extendable-string - - ;; stream - #:read-delimited - #:read-file - - ;; smbpasswd - #:set-smb-password - #:smb-password-error - - ;; actor - #:bknr-actor - #:bknr-actor-name - #:run-function - #:actor-start - #:actor-stop - #:actor-running-p - - ;; cron - #:cron-actor - - ;; reader - #:whitespace-char-p - #:whitespace-p - #:bknr-read-delimited-list - #:bknr-read - #:string-beginning-with-p - #:string-delimited-by-p - - ;; crypt-md5 - #:crypt-md5 - #:verify-md5-password - - ;; FDF creation - #:make-fdf-file - - #:remove-keys - #:eval-initargs - - ;; Package cleaning for the build process - #:within-temporary-package - - ;; mp compatibility - #:mp-make-lock - #:mp-with-lock-held - #:mp-with-recursive-lock-held + ;; list functions + #:delete-first + #:make-keyword-from-string + + #:assoc-values + #:assoc-to-keywords + #:insert-at-index + #:find-neighbourhood + #:group-by + #:group-on + #:find-all + #:genlist + #:nrotate + #:shift-until + #:count-multiple + + ;; hash table + #:hash-to-list + #:hash-values + #:hash-keys + #:incf-hash + + ;; randomize + #:random-elts + #:randomize-list + + ;; md5 + #:hash-to-hex + #:md5-string + + ;; capabilty + #:make-capability-string + + ;; content-types + #:pathname-type-symbol + #:image-content-type + #:pathname-content-type + #:image-type-symbol + + ;; utf-8 + #:convert-utf8-to-latin1 + + ;; strings + #:find-matching-strings + #:make-extendable-string + + ;; stream + #:read-delimited + #:read-file + + ;; smbpasswd + #:set-smb-password + #:smb-password-error + + ;; actor + #:bknr-actor + #:bknr-actor-name + #:run-function + #:actor-start + #:actor-stop + #:actor-running-p + + ;; cron + #:cron-actor + + ;; reader + #:whitespace-char-p + #:whitespace-p + #:bknr-read-delimited-list + #:bknr-read + #:string-beginning-with-p + #:string-delimited-by-p + + ;; crypt-md5 + #:crypt-md5 + #:verify-md5-password + + ;; FDF creation + #:make-fdf-file + + #:remove-keys + #:eval-initargs + + ;; Package cleaning for the build process + #:within-temporary-package + + ;; mp compatibility + #:mp-make-lock + #:mp-with-lock-held + #:mp-with-recursive-lock-held - ;; class utils - #:class-subclasses + ;; class utils + #:class-subclasses - ;; norvig - #:find-all)) + ;; norvig + #:find-all)) Modified: branches/trunk-reorg/bknr/modules/bug/package.lisp ============================================================================== --- branches/trunk-reorg/bknr/modules/bug/package.lisp (original) +++ branches/trunk-reorg/bknr/modules/bug/package.lisp Sun Feb 10 17:47:54 2008 @@ -12,7 +12,7 @@ :bknr.indices :bknr.datastore :bknr.mail) - (:shadowing-import-from :cl-interpol quote-meta-chars) + (:shadowing-import-from :cl-interpol #:quote-meta-chars) (:export #:bug-tracker #:bug-tracker-bug-reports #:bug-tracker-add-bug-report @@ -32,6 +32,5 @@ #:priority-to-num #:bug-report-add-annotation #:bug-report-owner - #:edit-bug-report-handler) - (:shadowing-import-from :cl-interpol #:quote-meta-chars)) + #:edit-bug-report-handler)) Modified: branches/trunk-reorg/bknr/web/src/images/image.lisp ============================================================================== --- branches/trunk-reorg/bknr/web/src/images/image.lisp (original) +++ branches/trunk-reorg/bknr/web/src/images/image.lisp Sun Feb 10 17:47:54 2008 @@ -194,4 +194,6 @@ #+cmu (unix:unix-rmdir (namestring file)) #+sbcl - (sb-posix:rmdir (namestring file))))) + (sb-posix:rmdir (namestring file)) + #+openmcl + (ccl::%rmdir (namestring file))))) Modified: branches/trunk-reorg/bknr/web/src/web/template-handler.lisp ============================================================================== --- branches/trunk-reorg/bknr/web/src/web/template-handler.lisp (original) +++ branches/trunk-reorg/bknr/web/src/web/template-handler.lisp Sun Feb 10 17:47:54 2008 @@ -13,7 +13,7 @@ "/usr/local/share/xml/catalog")) (eval-when (:load-toplevel :execute) - (let ((env-catalog (sb-ext:posix-getenv "XMLCATALOG"))) + (let ((env-catalog (#+sbcl sb-ext:posix-getenv #+openmcl ccl:getenv "XMLCATALOG"))) (when env-catalog (pushnew env-catalog *template-dtd-catalog* :test #'equal))) (setf cxml:*catalog* (cxml:make-catalog (remove-if-not #'probe-file *template-dtd-catalog*)) From ksprotte at common-lisp.net Mon Feb 11 10:13:25 2008 From: ksprotte at common-lisp.net (ksprotte at common-lisp.net) Date: Mon, 11 Feb 2008 05:13:25 -0500 (EST) Subject: [bknr-cvs] r2459 - branches/bos/projects/bos/payment-website/infosystem Message-ID: <20080211101325.1C8C881007@common-lisp.net> Author: ksprotte Date: Mon Feb 11 05:13:22 2008 New Revision: 2459 Modified: branches/bos/projects/bos/payment-website/infosystem/javascript.js Log: Fixed YouTube-Fenster #6 by changing height Modified: branches/bos/projects/bos/payment-website/infosystem/javascript.js ============================================================================== --- branches/bos/projects/bos/payment-website/infosystem/javascript.js (original) +++ branches/bos/projects/bos/payment-website/infosystem/javascript.js Mon Feb 11 05:13:22 2008 @@ -899,7 +899,7 @@ document.getElementById("MovieApplet").innerHTML = ' '; + + movie_url + '" type="application/x-shockwave-flash" width="360" height="302"> '; } } From hhubner at common-lisp.net Mon Feb 11 10:46:19 2008 From: hhubner at common-lisp.net (hhubner at common-lisp.net) Date: Mon, 11 Feb 2008 05:46:19 -0500 (EST) Subject: [bknr-cvs] r2460 - branches/bos/projects/bos/web Message-ID: <20080211104619.59E892D1B7@common-lisp.net> Author: hhubner Date: Mon Feb 11 05:46:15 2008 New Revision: 2460 Modified: branches/bos/projects/bos/web/webserver.lisp Log: Fix for #20, set session's language when / page is sent out. Modified: branches/bos/projects/bos/web/webserver.lisp ============================================================================== --- branches/bos/projects/bos/web/webserver.lisp (original) +++ branches/bos/projects/bos/web/webserver.lisp Mon Feb 11 05:46:15 2008 @@ -47,8 +47,11 @@ ((and (not (scan "/" template-name)) (not (probe-file (merge-pathnames (make-pathname :name template-name :type "xml") (template-handler-destination handler))))) - (setf template-name (format nil "~A/~A" (or (find-browser-prefered-language request) - *default-language*) + (unless (session-variable :language) + (setf (session-variable :language) (or (find-browser-prefered-language request) + *default-language*))) + (setf template-name (format nil "~A/~A" + (session-variable :language) (if (equal "" template-name) "index" template-name))))) (call-next-method handler template-name)) From ksprotte at common-lisp.net Mon Feb 11 11:39:57 2008 From: ksprotte at common-lisp.net (ksprotte at common-lisp.net) Date: Mon, 11 Feb 2008 06:39:57 -0500 (EST) Subject: [bknr-cvs] r2461 - branches/bos/projects/bos/web Message-ID: <20080211113957.7F1B74D042@common-lisp.net> Author: ksprotte Date: Mon Feb 11 06:39:55 2008 New Revision: 2461 Modified: branches/bos/projects/bos/web/tags.lisp Log: added new template var :geo-coord for save-profile and removed sqm-x sqm-y not tested yet Modified: branches/bos/projects/bos/web/tags.lisp ============================================================================== --- branches/bos/projects/bos/web/tags.lisp (original) +++ branches/bos/projects/bos/web/tags.lisp Mon Feb 11 06:39:55 2008 @@ -168,8 +168,11 @@ (setf (get-template-var :country) (sponsor-country sponsor)) (setf (get-template-var :infotext) (sponsor-info-text sponsor)) (setf (get-template-var :name) (user-full-name sponsor)) - (setf (get-template-var :sqm-x) (format nil "~,3f" (m2-utm-x (first (contract-m2s contract))))) - (setf (get-template-var :sqm-y) (format nil "~,3f" (m2-utm-y (first (contract-m2s contract))))) + (setf (get-template-var :geo-coord) (multiple-value-bind (left top) + (contract-bounding-box contract) + (apply #'geometry:format-lon-lat nil + (geo-utm:utm-x-y-to-lon-lat (+ +nw-utm-x+ left) + (- +nw-utm-y+ top) +utm-zone+ t)))) (setf (get-template-var :numsqm) (format nil "~D" (apply #'+ (mapcar #'(lambda (contract) (length (contract-m2s contract))) (sponsor-contracts sponsor)))))) From hhubner at common-lisp.net Mon Feb 11 12:13:00 2008 From: hhubner at common-lisp.net (hhubner at common-lisp.net) Date: Mon, 11 Feb 2008 07:13:00 -0500 (EST) Subject: [bknr-cvs] r2462 - branches/bos/projects/bos/web Message-ID: <20080211121300.AAD7962120@common-lisp.net> Author: hhubner Date: Mon Feb 11 07:12:57 2008 New Revision: 2462 Modified: branches/bos/projects/bos/web/sponsor-handlers.lisp Log: Fix password setting through CMS. Modified: branches/bos/projects/bos/web/sponsor-handlers.lisp ============================================================================== --- branches/bos/projects/bos/web/sponsor-handlers.lisp (original) +++ branches/bos/projects/bos/web/sponsor-handlers.lisp Mon Feb 11 07:12:57 2008 @@ -181,7 +181,9 @@ (let ((field-value (query-param req (string-downcase (symbol-name field-name))))) (when (and field-value (not (equal field-value (slot-value sponsor field-name)))) - (change-slot-values sponsor field-name field-value) + (if (eq field-name 'password) + (set-user-password sponsor field-value) + (change-slot-values sponsor field-name field-value)) (setf changed t) (html (:p "Changed " (:princ-safe (string-downcase (symbol-name field-name)))))))) (dolist (contract (sponsor-contracts sponsor)) From ksprotte at common-lisp.net Mon Feb 11 12:30:10 2008 From: ksprotte at common-lisp.net (ksprotte at common-lisp.net) Date: Mon, 11 Feb 2008 07:30:10 -0500 (EST) Subject: [bknr-cvs] r2463 - branches/bos/projects/bos/web Message-ID: <20080211123010.2FAEA5C16F@common-lisp.net> Author: ksprotte Date: Mon Feb 11 07:30:08 2008 New Revision: 2463 Modified: branches/bos/projects/bos/web/tags.lisp Log: added again template-vars :sqm-x, :sqm-y. Also reindent/untabify Modified: branches/bos/projects/bos/web/tags.lisp ============================================================================== --- branches/bos/projects/bos/web/tags.lisp (original) +++ branches/bos/projects/bos/web/tags.lisp Mon Feb 11 07:30:08 2008 @@ -10,13 +10,13 @@ (defun language-options-1 (current-language) (loop for (language-symbol language-name) in (website-languages) - do (if (equal language-symbol current-language) - (html ((:option :value (format nil "/~a/index" language-symbol) :selected "selected") " " (:princ language-name) " ")) - (html ((:option :value (format nil "/~a/index" language-symbol)) " " (:princ language-name) " "))))) + do (if (equal language-symbol current-language) + (html ((:option :value (format nil "/~a/index" language-symbol) :selected "selected") " " (:princ language-name) " ")) + (html ((:option :value (format nil "/~a/index" language-symbol)) " " (:princ language-name) " "))))) (define-bknr-tag language-chooser (name) (html ((:select :name name) - (language-options-1 (current-website-language))))) + (language-options-1 (current-website-language))))) (define-bknr-tag language-options () (language-options-1 (current-website-language))) @@ -27,7 +27,7 @@ (define-bknr-tag process-payment (&key children) (with-template-vars (cartId transId email country) (let* ((contract (get-contract (parse-integer cartId))) - (sponsor (contract-sponsor contract))) + (sponsor (contract-sponsor contract))) (change-slot-values sponsor 'bknr.web::email email) (change-slot-values contract 'bos.m2::worldpay-trans-id transId) (sponsor-set-country sponsor country) @@ -40,13 +40,13 @@ (with-template-vars (gift email name address want-print) (let ((contract (find-store-object (parse-integer (get-template-var :contract-id))))) (when (equal want-print "no") - (contract-set-download-only-p contract t)) + (contract-set-download-only-p contract t)) (contract-issue-cert contract name :address address :language (session-variable :language)) (mail-worldpay-sponsor-data (get-template-var :request)) (bknr.web::redirect-request :target (if gift "index" - (format nil "profil_setup?name=~A&email=~A&sponsor-id=~A" - (uriencode-string name) (uriencode-string email) - (store-object-id (contract-sponsor contract)))))))) + (format nil "profil_setup?name=~A&email=~A&sponsor-id=~A" + (uriencode-string name) (uriencode-string email) + (store-object-id (contract-sponsor contract)))))))) (define-bknr-tag urkunde-per-post (&key contract-id min-amount message) (let ((contract (get-contract (parse-integer contract-id)))) @@ -60,81 +60,81 @@ (define-bknr-tag maybe-base (&key href) (when (and href - (not (equal "" href))) + (not (equal "" href))) (html ((:base "href" href))))) (define-bknr-tag buy-sqm (&key children) (handler-case (with-template-vars (numsqm numsqm1 action gift donationcert-yearly download-only) - (let* ((numsqm (parse-integer (or numsqm numsqm1))) - ;; Wer ueber dieses Formular bestellt, ist ein neuer - ;; Sponsor, also ein neues Sponsorenobjekt anlegen. Eine - ;; Profil-ID wird automatisch zugewiesen, sonstige Daten - ;; haben wir zu diesem Zeitpunkt noch nicht. - ;; ?berweisung wird nur f?r die deutsche und d?nische - ;; Website angeboten, was passenderweise durch die folgende - ;; ?berpr?fung auch sicher gestellt wurde. Sollte man aber - ;; eventuell noch mal pr?fen und sicher stellen. - (manual-transfer (or (scan #?r"rweisen" action) - (scan #?r"rweisung" action) - (scan #?r"verf" action))) - (language (session-variable :language)) - (sponsor (make-sponsor :language language)) - (contract (make-contract sponsor numsqm - :download-only download-only - :expires (+ (if manual-transfer - bos.m2::*manual-contract-expiry-time* - bos.m2::*online-contract-expiry-time*) - (get-universal-time))))) - (destructuring-bind (price currency) - (case (make-keyword-from-string language) - (:da (list (* numsqm 24) "DKK")) - (t (list (* numsqm 3) "EUR"))) - (setf (get-template-var :worldpay-url) - (if manual-transfer - (format nil "ueberweisung?contract-id=~A&amount=~A&numsqm=~A~@[&donationcert-yearly=1~]" - (store-object-id contract) - price - numsqm - donationcert-yearly) - (format nil "https://select.worldpay.com/wcc/purchase?instId=~A&cartId=~A&amount=~A¤cy=~A&lang=~A&desc=~A&MC_sponsorid=~A&MC_password=~A&MC_donationcert-yearly=~A&MC_gift=~A~@[~A~]" - *worldpay-installation-id* - (store-object-id contract) - price - currency - language - (encode-urlencoded (format nil "~A ~A Samboja Lestari" - numsqm - (case (make-keyword-from-string language) - (:de "qm Regenwald in") - (:da "m2 Regnskov i") - (t "sqm rain forest in")))) - (store-object-id sponsor) - (sponsor-master-code sponsor) - (if donationcert-yearly "1" "0") - (if gift "1" "0") - (when *worldpay-test-mode* "&testMode=100")))))) - (mapc #'emit-template-node children)) + (let* ((numsqm (parse-integer (or numsqm numsqm1))) + ;; Wer ueber dieses Formular bestellt, ist ein neuer + ;; Sponsor, also ein neues Sponsorenobjekt anlegen. Eine + ;; Profil-ID wird automatisch zugewiesen, sonstige Daten + ;; haben wir zu diesem Zeitpunkt noch nicht. + ;; ?berweisung wird nur f?r die deutsche und d?nische + ;; Website angeboten, was passenderweise durch die folgende + ;; ?berpr?fung auch sicher gestellt wurde. Sollte man aber + ;; eventuell noch mal pr?fen und sicher stellen. + (manual-transfer (or (scan #?r"rweisen" action) + (scan #?r"rweisung" action) + (scan #?r"verf" action))) + (language (session-variable :language)) + (sponsor (make-sponsor :language language)) + (contract (make-contract sponsor numsqm + :download-only download-only + :expires (+ (if manual-transfer + bos.m2::*manual-contract-expiry-time* + bos.m2::*online-contract-expiry-time*) + (get-universal-time))))) + (destructuring-bind (price currency) + (case (make-keyword-from-string language) + (:da (list (* numsqm 24) "DKK")) + (t (list (* numsqm 3) "EUR"))) + (setf (get-template-var :worldpay-url) + (if manual-transfer + (format nil "ueberweisung?contract-id=~A&amount=~A&numsqm=~A~@[&donationcert-yearly=1~]" + (store-object-id contract) + price + numsqm + donationcert-yearly) + (format nil "https://select.worldpay.com/wcc/purchase?instId=~A&cartId=~A&amount=~A¤cy=~A&lang=~A&desc=~A&MC_sponsorid=~A&MC_password=~A&MC_donationcert-yearly=~A&MC_gift=~A~@[~A~]" + *worldpay-installation-id* + (store-object-id contract) + price + currency + language + (encode-urlencoded (format nil "~A ~A Samboja Lestari" + numsqm + (case (make-keyword-from-string language) + (:de "qm Regenwald in") + (:da "m2 Regnskov i") + (t "sqm rain forest in")))) + (store-object-id sponsor) + (sponsor-master-code sponsor) + (if donationcert-yearly "1" "0") + (if gift "1" "0") + (when *worldpay-test-mode* "&testMode=100")))))) + (mapc #'emit-template-node children)) (bos.m2::allocation-areas-exhausted (e) (declare (ignore e)) (bknr.web::redirect-request :target "allocation-areas-exhausted")))) (define-bknr-tag mail-transfer () (with-query-params ((get-template-var :request) - country - contract-id - name vorname strasse plz ort) + country + contract-id + name vorname strasse plz ort) (let* ((contract (store-object-with-id (parse-integer contract-id))) - (download-only (< (contract-price contract) *mail-certificate-threshold*))) + (download-only (< (contract-price contract) *mail-certificate-threshold*))) (with-transaction (:prepare-before-mail) - (setf (contract-download-only contract) download-only) - (setf (sponsor-country (contract-sponsor contract)) country)) + (setf (contract-download-only contract) download-only) + (setf (sponsor-country (contract-sponsor contract)) country)) (contract-issue-cert contract (format nil "~A ~A" vorname name) - :address (format nil "~A ~A~%~A~%~A ~A" - vorname name - strasse - plz ort) - :language (session-variable :language)) + :address (format nil "~A ~A~%~A~%~A ~A" + vorname name + strasse + plz ort) + :language (session-variable :language)) (mail-manual-sponsor-data (get-template-var :request))))) (define-bknr-tag when-certificate (&key children) @@ -148,34 +148,36 @@ (define-bknr-tag save-profile (&key children) (let* ((sponsor (bknr-request-user (get-template-var :request))) - (contract (first (sponsor-contracts sponsor)))) + (contract (first (sponsor-contracts sponsor)))) (with-template-vars (email name password infotext anonymize) (when anonymize - (change-slot-values sponsor - 'full-name nil - 'info-text nil - 'email nil)) + (change-slot-values sponsor + 'full-name nil + 'info-text nil + 'email nil)) (when name - (change-slot-values sponsor 'full-name name)) + (change-slot-values sponsor 'full-name name)) (when email - (change-slot-values sponsor 'bknr.web::email email)) + (change-slot-values sponsor 'bknr.web::email email)) (when password - (set-user-password sponsor password)) + (set-user-password sponsor password)) (when infotext - (change-slot-values sponsor 'info-text infotext))) + (change-slot-values sponsor 'info-text infotext))) (setf (get-template-var :sponsor-id) (format nil "~D" (store-object-id sponsor))) (setf (get-template-var :contract-id) (format nil "~D" (store-object-id contract))) (setf (get-template-var :country) (sponsor-country sponsor)) (setf (get-template-var :infotext) (sponsor-info-text sponsor)) (setf (get-template-var :name) (user-full-name sponsor)) + (setf (get-template-var :sqm-x) (format nil "~,3f" (m2-utm-x (first (contract-m2s contract))))) + (setf (get-template-var :sqm-y) (format nil "~,3f" (m2-utm-y (first (contract-m2s contract))))) (setf (get-template-var :geo-coord) (multiple-value-bind (left top) - (contract-bounding-box contract) - (apply #'geometry:format-lon-lat nil - (geo-utm:utm-x-y-to-lon-lat (+ +nw-utm-x+ left) - (- +nw-utm-y+ top) +utm-zone+ t)))) + (contract-bounding-box contract) + (apply #'geometry:format-lon-lat nil + (geo-utm:utm-x-y-to-lon-lat (+ +nw-utm-x+ left) + (- +nw-utm-y+ top) +utm-zone+ t)))) (setf (get-template-var :numsqm) - (format nil "~D" - (apply #'+ (mapcar #'(lambda (contract) (length (contract-m2s contract))) (sponsor-contracts sponsor)))))) + (format nil "~D" + (apply #'+ (mapcar #'(lambda (contract) (length (contract-m2s contract))) (sponsor-contracts sponsor)))))) (mapc #'emit-template-node children)) (define-bknr-tag admin-login-page (&key children) @@ -185,7 +187,7 @@ (define-bknr-tag google-analytics-track () (html ((:script :type "text/javascript") - "var gaJsHost = (('https:' == document.location.protocol) ? 'https://ssl.' : 'http://www.'); + "var gaJsHost = (('https:' == document.location.protocol) ? 'https://ssl.' : 'http://www.'); document.write(unescape('%3Cscript src=%22' + gaJsHost + 'google-analytics.com/ga.js%22 type=%22text/javascript%22%3E%3C/script%3E'));") - ((:script :type "text/javascript") - (:princ #?"if (_gat) { var pageTracker = _gat._getTracker('$(*google-analytics-account*)'); pageTracker._initData(); pageTracker._trackPageview(); }")))) + ((:script :type "text/javascript") + (:princ #?"if (_gat) { var pageTracker = _gat._getTracker('$(*google-analytics-account*)'); pageTracker._initData(); pageTracker._trackPageview(); }")))) From dverna at common-lisp.net Mon Feb 11 12:35:18 2008 From: dverna at common-lisp.net (dverna at common-lisp.net) Date: Mon, 11 Feb 2008 07:35:18 -0500 (EST) Subject: [bknr-cvs] r2464 - trunk/projects/lisp-ecoop/website/templates Message-ID: <20080211123518.61D2972096@common-lisp.net> Author: dverna Date: Mon Feb 11 07:35:17 2008 New Revision: 2464 Modified: trunk/projects/lisp-ecoop/website/templates/home.xml trunk/projects/lisp-ecoop/website/templates/lisp-ecoop.xsl trunk/projects/lisp-ecoop/website/templates/toplevel.xml Log: Fixed workshop location spelling Modified: trunk/projects/lisp-ecoop/website/templates/home.xml ============================================================================== --- trunk/projects/lisp-ecoop/website/templates/home.xml (original) +++ trunk/projects/lisp-ecoop/website/templates/home.xml Mon Feb 11 07:35:17 2008 @@ -5,7 +5,7 @@

5th European Lisp Workshop

-

July 07 - Paphos-Cyprus - co-located with ECOOP 2008

+

July 07 - Paphos, Cyprus - co-located with ECOOP 2008

+ + + + + + + + + + + + + + + + + + + + + + + Added: branches/trunk-reorg/thirdparty/uffi/doc/catalog-debian.xml ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi/doc/catalog-debian.xml Mon Feb 11 09:06:27 2008 @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Added: branches/trunk-reorg/thirdparty/uffi/doc/catalog-mandrake.xml ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi/doc/catalog-mandrake.xml Mon Feb 11 09:06:27 2008 @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Added: branches/trunk-reorg/thirdparty/uffi/doc/catalog-suse.xml ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi/doc/catalog-suse.xml Mon Feb 11 09:06:27 2008 @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Added: branches/trunk-reorg/thirdparty/uffi/doc/catalog-suse90.xml ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi/doc/catalog-suse90.xml Mon Feb 11 09:06:27 2008 @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Added: branches/trunk-reorg/thirdparty/uffi/doc/catalog-suse91.xml ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi/doc/catalog-suse91.xml Mon Feb 11 09:06:27 2008 @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Added: branches/trunk-reorg/thirdparty/uffi/doc/catalog-ubuntu.xml ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi/doc/catalog-ubuntu.xml Mon Feb 11 09:06:27 2008 @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Added: branches/trunk-reorg/thirdparty/uffi/doc/entities.inc ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi/doc/entities.inc Mon Feb 11 09:06:27 2008 @@ -0,0 +1,16 @@ +UFFI"> +FFI"> +CMUCL"> +SCL"> +Lispworks"> +SBCL"> +OpenMCL"> +MCL"> +AllegroCL"> +ANSI Common Lisp"> +T"> +NIL"> +NULL"> +C"> +defsystem"> +ASDF"> Added: branches/trunk-reorg/thirdparty/uffi/doc/fo.xsl ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi/doc/fo.xsl Mon Feb 11 09:06:27 2008 @@ -0,0 +1,8 @@ + + + + + + + Added: branches/trunk-reorg/thirdparty/uffi/doc/glossary.xml ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi/doc/glossary.xml Mon Feb 11 09:06:27 2008 @@ -0,0 +1,21 @@ + + +%myents; +]> + + + + Foreign Function Interface + FFI) + + + + An interface to a C-compatible library. + + + + + + Added: branches/trunk-reorg/thirdparty/uffi/doc/html.tar.gz ============================================================================== Binary file. No diff available. Added: branches/trunk-reorg/thirdparty/uffi/doc/html.xsl ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi/doc/html.xsl Mon Feb 11 09:06:27 2008 @@ -0,0 +1,10 @@ + + + + + + + + + Added: branches/trunk-reorg/thirdparty/uffi/doc/html_chunk.xsl ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi/doc/html_chunk.xsl Mon Feb 11 09:06:27 2008 @@ -0,0 +1,9 @@ + + + + + + + + Added: branches/trunk-reorg/thirdparty/uffi/doc/intro.xml ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi/doc/intro.xml Mon Feb 11 09:06:27 2008 @@ -0,0 +1,113 @@ + + +%myents; +]> + + + Introduction + + Purpose + + This reference guide describes &uffi;, a package that provides a + cross-implementation interface from Common Lisp to C-language + compatible libraries. + + + + + Background + + + Every Common Lisp implementation has a method for interfacing to + C-language compatible libraries. These methods are often termed + a Foreign Function Library Interface + (&ffi;). Unfortunately, these methods vary widely amongst + implementations, thus preventing the writing of a portable FFI + to a particular C-library. + + + &uffi; gathers a common subset of functionality between Common + Lisp implementations. &uffi; wraps this common subset of + functionality with it's own syntax and provides macro + translation of uffi functions into the specific syntax of + supported Common Lisp implementations. + + + Developers who use &uffi; to interface with C libraries will + automatically have their code function in each of uffi's supported + implementations. + + + + + Supported Implementations + The primary tested and supported platforms for &uffi; are: + + + &acl; v6.2 on Debian GNU/Linux + FreeBSD 4.5, Solaris v2.8, and Microsoft Windows XP. + &lw; v4.2 on Debian GNU/Linux and Microsoft Windows XP. + &cmucl; 18d on Debian GNU/Linux, FreeBSD 4.5, and Solaris 2.8 + &sbcl; 0.7.8 on Debian GNU/Linux + &scl; 1.1.1 on Debian GNU/Linux + &openmcl; 0.13 on Debian GNU/Linux for PowerPC + + Beta code is included with &uffi; for + + + &openmcl; and &mcl; with MacOSX + + + + + Design + + Overview + + &uffi; was designed as a cross-implementation + compatible Foreign Function Interface. + Necessarily, + only a common subset of functionality can be + provided. Likewise, not every optimization for that a specific + implementation provides can be supported. Wherever possible, + though, implementation-specific optimizations are invoked. + + + + + Priorities + + The design of &uffi; is dictated by the order of these priorities: + + + + + Code using &uffi; must operate correctly on all + supported implementations. + + + + + Take advantage of implementation-specific optimizations. Ideally, + there will not a situation where an implementation-specific + &ffi; will be chosen due to lack of optimizations in &uffi;. + + + + Provide a simple interface to developers using + &uffi;. This priority is quite a bit lower than the above priorities. + This lower priority is manifest by programmers having to pass types in + pointer and array dereferencing, needing to use + cstring wrapper functions, and the use of + ensure-char-character and ensure-char-integer functions. My hope is + that the developer inconvenience will be outweighed by the generation + of optimized code that is cross-implementation compatible. + + + + + + + Added: branches/trunk-reorg/thirdparty/uffi/doc/notes.xml ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi/doc/notes.xml Mon Feb 11 09:06:27 2008 @@ -0,0 +1,94 @@ + + +%myents; +]> + + + Programming Notes + + + Implementation Specific Notes + + + + &acl; + + + + + &lw; + + + + + &cmucl; + + + + + + + Foreign Object Representation and Access + There are two main approaches used to represent foreign + objects: an integer that represents an address in memory, and a + object that also includes run-time typing. The advantage of + run-time typing is the system can dereference pointers and perform + array access without those functions requiring a type at the cost + of additional overhead to generate and store the run-time + typing. The advantage of integer representation, at least for + &acl;, is that the compiler can generate inline code to + dereference pointers. Further, the overhead of the run-time type + information is eliminated. The disadvantage is the program must + then supply + the type to the functions to dereference objects and array. + + + + + Optimizing Code Using UFFI + + Background + + Two implementions have different techniques to optimize + (open-code) foreign objects. &acl; can open-code foreign + object + access if pointers are integers and the type of object is + specified in the access function. Thus, &uffi; represents objects + in &acl; as integers which don't have type information. + + &cmucl; works best when keeping objects as typed + objects. However, it's compiler can open-code object access when + the object type is specified in declare + commands and in :type specifiers in + defstruct and defclass. + &lw;, in converse to &acl; and &cmucl; does not do + any open coding of object access. &lw;, by default, maintains + objects with run-time typing. + + + Cross-Implementation Optimization + + To fully optimize across platforms, both explicit type + information must be passed to dereferencing of pointers and + arrays. Though this optimization only helps with &acl;, &uffi; + is designed to require this type information be passed the + dereference functions. Second, declarations of type should be + made in functions, structures, and classes where foreign + objects will be help. This will optimize access for &lw; + + + Here is an example that should both methods being used for + maximum cross-implementation optimization: + +(uffi:def-type the-struct-type-def the-struct-type) +(let ((a-foreign-struct (allocate-foreign-object 'the-struct-type))) + (declare 'the-struct-type-def a-foreign-struct) + (get-slot-value a-foreign-struct 'the-struct-type 'field-name)) + + + + + + Added: branches/trunk-reorg/thirdparty/uffi/doc/preface.xml ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi/doc/preface.xml Mon Feb 11 09:06:27 2008 @@ -0,0 +1,16 @@ + + +%myents; +]> + + + Preface + This reference guide describes the usage and features of + &uffi;. The first chapter provides an overview to the design of + &uffi;. Following that chapter is the reference section for all + user accessible functions of &uffi;. The appendix covers the + installation and implementation-specifc features of &uffi;. + + Added: branches/trunk-reorg/thirdparty/uffi/doc/ref_aggregate.xml ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi/doc/ref_aggregate.xml Mon Feb 11 09:06:27 2008 @@ -0,0 +1,524 @@ + + +%myents; +]> + + + Aggregate Types + + Overview + + Aggregate types are comprised of one or more primitive types. + + + + + + def-enum + Defines a &c; enumeration. + + Macro + + + Syntax + + def-enum name fields &key separator-string + + + + Arguments and Values + + + name + + A symbol that names the enumeration. + + + + + fields + + A list of field defintions. Each definition can be +a symbol or a list of two elements. Symbols get assigned a value of the +current counter which starts at 0 and +increments by 1 for each subsequent symbol. It the field definition is a list, the first position is the symbol and the second +position is the value to assign the the symbol. The current counter gets set +to 1+ this value. + + + + + separator-string + + A string that governs the creation of constants. The +default is "#". + + + + + + Description + + Declares a &c; enumeration. It generates constants with integer values for the elements of the enumeration. The symbols for the these constant +values are created by the concatenation of the +enumeration name, separator-string, and field symbol. Also creates +a foreign type with the name name of type +:int. + + + + Examples + +(def-enum abc (:a :b :c)) +;; Creates constants abc#a (1), abc#b (2), abc#c (3) and defines +;; the foreign type "abc" to be :int + +(def-enum efoo (:e1 (:e2 10) :e3) :separator-string "-") +;; Creates constants efoo-e1 (1), efoo-e2 (10), efoo-e3 (11) and defines +;; the foreign type efoo to be :int + + + + Side Effects + Creates a :int foreign type, defines constants. + + + Affected by + None. + + + Exceptional Situations + None. + + + + + + + def-struct + Defines a &c; structure. + + Macro + + + Syntax + + def-struct name &rest fields + + + + Arguments and Values + + + name + + A symbol that names the structure. + + + + + fields + + A variable number of field defintions. Each definition is a list consisting of a symbol naming the field followed by its foreign type. + + + + + + + Description + + Declares a structure. A special type is available as a slot +in the field. It is a pointer that points to an instance of the parent +structure. It's type is :pointer-self. + + + + + Examples + +(def-struct foo (a :unsigned-int) + (b (* :char)) + (c (:array :int 10)) + (next :pointer-self)) + + + + Side Effects + Creates a foreign type. + + + Affected by + None. + + + Exceptional Situations + None. + + + + + + + get-slot-value + Retrieves a value from a slot of a structure. + + Macro + + + Syntax + + get-slot-value obj type field => value + + + + Arguments and Values + + + obj + + A pointer to foreign structure. + + + + + type + + A name of the foreign structure. + + + + + field + + A name of the desired field in foreign structure. + + + + + value + + The value of the field in the structure. + + + + + + + Description + + Accesses a slot value from a structure. This is generalized + and can be used with setf. + + + + Examples + +(get-slot-value foo-ptr 'foo-structure 'field-name) +(setf (get-slot-value foo-ptr 'foo-structure 'field-name) 10) + + + + Side Effects + None. + + + Affected by + None. + + + Exceptional Situations + None. + + + + + + get-slot-pointer + Retrieves a pointer from a slot of a structure. + + Macro + + + Syntax + + get-slot-pointer obj type field => pointer + + + + Arguments and Values + + + obj + + A pointer to foreign structure. + + + + + type + + A name of the foreign structure. + + + + + field + + A name of the desired field in foreign structure. + + + + + pointer + + The value of the field in the structure. + + + + + + + Description + + This is similar to get-slot-value. It + is used when the value of a slot is a pointer type. + + + + Examples + +(get-slot-pointer foo-ptr 'foo-structure 'my-char-ptr) + + + + Side Effects + None. + + + Affected by + None. + + + Exceptional Situations + None. + + + + + + + def-array-pointer + Defines a pointer to a array of type. + + Macro + + + Syntax + + def-array-pointer name type + + + + Arguments and Values + + + name + + A name of the new foreign type. + + + + + type + + The foreign type of the array elements. + + + + + + + Description + + Defines a type tat is a pointer to an array of type. + + + + Examples + +(def-array-pointer byte-array-pointer :unsigned-char) + + + + Side Effects + Defines a new foreign type. + + + Affected by + None. + + + Exceptional Situations + None. + + + + + + + deref-array + Deference an array. + + Macro + + + Syntax + + deref-array array type position => value + + + + Arguments and Values + + + array + + A foreign array. + + + + + type + + The foreign type of the array. + + + + + position + + An integer specifying the position to retrieve from +the array. + + + + + value + + The value stored in the position of the array. + + + + + + + Description + + Dereferences (retrieves) the value of an array element. + + + + Examples + +(def-array-pointer ca :char) +(let ((fs (convert-to-foreign-string "ab"))) + (values (null-char-p (deref-array fs 'ca 0)) + (null-char-p (deref-array fs 'ca 2)))) +=> &nil; + &t; + + + + Notes + + The TYPE argument is ignored for CL implementations other than + AllegroCL. If you want to cast a pointer to another type use + WITH-CAST-POINTER together with DEREF-POINTER/DEREF-ARRAY. + + + + Side Effects + None. + + + Affected by + None. + + + Exceptional Situations + None. + + + + + + def-union + Defines a foreign union type. + + Macro + + + Syntax + + def-union name &rest fields + + + + Arguments and Values + + + name + + A name of the new union type. + + + + + fields + + A list of fields of the union. + + + + + + + Description + + Defines a foreign union type. + + + + Examples + +(def-union test-union + (a-char :char) + (an-int :int)) + +(let ((u (allocate-foreign-object 'test-union)) + (setf (get-slot-value u 'test-union 'an-int) (+ 65 (* 66 256))) + (prog1 + (ensure-char-character (get-slot-value u 'test-union 'a-char)) + (free-foreign-object u))) +=> #\A + + + + Side Effects + Defines a new foreign type. + + + Affected by + None. + + + Exceptional Situations + None. + + + + + Added: branches/trunk-reorg/thirdparty/uffi/doc/ref_declare.xml ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi/doc/ref_declare.xml Mon Feb 11 09:06:27 2008 @@ -0,0 +1,82 @@ + + +%myents; +]> + + + Declarations + + + + Overview + Declarations are used to give the compiler optimizing + information about foreign types. Currently, only &cmucl; + supports declarations. On &acl; and &lw;, these expressions + declare the type generically as &t; + + + + + + + def-type + Defines a Common Lisp type. + + Macro + + + Syntax + + def-type name type + + + + Arguments and Values + + + name + + A symbol naming the type + + + + type + + A form that specifies the &uffi; type. It is not evaluated. + + + + + + + Description + Defines a Common Lisp type based on a &uffi; type. + + + + Examples + +(def-type char-ptr '(* :char)) +... +(defun foo (ptr) +(declare (type char-ptr ptr)) +... + + + + Side Effects + Defines a new &cl; type. + + + Affected by + None. + + + Exceptional Situations + None. + + + + Added: branches/trunk-reorg/thirdparty/uffi/doc/ref_func_libr.xml ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi/doc/ref_func_libr.xml Mon Feb 11 09:06:27 2008 @@ -0,0 +1,264 @@ + + +%myents; +]> + + + Functions & Libraries + + + + def-function + Declares a function. + + Macro + + + Syntax + + def-function name args &key module returning + + + + Arguments and Values + + + name + + A string or list specificying the function name. If it is a string, that names the foreign function. A Lisp name is created by translating #\_ to #\- and by converting to upper-case in case-insensitive Lisp implementations. If it is a list, the first item is a string specifying the foreign function name and the second it is a symbol stating the Lisp name. + + + + + args + + A list of argument declarations. If &nil;, indicates that the function does not take any arguments. + + + + + module + + A string specifying which module (or library) that the foreign function resides. (Required by Lispworks) + + + + returning + + A declaration specifying the result type of the +foreign function. If :void indicates module does not return any value. + + + + + + + Description + Declares a foreign function. + + + + Examples + +(def-function "gethostname" + ((name (* :unsigned-char)) + (len :int)) + :returning :int) + + + + Side Effects + None. + + + Affected by + None. + + + Exceptional Situations + None. + + + + + + load-foreign-library + Loads a foreign library. + + Function + + + Syntax + + load-foreign-library filename &key module supporting-libraries force-load => success + + + + Arguments and Values + + + filename + + A string or pathname specifying the library location +in the filesystem. At least one implementation (&lw;) can not +accept a logical pathname. If this parameter denotes a pathname without a +directory component then most of the supported Lisp implementations will be +able to find the library themselves if it is located in one of the standard +locations as defined by the underlying operating system. + + + + + module + + A string designating the name of the module to apply +to functions in this library. (Required for Lispworks) + + + + + supporting-libraries + + A list of strings naming the libraries required to +link the foreign library. (Required by CMUCL) + + + + + force-load + + Forces the loading of the library if it has been previously loaded. + + + + + success + + A boolean flag, &t; if the library was able to be +loaded successfully or if the library has been previously loaded, + + + + + + + Description + Loads a foreign library. Applies a module name to functions +within the library. Ensures that a library is only loaded once during +a session. A library can be reloaded by using the :force-load key. + + + + Examples + + (load-foreign-library #p"/usr/lib/libmysqlclient.so" + :module "mysql" + :supporting-libraries '("c")) + => T + + + + Side Effects + Loads the foreign code into the Lisp system. + + + + Affected by + Ability to load the file. + + + Exceptional Situations + An error will be signaled if the library is unable to be loaded. + + + + + + find-foreign-library + Finds a foreign library file. + + Function + + + Syntax + + find-foreign-library names directories & drive-letters types => path + + + + Arguments and Values + + + names + + A string or list of strings containing the base name of the library file. + + + + + directories + + A string or list of strings containing the directory the library file. + + + + + drive-letters + + A string or list of strings containing the drive letters for the library file. + + + + + types + + A string or list of strings containing the file type of the library file. Default +is &nil;. If &nil;, will use a default type based on the currently running implementation. + + + + + path + + A path containing the path found, or &nil; if the library file was not found. + + + + + + + Description + Finds a foreign library by searching through a number of possible locations. Returns +the path of the first found file. + + + + Examples + +(find-foreign-library '("libmysqlclient" "libmysql") + '("/opt/mysql/lib/mysql/" "/usr/local/lib/" "/usr/lib/" "/mysql/lib/opt/") + :types '("so" "dll") + :drive-letters '("C" "D" "E")) +=> #P"D:\\mysql\\lib\\opt\\libmysql.dll" + + + + Side Effects + None. + + + + Affected by + None. + + + Exceptional Situations + None. + + + + + + Added: branches/trunk-reorg/thirdparty/uffi/doc/ref_object.xml ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi/doc/ref_object.xml Mon Feb 11 09:06:27 2008 @@ -0,0 +1,859 @@ + + +%myents; +]> + + + Objects + +Overview + + Objects are entities that can allocated, referred to by pointers, and +can be freed. + + + + + + + allocate-foreign-object + Allocates an instance of a foreign object. + + Macro + + + Syntax + + allocate-foreign-object type &optional size => ptr + + + + Arguments and Values + + + type + + The type of foreign object to allocate. This parameter is evaluated. + + + + + size + + An optional size parameter that is evaluated. If specified, allocates and returns an +array of type that is size members long. This parameter is evaluated. + + + + + ptr + + A pointer to the foreign object. + + + + + + + Description + + Allocates an instance of a foreign object. It returns a pointer to the object. + + + + Examples + +(def-struct ab (a :int) (b :double)) +(allocate-foreign-object 'ab) +=> #<ptr> + + + + Side Effects + None. + + + Affected by + None. + + + Exceptional Situations + None. + + + + + + + free-foreign-object + Frees memory that was allocated for a foreign boject. + + Macro + + + Syntax + + free-foreign-object ptr + + + + Arguments and Values + + + ptr + + A pointer to the allocated foreign object to free. + + + + + + + Description + + Frees the memory used by the allocation of a foreign object. + + + + Side Effects + None. + + + Affected by + None. + + + Exceptional Situations + None. + + + + + + + with-foreign-object + Wraps the allocation of a foreign object around a body of code. + + Macro + + + Syntax + + with-foreign-object (var type) &body body => form-return + + + + Arguments and Values + + + var + + The variable name to bind. + + + + + type + + The type of foreign object to allocate. This parameter is evaluated. + + + + + form-return + + The result of evaluating the body. + + + + + + + Description + +This function wraps the allocation, binding, and destruction of a foreign object. +On &cmucl; and +&lw; platforms the object is stack allocated for efficiency. Benchmarks show that &acl; performs +much better with static allocation. + + + + Examples + +(defun gethostname2 () + "Returns the hostname" + (uffi:with-foreign-object (name '(:array :unsigned-char 256)) + (if (zerop (c-gethostname (uffi:char-array-to-pointer name) 256)) + (uffi:convert-from-foreign-string name) + (error "gethostname() failed.")))) + + + + Side Effects + None. + + + Affected by + None. + + + Exceptional Situations + None. + + + + + + size-of-foreign-type + Returns the number of data bytes used by a foreign object type. + + Macro + + + Syntax + + size-of-foreign-type ftype + + + + Arguments and Values + + + ftype + + A foreign type specifier. This parameter is evaluated. + + + + + + + Description + + Returns the number of data bytes used by a foreign object type. This does not include any Lisp storage overhead. + + + + Examples + + +(size-of-foreign-object :unsigned-byte) +=> 1 +(size-of-foreign-object 'my-100-byte-vector-type) +=> 100 + + + + + Side Effects + None. + + Affected by + None. + + + Exceptional Situations + None. + + + + + + pointer-address + Returns the address of a pointer. + + Macro + + + Syntax + + pointer-address ptr => address + + + + Arguments and Values + + + ptr + + A pointer to a foreign object. + + + + + address + + An integer representing the pointer's address. + + + + + + + Description + + Returns the address as an integer of a pointer. + + + + Side Effects + None. + + + Affected by + None. + + + Exceptional Situations + None. + + + + + + + deref-pointer + Deferences a pointer. + + Macro + + + Syntax + + deref-pointer ptr type => value + + + + Arguments and Values + + + ptr + + A pointer to a foreign object. + + + + + type + + A foreign type of the object being pointed to. + + + + + value + + The value of the object where the pointer points. + + + + + + + Description + + Returns the object to which a pointer points. + + + + Examples + + +(let ((intp (allocate-foreign-object :int))) + (setf (deref-pointer intp :int) 10) + (prog1 + (deref-pointer intp :int) + (free-foreign-object intp))) +=> 10 + + + + + Notes + + The TYPE argument is ignored for CL implementations other than + AllegroCL. If you want to cast a pointer to another type use + WITH-CAST-POINTER together with DEREF-POINTER/DEREF-ARRAY. + + + + Side Effects + None. + + + Affected by + None. + + + Exceptional Situations + None. + + + + + + ensure-char-character + Ensures that a dereferenced :char pointer is +a character. + + Macro + + + Syntax + + ensure-char-character object => char + + + + Arguments and Values + + + object + + Either a character or a integer specifying a character code. + + + + + char + + A character. + + + + + + + Description + + Ensures that an objects obtained by dereferencing +:char and :unsigned-char +pointers are a lisp character. + + + + Examples + + +(let ((fs (convert-to-foreign-string "a"))) + (prog1 + (ensure-char-character (deref-pointer fs :char)) + (free-foreign-object fs))) +=> #\a + + + + + Side Effects + None. + + + Affected by + None. + + + Exceptional Situations + Depending upon the implementation and what &uffi; expects, this +macro may signal an error if the object is not a character or +integer. + + + + + + ensure-char-integer + Ensures that a dereferenced :char pointer is +an integer. + + Macro + + + Syntax + + ensure-char-integer object => int + + + + Arguments and Values + + + object + + Either a character or a integer specifying a character code. + + + + + int + + An integer. + + + + + + + Description + + Ensures that an object obtained by dereferencing a +:char pointer is an integer. + + + + Examples + + +(let ((fs (convert-to-foreign-string "a"))) + (prog1 + (ensure-char-integer (deref-pointer fs :char)) + (free-foreign-object fs))) +=> 96 + + + + + Side Effects + None. + + + Affected by + None. + + + Exceptional Situations + Depending upon the implementation and what &uffi; expects, this +macro may signal an error if the object is not a character or +integer. + + + + + + make-null-pointer + Create a &null; pointer. + + Macro + + + Syntax + + make-null-pointer type => ptr + + + + Arguments and Values + + + type + + A type of object to which the pointer refers. + + + + + ptr + + The &null; pointer of type type. + + + + + + + Description + + Creates a &null; pointer of a specified type. + + + + Side Effects + None. + + + Affected by + None. + + + Exceptional Situations + None. + + + + + + + null-pointer-p + Tests a pointer for &null; value. + + Macro + + + Syntax + + null-pointer-p ptr => is-null + + + + Arguments and Values + + + ptr + + A foreign object pointer. + + + + + is-null + + The boolean flag. + + + + + + + Description + + A predicate testing if a pointer is has a &null; value. + + + + Side Effects + None. + + + Affected by + None. + + + Exceptional Situations + None. + + + + + + + +null-cstring-pointer+ + A constant &null; cstring pointer. + + Constant + + + Description + + A &null; cstring pointer. This can be used for testing +if a cstring returned by a function is &null;. + + + + + + + with-cast-pointer + Wraps a body of code with a pointer cast to a new type. + + Macro + + + Syntax + + with-cast-pointer (binding-name ptr type) & body body => value + + + + Arguments and Values + + + binding-name + + A symbol which will be bound to the casted object. + + + + + ptr + + A pointer to a foreign object. + + + + + type + + A foreign type of the object being pointed to. + + + + + value + + The value of the object where the pointer points. + + + + + + + Description + + Executes BODY with POINTER cast to be a pointer to type TYPE. + BINDING-NAME is will be bound to this value during the execution of + BODY. + + This is a no-op in AllegroCL but will wrap BODY in a LET form if + BINDING-NAME is provided. + + This macro is meant to be used in conjunction with DEREF-POINTER or + DEREF-ARRAY. In Allegro CL the "cast" will actually take place in + DEREF-POINTER or DEREF-ARRAY. + + + + Examples + +(with-foreign-object (size :int) + ;; FOO is a foreign function returning a :POINTER-VOID + (let ((memory (foo size))) + (when (mumble) + ;; at this point we know for some reason that MEMORY points + ;; to an array of unsigned bytes + (with-cast-pointer (memory :unsigned-byte) + (dotimes (i (deref-pointer size :int)) + (do-something-with + (deref-array memory '(:array :unsigned-byte) i))))))) + + + + Side Effects + None. + + + Affected by + None. + + + Exceptional Situations + None. + + + + + + def-foreign-var + +Defines a symbol macro to access a variable in foreign code + + Macro + + + Syntax + + def-foreign-var name type module + + + + Arguments and Values + + + name + + +A string or list specificying the symbol macro's name. If it is a + string, that names the foreign variable. A Lisp name is created + by translating #\_ to #\- and by converting to upper-case in + case-insensitive Lisp implementations. If it is a list, the first + item is a string specifying the foreign variable name and the + second it is a symbol stating the Lisp name. + + + + + type + + A foreign type of the foreign variable. + + + + + module + + + A string specifying the module (or library) the foreign variable + resides in. (Required by Lispworks) + + + + + + + Description + +Defines a symbol macro which can be used to access (get and set) the +value of a variable in foreign code. + + + + Examples + + C code + + int baz = 3; + + typedef struct { + int x; + double y; + } foo_struct; + + foo_struct the_struct = { 42, 3.2 }; + + int foo () { + return baz; + } + + + +Lisp code + + (uffi:def-struct foo-struct + (x :int) + (y :double)) + + (uffi:def-function ("foo" foo) + () + :returning :int + :module "foo") + + (uffi:def-foreign-var ("baz" *baz*) :int "foo") + (uffi:def-foreign-var ("the_struct" *the-struct*) foo-struct "foo") + + +*baz* + => 3 + +(incf *baz*) + => 4 + +(foo) + => 4 + + + + + Side Effects + None. + + + Affected by + None. + + + Exceptional Situations + None. + + + + Added: branches/trunk-reorg/thirdparty/uffi/doc/ref_primitive.xml ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi/doc/ref_primitive.xml Mon Feb 11 09:06:27 2008 @@ -0,0 +1,279 @@ + + +%myents; +]> + + + Primitive Types + + Overview + + Primitive types have a single value, these include + characters, numbers, and pointers. They are all symbols in + the keyword package. + + + + :char - Signed 8-bits. A + dereferenced :char pointer returns an character. + + + + :unsigned-char - Unsigned 8-bits. A dereferenced :unsigned-char + pointer returns an character. + + + + :byte - Signed 8-bits. A + dereferenced :byte pointer returns an integer. + + + + :unsigned-byte - Unsigned 8-bits. A + dereferenced :unsigned-byte pointer returns an integer. + + + + :short - Signed 16-bits. + + + + :unsigned-short - Unsigned 16-bits. + + + + :int - Signed 32-bits. + + + :unsigned-int - Unsigned 32-bits. + + + :long - Signed 32 or 64 bits, depending upon the platform. + + + :unsigned-long - Unsigned 32 or 64 bits, depending upon the platform. + + + :float - 32-bit floating point. + + + :double - 64-bit floating point. + + + :cstring - + A &null; terminated string used for passing and returning characters strings with a &c; function. + + + + :void - + The absence of a value. Used to indicate that a function does not return a value. + + + + :pointer-void - Points to a generic object. + + + * - Used to declare a pointer to an object + + + + + + + def-constant + Binds a symbol to a constant. + + Macro + + + Syntax + + def-constant name value &key export + + + + Arguments and Values + + + name + + A symbol that will be bound to the value. + + + + + value + + An evaluated form that is bound the the name. + + + + + export + + When &t;, the name is exported from the current package. The default is &nil; + + + + + + Description + This is a thin wrapper around defconstant. It evaluates at + compile-time and optionally exports the symbol from the package. + + + + Examples + +(def-constant pi2 (* 2 pi)) +(def-constant exported-pi2 (* 2 pi) :export t) + + + + Side Effects + Creates a new special variable.. + + + Affected by + None. + + + Exceptional Situations + None. + + + + + + def-foreign-type + Defines a new foreign type. + + Macro + + + Syntax + + def-foreign-type name type + + + + Arguments and Values + + + name + + A symbol naming the new foreign type. + + + + + value + + A form that is not evaluated that defines the new + foreign type. + + + + + + + Description + Defines a new foreign type. + + + + Examples + +(def-foreign-type my-generic-pointer :pointer-void) +(def-foreign-type a-double-float :double-float) +(def-foreign-type char-ptr (* :char)) + + + + Side Effects + Defines a new foreign type. + + + + Affected by + None. + + + Exceptional Situations + None. + + + + + + null-char-p + Tests a character for &null; value. + + Macro + + + Syntax + + null-char-p char => is-null + + + + Arguments and Values + + + char + + A character or integer. + + + + + is-null + + A boolean flag indicating if char is a &null; value. + + + + + + + Description + + A predicate testing if a character or integer is &null;. This + abstracts the difference in implementations where some return a + character + and some return a + integer + whence dereferencing a + C + character pointer. + + + + Examples + +(def-array-pointer ca :unsigned-char) +(let ((fs (convert-to-foreign-string "ab"))) + (values (null-char-p (deref-array fs 'ca 0)) + (null-char-p (deref-array fs 'ca 2)))) +=> &nil; + &t; + + + + Side Effects + None. + + + + Affected by + None. + + + Exceptional Situations + None. + + + Added: branches/trunk-reorg/thirdparty/uffi/doc/ref_string.xml ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi/doc/ref_string.xml Mon Feb 11 09:06:27 2008 @@ -0,0 +1,514 @@ + + +%myents; +]> + + + Strings + + Overview + + &uffi; has functions to two types of C-compatible + strings: cstring and foreign + strings. cstrings are used only as parameters to + and from functions. In some implementations a cstring is not a foreign + type but rather the Lisp string itself. On other platforms a cstring + is a newly allocated foreign vector for storing characters. The + following is an example of using cstrings to both send and return a + value. + + + +(uffi:def-function ("getenv" c-getenv) + ((name :cstring)) + :returning :cstring) + +(defun my-getenv (key) + "Returns an environment variable, or NIL if it does not exist" + (check-type key string) + (uffi:with-cstring (key-native key) + (uffi:convert-from-cstring (c-getenv key-native)))) + + + + In contrast, foreign strings are always a foreign vector of + characters which have memory allocated. Thus, if you need to + allocate memory to hold the return value of a string, you must + use a foreign string and not a cstring. The following is an + example of using a foreign string for a return value. + + + +(uffi:def-function ("gethostname" c-gethostname) + ((name (* :unsigned-char)) + (len :int)) + :returning :int) + +(defun gethostname () + "Returns the hostname" + (let* ((name (uffi:allocate-foreign-string 256)) + (result-code (c-gethostname name 256)) + (hostname (when (zerop result-code) + (uffi:convert-from-foreign-string name)))) + ;; UFFI does not yet provide a universal way to free + ;; memory allocated by C's malloc. At this point, a program + ;; needs to call C's free function to free such memory. + (unless (zerop result-code) + (error "gethostname() failed.")))) + + + + Foreign functions that return pointers to freshly allocated + strings should in general not return cstrings, but foreign + strings. (There is no portable way to release such cstrings from + Lisp.) The following is an example of handling such a function. + + + +(uffi:def-function ("readline" c-readline) + ((prompt :cstring)) + :returning (* :char)) + +(defun readline (prompt) + "Reads a string from console with line-editing." + (with-cstring (c-prompt prompt) + (let* ((c-str (c-readline c-prompt)) + (str (convert-from-foreign-string c-str))) + (uffi:free-foreign-object c-str) + str))) + + + + + + + convert-from-cstring + Converts a cstring to a Lisp string. + Macro + + + Syntax + + convert-from-cstring + cstring + => + string + + + + Arguments and Values + + + cstring + + A cstring. + + + + + string + + A Lisp string. + + + + + + + Description + + Converts a Lisp string to a cstring. This is + most often used when processing the results of a foreign function + that returns a cstring. + + + + Side Effects + None. + + + Affected by + None. + + + Exceptional Situations + None. + + + + + + + convert-to-cstring + Converts a Lisp string to a cstring. + Macro + + + Syntax + + convert-to-cstring + string + => + cstring + + + + Arguments and Values + + + string + + A Lisp string. + + + + + cstring + + A cstring. + + + + + + + Description + + Converts a Lisp string to a cstring. The + cstring should be freed with + free-cstring. + + + + Side Effects + On some implementations, this function allocates memory. + + + Affected by + None. + + + Exceptional Situations + None. + + + + + + + free-cstring + Free memory used by cstring. + + Macro + + + Syntax + + free-cstring cstring + + + + Arguments and Values + + + cstring + + A cstring. + + + + + + + Description + + Frees any memory possibly allocated by + convert-to-cstring. On some implementions, a cstring is just the Lisp string itself. + + + + Side Effects + None. + + + Affected by + None. + + + Exceptional Situations + None. + + + + + + + with-cstring + Binds a newly created cstring. + Macro + + + Syntax + + with-cstring + (cstring string) {body} + + + + Arguments and Values + + + cstring + + A symbol naming the cstring to be created. + + + + + string + + A Lisp string that will be translated to a cstring. + + + + + body + + The body of where the cstring will be bound. + + + + + + + Description + + Binds a symbol to a cstring created from conversion of a + string. Automatically frees the cstring. + + + + Examples + + +(def-function ("getenv" c-getenv) + ((name :cstring)) + :returning :cstring) + +(defun getenv (key) + "Returns an environment variable, or NIL if it does not exist" + (check-type key string) + (with-cstring (key-cstring key) + (convert-from-cstring (c-getenv key-cstring)))) + + + + + Side Effects + None. + + + Affected by + None. + + + Exceptional Situations + None. + + + + + + + convert-from-foreign-string + Converts a foreign string into a Lisp string. + Macro + + + Syntax + + convert-from-foreign-string + foreign-string &key length null-terminated-p + => + string + + + + Arguments and Values + + + foreign-string + + A foreign string. + + + + + length + + The length of the foreign string to convert. The + default is the length of the string until a &null; + character is reached. + + + + + null-terminated-p + + A boolean flag with a default value of &t; When true, + the string is converted until the first &null; character is reached. + + + + + string + + A Lisp string. + + + + + + + Description + + Returns a Lisp string from a foreign string. + Can translated ASCII and binary strings. + + + + Side Effects + None. + + + Affected by + None. + + + Exceptional Situations + None. + + + + + + + convert-to-foreign-string + Converts a Lisp string to a foreign string. + + Macro + + + Syntax + + convert-to-foreign-string + string => + foreign-string + + + + Arguments and Values + + + string + + A Lisp string. + + + + + foreign-string + + A foreign string. + + + + + + + Description + + Converts a Lisp string to a foreign string. Memory should be + freed with free-foreign-object. + + + + Side Effects + None. + + + Affected by + None. + + + Exceptional Situations + None. + + + + + + allocate-foreign-string + Allocates space for a foreign string. + + Macro + + + Syntax + + allocate-foreign-string size + &key unsigned => + foreign-string + + + + Arguments and Values + + + size + + The size of the space to be allocated in bytes. + + + + + unsigned + + A boolean flag with a default value of &t;. When true, + marks the pointer as an :unsigned-char. + + + + + foreign-string + + A foreign string which has undefined contents. + + + + + + + Description + + Allocates space for a foreign string. Memory should + be freed with free-foreign-object. + + + + Side Effects + None. + + + Affected by + None. + + + Exceptional Situations + None. + + + + Added: branches/trunk-reorg/thirdparty/uffi/doc/schemas.xml ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi/doc/schemas.xml Mon Feb 11 09:06:27 2008 @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + Added: branches/trunk-reorg/thirdparty/uffi/doc/uffi.pdf ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi/doc/uffi.pdf Mon Feb 11 09:06:27 2008 @@ -0,0 +1,2920 @@ +%PDF-1.3 +%???? +4 0 obj +<< /Type /Info +/Producer (FOP 0.20.5) >> +endobj +5 0 obj +<< /Length 201 /Filter [ /ASCII85Decode /FlateDecode ] + >> +stream +GaqdX]aDVA&-UqjSmom=E4u;+CBYq42W:aU`jc=(4<^HFDa4C2;[pruRj?RM"`9CC5\c!@$)nLL3h\g!;4sXMmfN\;Ob/;ZJ4jmbWdP1T8;@d21LPNCB?%>c^1qP2i7r8X.ie[\P0lY%HhV`UBe#dQ"_J#\3Ui0X8G0l\r9 +endstream +endobj +6 0 obj +<< /Type /Page +/Parent 1 0 R +/MediaBox [ 0 0 595 842 ] +/Resources 3 0 R +/Contents 5 0 R +>> +endobj +7 0 obj +<< /Length 965 /Filter [ /ASCII85Decode /FlateDecode ] + >> +stream +Gau0Bhf%4&&:WfGn0=3URfk)AmA]JBeZIYgNc('34da.jX2/DV"(QiZ*"qb;,h;`ftfIG`k/p0G1qpZUq5AdCn<=r\6KFJq+B'#DKK+uASe#Y^7EH.-48iCMeot"J0k2]6$(m:faarMNY-s4#$fda!K$\]in at W.:rsbO`"bFihimpH/0d]2W`'Y)hQ6WChV at 0:hFQ?-t9M!XGE:B%rZ/K3PN*)V[[7-2Gd7P&&k.$Y2)-;<1#`(S\[k+:@&^f3gar)'V?+p3L_Vh9Ibga1?J*ZTNf3FWD&0q'?4/^OYR*$")_Ui#L7AHEUN,P]`Sqe^t.7$+>jT3DYW-\aR\nsG_kCnO9lShmE-OHGSHnO2l?:8eeTA)!*))0J;PpD3Ah65Y)fM^`@U1u;-cV-RmDqCj;RF/XPm5 at 2]Jb8-`#:9=8*YAh/K\#:e1Sh`L88OX6\FPZ_XDDVqi?;`(J$-AOdp;p<$-p'P;;5fCdZqc--*R.SO(,e0->AAR2DkCd5 at +JbD*JbOS4d<'MfB5,fRDq`W2EC,.o at sm$[U4k-2s#:5$5):NjsEfh6S$m&l'MeN]+MErK_%<=R0":5hUopj[22Kl;R+H#[9k%Q\PY1p9<'&f7 at i*$o%1]nO`Y,,r2u`B_t at aheY@Sq*.LdNo<&"a/-FjXAJ/NGa'N3o(jZFhcV4>eptt +endstream +endobj +8 0 obj +<< /Type /Page +/Parent 1 0 R +/MediaBox [ 0 0 595 842 ] +/Resources 3 0 R +/Contents 7 0 R +>> +endobj +9 0 obj +<< /Length 81 /Filter [ /ASCII85Decode /FlateDecode ] + >> +stream +Garg^iGoCd.c`?]8EV`b1=.gRYV7c]1UaMe0JP941GUmh0[MUU-q[K1isOjf_GG&\U1]Eh,lhpD'$^~> +endstream +endobj +10 0 obj +<< /Type /Page +/Parent 1 0 R +/MediaBox [ 0 0 595 842 ] +/Resources 3 0 R +/Contents 9 0 R +>> +endobj +11 0 obj +<< /Length 2067 /Filter [ /ASCII85Decode /FlateDecode ] + >> +stream +Gb"/l?#S1_'Sc)J.t"a>Kp)+Vq!/R8Qp3;[(4CMY00H#1/WGaZNbtG6]N-pY`Bc"dd6p!QCD?\p*V8A5bKp+irL:\qZ-,#ZX0!((/"V=&nJCVMNoUT<#$QVo*7aZ;dU(A1gE=d[MRFl;<<_1fn5%k%1!+563mltaW<4K%jgl761#=.Lk%_mVW4tZUsj>-9:=DB:apP&fVqXd"9RCbfPUX`3=LkNWSY5BnYIcQ10q$Q at U\0lZ`IBYUQ,P0L-eAfbZWC"8[9.WImqTHqUJb[q)lt5Q-PN$K?f<;V\Pca#-mjO4^Kb[6C(^!0aiQr(aI,`k../Ap=]9auBq`*SE6s/$B0djI`9n0J7_K?eDu5s7\q4pT!>&p`A42uu73,M-;6a7Va4\((Nn6nL\?1BKk=+N!3T"-8o:T%TGK^!+MhMk'[!%]4N2*!S!Y(NUkhQnl39.]R?5/loOu9fR+OKqJ#nGH**%:+VLT6XZm8ui&!.c0kRIK.CMK<5iEskj+X(>Fp\*7oXoJ+Fd:EBW?h*L2Y/T[O(b'[LW74i&VYHB"&EZlP:W$c>h4-1b;0==TP9Q)tlB$n`H*s?oBA/'E!dVBR;,om04SVEDQKB1Np%K_4L+VqTTH$VWVF#Vtjk$.*>Zmc9&ra_b at JTFUGp9g/uf at YSJ2Xa?_d>nkd-bfcq#W+Y!TuHC at ADI"de)dmZdTZ"._<#RM&PnLCJ3[J84*oi8CN[\!=)T^F6ZW:jK7Q9P8>U3F*M_1jpE?`t*NE(W0pHGSJ^0I<9&2*Y7]ae8b!1c'H15blpG$4a"M.BK\ijZL[iR?SSK=]8R;@Z:Eg6h>jZ5XL:f#PX6Q&V>Xj2(09bsB!gd*(0=6\Q.25!hDCjQ+GdV1pCl#UHIfP;q`g*WHh*^]#mi%!sA[R;VNZNq_bdSl(e"aTc4]!2\d&AM0F0Kt17CD2;'\_>TnQ`:J01-#X4r?^]G/sDYB8?sk[JqR>A"?N5qh>Lr[ApneD-FArt$)Vs!5\E>/"Lq[f,Y2f)WUE1S%IlkP+OD!f#m'J&2W:pQU>@KIgPCCQH-epS<^5BqPpS&&Q+r+>$.,4IJ\Ip8GNY@?,6Ok18eX#c!e$gFh0iTrXS_9WpKJiF2apd1APq-iI^/Z1Ik+HclS"7Y(eY5U9B*GFkl6e6/OjU9)uII)`JLLI6..1Nr+9Ff]_Ucpd?Eh^NC,m +endstream +endobj +12 0 obj +<< /Type /Page +/Parent 1 0 R +/MediaBox [ 0 0 595 842 ] +/Resources 3 0 R +/Contents 11 0 R +/Annots 13 0 R +>> +endobj +13 0 obj +[ +14 0 R +16 0 R +18 0 R +20 0 R +22 0 R +24 0 R +26 0 R +28 0 R +30 0 R +32 0 R +34 0 R +36 0 R +38 0 R +40 0 R +42 0 R +44 0 R +46 0 R +48 0 R +50 0 R +52 0 R +54 0 R +56 0 R +58 0 R +60 0 R +62 0 R +64 0 R +66 0 R +68 0 R +70 0 R +72 0 R +74 0 R +76 0 R +78 0 R +80 0 R +82 0 R +84 0 R +86 0 R +88 0 R +90 0 R +92 0 R +94 0 R +96 0 R +98 0 R +100 0 R +102 0 R +104 0 R +106 0 R +108 0 R +110 0 R +112 0 R +114 0 R +116 0 R +118 0 R +120 0 R +122 0 R +124 0 R +126 0 R +] +endobj +14 0 obj +<< /Type /Annot +/Subtype /Link +/Rect [ 120.0 704.89 149.98 694.89 ] +/C [ 0 0 0 ] +/Border [ 0 0 0 ] +/A 15 0 R +/H /I +>> +endobj +16 0 obj +<< /Type /Annot +/Subtype /Link +/Rect [ 120.0 693.89 179.44 683.89 ] +/C [ 0 0 0 ] +/Border [ 0 0 0 ] +/A 17 0 R +/H /I +>> +endobj +18 0 obj +<< /Type /Annot +/Subtype /Link +/Rect [ 144.0 682.89 176.22 672.89 ] +/C [ 0 0 0 ] +/Border [ 0 0 0 ] +/A 19 0 R +/H /I +>> +endobj +20 0 obj +<< /Type /Annot +/Subtype /Link +/Rect [ 144.0 671.89 192.88 661.89 ] +/C [ 0 0 0 ] +/Border [ 0 0 0 ] +/A 21 0 R +/H /I +>> +endobj +22 0 obj +<< /Type /Annot +/Subtype /Link +/Rect [ 144.0 660.89 254.83 650.89 ] +/C [ 0 0 0 ] +/Border [ 0 0 0 ] +/A 23 0 R +/H /I +>> +endobj +24 0 obj +<< /Type /Annot +/Subtype /Link +/Rect [ 144.0 649.89 172.33 639.89 ] +/C [ 0 0 0 ] +/Border [ 0 0 0 ] +/A 25 0 R +/H /I +>> +endobj +26 0 obj +<< /Type /Annot +/Subtype /Link +/Rect [ 168.0 638.89 207.43 628.89 ] +/C [ 0 0 0 ] +/Border [ 0 0 0 ] +/A 27 0 R +/H /I +>> +endobj +28 0 obj +<< /Type /Annot +/Subtype /Link +/Rect [ 168.0 627.89 204.67 617.89 ] +/C [ 0 0 0 ] +/Border [ 0 0 0 ] +/A 29 0 R +/H /I +>> +endobj +30 0 obj +<< /Type /Annot +/Subtype /Link +/Rect [ 120.0 616.89 210.83 606.89 ] +/C [ 0 0 0 ] +/Border [ 0 0 0 ] +/A 31 0 R +/H /I +>> +endobj +32 0 obj +<< /Type /Annot +/Subtype /Link +/Rect [ 144.0 605.89 268.43 595.89 ] +/C [ 0 0 0 ] +/Border [ 0 0 0 ] +/A 33 0 R +/H /I +>> +endobj +34 0 obj +<< /Type /Annot +/Subtype /Link +/Rect [ 168.0 594.89 211.33 584.89 ] +/C [ 0 0 0 ] +/Border [ 0 0 0 ] +/A 35 0 R +/H /I +>> +endobj +36 0 obj +<< /Type /Annot +/Subtype /Link +/Rect [ 168.0 583.89 210.22 573.89 ] +/C [ 0 0 0 ] +/Border [ 0 0 0 ] +/A 37 0 R +/H /I +>> +endobj +38 0 obj +<< /Type /Annot +/Subtype /Link +/Rect [ 168.0 572.89 203.56 562.89 ] +/C [ 0 0 0 ] +/Border [ 0 0 0 ] +/A 39 0 R +/H /I +>> +endobj +40 0 obj +<< /Type /Annot +/Subtype /Link +/Rect [ 144.0 561.89 314.52 551.89 ] +/C [ 0 0 0 ] +/Border [ 0 0 0 ] +/A 41 0 R +/H /I +>> +endobj +42 0 obj +<< /Type /Annot +/Subtype /Link +/Rect [ 144.0 550.89 263.73 540.89 ] +/C [ 0 0 0 ] +/Border [ 0 0 0 ] +/A 43 0 R +/H /I +>> +endobj +44 0 obj +<< /Type /Annot +/Subtype /Link +/Rect [ 168.0 539.89 216.88 529.89 ] +/C [ 0 0 0 ] +/Border [ 0 0 0 ] +/A 45 0 R +/H /I +>> +endobj +46 0 obj +<< /Type /Annot +/Subtype /Link +/Rect [ 168.0 528.89 312.72 518.89 ] +/C [ 0 0 0 ] +/Border [ 0 0 0 ] +/A 47 0 R +/H /I +>> +endobj +48 0 obj +<< /Type /Annot +/Subtype /Link +/Rect [ 120.0 517.89 178.87 507.89 ] +/C [ 0 0 0 ] +/Border [ 0 0 0 ] +/A 49 0 R +/H /I +>> +endobj +50 0 obj +<< /Type /Annot +/Subtype /Link +/Rect [ 144.0 506.89 177.32 496.89 ] +/C [ 0 0 0 ] +/Border [ 0 0 0 ] +/A 51 0 R +/H /I +>> +endobj +52 0 obj +<< /Type /Annot +/Subtype /Link +/Rect [ 120.0 495.89 195.83 485.89 ] +/C [ 0 0 0 ] +/Border [ 0 0 0 ] +/A 53 0 R +/H /I +>> +endobj +54 0 obj +<< /Type /Annot +/Subtype /Link +/Rect [ 144.0 484.89 193.43 474.89 ] +/C [ 0 0 0 ] +/Border [ 0 0 0 ] +/A 55 0 R +/H /I +>> +endobj +56 0 obj +<< /Type /Annot +/Subtype /Link +/Rect [ 144.0 473.89 209.53 463.89 ] +/C [ 0 0 0 ] +/Border [ 0 0 0 ] +/A 57 0 R +/H /I +>> +endobj +58 0 obj +<< /Type /Annot +/Subtype /Link +/Rect [ 144.0 462.89 188.43 452.89 ] +/C [ 0 0 0 ] +/Border [ 0 0 0 ] +/A 59 0 R +/H /I +>> +endobj +60 0 obj +<< /Type /Annot +/Subtype /Link +/Rect [ 120.0 451.89 203.58 441.89 ] +/C [ 0 0 0 ] +/Border [ 0 0 0 ] +/A 61 0 R +/H /I +>> +endobj +62 0 obj +<< /Type /Annot +/Subtype /Link +/Rect [ 144.0 440.89 182.32 430.89 ] +/C [ 0 0 0 ] +/Border [ 0 0 0 ] +/A 63 0 R +/H /I +>> +endobj +64 0 obj +<< /Type /Annot +/Subtype /Link +/Rect [ 144.0 429.89 182.32 419.89 ] +/C [ 0 0 0 ] +/Border [ 0 0 0 ] +/A 65 0 R +/H /I +>> +endobj +66 0 obj +<< /Type /Annot +/Subtype /Link +/Rect [ 144.0 418.89 198.99 408.89 ] +/C [ 0 0 0 ] +/Border [ 0 0 0 ] +/A 67 0 R +/H /I +>> +endobj +68 0 obj +<< /Type /Annot +/Subtype /Link +/Rect [ 144.0 407.89 205.66 397.89 ] +/C [ 0 0 0 ] +/Border [ 0 0 0 ] +/A 69 0 R +/H /I +>> +endobj +70 0 obj +<< /Type /Annot +/Subtype /Link +/Rect [ 144.0 396.89 212.3 386.89 ] +/C [ 0 0 0 ] +/Border [ 0 0 0 ] +/A 71 0 R +/H /I +>> +endobj +72 0 obj +<< /Type /Annot +/Subtype /Link +/Rect [ 144.0 385.89 188.41 375.89 ] +/C [ 0 0 0 ] +/Border [ 0 0 0 ] +/A 73 0 R +/H /I +>> +endobj +74 0 obj +<< /Type /Annot +/Subtype /Link +/Rect [ 144.0 374.89 182.88 364.89 ] +/C [ 0 0 0 ] +/Border [ 0 0 0 ] +/A 75 0 R +/H /I +>> +endobj +76 0 obj +<< /Type /Annot +/Subtype /Link +/Rect [ 120.0 363.89 166.1 353.89 ] +/C [ 0 0 0 ] +/Border [ 0 0 0 ] +/A 77 0 R +/H /I +>> +endobj +78 0 obj +<< /Type /Annot +/Subtype /Link +/Rect [ 144.0 352.89 235.08 342.89 ] +/C [ 0 0 0 ] +/Border [ 0 0 0 ] +/A 79 0 R +/H /I +>> +endobj +80 0 obj +<< /Type /Annot +/Subtype /Link +/Rect [ 144.0 341.89 219.52 331.89 ] +/C [ 0 0 0 ] +/Border [ 0 0 0 ] +/A 81 0 R +/H /I +>> +endobj +82 0 obj +<< /Type /Annot +/Subtype /Link +/Rect [ 144.0 330.89 221.76 320.89 ] +/C [ 0 0 0 ] +/Border [ 0 0 0 ] +/A 83 0 R +/H /I +>> +endobj +84 0 obj +<< /Type /Annot +/Subtype /Link +/Rect [ 144.0 319.89 223.97 309.89 ] +/C [ 0 0 0 ] +/Border [ 0 0 0 ] +/A 85 0 R +/H /I +>> +endobj +86 0 obj +<< /Type /Annot +/Subtype /Link +/Rect [ 144.0 308.89 205.65 298.89 ] +/C [ 0 0 0 ] +/Border [ 0 0 0 ] +/A 87 0 R +/H /I +>> +endobj +88 0 obj +<< /Type /Annot +/Subtype /Link +/Rect [ 144.0 297.89 196.2 287.89 ] +/C [ 0 0 0 ] +/Border [ 0 0 0 ] +/A 89 0 R +/H /I +>> +endobj +90 0 obj +<< /Type /Annot +/Subtype /Link +/Rect [ 144.0 286.89 230.61 276.89 ] +/C [ 0 0 0 ] +/Border [ 0 0 0 ] +/A 91 0 R +/H /I +>> +endobj +92 0 obj +<< /Type /Annot +/Subtype /Link +/Rect [ 144.0 275.89 221.74 265.89 ] +/C [ 0 0 0 ] +/Border [ 0 0 0 ] +/A 93 0 R +/H /I +>> +endobj +94 0 obj +<< /Type /Annot +/Subtype /Link +/Rect [ 144.0 264.89 216.21 254.89 ] +/C [ 0 0 0 ] +/Border [ 0 0 0 ] +/A 95 0 R +/H /I +>> +endobj +96 0 obj +<< /Type /Annot +/Subtype /Link +/Rect [ 144.0 253.89 199.55 243.89 ] +/C [ 0 0 0 ] +/Border [ 0 0 0 ] +/A 97 0 R +/H /I +>> +endobj +98 0 obj +<< /Type /Annot +/Subtype /Link +/Rect [ 144.0 242.89 233.05 232.89 ] +/C [ 0 0 0 ] +/Border [ 0 0 0 ] +/A 99 0 R +/H /I +>> +endobj +100 0 obj +<< /Type /Annot +/Subtype /Link +/Rect [ 144.0 231.89 212.32 221.89 ] +/C [ 0 0 0 ] +/Border [ 0 0 0 ] +/A 101 0 R +/H /I +>> +endobj +102 0 obj +<< /Type /Annot +/Subtype /Link +/Rect [ 144.0 220.89 205.08 210.89 ] +/C [ 0 0 0 ] +/Border [ 0 0 0 ] +/A 103 0 R +/H /I +>> +endobj +104 0 obj +<< /Type /Annot +/Subtype /Link +/Rect [ 120.0 209.89 160.56 199.89 ] +/C [ 0 0 0 ] +/Border [ 0 0 0 ] +/A 105 0 R +/H /I +>> +endobj +106 0 obj +<< /Type /Annot +/Subtype /Link +/Rect [ 144.0 198.89 227.31 188.89 ] +/C [ 0 0 0 ] +/Border [ 0 0 0 ] +/A 107 0 R +/H /I +>> +endobj +108 0 obj +<< /Type /Annot +/Subtype /Link +/Rect [ 144.0 187.89 215.65 177.89 ] +/C [ 0 0 0 ] +/Border [ 0 0 0 ] +/A 109 0 R +/H /I +>> +endobj +110 0 obj +<< /Type /Annot +/Subtype /Link +/Rect [ 144.0 176.89 190.09 166.89 ] +/C [ 0 0 0 ] +/Border [ 0 0 0 ] +/A 111 0 R +/H /I +>> +endobj +112 0 obj +<< /Type /Annot +/Subtype /Link +/Rect [ 144.0 165.89 192.33 155.89 ] +/C [ 0 0 0 ] +/Border [ 0 0 0 ] +/A 113 0 R +/H /I +>> +endobj +114 0 obj +<< /Type /Annot +/Subtype /Link +/Rect [ 144.0 154.89 255.08 144.89 ] +/C [ 0 0 0 ] +/Border [ 0 0 0 ] +/A 115 0 R +/H /I +>> +endobj +116 0 obj +<< /Type /Annot +/Subtype /Link +/Rect [ 144.0 143.89 243.42 133.89 ] +/C [ 0 0 0 ] +/Border [ 0 0 0 ] +/A 117 0 R +/H /I +>> +endobj +118 0 obj +<< /Type /Annot +/Subtype /Link +/Rect [ 144.0 132.89 233.42 122.89 ] +/C [ 0 0 0 ] +/Border [ 0 0 0 ] +/A 119 0 R +/H /I +>> +endobj +120 0 obj +<< /Type /Annot +/Subtype /Link +/Rect [ 120.0 121.89 223.88 111.89 ] +/C [ 0 0 0 ] +/Border [ 0 0 0 ] +/A 121 0 R +/H /I +>> +endobj +122 0 obj +<< /Type /Annot +/Subtype /Link +/Rect [ 144.0 110.89 193.43 100.89 ] +/C [ 0 0 0 ] +/Border [ 0 0 0 ] +/A 123 0 R +/H /I +>> +endobj +124 0 obj +<< /Type /Annot +/Subtype /Link +/Rect [ 144.0 99.89 223.42 89.89 ] +/C [ 0 0 0 ] +/Border [ 0 0 0 ] +/A 125 0 R +/H /I +>> +endobj +126 0 obj +<< /Type /Annot +/Subtype /Link +/Rect [ 144.0 88.89 222.31 78.89 ] +/C [ 0 0 0 ] +/Border [ 0 0 0 ] +/A 127 0 R +/H /I +>> +endobj +128 0 obj +<< /Length 395 /Filter [ /ASCII85Decode /FlateDecode ] + >> +stream +Gb"/g:J8Sj&B4,8.H[!;h!T(Rn'RjY'ed^U&eDfr8g#IJ<5ieE/h%+X._W7<-'o^;H'q/FO3Gm$RcOT!_$"S2#cnUAi\(Y'Kqa_='4J\j^ghDA;n-3Ze<=ImDi2+Y2HALbWm[RZ)M\-O,"4O';A9L0\5(uhm*1b;S;.4ZF at qXqp7nVA@^YTnj`8S:;5H.Io"463c^1Cpr/`T^G6a\YMhr/4*9loWi+2[ZDg`I%c.Zs#<6)Ef.8ls?$B/Bu@:fk*7G[Zcd=$=<`l5327uA#Fs3`fLbVj[J/UAEI6&+;P*,!t*-Q-Mg!:e=)K+d"6\_Xm10Y`88*uV93LMnh<@Zg%kmTo' +endstream +endobj +129 0 obj +<< /Type /Page +/Parent 1 0 R +/MediaBox [ 0 0 595 842 ] +/Resources 3 0 R +/Contents 128 0 R +/Annots 130 0 R +>> +endobj +130 0 obj +[ +131 0 R +133 0 R +135 0 R +137 0 R +] +endobj +131 0 obj +<< /Type /Annot +/Subtype /Link +/Rect [ 120.0 768.889 177.22 758.889 ] +/C [ 0 0 0 ] +/Border [ 0 0 0 ] +/A 132 0 R +/H /I +>> +endobj +133 0 obj +<< /Type /Annot +/Subtype /Link +/Rect [ 144.0 757.889 210.93 747.889 ] +/C [ 0 0 0 ] +/Border [ 0 0 0 ] +/A 134 0 R +/H /I +>> +endobj +135 0 obj +<< /Type /Annot +/Subtype /Link +/Rect [ 144.0 746.889 177.33 736.889 ] +/C [ 0 0 0 ] +/Border [ 0 0 0 ] +/A 136 0 R +/H /I +>> +endobj +137 0 obj +<< /Type /Annot +/Subtype /Link +/Rect [ 120.0 735.889 155.55 725.889 ] +/C [ 0 0 0 ] +/Border [ 0 0 0 ] +/A 138 0 R +/H /I +>> +endobj +139 0 obj +<< /Length 590 /Filter [ /ASCII85Decode /FlateDecode ] + >> +stream +Gasam9lHOU&A at ZcHqY%9q?(6;7d:'Sdj12lj?7_goqSQu!$dijlE3"3/-*^N6q+X%eOOKE_2c)c,smE<43&Nmfe5`:gs5bX5R2"l8\`E$^`J]Pfn_P;7":!n-&%nfP\O%`C5RMj:e"hiP$$&6rVjhH#:O4=B1WPkS(?j%8l*IH:id>GPuA*Odr9IWR8dpqkq&ag2Ic5c&G8D][DM=$cX<%FcC'^1pfD/f4 at 2%$FdMVr:aUa@`.cT!W\\E5hk0!;W<8BGEo,Q1.k4lk_>k,f-W!)s?lb[Li(e<7$oH0,NbJj\6fe?_+`]>?_k0oUVEkJP(Vm2F5g"T0JcA]'VWq#P1U\?)5X+_l!\pVQ at H!CE[r9ne%Hi:-RBM68d/LuppI3Y6_";"b2b"9)~> +endstream +endobj +140 0 obj +<< /Type /Page +/Parent 1 0 R +/MediaBox [ 0 0 595 842 ] +/Resources 3 0 R +/Contents 139 0 R +>> +endobj +141 0 obj +<< /Length 2030 /Filter [ /ASCII85Decode /FlateDecode ] + >> +stream +Gatm<968iG&AJ$Cn.oY+AdH-(>HPi7FI^8ibL=Zl4[:8@@8%7a84n#SI?t"+/7m7Mg5IZ>Ks:@G]tj=+in]T,\\9*)T!c]o*,BU]/-gXBMHno at +tp2'0=4bAl]96NQ<"HYDlkNKMX2U3P0gccp6bh]2H"(&g2Kp'[JmO6^T'(046knf-h8;8::s->^M at C,C,YDc/E4HpclV1iN%bHE^8j/o[_2#>KUoVGa`8_2R52\6Zog]d`p-Oo262LB_Ipp!IV4f53=e&-+(%:qL63J\j"1X[.Q*h59crU(+_nHm6-E0m!H:342jL,?YP>7MfT)4+#&-.pa]K'd-WqLfa)RUlr(<4s'kM`)oQdJoV=OfgsMVg%dt5'?$9U$Z#S,=V>F.I+GE'n8kl6W!BbA'J%bLsV1W:dpgaG6/iagNOG,85Zu"5dYtj at Wi6*]@=`)!+gn9g_\gEk]eCt][RFXUanG3W'd:IZ&(t+Pk_NK!ut0j!AlqV5gq2LeG#pC2#G(XXeC"2#)O-$/Gfa\rnGf,X1g`J)Ns7L..e[9>LKf0qGN4/9nanCqEb->caenF?A[C?TX:H7<>hQg\md,7H&=Sp&t2!&W*a>@/p32NXq1. at HeqFMS1$a6UWe'UnNp2)Siufb;MVA.7#NC]MQF"E*:\[l!;:4:h(?F@[fpBg.<,NW32sL8&N0G$p;o(9/]2p6P-/G]47]L.k$j(A"4W9\IjN:kM,a at 5Qe841,Hg2t`)(T$?NQ at Dmpm(-8#'EK;Dh,AuRq&N$_se?_a8#G1<.rO@`:\<;6;3_gdVX<->%M)_\G"_e2^E/1N6S5!V5bTd8el3Pe*+S37e-LkaS9GB]c3mi0-iD8?92ZQgN6M5Cs0Gs,A[g)%;L*#DXjRW%]bpfB:q>BaMQBs0qmMj:#p&06TnEjUlW-\P>N?bLj>ruB:f_#pH`bLm"%-r+DB&\@7J%_=(!PUp52"'YN6-)P)_Z(\rs"MM8>Z%@A00_U-#E_"C::,p\4(tG71N.iNVP+7:%.sF4N#Ya-POP-/SiY5Vk7/J7b(eda3KHQakC'=3q.ZoTnc!S`kmNFom_j[u]B(:\2\$'Xf;q9UUTX!4TcJ:CZtM7#VGu08msT(iLSLWi2*NEXEAZBXb2.sV61A'9N\_*IkcWSldIbW\fCQ,_Kf_m>,lMsa+7De=-IVRTB7!/XpRQcZ(V%r^3BNb%`!OY]Sf>=_&r/c*"QMWMII[!B5+N^f.fUq-?DZe*mPR>7U+>YZ571l0<1]a;QV&h:>q._p,I7+LcIs6&I:A+Yaa/fT^Sct)tc%t*d7B&JIlg,8>0&c=86sF?-Il1;J;u#<l]EG53 at K9Ae+%5`Ye]^>%JB4=X8(WdPS +endstream +endobj +142 0 obj +<< /Type /Page +/Parent 1 0 R +/MediaBox [ 0 0 595 842 ] +/Resources 3 0 R +/Contents 141 0 R +>> +endobj +143 0 obj +<< /Length 996 /Filter [ /ASCII85Decode /FlateDecode ] + >> +stream +GasIg95g=S&AIV:i0[&A8)]Xn0B6D"ZsnN]RNA^dWF.=D;XNHMHm=_4u,]KAknM1XCp;gl^o+b0H(!+"R;i9SSJI`EX+N-sk[*q==*fW!"2A>h`2$f.(pp9&l-p6spl5r3JjOgM!8(G)oj2('l8rlI]A8HeO'V,NnQ at pB(/L2)lRWT])gt#+CtLd9AfK*kH)S5e!>G",!0,3luu'h,e#hr]AOL*kJpNgm>ZgfaB%KRn\,_pOb\-BpacbM#^D>](6\T^K&02#-E42([YlQg*B8L"W8V4VSL"fJ<;D^5A9e,kuP(/N#"gb.NgnI>?h"VE*Z891C#5?kk[Tu=E:'ngPqNc)mU&Q[Sc%qRJ-6L2Dc9@@4h=nJp^Q>+`MAP>V1e!rE,p^4rH@*,TgGj!Y'FL]9Y"]Q$hpMgI=d$Y;'Ri'X3Sk>LHNTb"D%NE7=$V9s0D7AU5^(XK2,<-`qpEN*\.N9j$-VEno!sYS.f-,o4P[+3rs"5"UFeg#p:If(@dl->.RE6&^ch>Ar_'NP"/hjr8"l+qeqSg9N)V-HeB\&4TYOD[]PUJBZm*hRo%R6I-s*9MaRY*e@#/RBYZ'VXS0Rg#LF[[eeRBJt2Qsf_(ZjD0oO&8^L)c.+,"GP[-JW?rr>IB>Z(~> +endstream +endobj +144 0 obj +<< /Type /Page +/Parent 1 0 R +/MediaBox [ 0 0 595 842 ] +/Resources 3 0 R +/Contents 143 0 R +>> +endobj +145 0 obj +<< /Length 2451 /Filter [ /ASCII85Decode /FlateDecode ] + >> +stream +Gat%%99\/>&\d_;i([,"%a=Z72bTDf46=CP4??V*E(P#)LbFl1Xk(6N+<*R)32 at q$WNBWZ!4j,/IKB?)r:%U&i:nHge%dtF&$Bu!n/PO/4=BZelQed9U*+X)Xn2GEO**Y1I!k+Ir$5]Rl=RO0QHYH/"5E at LrCMTDA-)q6tGE.nFecZ>cs)'&AX\5lq[KDMNtU]USLqoUY-2\8gN at rGCJHW'k'h>:Emqr:EHL*/?)p6 at N_hIMr$D^Sk`;9PL"J94?s9 at N&SLn]S9u1J/l-7@>p]h`_p,J$R`U%%*Z at Yi_o,\[ZI!q#u'MK52quqnhN4GA)r`o&W9/]'IY_=GNk*I-G2A[C%2[j2g(\MeK)S8bW,`Bdu;==R[b#gn0rOVmj4cr$"75sh]lAqB^S^0A!VZ#V%H.nd`1523l.EZY>VcgBsXFD7$F>3pZGnGMe[p6MaKg:'/TA?Y!_CRuO#Z*!YRHqHM2Rj2iYLC^")_:L)#"n,`Q2Ks*c0D!0c?%bHd5JsXI$ANSOckc8rjmZFhc&l1b]SE+\(g,EN at NJd/!eQ9/0F]>Wu+iG,EhapQc<]"C#V"'A2['AJf2>>Ll*VWM%$MaVO*OD=>\/>1B*8o2:"q4XN0c;n+`9r<,>(%:3/Yj"#Ymmk[ELk$96N1eDlAQHU^RNi_LnK_^&gp$.q,=4lX7l0_O8kHm5BY"XHbg-YleeWqK*`JT>aNL$B9UOXN[F<.3Xj!,c5["+feTTJGH.QplkX;hm%d4M&gX,7*/r8s!#KjEE+,l4(2Lf-qD=Z)->gq)T%^)YL/i*.W>_uL5M!pp_s`6 at V1R]aQT]H2%?RoNF;0TAR%cJ6[L!N6>?!\2h:0cnsmo[,!@K>F3ca,o:kZkf.5`4QoDI84".an6kkYXl\4Tekepe=DZRQV;?.ac[QeKq*Vr0i-Qd7RBY$44RfJmOt6<9QfgSqVb5/S$aVaHep)0OtH[lg+1VHnW5(4l6WLlp`m?bKk,*eX&4bfXI4"SKl4Q&\\=nq8,(1":aJD<-&$HH)X50,?a`rRi+d<"@/B^V0MCjP/*,t""'#6rOMKZA`g"nMWCBb:ML+.)biM;Q#'l*-ejp__Du^u)PAulJXh*@gF."&1.6TV?hcQ[k5Z+c)o@,iBT;(@)\Q+3>@..`ZXqRH].CJV(Cd7M9+]qN)ISVkNZgg/L9VIHA6NUc27mkX_"X7`-2()+?8QH!+8U0m-dk',,&,,!Aq5k9]$pZ9ZjB*\"nK*;0n'Wp5L^uQ6KZI!ZPI7ZN77eM?6*eG;c?ZE4C4Al3%dt34,`H:3N6UPEhoR at GU#`trD2n3^9l1/fmY at GZ%l9%qna6RTaO"$IM[D["(]*I-j6OjHs9/J+Ou/G at 0.IjZA6j7<7fH:8u*;NE5+Ea+\-3L=^tc,58kWbD<5Ac`d*qXe/siR>`bZ&@;;(&Agi2JE>pK'YOSN at P0WaqB:?&k^g4,lT][5()R2WTa13m$BdO\9J'/Z4C'Z*>IZn"]e)F3k&;$?-WalfK%J/\O_gs7iUr;4is6Hk7Q,3)%QYq?(XR_B^XP3IUX#*mqo):9M[jeG@oScJXUV!SBJ#R:$Y/Q,sD]OuudP\3d;Y+MQ/2s/3&:+^ICfNf/c4<'bo64B'0FCr2;kpa4]:G*\ZB+&cqlD/3k`P=X&YAW#_g6Uq=CXar0b7!V-ro>YZ5lDccX_WI&]9P9DVg$H1tOF9fPb#l_"*Vj>j>[6*bt`Z-ed$jOtP.Hqcf+kgcB\hS&pQ"g8iKA%0CemBqt*kNC-FOb'n at eTQ2giCJfYQN8TVCMC"GTJq>+Z]uX[11cDYqfAb0$Lep:,[,Gr;8gk/]&FBVaQFp)K-,k"31gI8Hk25bV1Y\ROH::5K"N=?G,Y6,A\h>uTT=MO4,G^pC$)0=O=QSF/HYmV=c/9sh;bD#KC@["MPsl#N!G&M1GFKu5fgL[#o_Im^Wl06e>>H_T at b4U=[hF#U3cL6<%L8>YoT"*/^_4u7C&!Vq50I;^;Z;'lh&DC::"'pSbfpjN-U;9VB"?_mb1pb0+Y\X3~> +endstream +endobj +146 0 obj +<< /Type /Page +/Parent 1 0 R +/MediaBox [ 0 0 595 842 ] +/Resources 3 0 R +/Contents 145 0 R +>> +endobj +147 0 obj +<< /Length 302 /Filter [ /ASCII85Decode /FlateDecode ] + >> +stream +Garo<4&U9;3%P9+r7(;"`Q\cjW9#qBR3V\%olqEW.%a-L(eVj]Kbq at 6g/QR579;Q[Jn6 +endstream +endobj +148 0 obj +<< /Type /Page +/Parent 1 0 R +/MediaBox [ 0 0 595 842 ] +/Resources 3 0 R +/Contents 147 0 R +>> +endobj +149 0 obj +<< /Length 468 /Filter [ /ASCII85Decode /FlateDecode ] + >> +stream +GarnS9iHZu'YO#fEi_&S#!rq^g8YCU:<+573?GDQ`Jd&9J_'\`%3KG#XhuHsm(Sg7H*bH$H(ZPkE>297Ccm;)cUYp&^1B"_ka/+eRZa1_VkK(?@e_(>^^&<)LaWZt!'8b#j_^eeh78XRYOd^2VFUpI3?NFES7g+=G`$u%sGn(F0Vk@,KAqN(3qOp3YY4r&ln*/a_2bh_7pgq:n.~> +endstream +endobj +150 0 obj +<< /Type /Page +/Parent 1 0 R +/MediaBox [ 0 0 595 842 ] +/Resources 3 0 R +/Contents 149 0 R +>> +endobj +151 0 obj +<< /Length 820 /Filter [ /ASCII85Decode /FlateDecode ] + >> +stream +GatU29on!^&A at ZcHn/0*l>J&`Z!EHig6F/9?:k_O3,Bk'ck+q%n*;6L*S?HR.k]'(2tQt0_`S'SG;Fu0!pZI%*al>m&;8;`+ at Q;U`<@[+;37O at _l#3=,P2'A*t:gbK$=;u3WfYi*/[UTZiR7N4>)[V!ub*8rA\%[WiYllj!<*#lNln0%saW+RC,7*qjk-pW,U^i]!tQWW!"?ckeB*,3C$MSj`9c"T%PM.g`n$OV;8Bm+2bXr8kh?I8CEK:._We!kDK^!C?N6hqOTpCV+>6piYW27,S:*UfCLW+L>(=r(h3IGVEpXOiVBK8,M\dHbXbHOoi!-n;N_r)u1_]c>mi]O]iEbMCnjYH-5'.6J\%1DQ4qefHTmYXaF&92cTmWpS/6$Q]<=0R$6Xm*J-iBY\L^n`<\gH0b)m(Ei#WsYD(Ju:_X7:%G]-us4j8CpKWgpSskP1".]j6r=uRXPrChD1H&K:gEgKDM*nc'%^H`%_ at o">VB)BG:uk$m(#d_kte^j5abbp]=!oFX +endstream +endobj +152 0 obj +<< /Type /Page +/Parent 1 0 R +/MediaBox [ 0 0 595 842 ] +/Resources 3 0 R +/Contents 151 0 R +>> +endobj +153 0 obj +<< /Length 1246 /Filter [ /ASCII85Decode /FlateDecode ] + >> +stream +Gau`T?*g"Y&:O;Vd,RhJ<^6`VnWm^SLJF^@-etVq%iBsoK#-QdGPpof/_66RmeP2/Mi(?\#+s>]fm$GgCq"?ofs)U.^%\3Q-'1[(L8VW9fO+h%H'RH8noM.1fULU'&/\eMSUV'GK:,"WU_qcs2UCWXoXR=%r4acFZQ`.MV/cHAV)0)7m)nJUhf_:1 at P]!+JW at IE'Nd=[:X?q*PQg7r%<'d9WfsebakZ5J0PLN=8V7^NNhp.^$tX4.JI!"J"bf at M\N1KS"B4]C24 at A;0>t0P[:2EifGpp&25ZKh7"Q7C)VOJSd0$CDi2i`S+dA?eS-]e,YCV[a27*#?>1O5sp`_&\-90L5Yk]u4e_ojjq^qBTCq4I-AbZ0*F:o*!!@pPgOVAV[AT[PYou`cMuMT$4QFo8ugo;TKq/mX;]_j>@ChWQt[YT;0Z'o#IT-cbAN#rr,3D75==;,W)\bau7"QhF5o4be\C5jVYD@`A[Bchc`(4FOX5Nrrk?/:U0~> +endstream +endobj +154 0 obj +<< /Type /Page +/Parent 1 0 R +/MediaBox [ 0 0 595 842 ] +/Resources 3 0 R +/Contents 153 0 R +>> +endobj +155 0 obj +<< /Length 961 /Filter [ /ASCII85Decode /FlateDecode ] + >> +stream +Gasaoa_oie&A at rkGUh^IAjoTC`SR+C"]D].M?rUCmX^\g=GXE.EYAD#WQh4ab;+J(cnh1ND`6GJZ]AH"5TF5DptM2=Sn86fqM,'kciMpuOActj1&,h]+Cd86It at Vo>>]njXe:YW",+i*:,$4g2V=tq,"RoG+d6 at F(7:Bp2_0itO`&'IZT"U8a8I`!Vid+"oW26^!1okR0k_Ci->I3YA<<]:$Sf"rT"\SP6!'QaVD1Ka^_48\B:2`3/XTJqI?Dpn'&PjQUQO&1QKI=T.lEm)0^M,WC&RrbIlbLt.4Q)nLOp^O1R)]:nupL/rY"^h,UsAd!nkZ81X9+[@X0,H4)%^2CD^4SXd+$(%lO&hg5DMuZ&MlP>eAW0a,R!aMbG"mlNdE;t?l3 at VhloiQ)#7I>^ib_e)K-:b!"#tS_c48iGR$UFigL8*f]c*>oTM32+cR:RkW2"S<@7RP+s$P?uVc^L]HS/XdAqI3h>NUQb]SD13OK8eZe(mIm>ZsKk,V9ND/9(!QrSXSe=V$lBrWbE[;AYh@=YJ&c*aZ,4.V93O,+qIR;C9(?a=Z-X2$aC:E2t)`VD5Gd12*Xlij$?EeS?u#"\D!F75../`]dQWH`X*ju6bQoD<0-!-F]R&KG,p4(5M7]C#j at B4j5b9aRL1!_+scI(.Y(1rTsQ<-7HU:K7g`!=RNTDO("`/9]&VZLPZ6JAO?TErp4"j&Qn:C%b2e0kTV2^Es`mX6*A"Hp2bECpQ_-Sab](ng^"6!iIE]9G)Kuqrs.CNCSL~> +endstream +endobj +156 0 obj +<< /Type /Page +/Parent 1 0 R +/MediaBox [ 0 0 595 842 ] +/Resources 3 0 R +/Contents 155 0 R +>> +endobj +157 0 obj +<< /Length 746 /Filter [ /ASCII85Decode /FlateDecode ] + >> +stream +GauHI9okbt&A at ZcHqZ$Kq at c57=`&J`eq!m4b]GVd!cKDAF?ic)p[]tJ#_8-,>*sR<^"9da]E!E`gG[@*3lM,_s(%;M,pMt+G[^8r>?+4bD&:T]_FPH;&;$iqX=D)^NI&WOHQ"DW!pUCUgN?mtmG?::qQH[:-1hr`B>WOMBm;)H(mr3%*uYp&be.YU><+$]co3nKEQK18N4f8VhuH%Q$3ao%L\%a`^21AP-Z8WbRt*k""lLHgG![l:rrk,-j;%~> +endstream +endobj +158 0 obj +<< /Type /Page +/Parent 1 0 R +/MediaBox [ 0 0 595 842 ] +/Resources 3 0 R +/Contents 157 0 R +>> +endobj +159 0 obj +<< /Length 1112 /Filter [ /ASCII85Decode /FlateDecode ] + >> +stream +Gatm:?#S1G'RfGRY]sT'Ll&n+"::k)6NW6=BRpuBK9s/TUc'Yn3nV413_jHB-CI'#R]N\OJFj(Op`fE8*L5+]=:i[I>P\5oHU"3+sD=6TKRg%F!)@>&[d-u[pB*d]i5<7`$&Mn>"#2F[<\N+.SN>!l?Le"l0Bmd_;0eXul;.:]@<*#7hKVrEXaXH:RKYg(DSr-#93o^U)@Y58C']aq7*KYrp54NTJ1n\p$aWna)f-#AR[\Dr-@&TtD$jGd5A1tHmDChTZ`M'*e4>:b*tY=@mTS2XJc!XQ/4PT)SOQ6rWA>eEh at ZHP%DDitM7S[/49]\Z^s5(66"TkIYPbS$rYUti-eT?Xg%Po\qm7#XAPY%?cRGZDI#q#Nc_ArJ[#-+]Q;pb'G6'<\+I^puoHr]B!4432W-PM[i$)Yi'lEtNb"`sGjCO_tA`M9T)TIBtf-YU"QJ@`#NG98tHpWqugju;?7Ol:rU!+uPNa)3puMZ.tbE88IeHL6`@j.?.NLZA:DGTdUqs+QG9J&`7X!g&'W&,k5n2a[R$0+oU*`H6WP18PgB:U9DZFI+Y&Du;Xj4(Y1I?ulSeb.T%'*r+o!09ja:1lfXCVB[!L:7t00,,Yp/Hp`lM(4LNZd5s:l1!_h at lEnSCV%lpR7*.&qjC/F8,XB[?HaD~> +endstream +endobj +160 0 obj +<< /Type /Page +/Parent 1 0 R +/MediaBox [ 0 0 595 842 ] +/Resources 3 0 R +/Contents 159 0 R +>> +endobj +161 0 obj +<< /Length 293 /Filter [ /ASCII85Decode /FlateDecode ] + >> +stream +GarnQ0lFl_%,CL_Nm:IU&g^Br)^$$0'EtiY*J. +endstream +endobj +162 0 obj +<< /Type /Page +/Parent 1 0 R +/MediaBox [ 0 0 595 842 ] +/Resources 3 0 R +/Contents 161 0 R +>> +endobj +163 0 obj +<< /Length 1766 /Filter [ /ASCII85Decode /FlateDecode ] + >> +stream +Gat(lX7Q'DY%V^=G"m9[4P#$+^G=;o1DZFm>P<24/_L_EC64LX$#dI:+&/rmG6mGLDQC1h>j[GNeHs7EL at 6`%\-_%BfCndiqb.ENKa at E7:Y1VdMk'H(X2Z7jLMnK=F$bJ at 37:L.h0.eY4*2RoZqFm1]E=kX_GqC9Ma-FR"dKOsmhdd"33)lr8m.ehk at K<#Z'pbEjin&CfFd[>Csgnj?]8,?($&F"kjIh5G5sj)Gm=,>ERHDb!2BE"9`kJ[*Sk"SM?W4r%@&M[%cN0"W+;6-pAJ")NnL,e*lIX(LKfNtX1.'kg4u(o>A*G8#[h)%$=qO]ja-*07HlIhV[l$J4DE:%3FY'-Dj/]"<3DHGjcZ/-7H,UL0d"?_PT[N$ou'nL^S%T9YaRFk8S/iS;PRmkZQR;a,R_18ESV3UV"U,;o4CUH`^<^QC^>k$Fo>;W/5t)XJ]HcRY4dp?,V=5B#R at onICR/8p<7qknC(4$,e8*Gq+p:&6mI\Z.L_i-"oromN(9mUCJA-RY`oP/WWRcK;<)p#0)+PnVo/NO'+0N9XR\;lKKP^\nBO+L9)@,WbJ=+/H$UZ`knh0NVUUQ&^R<`hM4.AnLNFLcp&>-jkATfEL7$80KV9c663bBTrFi'o<+a]h;H9)DFl)5O`D\,%629qNT)[=+R0>o#n+Q@:r\u%/Kkrm-/f!jpJ+CM[Pn$,r]'ZpC1nF?J.A0@!-U]+`t>>f(nTWFZl11SAXZJ>7hrA,1#Eq"Y at MB7O\7'jsiVtf/N^&g>-?ggRe8SdrF$jfkZ.5s#M7.!+*][11GgV^&A0sA8T(sZIV@/TZj7==lF\oO?'jkUdW:sE6L^BD6(eeQ(gI`&>Z#cLg0!:jnU<^F\t\G`ji0u6X_rR0oZ6V])MEd-OQEW/H[GO.D$(el5!R/IqFVsR=[-Q2*,3+Wnc]=bHlHG3FVHA>amR\]9XAZkZQQgHrX%n1ilD=P8O.6Ipb-pH2>IX1J.Ht:`KBc%GR6Lt[I4<^F!qEe#Z@!hG,`M_fP0hd7JJoV^pAN(4=>9kPDfr#6Irs+Ukg*Q~> +endstream +endobj +164 0 obj +<< /Type /Page +/Parent 1 0 R +/MediaBox [ 0 0 595 842 ] +/Resources 3 0 R +/Contents 163 0 R +>> +endobj +165 0 obj +<< /Length 1042 /Filter [ /ASCII85Decode /FlateDecode ] + >> +stream +GatU29on$O&A at 7.pse_4$8l4M]sm>uV6/74Wf;==H6<\mO;seEA at qa-Mnq=(=XTK78.dXihE5Bk+1KGHk:\fF'VH^Rk-Hboc?pl6m:\:f#G(>l[9PK44smA-4_PT@^)(B'MFE,LUtR=s6;)FjG+PH0lTQ:QV.n5S/Pn*b;cB_Zq=fn8PrbF0%@bj64uR&-Quf_nNCW.aJZY8`PUU"AsKVnhpo2V[T>F'IQV3kAb0mnY+sMEb6qKZ)N(8YA]&b`@(d:+r5,pD3'#rPpnGa+=/_i(dEHSo;7eQ(_a52CZrX&$[6r%&qc(5DY3MkeULfX2crphO?3 at d8F_4bjjWEo9eo,FW<:*J`\CaCap[-nHED"SGDraH-Hpd:mf3'C0[S at XaU*r_:-E%%-aJS]P(5]O4L(p8F2(d;N&dJZNk#Uo\#.%V2$88lEHOI&m%XJCW0iH8]&R94fo]G`ML&KLNU&>8+j,.9#?cfII99ic+uEuG13UB?Lo@*,7kim-aB#'(ra'W&[g(0?J5YR2Wb(rq!e>U&GSW)gu-cn_noNS<+OX,20E!]u?U9q%%`_JUmCPbd]YYmA\WKIMV4ibXHWAJX1/+j&6-mbLph2<&F30O8tg7]bFq+1uhEi1_gPlg%X1eE]c at B!1oSB[^CRg at 2b4EFB]2`Qhi@)3-gG~> +endstream +endobj +166 0 obj +<< /Type /Page +/Parent 1 0 R +/MediaBox [ 0 0 595 842 ] +/Resources 3 0 R +/Contents 165 0 R +>> +endobj +167 0 obj +<< /Length 853 /Filter [ /ASCII85Decode /FlateDecode ] + >> +stream +Gatm:9lHLT(r#07ppTl-c^u$r2C[1^_k^#\ML&EKTZ!Xt'$-$\[JTVQE<)1fdRk5jr9A]TTD.Zf2p(.ZB*tkn,R-h(6!uRd!4`=:5p-5\E@@?<0+Pr%7aAi$)?;+l5u7V-iW1Q at Vq&Ace&QRDF3lAp[EI*P&CI%t-u629<)mR']@S9 at DT^4s?QH%+Q2.YJ27q*#N.Pmf at Or%A at 3g7B?dm5`/OH$Qin=qM%%/*\quF_""A?Zf[_2Y-(e88cfKO4RGKRXaQ^msJ2d\2otQY:5eT$AjBla+l*)!R/,=DG+8;ANGGqK+TPld];ADf>f>OG-hj0nLnkj&HTp]^F_eTBcki/Z":5!h&hYS\fp/-FI0#U7P+`A5&,/g`G8 at 5b(dhT[:\lI9Nd?L65E(c0OEOSE]q0gRZFQUF!JfdaHQOtWm'\/eR`_t(g.P?aq)WSb;*'t,EgZFZ53mVO@*MN*cqr;Hs`j>R<5S2KtTV8[6J29:p'VF_6+,"J$j\aUI^=e=0@#CQ*U4REj:Fk5[MeRL*:$C]?d+tc#t*udXYs,VP"cH8Ngg.qSR&i[k+F]CHBAFgsMXd\1 at T39ZStLhLjB.#Slm'h(m\al/RDgW*1i?d/K?`OJ=c^#ZAR9/qZ#f_JICp7%STH]`6Sh5.OXEot:H)!93pK6]6Jj"FJ\^DLr]A*KkO66\BSO9;7C55 at CQ8WK@t2UE&^p'r8%SVmij,M6f4AmOX#,q;Qp~> +endstream +endobj +168 0 obj +<< /Type /Page +/Parent 1 0 R +/MediaBox [ 0 0 595 842 ] +/Resources 3 0 R +/Contents 167 0 R +>> +endobj +169 0 obj +<< /Length 818 /Filter [ /ASCII85Decode /FlateDecode ] + >> +stream +Gatm:9omaW&A at g>pr;`q`ntqL+RP%T!XU.)BJ5T;[WPcK-7Oe`YlC:SBcAFZq]VY(;*:<1Gr,%Sc@%g#qiLq2+]0 at W-O;7N(ng`A5SAm'A/n4e5b*BI2d_bBhh%ICr`l3X^o2FT6$iSYc6+QeK!^')[aStsf]f7e\^fdnQkJhWDJ"RCDY7;idc_KQFf(u349DElOc=[u=P]uJa.7%WS_J"\i?9!Tb(X4OU,J>kah0/7M!,\LS3][S=VT#-#KGs59b\JM>3_I?^'1d)koB.?AkeE%NYF/?C^(/.;tS[cYoWET``/H;)0G$RNHW/0?qM*,!S.5R8B"9h2I:o`Z':(G@`P9:'T\fc_%-oi;VSg$+-a2O;F&G#Rn>\TBnPTD<3;+cUrtmHD4'KnSKnk%G]pTTNM[j`+5 at k_qu`oXM%1_;U2^L83nj\\T]-`R+&,YPAZZ1h"OE#_D>Ttl?I,Cg3DGF0:mR;R]G+1Jgq92F$3PsdC_*^?\h>Zh!IL:'clZ=#=O at TimjIk!FSU?p^a$XLU+:WQ:%THF-"]5T9J:#[PhM(q6g<))e~> +endstream +endobj +170 0 obj +<< /Type /Page +/Parent 1 0 R +/MediaBox [ 0 0 595 842 ] +/Resources 3 0 R +/Contents 169 0 R +>> +endobj +171 0 obj +<< /Length 670 /Filter [ /ASCII85Decode /FlateDecode ] + >> +stream +Gat=)95iQ=%)2U?kh$lVkq-\['[7*ihgSCP,pX(Ydf=r9J,s[$#*M4S,i_^A#3%f at IJ9]7Ac_m]pnpK!J<:4YTF1a`arr3bJi&";8OHbtqA^RIba,,.J<97Ml>B=Pm&^MVB%@rKL[JMfTOg;)="!:X4<5Qi#6R'Md`7kc-re+^QVNFN6`=3W<&oWMO=>+M/K1B'3/O@[\?1)s$If[Un,n).g'GQg,.t`FMsY4sCg$L/8uO^]Xs\BKZ=!7l<41E*XD%i>(eTL;eGQUnG)]VtX`*No''4!"_4#keOlhA>[aq at KT=%'MLJ\GmXG;UV88+1(-ORDQ6F/JU.WAE_:+9_9BW+%\@o?im1<](O_K"b9S6UUD72f6(lEW at SYH4>o_X at 6"B+]iRaejmE]A=WQK/oLT^UeOL;K,&De9^]@ZjZPQ/rf>SpQIa$WQcb`hK6#/b`bJ5Ft/!,p,Ulpd>k?We0O-q<]B;=8>OnNDZ@$^50B*gaJ8I[/8KuPHl?>;o8G,MN40&T0t3dsM^ZOA,&:ZQOk.-Ak3&g.l,l6J1K'cL/8c?,io"bHpT!6t`$'9b17+S'%c!G%_LOIf$LZs?@)3uY7!A<.\Xse*J.$T>;Cq[o*tS=PV>~> +endstream +endobj +172 0 obj +<< /Type /Page +/Parent 1 0 R +/MediaBox [ 0 0 595 842 ] +/Resources 3 0 R +/Contents 171 0 R +>> +endobj +173 0 obj +<< /Length 1143 /Filter [ /ASCII85Decode /FlateDecode ] + >> +stream +Gatm:>Ar7S'Roe[&Gi]p6*,;I#IK#N\6+J:lPs>%;=?eN-qAe=H'FgOs*gamM3Mkr*\ceHkE+R]hmr6<+-YBi:H3kETK#L5=VRrM0So?+"-,V\E'aT',Y0i0\$u+r7U?7J"j*qd70=Ck%3!^u+>O:a&R`Z]*i5$FQn"B8>Ql:FB)V*(+mu-FRHmRI-ClWg]RPP;K2Xtq'LBNfFo#=2WHpgc at mk,IN'fkK$(;kE7Ro^3d/gJ4N(&*!mE8NkBj3Mb>L_1R<%pPDq#5n%n=5e+QZ''"UC&_DJ3_W$kA%]baJs)N"uup?6=LT(30O:uL7?d][99=-!\WCZf'2Jkp^f3)Fj+VIMtM1#V`F7f)70]68&7\@:\#55?,8S$cFjr7G;3/CSEH[<:\+0UF,sU([;mja;`%^H(&:L"XXAocT>P^:rfq;"+eS^dW-WMVbQhRNfFdP?1rKe9K,Z,L?gRTt\c at e?J/?7GBl0_B$.4/m at V.XXa^Rr.C1n.RV)`YQOD$>`Qi4U/MA(iF-B/9UtWB2>K^JY$Na/9G[c_."itLKj!rDgXRGX(SEcYcYh2BSMLAjM&=>9lJJKDcTs%47nIcP94ddb(%WoIkEth#QOg^2e:s>atOJ/;LEjrgu$tZ:(\3 at ogMX$FqTN8E22;tpiYo1dF8aoZ-[>U7K\uU+S7A_qK_%q[(DiuVJ*XBFk'7mX3`HWK^1^E]%c$=^XP=mr()7)G)4lP/8`%boONpmO'P*-=b;do_bBKP[-Cd)bP"j!`EhLs?Z)'7_X%"b&q9iYp-)V17ss*4^MHg0NU6k9rS"2"6mL,+8CHTB?$!EC9iYGpX-Sqe6TB)CQKaZTi%DPJbY(!'IN-Gh3<$@`LU(%.mU,jNdG56ho/Z~> +endstream +endobj +174 0 obj +<< /Type /Page +/Parent 1 0 R +/MediaBox [ 0 0 595 842 ] +/Resources 3 0 R +/Contents 173 0 R +>> +endobj +175 0 obj +<< /Length 888 /Filter [ /ASCII85Decode /FlateDecode ] + >> +stream +Gatm:>Aoub'RnB3YV^'02W346J\,\6:OLIN\[tL]akV(I$J(&Fe5&JABM:Jhe_k"m[3(H#Xelj:_ at ll`UZ7!:nYD"mQ*oG7$VijOaGj1A0?F.uP_C0^DIe,)h5 at Y%=%:ZF5YCr_:R.Am5LdA>sk09/t91F*'*f4>_/o`CX&>LiA4W3X$<*dVoi7!JUFX%+A]gTbHO-?P at ilah"`dR`TqU%gJTkO##$9Kct'Ji2YM>4'=C$;aS9]+f^]*Ce!uV3,`C,**&19(*Y.njDpeE.d+j.Q*%kGd">;p:3 at VJK0oQa@2\5g$f<^!9&V=:(ZVaF1L6%TXF%it,LSlnZUJDX5T4UZi*+]'Q0fO"S`Zf*.5bPD#JScRbjhJ0JNaggh9GtE\'LU73\`(P,ZQI!8.6sd:&CX9)qFbZ!?)@Xm8crA+G56t9-3*8U+\S_>+UH]*sTSK$SO$#+hL]O[%(S7DhK6B"#cJU0N(^4MK,5S8_cl*OD1o2s"+lhn]h>ab+iD2,D^36C>#DcO0*623\MH at D`>N+Ucmt];4=^NVq0K*.raVl]QXjqrJqibGgA&kC@\>UdCq*>kkH?uh8K@[Ad]f@\uhb\W;_X;7TQ]+ZY/!$9%`W0HWZql7p=%1d^>tTf1eRkJjJ9>T0?K+Rj_I2*@QN,;?mDSQYkes;;\1Kipl@:di<=_@=gG-S+.e3rj=/KDl=gdL>74rGqp_Sh]WbbQGlMp+poda=&1%5JrK;`kI[g0j%b(fB1Om2(4=9_B"dtL5&g/-^h8`3Tc-Y"mPCM:)5nfO(Z-$1lf6/<2.Yk3n.hU2`JFSR_g[`B^q+sr6YJ$S~> +endstream +endobj +176 0 obj +<< /Type /Page +/Parent 1 0 R +/MediaBox [ 0 0 595 842 ] +/Resources 3 0 R +/Contents 175 0 R +>> +endobj +177 0 obj +<< /Length 305 /Filter [ /ASCII85Decode /FlateDecode ] + >> +stream +GarnQ]1rG_&FB?1>:'u!r3iegPS>q[aW7+c`u5GA4)h8DrZ7)ii_uXdS)'X'IEXURc!GtNke2QZ)2D9?JH(<'kq$kX_'tE$Ba>gM]R"DNWQiI@]Kg]i<,5>;"kIt[1\!lteC409h!>IU5(W6u&oq_h,LIob2?$pN$!c#;8jPi4F&*0'^X]koD*9G7LVqcqRC^#Y9,&g$l4sKAOuGTOruCnZ;`ZPLp!DMseLYTsM5\>flWmn*B2AP7p"Z52'kjaH3Wg?2,_F+/fJZuuX[[GcH*P&GBU&[0;7j/cU+33n!S9/EoD~> +endstream +endobj +178 0 obj +<< /Type /Page +/Parent 1 0 R +/MediaBox [ 0 0 595 842 ] +/Resources 3 0 R +/Contents 177 0 R +>> +endobj +179 0 obj +<< /Length 956 /Filter [ /ASCII85Decode /FlateDecode ] + >> +stream +Gau0B>AqtE'RoMSY_3.[7#b]sEBM(5:(1i-+JD6::`eEAl%7?ZUb6-Rof/;h-g at oN$.P=:oR,iuq&Ea3P;aR#ncYg5MNS93l\UCQrHUq19T\a((>MF-#(=,YX>YB^^8'ne7<.B#X'e3uJ4D,@?k`jQ!N7P"@V,0_.8$/6o3&?rTjolI1Wh6(MZoroS`['NcA>Ng^=.IB<$#g&.2&<<5$MqjYBGhbZ&>=.WJ:T/`;W?IAT:,Z;aa^o!o[QpNb$nunApFu7fAnjo<>>0$qME6b at 588,$10GmF"N'9N]$d\+oC6J[_L=@R8a1/IuYkP4Af>0A$)\c;!+-+gC%!?Zfr13Ib&^^?XEkU.p'HoWXDub]K4Hh!ZJ^HdMYu:ercRT`"jo!8=eS_bLp%Vgs>&ll4%^\'7L]>^uC)XYWUg1(QlD:I-9[]"*N)K/=0K5V"n"/\fB`Ni;O`*&T4moCAZ6_s"\>5eGuI!]c_m;Hd_(?KM?Fh^m#Vj24jh60FI=n=K-"Qu2bREXMIf5jrb(li0p779EBP:RP_QIb`kY*,jrG!%!Z?537jmcPd,DnQX>";hH*;F3RF^^G>rTJ'1#qZ8q>Ui`+LhTVE:c<$FFNK"Xd%-p9RP55I.LQZ[M]pq:[G'X9Ocd2NHTAh\_XPOrk`57BXZm`[nU:_m +endstream +endobj +180 0 obj +<< /Type /Page +/Parent 1 0 R +/MediaBox [ 0 0 595 842 ] +/Resources 3 0 R +/Contents 179 0 R +>> +endobj +181 0 obj +<< /Length 597 /Filter [ /ASCII85Decode /FlateDecode ] + >> +stream +Gat$ubAQ&g&A7(;&gu]&j`3:BgoblIEj<`:O\DtUIQJ9e/*AV$,CdV.)@(h*M@))=VS;!jecA:eZ6gJ4]u_4Fa)_'=+0`-9DA1Pg0Dl;O!-p5I at bLa46T`B`^4A2rQd]f8:(klEltS,n7ZNA_Mm$(>?/G\B!jb1*SZ8L`$-UfX9sO5d at rp(0X,5"`j:2$9].jXgH$J4uhjLL0D>/Seu']5`#(@PbLCna`Q3)BKY>LKVk5--.A"k'Sr]]IA'-[.UNB;(rQ+FSWkd,9Bc*+8/&oX1.if\"fJX(:SS#PN<#>bj7#sLc,^jIU@>)IB9eS8m@&ml"(CL7<0o!UVTI4+D'(PlB$b+lYFm#'r3*h6!'B#rje(>8]?[j[ehM\+d?j&OSJK6Y`0JJDGHUlP.hof::@$rADuCJg<`dc~> +endstream +endobj +182 0 obj +<< /Type /Page +/Parent 1 0 R +/MediaBox [ 0 0 595 842 ] +/Resources 3 0 R +/Contents 181 0 R +>> +endobj +183 0 obj +<< /Length 1266 /Filter [ /ASCII85Decode /FlateDecode ] + >> +stream +Gat%#;3.J1&:Vs/5l8o?V;d*C(fkCJhF=)J*.YR/!.IR4Q4&9p0(!2J3$S\.1q5EZ\np&=T,5=d%kc at GTSTh*["#oXc5?CW5^4X[&nDkG2V#[Q7_Ulh74_k3Q;?-%bl6Z"j0SMq at V%3A2eJ1<5_:LET2DSbWMR$U.^(k8($p,WGpHp-u0CI2JJ7Lk;IUrUuWbM)bla"^`4[^U1Hu"]fb`a\nf8FtGiNR"8TEN7WK1J)7(PhuXlY\[rN'W38=It(-O at fG2<'>*Ub$Gl(AKeilW*KqU?fksd/.HbT`M>@9:R.]S#I7-Qj:4sf?%Ds*%L4nZ3fWIp>`0I^D8&KaX+Y\ZRu=)P4KlpVDE=<8]U4^m7,8H7?p!@LK+O$8&lB7D+F.mF4GL9MRcn[S1A8UZCK<'Ig,Ft#H9eVa;OF>aBt6paTC at JR9bKrRZBJ:(X6>"g6g*p)Vmf-UM&WGBU]2'1H:lS00loC7*)b$*Iq2hL>kI?ML[o?@0KDYm\D-q`rs0&1dK"hhVAfaPJ/EP45b=WT\bUOBYZl!?@Luht3C\dlr-o8d&';P!g'iWmoY5f]!PA~> +endstream +endobj +184 0 obj +<< /Type /Page +/Parent 1 0 R +/MediaBox [ 0 0 595 842 ] +/Resources 3 0 R +/Contents 183 0 R +>> +endobj +185 0 obj +<< /Length 817 /Filter [ /ASCII85Decode /FlateDecode ] + >> +stream +Gat%!bDt%*']&L6]OPOcj(E7]"B%aS"Tfs:L^dpX[S at dk4@l!"iTkJiNK^f76'\J&^?7]*4kG,g(9]rA6if(S"jqpprIQ5&IM;h#"G)XOUd.4tIb]>X'6T at bU>Ve48OSCi0VBIP=hOj+@@+BP1B+>E/97Jd;"6_loM]WI3)%nXGAG3+=FF,Z.ai at icj.`PXceYnL347 at hn)^?_eSe=Q0"hle]p>u^+E$FTB1On95V)%Mb+n\98?`J1Q#JQ/cBb#/[@1L^I3>>L'n\'s#IAG#F&JZ^;85VN:[QhID\V5 at -JU7ID_:CR-5K*IJ:pVaY&$S#>?o](T6"t[Bo-(;_*JrEL@?<;J1^4EAldtr1A6ApK!ciP:@%lHpNsLcS6$YqH3\&PPf)Cp<*:jObF)dIGU^L(F+1%aX'YBDlU0$qeG>>8>[$kfr_He]E at c@ +endstream +endobj +186 0 obj +<< /Type /Page +/Parent 1 0 R +/MediaBox [ 0 0 595 842 ] +/Resources 3 0 R +/Contents 185 0 R +>> +endobj +187 0 obj +<< /Length 611 /Filter [ /ASCII85Decode /FlateDecode ] + >> +stream +Gat$u9omaW&A at 7.pr;`1#CfNs!3%Kk!=:%(BJ7.EgH$KkRhRfHi8_a at BfJ^$/Es[T%mXg/9pD[>fD>=aZ-mnmmja+:_9V;(QCar`PP[T)s9lkU=0sk+RJAoI-_"$\Y:UA3s+tj&eT75Np%9H(h3\[1lDH:W\=p23lg-!mNm+1(X$X8kkbe*7`I'];)A[prt&cuUF4!>^4DWQam>u]q)mSeR=W4r4:fiMn_IkLP4)fRDk)%3)M4-:&mg5[671<[>LB?b0iQ-+VcU*!*0Bs/XsAeU/NIp3sUmY%KfQ[,P2M=NO:,3HZN,A6grAQpt>k7RAS;=DtGs)RDAVbVr78m!FfT5KIoEA:H9 at cJaBi2?nb7 at YZ,oJO3U:4oqW0b\gPBZAY"+Aj$ep2N)hrs*cuERF~> +endstream +endobj +188 0 obj +<< /Type /Page +/Parent 1 0 R +/MediaBox [ 0 0 595 842 ] +/Resources 3 0 R +/Contents 187 0 R +>> +endobj +189 0 obj +<< /Length 1060 /Filter [ /ASCII85Decode /FlateDecode ] + >> +stream +Gat%"hf"u<&:Vr4_.3=lMf"FCUeOHcWcdU)HlPrlOh`>YNPfpWjR$n[u7bn(E8-j#,m9`c^t20Z2$RQbt3I\H_kgb/^t1h[-s!GVWHPmWB\YYYd2nr*hM-B41?B,@"s880ea+ at N&J_ZO>5pcOm(:VJ`#ck4_]@K_8$C>uFgT;k;j=gq7MTh2[c'`40sh2LO.R]mT,2Dl>$73KRTRW6%$;GlbJNY8-Uh#t8c^0`'_P+b4o%V43'W^0>slIOTF<;qNN]du#FOn\RT(!c_:9"CN(7;#($Wm`mMFe%Ti+65pSpCqX,<8bM4sXo72..WGP_R(2rU_sbc?>QqnIqKs?([Y7c^H+8.c;2Qh`4nn0aIH=M]nr"[F'ssVq*5,i__l0`NHl[koKkZlH_Y>g3)4n*i-NjsHC&2Qnj+B6(ZdI>(L0CCLjm/\?d=QpF[$kWc%g`^22.9g0g^U4"#fPf2H^s8TqQ1$L;FPh%*sgjO?51j+mIbc)'?%`l1Ar.WqF2;hkP at Ce8YkUP9#3/#/ms>o.M\[Fr5"5/C\9YA2`2/'#;FlIXZC7j>E-*C8+sY%hk)m;CY**;RjGB/B]Xt*I6c7;d?,-.k-ipjX!fn`A%n0o_KV"h-D/\hpSV at G+KUa]a="Khoh9RR&anFs#0B;G*3Wp'G,#M6X(V;W9&/.I9rHK?JM<)MMc9*Vl)ks'StXq#`_"B>MiC1451kXgJ!Pp/GP'6!2=%0$RXaY=74F;>i+t+ATtt#iW:WTM$;V.!"hg$+4K\J-i~> +endstream +endobj +190 0 obj +<< /Type /Page +/Parent 1 0 R +/MediaBox [ 0 0 595 842 ] +/Resources 3 0 R +/Contents 189 0 R +>> +endobj +191 0 obj +<< /Length 1072 /Filter [ /ASCII85Decode /FlateDecode ] + >> +stream +Gat=*>AqtE'RoMSLrN(8;%qjH(^[!4C_B8]TbUl^%pnOC6#@7)'XiLP01h[EB`fbuPiJ at qF8O8EHG+QGMZ_$#MM$&_#_Uq7#,-KR^^pbR7OVZ/"RAGED>?aCjCRgD=F\[q1k;93cpFi77-9#."U9nIfp>6EW at if\i"QeE]mMo7^P`!;!8t47/q0$P^c7kVAHJ/YV^%V!XFBB2F=N:LW0l^(Yh8XEW_t0HqNU*R^V)WV[^(V1a at -kjF'ZF[-t_7*?(D/TWI.O$!Jr%Fj#^Bi.P'hdaCbmLl=3MWC at FZL.I7d`6]'TJ]>R\IK3Dfr.G=FUrlKZeU:((b%8 at N=!f'h$QSm8p*6MCQS^sN&*OClo at pW_.mD*I+*JkWKnPH`0,JA%%-%!QU$4,hoL4**fs-7k=hLm`mHk_?VhlF&>QK*'3%Of at mC9u^=g,FPAIaY5l-Un#-Wd7Y]X0b]$LM9c=b*><2F3X>(%9H!]QP*^2R%+:O_oE+S^`@G`tS4JN_GHD:G6(Jt/MDC+uYc$*<=']sf"F/8>"E7b+^R;X*.0oQ)?QH-;P4f.=o-SeUTApap:0\^Y-^Dc+ at D1ml\dDQUIo1/6`"#I[HhS)5+[P60W![#S+a3nMpA`$P#Ou1\)/JOe(nq:^a2M.J%r`^j`#@6Y:3XWk0TFm-r?!SmQX@[[l]u\G,gLe=2:q9^^I_$!=C6(`^].DS,M#l&O$3:U#%+<,X`V"Q$*9gJm"D@$6id0k,]&uSVD3cU at WrE&VeX]G~> +endstream +endobj +192 0 obj +<< /Type /Page +/Parent 1 0 R +/MediaBox [ 0 0 595 842 ] +/Resources 3 0 R +/Contents 191 0 R +>> +endobj +193 0 obj +<< /Length 1011 /Filter [ /ASCII85Decode /FlateDecode ] + >> +stream +Gat=*gQ'`:&:O"K=SpU5M"*>tO?hM7>mVd_F>@kL6"M<%\OrVoa"KmJ_:l38_l5/#*d^lJUB:H^$UU"K*A4Ybj&d#9-h6gCC(bIt!gH/%O1.Jn:YB>::C]INZ=>fh)SH"EgWnS4u&k\>0USh\'["\CSfBR=!Xnf8c5>.u_N/eG/F[$\>4Ca6WrVY)$Zn?tne\D2'@6\O4S&g_+Y at EYWnfBEED4VpnqW)3 at +7Q4b3(qmd at t=BqRe"aPegB4r'sDYPMA'4Ohruh;"Rsg_lr#XK>m"5kcmrZBn1IF##5b"J#i*4'Z98m7UKG:Ob(C>\kX->HJ^VgioDS4[9ubXdfes82R`];un:2ZM:`8?&tQLnB`t_9hlt`+'2DAXiHDtRa8e3kSGHuGDu~> +endstream +endobj +194 0 obj +<< /Type /Page +/Parent 1 0 R +/MediaBox [ 0 0 595 842 ] +/Resources 3 0 R +/Contents 193 0 R +>> +endobj +195 0 obj +<< /Length 691 /Filter [ /ASCII85Decode /FlateDecode ] + >> +stream +Gat%!9lldX&A at ZcFA*2$l4ZaEA0u$H6RU,P-`!*;#D,BgALi*%iYX0\DrJmn'g%cG.$*1hRegW&IDF1+SIL8oa&G.8!'NsOlQS>i$d6PDc`"Yem+sl./7=M!YK5N/Ed'VZoX;-Jkm?$2Z.,%l$fsAm'7lg9n&';<)c^rh^OiHmX8uidWGBU8>A[3PZ+'7_t3[$n1]tAoefP^dH1O$PWU=K'(C#GqA_tM2N\kSeU]@[E.-;f(/=9X9r/'`nni"dp_XkMDJlS35-@'(PoX)4`(kT+b!B6IC at GO.]&/s`/?1a%$!ImX99HBIrRZ"p2oV#A`]0Xu852hb3RKj=%hX"k1Gn%-/rP)BQ_,TSH]_I?rj, at oFmlMVmuC7(jsE!3!>h\t\BD/Gn6&V:5d6h0-`K]^>f9JmS:R*16O.9RPOr at R'^p3\U\'<`lW==Z1#0-RJ&,Za:7XEfd%pg;n?H*MKpo)IZ[M?5dHg#_,4e=@.g*9sGtgkXGU]Q at b^@j]2E/-G?bo8Tg2'GeKK[OF#*p61(oT\Q3mqr6E:_dK)=3tlme$/56r,SE9\b"#H%r=;_KVqV~> +endstream +endobj +196 0 obj +<< /Type /Page +/Parent 1 0 R +/MediaBox [ 0 0 595 842 ] +/Resources 3 0 R +/Contents 195 0 R +>> +endobj +197 0 obj +<< /Length 656 /Filter [ /ASCII85Decode /FlateDecode ] + >> +stream +Gat$u9okbt&A at ZcI,$k=osaIbQ$1^M:i0:6QM/c#5SB9'7=YH=g4*H38\hP:>B.KSH%'\gbkO at 3hL&^e.%h00df?.K5S/)\6&G_5M at 374UNhj6h)m$2F,PL?pnL1_7'K='TG)k&2P:lj8UE^OaKi$$Cu1O//8nBV7 at S>hSPh>8 at T,5YE(l#D,BO3e7O""ne9\=cP&eoKoG?:_]>NLdI?0To/I6Q;b.$7'C[52QXd%[%Ta<,Ak-_iU:n8 at 4E9GJtZ+GAh'^MB'e'+]PeB<[WkNhrpZRm>cS9HdbCkdl!7?O!K`0=lU%MhbQMueuM:\!;kS'%%V/b6jq&h_B2SQ/oqAns=s1Qp>!h6Hcn#h\clRq,#.pRM$EGBp]_"=APF$QI)>KkLOUXOnj!Gf0T'eRP3;ep-ep8lO@/HI5D=1haad at Z1.A`9hVrUSIi0O7A!RrHFYGCZ(*M%kihhOOKu1qQhp4\0RJ4rFDBbd`.VHB +endstream +endobj +198 0 obj +<< /Type /Page +/Parent 1 0 R +/MediaBox [ 0 0 595 842 ] +/Resources 3 0 R +/Contents 197 0 R +>> +endobj +199 0 obj +<< /Length 438 /Filter [ /ASCII85Decode /FlateDecode ] + >> +stream +Gat$tbAP0N&A70Vp'=!$rJ9k%#^m[BKN'B`Po`9Wcq**A`&[JY)]HL`-pa+O]@P9QG]l62]XoO$<$;Vl8j*4pNrl9k"iZRRnc^N%6aVKTd5'SC0t]mG>b_Eu;A[iU'7dC+L#NLeCB,#HD7 at uiZpeRbds[f*X,G(:VG%t%7k;TDb at WA#E`:]EfJ?`V_8^#AZGX+u>q?3 at YtuY3!04o9m85$u];TM+A/&V-FLgjUD>DlT;?f;l+r\s`/s at L6gFP9B/X;JC=0r"R#!AS17)cb12dE%C,3qN!Ho^"NT39hc=);-Ieh4*trSb%=03ht/BfdSClJf>(].^&.[OOt_n+uoWA6PCsnb5^S%[cE0KgPd^4@/07jKq%1On[E(Vr&?r6m*",n-MU^":u8DBLofQD]\S0V2tOHV;(-YO1BjgI(j?_3H +endstream +endobj +200 0 obj +<< /Type /Page +/Parent 1 0 R +/MediaBox [ 0 0 595 842 ] +/Resources 3 0 R +/Contents 199 0 R +>> +endobj +201 0 obj +<< /Length 1607 /Filter [ /ASCII85Decode /FlateDecode ] + >> +stream +Gat=,968iG&AII3E,oXZ"&T+Fpi*+$O__Mf:2D3d-QQ"5"%5Ej'9Z2fLo^OO!!F^#%p;Us([N(;rcYjAFZfQcf!Slc:h[i&R:AD+T]PYbZiU at M/+>4uY\1qcp#j9ram#YpQPKPGV6C+DIXqlL!Y>Z-i$.)(.I`MO4$+TcD=:V2e?llqCkTd0M\SR0VZ&!c^=":Sa#2Tk1rZp"S?NIQPV=to?tCU5)]?R2G4gmhd7K=UD#KbK2>@]e#*/De/bZ^d9nE*j%MdM$gpQ"h0O388Hp8%0<2dd7uW-"XZk;c]D/m[bL%(TZf7pkL1j/c*h;I44Gh05mF=V+.bbhCn==il.[)W&^rX(1c^cp5M*HIFR4NaJcs+.Xl]Y!/=j)%l\\C^Y'.hqh=10Q0E)=\:t)!eb3sTU[K,TN?$k;Ne9BB%!j9qBMOeQ)B;1IU(9o4]*68SGXZd7fhqb7'H!dk\l%X)+AuVRT.[M7K.G:5SU=Njl>a*'4Ssr=^PArho.m>m\@S\Aj`B#GRp%^`BFDjb9B(bZ[CfV%LbT at qi&gjMn&\5k]26+*Y.CrR]]9Y5%2n$WfQ-2\^#3#6Iu+IJ['ggb+q^BMk\Q6m)(,Y[_W/.B"Xi8aE6)jGXs,\5HJ;5:u>AVZ$*K&-g1Z1YN4X`Hr_?jh^"p):PD&_s1.tL>&mcZu_0f:a^BU$WC'^jQhbbAHVIVFV+fh:LoJ&/ug)MD8G3NU<+4H6sg;pdS$YR"#Dn#P*3s]E4n'ph(S2_O&#k9e[5>f!u+K)?Q8ecL*]```5m$^rmeP..ZT.)b]Ko_Tr'4(3Z**Z+3:@O*lI8LFbX_+IpA@;'GX%R?k&M5X4*S>VV9NF2LNKsNf?hWd+D_O)B+>-R0jCU[O<"H4l?"qW9ahap=Y$!$pq%L=t^(/*es^TlJcPtAXnlmcUuu:^U%DV\Ij?u-lr/Ob3/0^dBhJCq1u#qmUums'#[]6qDeittO)]7c?KBDH&[5:;&45'"aA$+g,gK1.p">Q/Q9]bb_e]4#5qNm#[Wb5p6FWO8:FQsIbMbC&Nc-Z82s3!-f5=F?ca*u,T,e)(.i8.0#~> +endstream +endobj +202 0 obj +<< /Type /Page +/Parent 1 0 R +/MediaBox [ 0 0 595 842 ] +/Resources 3 0 R +/Contents 201 0 R +>> +endobj +203 0 obj +<< /Length 1498 /Filter [ /ASCII85Decode /FlateDecode ] + >> +stream +Gat%#997gc&AJ$C#jJ%p_3u+<#Gj"mfJG&(U+Oa/kbTm5=f0bl+=JQTY\1qdW+sCn=M[WW5`rl\>Y_or#kBFflO(SM>%`-+`4Qh136ub<"r^gbg:.EG]\5`GF=C%<;4Qo:J(7jC6oma^8eG!\_K:>IK>mfm9P?NiQX(fdZ*-0tS1Wu)mFrk1D^F",CeR0[P"=>SW#sb-/";P]8l6Mc;"@]U*Vn%JfW$JSH`DpZ;N,:HD-*'>-B?-&#Ba]",'fnrC0j)U>h-&BEm[uNcRe5_cS*TCk.n&M6R?HWX/'Y;.$Ub<`1IB=F6b5l6*dc!GP9uuiu/^AT#j#q)idD#aKc\.0dRar"9lO.'<#[,WZPL9(G="9`fuO\l!gsZ]OkFmN)S[*bj'>B$-bdtoE2F#s/^Jp==JL4T<)<#QPsp++.9]!P(TbK#la('Vr-$,CB<`0QE$8>5h*b]KS%gm[a;8-T6sUBUpgo1\+SU>9b0aY0Q=Up3$HG at 2O\u.7R5l_=pWRJsXPBmLT#rjgF>6SPJj.\Jk/di'=.;;cWiBP\X>A]eE2XR)Bp!gK)OjbcmGTGp?::jkCor8=UGXE51=k/sgi.'b\Sa=7TbT\Ju8d\XWJL#"LLb=>D>oeTP<@1WM;C,SH21[S-%LK$Xt5A-up$QGo`hD$FO.8")+m/GAX5"U]''B./_(NfFK^-\g8o'c#.UGpjZcm at An"`-S`GYc9+l4eGqgrK:W,1X&c.B?nV&2P#T.SIDhadHVmcb[$qF_a`Pl7#b.rap:r#d2bqHm1*h&ZT88$eH/\*<7<(.SN-#2Um7hd@?K at K,C8N\^C=]b7l/[6.JO#N(!2R;5PXIFA.#FVMI=5C1.\4Pu`:g&[$@]1m5K3iLp]oVKZrg)(3#^"'"7TXF34.QT-jgPX#LLEkko/=5:6F7GH0Z\9ot"h[>W6LjeLTn\.jpFXd7?D@=FTs?TOQ#WR>I`#oNinG5Fbcio135;)#?22jW,KZV!B9u_]/J0h~> +endstream +endobj +204 0 obj +<< /Type /Page +/Parent 1 0 R +/MediaBox [ 0 0 595 842 ] +/Resources 3 0 R +/Contents 203 0 R +>> +endobj +205 0 obj +<< /Length 476 /Filter [ /ASCII85Decode /FlateDecode ] + >> +stream +Gat%_92!/f'SZ;W'gl#=+Lgs6N1aRP?+:Ham&WaHcI@@kR\lhYH7)FV=;q])]/021kM1>V at rF-SLg\"H[N7nRO!*d)6%i)_.R?@6NT+Sm2d20Ken/PF at maIb->gJY-uf]8qgS3O*]@$/9e4!-"/gm5)D&n!DMqsWGFItg^Fm)fnPpB[eshOP^gnN6==0ZVca"lR at 6hcFm/3SfZX0Z]$oi#mbjs84MdF#c`nC1/Lk/Ac5.ocC15J?aj6$9!.i;su#Bqq9La\onI:n=A[;2mUc(!;=Ch6j-<=6)U*0"R]R^CeU'[^7bEDiJj&D9=OMql+ at YE72W-CU7DSW-bmGqVC:D)h\eahN4["Fc.fHV_mZPneT8FC]fh#LF;9Q/^T:,UBYZ at nf!dqNRPMaj0QOZ4_f+]K/mc]5�g7?qZ9k?h"h~> +endstream +endobj +206 0 obj +<< /Type /Page +/Parent 1 0 R +/MediaBox [ 0 0 595 842 ] +/Resources 3 0 R +/Contents 205 0 R +>> +endobj +207 0 obj +<< /Length 2198 /Filter [ /ASCII85Decode /FlateDecode ] + >> +stream +GauHM95iTD&AJ$C#ekCZGSs*&dlB9O%AX7J[,%>=*b^tIe7ch'7."U`lT9JbUn2^[U'Ms:8[*9WDd;Je`cGD[k;e!]TK#]:(qV2Q"6XWFIbXhU"u#i'q4EJq,q0*+9PYBpq#n]W3hpZ?jCMCdML+N9cbm!eY4.Z^2T.2n1h5XH3De'DL*X\'!S))h-_p8*O-3eB](W!aqho,k!a/B_bPEfEhTb`gt&K_auYkugAGHH)@bS2JJ=o$YoK&43'@cOWFN5DkR<:b8$5'kE[:Pq#5`%%OkeKN&Lt9kq#3?\t]e_[udG?[(niYdmW",>2">T-2=Cf2Pf;@*p/:b.GZ6JXGPe<#nCH%8nK&9N'qu3a%NU0$h`p1ra#c/dQ#^[=:&Dt_N5c(6X6/sd.+-L[q#>&Y7&YN65`Nqg1T^EBB`**7#@`XFI!B:7;jm(1MKG_F6(WNA8UW)NupS(UH]BaEH)CH5D;+L>B8/so;RMnQ[fFu&eLFN="*dTgi)#gH2>(lpOeX9PW?pS(G:=ib2FBP`R3Z:\nPQH1ff!%PL,RAbT'L9c<6RQ%&(GD9ZIO_.^j;).-6*/NlHY4dnqRei?$e$=DoSd^V$n1I.t'o"9\feRrN8(Lp^7s%NqM`2pf;j2f#dBtaj+I5_`2sW![$rKsVU,AcZXBPAL%*/-!hd*J/el,[[6\EjpltV8cQ>=DieX>3p\:*^IDC>K5M`S;$E"F9A>@tl,1h_##kM9:-o)CgpLi$Q;W1e at u7iN3IV^(AiF!gBc'Sila1BhR)Qkn.Ze+6Xe8DqK98QR:bj6g,eG]\'9.A5"6EP%NkOGjaKE7h$>o4U1op^0?90TVF"8M`0p4(m\ej)a:on_$8gq0AMq5C\^j#4rS%nWlH`B\Gh0=]ebi:`Vp5:E2==iC=p)('26WUX'r:l/ZB-d-Ce(1bcLDjctHWIWDT8,A`r(Is3sONNZC*X+BI at W^prnn,Bc86~> +endstream +endobj +208 0 obj +<< /Type /Page +/Parent 1 0 R +/MediaBox [ 0 0 595 842 ] +/Resources 3 0 R +/Contents 207 0 R +>> +endobj +209 0 obj +<< /Length 163 /Filter [ /ASCII85Decode /FlateDecode ] + >> +stream +Garo9YmS?5&-_t0MH=Q!md8imEc"&L)\KLlbDTJ)Qm2?S:BClT]_9Uoi3[]SP2JeqKa#"4NdX3VaI3RTL8eXX1C[*kK- at mG5->U>"h&` +endstream +endobj +210 0 obj +<< /Type /Page +/Parent 1 0 R +/MediaBox [ 0 0 595 842 ] +/Resources 3 0 R +/Contents 209 0 R +>> +endobj +211 0 obj +<< /Length 711 /Filter [ /ASCII85Decode /FlateDecode ] + >> +stream +Gat%!997OU&AI=/ppb\7&AR6-8 at q\.#Za82E<-OmFkTB';XB(W^W3=[ERHb):o2;jSSu5fpG%Y6]r)-/+:1Yu-q;qsUY'uKOp#5>)$e8$8e:.Oh,ALDpZO\25<'?I3-GK9oE)h(;b0MG&.ckJlBaERW\F*SQ.su9172WKZ([UXX&5u31f^a*%1,:S:P9T3D.Yt4WRiq[dNIO$Y3nMqXZeXdf(iA%+\6*ln[;\QO<``pc#o/WNjgGME0A7oMr>Q6h/o-&LFOQ]Djt0aX)TE%:dI6CB\^?T]=r2n<)nS3u=958sV0K!j]hD+bqsO*S%6F%CklUn[]?!W6!f:Cd`TrhO-iI1Qs2jqJ8$`)HqRLFrXOAi#:2p>oo?.]rC%TmS=.S]@fNg2ObM8Bra\`Hd)3'O;F7bik)[cjl`cB]9=$K!I]0sI2p/)F#rrHj!W.b~> +endstream +endobj +212 0 obj +<< /Type /Page +/Parent 1 0 R +/MediaBox [ 0 0 595 842 ] +/Resources 3 0 R +/Contents 211 0 R +>> +endobj +213 0 obj +<< /Length 715 /Filter [ /ASCII85Decode /FlateDecode ] + >> +stream +Gatm9a_oie&A at B[GYEX6b#K,d/Wd at -U$.(N68*0cMG2\)[(';nk3ks"MR?Sf$5C41oXoIU]G]T&cKbuL&IHrSIcOnDG6l(J8!'NsOlQS>i5e^ApT#r5WisePnin%W5Qi#."*t._g0 at 0<_5.nYk1MCn<1>ApKOn0%g&;n,W+aDXIS_NkdlV>Jp,>;;q'dqWrFtPqb0PZ#69#-"QNF#e>\+$:*/$b06Duo]our+?$#m;B at L"9*$1Ad%B(6PY,,HD)V1lR-gR1i22uuIZW$ZBe/KV<$-io87$b at e\FfI7P"=ZVC_G*V.h<=bg88;F:9X67NE%+UMc=V>k4#WTPk2rrL?s3]VC5R!$0[Lf+9o4TgBDP`3&S@]?CL+[+AQZmk.aGBN8`1XJ4mPSrrs='M.?o.ofU-h3KR'XuiY`)L6N<]3;(;doqc?D0,^9u%H-#;^fCM2kr];U:*rP[mXpu7WifjKhA+,D4fmM'Ij,20UlN6$s!I)07]T78_1b[T3dU?.YX+`EZkdJ@[C`nKq*Rl9.O,7bO1h\^J^)G)R&.d8*eQHQcHBM$djC(mLJPiGr]Qe`gL1UR-F5P8SRue\0Ku^+A"IW6IWTU0)ch'7O',6,OD;+BL:q)&n,U;UO\>jC#ejH);\.J6C[_D@^5(9W)LWs!Z]M76^$A:^<6DMW4F)LrUZ"l2&@+gTtGnZT&q[IeJ'./(k^FG2Q!W~> +endstream +endobj +214 0 obj +<< /Type /Page +/Parent 1 0 R +/MediaBox [ 0 0 595 842 ] +/Resources 3 0 R +/Contents 213 0 R +>> +endobj +215 0 obj +<< /Length 653 /Filter [ /ASCII85Decode /FlateDecode ] + >> +stream +Gat$ua_oie&A at B[G]\I^b#K.:$0iLf/gqq)de9?TPcI-//(-lXpSAXp>3n5"!'u[7a*BK4aLaEVJ'S[g5U-tU!Cj\O+RC/$,R',P(E`lOEJ_E5^*KPh5sJ6EdBNfufEF7_O[*Tl+;olpp4TNpHCYu/jONZ&Xf5t9<^/!t*o4FFO%N^/c*PFqUUM:-NW'@@_F]j%,`!'=>=JoJ(hWpKpR-H/9?QfRe8$Um<1EaI([!Hrc9UtZ\(I]4G53:J?_2u'%?g>mUMf@>+DP-Mm(pdi"5_YLjA3a.,q4^49l+I6 at Au-1`PGJ!JB;IS+g%f[]!6$T0-%2IJRc.D!IXaIQ2`abH]X790DC0 +endstream +endobj +216 0 obj +<< /Type /Page +/Parent 1 0 R +/MediaBox [ 0 0 595 842 ] +/Resources 3 0 R +/Contents 215 0 R +>> +endobj +217 0 obj +<< /Length 1048 /Filter [ /ASCII85Decode /FlateDecode ] + >> +stream +Gat%"?#Q2d'Re<25^>tu`PXURd'm!?UeT[@XjLI at 4ZLA*W-i-qBcBeDmkZq26QkX3$blDkHgZY"^0=@hJ&Dhm!!UY'T"*'h!Zb?*d%L`T%eU+#`,h64o5jVjAc0RDjX`VH'QKeH2CMB(J>b5"N.?sGi$FMtGuRCujP(VdN_$Qd[R,e=eQn>V9!`'j2irTBJP0CH`cc_DJ)OB'UYKR`Md0oAu")FjTtgR.iI&lTKJ[1;7OK]epTFA**9CP^=pe51^g=B(_=_kqI<1=C.l\dC&RV(FFGj9cP(oeHB/RdRGeT/nfL9.Ujp-*>eXU]c4/j\iAbOn&@he\#1SCXsa1q]\J/J_ at qhOZT]3$1DaUsFJt"s5=3.&('duQ9I:?ED5iEsk at LjbUPe/1>ZJ+/K^5P'-p?giY.)Is#f(uUmJ!e8gS^@S%&g/nNuJ.X>>a2FGTIst8GBR?_:ub at O%Jhtte92P0p;%FA!0aFc==K?`<+u-AAl9NqZeR%&M(%perf-H9M1i!0rm$l<@G\bJH8(7&[b`SXRt=ifo>:@B?^"A_LRG1T-)LppN^lldH/)VP:h^I=!/I(i/tfFkf"4,uFZ_Sn(>&.-YLj!Z0bisF.d,>2*qJ.r?,uWnRO)a@`_QpK4Co"Ed)T\7429qT39H>SY::Jh[gC\n^P\Og5GAEn&2\Tt73./-mfi$8578JJl0hMTuERZg+JiiM`gZ38*hs>[iO6g\WUJUoB0NE;ui14s"LF2XXA&Y.H~> +endstream +endobj +218 0 obj +<< /Type /Page +/Parent 1 0 R +/MediaBox [ 0 0 595 842 ] +/Resources 3 0 R +/Contents 217 0 R +>> +endobj +219 0 obj +<< /Length 990 /Filter [ /ASCII85Decode /FlateDecode ] + >> +stream +Gat%"8T3'C'Y`a3pk2h-%'u#X!)d$Y<)b>5%30o9e/9VLcFA*Jo\VH2Rdmn-S15?$bM1qKQLee[joYpO!&tC]A-%>U!X6sM:`qHBJY3DW7Y>@nr&D5a>C at Ff$DNS^M?O8h"tTe-pWBjGHN,p0H!.@\F&ue?Os!)8O=G&3PJC$XUFVn63ia5D/LRXfF3h`s+!6%d^.uL4ldhq*1Tu!Md>Fb',4p$8I(d6XODTSpK2#,ehP`c[[R18j at k`*6Xl>=H*E.22S_!&6S&E*=]LAQK- at l`fi8cN:1TcU39JX$L.=]gT('BHbT<>C#i^;1,5&"*/), at 2C$6^>TBlHQ@!i6?L at t@Q/M_!H8Q!k&#;d#PguIdfMNS[?hl5cRj at hS012HE5&."X:=1[eTu9[T_ngM@"\qd18gKL[GO")O1+q#P.a?6)*C(4GbG7?*^?DRLbl4HQc`]V +endstream +endobj +220 0 obj +<< /Type /Page +/Parent 1 0 R +/MediaBox [ 0 0 595 842 ] +/Resources 3 0 R +/Contents 219 0 R +>> +endobj +221 0 obj +<< /Length 667 /Filter [ /ASCII85Decode /FlateDecode ] + >> +stream +Gat%!9p:c+&A at Zck.#b/bBu)NXibB@=RK3m96jAFKFD"bKNWl)qsPOB^.H1F\M0S'rHR/%LV(o[o8t4JJHRAp4u+0X.mheCk%@DKNHhch[,GDl+I05I3e)"5GuJAJ!q-&buml\42jL`6XJ2,0F6c^gdc@%3eWqH6sp*`@UNqJGuFnDQc]S,9O4%mB$O*8^_$)1?'@IOatZHO;D,W0^]u(p#bM4h\\kTArTU7:2^0\:EQi7:ZeajC2*.7LEE-f1A6oj=HrfUh?j*ebAprJV0^XR([CtcRb`#,YO/iWRs"Miseo=AL$K7 at 9kT\=$k;"pJiYF91gPIh(1tW./#Qs'+hEEm8gLDV,%Fgke%bSrC at poqZf12%>$r`bAl*)*0[X)%2f6[5TTP`X,Ji/Aku/dj+=!P/MAVb9J2 +endstream +endobj +222 0 obj +<< /Type /Page +/Parent 1 0 R +/MediaBox [ 0 0 595 842 ] +/Resources 3 0 R +/Contents 221 0 R +>> +endobj +223 0 obj +<< /Length 887 /Filter [ /ASCII85Decode /FlateDecode ] + >> +stream +Gau0B>AqtE'RoMSn.XM$C4(kJ#772#N!H.Q6Asb&G]6TZ#ts<@$`!WGS6PBV9=#Ga(SB/ts,Okh3aBAo8-.k7#S>!+"El:(OSN>##t0;j%!(K]E"BZggr[7@"@#0Ha`oOjOYJObK**H[Jl;`!dQ,B"dug`]3nB!WGPShOMDX3rJi-trmDX99\(WFiFOf6jW6e%qi7,X\7cACs]jRPK4pFJ(5q"(D+D(CnR-Gr\Dec&,o?'MB:2KR!7jq()qAc9%5X2Ojpg/VfB(,`$TW=2h?!X1W2`iuA73HNp6m4-IA"XD[Nu+&I_#CD(T6183n)NaQej&LPfOFRFdW at sb@JB&cmlZor=IrIF^pW`!L"2@$S'n-'8iYoh.P_/m%VfB]H/X>!ebcBQPT,0o8p8l'/d=@q6,NJe.ioK]s:l2Y\0YDI:'W/=cl[c1U/&#Jl9ifs8;e%AS4e"U@*N+N!WFCY!*/a2SP`]?_&E=S-s9RYmlMKN%]^m^ci+Uo!#fl*"uXSe +endstream +endobj +224 0 obj +<< /Type /Page +/Parent 1 0 R +/MediaBox [ 0 0 595 842 ] +/Resources 3 0 R +/Contents 223 0 R +>> +endobj +225 0 obj +<< /Length 203 /Filter [ /ASCII85Decode /FlateDecode ] + >> +stream +Garp%]*cD?&;B(lTAif_$R`8BHYik^&0#%>Yu"";Kb:)o^QBY5+B&aI*53o'Z5+9M0a_s%(al/rj([^&'WaY5VALlT);Cm7oZ)<&l#1Vo9F-k,-]_a1rN +endstream +endobj +226 0 obj +<< /Type /Page +/Parent 1 0 R +/MediaBox [ 0 0 595 842 ] +/Resources 3 0 R +/Contents 225 0 R +>> +endobj +227 0 obj +<< /Length 1437 /Filter [ /ASCII85Decode /FlateDecode ] + >> +stream +Gat$8gMYb(o\EjtFMNtH0dkh"a]jX75_lMXac4s1MGgf+7=J!oBge+N5k7R*>!a'u;'MH'.%B'@b9T!GMlh*JO0 at p2TRFF4f%s]K\t`q`ZQ03qJI$jh+9HRONPHpH4mlJ%oaXVnOAe]7i+nOQOp!ANmgGR8Q-rTbp^i7sD6P]e'?A$?rY`m(AemKB\?l1?jGd]0j;iaADN2pt2#BYbFCc0?m1Qo^-<]];c9"[C0&0<:l[o:V2Ai+H6M_Z_[\)Z*a`,cp7`39(5rt3a\i9jQ,MW>M'lBNO#d:]UN6NCOfrf:FQ"2 at ThT+J)_c_:*4He1mV6)nj)m[X'E62dV3hpQ9Ck&ooIBuS?`,RIop/[ON.)bj5CU1Q"=EW.j<9c0Rgh#N,EO)&G.%Cg6A1shSpB^fR?@._TdDd>KYtmD&aY$;#FhXm%D at l\^j^i;gp\:WG7GUJ["[+DN`i=C0;9#Uot<^qGE7hUlcO?8358[Vg3`ULNII:_Q!n=VqX+mfouKSZpMKTq?.b`k?%$M-X45:Gb`#mBjHt4nLYKr6i0+E_FE$iK0T.M]_#tWQ,(0LA,f(.(N`$(Q68MCO/]Sa97%LUNp7enkI#p7IZGWT=ZWjiRA\CVDn:j[]e6SdLR.GWYHi]TVF(rlJ<8"Eq4]ouN'%-9a1'E'"hF.kM~> +endstream +endobj +228 0 obj +<< /Type /Page +/Parent 1 0 R +/MediaBox [ 0 0 595 842 ] +/Resources 3 0 R +/Contents 227 0 R +>> +endobj +229 0 obj +<< /Length 1777 /Filter [ /ASCII85Decode /FlateDecode ] + >> +stream +Gat,fcT?b63OK%[QK at Y3QZr;.CKj+2p?W/;dEL)G?pO8ZFkh1'Dr*$T$*D6oLE*ELgu`?2NT#ME/Aq'bkuCO)8pJkJ+GLkL<42TaCj+IV_'"$GEYrSfl$prd'#$Jeh=WEBP8BUM".?^.*@UK7PO&QTI*qF/TE]pm#*If#QU at X-u*?stVViNKFX_trJfbLY19WuNN:5[o^lbMq2rr.VY#!0#rah_'8PU3AF=rc%EP]64oaHDX--e8Gi!lpd&n`*F7Kd7h3?ah*MOm<2AJqrXdcVS@,4K:Suq(?87]bD>IM4RBWu'F9EX8smf;X>8roY)ga'R^saNc.Wb"I09["\i#'cZ&CW$Tu@(OV[IG=>3Rf)5K$%jR[d4#kG-,0IAkCN-SYiK.u45iWQ[rs#:!'+hq^In?G<]0L%"F<3f*l3_8*1XLk-2Ui-i$VIUF,b%lB.7cM&MsHt-c!:qpQ'>TYDM`0DII8S(^I&^h7V';+0!0Q4<^ZDO4i:2.*Y^)%[W8Q%?I^dO$p_GKSu$:>W;5mb:A#!+IK^9MKBB)n41,W2OG0a8OXOO$QL at VLqrNTPNT)n0>7'6B3.3IkjVc5H$@;L^\.1)SgCl\Ui'CN"TSUDZ&Ci!a;qU`eS5PnX+!a/l>$25d8aJo$N(L3 at LR>1AhI8e"7&+?-59S5UUg- at gR&Re,b.VFX:Dlf=BlY4V at 7;()1k=>n3_f^bAO=r^gE8>0/T>7L(VU^g_Nb#]4W*rXs7Y(-Vfs$9"[-d9HUnCKTEWjN2Q,flMkn]LTAn.)djB5Tp4nV_NTkCUEsGbMs;Y,0Q\V9?B'8,W2WE2:#7?&.#SH(+:>A)''JVYJ4j"rI0iLFW/"'keu3JXU>T`##>9)"(;-W>*;)%hB;M&r4j#1Iq%#r_,UICO/'_E(^Et'7d\[qJ!O-`f&T^9K:u<KLn)K`Tfj)5L[^En8tY-9k`'apP'BM+EL]Y*V1Ye.S?DK^4kT,EmcqQ!"nH*2A*i,5`%'h9*XoZmii2!nR+CpB%(-ME'b at t>%t/?Bi&r]%7Igjf%(8&A0nR23*;cZ&126,die7l0>&H6*if;<(9P$lSNuqt at UA\9!nkrqA7I2$e at Rn2RGgMMlWP]"!l^U'U&rn+KYAXE(om,^uV51Kp1f\#WU+,?HPd`qGP,&\ZF)UKZkch(DeA.pMtWqQue+Mb%q+-taoja?b at rM?OiBWW@@Y&`Z*'8?MU~> +endstream +endobj +230 0 obj +<< /Type /Page +/Parent 1 0 R +/MediaBox [ 0 0 595 842 ] +/Resources 3 0 R +/Contents 229 0 R +>> +endobj +231 0 obj +<< /Length 257 /Filter [ /ASCII85Decode /FlateDecode ] + >> +stream +GasJK0aiUf'SQ5YMDshYCQ-9#YsLNo.qC.N'Vc,58u&6ThcCDKK2Al/4-$q#Kd):.LR97heIW'>M1JDTL7$5_i!_'$TUp*1Na2o&j0Kh at kBc=;O0R8CQ1fMXD-'nHHcIsLO,m#bR`^o`]1EK=^UpeWS+,)!n(GFVFc at R"6!_Q'Ok52mi5cUr>XD$rA:anP%SfAYY,"lE3o^8f'2psdn8iNtoM/1EdJD>*O_ibH[icQ#M#a,U.[L&jo5-_R"^Ho~> +endstream +endobj +232 0 obj +<< /Type /Page +/Parent 1 0 R +/MediaBox [ 0 0 595 842 ] +/Resources 3 0 R +/Contents 231 0 R +>> +endobj +233 0 obj +<< /Length 1328 /Filter [ /ASCII85Decode /FlateDecode ] + >> +stream +Gau`SD/\/e&H;*)+_8BS!&Z at BM,Jm68='JC0Eg->m)u[FZ;'!TABC[D[JonF7EVDObAMh39n7n@][u>fj6=I%[WoXiA,sTb17O!6Fpol0N8*GWDe=<1DiS(6:N+3`Fb^,P)F03cc&MRnottp&_2KBY6ZjQ4Xo(,Of;Pg"-,+AP_ko_;e0\o1'Bn-R)kkf at U4nt3%9+qoDj\V!bb,af#t=sdk<)>AF(_qN//rX$85gq/\l=9!f,1M7%nSOcpV<3m7'X\Y"L3kk)\B5'`[]KcKgol:SL#o[)-A?P`-U^r/4K*&eZ,,9Q>\':K\F^%kc5XHVkKe52GqX67Z]XZ60@]Dq.";!sa6mds=$KIi&]fRiH/OcpeF=I0p?h$4NeAZb3eprk/"/LDoY!M'JILetk[%?O2D!(mQZ9c=9S2?+BTTH5'[Qs(dVZ(/D*dH1ZCt=\(d3s3c_P:^SXHs`@Qn_ at Vr[@;X8kaSn18Es01Kr\AQg5+h\-RI++M%Y*/]IXXn)[0?QZUI^'FpOLu.2eh<^9H46Q(=aE'j/D6pN9lBW at oM.(L&)bN'"N?e+[H4o"YEpH1eobca[a-'0Ee^lLnrfH`^c);..8XR[e^FH43^;3(c*+m&3-YqS at 3=D65j54I\o"d?@3<)$4e5H`2+_ch/T+l;j%39kSM[>pu_#>'HHY<'KS84$p_Gi7+UMF2<,R[OD:)@%+sG3%om]Jou2%X;UM%=!Wd-"IiCDdDm4Y'7Kig`MK>(B/]'C=]JpBYd0kDFaL>Bi-9bA\rfGC]CRkj at kkFKMOci#+`XGk6<;!]9Qfg'qHu0SOXN*l+2=WJ(0tZZ-4HtFq[hK/rcMsV\'s51YI?HJ\Na,enoZS7rO['=Vk'=/]4&^4BNLQ&fR62%;iC3C03XWpd^:U_ihEF565RNFN44O8B2"ed$j9FX&f\o=qp,!tA*PN]+_EV2:==>Q!#1ptugHb4aK!WD,naARmoWs7"(R_u!O.e)m\I.V8QSASnDi#O'O<*ZRQ]og%/*U)1)n]ug1,bLBpCBb2u7,$!Hdfh\F,ZM9:jX*Zn8%HYCP?C`L=PEq[V&9Xf&I.OU5iFn7=Q$E4T`5k6%erAjbZ*"#1=i!INSPGk(r#W"?L"(JqWk$7os>RS4@~> +endstream +endobj +234 0 obj +<< /Type /Page +/Parent 1 0 R +/MediaBox [ 0 0 595 842 ] +/Resources 3 0 R +/Contents 233 0 R +>> +endobj +235 0 obj +<< /Length 1066 /Filter [ /ASCII85Decode /FlateDecode ] + >> +stream +Gat%"D/[lW&H:NniGWgo\p!F"ahEbNU`kDE<^6rci2'1a8F;MK/cGE'YE$5W$;Kf5(Z4&4HgW2`=0q!/!$Z\$@.gZ3Jm_P>b0C&2$54&[!T*%8au*N:B(Qrs*&/:7Q"TpWmd>P.$3,H#ZQ/d6X.&eZ^.Mb'>a*oP7[7r<5gT&d\RHT>ujt8=/e%F>4'L]m[]bXanWf5TH>ZSi*@6c&Mg\"SYU4JP8\Gc=Z_%;W9aKY-WP[^Z%E5E`-^<'MnV2+>-p=#"+4A*"D89(`'>Ic%hafBR8r,aT at hM[^i0Z0$$#M^MKDb6(+F"r)O66O8G@`XKVl_5^<$lumtmME at UEuM`YsbDJjS at lA\3^M93^De4?6EAQ/PW#PO_tV=tl*-pqkMkOY$Q\#"GV$&3fj6?1-ag=k(As^J'>:--mC(fZ;4"VjC?JL1,mXi4D#=;Y%l at m9XT^,Y8W$q3S3[imCpr?8oC(a6VUq%B[h0*(:nJMl[#U\^RD02)EnJU2u24Ym!&=9f3jY:#`7Bs'G3DZ6TYiG:^W +endstream +endobj +236 0 obj +<< /Type /Page +/Parent 1 0 R +/MediaBox [ 0 0 595 842 ] +/Resources 3 0 R +/Contents 235 0 R +/Annots 237 0 R +>> +endobj +237 0 obj +[ +238 0 R +239 0 R +240 0 R +241 0 R +242 0 R +243 0 R +244 0 R +] +endobj +238 0 obj +<< /Type /Annot +/Subtype /Link +/Rect [ 352.0 687.572 373.66 677.572 ] +/C [ 0 0 0 ] +/Border [ 0 0 0 ] +/A << /URI (http://uffi.b9.com) +/S /URI >> +/H /I +>> +endobj +239 0 obj +<< /Type /Annot +/Subtype /Link +/Rect [ 381.047 687.572 451.607 677.572 ] +/C [ 0 0 0 ] +/Border [ 0 0 0 ] +/A << /URI (http://uffi.b9.com) +/S /URI >> +/H /I +>> +endobj +240 0 obj +<< /Type /Annot +/Subtype /Link +/Rect [ 532.89 676.572 564.57 666.572 ] +/C [ 0 0 0 ] +/Border [ 0 0 0 ] +/A << /URI (http://www.sourceforge.net/projects/cclan) +/S /URI >> +/H /I +>> +endobj +241 0 obj +<< /Type /Annot +/Subtype /Link +/Rect [ 571.85 676.572 586.29 666.572 ] +/C [ 0 0 0 ] +/Border [ 0 0 0 ] +/A << /URI (http://www.sourceforge.net/projects/cclan) +/S /URI >> +/H /I +>> +endobj +242 0 obj +<< /Type /Annot +/Subtype /Link +/Rect [ 120.0 665.572 280.52 655.572 ] +/C [ 0 0 0 ] +/Border [ 0 0 0 ] +/A << /URI (http://www.sourceforge.net/projects/cclan) +/S /URI >> +/H /I +>> +endobj +243 0 obj +<< /Type /Annot +/Subtype /Link +/Rect [ 178.61 654.572 194.16 644.572 ] +/C [ 0 0 0 ] +/Border [ 0 0 0 ] +/A << /URI (http://cvs.sourceforge.net/cgi-bin/viewcvs.cgi/cclan/asdf/asdf.lisp) +/S /URI >> +/H /I +>> +endobj +244 0 obj +<< /Type /Annot +/Subtype /Link +/Rect [ 199.99 654.572 462.73 644.572 ] +/C [ 0 0 0 ] +/Border [ 0 0 0 ] +/A << /URI (http://cvs.sourceforge.net/cgi-bin/viewcvs.cgi/cclan/asdf/asdf.lisp) +/S /URI >> +/H /I +>> +endobj +245 0 obj +<< /Length 293 /Filter [ /ASCII85Decode /FlateDecode ] + >> +stream +GarnQ]2$6t']&^&GAN"?r-jS=&QCY6DnqH(8S'?1_$pKrO41H]6pb4_c9758]^t3e'Yl"u/&8WI_N?OFq(XQC.2_#?#n?k:YFDFBT$LF50&RcJF-\:`1m>67-=V?*%$aAkSQ'/o9fVhMC`.g%9VrFjO-`BDH52e\$=>g; +endstream +endobj +246 0 obj +<< /Type /Page +/Parent 1 0 R +/MediaBox [ 0 0 595 842 ] +/Resources 3 0 R +/Contents 245 0 R +>> +endobj +249 0 obj +<< + /Title (\376\377\0\125\0\106\0\106\0\111\0\40\0\122\0\145\0\146\0\145\0\162\0\145\0\156\0\143\0\145\0\40\0\107\0\165\0\151\0\144\0\145) + /Parent 247 0 R + /Next 251 0 R + /A 248 0 R +>> endobj +251 0 obj +<< + /Title (\376\377\0\124\0\141\0\142\0\154\0\145\0\40\0\157\0\146\0\40\0\103\0\157\0\156\0\164\0\145\0\156\0\164\0\163) + /Parent 247 0 R + /Prev 249 0 R + /Next 252 0 R + /A 250 0 R +>> endobj +252 0 obj +<< + /Title (\376\377\0\120\0\162\0\145\0\146\0\141\0\143\0\145) + /Parent 247 0 R + /Prev 251 0 R + /Next 253 0 R + /A 15 0 R +>> endobj +253 0 obj +<< + /Title (\376\377\0\103\0\150\0\141\0\160\0\164\0\145\0\162\0\240\0\61\0\56\0\240\0\111\0\156\0\164\0\162\0\157\0\144\0\165\0\143\0\164\0\151\0\157\0\156) + /Parent 247 0 R + /First 254 0 R + /Last 257 0 R + /Prev 252 0 R + /Next 260 0 R + /Count -6 + /A 17 0 R +>> endobj +254 0 obj +<< + /Title (\376\377\0\120\0\165\0\162\0\160\0\157\0\163\0\145) + /Parent 253 0 R + /Next 255 0 R + /A 19 0 R +>> endobj +255 0 obj +<< + /Title (\376\377\0\102\0\141\0\143\0\153\0\147\0\162\0\157\0\165\0\156\0\144) + /Parent 253 0 R + /Prev 254 0 R + /Next 256 0 R + /A 21 0 R +>> endobj +256 0 obj +<< + /Title (\376\377\0\123\0\165\0\160\0\160\0\157\0\162\0\164\0\145\0\144\0\40\0\111\0\155\0\160\0\154\0\145\0\155\0\145\0\156\0\164\0\141\0\164\0\151\0\157\0\156\0\163) + /Parent 253 0 R + /Prev 255 0 R + /Next 257 0 R + /A 23 0 R +>> endobj +257 0 obj +<< + /Title (\376\377\0\104\0\145\0\163\0\151\0\147\0\156) + /Parent 253 0 R + /First 258 0 R + /Last 259 0 R + /Prev 256 0 R + /Count -2 + /A 25 0 R +>> endobj +258 0 obj +<< + /Title (\376\377\0\117\0\166\0\145\0\162\0\166\0\151\0\145\0\167) + /Parent 257 0 R + /Next 259 0 R + /A 27 0 R +>> endobj +259 0 obj +<< + /Title (\376\377\0\120\0\162\0\151\0\157\0\162\0\151\0\164\0\151\0\145\0\163) + /Parent 257 0 R + /Prev 258 0 R + /A 29 0 R +>> endobj +260 0 obj +<< + /Title (\376\377\0\103\0\150\0\141\0\160\0\164\0\145\0\162\0\240\0\62\0\56\0\240\0\120\0\162\0\157\0\147\0\162\0\141\0\155\0\155\0\151\0\156\0\147\0\40\0\116\0\157\0\164\0\145\0\163) + /Parent 247 0 R + /First 261 0 R + /Last 266 0 R + /Prev 253 0 R + /Next 269 0 R + /Count -8 + /A 31 0 R +>> endobj +261 0 obj +<< + /Title (\376\377\0\111\0\155\0\160\0\154\0\145\0\155\0\145\0\156\0\164\0\141\0\164\0\151\0\157\0\156\0\40\0\123\0\160\0\145\0\143\0\151\0\146\0\151\0\143\0\40\0\116\0\157\0\164\0\145\0\163) + /Parent 260 0 R + /First 262 0 R + /Last 264 0 R + /Next 265 0 R + /Count -3 + /A 33 0 R +>> endobj +262 0 obj +<< + /Title (\376\377\0\101\0\154\0\154\0\145\0\147\0\162\0\157\0\103\0\114) + /Parent 261 0 R + /Next 263 0 R + /A 35 0 R +>> endobj +263 0 obj +<< + /Title (\376\377\0\114\0\151\0\163\0\160\0\167\0\157\0\162\0\153\0\163) + /Parent 261 0 R + /Prev 262 0 R + /Next 264 0 R + /A 37 0 R +>> endobj +264 0 obj +<< + /Title (\376\377\0\103\0\115\0\125\0\103\0\114) + /Parent 261 0 R + /Prev 263 0 R + /A 39 0 R +>> endobj +265 0 obj +<< + /Title (\376\377\0\106\0\157\0\162\0\145\0\151\0\147\0\156\0\40\0\117\0\142\0\152\0\145\0\143\0\164\0\40\0\122\0\145\0\160\0\162\0\145\0\163\0\145\0\156\0\164\0\141\0\164\0\151\0\157\0\156\0\40\0\141\0\156\0\144\0\40\0\101\0\143\0\143\0\145\0\163\0\163) + /Parent 260 0 R + /Prev 261 0 R + /Next 266 0 R + /A 41 0 R +>> endobj +266 0 obj +<< + /Title (\376\377\0\117\0\160\0\164\0\151\0\155\0\151\0\172\0\151\0\156\0\147\0\40\0\103\0\157\0\144\0\145\0\40\0\125\0\163\0\151\0\156\0\147\0\40\0\125\0\106\0\106\0\111) + /Parent 260 0 R + /First 267 0 R + /Last 268 0 R + /Prev 265 0 R + /Count -2 + /A 43 0 R +>> endobj +267 0 obj +<< + /Title (\376\377\0\102\0\141\0\143\0\153\0\147\0\162\0\157\0\165\0\156\0\144) + /Parent 266 0 R + /Next 268 0 R + /A 45 0 R +>> endobj +268 0 obj +<< + /Title (\376\377\0\103\0\162\0\157\0\163\0\163\0\55\0\111\0\155\0\160\0\154\0\145\0\155\0\145\0\156\0\164\0\141\0\164\0\151\0\157\0\156\0\40\0\117\0\160\0\164\0\151\0\155\0\151\0\172\0\141\0\164\0\151\0\157\0\156) + /Parent 266 0 R + /Prev 267 0 R + /A 47 0 R +>> endobj +269 0 obj +<< + /Title (\376\377\0\104\0\145\0\143\0\154\0\141\0\162\0\141\0\164\0\151\0\157\0\156\0\163) + /Parent 247 0 R + /First 271 0 R + /Last 272 0 R + /Prev 260 0 R + /Next 273 0 R + /Count -2 + /A 49 0 R +>> endobj +271 0 obj +<< + /Title (\376\377\0\117\0\166\0\145\0\162\0\166\0\151\0\145\0\167) + /Parent 269 0 R + /Next 272 0 R + /A 270 0 R +>> endobj +272 0 obj +<< + /Title (\376\377\0\144\0\145\0\146\0\55\0\164\0\171\0\160\0\145) + /Parent 269 0 R + /Prev 271 0 R + /A 51 0 R +>> endobj +273 0 obj +<< + /Title (\376\377\0\120\0\162\0\151\0\155\0\151\0\164\0\151\0\166\0\145\0\40\0\124\0\171\0\160\0\145\0\163) + /Parent 247 0 R + /First 274 0 R + /Last 276 0 R + /Prev 269 0 R + /Next 277 0 R + /Count -3 + /A 53 0 R +>> endobj +274 0 obj +<< + /Title (\376\377\0\144\0\145\0\146\0\55\0\143\0\157\0\156\0\163\0\164\0\141\0\156\0\164) + /Parent 273 0 R + /Next 275 0 R + /A 55 0 R +>> endobj +275 0 obj +<< + /Title (\376\377\0\144\0\145\0\146\0\55\0\146\0\157\0\162\0\145\0\151\0\147\0\156\0\55\0\164\0\171\0\160\0\145) + /Parent 273 0 R + /Prev 274 0 R + /Next 276 0 R + /A 57 0 R +>> endobj +276 0 obj +<< + /Title (\376\377\0\156\0\165\0\154\0\154\0\55\0\143\0\150\0\141\0\162\0\55\0\160) + /Parent 273 0 R + /Prev 275 0 R + /A 59 0 R +>> endobj +277 0 obj +<< + /Title (\376\377\0\101\0\147\0\147\0\162\0\145\0\147\0\141\0\164\0\145\0\40\0\124\0\171\0\160\0\145\0\163) + /Parent 247 0 R + /First 278 0 R + /Last 284 0 R + /Prev 273 0 R + /Next 285 0 R + /Count -7 + /A 61 0 R +>> endobj +278 0 obj +<< + /Title (\376\377\0\144\0\145\0\146\0\55\0\145\0\156\0\165\0\155) + /Parent 277 0 R + /Next 279 0 R + /A 63 0 R +>> endobj +279 0 obj +<< + /Title (\376\377\0\144\0\145\0\146\0\55\0\163\0\164\0\162\0\165\0\143\0\164) + /Parent 277 0 R + /Prev 278 0 R + /Next 280 0 R + /A 65 0 R +>> endobj +280 0 obj +<< + /Title (\376\377\0\147\0\145\0\164\0\55\0\163\0\154\0\157\0\164\0\55\0\166\0\141\0\154\0\165\0\145) + /Parent 277 0 R + /Prev 279 0 R + /Next 281 0 R + /A 67 0 R +>> endobj +281 0 obj +<< + /Title (\376\377\0\147\0\145\0\164\0\55\0\163\0\154\0\157\0\164\0\55\0\160\0\157\0\151\0\156\0\164\0\145\0\162) + /Parent 277 0 R + /Prev 280 0 R + /Next 282 0 R + /A 69 0 R +>> endobj +282 0 obj +<< + /Title (\376\377\0\144\0\145\0\146\0\55\0\141\0\162\0\162\0\141\0\171\0\55\0\160\0\157\0\151\0\156\0\164\0\145\0\162) + /Parent 277 0 R + /Prev 281 0 R + /Next 283 0 R + /A 71 0 R +>> endobj +283 0 obj +<< + /Title (\376\377\0\144\0\145\0\162\0\145\0\146\0\55\0\141\0\162\0\162\0\141\0\171) + /Parent 277 0 R + /Prev 282 0 R + /Next 284 0 R + /A 73 0 R +>> endobj +284 0 obj +<< + /Title (\376\377\0\144\0\145\0\146\0\55\0\165\0\156\0\151\0\157\0\156) + /Parent 277 0 R + /Prev 283 0 R + /A 75 0 R +>> endobj +285 0 obj +<< + /Title (\376\377\0\117\0\142\0\152\0\145\0\143\0\164\0\163) + /Parent 247 0 R + /First 286 0 R + /Last 298 0 R + /Prev 277 0 R + /Next 299 0 R + /Count -13 + /A 77 0 R +>> endobj +286 0 obj +<< + /Title (\376\377\0\141\0\154\0\154\0\157\0\143\0\141\0\164\0\145\0\55\0\146\0\157\0\162\0\145\0\151\0\147\0\156\0\55\0\157\0\142\0\152\0\145\0\143\0\164) + /Parent 285 0 R + /Next 287 0 R + /A 79 0 R +>> endobj +287 0 obj +<< + /Title (\376\377\0\146\0\162\0\145\0\145\0\55\0\146\0\157\0\162\0\145\0\151\0\147\0\156\0\55\0\157\0\142\0\152\0\145\0\143\0\164) + /Parent 285 0 R + /Prev 286 0 R + /Next 288 0 R + /A 81 0 R +>> endobj +288 0 obj +<< + /Title (\376\377\0\167\0\151\0\164\0\150\0\55\0\146\0\157\0\162\0\145\0\151\0\147\0\156\0\55\0\157\0\142\0\152\0\145\0\143\0\164) + /Parent 285 0 R + /Prev 287 0 R + /Next 289 0 R + /A 83 0 R +>> endobj +289 0 obj +<< + /Title (\376\377\0\163\0\151\0\172\0\145\0\55\0\157\0\146\0\55\0\146\0\157\0\162\0\145\0\151\0\147\0\156\0\55\0\164\0\171\0\160\0\145) + /Parent 285 0 R + /Prev 288 0 R + /Next 290 0 R + /A 85 0 R +>> endobj +290 0 obj +<< + /Title (\376\377\0\160\0\157\0\151\0\156\0\164\0\145\0\162\0\55\0\141\0\144\0\144\0\162\0\145\0\163\0\163) + /Parent 285 0 R + /Prev 289 0 R + /Next 291 0 R + /A 87 0 R +>> endobj +291 0 obj +<< + /Title (\376\377\0\144\0\145\0\162\0\145\0\146\0\55\0\160\0\157\0\151\0\156\0\164\0\145\0\162) + /Parent 285 0 R + /Prev 290 0 R + /Next 292 0 R + /A 89 0 R +>> endobj +292 0 obj +<< + /Title (\376\377\0\145\0\156\0\163\0\165\0\162\0\145\0\55\0\143\0\150\0\141\0\162\0\55\0\143\0\150\0\141\0\162\0\141\0\143\0\164\0\145\0\162) + /Parent 285 0 R + /Prev 291 0 R + /Next 293 0 R + /A 91 0 R +>> endobj +293 0 obj +<< + /Title (\376\377\0\145\0\156\0\163\0\165\0\162\0\145\0\55\0\143\0\150\0\141\0\162\0\55\0\151\0\156\0\164\0\145\0\147\0\145\0\162) + /Parent 285 0 R + /Prev 292 0 R + /Next 294 0 R + /A 93 0 R +>> endobj +294 0 obj +<< + /Title (\376\377\0\155\0\141\0\153\0\145\0\55\0\156\0\165\0\154\0\154\0\55\0\160\0\157\0\151\0\156\0\164\0\145\0\162) + /Parent 285 0 R + /Prev 293 0 R + /Next 295 0 R + /A 95 0 R +>> endobj +295 0 obj +<< + /Title (\376\377\0\156\0\165\0\154\0\154\0\55\0\160\0\157\0\151\0\156\0\164\0\145\0\162\0\55\0\160) + /Parent 285 0 R + /Prev 294 0 R + /Next 296 0 R + /A 97 0 R +>> endobj +296 0 obj +<< + /Title (\376\377\0\53\0\156\0\165\0\154\0\154\0\55\0\143\0\163\0\164\0\162\0\151\0\156\0\147\0\55\0\160\0\157\0\151\0\156\0\164\0\145\0\162\0\53) + /Parent 285 0 R + /Prev 295 0 R + /Next 297 0 R + /A 99 0 R +>> endobj +297 0 obj +<< + /Title (\376\377\0\167\0\151\0\164\0\150\0\55\0\143\0\141\0\163\0\164\0\55\0\160\0\157\0\151\0\156\0\164\0\145\0\162) + /Parent 285 0 R + /Prev 296 0 R + /Next 298 0 R + /A 101 0 R +>> endobj +298 0 obj +<< + /Title (\376\377\0\144\0\145\0\146\0\55\0\146\0\157\0\162\0\145\0\151\0\147\0\156\0\55\0\166\0\141\0\162) + /Parent 285 0 R + /Prev 297 0 R + /A 103 0 R +>> endobj +299 0 obj +<< + /Title (\376\377\0\123\0\164\0\162\0\151\0\156\0\147\0\163) + /Parent 247 0 R + /First 300 0 R + /Last 306 0 R + /Prev 285 0 R + /Next 307 0 R + /Count -7 + /A 105 0 R +>> endobj +300 0 obj +<< + /Title (\376\377\0\143\0\157\0\156\0\166\0\145\0\162\0\164\0\55\0\146\0\162\0\157\0\155\0\55\0\143\0\163\0\164\0\162\0\151\0\156\0\147) + /Parent 299 0 R + /Next 301 0 R + /A 107 0 R +>> endobj +301 0 obj +<< + /Title (\376\377\0\143\0\157\0\156\0\166\0\145\0\162\0\164\0\55\0\164\0\157\0\55\0\143\0\163\0\164\0\162\0\151\0\156\0\147) + /Parent 299 0 R + /Prev 300 0 R + /Next 302 0 R + /A 109 0 R +>> endobj +302 0 obj +<< + /Title (\376\377\0\146\0\162\0\145\0\145\0\55\0\143\0\163\0\164\0\162\0\151\0\156\0\147) + /Parent 299 0 R + /Prev 301 0 R + /Next 303 0 R + /A 111 0 R +>> endobj +303 0 obj +<< + /Title (\376\377\0\167\0\151\0\164\0\150\0\55\0\143\0\163\0\164\0\162\0\151\0\156\0\147) + /Parent 299 0 R + /Prev 302 0 R + /Next 304 0 R + /A 113 0 R +>> endobj +304 0 obj +<< + /Title (\376\377\0\143\0\157\0\156\0\166\0\145\0\162\0\164\0\55\0\146\0\162\0\157\0\155\0\55\0\146\0\157\0\162\0\145\0\151\0\147\0\156\0\55\0\163\0\164\0\162\0\151\0\156\0\147) + /Parent 299 0 R + /Prev 303 0 R + /Next 305 0 R + /A 115 0 R +>> endobj +305 0 obj +<< + /Title (\376\377\0\143\0\157\0\156\0\166\0\145\0\162\0\164\0\55\0\164\0\157\0\55\0\146\0\157\0\162\0\145\0\151\0\147\0\156\0\55\0\163\0\164\0\162\0\151\0\156\0\147) + /Parent 299 0 R + /Prev 304 0 R + /Next 306 0 R + /A 117 0 R +>> endobj +306 0 obj +<< + /Title (\376\377\0\141\0\154\0\154\0\157\0\143\0\141\0\164\0\145\0\55\0\146\0\157\0\162\0\145\0\151\0\147\0\156\0\55\0\163\0\164\0\162\0\151\0\156\0\147) + /Parent 299 0 R + /Prev 305 0 R + /A 119 0 R +>> endobj +307 0 obj +<< + /Title (\376\377\0\106\0\165\0\156\0\143\0\164\0\151\0\157\0\156\0\163\0\40\0\46\0\40\0\114\0\151\0\142\0\162\0\141\0\162\0\151\0\145\0\163) + /Parent 247 0 R + /First 308 0 R + /Last 310 0 R + /Prev 299 0 R + /Next 311 0 R + /Count -3 + /A 121 0 R +>> endobj +308 0 obj +<< + /Title (\376\377\0\144\0\145\0\146\0\55\0\146\0\165\0\156\0\143\0\164\0\151\0\157\0\156) + /Parent 307 0 R + /Next 309 0 R + /A 123 0 R +>> endobj +309 0 obj +<< + /Title (\376\377\0\154\0\157\0\141\0\144\0\55\0\146\0\157\0\162\0\145\0\151\0\147\0\156\0\55\0\154\0\151\0\142\0\162\0\141\0\162\0\171) + /Parent 307 0 R + /Prev 308 0 R + /Next 310 0 R + /A 125 0 R +>> endobj +310 0 obj +<< + /Title (\376\377\0\146\0\151\0\156\0\144\0\55\0\146\0\157\0\162\0\145\0\151\0\147\0\156\0\55\0\154\0\151\0\142\0\162\0\141\0\162\0\171) + /Parent 307 0 R + /Prev 309 0 R + /A 127 0 R +>> endobj +311 0 obj +<< + /Title (\376\377\0\101\0\160\0\160\0\145\0\156\0\144\0\151\0\170\0\240\0\101\0\56\0\240\0\111\0\156\0\163\0\164\0\141\0\154\0\154\0\141\0\164\0\151\0\157\0\156) + /Parent 247 0 R + /First 312 0 R + /Last 313 0 R + /Prev 307 0 R + /Next 314 0 R + /Count -2 + /A 132 0 R +>> endobj +312 0 obj +<< + /Title (\376\377\0\104\0\157\0\167\0\156\0\154\0\157\0\141\0\144\0\40\0\125\0\106\0\106\0\111) + /Parent 311 0 R + /Next 313 0 R + /A 134 0 R +>> endobj +313 0 obj +<< + /Title (\376\377\0\114\0\157\0\141\0\144\0\151\0\156\0\147) + /Parent 311 0 R + /Prev 312 0 R + /A 136 0 R +>> endobj +314 0 obj +<< + /Title (\376\377\0\107\0\154\0\157\0\163\0\163\0\141\0\162\0\171) + /Parent 247 0 R + /Prev 311 0 R + /A 138 0 R +>> endobj +315 0 obj +<< /Type /Font +/Subtype /Type1 +/Name /F3 +/BaseFont /Helvetica-Bold +/Encoding /WinAnsiEncoding >> +endobj +316 0 obj +<< /Type /Font +/Subtype /Type1 +/Name /F5 +/BaseFont /Times-Roman +/Encoding /WinAnsiEncoding >> +endobj +317 0 obj +<< /Type /Font +/Subtype /Type1 +/Name /F10 +/BaseFont /Courier-Oblique +/Encoding /WinAnsiEncoding >> +endobj +318 0 obj +<< /Type /Font +/Subtype /Type1 +/Name /F1 +/BaseFont /Helvetica +/Encoding /WinAnsiEncoding >> +endobj +319 0 obj +<< /Type /Font +/Subtype /Type1 +/Name /F6 +/BaseFont /Times-Italic +/Encoding /WinAnsiEncoding >> +endobj +320 0 obj +<< /Type /Font +/Subtype /Type1 +/Name /F4 +/BaseFont /Helvetica-BoldOblique +/Encoding /WinAnsiEncoding >> +endobj +321 0 obj +<< /Type /Font +/Subtype /Type1 +/Name /F9 +/BaseFont /Courier +/Encoding /WinAnsiEncoding >> +endobj +322 0 obj +<< /Type /Font +/Subtype /Type1 +/Name /F7 +/BaseFont /Times-Bold +/Encoding /WinAnsiEncoding >> +endobj +1 0 obj +<< /Type /Pages +/Count 55 +/Kids [6 0 R 8 0 R 10 0 R 12 0 R 129 0 R 140 0 R 142 0 R 144 0 R 146 0 R 148 0 R 150 0 R 152 0 R 154 0 R 156 0 R 158 0 R 160 0 R 162 0 R 164 0 R 166 0 R 168 0 R 170 0 R 172 0 R 174 0 R 176 0 R 178 0 R 180 0 R 182 0 R 184 0 R 186 0 R 188 0 R 190 0 R 192 0 R 194 0 R 196 0 R 198 0 R 200 0 R 202 0 R 204 0 R 206 0 R 208 0 R 210 0 R 212 0 R 214 0 R 216 0 R 218 0 R 220 0 R 222 0 R 224 0 R 226 0 R 228 0 R 230 0 R 232 0 R 234 0 R 236 0 R 246 0 R ] >> +endobj +2 0 obj +<< /Type /Catalog +/Pages 1 0 R + /Outlines 247 0 R + /PageMode /UseOutlines + /Names << /Dests << /Names [ (preface) [ 140 0 R /XYZ 115.0 774.889 null ] (introduction) [ 142 0 R /XYZ 115.0 774.889 null ] (notes) [ 146 0 R /XYZ 115.0 774.889 null ] (ref_declarations) [ 150 0 R /XYZ 115.0 774.889 null ] (primitives) [ 154 0 R /XYZ 115.0 774.889 null ] (aggregates) [ 162 0 R /XYZ 115.0 774.889 null ] (objects) [ 178 0 R /XYZ 115.0 774.889 null ] (strings) [ 208 0 R /XYZ 115.0 774.889 null ] (func_libr) [ 226 0 R /XYZ 115.0 774.889 null ] (installation) [ 236 0 R /XYZ 115.0 774.889 null ] (glossary) [ 246 0 R /XYZ 115.0 774.889 null ] (id2463880) [ 10 0 R /XYZ 115.0 774.889 null ] ] >> >> + >> +endobj +3 0 obj +<< +/Font << /F3 315 0 R /F5 316 0 R /F10 317 0 R /F6 319 0 R /F1 318 0 R /F4 320 0 R /F9 321 0 R /F7 322 0 R >> +/ProcSet [ /PDF /ImageC /Text ] >> +endobj +15 0 obj +<< +/S /GoTo +/D [140 0 R /XYZ 115.0 774.889 null] +>> +endobj +17 0 obj +<< +/S /GoTo +/D [142 0 R /XYZ 115.0 774.889 null] +>> +endobj +19 0 obj +<< +/S /GoTo +/D [142 0 R /XYZ 115.0 736.898 null] +>> +endobj +21 0 obj +<< +/S /GoTo +/D [142 0 R /XYZ 115.0 671.572 null] +>> +endobj +23 0 obj +<< +/S /GoTo +/D [142 0 R /XYZ 115.0 509.246 null] +>> +endobj +25 0 obj +<< +/S /GoTo +/D [142 0 R /XYZ 115.0 246.92 null] +>> +endobj +27 0 obj +<< +/S /GoTo +/D [142 0 R /XYZ 115.0 213.594 null] +>> +endobj +29 0 obj +<< +/S /GoTo +/D [142 0 R /XYZ 115.0 130.155 null] +>> +endobj +31 0 obj +<< +/S /GoTo +/D [146 0 R /XYZ 115.0 774.889 null] +>> +endobj +33 0 obj +<< +/S /GoTo +/D [146 0 R /XYZ 115.0 736.898 null] +>> +endobj +35 0 obj +<< +/S /GoTo +/D [146 0 R /XYZ 115.0 693.572 null] +>> +endobj +37 0 obj +<< +/S /GoTo +/D [146 0 R /XYZ 115.0 654.133 null] +>> +endobj +39 0 obj +<< +/S /GoTo +/D [146 0 R /XYZ 115.0 614.694 null] +>> +endobj +41 0 obj +<< +/S /GoTo +/D [146 0 R /XYZ 115.0 575.255 null] +>> +endobj +43 0 obj +<< +/S /GoTo +/D [146 0 R /XYZ 115.0 443.929 null] +>> +endobj +45 0 obj +<< +/S /GoTo +/D [146 0 R /XYZ 115.0 410.603 null] +>> +endobj +47 0 obj +<< +/S /GoTo +/D [146 0 R /XYZ 115.0 252.164 null] +>> +endobj +49 0 obj +<< +/S /GoTo +/D [150 0 R /XYZ 115.0 774.889 null] +>> +endobj +51 0 obj +<< +/S /GoTo +/D [152 0 R /XYZ 115.0 774.889 null] +>> +endobj +53 0 obj +<< +/S /GoTo +/D [154 0 R /XYZ 115.0 774.889 null] +>> +endobj +55 0 obj +<< +/S /GoTo +/D [156 0 R /XYZ 115.0 774.889 null] +>> +endobj +57 0 obj +<< +/S /GoTo +/D [158 0 R /XYZ 115.0 774.889 null] +>> +endobj +59 0 obj +<< +/S /GoTo +/D [160 0 R /XYZ 115.0 774.889 null] +>> +endobj +61 0 obj +<< +/S /GoTo +/D [162 0 R /XYZ 115.0 774.889 null] +>> +endobj +63 0 obj +<< +/S /GoTo +/D [164 0 R /XYZ 115.0 774.889 null] +>> +endobj +65 0 obj +<< +/S /GoTo +/D [166 0 R /XYZ 115.0 774.889 null] +>> +endobj +67 0 obj +<< +/S /GoTo +/D [168 0 R /XYZ 115.0 774.889 null] +>> +endobj +69 0 obj +<< +/S /GoTo +/D [170 0 R /XYZ 115.0 774.889 null] +>> +endobj +71 0 obj +<< +/S /GoTo +/D [172 0 R /XYZ 115.0 774.889 null] +>> +endobj +73 0 obj +<< +/S /GoTo +/D [174 0 R /XYZ 115.0 774.889 null] +>> +endobj +75 0 obj +<< +/S /GoTo +/D [176 0 R /XYZ 115.0 774.889 null] +>> +endobj +77 0 obj +<< +/S /GoTo +/D [178 0 R /XYZ 115.0 774.889 null] +>> +endobj +79 0 obj +<< +/S /GoTo +/D [180 0 R /XYZ 115.0 774.889 null] +>> +endobj +81 0 obj +<< +/S /GoTo +/D [182 0 R /XYZ 115.0 774.889 null] +>> +endobj +83 0 obj +<< +/S /GoTo +/D [184 0 R /XYZ 115.0 774.889 null] +>> +endobj +85 0 obj +<< +/S /GoTo +/D [186 0 R /XYZ 115.0 774.889 null] +>> +endobj +87 0 obj +<< +/S /GoTo +/D [188 0 R /XYZ 115.0 774.889 null] +>> +endobj +89 0 obj +<< +/S /GoTo +/D [190 0 R /XYZ 115.0 774.889 null] +>> +endobj +91 0 obj +<< +/S /GoTo +/D [192 0 R /XYZ 115.0 774.889 null] +>> +endobj +93 0 obj +<< +/S /GoTo +/D [194 0 R /XYZ 115.0 774.889 null] +>> +endobj +95 0 obj +<< +/S /GoTo +/D [196 0 R /XYZ 115.0 774.889 null] +>> +endobj +97 0 obj +<< +/S /GoTo +/D [198 0 R /XYZ 115.0 774.889 null] +>> +endobj +99 0 obj +<< +/S /GoTo +/D [200 0 R /XYZ 115.0 774.889 null] +>> +endobj +101 0 obj +<< +/S /GoTo +/D [202 0 R /XYZ 115.0 774.889 null] +>> +endobj +103 0 obj +<< +/S /GoTo +/D [204 0 R /XYZ 115.0 774.889 null] +>> +endobj +105 0 obj +<< +/S /GoTo +/D [208 0 R /XYZ 115.0 774.889 null] +>> +endobj +107 0 obj +<< +/S /GoTo +/D [212 0 R /XYZ 115.0 774.889 null] +>> +endobj +109 0 obj +<< +/S /GoTo +/D [214 0 R /XYZ 115.0 774.889 null] +>> +endobj +111 0 obj +<< +/S /GoTo +/D [216 0 R /XYZ 115.0 774.889 null] +>> +endobj +113 0 obj +<< +/S /GoTo +/D [218 0 R /XYZ 115.0 774.889 null] +>> +endobj +115 0 obj +<< +/S /GoTo +/D [220 0 R /XYZ 115.0 774.889 null] +>> +endobj +117 0 obj +<< +/S /GoTo +/D [222 0 R /XYZ 115.0 774.889 null] +>> +endobj +119 0 obj +<< +/S /GoTo +/D [224 0 R /XYZ 115.0 774.889 null] +>> +endobj +121 0 obj +<< +/S /GoTo +/D [226 0 R /XYZ 115.0 774.889 null] +>> +endobj +123 0 obj +<< +/S /GoTo +/D [228 0 R /XYZ 115.0 774.889 null] +>> +endobj +125 0 obj +<< +/S /GoTo +/D [230 0 R /XYZ 115.0 774.889 null] +>> +endobj +127 0 obj +<< +/S /GoTo +/D [234 0 R /XYZ 115.0 774.889 null] +>> +endobj +132 0 obj +<< +/S /GoTo +/D [236 0 R /XYZ 115.0 774.889 null] +>> +endobj +134 0 obj +<< +/S /GoTo +/D [236 0 R /XYZ 115.0 736.898 null] +>> +endobj +136 0 obj +<< +/S /GoTo +/D [236 0 R /XYZ 115.0 649.572 null] +>> +endobj +138 0 obj +<< +/S /GoTo +/D [246 0 R /XYZ 115.0 774.889 null] +>> +endobj +247 0 obj +<< + /First 249 0 R + /Last 314 0 R +>> endobj +248 0 obj +<< +/S /GoTo +/D [10 0 R /XYZ 115.0 774.889 null] +>> +endobj +250 0 obj +<< +/S /GoTo +/D [12 0 R /XYZ 115.0 764.889 null] +>> +endobj +270 0 obj +<< +/S /GoTo +/D [150 0 R /XYZ 115.0 728.236 null] +>> +endobj +xref +0 323 +0000000000 65535 f +0000085208 00000 n +0000085695 00000 n +0000086406 00000 n +0000000015 00000 n +0000000071 00000 n +0000000363 00000 n +0000000469 00000 n +0000001525 00000 n +0000001631 00000 n +0000001802 00000 n +0000001909 00000 n +0000004069 00000 n +0000004192 00000 n +0000004625 00000 n +0000086571 00000 n +0000004759 00000 n +0000086639 00000 n +0000004893 00000 n +0000086707 00000 n +0000005027 00000 n +0000086775 00000 n +0000005161 00000 n +0000086843 00000 n +0000005295 00000 n +0000086911 00000 n +0000005429 00000 n +0000086978 00000 n +0000005563 00000 n +0000087046 00000 n +0000005697 00000 n +0000087114 00000 n +0000005831 00000 n +0000087182 00000 n +0000005965 00000 n +0000087250 00000 n +0000006099 00000 n +0000087318 00000 n +0000006233 00000 n +0000087386 00000 n +0000006367 00000 n +0000087454 00000 n +0000006501 00000 n +0000087522 00000 n +0000006635 00000 n +0000087590 00000 n +0000006769 00000 n +0000087658 00000 n +0000006903 00000 n +0000087726 00000 n +0000007037 00000 n +0000087794 00000 n +0000007171 00000 n +0000087862 00000 n +0000007305 00000 n +0000087930 00000 n +0000007439 00000 n +0000087998 00000 n +0000007573 00000 n +0000088066 00000 n +0000007707 00000 n +0000088134 00000 n +0000007841 00000 n +0000088202 00000 n +0000007975 00000 n +0000088270 00000 n +0000008109 00000 n +0000088338 00000 n +0000008243 00000 n +0000088406 00000 n +0000008377 00000 n +0000088474 00000 n +0000008510 00000 n +0000088542 00000 n +0000008644 00000 n +0000088610 00000 n +0000008778 00000 n +0000088678 00000 n +0000008911 00000 n +0000088746 00000 n +0000009045 00000 n +0000088814 00000 n +0000009179 00000 n +0000088882 00000 n +0000009313 00000 n +0000088950 00000 n +0000009447 00000 n +0000089018 00000 n +0000009581 00000 n +0000089086 00000 n +0000009714 00000 n +0000089154 00000 n +0000009848 00000 n +0000089222 00000 n +0000009982 00000 n +0000089290 00000 n +0000010116 00000 n +0000089358 00000 n +0000010250 00000 n +0000089426 00000 n +0000010384 00000 n +0000089494 00000 n +0000010520 00000 n +0000089563 00000 n +0000010656 00000 n +0000089632 00000 n +0000010792 00000 n +0000089701 00000 n +0000010928 00000 n +0000089770 00000 n +0000011064 00000 n +0000089839 00000 n +0000011200 00000 n +0000089908 00000 n +0000011336 00000 n +0000089977 00000 n +0000011472 00000 n +0000090046 00000 n +0000011608 00000 n +0000090115 00000 n +0000011744 00000 n +0000090184 00000 n +0000011880 00000 n +0000090253 00000 n +0000012016 00000 n +0000090322 00000 n +0000012150 00000 n +0000090391 00000 n +0000012284 00000 n +0000012772 00000 n +0000012898 00000 n +0000012951 00000 n +0000090460 00000 n +0000013089 00000 n +0000090529 00000 n +0000013227 00000 n +0000090598 00000 n +0000013365 00000 n +0000090667 00000 n +0000013503 00000 n +0000014186 00000 n +0000014296 00000 n +0000016420 00000 n +0000016530 00000 n +0000017619 00000 n +0000017729 00000 n +0000020274 00000 n +0000020384 00000 n +0000020779 00000 n +0000020889 00000 n +0000021450 00000 n +0000021560 00000 n +0000022473 00000 n +0000022583 00000 n +0000023923 00000 n +0000024033 00000 n +0000025087 00000 n +0000025197 00000 n +0000026036 00000 n +0000026146 00000 n +0000027352 00000 n +0000027462 00000 n +0000027848 00000 n +0000027958 00000 n +0000029818 00000 n +0000029928 00000 n +0000031064 00000 n +0000031174 00000 n +0000032120 00000 n +0000032230 00000 n +0000033141 00000 n +0000033251 00000 n +0000034014 00000 n +0000034124 00000 n +0000035361 00000 n +0000035471 00000 n +0000036452 00000 n +0000036562 00000 n +0000036960 00000 n +0000037070 00000 n +0000038119 00000 n +0000038229 00000 n +0000038919 00000 n +0000039029 00000 n +0000040389 00000 n +0000040499 00000 n +0000041409 00000 n +0000041519 00000 n +0000042223 00000 n +0000042333 00000 n +0000043487 00000 n +0000043597 00000 n +0000044763 00000 n +0000044873 00000 n +0000045978 00000 n +0000046088 00000 n +0000046872 00000 n +0000046982 00000 n +0000047731 00000 n +0000047841 00000 n +0000048372 00000 n +0000048482 00000 n +0000050183 00000 n +0000050293 00000 n +0000051885 00000 n +0000051995 00000 n +0000052564 00000 n +0000052674 00000 n +0000054966 00000 n +0000055076 00000 n +0000055332 00000 n +0000055442 00000 n +0000056246 00000 n +0000056356 00000 n +0000057164 00000 n +0000057274 00000 n +0000058020 00000 n +0000058130 00000 n +0000059272 00000 n +0000059382 00000 n +0000060465 00000 n +0000060575 00000 n +0000061335 00000 n +0000061445 00000 n +0000062425 00000 n +0000062535 00000 n +0000062831 00000 n +0000062941 00000 n +0000064472 00000 n +0000064582 00000 n +0000066453 00000 n +0000066563 00000 n +0000066913 00000 n +0000067023 00000 n +0000068445 00000 n +0000068555 00000 n +0000069715 00000 n +0000069841 00000 n +0000069918 00000 n +0000070088 00000 n +0000070261 00000 n +0000070455 00000 n +0000070649 00000 n +0000070842 00000 n +0000071062 00000 n +0000071282 00000 n +0000071668 00000 n +0000090736 00000 n +0000090790 00000 n +0000071778 00000 n +0000090858 00000 n +0000071982 00000 n +0000072183 00000 n +0000072325 00000 n +0000072603 00000 n +0000072730 00000 n +0000072890 00000 n +0000073139 00000 n +0000073302 00000 n +0000073435 00000 n +0000073580 00000 n +0000073887 00000 n +0000074186 00000 n +0000074325 00000 n +0000074479 00000 n +0000074594 00000 n +0000074930 00000 n +0000075210 00000 n +0000075355 00000 n +0000075636 00000 n +0000090926 00000 n +0000075850 00000 n +0000075984 00000 n +0000076116 00000 n +0000076347 00000 n +0000076503 00000 n +0000076697 00000 n +0000076846 00000 n +0000077077 00000 n +0000077209 00000 n +0000077368 00000 n +0000077550 00000 n +0000077744 00000 n +0000077944 00000 n +0000078109 00000 n +0000078247 00000 n +0000078432 00000 n +0000078653 00000 n +0000078865 00000 n +0000079077 00000 n +0000079294 00000 n +0000079483 00000 n +0000079660 00000 n +0000079884 00000 n +0000080096 00000 n +0000080296 00000 n +0000080478 00000 n +0000080706 00000 n +0000080907 00000 n +0000081081 00000 n +0000081266 00000 n +0000081470 00000 n +0000081677 00000 n +0000081849 00000 n +0000082021 00000 n +0000082281 00000 n +0000082529 00000 n +0000082751 00000 n +0000083017 00000 n +0000083174 00000 n +0000083393 00000 n +0000083597 00000 n +0000083883 00000 n +0000084046 00000 n +0000084174 00000 n +0000084308 00000 n +0000084422 00000 n +0000084533 00000 n +0000084649 00000 n +0000084758 00000 n +0000084870 00000 n +0000084991 00000 n +0000085098 00000 n +trailer +<< +/Size 323 +/Root 2 0 R +/Info 4 0 R +>> +startxref +90995 +%%EOF Added: branches/trunk-reorg/thirdparty/uffi/doc/uffi.xml ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi/doc/uffi.xml Mon Feb 11 09:06:27 2008 @@ -0,0 +1,24 @@ + + + +%myents; +%xinclude; +]> + + + + + + + + + + + + + + + + Added: branches/trunk-reorg/thirdparty/uffi/doc/xinclude.mod ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi/doc/xinclude.mod Mon Feb 11 09:06:27 2008 @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + Added: branches/trunk-reorg/thirdparty/uffi/examples/Makefile ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi/examples/Makefile Mon Feb 11 09:06:27 2008 @@ -0,0 +1,45 @@ +# FILE IDENTIFICATION +# +# Name: Makefile +# Purpose: Makefile for UFFI examples +# Programer: Kevin M. Rosenberg +# Date Started: Mar 2002 +# +# CVS Id: $Id$ +# +# This file, part of UFFI, is Copyright (c) 2002-2005 by Kevin M. Rosenberg +# + +SUBDIRS:= + +include ../Makefile.common + +.PHONY: distclean +distclean: clean + + +base=c-test-fns +source=$(base).c +object=$(base).o +shared_lib=$(base).so + +.PHONY: all +all: $(shared_lib) + +linux: $(source) Makefile + gcc -fPIC -DPIC -c $(source) -o $(object) + gcc -shared $(object) -o $(shared_lib) + rm $(object) + +mac: + cc -dynamic -c $(source) -o $(object) + ld -bundle /usr/lib/bundle1.o -flat_namespace -undefined suppress -o $(base).dylib $(object) + ld -bundle /usr/lib/bundle1.o -flat_namespace -undefined suppress /usr/lib/libz.dylib -o z.dylib + +solaris: + cc -KPIC -c $(source) -o $(object) + cc -G $(object) -o $(shared_lib) + +aix-acl: + gcc -c -D_BSD -D_NO_PROTO -D_NONSTD_TYPES -D_MBI=void $(source) + make_shared -o $(shared_lib) $(object) Added: branches/trunk-reorg/thirdparty/uffi/examples/Makefile.msvc ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi/examples/Makefile.msvc Mon Feb 11 09:06:27 2008 @@ -0,0 +1,27 @@ +# FILE IDENTIFICATION +# +# Name: Makefile.msvc +# Purpose: Makefile for the CLSQL UFFI helper package (MSVC) +# Programer: Kevin M. Rosenberg +# Date Started: Mar 2002 +# +# CVS Id: $Id: Makefile.msvc,v 1.1 2002/03/23 10:26:03 kevin Exp $ +# +# This file, part of CLSQL, is Copyright (c) 2002-2005 by Kevin M. Rosenberg + +BASE=c-test-fns + +# Nothing to configure beyond here + +SRC=$(BASE).c +OBJ=$(BASE).obj +DLL=$(BASE).dll + +$(DLL): $(SRC) + cl /MD /LD -D_MT /DWIN32=1 $(SRC) + del $(OBJ) $(BASE).exp + +clean: + del /q $(DLL) + + Added: branches/trunk-reorg/thirdparty/uffi/examples/acl-compat-tester.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi/examples/acl-compat-tester.lisp Mon Feb 11 09:06:27 2008 @@ -0,0 +1,600 @@ +;; tester.cl +;; A test harness for Allegro CL. +;; +;; copyright (c) 1985-1986 Franz Inc, Alameda, CA +;; copyright (c) 1986-2001 Franz Inc, Berkeley, CA - All rights reserved. +;; +;; This code is free software; you can redistribute it and/or +;; modify it under the terms of the version 2.1 of +;; the GNU Lesser General Public License as published by +;; the Free Software Foundation, as clarified by the Franz +;; preamble to the LGPL found in +;; http://opensource.franz.com/preamble.html. +;; +;; This code is distributed in the hope that it will be useful, +;; but without any warranty; without even the implied warranty of +;; merchantability or fitness for a particular purpose. See the GNU +;; Lesser General Public License for more details. +;; +;; Version 2.1 of the GNU Lesser General Public License can be +;; found at http://opensource.franz.com/license.html. +;; If it is not present, you can access it from +;; http://www.gnu.org/copyleft/lesser.txt (until superseded by a newer +;; version) or write to the Free Software Foundation, Inc., 59 Temple +;; Place, Suite 330, Boston, MA 02111-1307 USA +;; +;;;; from the original ACL 6.1 sources: +;; $Id$ + + +(defpackage :util.test + (:use :common-lisp) + (:shadow #:test) + (:export +;;;; Control variables: + #:*break-on-test-failures* + #:*error-protect-tests* + #:*test-errors* + #:*test-successes* + #:*test-unexpected-failures* + +;;;; The test macros: + #:test + #:test-error + #:test-no-error + #:test-warning + #:test-no-warning + + #:with-tests + )) + +(in-package :util.test) + +#+cmu +(unless (find-class 'break nil) + (define-condition break (simple-condition) ())) + +(define-condition simple-break (error simple-condition) ()) + +;; the if* macro used in Allegro: +;; +;; This is in the public domain... please feel free to put this definition +;; in your code or distribute it with your version of lisp. + +(eval-when (:compile-toplevel :load-toplevel :execute) + (defvar if*-keyword-list '("then" "thenret" "else" "elseif"))) + +(defmacro if* (&rest args) + (do ((xx (reverse args) (cdr xx)) + (state :init) + (elseseen nil) + (totalcol nil) + (lookat nil nil) + (col nil)) + ((null xx) + (cond ((eq state :compl) + `(cond , at totalcol)) + (t (error "if*: illegal form ~s" args)))) + (cond ((and (symbolp (car xx)) + (member (symbol-name (car xx)) + if*-keyword-list + :test #'string-equal)) + (setq lookat (symbol-name (car xx))))) + + (cond ((eq state :init) + (cond (lookat (cond ((string-equal lookat "thenret") + (setq col nil + state :then)) + (t (error + "if*: bad keyword ~a" lookat)))) + (t (setq state :col + col nil) + (push (car xx) col)))) + ((eq state :col) + (cond (lookat + (cond ((string-equal lookat "else") + (cond (elseseen + (error + "if*: multiples elses"))) + (setq elseseen t) + (setq state :init) + (push `(t , at col) totalcol)) + ((string-equal lookat "then") + (setq state :then)) + (t (error "if*: bad keyword ~s" + lookat)))) + (t (push (car xx) col)))) + ((eq state :then) + (cond (lookat + (error + "if*: keyword ~s at the wrong place " (car xx))) + (t (setq state :compl) + (push `(,(car xx) , at col) totalcol)))) + ((eq state :compl) + (cond ((not (string-equal lookat "elseif")) + (error "if*: missing elseif clause "))) + (setq state :init))))) + + + + +(defvar *break-on-test-failures* nil + "When a test failure occurs, common-lisp:break is called, allowing +interactive debugging of the failure.") + +(defvar *test-errors* 0 + "The value is the number of test errors which have occurred.") +(defvar *test-successes* 0 + "The value is the number of test successes which have occurred.") +(defvar *test-unexpected-failures* 0 + "The value is the number of unexpected test failures which have occurred.") + +(defvar *error-protect-tests* nil + "Protect each test from errors. If an error occurs, then that will be +taken as a test failure unless test-error is being used.") + +(defmacro test-values-errorset (form &optional announce catch-breaks) + ;; internal macro + (let ((g-announce (gensym)) + (g-catch-breaks (gensym))) + `(let* ((,g-announce ,announce) + (,g-catch-breaks ,catch-breaks)) + (handler-case (cons t (multiple-value-list ,form)) + (condition (condition) + (if* (and (null ,g-catch-breaks) + (typep condition 'simple-break)) + then (break condition) + elseif ,g-announce + then (format *error-output* "~&Condition type: ~a~%" + (class-of condition)) + (format *error-output* "~&Message: ~a~%" condition)) + condition))))) + +(defmacro test-values (form &optional announce catch-breaks) + ;; internal macro + (if* *error-protect-tests* + then `(test-values-errorset ,form ,announce ,catch-breaks) + else `(cons t (multiple-value-list ,form)))) + +(defmacro test (expected-value test-form + &key (test #'eql test-given) + (multiple-values nil multiple-values-given) + (fail-info nil fail-info-given) + (known-failure nil known-failure-given) + +;;;;;;;;;; internal, undocumented keywords: +;;;; Note about these keywords: if they were documented, we'd have a +;;;; problem, since they break the left-to-right order of evaluation. +;;;; Specifically, errorset breaks it, and I don't see any way around +;;;; that. `errorset' is used by the old test.cl module (eg, +;;;; test-equal-errorset). + errorset + reported-form + (wanted-message nil wanted-message-given) + (got-message nil got-message-given)) + "Perform a single test. `expected-value' is the reference value for the +test. `test-form' is a form that will produce the value to be compared to +the expected-value. If the values are not the same, then an error is +logged, otherwise a success is logged. + +Normally the comparison of values is done with `eql'. The `test' keyword +argument can be used to specify other comparison functions, such as eq, +equal,equalp, string=, string-equal, etc. + +Normally, only the first return value from the test-form is considered, +however if `multiple-values' is t, then all values returned from test-form +are considered. + +`fail-info' allows more information to be printed with a test failure. + +`known-failure' marks the test as a known failure. This allows for +programs that do regression analysis on the output from a test run to +discriminate on new versus known failures." + `(test-check + :expected-result ,expected-value + :test-results + (,(if errorset 'test-values-errorset 'test-values) ,test-form t) + ,@(when test-given `(:predicate ,test)) + ,@(when multiple-values-given `(:multiple-values ,multiple-values)) + ,@(when fail-info-given `(:fail-info ,fail-info)) + ,@(when known-failure-given `(:known-failure ,known-failure)) + :test-form ',(if reported-form reported-form test-form) + ,@(when wanted-message-given `(:wanted-message ,wanted-message)) + ,@(when got-message-given `(:got-message ,got-message)))) + +(defmethod conditionp ((thing condition)) t) +(defmethod conditionp ((thing t)) nil) + +(defmacro test-error (form &key announce + catch-breaks + (fail-info nil fail-info-given) + (known-failure nil known-failure-given) + (condition-type ''simple-error) + (include-subtypes nil include-subtypes-given) + (format-control nil format-control-given) + (format-arguments nil format-arguments-given)) + "Test that `form' signals an error. The order of evaluation of the +arguments is keywords first, then test form. + +If `announce' is non-nil, then cause the error message to be printed. + +The `catch-breaks' is non-nil then consider a call to common-lisp:break an +`error'. + +`fail-info' allows more information to be printed with a test failure. + +`known-failure' marks the test as a known failure. This allows for +programs that do regression analysis on the output from a test run to +discriminate on new versus known failures. + +If `condition-type' is non-nil, it should be a symbol naming a condition +type, which is used to check against the signalled condition type. The +test will fail if they do not match. + +`include-subtypes', used with `condition-type', can be used to match a +condition to an entire subclass of the condition type hierarchy. + +`format-control' and `format-arguments' can be used to check the error +message itself." + (let ((g-announce (gensym)) + (g-catch-breaks (gensym)) + (g-fail-info (gensym)) + (g-known-failure (gensym)) + (g-condition-type (gensym)) + (g-include-subtypes (gensym)) + (g-format-control (gensym)) + (g-format-arguments (gensym)) + (g-c (gensym))) + `(let* ((,g-announce ,announce) + (,g-catch-breaks ,catch-breaks) + ,@(when fail-info-given `((,g-fail-info ,fail-info))) + ,@(when known-failure-given `((,g-known-failure ,known-failure))) + (,g-condition-type ,condition-type) + ,@(when include-subtypes-given + `((,g-include-subtypes ,include-subtypes))) + ,@(when format-control-given + `((,g-format-control ,format-control))) + ,@(when format-arguments-given + `((,g-format-arguments ,format-arguments))) + (,g-c (test-values-errorset ,form ,g-announce ,g-catch-breaks))) + (test-check + :predicate #'eq + :expected-result t + :test-results + (test-values (and (conditionp ,g-c) + ,@(if* include-subtypes-given + then `((if* ,g-include-subtypes + then (typep ,g-c ,g-condition-type) + else (eq (class-of ,g-c) + (find-class + ,g-condition-type)))) + else `((eq (class-of ,g-c) + (find-class ,g-condition-type)))) + ,@(when format-control-given + `((or + (null ,g-format-control) + (string= + (concatenate 'simple-string + "~1@<" ,g-format-control "~:@>") + (simple-condition-format-control ,g-c))))) + ,@(when format-arguments-given + `((or + (null ,g-format-arguments) + (equal + ,g-format-arguments + (simple-condition-format-arguments ,g-c)))))) + t) + :test-form ',form + ,@(when fail-info-given `(:fail-info ,g-fail-info)) + ,@(when known-failure-given `(:known-failure ,g-known-failure)) + :condition-type ,g-condition-type + :condition ,g-c + ,@(when include-subtypes-given + `(:include-subtypes ,g-include-subtypes)) + ,@(when format-control-given + `(:format-control ,g-format-control)) + ,@(when format-arguments-given + `(:format-arguments ,g-format-arguments)))))) + +(defmacro test-no-error (form &key announce + catch-breaks + (fail-info nil fail-info-given) + (known-failure nil known-failure-given)) + "Test that `form' does not signal an error. The order of evaluation of +the arguments is keywords first, then test form. + +If `announce' is non-nil, then cause the error message to be printed. + +The `catch-breaks' is non-nil then consider a call to common-lisp:break an +`error'. + +`fail-info' allows more information to be printed with a test failure. + +`known-failure' marks the test as a known failure. This allows for +programs that do regression analysis on the output from a test run to +discriminate on new versus known failures." + (let ((g-announce (gensym)) + (g-catch-breaks (gensym)) + (g-fail-info (gensym)) + (g-known-failure (gensym)) + (g-c (gensym))) + `(let* ((,g-announce ,announce) + (,g-catch-breaks ,catch-breaks) + ,@(when fail-info-given `((,g-fail-info ,fail-info))) + ,@(when known-failure-given `((,g-known-failure ,known-failure))) + (,g-c (test-values-errorset ,form ,g-announce ,g-catch-breaks))) + (test-check + :predicate #'eq + :expected-result t + :test-results (test-values (not (conditionp ,g-c))) + :test-form ',form + :condition ,g-c + ,@(when fail-info-given `(:fail-info ,g-fail-info)) + ,@(when known-failure-given `(:known-failure ,g-known-failure)))))) + +(defvar *warn-cookie* (cons nil nil)) + +(defmacro test-warning (form &key fail-info known-failure) + "Test that `form' signals a warning. The order of evaluation of +the arguments is keywords first, then test form. + +`fail-info' allows more information to be printed with a test failure. + +`known-failure' marks the test as a known failure. This allows for +programs that do regression analysis on the output from a test run to +discriminate on new versus known failures." + (let ((g-fail-info (gensym)) + (g-known-failure (gensym)) + (g-value (gensym))) + `(let* ((,g-fail-info ,fail-info) + (,g-known-failure ,known-failure) + (,g-value (test-values-errorset ,form nil t))) + (test + *warn-cookie* + (if* (or (typep ,g-value 'simple-warning) (typep ,g-value 'warning)) + then *warn-cookie* + else ;; test produced no warning + nil) + :test #'eq + :reported-form ,form ;; quoted by test macro + :wanted-message "a warning" + :got-message "no warning" + :fail-info ,g-fail-info + :known-failure ,g-known-failure)))) + +(defmacro test-no-warning (form &key fail-info known-failure) + "Test that `form' does not signal a warning. The order of evaluation of +the arguments is keywords first, then test form. + +`fail-info' allows more information to be printed with a test failure. + +`known-failure' marks the test as a known failure. This allows for +programs that do regression analysis on the output from a test run to +discriminate on new versus known failures." + (let ((g-fail-info (gensym)) + (g-known-failure (gensym)) + (g-value (gensym))) + `(let* ((,g-fail-info ,fail-info) + (,g-known-failure ,known-failure) + (,g-value (test-values-errorset ,form nil t))) + (test + *warn-cookie* + (if* (or (typep ,g-value 'simple-warning) (typep ,g-value 'warning)) + then nil ;; test produced warning + else *warn-cookie*) + :test #'eq + :reported-form ',form + :wanted-message "no warning" + :got-message "a warning" + :fail-info ,g-fail-info + :known-failure ,g-known-failure)))) + +(defvar *announce-test* nil) ;; if true announce each test that was done + +(defmacro errorset (form &optional announce catch-breaks) + ;; Evaluate FORM, and if there are no errors and FORM returns + ;; values v1,v2,...,vn, then return values t,v1,v2,...,vn. If an + ;; error occurs while evaluating FORM, then return nil immediately. + ;; If ANNOUNCE is t, then the error message will be printed out. + (if catch-breaks + `(handler-case (values-list (cons t (multiple-value-list ,form))) + (error (condition) + (declare (ignorable condition)) + ,@(if announce `((format *error-output* "~&Error: ~a~%" condition))) + nil) + (simple-break (condition) + (declare (ignorable condition)) + ,@(if announce `((format *error-output* "~&Warning: ~a~%" condition)) +) + nil)) + `(handler-case (values-list (cons t (multiple-value-list ,form))) + (error (condition) + (declare (ignorable condition)) + ,@(if announce `((format *error-output* "~&Error: ~a~%" condition))) + nil)))) + +(defun test-check (&key (predicate #'eql) + expected-result test-results test-form + multiple-values fail-info known-failure + wanted-message got-message condition-type condition + include-subtypes format-control format-arguments + &aux fail predicate-failed got wanted) + ;; for debugging large/complex test sets: + (when *announce-test* + (format t "Just did test ~s~%" test-form) + (force-output)) + + ;; this is an internal function + (flet ((check (expected-result result) + (let* ((results + (multiple-value-list + (errorset (funcall predicate expected-result result) t))) + (failed (null (car results)))) + (if* failed + then (setq predicate-failed t) + nil + else (cadr results))))) + (when (conditionp test-results) + (setq condition test-results) + (setq test-results nil)) + (when (null (car test-results)) + (setq fail t)) + (if* (and (not fail) (not multiple-values)) + then ;; should be a single result + ;; expected-result is the single result wanted + (when (not (and (cdr test-results) + (check expected-result (cadr test-results)))) + (setq fail t)) + (when (and (not fail) (cddr test-results)) + (setq fail 'single-got-multiple)) + else ;; multiple results wanted + ;; expected-result is a list of results, each of which + ;; should be checked against the corresponding test-results + ;; using the predicate + (do ((got (cdr test-results) (cdr got)) + (want expected-result (cdr want))) + ((or (null got) (null want)) + (when (not (and (null want) (null got))) + (setq fail t))) + (when (not (check (car got) (car want))) + (return (setq fail t))))) + (if* fail + then (when (not known-failure) + (format *error-output* + "~& * * * UNEXPECTED TEST FAILURE * * *~%") + (incf *test-unexpected-failures*)) + (format *error-output* "~&Test failed: ~@[known failure: ~*~]~s~%" + known-failure test-form) + (if* (eq 'single-got-multiple fail) + then (format + *error-output* + "~ +Reason: additional value were returned from test form.~%") + elseif predicate-failed + then (format *error-output* "Reason: predicate error.~%") + elseif (null (car test-results)) + then (format *error-output* "~ +Reason: an error~@[ (of type `~s')~] was detected.~%" + (when condition (class-of condition))) + elseif condition + then (if* (not (conditionp condition)) + then (format *error-output* "~ +Reason: expected but did not detect an error of type `~s'.~%" + condition-type) + elseif (null condition-type) + then (format *error-output* "~ +Reason: detected an unexpected error of type `~s': + ~a.~%" + (class-of condition) + condition) + elseif (not (if* include-subtypes + then (typep condition condition-type) + else (eq (class-of condition) + (find-class condition-type)))) + then (format *error-output* "~ +Reason: detected an incorrect condition type.~%") + (format *error-output* + " wanted: ~s~%" condition-type) + (format *error-output* + " got: ~s~%" (class-of condition)) + elseif (and format-control + (not (string= + (setq got + (concatenate 'simple-string + "~1@<" format-control "~:@>")) + (setq wanted + (simple-condition-format-control + condition))))) + then ;; format control doesn't match + (format *error-output* "~ +Reason: the format-control was incorrect.~%") + (format *error-output* " wanted: ~s~%" wanted) + (format *error-output* " got: ~s~%" got) + elseif (and format-arguments + (not (equal + (setq got format-arguments) + (setq wanted + (simple-condition-format-arguments + condition))))) + then (format *error-output* "~ +Reason: the format-arguments were incorrect.~%") + (format *error-output* " wanted: ~s~%" wanted) + (format *error-output* " got: ~s~%" got) + else ;; what else???? + (error "internal-error")) + else (let ((*print-length* 50) + (*print-level* 10)) + (if* wanted-message + then (format *error-output* + " wanted: ~a~%" wanted-message) + else (if* (not multiple-values) + then (format *error-output* + " wanted: ~s~%" + expected-result) + else (format + *error-output* + " wanted values: ~{~s~^, ~}~%" + expected-result))) + (if* got-message + then (format *error-output* + " got: ~a~%" got-message) + else (if* (not multiple-values) + then (format *error-output* " got: ~s~%" + (second test-results)) + else (format + *error-output* + " got values: ~{~s~^, ~}~%" + (cdr test-results)))))) + (when fail-info + (format *error-output* "Additional info: ~a~%" fail-info)) + (incf *test-errors*) + (when *break-on-test-failures* + (break "~a is non-nil." '*break-on-test-failures*)) + else (when known-failure + (format *error-output* + "~&Expected test failure for ~s did not occur.~%" + test-form) + (when fail-info + (format *error-output* "Additional info: ~a~%" fail-info)) + (setq fail t)) + (incf *test-successes*)) + (not fail))) + +(defmacro with-tests ((&key (name "unnamed")) &body body) + (let ((g-name (gensym))) + `(flet ((doit () , at body)) + (let ((,g-name ,name) + (*test-errors* 0) + (*test-successes* 0) + (*test-unexpected-failures* 0)) + (format *error-output* "Begin ~a test~%" ,g-name) + (if* *break-on-test-failures* + then (doit) + else (handler-case (doit) + (error (c) + (format + *error-output* + "~ +~&Test ~a aborted by signalling an uncaught error:~%~a~%" + ,g-name c)))) + #+allegro + (let ((state (sys:gsgc-switch :print))) + (setf (sys:gsgc-switch :print) nil) + (format t "~&**********************************~%" ,g-name) + (format t "End ~a test~%" ,g-name) + (format t "Errors detected in this test: ~s " *test-errors*) + (unless (zerop *test-unexpected-failures*) + (format t "UNEXPECTED: ~s" *test-unexpected-failures*)) + (format t "~%Successes this test:~s~%" *test-successes*) + (setf (sys:gsgc-switch :print) state)) + #-allegro + (progn + (format t "~&**********************************~%" ,g-name) + (format t "End ~a test~%" ,g-name) + (format t "Errors detected in this test: ~s " *test-errors*) + (unless (zerop *test-unexpected-failures*) + (format t "UNEXPECTED: ~s" *test-unexpected-failures*)) + (format t "~%Successes this test:~s~%" *test-successes*)) + )))) + +(provide :tester #+module-versions 1.1) Added: branches/trunk-reorg/thirdparty/uffi/examples/arrays.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi/examples/arrays.lisp Mon Feb 11 09:06:27 2008 @@ -0,0 +1,63 @@ +;;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Base: 10 -*- +;;;; ************************************************************************* +;;;; FILE IDENTIFICATION +;;;; +;;;; Name: arrays.cl +;;;; Purpose: UFFI Example file to test arrays +;;;; Programmer: Kevin M. Rosenberg +;;;; Date Started: Mar 2002 +;;;; +;;;; $Id$ +;;;; +;;;; This file, part of UFFI, is Copyright (c) 2002-2005 by Kevin M. Rosenberg +;;;; +;;;; ************************************************************************* + +(in-package :cl-user) + +(uffi:def-constant +column-length+ 10) +(uffi:def-constant +row-length+ 10) + +(uffi:def-foreign-type long-ptr (* :long)) + +(defun test-array-1d () + "Tests vector" + (let ((a (uffi:allocate-foreign-object :long +column-length+))) + (dotimes (i +column-length+) + (setf (uffi:deref-array a '(:array :long) i) (* i i))) + (dotimes (i +column-length+) + (format t "~&~D => ~D" i (uffi:deref-array a '(:array :long) i))) + (uffi:free-foreign-object a)) + (values)) + +(defun test-array-2d () + "Tests 2d array" + (let ((a (uffi:allocate-foreign-object 'long-ptr +row-length+))) + (dotimes (r +row-length+) + (declare (fixnum r)) + (setf (uffi:deref-array a '(:array (* :long)) r) + (uffi:allocate-foreign-object :long +column-length+)) + (let ((col (uffi:deref-array a '(:array (* :long)) r))) + (dotimes (c +column-length+) + (declare (fixnum c)) + (setf (uffi:deref-array col '(:array :long) c) (+ (* r +column-length+) c))))) + + (dotimes (r +row-length+) + (declare (fixnum r)) + (format t "~&Row ~D: " r) + (let ((col (uffi:deref-array a '(:array (* :long)) r))) + (dotimes (c +column-length+) + (declare (fixnum c)) + (let ((result (uffi:deref-array col '(:array :long) c))) + (format t "~d " result))))) + + (uffi:free-foreign-object a)) + (values)) + +#+examples-uffi +(test-array-1d) + +#+examples-uffi +(test-array-2d) + + Added: branches/trunk-reorg/thirdparty/uffi/examples/atoifl.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi/examples/atoifl.lisp Mon Feb 11 09:06:27 2008 @@ -0,0 +1,56 @@ +;;;; -*- Mode: Lisp; Syntax: ANSI-Common-Lisp; Base: 10 -*- +;;;; ************************************************************************* +;;;; FILE IDENTIFICATION +;;;; +;;;; Name: atoifl.cl +;;;; Purpose: UFFI Example file to atoi/atof/atol +;;;; Programmer: Kevin M. Rosenberg +;;;; Date Started: Mar 2002 +;;;; +;;;; $Id$ +;;;; +;;;; This file, part of UFFI, is Copyright (c) 2002-2005 by Kevin M. Rosenberg +;;;; +;;;; ************************************************************************* + +(in-package :cl-user) + +(uffi:def-function ("atoi" c-atoi) + ((str :cstring)) + :returning :int) + +(uffi:def-function ("atol" c-atol) + ((str :cstring)) + :returning :long) + +(uffi:def-function ("atof" c-atof) + ((str :cstring)) + :returning :double) + +(defun atoi (str) + "Returns a int from a string." + (uffi:with-cstring (str-cstring str) + (c-atoi str-cstring))) + +(defun atof (str) + "Returns a double float from a string." + (uffi:with-cstring (str-cstring str) + (c-atof str-cstring))) + +#+examples-uffi +(progn + (flet ((print-results (str) + (format t "~&(atoi ~S) => ~S" str (atoi str)))) + (print-results "55"))) + + +#+test-uffi +(progn + (util.test:test (atoi "123") 123 :test #'eql + :fail-info "Error with atoi") + (util.test:test (atoi "") 0 :test #'eql + :fail-info "Error with atoi") + (util.test:test (atof "2.23") 2.23d0 :test #'eql + :fail-info "Error with atof") + ) + Added: branches/trunk-reorg/thirdparty/uffi/examples/c-test-fns.c ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi/examples/c-test-fns.c Mon Feb 11 09:06:27 2008 @@ -0,0 +1,91 @@ +/*************************************************************************** + * FILE IDENTIFICATION + * + * Name: c-test-fns.c + * Purpose: Test functions in C for UFFI library + * Programer: Kevin M. Rosenberg + * Date Started: Mar 2002 + * + * CVS Id: $Id$ + * + * This file, part of UFFI, is Copyright (c) 2002-2005 by Kevin M. Rosenberg + * + * These variables are correct for GCC + * you'll need to modify these for other compilers + ***************************************************************************/ + +#ifdef WIN32 +#include + +BOOL WINAPI DllEntryPoint(HINSTANCE hinstdll, + DWORD fdwReason, + LPVOID lpvReserved) +{ + return 1; +} + +#define DLLEXPORT __declspec(dllexport) + +#else +#define DLLEXPORT +#endif + +#include +#include +#include + + +/* Test of constant input string */ +DLLEXPORT +int +cs_count_upper (char* psz) +{ + int count = 0; + + if (psz) { + while (*psz) { + if (isupper (*psz)) + ++count; + ++psz; + } + return count; + } else + return -1; +} + +/* Test of input and output of a string */ +DLLEXPORT +void +cs_to_upper (char* psz) +{ + if (psz) { + while (*psz) { + *psz = toupper (*psz); + ++psz; + } + } +} + +/* Test of an output only string */ +DLLEXPORT +void +cs_make_random (int size, char* buffer) +{ + int i; + for (i = 0; i < size; i++) + buffer[i] = 'A' + (rand() % 26); +} + + +/* Test of input/output vector */ +DLLEXPORT +void +half_double_vector (int size, double* vec) +{ + int i; + for (i = 0; i < size; i++) + vec[i] /= 2.; +} + + + Added: branches/trunk-reorg/thirdparty/uffi/examples/c-test-fns.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi/examples/c-test-fns.lisp Mon Feb 11 09:06:27 2008 @@ -0,0 +1,118 @@ +;;;; -*- Mode: Lisp; Syntax: ANSI-Common-Lisp; Base: 10 -*- +;;;; ************************************************************************* +;;;; FILE IDENTIFICATION +;;;; +;;;; Name: c-test-fns.cl +;;;; Purpose: UFFI Example file for zlib compression +;;;; Programmer: Kevin M. Rosenberg +;;;; Date Started: Mar 2002 +;;;; +;;;; $Id$ +;;;; +;;;; This file, part of UFFI, is Copyright (c) 2002-2005 by Kevin M. Rosenberg +;;;; +;;;; ************************************************************************* + +(in-package :cl-user) + +(unless (uffi:load-foreign-library + (uffi:find-foreign-library "c-test-fns" + (list *load-truename* "/home/kevin/debian/src/uffi/examples/")) + :supporting-libraries '("c")) + (warn "Unable to load c-test-fns library")) + +(uffi:def-function ("cs_to_upper" cs-to-upper) + ((input (* :unsigned-char))) + :returning :void + ) + +(defun string-to-upper (str) + (uffi:with-foreign-string (str-foreign str) + (cs-to-upper str-foreign) + (uffi:convert-from-foreign-string str-foreign))) + +(uffi:def-function ("cs_count_upper" cs-count-upper) + ((input :cstring)) + :returning :int + ) + +(defun string-count-upper (str) + (uffi:with-cstring (str-cstring str) + (cs-count-upper str-cstring))) + +(uffi:def-function ("half_double_vector" half-double-vector) + ((size :int) + (vec (* :double))) + :returning :void) + +(uffi:def-constant +double-vec-length+ 10) +(defun test-half-double-vector () + (let ((vec (uffi:allocate-foreign-object :double +double-vec-length+)) + results) + (dotimes (i +double-vec-length+) + (setf (uffi:deref-array vec '(:array :double) i) + (coerce i 'double-float))) + (half-double-vector +double-vec-length+ vec) + (dotimes (i +double-vec-length+) + (push (uffi:deref-array vec '(:array :double) i) results)) + (uffi:free-foreign-object vec) + (nreverse results))) + +(defun t2 () + (let ((vec (make-array +double-vec-length+ :element-type 'double-float))) + (dotimes (i +double-vec-length+) + (setf (aref vec i) (coerce i 'double-float))) + (half-double-vector +double-vec-length+ vec) + vec)) + +#+(or cmu scl) +(defun t3 () + (let ((vec (make-array +double-vec-length+ :element-type 'double-float))) + (dotimes (i +double-vec-length+) + (setf (aref vec i) (coerce i 'double-float))) + (system:without-gcing + (half-double-vector +double-vec-length+ (system:vector-sap vec))) + vec)) + +#+examples-uffi +(format t "~&(string-to-upper \"this is a test\") => ~A" + (string-to-upper "this is a test")) + +#+examples-uffi +(format t "~&(string-to-upper nil) => ~A" + (string-to-upper nil)) + +#+examples-uffi +(format t "~&(string-count-upper \"This is a Test\") => ~A" + (string-count-upper "This is a Test")) + +#+examples-uffi +(format t "~&(string-count-upper nil) => ~A" + (string-count-upper nil)) + +#+examples-uffi +(format t "~&Half vector: ~S" (test-half-double-vector)) + + + +#+test-uffi +(progn + (util.test:test (string= (string-to-upper "this is a test") "THIS IS A TEST") + t + :test #'eql + :fail-info "Error with string-to-upper") + (util.test:test (string-to-upper nil) nil + :fail-info "string-to-upper with nil failed") + (util.test:test (string-count-upper "This is a Test") + 2 + :test #'eql + :fail-info "Error with string-count-upper") + (util.test:test (string-count-upper nil) -1 + :test #'eql + :fail-info "string-count-upper with nil failed") + + (util.test:test (test-half-double-vector) + '(0.0d0 0.5d0 1.0d0 1.5d0 2.0d0 2.5d0 3.0d0 3.5d0 4.0d0 4.5d0) + :test #'equal + :fail-info "Error comparing half-double-vector") + ) Added: branches/trunk-reorg/thirdparty/uffi/examples/compress.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi/examples/compress.lisp Mon Feb 11 09:06:27 2008 @@ -0,0 +1,116 @@ +;;;; -*- Mode: Lisp; Syntax: ANSI-Common-Lisp; Base: 10 -*- +;;;; ************************************************************************* +;;;; FILE IDENTIFICATION +;;;; +;;;; Name: compress.cl +;;;; Purpose: UFFI Example file for zlib compression +;;;; Programmer: Kevin M. Rosenberg +;;;; Date Started: Feb 2002 +;;;; +;;;; $Id$ +;;;; +;;;; This file, part of UFFI, is Copyright (c) 2002-2005 by Kevin M. Rosenberg +;;;; +;;;; ************************************************************************* + +(in-package :cl-user) + +(eval-when (:load-toplevel :execute) + (unless (uffi:load-foreign-library + #-(or macosx darwin) + (uffi:find-foreign-library + "libz" + '("/usr/local/lib/" "/usr/lib/" "/zlib/") + :types '("so" "a")) + #+(or macosx darwin) + (uffi:find-foreign-library "z" + `(,(pathname-directory *load-pathname*))) + :module "zlib" + :supporting-libraries '("c")) + (warn "Unable to load zlib"))) + +(uffi:def-function ("compress" c-compress) + ((dest (* :unsigned-char)) + (destlen (* :long)) + (source :cstring) + (source-len :long)) + :returning :int + :module "zlib") + +(defun compress (source) + "Returns two values: array of bytes containing the compressed data + and the numbe of compressed bytes" + (let* ((sourcelen (length source)) + (destsize (+ 12 (ceiling (* sourcelen 1.01)))) + (dest (uffi:allocate-foreign-string destsize :unsigned t)) + (destlen (uffi:allocate-foreign-object :long))) + (setf (uffi:deref-pointer destlen :long) destsize) + (uffi:with-cstring (source-native source) + (let ((result (c-compress dest destlen source-native sourcelen)) + (newdestlen (uffi:deref-pointer destlen :long))) + (unwind-protect + (if (zerop result) + (values (uffi:convert-from-foreign-string + dest + :length newdestlen + :null-terminated-p nil) + newdestlen) + (error "zlib error, code ~D" result)) + (progn + (uffi:free-foreign-object destlen) + (uffi:free-foreign-object dest))))))) + +(uffi:def-function ("uncompress" c-uncompress) + ((dest (* :unsigned-char)) + (destlen (* :long)) + (source :cstring) + (source-len :long)) + :returning :int + :module "zlib") + +(defun uncompress (source) + (let* ((sourcelen (length source)) + (destsize 200000) ;adjust as needed + (dest (uffi:allocate-foreign-string destsize :unsigned t)) + (destlen (uffi:allocate-foreign-object :long))) + (setf (uffi:deref-pointer destlen :long) destsize) + (uffi:with-cstring (source-native source) + (let ((result (c-uncompress dest destlen source-native sourcelen)) + (newdestlen (uffi:deref-pointer destlen :long))) + (unwind-protect + (if (zerop result) + (uffi:convert-from-foreign-string + dest + :length newdestlen + :null-terminated-p nil) + (error "zlib error, code ~D" result)) + (progn + (uffi:free-foreign-object destlen) + (uffi:free-foreign-object dest))))))) + +#+examples-uffi +(progn + (flet ((print-results (str) + (multiple-value-bind (compressed len) (compress str) + (let ((*print-length* nil)) + (format t "~&(compress ~S) => " str) + (format t "~S~%" (map 'list #'char-code compressed)))))) + (print-results "") + (print-results "test") + (print-results "test2"))) + +#+test-uffi +(progn + (flet ((test-compress (str) + (multiple-value-bind (compressed len) (compress str) + (multiple-value-bind (uncompressed len2) (uncompress compressed) + (util.test:test str uncompressed :test #'string= + :fail-info "Error uncompressing a compressed string"))))) + (test-compress "") + (test-compress "test") + (test-compress "test2"))) + +;; Results of the above on my system: +;; (compress "") => 789c300001,8 +;; (compress "test") => 789c2b492d2e1045d1c1,12 +;; (compress "test2") => 789c2b492d2e31206501f3,13 Added: branches/trunk-reorg/thirdparty/uffi/examples/file-socket.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi/examples/file-socket.lisp Mon Feb 11 09:06:27 2008 @@ -0,0 +1,39 @@ +;;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Base: 10 -*- +;;;; ************************************************************************* +;;;; FILE IDENTIFICATION +;;;; +;;;; Name: file-socket.cl +;;;; Purpose: UFFI Example file to get a socket on a file +;;;; Programmer: Kevin M. Rosenberg +;;;; Date Started: Jul 2002 +;;;; +;;;; $Id$ +;;;; +;;;; This file, part of UFFI, is Copyright (c) 2002-2005 by Kevin M. Rosenberg +;;;; +;;;; ************************************************************************* + +(in-package :cl-user) + +;; Values for linux +(uffi:def-constant PF_UNIX 1) +(uffi:def-constant SOCK_STREAM 1) + +(uffi:def-function ("socket" c-socket) + ((family :int) + (type :int) + (protocol :int)) + :returning :int) + +(uffi:def-function ("connect" c-connect) + ((sockfd :int) + (serv-addr :void-pointer) + (addr-len :int)) + :returning :int) + +(defun connect-to-file-socket (filename) + (let ((socket (c-socket PF_UNIX SOCK_STREAM 0))) + (if (plusp socket) + (let ((stream (c-connect socket filename (length filename)))) + stream) + (error "Unable to create socket")))) Added: branches/trunk-reorg/thirdparty/uffi/examples/getenv.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi/examples/getenv.lisp Mon Feb 11 09:06:27 2008 @@ -0,0 +1,44 @@ +;;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Base: 10 -*- +;;;; ************************************************************************* +;;;; FILE IDENTIFICATION +;;;; +;;;; Name: getenv.cl +;;;; Purpose: UFFI Example file to get environment variable +;;;; Programmer: Kevin M. Rosenberg +;;;; Date Started: Feb 2002 +;;;; +;;;; $Id$ +;;;; +;;;; This file, part of UFFI, is Copyright (c) 2002-2005 by Kevin M. Rosenberg +;;;; +;;;; ************************************************************************* + +(in-package :cl-user) + + +(uffi:def-function ("getenv" c-getenv) + ((name :cstring)) + :returning :cstring) + +(defun my-getenv (key) + "Returns an environment variable, or NIL if it does not exist" + (check-type key string) + (uffi:with-cstring (key-native key) + (uffi:convert-from-cstring (c-getenv key-native)))) + +#+examples-uffi +(progn + (flet ((print-results (str) + (format t "~&(getenv ~S) => ~S" str (my-getenv str)))) + (print-results "USER") + (print-results "_FOO_"))) + + +#+test-uffi +(progn + (util.test:test (my-getenv "_FOO_") nil :fail-info "Error retrieving non-existent getenv") + (util.test:test (and (stringp (my-getenv "USER")) + (< 0 (length (my-getenv "USER")))) + t :fail-info "Error retrieving getenv") +) + Added: branches/trunk-reorg/thirdparty/uffi/examples/gethostname.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi/examples/gethostname.lisp Mon Feb 11 09:06:27 2008 @@ -0,0 +1,63 @@ +;;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Base: 10 -*- +;;;; ************************************************************************* +;;;; FILE IDENTIFICATION +;;;; +;;;; Name: gethostname.cl +;;;; Purpose: UFFI Example file to get hostname of system +;;;; Programmer: Kevin M. Rosenberg +;;;; Date Started: Feb 2002 +;;;; +;;;; $Id$ +;;;; +;;;; This file, part of UFFI, is Copyright (c) 2002-2005 by Kevin M. Rosenberg +;;;; +;;;; ************************************************************************* + +(in-package :cl-user) + + +;;; This example is inspired by the example on the CL-Cookbook web site + +(uffi:def-function ("gethostname" c-gethostname) + ((name (* :unsigned-char)) + (len :int)) + :returning :int) + +(defun gethostname () + "Returns the hostname" + (let* ((name (uffi:allocate-foreign-string 256)) + (result-code (c-gethostname name 256)) + (hostname (when (zerop result-code) + (uffi:convert-from-foreign-string name)))) + (uffi:free-foreign-object name) + (unless (zerop result-code) + (error "gethostname() failed.")) + hostname)) + +(defun gethostname2 () + "Returns the hostname" + (uffi:with-foreign-object (name '(:array :unsigned-char 256)) + (if (zerop (c-gethostname (uffi:char-array-to-pointer name) 256)) + (uffi:convert-from-foreign-string name) + (error "gethostname() failed.")))) + +#+examples-uffi +(progn + (format t "~&Hostname (technique 1): ~A" (gethostname)) + (format t "~&Hostname (technique 2): ~A" (gethostname2))) + +#+test-uffi +(progn + (let ((hostname1 (gethostname)) + (hostname2 (gethostname2))) + + (util.test:test (and (stringp hostname1) (stringp hostname2)) t + :fail-info "gethostname not string") + (util.test:test (and (not (zerop (length hostname1))) + (not (zerop (length hostname2)))) t + :fail-info "gethostname length 0") + (util.test:test (string= hostname1 hostname1) t + :fail-info "gethostname techniques don't match")) + ) + + Added: branches/trunk-reorg/thirdparty/uffi/examples/getshells.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi/examples/getshells.lisp Mon Feb 11 09:06:27 2008 @@ -0,0 +1,44 @@ +;;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Base: 10 -*- +;;;; ************************************************************************* +;;;; FILE IDENTIFICATION +;;;; +;;;; Name: getshells.cl +;;;; Purpose: UFFI Example file to get lisp of legal shells +;;;; Programmer: Kevin M. Rosenberg +;;;; Date Started: Mar 2002 +;;;; +;;;; $Id$ +;;;; +;;;; This file, part of UFFI, is Copyright (c) 2002-2005 by Kevin M. Rosenberg +;;;; +;;;; ************************************************************************* + +(in-package :cl-user) + + +(uffi:def-function "setusershell" + nil + :returning :void) + +(uffi:def-function "endusershell" + nil + :returning :void) + +(uffi:def-function "getusershell" + nil + :returning :cstring) + +(defun getshells () + "Returns list of valid shells" + (setusershell) + (let (shells) + (do ((shell (uffi:convert-from-cstring (getusershell)) + (uffi:convert-from-cstring (getusershell)))) + ((null shell)) + (push shell shells)) + (endusershell) + (nreverse shells))) + +#+examples-uffi +(format t "~&Shells: ~S" (getshells)) + Added: branches/trunk-reorg/thirdparty/uffi/examples/gettime.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi/examples/gettime.lisp Mon Feb 11 09:06:27 2008 @@ -0,0 +1,73 @@ +;;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Base: 10 -*- +;;;; ************************************************************************* +;;;; FILE IDENTIFICATION +;;;; +;;;; Name: gettime +;;;; Purpose: UFFI Example file to get time, use C structures +;;;; Programmer: Kevin M. Rosenberg +;;;; Date Started: Feb 2002 +;;;; +;;;; $Id$ +;;;; +;;;; This file, part of UFFI, is Copyright (c) 2002-2005 by Kevin M. Rosenberg +;;;; +;;;; ************************************************************************* + +(in-package :cl-user) + +(uffi:def-foreign-type time-t :unsigned-long) + +(uffi:def-struct tm + (sec :int) + (min :int) + (hour :int) + (mday :int) + (mon :int) + (year :int) + (wday :int) + (yday :int) + (isdst :int)) + +(uffi:def-function ("time" c-time) + ((time (* time-t))) + :returning time-t) + +(uffi:def-function ("localtime" c-localtime) + ((time (* time-t))) + :returning (* tm)) + +(uffi:def-type time-t :unsigned-long) +(uffi:def-type tm-pointer (* tm)) + +(defun gettime () + "Returns the local time" + (uffi:with-foreign-object (time 'time-t) +;; (declare (type time-t time)) + (c-time time) + (let ((tm-ptr (the tm-pointer (c-localtime time)))) + (declare (type tm-pointer tm-ptr)) + (let ((time-string (format nil "~2d/~2,'0d/~d ~2d:~2,'0d:~2,'0d" + (1+ (uffi:get-slot-value tm-ptr 'tm 'mon)) + (uffi:get-slot-value tm-ptr 'tm 'mday) + (+ 1900 (uffi:get-slot-value tm-ptr 'tm 'year)) + (uffi:get-slot-value tm-ptr 'tm 'hour) + (uffi:get-slot-value tm-ptr 'tm 'min) + (uffi:get-slot-value tm-ptr 'tm 'sec) + ))) + time-string)))) + + + + +#+examples-uffi +(format t "~&~A" (gettime)) + +#+test-uffi +(progn + (let ((time (gettime))) + (util.test:test (stringp time) t :fail-info "Time is not a string") + (util.test:test (plusp (parse-integer time :junk-allowed t)) + t + :fail-info "time string does not start with a number"))) + + Added: branches/trunk-reorg/thirdparty/uffi/examples/run-examples.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi/examples/run-examples.lisp Mon Feb 11 09:06:27 2008 @@ -0,0 +1,36 @@ +;;;; -*- Mode: Lisp; Syntax: ANSI-Common-Lisp; Base: 10 -*- +;;;; ************************************************************************* +;;;; FILE IDENTIFICATION +;;;; +;;;; Name: run-examples.cl +;;;; Purpose: Load and execute all examples for UFFI +;;;; Programmer: Kevin M. Rosenberg +;;;; Date Started: Feb 2002 +;;;; +;;;; $Id$ +;;;; +;;;; This file, part of UFFI, is Copyright (c) 2002-2005 by Kevin M. Rosenberg +;;;; +;;;; ************************************************************************* + +#-uffi (asdf:oos 'asdf:load-op :uffi) + +(pushnew :examples-uffi cl:*features*) + +(flet ((load-test (name) + (load (make-pathname :defaults *load-truename* :name name)))) + (load-test "c-test-fns") + (load-test "arrays") + (load-test "union") + (load-test "strtol") + (load-test "atoifl") + (load-test "gettime") + (load-test "getenv") + (load-test "gethostname") + (load-test "getshells") + (load-test "compress")) + +(setq cl:*features* (remove :examples-uffi cl:*features*)) + + + Added: branches/trunk-reorg/thirdparty/uffi/examples/strtol.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi/examples/strtol.lisp Mon Feb 11 09:06:27 2008 @@ -0,0 +1,80 @@ +;;;; -*- Mode: Lisp; Syntax: ANSI-Common-Lisp; Base: 10 -*- +;;;; ************************************************************************* +;;;; FILE IDENTIFICATION +;;;; +;;;; Name: strtol.cl +;;;; Purpose: UFFI Example file to strtol, uses pointer arithmetic +;;;; Programmer: Kevin M. Rosenberg +;;;; Date Started: Feb 2002 +;;;; +;;;; $Id$ +;;;; +;;;; This file, part of UFFI, is Copyright (c) 2002-2005 by Kevin M. Rosenberg +;;;; +;;;; ************************************************************************* + +(in-package :cl-user) + +(uffi:def-foreign-type char-ptr (* :unsigned-char)) + +;; This example does not use :cstring to pass the input string since +;; the routine needs to do pointer arithmetic to see how many characters +;; were parsed + +(uffi:def-function ("strtol" c-strtol) + ((nptr char-ptr) + (endptr (* char-ptr)) + (base :int)) + :returning :long) + +(defun strtol (str &optional (base 10)) + "Returns a long int from a string. Returns number and condition flag. +Condition flag is T if all of string parses as a long, NIL if +their was no string at all, or an integer indicating position in string +of first non-valid character" + (let* ((str-native (uffi:convert-to-foreign-string str)) + (endptr (uffi:allocate-foreign-object 'char-ptr)) + (value (c-strtol str-native endptr base)) + (endptr-value (uffi:deref-pointer endptr 'char-ptr))) + + (unwind-protect + (if (uffi:null-pointer-p endptr-value) + (values value t) + (let ((next-char-value (uffi:deref-pointer endptr-value :unsigned-char)) + (chars-parsed (- (uffi:pointer-address endptr-value) + (uffi:pointer-address str-native)))) + (cond + ((zerop chars-parsed) + (values nil nil)) + ((uffi:null-char-p next-char-value) + (values value t)) + (t + (values value chars-parsed))))) + (progn + (uffi:free-foreign-object str-native) + (uffi:free-foreign-object endptr))))) + + + +#+examples-uffi +(progn + (flet ((print-results (str) + (multiple-value-bind (result flag) (strtol str) + (format t "~&(strtol ~S) => ~S,~S" str result flag)))) + (print-results "55") + (print-results "55.3") + (print-results "a"))) + +#+test-uffi +(progn + (flet ((test-strtol (str results) + (util.test:test (multiple-value-list (strtol str)) results + :test #'equal + :fail-info "Error testing strtol"))) + (test-strtol "123" '(123 t)) + (test-strtol "0" '(0 t)) + (test-strtol "55a" '(55 2)) + (test-strtol "a" '(nil nil)))) + + + Added: branches/trunk-reorg/thirdparty/uffi/examples/test-examples.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi/examples/test-examples.lisp Mon Feb 11 09:06:27 2008 @@ -0,0 +1,40 @@ +;;;; -*- Mode: Lisp; Syntax: ANSI-Common-Lisp; Base: 10 -*- +;;;; ************************************************************************* +;;;; FILE IDENTIFICATION +;;;; +;;;; Name: test-examples.cl +;;;; Purpose: Load and execute all examples for UFFI +;;;; Programmer: Kevin M. Rosenberg +;;;; Date Started: Feb 2002 +;;;; +;;;; $Id$ +;;;; +;;;; This file, part of UFFI, is Copyright (c) 2002-2005 by Kevin M. Rosenberg +;;;; +;;;; ************************************************************************* + +#-uffi (asdf:oos 'asdf:load-op :uffi) + +(unless (ignore-errors (find-package :util.test)) + (load (make-pathname :name "acl-compat-tester" :defaults *load-truename*))) + +(defun do-tests () + (pushnew :test-uffi cl:*features*) + (util.test:with-tests (:name "UFFI-Tests") + (setq util.test:*break-on-test-failures* nil) + (flet ((load-test (name) + (load (make-pathname :name name :defaults *load-truename*)))) + (load-test "c-test-fns") + (load-test "arrays") + (load-test "union") + (load-test "strtol") + (load-test "atoifl") + (load-test "gettime") + (load-test "getenv") + (load-test "gethostname") + (load-test "getshells") + (load-test "compress")) + (setq cl:*features* (remove :test-uffi cl:*features*)))) + +(do-tests) + Added: branches/trunk-reorg/thirdparty/uffi/examples/union.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi/examples/union.lisp Mon Feb 11 09:06:27 2008 @@ -0,0 +1,86 @@ +;;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Base: 10 -*- +;;;; ************************************************************************* +;;;; FILE IDENTIFICATION +;;;; +;;;; Name: union.cl +;;;; Purpose: UFFI Example file to test unions +;;;; Programmer: Kevin M. Rosenberg +;;;; Date Started: Mar 2002 +;;;; +;;;; $Id$ +;;;; +;;;; This file, part of UFFI, is Copyright (c) 2002-2005 by Kevin M. Rosenberg +;;;; +;;;; ************************************************************************* + +(in-package :cl-user) + +(uffi:def-union tunion1 + (char :char) + (int :int) + (uint :unsigned-int) + (sf :float) + (df :double)) + +(defun run-union-1 () + (let ((u (uffi:allocate-foreign-object 'tunion1))) + (setf (uffi:get-slot-value u 'tunion1 'uint) + ;; little endian + #-(or sparc sparc-v9 powerpc ppc big-endian) + (+ (* 1 (char-code #\A)) + (* 256 (char-code #\B)) + (* 65536 (char-code #\C)) + (* 16777216 255)) + ;; big endian + #+(or sparc sparc-v9 powerpc ppc big-endian) + (+ (* 16777216 (char-code #\A)) + (* 65536 (char-code #\B)) + (* 256 (char-code #\C)) + (* 1 255))) + (format *standard-output* "~&Should be #\A: ~S" + (uffi:ensure-char-character + (uffi:get-slot-value u 'tunion1 'char))) +;; (format *standard-output* "~&Should be negative number: ~D" +;; (uffi:get-slot-value u 'tunion1 'int)) + (format *standard-output* "~&Should be positive number: ~D" + (uffi:get-slot-value u 'tunion1 'uint)) + (uffi:free-foreign-object u)) + (values)) + +#+test-uffi +(defun test-union-1 () + (let ((u (uffi:allocate-foreign-object 'tunion1))) + (setf (uffi:get-slot-value u 'tunion1 'uint) + #-(or sparc sparc-v9 powerpc ppc) + (+ (* 1 (char-code #\A)) + (* 256 (char-code #\B)) + (* 65536 (char-code #\C)) + (* 16777216 128)) + #+(or sparc sparc-v9 powerpc ppc) + (+ (* 16777216 (char-code #\A)) + (* 65536 (char-code #\B)) + (* 256 (char-code #\C)) + (* 1 128))) ;set signed bit + (util.test:test (uffi:ensure-char-character + (uffi:get-slot-value u 'tunion1 'char)) + #\A + :test #'eql + :fail-info "Error with union character") + #-(or sparc sparc-v9 openmcl digitool) +;; (util.test:test (> 0 (uffi:get-slot-value u 'tunion1 'int)) +;; t +;; :fail-info +;; "Error with negative int in union") + (util.test:test (plusp (uffi:get-slot-value u 'tunion1 'uint)) + t + :fail-info + "Error with unsigned int in union") + (uffi:free-foreign-object u)) + (values)) + +#+examples-uffi +(run-union-1) + + +#+test-uffi +(test-union-1) Added: branches/trunk-reorg/thirdparty/uffi/src/Makefile ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi/src/Makefile Mon Feb 11 09:06:27 2008 @@ -0,0 +1,6 @@ +SUBDIRS := + +include ../Makefile.common + +.PHONY: distclean +distclean: clean Added: branches/trunk-reorg/thirdparty/uffi/src/aggregates.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi/src/aggregates.lisp Mon Feb 11 09:06:27 2008 @@ -0,0 +1,262 @@ +;;;; -*- Mode: Lisp; Syntax: ANSI-Common-Lisp; Base: 10; Package: UFFI -*- +;;;; ************************************************************************* +;;;; FILE IDENTIFICATION +;;;; +;;;; Name: aggregates.lisp +;;;; Purpose: UFFI source to handle aggregate types +;;;; Programmer: Kevin M. Rosenberg +;;;; Date Started: Feb 2002 +;;;; +;;;; $Id$ +;;;; +;;;; This file, part of UFFI, is Copyright (c) 2005 by Kevin M. Rosenberg +;;;; +;;;; ************************************************************************* + +(in-package #:uffi) + +(defmacro def-enum (enum-name args &key (separator-string "#")) + "Creates a constants for a C type enum list, symbols are created +in the created in the current package. The symbol is the concatenation +of the enum-name name, separator-string, and field-name" + (let ((counter 0) + (cmds nil) + (constants nil)) + (declare (fixnum counter)) + (dolist (arg args) + (let ((name (if (listp arg) (car arg) arg)) + (value (if (listp arg) + (prog1 + (setq counter (cadr arg)) + (incf counter)) + (prog1 + counter + (incf counter))))) + (setq name (intern (concatenate 'string + (symbol-name enum-name) + separator-string + (symbol-name name)))) + (push `(uffi:def-constant ,name ,value) constants))) + (setf cmds (append '(progn) + #+allegro `((ff:def-foreign-type ,enum-name :int)) + #+lispworks `((fli:define-c-typedef ,enum-name :int)) + #+(or cmu scl) `((alien:def-alien-type ,enum-name alien:signed)) + #+sbcl `((sb-alien:define-alien-type ,enum-name sb-alien:signed)) + #+digitool `((def-mcl-type ,enum-name :integer)) + #+openmcl `((ccl::def-foreign-type ,enum-name :int)) + (nreverse constants))) + cmds)) + + +(defmacro def-array-pointer (name-array type) + #+allegro + `(ff:def-foreign-type ,name-array + (:array ,(convert-from-uffi-type type :array))) + #+lispworks + `(fli:define-c-typedef ,name-array + (:c-array ,(convert-from-uffi-type type :array))) + #+(or cmu scl) + `(alien:def-alien-type ,name-array + (* ,(convert-from-uffi-type type :array))) + #+sbcl + `(sb-alien:define-alien-type ,name-array + (* ,(convert-from-uffi-type type :array))) + #+digitool + `(def-mcl-type ,name-array '(:array ,type)) + #+openmcl + `(ccl::def-foreign-type ,name-array (:array ,(convert-from-uffi-type type :array))) + ) + +(defun process-struct-fields (name fields &optional (variant nil)) + (let (processed) + (dolist (field fields) + (let* ((field-name (car field)) + (type (cadr field)) + (def (append (list field-name) + (if (eq type :pointer-self) + #+(or cmu scl) `((* (alien:struct ,name))) + #+sbcl `((* (sb-alien:struct ,name))) + #+(or openmcl digitool) `((:* (:struct ,name))) + #+lispworks `((:pointer ,name)) + #-(or cmu sbcl scl openmcl digitool lispworks) `((* ,name)) + `(,(convert-from-uffi-type type :struct)))))) + (if variant + (push (list def) processed) + (push def processed)))) + (nreverse processed))) + + +(defmacro def-struct (name &rest fields) + #+(or cmu scl) + `(alien:def-alien-type ,name (alien:struct ,name ,@(process-struct-fields name fields))) + #+sbcl + `(sb-alien:define-alien-type ,name (sb-alien:struct ,name ,@(process-struct-fields name fields))) + #+allegro + `(ff:def-foreign-type ,name (:struct ,@(process-struct-fields name fields))) + #+lispworks + `(fli:define-c-struct ,name ,@(process-struct-fields name fields)) + #+digitool + `(ccl:defrecord ,name ,@(process-struct-fields name fields)) + #+openmcl + `(ccl::def-foreign-type + nil + (:struct ,name ,@(process-struct-fields name fields))) + ) + + +(defmacro get-slot-value (obj type slot) + #+(or lispworks cmu sbcl scl) (declare (ignore type)) + #+allegro + `(ff:fslot-value-typed ,type :c ,obj ,slot) + #+lispworks + `(fli:foreign-slot-value ,obj ,slot) + #+(or cmu scl) + `(alien:slot ,obj ,slot) + #+sbcl + `(sb-alien:slot ,obj ,slot) + #+(or openmcl digitool) + `(ccl:pref ,obj ,(read-from-string (format nil ":~a.~a" (keyword type) (keyword slot)))) + ) + +#+(or openmcl digitool) +(defmacro set-slot-value (obj type slot value) ;use setf to set values + `(setf (ccl:pref ,obj ,(read-from-string (format nil ":~a.~a" (keyword type) (keyword slot)))) ,value)) + +#+(or openmcl digitool) +(defsetf get-slot-value set-slot-value) + + +(defmacro get-slot-pointer (obj type slot) + #+(or lispworks cmu sbcl scl) (declare (ignore type)) + #+allegro + `(ff:fslot-value-typed ,type :c ,obj ,slot) + #+lispworks + `(fli:foreign-slot-pointer ,obj ,slot) + #+(or cmu scl) + `(alien:slot ,obj ,slot) + #+sbcl + `(sb-alien:slot ,obj ,slot) + #+digitool + `(ccl:%int-to-ptr (+ (ccl:%ptr-to-int ,obj) (the fixnum (ccl:field-info ,type ,slot)))) + #+openmcl + `(let ((field (ccl::%find-foreign-record-type-field ,type ,slot))) + (ccl:%int-to-ptr (+ (ccl:%ptr-to-int ,obj) (the fixnum (ccl::foreign-record-field-offset field))))) +) + +;; necessary to eval at compile time for openmcl to compile convert-from-foreign-usb8 +;; below +(eval-when (:compile-toplevel :load-toplevel :execute) + ;; so we could allow '(:array :long) or deref with other type like :long only + #+(or openmcl digitool) + (defun array-type (type) + (let ((result type)) + (when (listp type) + (let ((type-list (if (eq (car type) 'quote) (nth 1 type) type))) + (when (and (listp type-list) (eq (car type-list) :array)) + (setf result (cadr type-list))))) + result)) + + + (defmacro deref-array (obj type i) + "Returns a field from a row" + #+(or lispworks cmu sbcl scl) (declare (ignore type)) + #+(or cmu scl) `(alien:deref ,obj ,i) + #+sbcl `(sb-alien:deref ,obj ,i) + #+lispworks `(fli:dereference ,obj :index ,i :copy-foreign-object nil) + #+allegro `(ff:fslot-value-typed (quote ,(convert-from-uffi-type type :type)) :c ,obj ,i) + #+openmcl + (let* ((array-type (array-type type)) + (local-type (convert-from-uffi-type array-type :allocation)) + (element-size-in-bits (ccl::%foreign-type-or-record-size local-type :bits))) + (ccl::%foreign-access-form + obj + (ccl::%foreign-type-or-record local-type) + `(* ,i ,element-size-in-bits) + nil)) + #+digitool + (let* ((array-type (array-type type)) + (local-type (convert-from-uffi-type array-type :allocation)) + (accessor (first (macroexpand `(ccl:pref obj ,local-type))))) + `(,accessor + ,obj + (* (the fixnum ,i) ,(size-of-foreign-type local-type)))) + )) + +; this expands to the %set-xx functions which has different params than %put-xx +#+digitool +(defmacro deref-array-set (obj type i value) + (let* ((array-type (array-type type)) + (local-type (convert-from-uffi-type array-type :allocation)) + (accessor (first (macroexpand `(ccl:pref obj ,local-type)))) + (settor (first (macroexpand `(setf (,accessor obj ,local-type) value))))) + `(,settor + ,obj + (* (the fixnum ,i) ,(size-of-foreign-type local-type)) + ,value))) + +#+digitool +(defsetf deref-array deref-array-set) + +(defmacro def-union (name &rest fields) + #+allegro + `(ff:def-foreign-type ,name (:union ,@(process-struct-fields name fields))) + #+lispworks + `(fli:define-c-union ,name ,@(process-struct-fields name fields)) + #+(or cmu scl) + `(alien:def-alien-type ,name (alien:union ,name ,@(process-struct-fields name fields))) + #+sbcl + `(sb-alien:define-alien-type ,name (sb-alien:union ,name ,@(process-struct-fields name fields))) + #+digitool + `(ccl:defrecord ,name (:variant ,@(process-struct-fields name fields t))) + #+openmcl + `(ccl::def-foreign-type nil + (:union ,name ,@(process-struct-fields name fields))) +) + + +#-(or sbcl cmu) +(defun convert-from-foreign-usb8 (s len) + (declare (optimize (speed 3) (space 0) (safety 0) (compilation-speed 0)) + (fixnum len)) + (let ((a (make-array len :element-type '(unsigned-byte 8)))) + (dotimes (i len a) + (declare (fixnum i)) + (setf (aref a i) (uffi:deref-array s '(:array :unsigned-byte) i))))) + +#+sbcl +(eval-when (:compile-toplevel :load-toplevel :execute) + (sb-ext:without-package-locks + (defvar *system-copy-fn* (if (fboundp (intern "COPY-FROM-SYSTEM-AREA" "SB-KERNEL")) + (intern "COPY-FROM-SYSTEM-AREA" "SB-KERNEL") + (intern "COPY-UB8-FROM-SYSTEM-AREA" "SB-KERNEL"))) + (defconstant +system-copy-offset+ (if (fboundp (intern "COPY-FROM-SYSTEM-AREA" "SB-KERNEL")) + (* sb-vm:vector-data-offset sb-vm:n-word-bits) + 0)) + (defconstant +system-copy-multiplier+ (if (fboundp (intern "COPY-FROM-SYSTEM-AREA" "SB-KERNEL")) + sb-vm:n-byte-bits + 1)))) + + +#+sbcl +(defun convert-from-foreign-usb8 (s len) + (let ((sap (sb-alien:alien-sap s))) + (declare (type sb-sys:system-area-pointer sap)) + (locally + (declare (optimize (speed 3) (safety 0))) + (let ((result (make-array len :element-type '(unsigned-byte 8)))) + (funcall *system-copy-fn* sap 0 result +system-copy-offset+ + (* len +system-copy-multiplier+)) + result)))) + +#+cmu +(defun convert-from-foreign-usb8 (s len) + (let ((sap (alien:alien-sap s))) + (declare (type system:system-area-pointer sap)) + (locally + (declare (optimize (speed 3) (safety 0))) + (let ((result (make-array len :element-type '(unsigned-byte 8)))) + (kernel:copy-from-system-area sap 0 + result (* vm:vector-data-offset + vm:word-bits) + (* len vm:byte-bits)) + result)))) Added: branches/trunk-reorg/thirdparty/uffi/src/corman/corman-notes.txt ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi/src/corman/corman-notes.txt Mon Feb 11 09:06:27 2008 @@ -0,0 +1,17 @@ +some notes: + we need the :pascal (:stdcall) calling conventions for + (def-function names args &key module returning calling-convention) + so I added this. calling-convention defaults to :cdecl + but on win32 we mostly use :stdcall + + #+corman is invalid, #+cormanlisp instead + + cormanlisp doesn't need to load and register the dll, since the underlying + LoadLibrary() call does this. we need the module keyword for def-function +instead. + (should probably default to kernel32.dll) + I'll think about library.cl, but we'll need more real-world win32 examples. + (ideally the complete winapi :) + I also have to look at valentina. + +patch -p0 < corman.diff Added: branches/trunk-reorg/thirdparty/uffi/src/corman/getenv-ccl.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi/src/corman/getenv-ccl.lisp Mon Feb 11 09:06:27 2008 @@ -0,0 +1,81 @@ +;;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Base: 10 -*- +;;;; ************************************************************************* +;;;; FILE IDENTIFICATION +;;;; +;;;; Name: getenv-ccl.cl +;;;; Purpose: cormanlisp version +;;;; Programmer: "Joe Marshall" +;;;; Date Started: Feb 2002 +;;;; +;;;; $Id$ +;;;; +;;;; ************************************************************************* + +(in-package :cl-user) + +(ct:defun-dll c-getenv ((lpname LPSTR) + (lpbuffer LPSTR) + (nsize LPDWORD)) + :library-name "kernel32.dll" + :return-type DWORD + :entry-name "GetEnvironmentVariableA" + :linkage-type :pascal) + +(defun getenv (name) + (let ((nsizebuf (ct:malloc (sizeof :long))) + (buffer (ct:malloc 1)) + (cname (ct:lisp-string-to-c-string name))) + (setf (ct:cref lpdword nsizebuf 0) 0) + (let* ((needed-size (c-getenv cname buffer nsizebuf)) + (buffer1 (ct:malloc (1+ needed-size)))) + (setf (ct:cref lpdword nsizebuf 0) needed-size) + (prog1 (if (zerop (c-getenv cname buffer1 nsizebuf)) + nil + (ct:c-string-to-lisp-string buffer1)) + (ct:free buffer1) + (ct:free nsizebuf))))) + +(defun cl:user-homedir-pathname (&optional host) + (cond ((or (stringp host) + (and (consp host) + (every #'stringp host))) nil) + ((or (eq host :unspecific) + (null host)) + (let ((homedrive (getenv "HOMEDRIVE")) + (homepath (getenv "HOMEPATH"))) + (parse-namestring + (if (and (stringp homedrive) + (stringp homepath) + (= (length homedrive) 2) + (> (length homepath) 0)) + (concatenate 'string homedrive homepath "\\") + "C:\\")))) + (t (error "HOST must be a string, list of strings, NIL or :unspecific")))) + +;| +(uffi:def-function ("getenv" c-getenv) + ((name :cstring)) + :returning :cstring) + +(defun my-getenv (key) + "Returns an environment variable, or NIL if it does not exist" + (check-type key string) + (uffi:with-cstring (key-native key) + (uffi:convert-from-cstring (c-getenv key-native)))) + +#examples-uffi +(progn + (flet ((print-results (str) + (format t "~&(getenv ~S) => ~S" str (my-getenv str)))) + (print-results "USER") + (print-results "_FOO_"))) + + +#test-uffi +(progn + (util.test:test (my-getenv "_FOO_") nil :fail-info "Error retrieving non-existent getenv") + (util.test:test (and (stringp (my-getenv "USER")) + (< 0 (length (my-getenv "USER")))) + t :fail-info "Error retrieving getenv") +) + Added: branches/trunk-reorg/thirdparty/uffi/src/functions.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi/src/functions.lisp Mon Feb 11 09:06:27 2008 @@ -0,0 +1,239 @@ +;;;; -*- Mode: Lisp; Syntax: ANSI-Common-Lisp; Base: 10; Package: UFFI -*- +;;;; ************************************************************************* +;;;; FILE IDENTIFICATION +;;;; +;;;; Name: function.lisp +;;;; Purpose: UFFI source to C function definitions +;;;; Programmer: Kevin M. Rosenberg +;;;; Date Started: Feb 2002 +;;;; +;;;; $Id$ +;;;; +;;;; This file, part of UFFI, is Copyright (c) 2005 by Kevin M. Rosenberg +;;;; +;;;; ************************************************************************* + +(in-package #:uffi) + +(defun process-function-args (args) + (if (null args) + #+(or lispworks cmu sbcl scl cormanlisp digitool) nil + #+allegro '(:void) + #+openmcl (values nil nil) + + ;; args not null + #+(or lispworks allegro cmu sbcl scl digitool cormanlisp) + (let (processed) + (dolist (arg args) + (push (process-one-function-arg arg) processed)) + (nreverse processed)) + #+openmcl + (let ((processed nil) + (params nil)) + (dolist (arg args) + (let ((name (car arg)) + (type (convert-from-uffi-type (cadr arg) :routine))) + ;;(when (and (listp type) (eq (car type) :address)) + ;;(setf type :address)) + (push name params) + (push type processed) + (push name processed))) + (values (nreverse params) (nreverse processed))) + )) + +(defun process-one-function-arg (arg) + (let ((name (car arg)) + (type (convert-from-uffi-type (cadr arg) :routine))) + #+(or cmu sbcl scl) + ;(list name type :in) + `(,name ,type ,@(if (= (length arg) 3) (list (third arg)) (values))) + #+(or allegro lispworks digitool) + (if (and (listp type) (listp (car type))) + (append (list name) type) + (list name type)) + #+openmcl + (declare (ignore name type)) + )) + + +(defun allegro-convert-return-type (type) + (if (and (listp type) (not (listp (car type)))) + (list type) + type)) + +(defun funcallable-lambda-list (args) + (let ((ll nil)) + (dolist (arg args) + (push (car arg) ll)) + (nreverse ll))) + +#| +(defmacro def-funcallable (name args &key returning) + (let ((result-type (convert-from-uffi-type returning :return)) + (function-args (process-function-args args))) + #+lispworks + `(fli:define-foreign-funcallable ,name ,function-args + :result-type ,result-type + :language :ansi-c + :calling-convention :cdecl) + #+(or cmu scl sbcl) + ;; requires the type of the function pointer be declared correctly! + (let* ((ptrsym (gensym)) + (ll (funcallable-lambda-list args))) + `(defun ,name ,(cons ptrsym ll) + (alien::alien-funcall ,ptrsym , at ll))) + #+openmcl + (multiple-value-bind (params args) (process-function-args args) + (let ((ptrsym (gensym))) + `(defun ,name ,(cons ptrsym params) + (ccl::ff-call ,ptrsym , at args ,result-type)))) + #+allegro + ;; this is most definitely wrong + (let* ((ptrsym (gensym)) + (ll (funcallable-lambda-list args))) + `(defun ,name ,(cons ptrsym ll) + (system::ff-funcall ,ptrsym , at ll))) + )) +|# + +(defun convert-lispworks-args (args) + (loop for arg in args + with processed = nil + do + (if (and (= (length arg) 3) (eq (third arg) :out)) + (push (list (first arg) + (list :reference-return (second arg))) processed) + (push (subseq arg 0 2) processed)) + finally (return (nreverse processed)))) + +(defun preprocess-names (names) + (let ((fname (gensym))) + (if (atom names) + (values (list names fname) fname (uffi::make-lisp-name names)) + (values (list (first names) fname) fname (second names))))) + +(defun preprocess-args (args) + (loop for arg in args + with lisp-args = nil and out = nil and processed = nil + do + (if (= (length arg) 3) + (ecase (third arg) + (:in + (progn + (push (first arg) lisp-args) + (push (list (first arg) (second arg)) processed))) + (:out + (progn + (push (list (first arg) (second arg)) out) + (push (list (first arg) (list '* (second arg))) processed)))) + (progn + (push (first arg) lisp-args) + (push arg processed))) + finally (return (values (nreverse lisp-args) + (nreverse out) + (nreverse processed))))) + + +(defmacro def-function (names args &key module returning) + (multiple-value-bind (lisp-args out processed) + (preprocess-args args) + (declare (ignorable lisp-args processed)) + (if (= (length out) 0) + `(%def-function ,names ,args + ,@(if module (list :module module) (values)) + ,@(if returning (list :returning returning) (values))) + + #+(or cmu scl sbcl) + `(%def-function ,names ,args + ,@(if returning (list :returning returning) (values))) + #+(and lispworks lispworks5) + (multiple-value-bind (name-pair fname lisp-name) + (preprocess-names names) + `(progn + (%def-function ,name-pair ,(convert-lispworks-args args) + ,@(if module (list :module module) (values)) + ,@(if returning (list :returning returning) (values))) + (defun ,lisp-name ,lisp-args + (,fname ,@(mapcar + #'(lambda (arg) + (cond ((member (first arg) lisp-args) + (first arg)) + ((member (first arg) out :key #'first) + t))) + args))))) + #+(and lispworks (not lispworks5)) + `(%def-function ,names ,(convert-lispworks-args args) + ,@(if module (list :module module) (values)) + ,@(if returning (list :returning returning) (values))) + #-(or cmu scl sbcl lispworks) + (multiple-value-bind (name-pair fname lisp-name) + (preprocess-names names) + `(progn + (%def-function ,name-pair ,processed + :module ,module :returning ,returning) + ;(declaim (inline ,fname)) + (defun ,lisp-name ,lisp-args + (with-foreign-objects ,out + (values (,fname ,@(mapcar #'first args)) + ,@(mapcar #'(lambda (arg) + (list 'deref-pointer + (first arg) + (second arg))) out)))))) + ))) + + +;; name is either a string representing foreign name, or a list +;; of foreign-name as a string and lisp name as a symbol +(defmacro %def-function (names args &key module returning) + #+(or cmu sbcl scl allegro openmcl digitool cormanlisp) (declare (ignore module)) + + (let* ((result-type (convert-from-uffi-type returning :return)) + (function-args (process-function-args args)) + (foreign-name (if (atom names) names (car names))) + (lisp-name (if (atom names) (make-lisp-name names) (cadr names)))) + ;; todo: calling-convention :stdcall for cormanlisp + #+allegro + `(ff:def-foreign-call (,lisp-name ,foreign-name) + ,function-args + :returning ,(allegro-convert-return-type result-type) + :call-direct t + :strings-convert nil) + #+(or cmu scl) + `(alien:def-alien-routine (,foreign-name ,lisp-name) + ,result-type + , at function-args) + #+sbcl + `(sb-alien:define-alien-routine (,foreign-name ,lisp-name) + ,result-type + , at function-args) + #+lispworks + `(fli:define-foreign-function (,lisp-name ,foreign-name :source) + ,function-args + ,@(if module (list :module module) (values)) + :result-type ,result-type + :language :ansi-c + #+:win32 :calling-convention #+:win32 :cdecl) + #+digitool + `(eval-when (:compile-toplevel :load-toplevel :execute) + (ccl:define-entry-point (,lisp-name ,foreign-name) + ,function-args + ,result-type)) + #+openmcl + (declare (ignore function-args)) + #+(and openmcl darwinppc-target) + (setf foreign-name (concatenate 'string "_" foreign-name)) + #+openmcl + (multiple-value-bind (params args) (process-function-args args) + `(defun ,lisp-name ,params + (ccl::external-call ,foreign-name , at args ,result-type))) + #+cormanlisp + `(ct:defun-dll ,lisp-name (,function-args) + :return-type ,result-type + ,@(if module (list :library-name module) (values)) + :entry-name ,foreign-name + :linkage-type ,calling-convention) ; we need :pascal + )) + + + + Added: branches/trunk-reorg/thirdparty/uffi/src/libraries.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi/src/libraries.lisp Mon Feb 11 09:06:27 2008 @@ -0,0 +1,134 @@ +;;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Base: 10; Package: UFFI -*- +;;;; ************************************************************************* +;;;; FILE IDENTIFICATION +;;;; +;;;; Name: libraries.lisp +;;;; Purpose: UFFI source to load foreign libraries +;;;; Programmer: Kevin M. Rosenberg +;;;; Date Started: Feb 2002 +;;;; +;;;; $Id$ +;;;; +;;;; This file, part of UFFI, is Copyright (c) 2002-2005 by Kevin M. Rosenberg +;;;; +;;;; ************************************************************************* + +(in-package #:uffi) + +(defvar *loaded-libraries* nil + "List of foreign libraries loaded. Used to prevent reloading a library") + +(defun default-foreign-library-type () + "Returns string naming default library type for platform" + #+(or win32 cygwin mswindows) "dll" + #+(or macosx darwin ccl-5.0) "dylib" + #-(or win32 cygwin mswindows macosx darwin ccl-5.0) "so" +) + +(defun foreign-library-types () + "Returns list of string naming possible library types for platform, sorted by preference" + #+(or win32 mswindows) '("dll" "lib") + #+(or macosx darwin ccl-5.0) '("dylib" "bundle") + #-(or win32 mswindows macosx darwin ccl-5.0) '("so" "a" "o") +) + +(defun find-foreign-library (names directories &key types drive-letters) + "Looks for a foreign library. directories can be a single +string or a list of strings of candidate directories. Use default +library type if type is not specified." + (unless types + (setq types (foreign-library-types))) + (unless (listp types) + (setq types (list types))) + (unless (listp names) + (setq names (list names))) + (unless (listp directories) + (setq directories (list directories))) + #+(or win32 mswindows) + (unless (listp drive-letters) + (setq drive-letters (list drive-letters))) + #-(or win32 mswindows) + (setq drive-letters '(nil)) + (dolist (drive-letter drive-letters) + (dolist (name names) + (dolist (dir directories) + (dolist (type types) + (let ((path (make-pathname + #+lispworks :host + #+lispworks (when drive-letter drive-letter) + #-lispworks :device + #-lispworks (when drive-letter drive-letter) + :name name + :type type + :directory + (etypecase dir + (pathname + (pathname-directory dir)) + (list + dir) + (string + (pathname-directory + (parse-namestring dir))))))) + (when (probe-file path) + (return-from find-foreign-library path))))))) + nil) + + +(defun load-foreign-library (filename &key module supporting-libraries + force-load) + #+(or allegro openmcl digitool sbcl) (declare (ignore module supporting-libraries)) + #+(or cmu scl) (declare (ignore module)) + #+lispworks (declare (ignore supporting-libraries)) + + (flet ((load-failure () + (error "Unable to load foreign library \"~A\"." filename))) + (when (and filename (or (null (pathname-directory filename)) + (probe-file filename))) + (if (pathnamep filename) ;; ensure filename is a string to check if already loaded + (setq filename (namestring (if (null (pathname-directory filename)) + filename + ;; lispworks treats as UNC, so use truename + #+(and lispworks win32) (truename filename) + #-(and lispworks win32) filename)))) + + (if (and (not force-load) + (find filename *loaded-libraries* :test #'string-equal)) + t ;; return T, but don't reload library + (progn + #+cmu + (let ((type (pathname-type (parse-namestring filename)))) + (if (string-equal type "so") + (unless + (sys::load-object-file filename) + (load-failure)) + (alien:load-foreign filename + :libraries + (convert-supporting-libraries-to-string + supporting-libraries)))) + #+scl + (let ((type (pathname-type (parse-namestring filename)))) + (alien:load-foreign filename + :libraries + (convert-supporting-libraries-to-string + supporting-libraries))) + #+sbcl + (handler-case (sb-alien::load-1-foreign filename) + (sb-int:unsupported-operator (c) + (if (fboundp (intern "LOAD-SHARED-OBJECT" :sb-alien)) + (funcall (intern "LOAD-SHARED-OBJECT" :sb-alien) filename) + (error c)))) + + #+lispworks (fli:register-module module :real-name filename + :connection-style :immediate) + #+allegro (load filename) + #+openmcl (ccl:open-shared-library filename) + #+digitool (ccl:add-to-shared-library-search-path filename t) + + (push filename *loaded-libraries*) + t))))) + +(defun convert-supporting-libraries-to-string (libs) + (let (lib-load-list) + (dolist (lib libs) + (push (format nil "-l~A" lib) lib-load-list)) + (nreverse lib-load-list))) Added: branches/trunk-reorg/thirdparty/uffi/src/objects.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi/src/objects.lisp Mon Feb 11 09:06:27 2008 @@ -0,0 +1,291 @@ +;;;; -*- Mode: Lisp; Syntax: ANSI-Common-Lisp; Base: 10; Package: UFFI -*- +;;;; ************************************************************************* +;;;; FILE IDENTIFICATION +;;;; +;;;; Name: objects.lisp +;;;; Purpose: UFFI source to handle objects and pointers +;;;; Programmer: Kevin M. Rosenberg +;;;; Date Started: Feb 2002 +;;;; +;;;; $Id$ +;;;; +;;;; This file, part of UFFI, is Copyright (c) 2002-2005 by Kevin M. Rosenberg +;;;; +;;;; ************************************************************************* + +(in-package #:uffi) + +(eval-when (:compile-toplevel :load-toplevel :execute) + (defun size-of-foreign-type (type) + #+lispworks (fli:size-of type) + #+allegro (ff:sizeof-fobject type) + #+(or cmu scl) (ash (eval `(alien:alien-size ,type)) -3) ;; convert from bits to bytes + #+sbcl (ash (eval `(sb-alien:alien-size ,type)) -3) ;; convert from bits to bytes + #+clisp (values (ffi:size-of type)) + #+digitool + (let ((mcl-type (ccl:find-mactype type nil t))) + (if mcl-type + (ccl::mactype-record-size mcl-type) + (ccl::record-descriptor-length (ccl:find-record-descriptor type t t)))) ;error if not a record + #+openmcl (ccl::%foreign-type-or-record-size type :bytes) + )) + +(defmacro allocate-foreign-object (type &optional (size :unspecified)) + "Allocates an instance of TYPE. If size is specified, then allocate +an array of TYPE with size SIZE. The TYPE parameter is evaluated." + (if (eq size :unspecified) + (progn + #+(or cmu scl) + `(alien:make-alien ,(convert-from-uffi-type (eval type) :allocation)) + #+sbcl + `(sb-alien:make-alien ,(convert-from-uffi-type (eval type) :allocation)) + #+lispworks + `(fli:allocate-foreign-object :type ',(convert-from-uffi-type type :allocate)) + #+allegro + `(ff:allocate-fobject ',(convert-from-uffi-type type :allocate) :c) + #+(or openmcl digitool) + `(new-ptr ,(size-of-foreign-type (convert-from-uffi-type type :allocation))) + ) + (progn + #+(or cmu scl) + `(alien:make-alien ,(convert-from-uffi-type (eval type) :allocation) ,size) + #+sbcl + `(sb-alien:make-alien ,(convert-from-uffi-type (eval type) :allocation) ,size) + #+lispworks + `(fli:allocate-foreign-object :type ',(convert-from-uffi-type type :allocate) :nelems ,size) + #+allegro + `(ff:allocate-fobject (list :array (quote ,(convert-from-uffi-type type :allocate)) ,size) :c) + #+(or openmcl digitool) + `(new-ptr (* ,size ,(size-of-foreign-type (convert-from-uffi-type type :allocation)))) + ))) + +(defmacro free-foreign-object (obj) + #+(or cmu scl) + `(alien:free-alien ,obj) + #+sbcl + `(sb-alien:free-alien ,obj) + #+lispworks + `(fli:free-foreign-object ,obj) + #+allegro + `(ff:free-fobject ,obj) + #+(or openmcl digitool) + `(dispose-ptr ,obj) + ) + +(defmacro null-pointer-p (obj) + #+lispworks `(fli:null-pointer-p ,obj) + #+allegro `(zerop ,obj) + #+(or cmu scl) `(alien:null-alien ,obj) + #+sbcl `(sb-alien:null-alien ,obj) + #+(or openmcl digitool) `(ccl:%null-ptr-p ,obj) + ) + +(defmacro make-null-pointer (type) + #+(or allegro openmcl digitool) (declare (ignore type)) + #+(or cmu scl) `(alien:sap-alien (system:int-sap 0) (* ,(convert-from-uffi-type (eval type) :type))) + #+sbcl `(sb-alien:sap-alien (sb-sys:int-sap 0) (* ,(convert-from-uffi-type (eval type) :type))) + #+lispworks `(fli:make-pointer :address 0 :type (quote ,(convert-from-uffi-type (eval type) :type))) + #+allegro 0 + #+(or openmcl digitool) `(ccl:%null-ptr) + ) + +(defmacro make-pointer (addr type) + #+(or allegro openmcl digitool) (declare (ignore type)) + #+(or cmu scl) `(alien:sap-alien (system:int-sap ,addr) (* ,(convert-from-uffi-type (eval type) :type))) + #+sbcl `(sb-alien:sap-alien (sb-sys:int-sap ,addr) (* ,(convert-from-uffi-type (eval type) :type))) + #+lispworks `(fli:make-pointer :address ,addr :type (quote ,(convert-from-uffi-type (eval type) :type))) + #+allegro addr + #+(or openmcl digitool) `(ccl:%int-to-ptr ,addr) + ) + + +(defmacro char-array-to-pointer (obj) + #+(or cmu scl) `(alien:cast ,obj (* (alien:unsigned 8))) + #+sbcl `(sb-alien:cast ,obj (* (sb-alien:unsigned 8))) + #+lispworks `(fli:make-pointer :type '(:unsigned :char) + :address (fli:pointer-address ,obj)) + #+allegro obj + #+(or openmcl digitool) obj + ) + +(defmacro deref-pointer (ptr type) + "Returns a object pointed" + #+(or cmu sbcl lispworks scl) (declare (ignore type)) + #+(or cmu scl) `(alien:deref ,ptr) + #+sbcl `(sb-alien:deref ,ptr) + #+lispworks `(fli:dereference ,ptr) + #+allegro `(ff:fslot-value-typed (quote ,(convert-from-uffi-type type :deref)) :c ,ptr) + #+(or openmcl digitool) `(ccl:pref ,ptr ,(convert-from-uffi-type type :deref)) + ) + +#+digitool +(defmacro deref-pointer-set (ptr type value) + `(setf (ccl:pref ,ptr ,(convert-from-uffi-type type :deref)) ,value)) + +#+digitool +(defsetf deref-pointer deref-pointer-set) + +(defmacro ensure-char-character (obj) + #+(or digitool) obj + #+(or allegro cmu sbcl scl openmcl) `(code-char ,obj) + ;; lispworks varies whether deref'ing array vs. slot access of a char + #+lispworks `(if (characterp ,obj) ,obj (code-char ,obj))) + +(defmacro ensure-char-integer (obj) + #+(or digitool) `(char-code ,obj) + #+(or allegro cmu sbcl scl openmcl) obj + ;; lispworks varies whether deref'ing array vs. slot access of a char + #+lispworks + `(if (integerp ,obj) ,obj (char-code ,obj))) + +(defmacro ensure-char-storable (obj) + #+(or digitool (and lispworks (not lispworks5))) obj + #+(or allegro cmu lispworks5 openmcl sbcl scl) + `(char-code ,obj)) + +(defmacro pointer-address (obj) + #+(or cmu scl) + `(system:sap-int (alien:alien-sap ,obj)) + #+sbcl + `(sb-sys:sap-int (sb-alien:alien-sap ,obj)) + #+lispworks + `(fli:pointer-address ,obj) + #+allegro + obj + #+(or openmcl digitool) + `(ccl:%ptr-to-int ,obj) + ) + +;; TYPE is evaluated. +#-(or openmcl digitool) +(defmacro with-foreign-object ((var type) &rest body) + #-(or cmu sbcl lispworks scl) ; default version + `(let ((,var (allocate-foreign-object ,type))) + (unwind-protect + (progn , at body) + (free-foreign-object ,var))) + #+(or cmu scl) + (let ((obj (gensym)) + (ctype (convert-from-uffi-type (eval type) :allocate))) + (if (and (consp ctype) (eq 'array (car ctype))) + `(alien:with-alien ((,obj ,ctype)) + (let* ((,var ,obj)) + , at body)) + `(alien:with-alien ((,obj ,ctype)) + (let* ((,var (alien:addr ,obj))) + , at body)))) + #+sbcl + (let ((obj (gensym)) + (ctype (convert-from-uffi-type (eval type) :allocate))) + (if (and (consp ctype) (eq 'array (car ctype))) + `(sb-alien:with-alien ((,obj ,ctype)) + (let* ((,var ,obj)) + , at body)) + `(sb-alien:with-alien ((,obj ,ctype)) + (let* ((,var (sb-alien:addr ,obj))) + , at body)))) + #+lispworks + `(fli:with-dynamic-foreign-objects ((,var ,(convert-from-uffi-type + (eval type) :allocate))) + , at body) + ) + +#-(or openmcl digitool) +(defmacro with-foreign-objects (bindings &rest body) + (if bindings + `(with-foreign-object ,(car bindings) + (with-foreign-objects ,(cdr bindings) + , at body)) + `(progn , at body))) + +#+(or openmcl digitool) +(defmacro with-foreign-objects (bindings &rest body) + (let ((params nil) type count) + (dolist (spec (reverse bindings)) ;keep order - macroexpands to let* + (setf type (convert-from-uffi-type (eval (nth 1 spec)) :allocate)) + (setf count 1) + (when (and (listp type) (eq (first type) :array)) + (setf count (nth 2 type)) + (unless (integerp count) (error "Invalid size for array: ~a" type)) + (setf type (nth 1 type))) + (push (list (first spec) (* count (size-of-foreign-type type))) params)) + `(ccl:%stack-block ,params , at body))) + +#+(or openmcl digitool) +(defmacro with-foreign-object ((var type) &rest body) + `(with-foreign-objects ((,var ,type)) + , at body)) + +#+lispworks +(defmacro with-cast-pointer ((binding-name pointer type) &body body) + `(fli:with-coerced-pointer (,binding-name + :type ',(convert-from-uffi-type (eval type) :type)) + ,pointer + , at body)) + +#+(or cmu scl sbcl) +(defmacro with-cast-pointer ((binding-name pointer type) &body body) + `(let ((,binding-name + (#+(or cmu scl) alien:cast + #+sbcl sb-alien:cast + ,pointer (* ,(convert-from-uffi-type (eval type) :type))))) + , at body)) + +#+(or allegro openmcl) +(defmacro with-cast-pointer ((binding-name pointer type) &body body) + (declare (ignore type)) + `(let ((,binding-name ,pointer)) + , at body)) + +#-(or lispworks cmu scl sbcl allegro openmcl) +(defmacro with-cast-pointer ((binding-name pointer type) &body body) + (declare (ignore binding-name pointer type body)) + '(error "WITH-CAST-POINTER not (yet) implemented for ~A" + (lisp-implementation-type))) + +#+(or allegro openmcl) +(defun convert-external-name (name) + "Add an underscore to NAME if necessary for the ABI." + #+(or macosx darwinppc-target) (concatenate 'string "_" name) + #-(or macosx darwinppc-target) name) + +(defmacro def-foreign-var (names type module) + #-lispworks (declare (ignore module)) + (let ((foreign-name (if (atom names) names (first names))) + (lisp-name (if (atom names) (make-lisp-name names) (second names))) + #-allegro + (var-type (convert-from-uffi-type type :type))) + #+(or cmu scl) + `(alien:def-alien-variable (,foreign-name ,lisp-name) ,var-type) + #+sbcl + `(sb-alien:define-alien-variable (,foreign-name ,lisp-name) ,var-type) + #+allegro + `(define-symbol-macro ,lisp-name + (ff:fslot-value-typed (quote ,(convert-from-uffi-type type :deref)) + :c (ff:get-entry-point ,(convert-external-name foreign-name)))) + #+lispworks + `(progn + (fli:define-foreign-variable (,lisp-name ,foreign-name) + :accessor :address-of + :type ,var-type + :module ,module) + (define-symbol-macro ,lisp-name (fli:dereference (,lisp-name) + :copy-foreign-object nil))) + #+openmcl + `(define-symbol-macro ,lisp-name + (deref-pointer (ccl:foreign-symbol-address + ,(convert-external-name foreign-name)) ,var-type)) + #-(or allegro cmu scl sbcl lispworks openmcl) + `(define-symbol-macro ,lisp-name + '(error "DEF-FOREIGN-VAR not (yet) defined for ~A" + (lisp-implementation-type))))) + + +;;; Define a special variable, like DEFVAR, that will be initialized +;;; to a pointer which may need to be reset when a saved image is +;;; loaded. This is needed for OpenMCL, which sets pointers to "dead +;;; macptrs" when a saved image is loaded. +;; This may possibly be needed for sbcl's SAVE-LISP-AND-DIE +(defmacro def-pointer-var (name value &optional doc) + #-openmcl `(defvar ,name ,value ,@(if doc (list doc))) + #+openmcl `(ccl::defloadvar ,name ,value ,doc)) Added: branches/trunk-reorg/thirdparty/uffi/src/os.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi/src/os.lisp Mon Feb 11 09:06:27 2008 @@ -0,0 +1,79 @@ +;;;; -*- Mode: Lisp; Syntax: ANSI-Common-Lisp; Base: 10; Package: UFFI -*- +;;;; ************************************************************************* +;;;; FILE IDENTIFICATION +;;;; +;;;; Name: os.lisp +;;;; Purpose: Operating system interface for UFFI +;;;; Programmer: Kevin M. Rosenberg +;;;; Date Started: Sep 2002 +;;;; +;;;; $Id$ +;;;; +;;;; This file, part of UFFI, is Copyright (c) 2002-2005 by Kevin M. Rosenberg. +;;;; +;;;; ************************************************************************* + +(in-package #:uffi) + + +(defun getenv (var) + "Return the value of the environment variable." + #+allegro (sys::getenv (string var)) + #+clisp (sys::getenv (string var)) + #+cmu (cdr (assoc (string var) ext:*environment-list* :test #'equalp + :key #'string)) + #+gcl (si:getenv (string var)) + #+lispworks (lw:environment-variable (string var)) + #+lucid (lcl:environment-variable (string var)) + #+(or openmcl digitool) (ccl::getenv var) + #+sbcl (sb-ext:posix-getenv var) + #-(or allegro clisp cmu gcl lispworks lucid openmcl digitool sbcl) + (error 'not-implemented :proc (list 'getenv var))) + + +;; modified from function ASDF -- Copyright Dan Barlow and Contributors + +(defun run-shell-command (control-string &rest args &key output) + "Interpolate ARGS into CONTROL-STRING as if by FORMAT, and +synchronously execute the result using a Bourne-compatible shell, with +output to *trace-output*. Returns the shell's exit code." + (unless output + (setq output *trace-output*)) + + (let ((command (apply #'format nil control-string args))) + #+sbcl + (sb-impl::process-exit-code + (sb-ext:run-program + "/bin/sh" + (list "-c" command) + :input nil :output output)) + + #+(or cmu scl) + (ext:process-exit-code + (ext:run-program + "/bin/sh" + (list "-c" command) + :input nil :output output)) + + #+allegro + (excl:run-shell-command command :input nil :output output) + + #+lispworks + (system:call-system-showing-output + command + :shell-type "/bin/sh" + :output-stream output) + + #+clisp ;XXX not exactly *trace-output*, I know + (ext:run-shell-command command :output :terminal :wait t) + + #+openmcl + (nth-value 1 + (ccl:external-process-status + (ccl:run-program "/bin/sh" (list "-c" command) + :input nil :output output + :wait t))) + + #-(or openmcl clisp lispworks allegro scl cmu sbcl) + (error "RUN-SHELL-PROGRAM not implemented for this Lisp.") + )) Added: branches/trunk-reorg/thirdparty/uffi/src/package.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi/src/package.lisp Mon Feb 11 09:06:27 2008 @@ -0,0 +1,84 @@ +;;;; -*- Mode: Lisp; Syntax: ANSI-Common-Lisp; Base: 10; Package: UFFI -*- +;;;; ************************************************************************* +;;;; FILE IDENTIFICATION +;;;; +;;;; Name: package.lisp +;;;; Purpose: Defines UFFI package +;;;; Programmer: Kevin M. Rosenberg +;;;; Date Started: Feb 2002 +;;;; +;;;; This file, part of UFFI, is Copyright (c) 2002-2005 by Kevin M. Rosenberg +;;;; +;;;; ************************************************************************* + +(in-package #:cl-user) + +(defpackage #:uffi + (:use #:cl) + (:export + + ;; immediate types + #:def-constant + #:def-foreign-type + #:def-type + #:null-char-p + + ;; aggregate types + #:def-enum + #:def-struct + #:get-slot-value + #:get-slot-pointer + #:def-array-pointer + #:deref-array + #:def-union + + ;; objects + #:allocate-foreign-object + #:free-foreign-object + #:with-foreign-object + #:with-foreign-objects + #:size-of-foreign-type + #:pointer-address + #:deref-pointer + #:ensure-char-character + #:ensure-char-integer + #:ensure-char-storable + #:null-pointer-p + #:make-null-pointer + #:make-pointer + #:pointer-address + #:+null-cstring-pointer+ + #:char-array-to-pointer + #:with-cast-pointer + #:def-foreign-var + #:convert-from-foreign-usb8 + #:def-pointer-var + + ;; string functions + #:convert-from-cstring + #:convert-to-cstring + #:free-cstring + #:with-cstring + #:with-cstrings + #:convert-from-foreign-string + #:convert-to-foreign-string + #:allocate-foreign-string + #:with-foreign-string + #:with-foreign-strings + #:foreign-string-length + + ;; function call + #:def-function + + ;; Libraries + #:find-foreign-library + #:load-foreign-library + #:default-foreign-library-type + #:foreign-library-types + + ;; OS + #:run-shell-command + #:getenv + )) + + Added: branches/trunk-reorg/thirdparty/uffi/src/primitives.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi/src/primitives.lisp Mon Feb 11 09:06:27 2008 @@ -0,0 +1,311 @@ +;;;; -*- Mode: Lisp; Syntax: ANSI-Common-Lisp; Base: 10; Package: UFFI -*- +;;;; ************************************************************************* +;;;; FILE IDENTIFICATION +;;;; +;;;; Name: primitives.lisp +;;;; Purpose: UFFI source to handle immediate types +;;;; Programmer: Kevin M. Rosenberg +;;;; Date Started: Feb 2002 +;;;; +;;;; $Id$ +;;;; +;;;; This file, part of UFFI, is Copyright (c) 2002-2005 by Kevin M. Rosenberg +;;;; +;;;; ************************************************************************* + +(in-package #:uffi) + +#+(or openmcl digitool) +(defvar *keyword-package* (find-package "KEYWORD")) + +#+(or openmcl digitool) +; MCL and OpenMCL expect a lot of FFI elements to be keywords (e.g. struct field names in OpenMCL) +; So this provides a function to convert any quoted symbols to keywords. +(defun keyword (obj) + (cond ((keywordp obj) + obj) + ((null obj) + nil) + ((symbolp obj) + (intern (symbol-name obj) *keyword-package*)) + ((and (listp obj) (eq (car obj) 'cl:quote)) + (keyword (cadr obj))) + ((stringp obj) + (intern obj *keyword-package*)) + (t + obj))) + +; Wrapper for unexported function we have to use +#+digitool +(defmacro def-mcl-type (name type) + `(ccl::def-mactype ,(keyword name) (ccl:find-mactype ,type))) + +(defmacro def-constant (name value &key (export nil)) + "Macro to define a constant and to export it" + `(eval-when (:compile-toplevel :load-toplevel :execute) + (defconstant ,name ,value) + ,(when export (list 'export `(quote ,name))) + ',name)) + +(defmacro def-type (name type) + "Generates a (deftype) statement for CL. Currently, only CMUCL +supports takes advantage of this optimization." + #+(or lispworks allegro openmcl digitool cormanlisp) (declare (ignore type)) + #+(or lispworks allegro openmcl digitool cormanlisp) `(deftype ,name () t) + #+(or cmu scl) + `(deftype ,name () '(alien:alien ,(convert-from-uffi-type type :declare))) + #+sbcl + `(deftype ,name () '(sb-alien:alien ,(convert-from-uffi-type type :declare))) + ) + +(defmacro null-char-p (val) + "Returns T if character is NULL" + `(zerop ,val)) + +(defmacro def-foreign-type (name type) + #+lispworks `(fli:define-c-typedef ,name ,(convert-from-uffi-type type :type)) + #+allegro `(ff:def-foreign-type ,name ,(convert-from-uffi-type type :type)) + #+(or cmu scl) `(alien:def-alien-type ,name ,(convert-from-uffi-type type :type)) + #+sbcl `(sb-alien:define-alien-type ,name ,(convert-from-uffi-type type :type)) + #+cormanlisp `(ct:defctype ,name ,(convert-from-uffi-type type :type)) + #+(or openmcl digitool) + (let ((mcl-type (convert-from-uffi-type type :type))) + (unless (or (keywordp mcl-type) (consp mcl-type)) + (setf mcl-type `(quote ,mcl-type))) + #+digitool + `(def-mcl-type ,(keyword name) ,mcl-type) + #+openmcl + `(ccl::def-foreign-type ,(keyword name) ,mcl-type)) + ) + +(eval-when (:compile-toplevel :load-toplevel :execute) + (defvar +type-conversion-hash+ (make-hash-table :size 20 :test #'eq)) + #+(or cmu sbcl scl) (defvar *cmu-def-type-hash* + (make-hash-table :size 20 :test #'eq)) + ) + +#+(or cmu scl) +(defvar *cmu-sbcl-def-type-list* + '((:char . (alien:signed 8)) + (:unsigned-char . (alien:unsigned 8)) + (:byte . (alien:signed 8)) + (:unsigned-byte . (alien:unsigned 8)) + (:short . (alien:signed 16)) + (:unsigned-short . (alien:unsigned 16)) + (:int . (alien:signed 32)) + (:unsigned-int . (alien:unsigned 32)) + #-x86-64 (:long . (alien:signed 32)) + #-x86-64 (:unsigned-long . (alien:unsigned 32)) + #+x86-64 (:long . (alien:signed 64)) + #+x86-64 (:unsigned-long . (alien:unsigned 64)) + (:float . alien:single-float) + (:double . alien:double-float) + (:void . t) + ) + "Conversions in CMUCL for def-foreign-type are different than in def-function") + +#+sbcl +(defvar *cmu-sbcl-def-type-list* + '((:char . (sb-alien:signed 8)) + (:unsigned-char . (sb-alien:unsigned 8)) + (:byte . (sb-alien:signed 8)) + (:unsigned-byte . (sb-alien:unsigned 8)) + (:short . (sb-alien:signed 16)) + (:unsigned-short . (sb-alien:unsigned 16)) + (:int . (sb-alien:signed 32)) + (:unsigned-int . (sb-alien:unsigned 32)) + #-x86-64 (:long . (sb-alien:signed 32)) + #-x86-64 (:unsigned-long . (sb-alien:unsigned 32)) + #+x86-64 (:long . (sb-alien:signed 64)) + #+x86-64 (:unsigned-long . (sb-alien:unsigned 64)) + (:float . sb-alien:single-float) + (:double . sb-alien:double-float) + (:void . t) + ) + "Conversions in SBCL for def-foreign-type are different than in def-function") + +(defvar *type-conversion-list* nil) + +#+(or cmu scl) +(setq *type-conversion-list* + '((* . *) (:void . c-call:void) + (:pointer-void . (* t)) + (:cstring . c-call:c-string) + (:char . c-call:char) + (:unsigned-char . (alien:unsigned 8)) + (:byte . (alien:signed 8)) + (:unsigned-byte . (alien:unsigned 8)) + (:short . c-call:short) + (:unsigned-short . c-call:unsigned-short) + (:int . alien:integer) (:unsigned-int . c-call:unsigned-int) + (:long . c-call:long) (:unsigned-long . c-call:unsigned-long) + (:float . c-call:float) (:double . c-call:double) + (:array . alien:array))) + +#+sbcl +(setq *type-conversion-list* + '((* . *) (:void . sb-alien:void) + (:pointer-void . (* t)) + #-sb-unicode(:cstring . sb-alien:c-string) + #+sb-unicode(:cstring . sb-alien:utf8-string) + (:char . sb-alien:char) + (:unsigned-char . (sb-alien:unsigned 8)) + (:byte . (sb-alien:signed 8)) + (:unsigned-byte . (sb-alien:unsigned 8)) + (:short . sb-alien:short) + (:unsigned-short . sb-alien:unsigned-short) + (:int . sb-alien:int) (:unsigned-int . sb-alien:unsigned-int) + (:long . sb-alien:long) (:unsigned-long . sb-alien:unsigned-long) + (:float . sb-alien:float) (:double . sb-alien:double) + (:array . sb-alien:array))) + +#+(or allegro cormanlisp) +(setq *type-conversion-list* + '((* . *) (:void . :void) + (:short . :short) + (:pointer-void . (* :void)) + (:cstring . (* :unsigned-char)) + (:byte . :char) + (:unsigned-byte . :unsigned-char) + (:char . :char) + (:unsigned-char . :unsigned-char) + (:int . :int) (:unsigned-int . :unsigned-int) + (:long . :long) (:unsigned-long . :unsigned-long) + (:float . :float) (:double . :double) + (:array . :array))) + +#+lispworks +(setq *type-conversion-list* + '((* . :pointer) (:void . :void) + (:short . :short) + (:pointer-void . (:pointer :void)) + (:cstring . (:reference-pass (:ef-mb-string :external-format + (:latin-1 :eol-style :lf)) + :allow-null t)) + (:cstring-returning . (:reference (:ef-mb-string :external-format + (:latin-1 :eol-style :lf)) + :allow-null t)) + (:byte . :byte) + (:unsigned-byte . (:unsigned :byte)) + (:char . :char) + (:unsigned-char . (:unsigned :char)) + (:int . :int) (:unsigned-int . (:unsigned :int)) + (:long . :long) (:unsigned-long . (:unsigned :long)) + (:float . :float) (:double . :double) + (:array . :c-array))) + +#+digitool +(setq *type-conversion-list* + '((* . :pointer) (:void . :void) + (:short . :short) (:unsigned-short . :unsigned-short) + (:pointer-void . :pointer) + (:cstring . :string) + (:char . :character) + (:unsigned-char . :unsigned-byte) + (:byte . :signed-byte) (:unsigned-byte . :unsigned-byte) + (:int . :long) (:unsigned-int . :unsigned-long) + (:long . :long) (:unsigned-long . :unsigned-long) + (:float . :single-float) (:double . :double-float) + (:array . :array))) + +#+openmcl +(setq *type-conversion-list* + '((* . :address) (:void . :void) + (:short . :short) (:unsigned-short . :unsigned-short) + (:pointer-void . :address) + (:cstring . :address) + (:char . :signed-char) + (:unsigned-char . :unsigned-char) + (:byte . :signed-byte) (:unsigned-byte . :unsigned-byte) + (:int . :int) (:unsigned-int . :unsigned-int) + (:long . :long) (:unsigned-long . :unsigned-long) + (:long-long . :signed-doubleword) (:unsigned-long-long . :unsigned-doubleword) + (:float . :single-float) (:double . :double-float) + (:array . :array))) + +(dolist (type *type-conversion-list*) + (setf (gethash (car type) +type-conversion-hash+) (cdr type))) + +#+(or cmu sbcl scl) +(dolist (type *cmu-sbcl-def-type-list*) + (setf (gethash (car type) *cmu-def-type-hash*) (cdr type))) + +(defun basic-convert-from-uffi-type (type) + (let ((found-type (gethash type +type-conversion-hash+))) + (if found-type + found-type + #-(or openmcl digitool) type + #+(or openmcl digitool) (keyword type)))) + +(defun %convert-from-uffi-type (type context) + "Converts from a uffi type to an implementation specific type" + (if (atom type) + (cond + #+(or allegro cormanlisp) + ((and (or (eq context :routine) (eq context :return)) + (eq type :cstring)) + (setq type '((* :char) integer))) + #+(or cmu sbcl scl) + ((eq context :type) + (let ((cmu-type (gethash type *cmu-def-type-hash*))) + (if cmu-type + cmu-type + (basic-convert-from-uffi-type type)))) + #+lispworks + ((and (eq context :return) + (eq type :cstring)) + (basic-convert-from-uffi-type :cstring-returning)) + #+digitool + ((and (eq type :void) (eq context :return)) nil) + (t + (basic-convert-from-uffi-type type))) + (let ((sub-type (car type))) + (case sub-type + (cl:quote + (convert-from-uffi-type (cadr type) context)) + (:struct-pointer + #+(or openmcl digitool) `(:* (:struct ,(%convert-from-uffi-type (cadr type) :struct))) + #-(or openmcl digitool) (%convert-from-uffi-type (list '* (cadr type)) :struct) + ) + (:struct + #+(or openmcl digitool) `(:struct ,(%convert-from-uffi-type (cadr type) :struct)) + #-(or openmcl digitool) (%convert-from-uffi-type (cadr type) :struct) + ) + (:union + #+(or openmcl digitool) `(:union ,(%convert-from-uffi-type (cadr type) :union)) + #-(or openmcl digitool) (%convert-from-uffi-type (cadr type) :union) + ) + (t + (cons (%convert-from-uffi-type (first type) context) + (%convert-from-uffi-type (rest type) context))))))) + +(defun convert-from-uffi-type (type context) + (let ((result (%convert-from-uffi-type type context))) + (cond + ((atom result) result) + #+openmcl + ((eq (car result) :address) + (if (eq context :struct) + (append '(:*) (cdr result)) + :address)) + #+digitool + ((and (eq (car result) :pointer) (eq context :allocation) :pointer)) + (t result)))) + +(eval-when (:compile-toplevel :load-toplevel :execute) + (when (char= #\a (schar (symbol-name '#:a) 0)) + (pushnew :uffi-lowercase-reader *features*)) + (when (not (string= (symbol-name '#:a) + (symbol-name '#:A))) + (pushnew :uffi-case-sensitive *features*))) + +(defun make-lisp-name (name) + (let ((converted (substitute #\- #\_ name))) + (intern + #+uffi-case-sensitive converted + #+(and (not uffi-lowercase-reader) (not uffi-case-sensitive)) (string-upcase converted) + #+(and uffi-lowercase-reader (not uffi-case-sensitive)) (string-downcase converted)))) + +(eval-when (:compile-toplevel :load-toplevel :execute) + (setq cl:*features* (delete :uffi-lowercase-reader *features*)) + (setq cl:*features* (delete :uffi-case-sensitive *features*))) Added: branches/trunk-reorg/thirdparty/uffi/src/readmacros-mcl.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi/src/readmacros-mcl.lisp Mon Feb 11 09:06:27 2008 @@ -0,0 +1,35 @@ +;;;; -*- Mode: Lisp; Syntax: ANSI-Common-Lisp; Base: 10; Package: UFFI -*- +;;;; ************************************************************************* +;;;; FILE IDENTIFICATION +;;;; +;;;; Name: readmacros-mcl.lisp +;;;; Purpose: This file holds functions using read macros for MCL +;;;; Programmer: Kevin M. Rosenberg/John Desoi +;;;; Date Started: Feb 2002 +;;;; +;;;; $Id$ +;;;; +;;;; This file, part of UFFI, is Copyright (c) 2002-2005 by Kevin M. Rosenberg +;;;; +;;;; ************************************************************************* + +(in-package #:uffi) + + +;; trap macros don't work right directly in the macros +#+digitool +(defun new-ptr (size) + (#_NewPtr size)) + +#+digitool +(defun dispose-ptr (ptr) + (#_DisposePtr ptr)) + +#+openmcl +(defmacro new-ptr (size) + `(ccl::malloc ,size)) + +#+openmcl +(defmacro dispose-ptr (ptr) + `(ccl::free ,ptr)) + Added: branches/trunk-reorg/thirdparty/uffi/src/strings.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi/src/strings.lisp Mon Feb 11 09:06:27 2008 @@ -0,0 +1,412 @@ +;;;; -*- Mode: Lisp; Syntax: ANSI-Common-Lisp; Base: 10; Package: UFFI -*- +;;;; ************************************************************************* +;;;; FILE IDENTIFICATION +;;;; +;;;; Name: strings.lisp +;;;; Purpose: UFFI source to handle strings, cstring and foreigns +;;;; Programmer: Kevin M. Rosenberg +;;;; Date Started: Feb 2002 +;;;; +;;;; $Id$ +;;;; +;;;; This file, part of UFFI, is Copyright (c) 2002-2005 by Kevin M. Rosenberg +;;;; ************************************************************************* + +(in-package #:uffi) + + +(def-pointer-var +null-cstring-pointer+ + #+(or cmu sbcl scl) nil + #+allegro 0 + #+lispworks (fli:make-pointer :address 0 :type '(:unsigned :char)) + #+(or openmcl digitool) (ccl:%null-ptr) +) + +(defmacro convert-from-cstring (obj) + "Converts a string from a c-call. Same as convert-from-foreign-string, except +that LW/CMU automatically converts strings from c-calls." + #+(or cmu sbcl lispworks scl) obj + #+allegro + (let ((stored (gensym))) + `(let ((,stored ,obj)) + (if (zerop ,stored) + nil + (values (excl:native-to-string ,stored))))) + #+(or openmcl digitool) + (let ((stored (gensym))) + `(let ((,stored ,obj)) + (if (ccl:%null-ptr-p ,stored) + nil + (values (ccl:%get-cstring ,stored))))) + ) + +(defmacro convert-to-cstring (obj) + #+(or cmu sbcl scl lispworks) obj + #+allegro + (let ((stored (gensym))) + `(let ((,stored ,obj)) + (if (null ,stored) + 0 + (values (excl:string-to-native ,stored))))) + #+(or openmcl digitool) + (let ((stored (gensym))) + `(let ((,stored ,obj)) + (if (null ,stored) + +null-cstring-pointer+ + (let ((ptr (new-ptr (1+ (length ,stored))))) + (ccl::%put-cstring ptr ,stored) + ptr)))) + ) + +(defmacro free-cstring (obj) + #+(or cmu sbcl scl lispworks) (declare (ignore obj)) + #+allegro + (let ((stored (gensym))) + `(let ((,stored ,obj)) + (unless (zerop ,stored) + (ff:free-fobject ,stored)))) + #+(or openmcl digitool) + (let ((stored (gensym))) + `(let ((,stored ,obj)) + (unless (ccl:%null-ptr-p ,stored) + (dispose-ptr ,stored)))) + ) + +(defmacro with-cstring ((cstring lisp-string) &body body) + #+(or cmu sbcl scl lispworks) + `(let ((,cstring ,lisp-string)) , at body) + #+allegro + (let ((acl-native (gensym)) + (stored-lisp-string (gensym))) + `(let ((,stored-lisp-string ,lisp-string)) + (excl:with-native-string (,acl-native ,stored-lisp-string) + (let ((,cstring (if ,stored-lisp-string ,acl-native 0))) + , at body)))) + #+(or openmcl digitool) + (let ((stored-lisp-string (gensym))) + `(let ((,stored-lisp-string ,lisp-string)) + (if (stringp ,stored-lisp-string) + (ccl:with-cstrs ((,cstring ,stored-lisp-string)) + , at body) + (let ((,cstring +null-cstring-pointer+)) + , at body)))) + ) + +(defmacro with-cstrings (bindings &rest body) + (if bindings + `(with-cstring ,(car bindings) + (with-cstrings ,(cdr bindings) + , at body)) + `(progn , at body))) + +;;; Foreign string functions + +(defmacro convert-to-foreign-string (obj) + #+lispworks + (let ((stored (gensym))) + `(let ((,stored ,obj)) + (if (null ,stored) + +null-cstring-pointer+ + (fli:convert-to-foreign-string + ,stored + :external-format '(:latin-1 :eol-style :lf))))) + #+allegro + (let ((stored (gensym))) + `(let ((,stored ,obj)) + (if (null ,stored) + 0 + (values (excl:string-to-native ,stored))))) + #+(or cmu scl) + (let ((size (gensym)) + (storage (gensym)) + (stored-obj (gensym)) + (i (gensym))) + `(let ((,stored-obj ,obj)) + (etypecase ,stored-obj + (null + (alien:sap-alien (system:int-sap 0) (* (alien:unsigned 8)))) + (string + (let* ((,size (length ,stored-obj)) + (,storage (alien:make-alien (alien:unsigned 8) (1+ ,size)))) + (setq ,storage (alien:cast ,storage (* (alien:unsigned 8)))) + (locally + (declare (optimize (speed 3) (safety 0))) + (dotimes (,i ,size) + (declare (fixnum ,i)) + (setf (alien:deref ,storage ,i) + (char-code (char ,stored-obj ,i)))) + (setf (alien:deref ,storage ,size) 0)) + ,storage))))) + #+sbcl + (let ((size (gensym)) + (storage (gensym)) + (stored-obj (gensym)) + (i (gensym))) + `(let ((,stored-obj ,obj)) + (etypecase ,stored-obj + (null + (sb-alien:sap-alien (sb-sys:int-sap 0) (* (sb-alien:unsigned 8)))) + (string + (let* ((,size (length ,stored-obj)) + (,storage (sb-alien:make-alien (sb-alien:unsigned 8) (1+ ,size)))) + (setq ,storage (sb-alien:cast ,storage (* (sb-alien:unsigned 8)))) + (locally + (declare (optimize (speed 3) (safety 0))) + (dotimes (,i ,size) + (declare (fixnum ,i)) + (setf (sb-alien:deref ,storage ,i) + (char-code (char ,stored-obj ,i)))) + (setf (sb-alien:deref ,storage ,size) 0)) + ,storage))))) + #+(or openmcl digitool) + (let ((stored-obj (gensym))) + `(let ((,stored-obj ,obj)) + (if (null ,stored-obj) + +null-cstring-pointer+ + (let ((ptr (new-ptr (1+ (length ,stored-obj))))) + (ccl::%put-cstring ptr ,stored-obj) + ptr)))) + ) + +;; Either length or null-terminated-p must be non-nil +(defmacro convert-from-foreign-string (obj &key + length + (locale :default) + (null-terminated-p t)) + #+allegro + (let ((stored-obj (gensym))) + `(let ((,stored-obj ,obj)) + (if (zerop ,stored-obj) + nil + (if (eq ,locale :none) + (fast-native-to-string ,stored-obj ,length) + (values + (excl:native-to-string + ,stored-obj + ,@(when length (list :length length)) + :truncate (not ,null-terminated-p))))))) + #+lispworks + (let ((stored-obj (gensym))) + `(let ((,stored-obj ,obj)) + (if (fli:null-pointer-p ,stored-obj) + nil + (if (eq ,locale :none) + (fast-native-to-string ,stored-obj ,length) + (fli:convert-from-foreign-string + ,stored-obj + ,@(when length (list :length length)) + :null-terminated-p ,null-terminated-p + :external-format '(:latin-1 :eol-style :lf)))))) + #+(or cmu scl) + (let ((stored-obj (gensym))) + `(let ((,stored-obj ,obj)) + (if (null-pointer-p ,stored-obj) + nil + (cmucl-naturalize-cstring (alien:alien-sap ,stored-obj) + :length ,length + :null-terminated-p ,null-terminated-p)))) + + #+sbcl + (let ((stored-obj (gensym))) + `(let ((,stored-obj ,obj)) + (if (null-pointer-p ,stored-obj) + nil + (sbcl-naturalize-cstring (sb-alien:alien-sap ,stored-obj) + :length ,length + :null-terminated-p ,null-terminated-p)))) + #+(or openmcl digitool) + (declare (ignore null-terminated-p)) + #+(or openmcl digitool) + (let ((stored-obj (gensym))) + `(let ((,stored-obj ,obj)) + (if (ccl:%null-ptr-p ,stored-obj) + nil + #+digitool (ccl:%get-cstring + ,stored-obj 0 + ,@(if length (list length) nil)) + #+openmcl ,@(if length + `((ccl:%str-from-ptr ,stored-obj ,length)) + `((ccl:%get-cstring ,stored-obj)))))) + ) + + +(defmacro allocate-foreign-string (size &key (unsigned t)) + #+ignore + (let ((array-def (gensym))) + `(let ((,array-def (list 'alien:array 'c-call:char ,size))) + (eval `(alien:cast (alien:make-alien ,,array-def) + ,(if ,unsigned + '(* (alien:unsigned 8)) + '(* (alien:signed 8))))))) + + #+(or cmu scl) + `(alien:make-alien ,(if unsigned + '(alien:unsigned 8) + '(alien:signed 8)) + ,size) + + #+sbcl + `(sb-alien:make-alien ,(if unsigned + '(sb-alien:unsigned 8) + '(sb-alien:signed 8)) + ,size) + + #+lispworks + `(fli:allocate-foreign-object :type + ,(if unsigned + ''(:unsigned :char) + :char) + :nelems ,size) + #+allegro + (declare (ignore unsigned)) + #+allegro + `(ff:allocate-fobject :char :c ,size) + #+(or openmcl digitool) + (declare (ignore unsigned)) + #+(or openmcl digitool) + `(new-ptr ,size) + ) + +(defun foreign-string-length (foreign-string) + #+allegro `(ff:foreign-strlen ,foreign-string) + #-allegro + `(loop with size = 0 + until (char= (deref-array ,foreign-string '(:array :unsigned-char) size) #\Null) + do (incf size) + finally return size)) + + +(defmacro with-foreign-string ((foreign-string lisp-string) &body body) + (let ((result (gensym))) + `(let* ((,foreign-string (convert-to-foreign-string ,lisp-string)) + (,result (progn , at body))) + (declare (dynamic-extent ,foreign-string)) + (free-foreign-object ,foreign-string) + ,result))) + +(defmacro with-foreign-strings (bindings &body body) + `(with-foreign-string ,(car bindings) + ,@(if (cdr bindings) + `((with-foreign-strings ,(cdr bindings) , at body)) + body))) + +;; Modified from CMUCL's source to handle non-null terminated strings +#+cmu +(defun cmucl-naturalize-cstring (sap &key length (null-terminated-p t)) + (declare (type system:system-area-pointer sap)) + (locally + (declare (optimize (speed 3) (safety 0))) + (let ((null-terminated-length + (when null-terminated-p + (loop + for offset of-type fixnum upfrom 0 + until (zerop (system:sap-ref-8 sap offset)) + finally (return offset))))) + (if length + (if (and null-terminated-length + (> (the fixnum length) (the fixnum null-terminated-length))) + (setq length null-terminated-length)) + (setq length null-terminated-length))) + (let ((result (make-string length))) + (kernel:copy-from-system-area sap 0 + result (* vm:vector-data-offset + vm:word-bits) + (* length vm:byte-bits)) + result))) + +#+scl +;; kernel:copy-from-system-area doesn't work like it does on CMUCL or SBCL, +;; so have to iteratively copy from sap +(defun cmucl-naturalize-cstring (sap &key length (null-terminated-p t)) + (declare (type system:system-area-pointer sap)) + (locally + (declare (optimize (speed 3) (safety 0))) + (let ((null-terminated-length + (when null-terminated-p + (loop + for offset of-type fixnum upfrom 0 + until (zerop (system:sap-ref-8 sap offset)) + finally (return offset))))) + (if length + (if (and null-terminated-length + (> (the fixnum length) (the fixnum null-terminated-length))) + (setq length null-terminated-length)) + (setq length null-terminated-length))) + (let ((result (make-string length))) + (dotimes (i length) + (declare (type fixnum i)) + (setf (char result i) (code-char (system:sap-ref-8 sap i)))) + result))) + +#+(and sbcl (not sb-unicode)) +(defun sbcl-naturalize-cstring (sap &key length (null-terminated-p t)) + (declare (type sb-sys:system-area-pointer sap) + (type (or null fixnum) length)) + (locally + (declare (optimize (speed 3) (safety 0))) + (let ((null-terminated-length + (when null-terminated-p + (loop + for offset of-type fixnum upfrom 0 + until (zerop (sb-sys:sap-ref-8 sap offset)) + finally (return offset))))) + (if length + (if (and null-terminated-length + (> (the fixnum length) (the fixnum null-terminated-length))) + (setq length null-terminated-length)) + (setq length null-terminated-length))) + (let ((result (make-string length))) + (funcall *system-copy-fn* sap 0 result +system-copy-offset+ + (* length +system-copy-multiplier+)) + result))) + +#+(and sbcl sb-unicode) +(defun sbcl-naturalize-cstring (sap &key length (null-terminated-p t)) + (declare (type sb-sys:system-area-pointer sap) + (type (or null fixnum) length)) + (locally + (declare (optimize (speed 3) (safety 0))) + (cond + (null-terminated-p + (let ((casted (sb-alien:cast (sb-alien:sap-alien sap (* char)) + #+sb-unicode sb-alien:utf8-string + #-sb-unicode sb-alien:c-string))) + (if length + (copy-seq (subseq casted 0 length)) + (copy-seq casted)))) + (t + (let ((result (make-string length))) + ;; this will not work in sb-unicode + (funcall *system-copy-fn* sap 0 result +system-copy-offset+ + (* length +system-copy-multiplier+)) + result))))) + + +(eval-when (:compile-toplevel :load-toplevel :execute) + (def-function "strlen" + ((str (* :unsigned-char))) + :returning :unsigned-int)) + +(def-type char-ptr-def (* :unsigned-char)) + +#+(or (and allegro (not ics)) (and lispworks (not lispworks5))) +(defun fast-native-to-string (s len) + (declare (optimize (speed 3) (space 0) (safety 0) (compilation-speed 0)) + (type char-ptr-def s)) + (let* ((len (or len (strlen s))) + (str (make-string len))) + (declare (fixnum len) + (type (simple-array #+lispworks base-char + #-lispworks (signed-byte 8) (*)) str)) + (dotimes (i len str) + (setf (aref str i) + (uffi:deref-array s '(:array :char) i))))) + +#+(or (and allegro ics) lispworks5) +(defun fast-native-to-string (s len) + (declare (optimize (speed 3) (space 0) (safety 0) (compilation-speed 0)) + (type char-ptr-def s)) + (let* ((len (or len (strlen s))) + (str (make-string len))) + (dotimes (i len str) + (setf (schar str i) (code-char (uffi:deref-array s '(:array :unsigned-byte) i)))))) Added: branches/trunk-reorg/thirdparty/uffi/tests/Makefile ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi/tests/Makefile Mon Feb 11 09:06:27 2008 @@ -0,0 +1,30 @@ +# FILE IDENTIFICATION +# +# Name: Makefile +# Purpose: Makefile for UFFI examples +# Programer: Kevin M. Rosenberg +# Date Started: Mar 2002 +# +# CVS Id: $Id$ +# +# This file, part of UFFI, is Copyright (c) 2002-2005 by Kevin M. Rosenberg + +SUBDIRS= + +include ../Makefile.common + +base=uffi-c-test +source=$(base).c +object=$(base).o +shared_lib=$(base).so + +.PHONY: all +all: $(shared_lib) + +$(shared_lib): $(source) Makefile + BASE=$(base) OBJECT=$(object) SOURCE=$(source) SHARED_LIB=$(shared_lib) sh make.sh + rm $(object) + +.PHONY: distclean +distclean: clean + rm -f $(base).dylib $(base).dylib $(base).so $(base).o Added: branches/trunk-reorg/thirdparty/uffi/tests/Makefile.msvc ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi/tests/Makefile.msvc Mon Feb 11 09:06:27 2008 @@ -0,0 +1,28 @@ +# FILE IDENTIFICATION +# +# Name: Makefile.msvc +# Purpose: Makefile for the CLSQL UFFI helper package (MSVC) +# Programer: Kevin M. Rosenberg +# Date Started: Mar 2002 +# +# CVS Id: $Id: Makefile.msvc,v 1.1 2002/03/23 10:26:03 kevin Exp $ +# +# This file, part of CLSQL, is Copyright (c) 2002-2005 by Kevin M. Rosenberg +# + +BASE=c-test-fns + +# Nothing to configure beyond here + +SRC=$(BASE).c +OBJ=$(BASE).obj +DLL=$(BASE).dll + +$(DLL): $(SRC) + cl /MD /LD -D_MT /DWIN32=1 $(SRC) + del $(OBJ) $(BASE).exp + +clean: + del /q $(DLL) + + Added: branches/trunk-reorg/thirdparty/uffi/tests/arrays.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi/tests/arrays.lisp Mon Feb 11 09:06:27 2008 @@ -0,0 +1,57 @@ +;;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Base: 10 -*- +;;;; ************************************************************************* +;;;; FILE IDENTIFICATION +;;;; +;;;; Name: arrays.lisp +;;;; Purpose: UFFI test arrays +;;;; Author: Kevin M. Rosenberg +;;;; Date Started: Mar 2002 +;;;; +;;;; $Id$ +;;;; +;;;; This file, part of UFFI, is Copyright (c) 2002-2005 by Kevin M. Rosenberg +;;;; +;;;; ************************************************************************* + +(in-package #:uffi-tests) + +(uffi:def-constant +column-length+ 10) +(uffi:def-constant +row-length+ 10) + +(uffi:def-foreign-type long-ptr (* :long)) + +(deftest :array.1 + (let ((a (uffi:allocate-foreign-object :long +column-length+)) + (results nil)) + (dotimes (i +column-length+) + (setf (uffi:deref-array a '(:array :long) i) (* i i))) + (dotimes (i +column-length+) + (push (uffi:deref-array a '(:array :long) i) results)) + (uffi:free-foreign-object a) + (nreverse results)) + (0 1 4 9 16 25 36 49 64 81)) + + +(deftest :array.2 + (let ((a (uffi:allocate-foreign-object 'long-ptr +row-length+)) + (results nil)) + (dotimes (r +row-length+) + (declare (fixnum r)) + (setf (uffi:deref-array a '(:array (* :long)) r) + (uffi:allocate-foreign-object :long +column-length+)) + (let ((col (uffi:deref-array a '(:array (* :long)) r))) + (dotimes (c +column-length+) + (declare (fixnum c)) + (setf (uffi:deref-array col '(:array :long) c) (+ (* r +column-length+) c))))) + + (dotimes (r +row-length+) + (declare (fixnum r)) + (let ((col (uffi:deref-array a '(:array (* :long)) r))) + (dotimes (c +column-length+) + (declare (fixnum c)) + (push (uffi:deref-array col '(:array :long) c) results)))) + (uffi:free-foreign-object a) + (nreverse results)) + (0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99)) + + Added: branches/trunk-reorg/thirdparty/uffi/tests/atoifl.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi/tests/atoifl.lisp Mon Feb 11 09:06:27 2008 @@ -0,0 +1,42 @@ +;;;; -*- Mode: Lisp; Syntax: ANSI-Common-Lisp; Base: 10 -*- +;;;; ************************************************************************* +;;;; FILE IDENTIFICATION +;;;; +;;;; Name: atoifl.lisp +;;;; Purpose: UFFI Example file to atoi/atof/atol +;;;; Programmer: Kevin M. Rosenberg +;;;; Date Started: Mar 2002 +;;;; +;;;; $Id$ +;;;; +;;;; This file, part of UFFI, is Copyright (c) 2002-2005 by Kevin M. Rosenberg +;;;; +;;;; ************************************************************************* + +(in-package #:uffi-tests) + +(uffi:def-function ("atoi" c-atoi) + ((str :cstring)) + :returning :int) + +(uffi:def-function ("atol" c-atol) + ((str :cstring)) + :returning :long) + +(uffi:def-function ("atof" c-atof) + ((str :cstring)) + :returning :double) + +(defun atoi (str) + "Returns a int from a string." + (uffi:with-cstring (str-cstring str) + (c-atoi str-cstring))) + +(defun atof (str) + "Returns a double float from a string." + (uffi:with-cstring (str-cstring str) + (c-atof str-cstring))) + +(deftest :atoi.1 (atoi "123") 123) +(deftest :atoi.2 (atoi "") 0) +(deftest :atof.3 (atof "2.23") 2.23d0) Added: branches/trunk-reorg/thirdparty/uffi/tests/casts.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi/tests/casts.lisp Mon Feb 11 09:06:27 2008 @@ -0,0 +1,51 @@ +;;;; -*- Mode: Lisp; Syntax: ANSI-Common-Lisp; Base: 10 -*- +;;;; ************************************************************************* +;;;; FILE IDENTIFICAION +;;;; +;;;; Name: casts.lisp +;;;; Purpose: Tests of with-cast-pointer +;;;; Programmer: Kevin M. Rosenberg / Edi Weitz +;;;; Date Started: Aug 2003 +;;;; +;;;; $Id$ +;;;; +;;;; This file, part of UFFI, is Copyright (c) 2003-2005 by Kevin M. Rosenberg +;;;; +;;;; ************************************************************************* + +(in-package #:uffi-tests) + +(uffi:def-function ("cast_test_int" cast-test-int) + () + :module "uffi_tests" + :returning :pointer-void) + +(uffi:def-function ("cast_test_float" cast-test-float) + () + :module "uffi_tests" + :returning :pointer-void) + +(deftest :cast.1 + (progn + (uffi:with-cast-pointer (temp (cast-test-int) :int) + (assert (= (uffi:deref-pointer temp :int) 23))) + (let ((result (cast-test-int))) + (uffi:with-cast-pointer (result2 result :int) + (assert (= (uffi:deref-pointer result2 :int) 23))) + (uffi:with-cast-pointer (temp result :int) + (assert (= (uffi:deref-pointer temp :int) 23)))) + t) + t) + +(deftest :cast.2 + (progn + (uffi:with-cast-pointer (temp (cast-test-float) :double) + (assert (= (uffi:deref-pointer temp :double) 3.21d0))) + (let ((result (cast-test-float))) + (uffi:with-cast-pointer (result2 result :double) + (assert (= (uffi:deref-pointer result2 :double) 3.21d0))) + (uffi:with-cast-pointer (temp result :double) + (assert (= (uffi:deref-pointer temp :double) 3.21d0)))) + t) + t) + Added: branches/trunk-reorg/thirdparty/uffi/tests/compress.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi/tests/compress.lisp Mon Feb 11 09:06:27 2008 @@ -0,0 +1,92 @@ +;;;; -*- Mode: Lisp; Syntax: ANSI-Common-Lisp; Base: 10 -*- +;;;; ************************************************************************* +;;;; FILE IDENTIFICATION +;;;; +;;;; Name: compress.lisp +;;;; Purpose: UFFI Example file for zlib compression +;;;; Author: Kevin M. Rosenberg +;;;; Date Started: Feb 2002 +;;;; +;;;; $Id$ +;;;; +;;;; This file, part of UFFI, is Copyright (c) 2002-2005 by Kevin M. Rosenberg +;;;; +;;;; ************************************************************************* + +(in-package #:uffi-tests) + +(uffi:def-function ("compress" c-compress) + ((dest (* :unsigned-char)) + (destlen (* :long)) + (source :cstring) + (source-len :long)) + :returning :int + :module "zlib") + +(defun compress (source) + "Returns two values: array of bytes containing the compressed data + and the numbe of compressed bytes" + (let* ((sourcelen (length source)) + (destsize (+ 12 (ceiling (* sourcelen 1.01)))) + (dest (uffi:allocate-foreign-string destsize :unsigned t)) + (destlen (uffi:allocate-foreign-object :long))) + (setf (uffi:deref-pointer destlen :long) destsize) + (uffi:with-cstring (source-native source) + (let ((result (c-compress dest destlen source-native sourcelen)) + (newdestlen (uffi:deref-pointer destlen :long))) + (unwind-protect + (if (zerop result) + (values (uffi:convert-from-foreign-usb8 + dest newdestlen) + newdestlen) + (error "zlib error, code ~D" result)) + (progn + (uffi:free-foreign-object destlen) + (uffi:free-foreign-object dest))))))) + +(uffi:def-function ("uncompress" c-uncompress) + ((dest (* :unsigned-char)) + (destlen (* :long)) + (source :cstring) + (source-len :long)) + :returning :int + :module "zlib") + +(defun uncompress (source) + (let* ((sourcelen (length source)) + (destsize 200000) ;adjust as needed + (dest (uffi:allocate-foreign-string destsize :unsigned t)) + (destlen (uffi:allocate-foreign-object :long))) + (setf (uffi:deref-pointer destlen :long) destsize) + (uffi:with-cstring (source-native source) + (let ((result (c-uncompress dest destlen source-native sourcelen)) + (newdestlen (uffi:deref-pointer destlen :long))) + (unwind-protect + (if (zerop result) + (uffi:convert-from-foreign-string + dest + :length newdestlen + :null-terminated-p nil) + (error "zlib error, code ~D" result)) + (progn + (uffi:free-foreign-object destlen) + (uffi:free-foreign-object dest))))))) + +(deftest :compress.1 (compress "") + #(120 156 3 0 0 0 0 1) 8) +(deftest :compress.2 (compress "test") + #(120 156 43 73 45 46 1 0 4 93 1 193) 12) +(deftest :compress.3 (compress "test2") + #(120 156 43 73 45 46 49 2 0 6 80 1 243) 13) + +(defun compress-uncompress (str) + (multiple-value-bind (compressed len) (compress str) + (declare (ignore len)) + (multiple-value-bind (uncompressed len2) (uncompress compressed) + (declare (ignore len2)) + uncompressed))) + + +(deftest :uncompress.1 "" "") +(deftest :uncompress.2 "test" "test") +(deftest :uncompress.3 "test2" "test2") Added: branches/trunk-reorg/thirdparty/uffi/tests/foreign-loader.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi/tests/foreign-loader.lisp Mon Feb 11 09:06:27 2008 @@ -0,0 +1,47 @@ +;;;; -*- Mode: Lisp; Syntax: ANSI-Common-Lisp; Base: 10 -*- +;;;; ************************************************************************* +;;;; FILE IDENTIFICATION +;;;; +;;;; Name: foreign-loader.lisp +;;;; Purpose: Loads foreign libraries +;;;; Author: Kevin M. Rosenberg +;;;; Date Started: Feb 2002 +;;;; +;;;; $Id$ +;;;; +;;;; This file, part of UFFI, is Copyright (c) 2002-2005 by Kevin M. Rosenberg +;;;; +;;;; ************************************************************************* + +;;; For CMUCL, it's necessary to load foreign files separate from their +;;; usage + +(in-package uffi-tests) + +#+clisp (uffi:load-foreign-library "/usr/lib/libz.so" :module "z") +#-clisp +(unless (uffi:load-foreign-library + (uffi:find-foreign-library + #-(or macosx darwin) + "libz" + #+(or macosx darwin) + "z" + (list (pathname-directory *load-pathname*) + "/usr/local/lib/" #+(or 64bit x86-64) "/usr/lib64/" + "/usr/lib/" "/zlib/")) + :module "zlib" + :supporting-libraries '("c")) + (warn "Unable to load zlib")) + +#+clisp (uffi:load-foreign-library "/home/kevin/debian/src/uffi/tests/uffi-c-test.so" :module "uffi_tests") +#-clisp +(unless (uffi:load-foreign-library + (uffi:find-foreign-library + '(#+(or 64bit x86-64) "uffi-c-test64" "uffi-c-test") + (list (pathname-directory *load-truename*) + "/usr/lib/uffi/" + "/home/kevin/debian/src/uffi/tests/")) + :supporting-libraries '("c") + :module "uffi_tests") + (warn "Unable to load uffi-c-test library")) + Added: branches/trunk-reorg/thirdparty/uffi/tests/foreign-var.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi/tests/foreign-var.lisp Mon Feb 11 09:06:27 2008 @@ -0,0 +1,88 @@ +;;;; -*- Mode: Lisp; Syntax: ANSI-Common-Lisp; Base: 10 -*- +;;;; ************************************************************************* +;;;; FILE IDENTIFICATION +;;;; +;;;; Name: foreign-var +;;;; Purpose: Tests of foreign variables +;;;; Authors: Kevin M. Rosenberg and Edi Weitz +;;;; Date Started: Aug 2003 +;;;; +;;;; $Id$ +;;;; +;;;; This file, part of UFFI, is Copyright (c) 2003-2005 by Kevin M. Rosenberg +;;; +;;;; ************************************************************************* + +(in-package #:uffi-tests) + +(def-foreign-var "uchar_13" :unsigned-byte "uffi_tests") +(def-foreign-var "schar_neg_120" :byte "uffi_tests") +(def-foreign-var "uword_257" :unsigned-short "uffi_tests") +(def-foreign-var "sword_neg_321" :short "uffi_tests") +(def-foreign-var "uint_1234567" :int "uffi_tests") +(def-foreign-var "sint_neg_123456" :int "uffi_tests") +(def-foreign-var "float_neg_4_5" :float "uffi_tests") +(def-foreign-var "double_3_1" :double "uffi_tests") + +(deftest :fvar.1 uchar-13 13) +(deftest :fvar.2 schar-neg-120 -120) +(deftest :fvar.3 uword-257 257) +(deftest :fvar.4 sword-neg-321 -321) +(deftest :fvar.5 uint-1234567 1234567) +(deftest :fvar.6 sint-neg-123456 -123456) +(deftest :fvar.7 float-neg-4-5 -4.5f0) +(deftest :fvar.8 double-3-1 3.1d0) + +(uffi:def-foreign-var ("fvar_addend" *fvar-addend*) :int "uffi_tests") + +(uffi:def-struct fvar-struct + (i :int) + (d :double)) + +(uffi:def-foreign-var ("fvar_struct" *fvar-struct*) fvar-struct + "uffi_tests") + +(uffi:def-function ("fvar_struct_int" fvar-struct-int) + () + :returning :int + :module "uffi_tests") + + (uffi:def-function ("fvar_struct_double" fvar-struct-double) + () + :returning :double + :module "uffi_tests") + +(deftest :fvarst.1 *fvar-addend* 3) +(deftest :fvarst.2 (uffi:get-slot-value *fvar-struct* 'fvar-struct 'i) 42) +(deftest :fvarst.3 (= (+ *fvar-addend* + (uffi:get-slot-value *fvar-struct* 'fvar-struct 'i)) + (fvar-struct-int)) + t) +(deftest :fvarst.4 (uffi:get-slot-value *fvar-struct* 'fvar-struct 'd) 3.2d0) +(deftest :fvarst.5 (= (uffi:get-slot-value *fvar-struct* 'fvar-struct 'd) + (fvar-struct-double)) + t) + +(deftest fvarst.6 + (let ((orig *fvar-addend*)) + (incf *fvar-addend* 3) + (prog1 + *fvar-addend* + (setf *fvar-addend* orig))) + 6) + +(deftest fvarst.7 + (let ((orig *fvar-addend*)) + (incf *fvar-addend* 3) + (prog1 + (fvar-struct-int) + (setf *fvar-addend* orig))) + 48) + +(deftest fvarst.8 + (let ((orig (uffi:get-slot-value *fvar-struct* 'fvar-struct 'i))) + (decf (uffi:get-slot-value *fvar-struct* 'fvar-struct 'i) 10) + (prog1 + (fvar-struct-int) + (setf (uffi:get-slot-value *fvar-struct* 'fvar-struct 'i) orig))) + 35) Added: branches/trunk-reorg/thirdparty/uffi/tests/getenv.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi/tests/getenv.lisp Mon Feb 11 09:06:27 2008 @@ -0,0 +1,64 @@ +;;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Base: 10 -*- +;;;; ************************************************************************* +;;;; FILE IDENTIFICATION +;;;; +;;;; Name: getenv.lisp +;;;; Purpose: UFFI Example file to get environment variable +;;;; Programmer: Kevin M. Rosenberg +;;;; Date Started: Feb 2002 +;;;; +;;;; $Id$ +;;;; +;;;; This file, part of UFFI, is Copyright (c) 2002-2005 by Kevin M. Rosenberg +;;;; +;;;; ************************************************************************* + +(in-package #:uffi-tests) + + +(uffi:def-function ("getenv" c-getenv) + ((name :cstring)) + :returning :cstring) + +(uffi:def-function ("setenv" c-setenv) + ((name :cstring) + (value :cstring) + (overwrite :int)) + :returning :int) + +(uffi:def-function ("unsetenv" c-unsetenv) + ((name :cstring)) + :returning :void) + +(defun my-getenv (key) + "Returns an environment variable, or NIL if it does not exist" + (check-type key string) + (uffi:with-cstring (key-native key) + (uffi:convert-from-cstring (c-getenv key-native)))) + +(defun my-setenv (key name &optional (overwrite t)) + "Returns an environment variable, or NIL if it does not exist" + (check-type key string) + (check-type name string) + (setq overwrite (if overwrite 1 0)) + (uffi:with-cstrings ((key-native key) + (name-native name)) + (c-setenv key-native name-native (if overwrite 1 0)))) + +(defun my-unsetenv (key) + "Returns an environment variable, or NIL if it does not exist" + (check-type key string) + (uffi:with-cstrings ((key-native key)) + (c-unsetenv key-native))) + +(deftest :getenv.1 (progn + (my-unsetenv "__UFFI_FOO1__") + (my-getenv "__UFFI_FOO1__")) + nil) +(deftest :getenv.2 (progn + (my-setenv "__UFFI_FOO1__" "UFFI-TEST") + (my-getenv "__UFFI_FOO1__")) + "UFFI-TEST") + + + Added: branches/trunk-reorg/thirdparty/uffi/tests/gethostname.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi/tests/gethostname.lisp Mon Feb 11 09:06:27 2008 @@ -0,0 +1,52 @@ +;;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Base: 10 -*- +;;;; ************************************************************************* +;;;; FILE IDENTIFICATION +;;;; +;;;; Name: gethostname.lisp +;;;; Purpose: UFFI Example file to get hostname of system +;;;; Programmer: Kevin M. Rosenberg +;;;; Date Started: Feb 2002 +;;;; +;;;; $Id$ +;;;; +;;;; This file, part of UFFI, is Copyright (c) 2002-2005 by Kevin M. Rosenberg +;;;; +;;;; ************************************************************************* + +(in-package #:uffi-tests) + + +;;; This example is inspired by the example on the CL-Cookbook web site + +(eval-when (:compile-toplevel :load-toplevel :execute) + (uffi:def-function ("gethostname" c-gethostname) + ((name (* :unsigned-char)) + (len :int)) + :returning :int) + + (defun gethostname () + "Returns the hostname" + (let* ((name (uffi:allocate-foreign-string 256)) + (result-code (c-gethostname name 256)) + (hostname (when (zerop result-code) + (uffi:convert-from-foreign-string name)))) + (uffi:free-foreign-object name) + (unless (zerop result-code) + (error "gethostname() failed.")) + hostname)) + + (defun gethostname2 () + "Returns the hostname" + (uffi:with-foreign-object (name '(:array :unsigned-char 256)) + (if (zerop (c-gethostname (uffi:char-array-to-pointer name) 256)) + (uffi:convert-from-foreign-string name) + (error "gethostname() failed."))))) + +(deftest :gethostname.1 (stringp (gethostname)) t) +(deftest :gethostname.2 (stringp (gethostname2)) t) +(deftest :gethostname.3 (plusp (length (gethostname))) t) +(deftest :gethostname.4 (plusp (length (gethostname2))) t) +(deftest :gethostname.5 (string= (gethostname) (gethostname2)) t) + + + Added: branches/trunk-reorg/thirdparty/uffi/tests/make.sh ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi/tests/make.sh Mon Feb 11 09:06:27 2008 @@ -0,0 +1,45 @@ +#!/bin/sh + +case "`uname`" in + Linux) os_linux=1 ;; + FreeBSD) os_freebsd=1 ;; + GNU/kFreeBSD) os_gnukfreebsd=1;; + Darwin) os_darwin=1 ;; + SunOS) os_sunos=1 ;; + AIX) os_aix=1 ;; + GNU) os_gnu=1 ;; + *) echo "Unable to identify uname " `uname` + exit 1 ;; +esac + +if [ "$os_linux" ]; then + gcc -fPIC -DPIC -c $SOURCE -o $OBJECT + gcc -shared $OBJECT -o $SHARED_LIB + +elif [ "$os_gnu" ]; then + gcc -fPIC -DPIC -c $SOURCE -o $OBJECT + gcc -shared $OBJECT -o $SHARED_LIB + +elif [ "$os_freebsd" ]; then + gcc -fPIC -DPIC -c $SOURCE -o $OBJECT + gcc -shared $OBJECT -o $SHARED_LIB + +elif [ "$os_gnukfreebsd" ]; then + gcc -fPIC -DPIC -c $SOURCE -o $OBJECT + gcc -shared $OBJECT -o $SHARED_LIB + +elif [ "$os_darwin" ]; then + cc -dynamic -c $SOURCE -o $OBJECT + ld -bundle /usr/lib/bundle1.o -flat_namespace -undefined suppress -o $BASE.dylib $OBJECT + ld -bundle /usr/lib/bundle1.o -flat_namespace -undefined suppress /usr/lib/libz.dylib -o z.dylib + +elif [ "$os_sunos" ]; then + cc -KPIC -c $SOURCE -o $OBJECT + cc -G $OBJECT -o $SHARED_LIB + +elif [ "$os_aix" ]; then + gcc -c -D_BSD -D_NO_PROTO -D_NONSTD_TYPES -D_MBI=void $SOURCE + make_shared -o $SHARED_LIB $OBJECT +fi + +exit 0 Added: branches/trunk-reorg/thirdparty/uffi/tests/objects.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi/tests/objects.lisp Mon Feb 11 09:06:27 2008 @@ -0,0 +1,70 @@ +;;;; -*- Mode: Lisp; Syntax: ANSI-Common-Lisp; Base: 10 -*- +;;;; ************************************************************************* +;;;; FILE IDENTIFICATION +;;;; +;;;; Name: pointers.lisp +;;;; Purpose: Test file for UFFI pointers +;;;; Programmer: Kevin M. Rosenberg +;;;; Date Started: Aug 2003 +;;;; +;;;; $Id$ +;;;; +;;;; This file, part of UFFI, is Copyright (c) 2003-2005 by Kevin M. Rosenberg +;;;; +;;;; ************************************************************************* + +(in-package #:uffi-tests) + +(deftest :chptr.1 + (let ((native-string "test string")) + (uffi:with-foreign-string (fs native-string) + (ensure-char-character + (deref-pointer fs :char)))) + #\t) + +(deftest :chptr.2 + (let ((native-string "test string")) + (uffi:with-foreign-string (fs native-string) + (ensure-char-character + (deref-pointer fs :unsigned-char)))) + #\t) + +(deftest :chptr.3 + (let ((native-string "test string")) + (uffi:with-foreign-string (fs native-string) + (ensure-char-integer + (deref-pointer fs :unsigned-char)))) + 116) + +(deftest :chptr.4 + (let ((native-string "test string")) + (uffi:with-foreign-string (fs native-string) + (integerp + (ensure-char-integer + (deref-pointer fs :unsigned-char))))) + t) + +(deftest :chptr.5 + (let ((fs (uffi:allocate-foreign-object :unsigned-char 128))) + (setf (uffi:deref-array fs '(:array :unsigned-char) 0) + (uffi:ensure-char-storable #\a)) + (setf (uffi:deref-array fs '(:array :unsigned-char) 1) + (uffi:ensure-char-storable (code-char 0))) + (uffi:convert-from-foreign-string fs)) + "a") + +;; This produces an array which needs fli:foreign-aref to access +;; rather than fli:dereference + +#-lispworks +(deftest :chptr.6 + (uffi:with-foreign-object (fs '(:array :unsigned-char 128)) + (setf (uffi:deref-array fs '(:array :unsigned-char) 0) + (uffi:ensure-char-storable #\a)) + (setf (uffi:deref-array fs '(:array :unsigned-char) 1) + (uffi:ensure-char-storable (code-char 0))) + (uffi:convert-from-foreign-string fs)) + "a") + + + Added: branches/trunk-reorg/thirdparty/uffi/tests/package.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi/tests/package.lisp Mon Feb 11 09:06:27 2008 @@ -0,0 +1,20 @@ +;;;; -*- Mode: Lisp; Syntax: ANSI-Common-Lisp; Base: 10 -*- +;;;; ************************************************************************* +;;;; FILE IDENTIFICATION +;;;; +;;;; Name: package.lisp +;;;; Purpose: Package file uffi testing suite +;;;; Author: Kevin M. Rosenberg +;;;; Date Started: Apr 2003 +;;;; +;;;; This file, part of UFFI, is Copyright (c) 2003-2005 by Kevin M. Rosenberg +;;;; +;;;; $Id$ +;;;; ************************************************************************* + +(defpackage #:uffi-tests + (:use #:asdf #:cl #:uffi #:rtest) + (:shadowing-import-from #:uffi #:run-shell-command)) + +(in-package #:uffi-tests) + Added: branches/trunk-reorg/thirdparty/uffi/tests/rt.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi/tests/rt.lisp Mon Feb 11 09:06:27 2008 @@ -0,0 +1,254 @@ +#|----------------------------------------------------------------------------| + | Copyright 1990 by the Massachusetts Institute of Technology, Cambridge MA. | + | | + | Permission to use, copy, modify, and distribute this software and its | + | documentation for any purpose and without fee is hereby granted, provided | + | that this copyright and permission notice appear in all copies and | + | supporting documentation, and that the name of M.I.T. not be used in | + | advertising or publicity pertaining to distribution of the software | + | without specific, written prior permission. M.I.T. makes no | + | representations about the suitability of this software for any purpose. | + | It is provided "as is" without express or implied warranty. | + | | + | M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING | + | ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL | + | M.I.T. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR | + | ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, | + | WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, | + | ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS | + | SOFTWARE. | + |----------------------------------------------------------------------------|# + +(defpackage #:regression-test + (:nicknames #:rtest #-lispworks #:rt) + (:use #:cl) + (:export #:*do-tests-when-defined* #:*test* #:continue-testing + #:deftest #:do-test #:do-tests #:get-test #:pending-tests + #:rem-all-tests #:rem-test) + (:documentation "The MIT regression tester with pfdietz's modifications")) + +(in-package :regression-test) + +(defvar *test* nil "Current test name") +(defvar *do-tests-when-defined* nil) +(defvar *entries* '(nil) "Test database") +(defvar *in-test* nil "Used by TEST") +(defvar *debug* nil "For debugging") +(defvar *catch-errors* t + "When true, causes errors in a test to be caught.") +(defvar *print-circle-on-failure* nil + "Failure reports are printed with *PRINT-CIRCLE* bound to this value.") +(defvar *compile-tests* nil + "When true, compile the tests before running them.") +(defvar *optimization-settings* '((safety 3))) +(defvar *expected-failures* nil + "A list of test names that are expected to fail.") + +(defstruct (entry (:conc-name nil) + (:type list)) + pend name form) + +(defmacro vals (entry) `(cdddr ,entry)) + +(defmacro defn (entry) `(cdr ,entry)) + +(defun pending-tests () + (do ((l (cdr *entries*) (cdr l)) + (r nil)) + ((null l) (nreverse r)) + (when (pend (car l)) + (push (name (car l)) r)))) + +(defun rem-all-tests () + (setq *entries* (list nil)) + nil) + +(defun rem-test (&optional (name *test*)) + (do ((l *entries* (cdr l))) + ((null (cdr l)) nil) + (when (equal (name (cadr l)) name) + (setf (cdr l) (cddr l)) + (return name)))) + +(defun get-test (&optional (name *test*)) + (defn (get-entry name))) + +(defun get-entry (name) + (let ((entry (find name (cdr *entries*) + :key #'name + :test #'equal))) + (when (null entry) + (report-error t + "~%No test with name ~:@(~S~)." + name)) + entry)) + +(defmacro deftest (name form &rest values) + `(add-entry '(t ,name ,form .,values))) + +(defun add-entry (entry) + (setq entry (copy-list entry)) + (do ((l *entries* (cdr l))) (nil) + (when (null (cdr l)) + (setf (cdr l) (list entry)) + (return nil)) + (when (equal (name (cadr l)) + (name entry)) + (setf (cadr l) entry) + (report-error nil + "Redefining test ~:@(~S~)" + (name entry)) + (return nil))) + (when *do-tests-when-defined* + (do-entry entry)) + (setq *test* (name entry))) + +(defun report-error (error? &rest args) + (cond (*debug* + (apply #'format t args) + (if error? (throw '*debug* nil))) + (error? (apply #'error args)) + (t (apply #'warn args)))) + +(defun do-test (&optional (name *test*)) + (do-entry (get-entry name))) + +(defun equalp-with-case (x y) + "Like EQUALP, but doesn't do case conversion of characters." + (cond + ((eq x y) t) + ((consp x) + (and (consp y) + (equalp-with-case (car x) (car y)) + (equalp-with-case (cdr x) (cdr y)))) + ((and (typep x 'array) + (= (array-rank x) 0)) + (equalp-with-case (aref x) (aref y))) + ((typep x 'vector) + (and (typep y 'vector) + (let ((x-len (length x)) + (y-len (length y))) + (and (eql x-len y-len) + (loop + for e1 across x + for e2 across y + always (equalp-with-case e1 e2)))))) + ((and (typep x 'array) + (typep y 'array) + (not (equal (array-dimensions x) + (array-dimensions y)))) + nil) + ((typep x 'array) + (and (typep y 'array) + (let ((size (array-total-size x))) + (loop for i from 0 below size + always (equalp-with-case (row-major-aref x i) + (row-major-aref y i)))))) + (t (eql x y)))) + +(defun do-entry (entry &optional + (s *standard-output*)) + (catch '*in-test* + (setq *test* (name entry)) + (setf (pend entry) t) + (let* ((*in-test* t) + ;; (*break-on-warnings* t) + (aborted nil) + r) + ;; (declare (special *break-on-warnings*)) + + (block aborted + (setf r + (flet ((%do + () + (if *compile-tests* + (multiple-value-list + (funcall (compile + nil + `(lambda () + (declare + (optimize ,@*optimization-settings*)) + ,(form entry))))) + (multiple-value-list + (eval (form entry)))))) + (if *catch-errors* + (handler-bind + ((style-warning #'muffle-warning) + (error #'(lambda (c) + (setf aborted t) + (setf r (list c)) + (return-from aborted nil)))) + (%do)) + (%do))))) + + (setf (pend entry) + (or aborted + (not (equalp-with-case r (vals entry))))) + + (when (pend entry) + (let ((*print-circle* *print-circle-on-failure*)) + (format s "~&Test ~:@(~S~) failed~ + ~%Form: ~S~ + ~%Expected value~P: ~ + ~{~S~^~%~17t~}~%" + *test* (form entry) + (length (vals entry)) + (vals entry)) + (format s "Actual value~P: ~ + ~{~S~^~%~15t~}.~%" + (length r) r))))) + (when (not (pend entry)) *test*)) + +(defun continue-testing () + (if *in-test* + (throw '*in-test* nil) + (do-entries *standard-output*))) + +(defun do-tests (&optional + (out *standard-output*)) + (dolist (entry (cdr *entries*)) + (setf (pend entry) t)) + (if (streamp out) + (do-entries out) + (with-open-file + (stream out :direction :output) + (do-entries stream)))) + +(defun do-entries (s) + (format s "~&Doing ~A pending test~:P ~ + of ~A tests total.~%" + (count t (cdr *entries*) + :key #'pend) + (length (cdr *entries*))) + (dolist (entry (cdr *entries*)) + (when (pend entry) + (format s "~@[~<~%~:; ~:@(~S~)~>~]" + (do-entry entry s)))) + (let ((pending (pending-tests)) + (expected-table (make-hash-table :test #'equal))) + (dolist (ex *expected-failures*) + (setf (gethash ex expected-table) t)) + (let ((new-failures + (loop for pend in pending + unless (gethash pend expected-table) + collect pend))) + (if (null pending) + (format s "~&No tests failed.") + (progn + (format s "~&~A out of ~A ~ + total tests failed: ~ + ~:@(~{~<~% ~1:;~S~>~ + ~^, ~}~)." + (length pending) + (length (cdr *entries*)) + pending) + (if (null new-failures) + (format s "~&No unexpected failures.") + (when *expected-failures* + (format s "~&~A unexpected failures: ~ + ~:@(~{~<~% ~1:;~S~>~ + ~^, ~}~)." + (length new-failures) + new-failures))) + )) + (null pending)))) Added: branches/trunk-reorg/thirdparty/uffi/tests/strtol.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi/tests/strtol.lisp Mon Feb 11 09:06:27 2008 @@ -0,0 +1,64 @@ +;;;; -*- Mode: Lisp; Syntax: ANSI-Common-Lisp; Base: 10 -*- +;;;; ************************************************************************* +;;;; FILE IDENTIFICATION +;;;; +;;;; Name: strtol.lisp +;;;; Purpose: UFFI Example file to strtol, uses pointer arithmetic +;;;; Programmer: Kevin M. Rosenberg +;;;; Date Started: Feb 2002 +;;;; +;;;; $Id$ +;;;; +;;;; This file, part of UFFI, is Copyright (c) 2002-2005 by Kevin M. Rosenberg +;;;; +;;;; ************************************************************************* + +(in-package #:uffi-tests) + +(uffi:def-foreign-type char-ptr (* :unsigned-char)) + +;; This example does not use :cstring to pass the input string since +;; the routine needs to do pointer arithmetic to see how many characters +;; were parsed + +(uffi:def-function ("strtol" c-strtol) + ((nptr char-ptr) + (endptr (* char-ptr)) + (base :int)) + :returning :long) + +(defun strtol (str &optional (base 10)) + "Returns a long int from a string. Returns number and condition flag. +Condition flag is T if all of string parses as a long, NIL if +their was no string at all, or an integer indicating position in string +of first non-valid character" + (let* ((str-native (uffi:convert-to-foreign-string str)) + (endptr (uffi:allocate-foreign-object 'char-ptr)) + (value (c-strtol str-native endptr base)) + (endptr-value (uffi:deref-pointer endptr 'char-ptr))) + + (unwind-protect + (if (uffi:null-pointer-p endptr-value) + (values value t) + (let ((next-char-value (uffi:deref-pointer endptr-value :unsigned-char)) + (chars-parsed (- (uffi:pointer-address endptr-value) + (uffi:pointer-address str-native)))) + (cond + ((zerop chars-parsed) + (values nil nil)) + ((uffi:null-char-p next-char-value) + (values value t)) + (t + (values value chars-parsed))))) + (progn + (uffi:free-foreign-object str-native) + (uffi:free-foreign-object endptr))))) + +(deftest :strtol.1 (strtol "123") 123 t) +(deftest :strtol.2 (strtol "0") 0 t) +(deftest :strtol.3 (strtol "55a") 55 2) +(deftest :strtol.4 (strtol "a") nil nil) + + + + Added: branches/trunk-reorg/thirdparty/uffi/tests/structs.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi/tests/structs.lisp Mon Feb 11 09:06:27 2008 @@ -0,0 +1,36 @@ +;;;; -*- Mode: Lisp; Syntax: ANSI-Common-Lisp; Base: 10 -*- +;;;; ************************************************************************* +;;;; FILE IDENTIFICATION +;;;; +;;;; Name: structs.lisp +;;;; Purpose: Test file for UFFI structures +;;;; Programmer: Kevin M. Rosenberg +;;;; Date Started: Feb 2002 +;;;; +;;;; $Id$ +;;;; +;;;; This file, part of UFFI, is Copyright (c) 2002-2005 by Kevin M. Rosenberg +;;;; +;;;; ************************************************************************* + +(in-package #:uffi-tests) + +;; Compilation failure as reported by Edi Weitz + + +(uffi:def-struct foo + (bar :pointer-self)) + +(uffi:def-foreign-type foo-ptr (* foo)) + +;; tests that compilation worked +(deftest :structs.1 + (with-foreign-object (p 'foo) + t) + t) + +(deftest :structs.2 + (progn + (uffi:def-foreign-type foo-struct (:struct foo)) + t) + t) Added: branches/trunk-reorg/thirdparty/uffi/tests/time.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi/tests/time.lisp Mon Feb 11 09:06:27 2008 @@ -0,0 +1,110 @@ +;;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Base: 10 -*- +;;;; ************************************************************************* +;;;; FILE IDENTIFICATION +;;;; +;;;; Name: time.lisp +;;;; Purpose: UFFI test file, time, use C structures +;;;; Author: Kevin M. Rosenberg +;;;; Date Started: Feb 2002 +;;;; +;;;; $Id$ +;;;; +;;;; This file, part of UFFI, is Copyright (c) 2002-2005 by Kevin M. Rosenberg +;;;; +;;;; ************************************************************************* + +(in-package #:uffi-tests) + +(uffi:def-foreign-type time-t :unsigned-long) + +(uffi:def-struct tm + (sec :int) + (min :int) + (hour :int) + (mday :int) + (mon :int) + (year :int) + (wday :int) + (yday :int) + (isdst :int) + ;; gmoffset present on SusE SLES9 + (gmoffset :long)) + +(uffi:def-function ("time" c-time) + ((time (* time-t))) + :returning time-t) + +(uffi:def-function "gmtime" + ((time (* time-t))) + :returning (:struct-pointer tm)) + +(uffi:def-function "asctime" + ((time (:struct-pointer tm))) + :returning :cstring) + +(uffi:def-type time-t :unsigned-long) +(uffi:def-type tm-pointer (:struct-pointer tm)) + +(deftest :time.1 + (uffi:with-foreign-object (time 'time-t) + (setf (uffi:deref-pointer time :unsigned-long) 7381) + (uffi:deref-pointer time :unsigned-long)) + 7381) + +(deftest :time.2 + (uffi:with-foreign-object (time 'time-t) + (setf (uffi:deref-pointer time :unsigned-long) 7381) + (let ((tm-ptr (the tm-pointer (gmtime time)))) + (values (1+ (uffi:get-slot-value tm-ptr 'tm 'mon)) + (uffi:get-slot-value tm-ptr 'tm 'mday) + (+ 1900 (uffi:get-slot-value tm-ptr 'tm 'year)) + (uffi:get-slot-value tm-ptr 'tm 'hour) + (uffi:get-slot-value tm-ptr 'tm 'min) + (uffi:get-slot-value tm-ptr 'tm 'sec) + ))) + 1 1 1970 2 3 1) + + +(uffi:def-struct timeval + (secs :long) + (usecs :long)) + +(uffi:def-struct timezone + (minutes-west :int) + (dsttime :int)) + +(uffi:def-function ("gettimeofday" c-gettimeofday) + ((tv (* timeval)) + (tz (* timezone))) + :returning :int) + +(defun get-utime () + (uffi:with-foreign-object (tv 'timeval) + (let ((res (c-gettimeofday tv (uffi:make-null-pointer 'timezone)))) + (values + (+ (* 1000000 (uffi:get-slot-value tv 'timeval 'secs)) + (uffi:get-slot-value tv 'timeval 'usecs)) + res)))) + +(deftest :timeofday.1 + (multiple-value-bind (t1 res1) (get-utime) + (multiple-value-bind (t2 res2) (get-utime) + (and (or (= t2 t1) (> t2 t1)) + (> t1 1000000000) + (> t2 1000000000) + (zerop res1) + (zerop res2)))) + t) + +(defun posix-time-to-asctime (secs) + "Converts number of seconds elapsed since 00:00:00 on January 1, 1970, Coordinated Universal Time (UTC)" + (string-right-trim + '(#\newline #\return) + (uffi:convert-from-cstring + (uffi:with-foreign-object (time 'time-t) + (setf (uffi:deref-pointer time :unsigned-long) secs) + (asctime (gmtime time)))))) + +(deftest :time.3 + (posix-time-to-asctime 0) + "Thu Jan 1 00:00:00 1970") Added: branches/trunk-reorg/thirdparty/uffi/tests/uffi-c-test-lib.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi/tests/uffi-c-test-lib.lisp Mon Feb 11 09:06:27 2008 @@ -0,0 +1,98 @@ +;;;; -*- Mode: Lisp; Syntax: ANSI-Common-Lisp; Base: 10 -*- +;;;; ************************************************************************* +;;;; FILE IDENTIFICATION +;;;; +;;;; Name: uffi-c-test-lib.lisp +;;;; Purpose: UFFI Example file for zlib compression +;;;; Programmer: Kevin M. Rosenberg +;;;; Date Started: Mar 2002 +;;;; +;;;; $Id$ +;;;; +;;;; This file, part of UFFI, is Copyright (c) 2002-2005 by Kevin M. Rosenberg +;;;; +;;;; ************************************************************************* + +(in-package #:uffi-tests) + + +(uffi:def-function ("cs_to_upper" cs-to-upper) + ((input (* :unsigned-char))) + :returning :void + :module "uffi_tests") + +(defun string-to-upper (str) + (uffi:with-foreign-string (str-foreign str) + (cs-to-upper str-foreign) + (uffi:convert-from-foreign-string str-foreign))) + +(uffi:def-function ("cs_count_upper" cs-count-upper) + ((input :cstring)) + :returning :int + :module "uffi_tests") + +(defun string-count-upper (str) + (uffi:with-cstring (str-cstring str) + (cs-count-upper str-cstring))) + +(uffi:def-function ("half_double_vector" half-double-vector) + ((size :int) + (vec (* :double))) + :returning :void + :module "uffi_tests") + +(uffi:def-function ("return_long_negative_one" return-long-negative-one) + () + :returning :long + :module "uffi_tests") + +(uffi:def-function ("return_int_negative_one" return-int-negative-one) + () + :returning :int + :module "uffi_tests") + +(uffi:def-function ("return_short_negative_one" return-short-negative-one) + () + :returning :short + :module "uffi_tests") + + +(uffi:def-constant +double-vec-length+ 10) +(defun test-half-double-vector () + (let ((vec (uffi:allocate-foreign-object :double +double-vec-length+)) + results) + (dotimes (i +double-vec-length+) + (setf (uffi:deref-array vec '(:array :double) i) + (coerce i 'double-float))) + (half-double-vector +double-vec-length+ vec) + (dotimes (i +double-vec-length+) + (push (uffi:deref-array vec '(:array :double) i) results)) + (uffi:free-foreign-object vec) + (nreverse results))) + +(defun t2 () + (let ((vec (make-array +double-vec-length+ :element-type 'double-float))) + (dotimes (i +double-vec-length+) + (setf (aref vec i) (coerce i 'double-float))) + (half-double-vector +double-vec-length+ vec) + vec)) + +#+(or cmu scl) +(defun t3 () + (let ((vec (make-array +double-vec-length+ :element-type 'double-float))) + (dotimes (i +double-vec-length+) + (setf (aref vec i) (coerce i 'double-float))) + (system:without-gcing + (half-double-vector +double-vec-length+ (system:vector-sap vec))) + vec)) + +(deftest :c-test.1 (string-to-upper "this is a test") "THIS IS A TEST") +(deftest :c-test.2 (string-to-upper nil) nil) +(deftest :c-test.3 (string-count-upper "This is a Test") 2) +(deftest :c-test.4 (string-count-upper nil) -1) +(deftest :c-test.5 (test-half-double-vector) + (0.0d0 0.5d0 1.0d0 1.5d0 2.0d0 2.5d0 3.0d0 3.5d0 4.0d0 4.5d0)) +(deftest :c-test.6 (return-long-negative-one) -1) +(deftest :c-test.7 (return-int-negative-one) -1) +(deftest :c-test.8 (return-short-negative-one) -1) + Added: branches/trunk-reorg/thirdparty/uffi/tests/uffi-c-test.c ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi/tests/uffi-c-test.c Mon Feb 11 09:06:27 2008 @@ -0,0 +1,158 @@ +/*************************************************************************** + * FILE IDENTIFICATION + * + * Name: c-test-fns.c + * Purpose: Test functions in C for UFFI library + * Programer: Kevin M. Rosenberg + * Date Started: Mar 2002 + * + * CVS Id: $Id$ + * + * This file, part of UFFI, is Copyright (c) 2002-2005 by Kevin M. Rosenberg + * + * These variables are correct for GCC + * you'll need to modify these for other compilers + ***************************************************************************/ + +#ifdef WIN32 +#include + +BOOL WINAPI DllEntryPoint(HINSTANCE hinstdll, + DWORD fdwReason, + LPVOID lpvReserved) +{ + return 1; +} + +#define DLLEXPORT __declspec(dllexport) + +#else +#define DLLEXPORT +#endif + +#include +#include +#include + + +DLLEXPORT unsigned char uchar_13 = 13; +DLLEXPORT signed char schar_neg_120 = -120; +DLLEXPORT unsigned short uword_257 = 257; +DLLEXPORT signed short sword_neg_321 = -321; +DLLEXPORT unsigned int uint_1234567 = 1234567; +DLLEXPORT signed int sint_neg_123456 = -123456; +DLLEXPORT double double_3_1 = 3.1; +DLLEXPORT float float_neg_4_5 = -4.5; + +/* Test of constant input string */ +DLLEXPORT +int +cs_count_upper (char* psz) +{ + int count = 0; + + if (psz) { + while (*psz) { + if (isupper (*psz)) + ++count; + ++psz; + } + return count; + } else + return -1; +} + +/* Test of input and output of a string */ +DLLEXPORT +void +cs_to_upper (char* psz) +{ + if (psz) { + while (*psz) { + *psz = toupper (*psz); + ++psz; + } + } +} + +/* Test of an output only string */ +DLLEXPORT +void +cs_make_random (int size, char* buffer) +{ + int i; + for (i = 0; i < size; i++) + buffer[i] = 'A' + (rand() % 26); +} + + +/* Test of input/output vector */ +DLLEXPORT +void +half_double_vector (int size, double* vec) +{ + int i; + for (i = 0; i < size; i++) + vec[i] /= 2.; +} + + + +DLLEXPORT +void * +cast_test_int () { + int *x = (int *) malloc(sizeof(int)); + *x = 23; + return x; +} + +DLLEXPORT +void * +cast_test_float () +{ + double *y = (double *) malloc(sizeof(double)); + *y = 3.21; + return y; +} + +DLLEXPORT +long +return_long_negative_one () +{ + return -1; +} + +DLLEXPORT +int +return_int_negative_one () +{ + return -1; +} + +DLLEXPORT +short +return_short_negative_one () +{ + return -1; +} + +DLLEXPORT int fvar_addend = 3; + +typedef struct { + int i; + double d; +} fvar_struct_type; + +fvar_struct_type fvar_struct = {42, 3.2}; + +DLLEXPORT +int fvar_struct_int () { + return (fvar_addend + fvar_struct.i); +} + +DLLEXPORT +double fvar_struct_double () { + return fvar_struct.d; +} + + Added: branches/trunk-reorg/thirdparty/uffi/tests/union.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi/tests/union.lisp Mon Feb 11 09:06:27 2008 @@ -0,0 +1,71 @@ +;;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Base: 10 -*- +;;;; ************************************************************************* +;;;; FILE IDENTIFICATION +;;;; +;;;; Name: union.lisp +;;;; Purpose: UFFI Example file to test unions +;;;; Programmer: Kevin M. Rosenberg +;;;; Date Started: Mar 2002 +;;;; +;;;; $Id$ +;;;; +;;;; This file, part of UFFI, is Copyright (c) 2002-2005 by Kevin M. Rosenberg +;;;; +;;;; ************************************************************************* + +(in-package #:uffi-tests) + +(uffi:def-union tunion1 + (char :char) + (int :int) + (uint :unsigned-int) + (sf :float) + (df :double)) + +(defvar *u* (uffi:allocate-foreign-object 'tunion1)) +(setf (uffi:get-slot-value *u* 'tunion1 'uint) + #-(or sparc sparc-v9 powerpc ppc) + (+ (* 1 (char-code #\A)) + (* 256 (char-code #\B)) + (* 65536 (char-code #\C)) + (* 16777216 128)) + #+(or sparc sparc-v9 powerpc ppc) + (+ (* 16777216 (char-code #\A)) + (* 65536 (char-code #\B)) + (* 256 (char-code #\C)) + (* 1 128))) + +(deftest :union.1 + (uffi:ensure-char-character + (uffi:get-slot-value *u* 'tunion1 'char)) + #\A) + +(deftest :union.2 + (uffi:ensure-char-integer + (uffi:get-slot-value *u* 'tunion1 'char)) + 65) + +#-(or sparc sparc-v9 openmcl digitool) +(deftest :union.3 (plusp (uffi:get-slot-value *u* 'tunion1 'uint)) t) + + +(uffi:def-union foo-u + (bar :pointer-self)) + +(uffi:def-foreign-type foo-u-ptr (* foo-u)) + +;; tests that compilation worked +(deftest :unions.4 + (with-foreign-object (p 'foo-u) + t) + t) + +(deftest :unions.5 + (progn + (uffi:def-foreign-type foo-union (:union foo-u)) + t) + t) + + + + Added: branches/trunk-reorg/thirdparty/uffi/uffi-tests.asd ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi/uffi-tests.asd Mon Feb 11 09:06:27 2008 @@ -0,0 +1,95 @@ +;;;; -*- Mode: Lisp; Syntax: ANSI-Common-Lisp; Base: 10 -*- +;;;; ************************************************************************* +;;;; FILE IDENTIFICATION +;;;; +;;;; Name: uffi-tests.asd +;;;; Purpose: ASDF system definitionf for uffi testing package +;;;; Author: Kevin M. Rosenberg +;;;; Date Started: Apr 2003 +;;;; +;;;; $Id$ +;;;; ************************************************************************* + +(defpackage #:uffi-tests-system + (:use #:asdf #:cl)) +(in-package #:uffi-tests-system) + +(operate 'load-op 'uffi) + +(defvar *library-file-dir* (append (pathname-directory *load-truename*) + (list "tests"))) + +(defclass uffi-test-source-file (c-source-file) + ()) + +(defmethod output-files ((o compile-op) (c uffi-test-source-file)) + (let* ((library-file-type + (funcall (intern (symbol-name'#:default-foreign-library-type) + (symbol-name '#:uffi)))) + (found + (some #'(lambda (dir) + (probe-file (make-pathname + :directory dir + :name (component-name c) + :type library-file-type))) + '((:absolute "usr" "lib" "uffi"))))) + (list (if found + found + (make-pathname :name (component-name c) + :type library-file-type + :directory *library-file-dir*))))) + +(defmethod perform ((o load-op) (c uffi-test-source-file)) + nil) ;;; library will be loaded by a loader file + +(defmethod operation-done-p ((o load-op) (c uffi-test-source-file)) + (and (symbol-function (intern (symbol-name '#:cs-count-upper) + (find-package '#:uffi-tests))) + t)) + +(defmethod perform ((o compile-op) (c uffi-test-source-file)) + (unless (operation-done-p o c) + #-(or win32 mswindows) + (unless (zerop (run-shell-command + #-freebsd "cd ~A; make" + #+freebsd "cd ~A; gmake" + (namestring (make-pathname :name nil + :type nil + :directory *library-file-dir*)))) + (error 'operation-error :component c :operation o)))) + +(defmethod operation-done-p ((o compile-op) (c uffi-test-source-file)) + (or (and (probe-file #p"/usr/lib/uffi/uffi-c-test.so") t) + (let ((lib (make-pathname :defaults (component-pathname c) + :type (uffi:default-foreign-library-type)))) + (and (probe-file lib) + (> (file-write-date lib) (file-write-date (component-pathname c))))))) + +(defsystem uffi-tests + :depends-on (:uffi) + :components + ((:module tests + :components + ((:file "rt") + (:file "package" :depends-on ("rt")) + (:uffi-test-source-file "uffi-c-test" :depends-on ("package")) + (:file "strtol" :depends-on ("package")) + (:file "atoifl" :depends-on ("package")) + (:file "getenv" :depends-on ("package")) + (:file "gethostname" :depends-on ("package")) + (:file "union" :depends-on ("package")) + (:file "arrays" :depends-on ("package")) + (:file "structs" :depends-on ("package")) + (:file "objects" :depends-on ("package")) + (:file "time" :depends-on ("package")) + (:file "foreign-loader" :depends-on ("package" "uffi-c-test")) + (:file "uffi-c-test-lib" :depends-on ("foreign-loader")) + (:file "compress" :depends-on ("foreign-loader")) + (:file "casts" :depends-on ("foreign-loader")) + (:file "foreign-var" :depends-on ("foreign-loader")) + )))) + +(defmethod perform ((o test-op) (c (eql (find-system :uffi-tests)))) + (or (funcall (intern (symbol-name '#:do-tests) + (find-package '#:regression-test))) + (error "test-op failed"))) Added: branches/trunk-reorg/thirdparty/uffi/uffi.asd ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi/uffi.asd Mon Feb 11 09:06:27 2008 @@ -0,0 +1,48 @@ +;;;; -*- Mode: Lisp; Syntax: ANSI-Common-Lisp; Base: 10 -*- +;;;; ************************************************************************* +;;;; FILE IDENTIFICATION +;;;; +;;;; Name: uffi.asd +;;;; Purpose: ASDF system definition file for UFFI package +;;;; Author: Kevin M. Rosenberg +;;;; Date Started: Aug 2002 +;;;; +;;;; $Id$ +;;;; +;;;; This file, part of UFFI, is Copyright (c) 2002-2005 by Kevin M. Rosenberg +;;;; +;;;; ************************************************************************* + +(defpackage #:uffi-system (:use #:asdf #:cl)) +(in-package #:uffi-system) + +#+(or allegro lispworks cmu openmcl digitool cormanlisp sbcl scl) +(defsystem uffi + :name "uffi" + :author "Kevin Rosenberg " + :version "1.2.x" + :maintainer "Kevin M. Rosenberg " + :licence "Lessor Lisp General Public License" + :description "Universal Foreign Function Library for Common Lisp" + :long-description "UFFI provides a universal foreign function interface (FFI) for Common Lisp. UFFI supports CMUCL, Lispworks, and AllegroCL." + + :components + ((:module :src + :components + ((:file "package") + (:file "primitives" :depends-on ("package")) + #+(or openmcl digitool) (:file "readmacros-mcl" :depends-on ("package")) + (:file "objects" :depends-on ("primitives")) + (:file "aggregates" :depends-on ("primitives")) + (:file "strings" :depends-on ("primitives" "functions" "aggregates" "objects")) + (:file "functions" :depends-on ("primitives")) + (:file "libraries" :depends-on ("package")) + (:file "os" :depends-on ("package")))) + )) + +#+(or allegro lispworks cmu openmcl digitool cormanlisp sbcl scl) +(defmethod perform ((o test-op) (c (eql (find-system 'uffi)))) + (oos 'load-op 'uffi-tests) + (oos 'test-op 'uffi-tests :force t)) + + From ksprotte at common-lisp.net Mon Feb 11 14:07:36 2008 From: ksprotte at common-lisp.net (ksprotte at common-lisp.net) Date: Mon, 11 Feb 2008 09:07:36 -0500 (EST) Subject: [bknr-cvs] r2471 - branches/trunk-reorg/thirdparty/cl-gd-0.5.6 Message-ID: <20080211140736.5973A5C000@common-lisp.net> Author: ksprotte Date: Mon Feb 11 09:07:36 2008 New Revision: 2471 Modified: branches/trunk-reorg/thirdparty/cl-gd-0.5.6/cl-gd.asd Log: cl-gd now always depends on uffi Modified: branches/trunk-reorg/thirdparty/cl-gd-0.5.6/cl-gd.asd ============================================================================== --- branches/trunk-reorg/thirdparty/cl-gd-0.5.6/cl-gd.asd (original) +++ branches/trunk-reorg/thirdparty/cl-gd-0.5.6/cl-gd.asd Mon Feb 11 09:07:36 2008 @@ -54,5 +54,4 @@ (:file "drawing") (:file "strings") (:file "misc")) - :depends-on (#-(or :clisp :openmcl) :uffi - #+(or :clisp :openmcl) :cffi-uffi-compat)) + :depends-on (:uffi)) From ksprotte at common-lisp.net Mon Feb 11 14:08:27 2008 From: ksprotte at common-lisp.net (ksprotte at common-lisp.net) Date: Mon, 11 Feb 2008 09:08:27 -0500 (EST) Subject: [bknr-cvs] r2472 - branches/trunk-reorg/thirdparty/cffi-070901/uffi-compat Message-ID: <20080211140827.2CD1B5F058@common-lisp.net> Author: ksprotte Date: Mon Feb 11 09:08:26 2008 New Revision: 2472 Added: branches/trunk-reorg/thirdparty/cffi-070901/uffi-compat/uffi.noasd - copied unchanged from r2469, branches/trunk-reorg/thirdparty/cffi-070901/uffi-compat/uffi.asd Removed: branches/trunk-reorg/thirdparty/cffi-070901/uffi-compat/uffi.asd Log: renamed uffi-compat/uffi.asd to uffi-compat/uffi.noasd From ksprotte at common-lisp.net Mon Feb 11 14:10:28 2008 From: ksprotte at common-lisp.net (ksprotte at common-lisp.net) Date: Mon, 11 Feb 2008 09:10:28 -0500 (EST) Subject: [bknr-cvs] r2473 - in branches/trunk-reorg/projects/bos: m2 web Message-ID: <20080211141028.C6F3C5F058@common-lisp.net> Author: ksprotte Date: Mon Feb 11 09:10:28 2008 New Revision: 2473 Modified: branches/trunk-reorg/projects/bos/m2/bos.m2.asd branches/trunk-reorg/projects/bos/web/bos.web.asd Log: changed bos dependencies (:bknr does not exist anymore) bos.m2: :bknr-datastore :bknr-modules bos.web: :bknr-web :bknr-modules Modified: branches/trunk-reorg/projects/bos/m2/bos.m2.asd ============================================================================== --- branches/trunk-reorg/projects/bos/m2/bos.m2.asd (original) +++ branches/trunk-reorg/projects/bos/m2/bos.m2.asd Mon Feb 11 09:10:28 2008 @@ -1,7 +1,7 @@ (in-package :cl-user) (asdf:defsystem :bos.m2 - :depends-on (:bknr :bknr-modules :net.post-office :cl-mime :iconv :kmrcl :iterate :arnesi) + :depends-on (:bknr-datastore :bknr-modules :cl-smtp :cl-mime :iconv :kmrcl :iterate :arnesi) :components ((:file "packages") (:file "geo-utm" :depends-on ("packages")) (:file "geometry" :depends-on ("packages")) Modified: branches/trunk-reorg/projects/bos/web/bos.web.asd ============================================================================== --- branches/trunk-reorg/projects/bos/web/bos.web.asd (original) +++ branches/trunk-reorg/projects/bos/web/bos.web.asd Mon Feb 11 09:10:28 2008 @@ -16,7 +16,7 @@ :description "worldpay test web server" :long-description "" - :depends-on (:bknr :bknr-modules :bos.m2 :cxml) + :depends-on (:bknr-web :bknr-modules :bos.m2 :cxml) :components ((:file "packages") (:file "utf-8" :depends-on ("packages")) From hhubner at common-lisp.net Mon Feb 11 14:23:20 2008 From: hhubner at common-lisp.net (hhubner at common-lisp.net) Date: Mon, 11 Feb 2008 09:23:20 -0500 (EST) Subject: [bknr-cvs] r2474 - in branches/trunk-reorg/thirdparty: cl-gd-0.5.6 uffi uffi-1.6.0 uffi-1.6.0/benchmarks uffi-1.6.0/doc uffi-1.6.0/examples uffi-1.6.0/src uffi-1.6.0/src/corman uffi-1.6.0/tests Message-ID: <20080211142320.7B15B601A8@common-lisp.net> Author: hhubner Date: Mon Feb 11 09:23:05 2008 New Revision: 2474 Added: branches/trunk-reorg/thirdparty/uffi-1.6.0/ branches/trunk-reorg/thirdparty/uffi-1.6.0/AUTHORS branches/trunk-reorg/thirdparty/uffi-1.6.0/ChangeLog branches/trunk-reorg/thirdparty/uffi-1.6.0/INSTALL branches/trunk-reorg/thirdparty/uffi-1.6.0/LICENSE branches/trunk-reorg/thirdparty/uffi-1.6.0/Makefile branches/trunk-reorg/thirdparty/uffi-1.6.0/Makefile.common branches/trunk-reorg/thirdparty/uffi-1.6.0/NEWS branches/trunk-reorg/thirdparty/uffi-1.6.0/README branches/trunk-reorg/thirdparty/uffi-1.6.0/TODO branches/trunk-reorg/thirdparty/uffi-1.6.0/benchmarks/ branches/trunk-reorg/thirdparty/uffi-1.6.0/benchmarks/Makefile branches/trunk-reorg/thirdparty/uffi-1.6.0/benchmarks/allocation.lisp branches/trunk-reorg/thirdparty/uffi-1.6.0/doc/ branches/trunk-reorg/thirdparty/uffi-1.6.0/doc/COPYING.GFDL branches/trunk-reorg/thirdparty/uffi-1.6.0/doc/Makefile branches/trunk-reorg/thirdparty/uffi-1.6.0/doc/appendix.xml branches/trunk-reorg/thirdparty/uffi-1.6.0/doc/bookinfo.xml branches/trunk-reorg/thirdparty/uffi-1.6.0/doc/catalog-darwin.xml branches/trunk-reorg/thirdparty/uffi-1.6.0/doc/catalog-debian.xml branches/trunk-reorg/thirdparty/uffi-1.6.0/doc/catalog-mandrake.xml branches/trunk-reorg/thirdparty/uffi-1.6.0/doc/catalog-suse.xml branches/trunk-reorg/thirdparty/uffi-1.6.0/doc/catalog-suse90.xml branches/trunk-reorg/thirdparty/uffi-1.6.0/doc/catalog-suse91.xml branches/trunk-reorg/thirdparty/uffi-1.6.0/doc/catalog-ubuntu.xml branches/trunk-reorg/thirdparty/uffi-1.6.0/doc/entities.inc branches/trunk-reorg/thirdparty/uffi-1.6.0/doc/fo.xsl branches/trunk-reorg/thirdparty/uffi-1.6.0/doc/glossary.xml branches/trunk-reorg/thirdparty/uffi-1.6.0/doc/html.tar.gz (contents, props changed) branches/trunk-reorg/thirdparty/uffi-1.6.0/doc/html.xsl branches/trunk-reorg/thirdparty/uffi-1.6.0/doc/html_chunk.xsl branches/trunk-reorg/thirdparty/uffi-1.6.0/doc/intro.xml branches/trunk-reorg/thirdparty/uffi-1.6.0/doc/notes.xml branches/trunk-reorg/thirdparty/uffi-1.6.0/doc/preface.xml branches/trunk-reorg/thirdparty/uffi-1.6.0/doc/ref_aggregate.xml branches/trunk-reorg/thirdparty/uffi-1.6.0/doc/ref_declare.xml branches/trunk-reorg/thirdparty/uffi-1.6.0/doc/ref_func_libr.xml branches/trunk-reorg/thirdparty/uffi-1.6.0/doc/ref_object.xml branches/trunk-reorg/thirdparty/uffi-1.6.0/doc/ref_primitive.xml branches/trunk-reorg/thirdparty/uffi-1.6.0/doc/ref_string.xml branches/trunk-reorg/thirdparty/uffi-1.6.0/doc/schemas.xml branches/trunk-reorg/thirdparty/uffi-1.6.0/doc/uffi.pdf branches/trunk-reorg/thirdparty/uffi-1.6.0/doc/uffi.xml branches/trunk-reorg/thirdparty/uffi-1.6.0/doc/xinclude.mod branches/trunk-reorg/thirdparty/uffi-1.6.0/examples/ branches/trunk-reorg/thirdparty/uffi-1.6.0/examples/Makefile branches/trunk-reorg/thirdparty/uffi-1.6.0/examples/Makefile.msvc branches/trunk-reorg/thirdparty/uffi-1.6.0/examples/acl-compat-tester.lisp branches/trunk-reorg/thirdparty/uffi-1.6.0/examples/arrays.lisp branches/trunk-reorg/thirdparty/uffi-1.6.0/examples/atoifl.lisp branches/trunk-reorg/thirdparty/uffi-1.6.0/examples/c-test-fns.c branches/trunk-reorg/thirdparty/uffi-1.6.0/examples/c-test-fns.lisp branches/trunk-reorg/thirdparty/uffi-1.6.0/examples/compress.lisp branches/trunk-reorg/thirdparty/uffi-1.6.0/examples/file-socket.lisp branches/trunk-reorg/thirdparty/uffi-1.6.0/examples/getenv.lisp branches/trunk-reorg/thirdparty/uffi-1.6.0/examples/gethostname.lisp branches/trunk-reorg/thirdparty/uffi-1.6.0/examples/getshells.lisp branches/trunk-reorg/thirdparty/uffi-1.6.0/examples/gettime.lisp branches/trunk-reorg/thirdparty/uffi-1.6.0/examples/run-examples.lisp branches/trunk-reorg/thirdparty/uffi-1.6.0/examples/strtol.lisp branches/trunk-reorg/thirdparty/uffi-1.6.0/examples/test-examples.lisp branches/trunk-reorg/thirdparty/uffi-1.6.0/examples/union.lisp branches/trunk-reorg/thirdparty/uffi-1.6.0/src/ branches/trunk-reorg/thirdparty/uffi-1.6.0/src/Makefile branches/trunk-reorg/thirdparty/uffi-1.6.0/src/aggregates.lisp branches/trunk-reorg/thirdparty/uffi-1.6.0/src/corman/ branches/trunk-reorg/thirdparty/uffi-1.6.0/src/corman/corman-notes.txt branches/trunk-reorg/thirdparty/uffi-1.6.0/src/corman/getenv-ccl.lisp branches/trunk-reorg/thirdparty/uffi-1.6.0/src/functions.lisp branches/trunk-reorg/thirdparty/uffi-1.6.0/src/libraries.lisp branches/trunk-reorg/thirdparty/uffi-1.6.0/src/objects.lisp branches/trunk-reorg/thirdparty/uffi-1.6.0/src/os.lisp branches/trunk-reorg/thirdparty/uffi-1.6.0/src/package.lisp branches/trunk-reorg/thirdparty/uffi-1.6.0/src/primitives.lisp branches/trunk-reorg/thirdparty/uffi-1.6.0/src/readmacros-mcl.lisp branches/trunk-reorg/thirdparty/uffi-1.6.0/src/strings.lisp branches/trunk-reorg/thirdparty/uffi-1.6.0/tests/ branches/trunk-reorg/thirdparty/uffi-1.6.0/tests/Makefile branches/trunk-reorg/thirdparty/uffi-1.6.0/tests/Makefile.msvc branches/trunk-reorg/thirdparty/uffi-1.6.0/tests/arrays.lisp branches/trunk-reorg/thirdparty/uffi-1.6.0/tests/atoifl.lisp branches/trunk-reorg/thirdparty/uffi-1.6.0/tests/casts.lisp branches/trunk-reorg/thirdparty/uffi-1.6.0/tests/compress.lisp branches/trunk-reorg/thirdparty/uffi-1.6.0/tests/foreign-loader.lisp branches/trunk-reorg/thirdparty/uffi-1.6.0/tests/foreign-var.lisp branches/trunk-reorg/thirdparty/uffi-1.6.0/tests/getenv.lisp branches/trunk-reorg/thirdparty/uffi-1.6.0/tests/gethostname.lisp branches/trunk-reorg/thirdparty/uffi-1.6.0/tests/make.sh branches/trunk-reorg/thirdparty/uffi-1.6.0/tests/objects.lisp branches/trunk-reorg/thirdparty/uffi-1.6.0/tests/package.lisp branches/trunk-reorg/thirdparty/uffi-1.6.0/tests/rt.lisp branches/trunk-reorg/thirdparty/uffi-1.6.0/tests/strtol.lisp branches/trunk-reorg/thirdparty/uffi-1.6.0/tests/structs.lisp branches/trunk-reorg/thirdparty/uffi-1.6.0/tests/time.lisp branches/trunk-reorg/thirdparty/uffi-1.6.0/tests/uffi-c-test-lib.lisp branches/trunk-reorg/thirdparty/uffi-1.6.0/tests/uffi-c-test.c branches/trunk-reorg/thirdparty/uffi-1.6.0/tests/union.lisp branches/trunk-reorg/thirdparty/uffi-1.6.0/uffi-tests.asd branches/trunk-reorg/thirdparty/uffi-1.6.0/uffi.asd Removed: branches/trunk-reorg/thirdparty/uffi/ Modified: branches/trunk-reorg/thirdparty/cl-gd-0.5.6/cl-gd.asd Log: switch to release uffi Modified: branches/trunk-reorg/thirdparty/cl-gd-0.5.6/cl-gd.asd ============================================================================== --- branches/trunk-reorg/thirdparty/cl-gd-0.5.6/cl-gd.asd (original) +++ branches/trunk-reorg/thirdparty/cl-gd-0.5.6/cl-gd.asd Mon Feb 11 09:23:05 2008 @@ -54,4 +54,9 @@ (:file "drawing") (:file "strings") (:file "misc")) +<<<<<<< .mine + :depends-on (#-clisp :uffi + #+clisp :cffi-uffi-compat)) +======= :depends-on (:uffi)) +>>>>>>> .r2473 Added: branches/trunk-reorg/thirdparty/uffi-1.6.0/AUTHORS ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi-1.6.0/AUTHORS Mon Feb 11 09:23:05 2008 @@ -0,0 +1,12 @@ +Kevin M. Rosenberg + Primary author + +John Desoi + Contributed MCL & OpenMCL support + +Reini Urban + Contributed initial Corman support + +Edi Weitz + Contributed with-cast-pointer and def-foreign-var along with + documentation Added: branches/trunk-reorg/thirdparty/uffi-1.6.0/ChangeLog ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi-1.6.0/ChangeLog Mon Feb 11 09:23:05 2008 @@ -0,0 +1,350 @@ +2007-07-22 Kevin Rosenberg (kevin at rosenberg.net) + * Version 1.6.0 (SPECIFICATION CHANGE) + * doc/ref_func_libr.xml: Change the specification of + load-foreign-library to better match the actual action of the + function. Rather than returning NIL for failure to load library, + signal an error. + * src/libraries.lisp: Rework load-foreign-library to ensure errors + are signaled on failure to load library. This was the case for + some implementations, change the other implementations to + match. (Inconsistency found due to Mark Wooding's remarks) + +2007-04-12 Kevin Rosenberg (kevin at rosenberg.net) + * Version 1.5.18 + * src/functions.lisp: Patch from Ian Eslick for Lispworks 5 + +2006-10-10 Kevin Rosenberg (kevin at rosenberg.net) + * Version 1.5.17 + * src/functions.lisp: Patch from Edi Weitz for Lispworks 5/Linux + +2006-09-02 Kevin Rosenberg (kevin at rosenberg.net) + * Version 1.5.16 + * src/libraries.lisp: Add cygwin support + +2006-08-13 Kevin Rosenberg (kevin at rosenberg.net) + * Version 1.5.15 + * src/{objects,strings}.lisp: Add support for Lispworks 5 + thanks to patches from Bill Atkins + +2006-07-04 Kevin Rosenberg (kevin at rosenberg.net) + * Version 1.5.14 + * src/{objects,strings}.lisp: Apply patch from Edi Weitz + +2006-05-17 Kevin Rosenberg (kevin at rosenberg.net) + * Version 1.5.13 + * src/libraries.lisp: Revert buggy patch from Yaroslav Kavenchuk. + +2006-05-17 Kevin Rosenberg (kevin at rosenberg.net) + * Version 1.5.12 + * src/libraries.lisp: Patch from Yaroslav Kavenchuk to set + default drive letters on MS Windows. + +2006-05-11 Kevin Rosenberg (kevin at rosenberg.net) + * Version 1.5.11: Export new macro DEF-POINTER-VAR based on patch from + James Bielman to support defining variables on platforms which + support saving objects, such as openmcl + +2006-04-17 Kevin Rosenberg (kevin at rosenberg.net) + * Version 1.5.10: Commit patch from Gary King for openmcl's + feature list change + +2005-11-14 Kevin Rosenberg (kevin at rosenberg.net) + * Version 1.5.7 + * src/strings.lisp: Add with-foreign-strings by James Biel + +2005-11-14 Kevin Rosenberg (kevin at rosenberg.net) + * Version 1.5.6 + * src/os.lisp: Remove getenv setter + +2005-11-07 Kevin Rosenberg (kevin at rosenberg.net) + * Version 1.5.5 + * src/os.lisp: Add support for getenv getter and setter + +2005-09-17 Kevin Rosenberg (kevin at rosenberg.net) + * Version 1.5.4 + * src/objects.lisp: prepend _ character for entry + point on Allegro macosx, patch by Luis Oliveira + +2005-07-05 Kevin Rosenberg (kevin at rosenberg.net) + * Version 1.5.0 + * Remove vestigial LLGPL license notices as UFFI as been + BSD-licensed for several years. + +2005-06-09 Kevin Rosenberg (kevin at rosenberg.net) + * Version 1.4.39 + * tests/objects.lisp: Rename from pointers.lisp. + Fix test CHPTR.4 as noted by Jorg Hohle + * src/objects.lisp: Remove default from ensure-char-integer + +2005-06-09 Kevin Rosenberg (kevin at rosenberg.net) + * Version 1.4.38 + * src/libraries.lisp: Commit patch from Edi Weitz to + allow plain filename library names to allow underlying + lisp implementation to find foreign libraries in the + locations known to the operating system. + * tests/cast.lisp: Add :module keyword as noted by Jorg Hohle. + * src/strings.lisp: Avoid multiple evaluation of input + parameters for macros as noted by Jorg Hohle. + +2005-04-12 Kevin Rosenberg (kevin at rosenberg.net) + * Version 1.4.37 + * src/strings.lisp: Fix variable name + +2005-04-04 Kevin Rosenberg (kevin at rosenberg.net) + * src/strings.lisp, src/aggregates.lisp: Support change in SBCL copy + function [Thanks for Nathan Froyd and Zach Beane] + +2005-04-03 Kevin Rosenberg (kevin at rosenberg.net) + * src/objects.lisp: Commit patch from James Bielman to add + def-foreign-var support for OpenMCL + +2005-03-03 Kevin Rosenberg (kevin at rosenberg.net) + * src/primitives.lisp: Add support for :union types + [patch from Cyrus Harmon] + * tests/union.lisp, tests/structs.lisp: Tests for + union and structure types [from Cyrus Harmon] + +2005-02-22 Kevin Rosenberg (kevin at rosenberg.net) + * src/primitives.lisp, src/strings.lisp: Better support + for sb-unicode [from Yoshinori Tahara and R. Mattes] + +2005-01-22 Kevin Rosenberg (kevin at rosenberg.net) + * src/primitives.lisp: Better support SBCL-AMD64 + +2004-11-08 Kevin Rosenberg (kevin at rosenberg.net) + * src/strings.lisp: Better support sb-unicode + * tests/compress.lisp: Support sb-unicode + +2004-10-07 Kevin Rosenberg (kevin at rosenberg.net) + * src/objects.lisp: Add new function: + convert-from-foreign-usb8 + +2004-04-15 Kevin Rosenberg (kevin at rosenberg.net) + * src/objects.lisp: Add new functions: + MAKE-POINTER and POINTER-ADDRESS + +2004-04-13 Kevin Rosenberg (kevin at rosenberg.net) + * src/string.lisp: Add new FOREIGN-STRING-LENGTH + +2003-08-15 Kevin Rosenberg (kevin at rosenberg.net) + * Added with-cast-pointer and def-foreign-var (patches submitted + by Edi Weitz). + * Added many new tests + +2002-10-16 Kevin Rosenberg (kevin at rosenberg.net) + * Added support for SBCL and SCL + +2002-09-29 Kevin Rosenberg (kevin at rosenberg.net) + * Numerous changes in openmcl support (uffi now supports + clsql on openmcl) + +2002-09-19 Kevin Rosenberg (kevin at rosenberg.net) + - Integrate John Desoi's OpenMCL support into src-mcl + * examples/Makefile: add section for building on MacOS X (John Desoi) + * examples/test-examples: changed from mk: to asdf: package loading (KMR) + * examples/run-examples: changed from mk: to asdf: package loading (KMR), + add conditional loading if UFFI not loaded (John Desoi) + * examples/compress.cl: Add dylib to library types for MacOSX (John Desoi), + converted compressed output to hexidecimal display (KMR) + * examples/union.cl: Rework the tests (KMR) + * src-main/libraries.cl: add dylib as default library type on MacOSX (John Desoi) + * src-main/aggregates.cl: convert from uffi type in deref-array (John Desoi) + +2002-09-16 Kevin Rosenberg (kevin at rosenberg.net) + - Restructure directories to move to a asdf definition file + without pathnames. + +2002-08-25 Kevin Rosenberg (kevin at rosenberg.net) + - Restructure directories to attempt to properly handle both + Common Lisp Controller and non-CLC systems + +2002-08-17 Kevin Rosenberg (kevin at rosenberg.net) + + - add uffi.asd for ASDF users + +2002-08-01 Kevin Rosenberg (kevin at rosenberg.net) + - Restructure directories to improve Common Lisp Controller v3 + compatibility + +2002-07-25 Kevin Rosenberg (kevin at rosenberg.net) + + - Rework handling of logical pathnames. + - Move run-examples.cl to examples directory. + +2002-06-28 Kevin Rosenberg (kevin at rosenberg.net) + + - Added size-of-foreign-type function. + +2002-06-26 Kevin Rosenberg (kevin at rosenberg.net) + + - Fix bug in Lispworks allocate-foreign-object + - Added new :unsigned-byte type. Made :byte signed. + +2002-04-27 Kevin Rosenberg (kevin at rosenberg.net) + - misc files + First debian version + +2002-04-23 Kevin Rosenberg (kevin at rosenberg.net) + - doc/* + Updated to debian docbook catalog + +2002-04-23 John DeSoi (desoi at mac.com) + * src/mcl/* + Improved MCL support + +2002-04-06 Kevin Rosenberg (kevin at rosenberg.net) + * src/mcl/libraries.cl: + Removed unnecessary function and added find-foreign-library + * src/mcl/*.cl: + Added authorship for John DeSoi + * doc/ref.sgml: + Added documentation for find-foreign-library + * uffi.system: + Simplied logical pathnames and MCL loading + +2002-04-04 John DeSoi (desoi at mac.com) + * src/mcl/*.cl + Added initial support for MCL + +2002-04-02 Kevin Rosenberg (kevin at rosenberg.net) + * src/libraries.cl: + Added test for .so libraries on CMUCL and use sys::load-object-file instead + of alien:load-library-file + * examples/Makefile: + Updated defaults so library is created correctly on Linux, FreeBSD, and Solaris + +2002-04-02 Kevin Rosenberg (kevin at rosenberg.net) + * examples/compress.cl: + Fixed missing '/' + * examples/union.cl: + Added support for SPARC big-endian + * test-examples.cl: + Automated testing suite + +2002-04-01 Kevin Rosenberg (kevin at rosenberg.net) + * src/libraries.cl: + * examples/Makefile: + Changed default type for FreeBSD and updated Makefile for + FreeBSD and Solaris. Enhanced find-foreign-library to + take a list of types to search. + * examples/compress.cl: + Add support to use find-foreign-library + +2002-03-31 Kevin Rosenberg (kevin at rosenberg.net) + * src/strings.cl: + Fixed bug in with-foreign-string (Thanks Harald Hanche-Olsen) + * examples/Makefile: + Create a .a library file for FreeBSD + * src/libraries.cl: + Added default type and find-foreign-library functions + +2002-03-29 Kevin Rosenberg (kevin at rosenberg.net) + * src/objects.cl: + Fixed bug in deref-pointer (Thanks John Desoi!) + +2002-03-22 Kevin Rosenberg (kevin at rosenberg.net) + * src/aggregates.cl: + Changed name and implementation of def-array to more appropriate + def-array-pointer + * src/ref.sgml: + Updated def-array-pointer documentation + * src/primitives.cl: + Made results of def-constant equal those of cl:defconstant + * src/objects.cl: + Made type be evaluated for with-foreign-object and allocate-foreign-object + * VERSION: + Increase to 0.3.0 to coincide with the release of CLSQL. + +21 Mar 2002 + * Fixed problem with NULL foreign-strings with CMUCL + * Added c-test-fns to examples for allow more specific testing + of UFFI. Builds on UNIX and Win32 platforms. + * Added def-union function, added union.cl example + * Fixed error with ensure-char-[character|integer] + * Added 2-d array example to examples/arrays.cl + * Fixed documentation error on gethostname + * Added ensure-char-* and def-union to documentation + * Added double-float vector example to c-test-fns + * Reworked cstring on Lispworks to have LW handle string conversion + * First pass at with-foreign-object -- unoptimized + * Added gethostname2 example which uses with-foreign-object + * Added char-array-to-pointer function to encapsulate + converting a char array to a char pointer + * Converted with-foreign-object to use stack allocation on CMUCL and LW + * Added benchmark code, first file is for allocation + +20 Mar 2002 + * Updated strings.cl so that foreign-strings are always unsigned. + Fixes a problem with strtol example. + * Added ensure-char-character and ensure-char-integer to handle + differences in implementations dereferencing of (* :char). + * Added section on design priorities for UFFI + * Added section in TODO on splitting implementation-dependent code + +19 Mar 2002 + * Added size parameter to allocate-foreign-object. Creates an array + of dimensions size. + * Got array-2d example working with a 1-d array. + * Cleaned strtol example + * Added TODO file + +18 Mar 2002 + * Documentation fixes (Erik Winkels) + * Fixed missing '.' in CMUCL type declarations (Erik Winkels) + +17 Mar 2002 + * Changed deref-pointer so it always returns a character when + called with a :char or :unsigned-char type + * Removed function ensure-char as no longer needed + * Added missing :byte specifier to Lispworks + * Changed default string type in Lispworks to :unsigned-char + which is the native type for Lispworks foreign-strings. + * Reworked strtol to handle new character pointing method + +16 Mar 2002 + * Fixed return value in load-foreign-library (Thanks Erik Winkels), + modified routine to accept pathnames as well as strings. + * Fix documention with :pointer-void (Again, Erik Winkels) + * Added missing type specifiers for CMUCL (Thanks a bunch, Erik!) + +15 Mar 2002 + * Finished basic skeleton of documentation. + +14 Mar 2002 + * Changed license to more liberal Lisp Lessor GNU Public License + * Fixed problem with uffi.system absent from in distribution + (Thanks John DeSoi) + * Fixed compiler warnings + + +11 Mar 2002 + * Changed def-type to def-foreign-type + * Created new macro def-type to generate cl:deftype forms. Removed + uffi-declare and uffi-slot-type as they are no longer necessary. + +10 Mar 2002 + * Modified input parameters to load-foreign-library + * Added to documention + * Changed parameter order in get-slot-value and deref-array + +9 Mar 2002 + * Added to documentation + * Made Allegro CL array access more efficient + * Changed def-routine name to def-function + * Fixed bug in def-function for Lispworks] + * Fixed error in +null-c-string-pointer+ name + * Fixed error in (make-null-pointer) for Lispworks + * Reworked Lispwork c-strings to be (* :char) rather than the + implementation default of (* (:unsigned :char)) to be consistent + with CMUCL. Bumped version to 0.2.0 because of change this change. + * Renamed c-string to cstring to emphasize it as a basic type + * Modified getenv.cl example to avoid name collison with LW + * Modified compress.cl to setup output buffer as :unsigned*char + * Added test-all-examples function. All routines tested okay with + ACL, LW, and CMUCL + +8 Mar 2002 + * Added ZIP file output with LF->CRLF translations to distribution + * Modified def-enum to use uffi:def-constant rather than + cl:defconstant + Added: branches/trunk-reorg/thirdparty/uffi-1.6.0/INSTALL ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi-1.6.0/INSTALL Mon Feb 11 09:23:05 2008 @@ -0,0 +1,3 @@ +Detailed installation instructions are supplied in PDF format +in the file ./doc/uffi.pdf. + Added: branches/trunk-reorg/thirdparty/uffi-1.6.0/LICENSE ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi-1.6.0/LICENSE Mon Feb 11 09:23:05 2008 @@ -0,0 +1,26 @@ +Copyright (c) 2001-2003 Kevin M. Rosenberg and contributors. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. Neither the name of the author nor the names of the contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +SUCH DAMAGE. Added: branches/trunk-reorg/thirdparty/uffi-1.6.0/Makefile ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi-1.6.0/Makefile Mon Feb 11 09:23:05 2008 @@ -0,0 +1,45 @@ +# FILE IDENTIFICATION +# +# Name: Makefile +# Purpose: Makefile for the uffi package +# Programer: Kevin M. Rosenberg, M.D. +# Date Started: Mar 2002 +# +# CVS Id: $Id: Makefile 10614 2005-07-06 01:05:14Z kevin $ +# +# This file, part of UFFI, is Copyright (c) 2002-2005 by Kevin M. Rosenberg + +PKG:=uffi +DEBPKG=cl-uffi +SUBDIRS:= examples src benchmarks +DOCSUBDIRS:=doc + +include Makefile.common + + +.PHONY: all +all: + + +.PHONY: distclean +distclean: clean + @$(MAKE) -C doc $@ +# ./debian/rules clean + + +SOURCE_FILES=src doc examples Makefile uffi.system uffi.debian.system \ + benchmarks COPYRIGHT README TODO INSTALL ChangeLog NEWS \ + test-examples.cl set-logical.cl + +.PHONY: doc +doc: + $(MAKE) -C doc + +.PHONY: dist +dist: clean + $(MAKE) -C doc $@ + +.PHONY: TAGS +TAGS: + if [ -f TAGS ]; then mv -f TAGS TAGS~; fi + find . -name \*.lisp -exec /usr/bin/etags -a \{\} \; Added: branches/trunk-reorg/thirdparty/uffi-1.6.0/Makefile.common ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi-1.6.0/Makefile.common Mon Feb 11 09:23:05 2008 @@ -0,0 +1,17 @@ +all: + + +.PHONY: clean +clean: + @rm -rf .bin + @rm -f *.ufsl *.fsl *.fas *.x86f *.sparcf *.fasl + @rm -f *.fasla8 *.fasla16 *.faslm8 *.faslm16 *.faslmt + @rm -f *~ *.bak *.orig *.err \#*\# .#* + @rm -f *.so *.a + @rm -rf debian/cl-uffi +ifneq ($(SUBDIRS)$(DOCSUBDIRS),) + @set -e; for i in $(SUBDIRS) $(DOCSUBDIRS); do \ + $(MAKE) -C $$i $@; done +endif + +.SUFFIXES: # No default suffixes Added: branches/trunk-reorg/thirdparty/uffi-1.6.0/NEWS ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi-1.6.0/NEWS Mon Feb 11 09:23:05 2008 @@ -0,0 +1 @@ +UFFI now supports AllegroCL AMD64 Added: branches/trunk-reorg/thirdparty/uffi-1.6.0/README ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi-1.6.0/README Mon Feb 11 09:23:05 2008 @@ -0,0 +1,20 @@ +Package: UFFI (Universal Foreign Language Interface) +Web site: http://uffi.b9.com +Author: Kevin M. Rosenberg + + +BRIEF DESCRIPTION +----------------- +uffi is a Common Lisp package for interfacing C-language compatible +libraries. Every Common Lisp implementation has a method for +interfacing to such libraries. Unfortunately, these method vary widely +amongst implementations. uffi gathers a common subset of functionality +between Common Lisp implementations. uffi wraps this common subset of +functionality into it's own syntax and provides macro translation of +uffi features into the specific syntax of supported Common Lisp +implementations. + +Currently, AllegroCL (Linux and Microsoft Windows), Lispworks (Linux +and Microsoft Windows), CMUCL, SBCL, and OpenMCL are supported. + + Added: branches/trunk-reorg/thirdparty/uffi-1.6.0/TODO ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi-1.6.0/TODO Mon Feb 11 09:23:05 2008 @@ -0,0 +1,7 @@ +- Run test-suite on MCL port + +- Add OpenMCL support for with-cast-pointer and def-foreign-var + +- Add support for direct vector passing to and from foreign functions + to avoid copying elements in and out of vector. + Added: branches/trunk-reorg/thirdparty/uffi-1.6.0/benchmarks/Makefile ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi-1.6.0/benchmarks/Makefile Mon Feb 11 09:23:05 2008 @@ -0,0 +1,6 @@ +SUBDIRS := + +include ../Makefile.common + +.PHONY: distclean +distclean: clean Added: branches/trunk-reorg/thirdparty/uffi-1.6.0/benchmarks/allocation.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi-1.6.0/benchmarks/allocation.lisp Mon Feb 11 09:23:05 2008 @@ -0,0 +1,126 @@ +;;;; -*- Mode: Lisp; Syntax: ANSI-Common-Lisp; Base: 10 -*- +;;;; ************************************************************************* +;;;; FILE IDENTIFICATION +;;;; +;;;; Name: allocation.cl +;;;; Purpose: Benchmark allocation and slot-access speed +;;;; Programmer: Kevin M. Rosenberg +;;;; Date Started: Mar 2002 +;;;; +;;;; $Id: allocation.lisp 10608 2005-07-01 00:39:48Z kevin $ +;;;; +;;;; This file, part of UFFI, is Copyright (c) 2002-2005 by Kevin M. Rosenberg +;;;; +;;;; ************************************************************************* + +(declaim (optimize (debug 3) (speed 3) (safety 1) (compilation-speed 0))) +(in-package :cl-user) + + +(defun stk-int () + #+allegro + (ff:with-stack-fobject (ptr :int) + (setf (ff:fslot-value ptr) 0)) + #+lispworks + (fli:with-dynamic-foreign-objects ((ptr :int)) + (setf (fli:dereference ptr) 0)) + #+cmu + (alien:with-alien ((ptr alien:signed)) + (let ((p (alien:addr ptr))) + (setf (alien:deref p) 0))) + #+sbcl + (sb-alien:with-alien ((ptr sb-alien:signed)) + (let ((p (sb-alien:addr ptr))) + (setf (sb-alien:deref p) 0))) + ) + +(defun stk-vector () + #+allegro + (ff:with-stack-fobject (ptr '(:array :int 10) ) + (setf (ff:fslot-value ptr 5) 0)) + #+lispworks + (fli:with-dynamic-foreign-objects ((ptr (:c-array :int 10))) + (setf (fli:dereference ptr 5) 0)) + #+cmu + (alien:with-alien ((ptr (alien:array alien:signed 10))) + (setf (alien:deref ptr 5) 0)) + #+sbcl + (sb-alien:with-alien ((ptr (sb-alien:array sb-alien:signed 10))) + (setf (sb-alien:deref ptr 5) 0)) + ) + +(defun stat-int () + #+allegro + (let ((ptr (ff:allocate-fobject :int :c))) + (declare (dynamic-extent ptr)) + (setf (ff:fslot-value-typed :int :c ptr) 0) + (ff:free-fobject ptr)) + #+lispworks + (let ((ptr (fli:allocate-foreign-object :type :int))) + (declare (dynamic-extent ptr)) + (setf (fli:dereference ptr) 0) + (fli:free-foreign-object ptr)) + #+cmu + (let ((ptr (alien:make-alien (alien:signed 32)))) + (declare ;;(type (alien (* (alien:unsigned 32))) ptr) + (dynamic-extent ptr)) + (setf (alien:deref ptr) 0) + (alien:free-alien ptr)) + #+sbcl + (let ((ptr (sb-alien:make-alien (sb-alien:signed 32)))) + (declare ;;(type (alien (* (alien:unsigned 32))) ptr) + (dynamic-extent ptr)) + (setf (sb-alien:deref ptr) 0) + (sb-alien:free-alien ptr)) + ) + +(defun stat-vector () + #+allegro + (let ((ptr (ff:allocate-fobject '(:array :int 10) :c))) + (declare (dynamic-extent ptr)) + (setf (ff:fslot-value-typed '(:array :int 10) :c ptr 5) 0) + (ff:free-fobject ptr)) + #+lispworks + (let ((ptr (fli:allocate-foreign-object :type '(:c-array :int 10)))) + (declare (dynamic-extent ptr)) + (setf (fli:dereference ptr 5) 0) + (fli:free-foreign-object ptr)) + #+cmu + (let ((ptr (alien:make-alien (alien:array (alien:signed 32) 10)))) + (declare ;;(type (alien (* (alien:unsigned 32))) ptr) + (dynamic-extent ptr)) + (setf (alien:deref ptr 5) 0) + (alien:free-alien ptr)) + #+sbcl + (let ((ptr (sb-alien:make-alien (sb-alien:array (sb-alien:signed 32) 10)))) + (declare ;;(type (sb-alien (* (sb-alien:unsigned 32))) ptr) + (dynamic-extent ptr)) + (setf (sb-alien:deref ptr 5) 0) + (sb-alien:free-alien ptr)) + ) + + +(defun stk-vs-stat () + (format t "~&Stack allocation, Integer") + (time (dotimes (i 1000) + (dotimes (j 1000) + (stk-int)))) + (format t "~&Static allocation, Integer") + (time (dotimes (i 1000) + (dotimes (j 1000) + (stat-int)))) + (format t "~&Stack allocation, Vector") + (time (dotimes (i 1000) + (dotimes (j 1000) + (stk-int)))) + (format t "~&Static allocation, Vector") + (time (dotimes (i 1000) + (dotimes (j 1000) + (stat-int)))) +) + + +(stk-vs-stat) + + + Added: branches/trunk-reorg/thirdparty/uffi-1.6.0/doc/COPYING.GFDL ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi-1.6.0/doc/COPYING.GFDL Mon Feb 11 09:23:05 2008 @@ -0,0 +1,330 @@ + GNU Free Documentation License + Version 1.1, March 2000 + + Copyright (C) 2000 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + +0. PREAMBLE + +The purpose of this License is to make a manual, textbook, or other +written document "free" in the sense of freedom: to assure everyone +the effective freedom to copy and redistribute it, with or without +modifying it, either commercially or noncommercially. Secondarily, +this License preserves for the author and publisher a way to get +credit for their work, while not being considered responsible for +modifications made by others. + +This License is a kind of "copyleft", which means that derivative +works of the document must themselves be free in the same sense. It +complements the GNU General Public License, which is a copyleft +license designed for free software. + +We have designed this License in order to use it for manuals for free +software, because free software needs free documentation: a free +program should come with manuals providing the same freedoms that the +software does. But this License is not limited to software manuals; +it can be used for any textual work, regardless of subject matter or +whether it is published as a printed book. We recommend this License +principally for works whose purpose is instruction or reference. + + +1. APPLICABILITY AND DEFINITIONS + +This License applies to any manual or other work that contains a +notice placed by the copyright holder saying it can be distributed +under the terms of this License. The "Document", below, refers to any +such manual or work. Any member of the public is a licensee, and is +addressed as "you". + +A "Modified Version" of the Document means any work containing the +Document or a portion of it, either copied verbatim, or with +modifications and/or translated into another language. + +A "Secondary Section" is a named appendix or a front-matter section of +the Document that deals exclusively with the relationship of the +publishers or authors of the Document to the Document's overall subject +(or to related matters) and contains nothing that could fall directly +within that overall subject. (For example, if the Document is in part a +textbook of mathematics, a Secondary Section may not explain any +mathematics.) The relationship could be a matter of historical +connection with the subject or with related matters, or of legal, +commercial, philosophical, ethical or political position regarding +them. + +The "Invariant Sections" are certain Secondary Sections whose titles +are designated, as being those of Invariant Sections, in the notice +that says that the Document is released under this License. + +The "Cover Texts" are certain short passages of text that are listed, +as Front-Cover Texts or Back-Cover Texts, in the notice that says that +the Document is released under this License. + +A "Transparent" copy of the Document means a machine-readable copy, +represented in a format whose specification is available to the +general public, whose contents can be viewed and edited directly and +straightforwardly with generic text editors or (for images composed of +pixels) generic paint programs or (for drawings) some widely available +drawing editor, and that is suitable for input to text formatters or +for automatic translation to a variety of formats suitable for input +to text formatters. A copy made in an otherwise Transparent file +format whose markup has been designed to thwart or discourage +subsequent modification by readers is not Transparent. A copy that is +not "Transparent" is called "Opaque". + +Examples of suitable formats for Transparent copies include plain +ASCII without markup, Texinfo input format, LaTeX input format, SGML +or XML using a publicly available DTD, and standard-conforming simple +HTML designed for human modification. Opaque formats include +PostScript, PDF, proprietary formats that can be read and edited only +by proprietary word processors, SGML or XML for which the DTD and/or +processing tools are not generally available, and the +machine-generated HTML produced by some word processors for output +purposes only. + +The "Title Page" means, for a printed book, the title page itself, +plus such following pages as are needed to hold, legibly, the material +this License requires to appear in the title page. For works in +formats which do not have any title page as such, "Title Page" means +the text near the most prominent appearance of the work's title, +preceding the beginning of the body of the text. + + +2. VERBATIM COPYING + +You may copy and distribute the Document in any medium, either +commercially or noncommercially, provided that this License, the +copyright notices, and the license notice saying this License applies +to the Document are reproduced in all copies, and that you add no other +conditions whatsoever to those of this License. You may not use +technical measures to obstruct or control the reading or further +copying of the copies you make or distribute. However, you may accept +compensation in exchange for copies. If you distribute a large enough +number of copies you must also follow the conditions in section 3. + +You may also lend copies, under the same conditions stated above, and +you may publicly display copies. + + +3. COPYING IN QUANTITY + +If you publish printed copies of the Document numbering more than 100, +and the Document's license notice requires Cover Texts, you must enclose +the copies in covers that carry, clearly and legibly, all these Cover +Texts: Front-Cover Texts on the front cover, and Back-Cover Texts on +the back cover. Both covers must also clearly and legibly identify +you as the publisher of these copies. The front cover must present +the full title with all words of the title equally prominent and +visible. You may add other material on the covers in addition. +Copying with changes limited to the covers, as long as they preserve +the title of the Document and satisfy these conditions, can be treated +as verbatim copying in other respects. + +If the required texts for either cover are too voluminous to fit +legibly, you should put the first ones listed (as many as fit +reasonably) on the actual cover, and continue the rest onto adjacent +pages. + +If you publish or distribute Opaque copies of the Document numbering +more than 100, you must either include a machine-readable Transparent +copy along with each Opaque copy, or state in or with each Opaque copy +a publicly-accessible computer-network location containing a complete +Transparent copy of the Document, free of added material, which the +general network-using public has access to download anonymously at no +charge using public-standard network protocols. If you use the latter +option, you must take reasonably prudent steps, when you begin +distribution of Opaque copies in quantity, to ensure that this +Transparent copy will remain thus accessible at the stated location +until at least one year after the last time you distribute an Opaque +copy (directly or through your agents or retailers) of that edition to +the public. + +It is requested, but not required, that you contact the authors of the +Document well before redistributing any large number of copies, to give +them a chance to provide you with an updated version of the Document. + + +4. MODIFICATIONS + +You may copy and distribute a Modified Version of the Document under +the conditions of sections 2 and 3 above, provided that you release +the Modified Version under precisely this License, with the Modified +Version filling the role of the Document, thus licensing distribution +and modification of the Modified Version to whoever possesses a copy +of it. In addition, you must do these things in the Modified Version: + +A. Use in the Title Page (and on the covers, if any) a title distinct + from that of the Document, and from those of previous versions + (which should, if there were any, be listed in the History section + of the Document). You may use the same title as a previous version + if the original publisher of that version gives permission. +B. List on the Title Page, as authors, one or more persons or entities + responsible for authorship of the modifications in the Modified + Version, together with at least five of the principal authors of the + Document (all of its principal authors, if it has less than five). +C. State on the Title page the name of the publisher of the + Modified Version, as the publisher. +D. Preserve all the copyright notices of the Document. +E. Add an appropriate copyright notice for your modifications + adjacent to the other copyright notices. +F. Include, immediately after the copyright notices, a license notice + giving the public permission to use the Modified Version under the + terms of this License, in the form shown in the Addendum below. +G. Preserve in that license notice the full lists of Invariant Sections + and required Cover Texts given in the Document's license notice. +H. Include an unaltered copy of this License. +I. Preserve the section entitled "History", and its title, and add to + it an item stating at least the title, year, new authors, and + publisher of the Modified Version as given on the Title Page. If + there is no section entitled "History" in the Document, create one + stating the title, year, authors, and publisher of the Document as + given on its Title Page, then add an item describing the Modified + Version as stated in the previous sentence. +J. Preserve the network location, if any, given in the Document for + public access to a Transparent copy of the Document, and likewise + the network locations given in the Document for previous versions + it was based on. These may be placed in the "History" section. + You may omit a network location for a work that was published at + least four years before the Document itself, or if the original + publisher of the version it refers to gives permission. +K. In any section entitled "Acknowledgements" or "Dedications", + preserve the section's title, and preserve in the section all the + substance and tone of each of the contributor acknowledgements + and/or dedications given therein. +L. Preserve all the Invariant Sections of the Document, + unaltered in their text and in their titles. Section numbers + or the equivalent are not considered part of the section titles. +M. Delete any section entitled "Endorsements". Such a section + may not be included in the Modified Version. +N. Do not retitle any existing section as "Endorsements" + or to conflict in title with any Invariant Section. + +If the Modified Version includes new front-matter sections or +appendices that qualify as Secondary Sections and contain no material +copied from the Document, you may at your option designate some or all +of these sections as invariant. To do this, add their titles to the +list of Invariant Sections in the Modified Version's license notice. +These titles must be distinct from any other section titles. + +You may add a section entitled "Endorsements", provided it contains +nothing but endorsements of your Modified Version by various +parties--for example, statements of peer review or that the text has +been approved by an organization as the authoritative definition of a +standard. + +You may add a passage of up to five words as a Front-Cover Text, and a +passage of up to 25 words as a Back-Cover Text, to the end of the list +of Cover Texts in the Modified Version. Only one passage of +Front-Cover Text and one of Back-Cover Text may be added by (or +through arrangements made by) any one entity. If the Document already +includes a cover text for the same cover, previously added by you or +by arrangement made by the same entity you are acting on behalf of, +you may not add another; but you may replace the old one, on explicit +permission from the previous publisher that added the old one. + +The author(s) and publisher(s) of the Document do not by this License +give permission to use their names for publicity for or to assert or +imply endorsement of any Modified Version. + + +5. COMBINING DOCUMENTS + +You may combine the Document with other documents released under this +License, under the terms defined in section 4 above for modified +versions, provided that you include in the combination all of the +Invariant Sections of all of the original documents, unmodified, and +list them all as Invariant Sections of your combined work in its +license notice. + +The combined work need only contain one copy of this License, and +multiple identical Invariant Sections may be replaced with a single +copy. If there are multiple Invariant Sections with the same name but +different contents, make the title of each such section unique by +adding at the end of it, in parentheses, the name of the original +author or publisher of that section if known, or else a unique number. +Make the same adjustment to the section titles in the list of +Invariant Sections in the license notice of the combined work. + +In the combination, you must combine any sections entitled "History" +in the various original documents, forming one section entitled +"History"; likewise combine any sections entitled "Acknowledgements", +and any sections entitled "Dedications". You must delete all sections +entitled "Endorsements." + + +6. COLLECTIONS OF DOCUMENTS + +You may make a collection consisting of the Document and other documents +released under this License, and replace the individual copies of this +License in the various documents with a single copy that is included in +the collection, provided that you follow the rules of this License for +verbatim copying of each of the documents in all other respects. + +You may extract a single document from such a collection, and distribute +it individually under this License, provided you insert a copy of this +License into the extracted document, and follow this License in all +other respects regarding verbatim copying of that document. + + +7. AGGREGATION WITH INDEPENDENT WORKS + +A compilation of the Document or its derivatives with other separate +and independent documents or works, in or on a volume of a storage or +distribution medium, does not as a whole count as a Modified Version +of the Document, provided no compilation copyright is claimed for the +compilation. Such a compilation is called an "aggregate", and this +License does not apply to the other self-contained works thus compiled +with the Document, on account of their being thus compiled, if they +are not themselves derivative works of the Document. + +If the Cover Text requirement of section 3 is applicable to these +copies of the Document, then if the Document is less than one quarter +of the entire aggregate, the Document's Cover Texts may be placed on +covers that surround only the Document within the aggregate. +Otherwise they must appear on covers around the whole aggregate. + + +8. TRANSLATION + +Translation is considered a kind of modification, so you may +distribute translations of the Document under the terms of section 4. +Replacing Invariant Sections with translations requires special +permission from their copyright holders, but you may include +translations of some or all Invariant Sections in addition to the +original versions of these Invariant Sections. You may include a +translation of this License provided that you also include the +original English version of this License. In case of a disagreement +between the translation and the original English version of this +License, the original English version will prevail. + + +9. TERMINATION + +You may not copy, modify, sublicense, or distribute the Document except +as expressly provided for under this License. Any other attempt to +copy, modify, sublicense or distribute the Document is void, and will +automatically terminate your rights under this License. However, +parties who have received copies, or rights, from you under this +License will not have their licenses terminated so long as such +parties remain in full compliance. + + +10. FUTURE REVISIONS OF THIS LICENSE + +The Free Software Foundation may publish new, revised versions +of the GNU Free Documentation License from time to time. Such new +versions will be similar in spirit to the present version, but may +differ in detail to address new problems or concerns. See +http://www.gnu.org/copyleft/. + +Each version of the License is given a distinguishing version number. +If the Document specifies that a particular numbered version of this +License "or any later version" applies to it, you have the option of +following the terms and conditions either of that specified version or +of any later version that has been published (not as a draft) by the +Free Software Foundation. If the Document does not specify a version +number of this License, you may choose any version ever published (not +as a draft) by the Free Software Foundation. + Added: branches/trunk-reorg/thirdparty/uffi-1.6.0/doc/Makefile ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi-1.6.0/doc/Makefile Mon Feb 11 09:23:05 2008 @@ -0,0 +1,144 @@ +############################################################################## +# FILE IDENTIFICATION +# +# Name: Makefile +# Purpose: Makefile for the uffi documentation +# Programer: Kevin M. Rosenberg +# Date Started: Mar 2002 +# +# CVS Id: $Id: Makefile 11021 2006-08-14 04:22:28Z kevin $ +# +# This file, part of UFFI, is Copyright (c) 2002-2005 by Kevin M. Rosenberg +############################################################################## + +DOCFILE_BASE_DEFAULT:=uffi +DOCFILE_EXT_DEFAULT:=xml + + +# Standard docfile processing + +DEBIAN=$(shell expr "`cat /etc/issue 2> /dev/null`" : '.*Debian.*') +UBUNTU=$(shell expr "`cat /etc/issue 2> /dev/null`" : '.*Ubuntu.*') +SUSE=$(shell expr "`cat /etc/issue 2> /dev/null`" : '.*SuSE.*') +SUSE91=$(shell expr "`cat /etc/issue 2> /dev/null`" : '.*SuSE Linux 9.1.*') +REDHAT=$(shell expr "`cat /etc/issue 2> /dev/null`" : '.*Red Hat.*') +MANDRAKE=$(shell expr "`cat /etc/issue 2> /dev/null`" : '.*Mandrake.*') +DARWIN=$(shell expr "`uname -a`" : '.*Darwin.*') + +ifneq (${DEBIAN},0) +OS:=debian +else + ifneq (${SUSE91},0) + OS=suse91 + else + ifneq (${SUSE},0) + OS=suse + else + ifneq (${REDHAT},0) + OS=redhat + else + ifneq (${MANDRAKE},0) + OS=mandrake + else + ifneq (${DARWIN},0) + OS=darwin + else + ifneq (${UBUNTU},0) + OS=ubuntu + endif + endif + endif + endif + endif + endif +endif + +ifndef DOCFILE_BASE +DOCFILE_BASE=${DOCFILE_BASE_DEFAULT} +endif + +ifndef DOCFILE_EXT +DOCFILE_EXT=${DOCFILE_EXT_DEFAULT} +endif + +DOCFILE:=${DOCFILE_BASE}.${DOCFILE_EXT} +FOFILE:=${DOCFILE_BASE}.fo +PDFFILE:=${DOCFILE_BASE}.pdf +PSFILE:=${DOCFILE_BASE}.ps +DVIFILE:=${DOCFILE_BASE}.dvi +TXTFILE:=${DOCFILE_BASE}.txt +HTMLFILE:=${DOCFILE_BASE}.html +TMPFILES:=${DOCFILE_BASE}.aux ${DOCFILE_BASE}.out ${DOCFILE_BASE}.log +DOCFILES:=$(shell echo *.xml *.xsl) + +ifeq ($(XSLTPROC),) + XSLTPROC:=xsltproc +endif + +CATALOG:=`pwd`/catalog-${OS}.xml +CHECK:=XML_CATALOG_FILES="$(CATALOG)" xmllint --noout --xinclude --postvalid $(DOCFILE) || exit 1 + +.PHONY: all +all: html pdf + +.PHONY: dist +dist: html pdf + +.PHONY: doc +doc: html pdf + +.PHONY: check +check: + @echo "Operating System Detected: ${OS}" + @$(CHECK) + +.PHONY: html +html: html.tar.gz + +html.tar.gz: $(DOCFILES) Makefile + @rm -rf html + @mkdir html + @XML_CATALOG_FILES="$(CATALOG)" $(XSLTPROC) --stringparam chunker.output.encoding ISO-8859-1 \ + --xinclude --output html/ html_chunk.xsl $(DOCFILE) + @GZIP='-9' tar czf html.tar.gz html + +.PHONY: fo +fo: ${FOFILE} + +${FOFILE}: $(DOCFILES) Makefile + @XML_CATALOG_FILES="$(CATALOG)" xsltproc --xinclude --output $(FOFILE) fo.xsl $(DOCFILE) + +.PHONY: pdf +pdf: ${PDFFILE} + +${PDFFILE}: ${DOCFILES} Makefile + @$(MAKE) fo + @fop $(FOFILE) -pdf $(PDFFILE) > /dev/null + +.PHONY: dvi +dvi: ${DVIFILE} + +.PHONY: ps +ps: ${PSFILE} + +${PSFILE}: ${DOCFILES} Makefile + @$(MAKE) fo + @fop $(FOFILE) -ps $(PSFILE) > /dev/null + + +.PHONY: txt +txt: ${TXTFILE} + +${TXTFILE}: ${FOFILE} + @XML_CATALOG_FILES="$(CATALOG)" xsltproc --xinclude --output ${HTMLFILE} html.xsl $(DOCFILE) + lynx -dump ${HTMLFILE} > ${TXTFILE} + +.PHONY: clean +clean: + @rm -f *~ *.bak *.orig \#*\# .\#* texput.log + @rm -rf html ${PSFILE} ${HTMLFILE} + @rm -f ${TMPFILES} ${FOFILE} + @rm -f ${DVIFILE} ${TXTFILE} + +.PHONY: distclean +distclean: clean Added: branches/trunk-reorg/thirdparty/uffi-1.6.0/doc/appendix.xml ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi-1.6.0/doc/appendix.xml Mon Feb 11 09:23:05 2008 @@ -0,0 +1,35 @@ + + +%myents; +]> + + + Installation + + Download &uffi; + +You need to download the &uffi; package from its web +home. +You also need to have a copy of &asdf;. If you need a copy of +&asdf;, it is included in the + + CCLAN package. You can download +the file defsystem.lisp from the CVS +tree. + + + + Loading + + After downloading and installing &asdf;, simply + push the + directory containing &uffi; into + asdf:*central-registry* variable. Whenever you +want to load the &uffi; package, use the form + (asdf:operate 'asdf:load-op :uffi). + + + Added: branches/trunk-reorg/thirdparty/uffi-1.6.0/doc/bookinfo.xml ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi-1.6.0/doc/bookinfo.xml Mon Feb 11 09:23:05 2008 @@ -0,0 +1,77 @@ + + +%myents; +]> + + + &uffi; Reference Guide + + Kevin + M. + Rosenberg + + Heart Hospital of New Mexico +

+ kevin at rosenberg.net + 504 Elm Street N.E. + Albuquerque + New Mexico + 87102 +
+ + + + + $Id: bookinfo.xml 8263 2003-11-21 05:44:46Z kevin $ + File $Date: 2003-11-20 22:44:46 -0700 (Thu, 20 Nov 2003) $ + + + 2002-2003 + Kevin M. Rosenberg + + + + + The &uffi; package was designed and + written by Kevin M. Rosenberg. + + + + + Permission is granted to copy, distribute and/or modify this document + under the terms of the GNU Free Documentation License, Version 1.1 + or any later version published by the Free Software Foundation; + with no Invariant Sections, with the no + Front-Cover Texts, and with no Back-Cover Texts. + A copy of the license is included in the &uffi; distribution. + + + + + Allegro CL® is a registered + trademark of Franz Inc. + + + + + Lispworks® is a registered + trademark of Xanalys Inc. + + + + + Microsoft Windows® is a + registered trademark of Microsoft Inc. + + + + + Other brand or product names are the registered trademarks + or trademarks of their respective holders. + + + + + Added: branches/trunk-reorg/thirdparty/uffi-1.6.0/doc/catalog-darwin.xml ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi-1.6.0/doc/catalog-darwin.xml Mon Feb 11 09:23:05 2008 @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Added: branches/trunk-reorg/thirdparty/uffi-1.6.0/doc/catalog-debian.xml ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi-1.6.0/doc/catalog-debian.xml Mon Feb 11 09:23:05 2008 @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Added: branches/trunk-reorg/thirdparty/uffi-1.6.0/doc/catalog-mandrake.xml ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi-1.6.0/doc/catalog-mandrake.xml Mon Feb 11 09:23:05 2008 @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Added: branches/trunk-reorg/thirdparty/uffi-1.6.0/doc/catalog-suse.xml ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi-1.6.0/doc/catalog-suse.xml Mon Feb 11 09:23:05 2008 @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Added: branches/trunk-reorg/thirdparty/uffi-1.6.0/doc/catalog-suse90.xml ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi-1.6.0/doc/catalog-suse90.xml Mon Feb 11 09:23:05 2008 @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Added: branches/trunk-reorg/thirdparty/uffi-1.6.0/doc/catalog-suse91.xml ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi-1.6.0/doc/catalog-suse91.xml Mon Feb 11 09:23:05 2008 @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Added: branches/trunk-reorg/thirdparty/uffi-1.6.0/doc/catalog-ubuntu.xml ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi-1.6.0/doc/catalog-ubuntu.xml Mon Feb 11 09:23:05 2008 @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Added: branches/trunk-reorg/thirdparty/uffi-1.6.0/doc/entities.inc ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi-1.6.0/doc/entities.inc Mon Feb 11 09:23:05 2008 @@ -0,0 +1,16 @@ +UFFI"> +FFI"> +CMUCL"> +SCL"> +Lispworks"> +SBCL"> +OpenMCL"> +MCL"> +AllegroCL"> +ANSI Common Lisp"> +T"> +NIL"> +NULL"> +C"> +defsystem"> +ASDF"> Added: branches/trunk-reorg/thirdparty/uffi-1.6.0/doc/fo.xsl ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi-1.6.0/doc/fo.xsl Mon Feb 11 09:23:05 2008 @@ -0,0 +1,8 @@ + + + + + + + Added: branches/trunk-reorg/thirdparty/uffi-1.6.0/doc/glossary.xml ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi-1.6.0/doc/glossary.xml Mon Feb 11 09:23:05 2008 @@ -0,0 +1,21 @@ + + +%myents; +]> + + + + Foreign Function Interface + FFI) + + + + An interface to a C-compatible library. + + + + + + Added: branches/trunk-reorg/thirdparty/uffi-1.6.0/doc/html.tar.gz ============================================================================== Binary file. No diff available. Added: branches/trunk-reorg/thirdparty/uffi-1.6.0/doc/html.xsl ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi-1.6.0/doc/html.xsl Mon Feb 11 09:23:05 2008 @@ -0,0 +1,10 @@ + + + + + + + + + Added: branches/trunk-reorg/thirdparty/uffi-1.6.0/doc/html_chunk.xsl ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi-1.6.0/doc/html_chunk.xsl Mon Feb 11 09:23:05 2008 @@ -0,0 +1,9 @@ + + + + + + + + Added: branches/trunk-reorg/thirdparty/uffi-1.6.0/doc/intro.xml ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi-1.6.0/doc/intro.xml Mon Feb 11 09:23:05 2008 @@ -0,0 +1,113 @@ + + +%myents; +]> + + + Introduction + + Purpose + + This reference guide describes &uffi;, a package that provides a + cross-implementation interface from Common Lisp to C-language + compatible libraries. + + + + + Background + + + Every Common Lisp implementation has a method for interfacing to + C-language compatible libraries. These methods are often termed + a Foreign Function Library Interface + (&ffi;). Unfortunately, these methods vary widely amongst + implementations, thus preventing the writing of a portable FFI + to a particular C-library. + + + &uffi; gathers a common subset of functionality between Common + Lisp implementations. &uffi; wraps this common subset of + functionality with it's own syntax and provides macro + translation of uffi functions into the specific syntax of + supported Common Lisp implementations. + + + Developers who use &uffi; to interface with C libraries will + automatically have their code function in each of uffi's supported + implementations. + + + + + Supported Implementations + The primary tested and supported platforms for &uffi; are: + + + &acl; v6.2 on Debian GNU/Linux + FreeBSD 4.5, Solaris v2.8, and Microsoft Windows XP. + &lw; v4.2 on Debian GNU/Linux and Microsoft Windows XP. + &cmucl; 18d on Debian GNU/Linux, FreeBSD 4.5, and Solaris 2.8 + &sbcl; 0.7.8 on Debian GNU/Linux + &scl; 1.1.1 on Debian GNU/Linux + &openmcl; 0.13 on Debian GNU/Linux for PowerPC + + Beta code is included with &uffi; for + + + &openmcl; and &mcl; with MacOSX + + + + + Design + + Overview + + &uffi; was designed as a cross-implementation + compatible Foreign Function Interface. + Necessarily, + only a common subset of functionality can be + provided. Likewise, not every optimization for that a specific + implementation provides can be supported. Wherever possible, + though, implementation-specific optimizations are invoked. + + + + + Priorities + + The design of &uffi; is dictated by the order of these priorities: + + + + + Code using &uffi; must operate correctly on all + supported implementations. + + + + + Take advantage of implementation-specific optimizations. Ideally, + there will not a situation where an implementation-specific + &ffi; will be chosen due to lack of optimizations in &uffi;. + + + + Provide a simple interface to developers using + &uffi;. This priority is quite a bit lower than the above priorities. + This lower priority is manifest by programmers having to pass types in + pointer and array dereferencing, needing to use + cstring wrapper functions, and the use of + ensure-char-character and ensure-char-integer functions. My hope is + that the developer inconvenience will be outweighed by the generation + of optimized code that is cross-implementation compatible. + + + + + + + Added: branches/trunk-reorg/thirdparty/uffi-1.6.0/doc/notes.xml ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi-1.6.0/doc/notes.xml Mon Feb 11 09:23:05 2008 @@ -0,0 +1,94 @@ + + +%myents; +]> + + + Programming Notes + + + Implementation Specific Notes + + + + &acl; + + + + + &lw; + + + + + &cmucl; + + + + + + + Foreign Object Representation and Access + There are two main approaches used to represent foreign + objects: an integer that represents an address in memory, and a + object that also includes run-time typing. The advantage of + run-time typing is the system can dereference pointers and perform + array access without those functions requiring a type at the cost + of additional overhead to generate and store the run-time + typing. The advantage of integer representation, at least for + &acl;, is that the compiler can generate inline code to + dereference pointers. Further, the overhead of the run-time type + information is eliminated. The disadvantage is the program must + then supply + the type to the functions to dereference objects and array. + + + + + Optimizing Code Using UFFI + + Background + + Two implementions have different techniques to optimize + (open-code) foreign objects. &acl; can open-code foreign + object + access if pointers are integers and the type of object is + specified in the access function. Thus, &uffi; represents objects + in &acl; as integers which don't have type information. + + &cmucl; works best when keeping objects as typed + objects. However, it's compiler can open-code object access when + the object type is specified in declare + commands and in :type specifiers in + defstruct and defclass. + &lw;, in converse to &acl; and &cmucl; does not do + any open coding of object access. &lw;, by default, maintains + objects with run-time typing. + + + Cross-Implementation Optimization + + To fully optimize across platforms, both explicit type + information must be passed to dereferencing of pointers and + arrays. Though this optimization only helps with &acl;, &uffi; + is designed to require this type information be passed the + dereference functions. Second, declarations of type should be + made in functions, structures, and classes where foreign + objects will be help. This will optimize access for &lw; + + + Here is an example that should both methods being used for + maximum cross-implementation optimization: + +(uffi:def-type the-struct-type-def the-struct-type) +(let ((a-foreign-struct (allocate-foreign-object 'the-struct-type))) + (declare 'the-struct-type-def a-foreign-struct) + (get-slot-value a-foreign-struct 'the-struct-type 'field-name)) + + + + + + Added: branches/trunk-reorg/thirdparty/uffi-1.6.0/doc/preface.xml ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi-1.6.0/doc/preface.xml Mon Feb 11 09:23:05 2008 @@ -0,0 +1,16 @@ + + +%myents; +]> + + + Preface + This reference guide describes the usage and features of + &uffi;. The first chapter provides an overview to the design of + &uffi;. Following that chapter is the reference section for all + user accessible functions of &uffi;. The appendix covers the + installation and implementation-specifc features of &uffi;. + + Added: branches/trunk-reorg/thirdparty/uffi-1.6.0/doc/ref_aggregate.xml ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi-1.6.0/doc/ref_aggregate.xml Mon Feb 11 09:23:05 2008 @@ -0,0 +1,524 @@ + + +%myents; +]> + + + Aggregate Types + + Overview + + Aggregate types are comprised of one or more primitive types. + + + + + + def-enum + Defines a &c; enumeration. + + Macro + + + Syntax + + def-enum name fields &key separator-string + + + + Arguments and Values + + + name + + A symbol that names the enumeration. + + + + + fields + + A list of field defintions. Each definition can be +a symbol or a list of two elements. Symbols get assigned a value of the +current counter which starts at 0 and +increments by 1 for each subsequent symbol. It the field definition is a list, the first position is the symbol and the second +position is the value to assign the the symbol. The current counter gets set +to 1+ this value. + + + + + separator-string + + A string that governs the creation of constants. The +default is "#". + + + + + + Description + + Declares a &c; enumeration. It generates constants with integer values for the elements of the enumeration. The symbols for the these constant +values are created by the concatenation of the +enumeration name, separator-string, and field symbol. Also creates +a foreign type with the name name of type +:int. + + + + Examples + +(def-enum abc (:a :b :c)) +;; Creates constants abc#a (1), abc#b (2), abc#c (3) and defines +;; the foreign type "abc" to be :int + +(def-enum efoo (:e1 (:e2 10) :e3) :separator-string "-") +;; Creates constants efoo-e1 (1), efoo-e2 (10), efoo-e3 (11) and defines +;; the foreign type efoo to be :int + + + + Side Effects + Creates a :int foreign type, defines constants. + + + Affected by + None. + + + Exceptional Situations + None. + + + + + + + def-struct + Defines a &c; structure. + + Macro + + + Syntax + + def-struct name &rest fields + + + + Arguments and Values + + + name + + A symbol that names the structure. + + + + + fields + + A variable number of field defintions. Each definition is a list consisting of a symbol naming the field followed by its foreign type. + + + + + + + Description + + Declares a structure. A special type is available as a slot +in the field. It is a pointer that points to an instance of the parent +structure. It's type is :pointer-self. + + + + + Examples + +(def-struct foo (a :unsigned-int) + (b (* :char)) + (c (:array :int 10)) + (next :pointer-self)) + + + + Side Effects + Creates a foreign type. + + + Affected by + None. + + + Exceptional Situations + None. + + + + + + + get-slot-value + Retrieves a value from a slot of a structure. + + Macro + + + Syntax + + get-slot-value obj type field => value + + + + Arguments and Values + + + obj + + A pointer to foreign structure. + + + + + type + + A name of the foreign structure. + + + + + field + + A name of the desired field in foreign structure. + + + + + value + + The value of the field in the structure. + + + + + + + Description + + Accesses a slot value from a structure. This is generalized + and can be used with setf. + + + + Examples + +(get-slot-value foo-ptr 'foo-structure 'field-name) +(setf (get-slot-value foo-ptr 'foo-structure 'field-name) 10) + + + + Side Effects + None. + + + Affected by + None. + + + Exceptional Situations + None. + + + + + + get-slot-pointer + Retrieves a pointer from a slot of a structure. + + Macro + + + Syntax + + get-slot-pointer obj type field => pointer + + + + Arguments and Values + + + obj + + A pointer to foreign structure. + + + + + type + + A name of the foreign structure. + + + + + field + + A name of the desired field in foreign structure. + + + + + pointer + + The value of the field in the structure. + + + + + + + Description + + This is similar to get-slot-value. It + is used when the value of a slot is a pointer type. + + + + Examples + +(get-slot-pointer foo-ptr 'foo-structure 'my-char-ptr) + + + + Side Effects + None. + + + Affected by + None. + + + Exceptional Situations + None. + + + + + + + def-array-pointer + Defines a pointer to a array of type. + + Macro + + + Syntax + + def-array-pointer name type + + + + Arguments and Values + + + name + + A name of the new foreign type. + + + + + type + + The foreign type of the array elements. + + + + + + + Description + + Defines a type tat is a pointer to an array of type. + + + + Examples + +(def-array-pointer byte-array-pointer :unsigned-char) + + + + Side Effects + Defines a new foreign type. + + + Affected by + None. + + + Exceptional Situations + None. + + + + + + + deref-array + Deference an array. + + Macro + + + Syntax + + deref-array array type position => value + + + + Arguments and Values + + + array + + A foreign array. + + + + + type + + The foreign type of the array. + + + + + position + + An integer specifying the position to retrieve from +the array. + + + + + value + + The value stored in the position of the array. + + + + + + + Description + + Dereferences (retrieves) the value of an array element. + + + + Examples + +(def-array-pointer ca :char) +(let ((fs (convert-to-foreign-string "ab"))) + (values (null-char-p (deref-array fs 'ca 0)) + (null-char-p (deref-array fs 'ca 2)))) +=> &nil; + &t; + + + + Notes + + The TYPE argument is ignored for CL implementations other than + AllegroCL. If you want to cast a pointer to another type use + WITH-CAST-POINTER together with DEREF-POINTER/DEREF-ARRAY. + + + + Side Effects + None. + + + Affected by + None. + + + Exceptional Situations + None. + + + + + + def-union + Defines a foreign union type. + + Macro + + + Syntax + + def-union name &rest fields + + + + Arguments and Values + + + name + + A name of the new union type. + + + + + fields + + A list of fields of the union. + + + + + + + Description + + Defines a foreign union type. + + + + Examples + +(def-union test-union + (a-char :char) + (an-int :int)) + +(let ((u (allocate-foreign-object 'test-union)) + (setf (get-slot-value u 'test-union 'an-int) (+ 65 (* 66 256))) + (prog1 + (ensure-char-character (get-slot-value u 'test-union 'a-char)) + (free-foreign-object u))) +=> #\A + + + + Side Effects + Defines a new foreign type. + + + Affected by + None. + + + Exceptional Situations + None. + + + + + Added: branches/trunk-reorg/thirdparty/uffi-1.6.0/doc/ref_declare.xml ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi-1.6.0/doc/ref_declare.xml Mon Feb 11 09:23:05 2008 @@ -0,0 +1,82 @@ + + +%myents; +]> + + + Declarations + + + + Overview + Declarations are used to give the compiler optimizing + information about foreign types. Currently, only &cmucl; + supports declarations. On &acl; and &lw;, these expressions + declare the type generically as &t; + + + + + + + def-type + Defines a Common Lisp type. + + Macro + + + Syntax + + def-type name type + + + + Arguments and Values + + + name + + A symbol naming the type + + + + type + + A form that specifies the &uffi; type. It is not evaluated. + + + + + + + Description + Defines a Common Lisp type based on a &uffi; type. + + + + Examples + +(def-type char-ptr '(* :char)) +... +(defun foo (ptr) +(declare (type char-ptr ptr)) +... + + + + Side Effects + Defines a new &cl; type. + + + Affected by + None. + + + Exceptional Situations + None. + + + + Added: branches/trunk-reorg/thirdparty/uffi-1.6.0/doc/ref_func_libr.xml ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi-1.6.0/doc/ref_func_libr.xml Mon Feb 11 09:23:05 2008 @@ -0,0 +1,264 @@ + + +%myents; +]> + + + Functions & Libraries + + + + def-function + Declares a function. + + Macro + + + Syntax + + def-function name args &key module returning + + + + Arguments and Values + + + name + + A string or list specificying the function name. If it is a string, that names the foreign function. A Lisp name is created by translating #\_ to #\- and by converting to upper-case in case-insensitive Lisp implementations. If it is a list, the first item is a string specifying the foreign function name and the second it is a symbol stating the Lisp name. + + + + + args + + A list of argument declarations. If &nil;, indicates that the function does not take any arguments. + + + + + module + + A string specifying which module (or library) that the foreign function resides. (Required by Lispworks) + + + + returning + + A declaration specifying the result type of the +foreign function. If :void indicates module does not return any value. + + + + + + + Description + Declares a foreign function. + + + + Examples + +(def-function "gethostname" + ((name (* :unsigned-char)) + (len :int)) + :returning :int) + + + + Side Effects + None. + + + Affected by + None. + + + Exceptional Situations + None. + + + + + + load-foreign-library + Loads a foreign library. + + Function + + + Syntax + + load-foreign-library filename &key module supporting-libraries force-load => success + + + + Arguments and Values + + + filename + + A string or pathname specifying the library location +in the filesystem. At least one implementation (&lw;) can not +accept a logical pathname. If this parameter denotes a pathname without a +directory component then most of the supported Lisp implementations will be +able to find the library themselves if it is located in one of the standard +locations as defined by the underlying operating system. + + + + + module + + A string designating the name of the module to apply +to functions in this library. (Required for Lispworks) + + + + + supporting-libraries + + A list of strings naming the libraries required to +link the foreign library. (Required by CMUCL) + + + + + force-load + + Forces the loading of the library if it has been previously loaded. + + + + + success + + A boolean flag, &t; if the library was able to be +loaded successfully or if the library has been previously loaded, + + + + + + + Description + Loads a foreign library. Applies a module name to functions +within the library. Ensures that a library is only loaded once during +a session. A library can be reloaded by using the :force-load key. + + + + Examples + + (load-foreign-library #p"/usr/lib/libmysqlclient.so" + :module "mysql" + :supporting-libraries '("c")) + => T + + + + Side Effects + Loads the foreign code into the Lisp system. + + + + Affected by + Ability to load the file. + + + Exceptional Situations + An error will be signaled if the library is unable to be loaded. + + + + + + find-foreign-library + Finds a foreign library file. + + Function + + + Syntax + + find-foreign-library names directories & drive-letters types => path + + + + Arguments and Values + + + names + + A string or list of strings containing the base name of the library file. + + + + + directories + + A string or list of strings containing the directory the library file. + + + + + drive-letters + + A string or list of strings containing the drive letters for the library file. + + + + + types + + A string or list of strings containing the file type of the library file. Default +is &nil;. If &nil;, will use a default type based on the currently running implementation. + + + + + path + + A path containing the path found, or &nil; if the library file was not found. + + + + + + + Description + Finds a foreign library by searching through a number of possible locations. Returns +the path of the first found file. + + + + Examples + +(find-foreign-library '("libmysqlclient" "libmysql") + '("/opt/mysql/lib/mysql/" "/usr/local/lib/" "/usr/lib/" "/mysql/lib/opt/") + :types '("so" "dll") + :drive-letters '("C" "D" "E")) +=> #P"D:\\mysql\\lib\\opt\\libmysql.dll" + + + + Side Effects + None. + + + + Affected by + None. + + + Exceptional Situations + None. + + + + + + Added: branches/trunk-reorg/thirdparty/uffi-1.6.0/doc/ref_object.xml ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi-1.6.0/doc/ref_object.xml Mon Feb 11 09:23:05 2008 @@ -0,0 +1,859 @@ + + +%myents; +]> + + + Objects + +Overview + + Objects are entities that can allocated, referred to by pointers, and +can be freed. + + + + + + + allocate-foreign-object + Allocates an instance of a foreign object. + + Macro + + + Syntax + + allocate-foreign-object type &optional size => ptr + + + + Arguments and Values + + + type + + The type of foreign object to allocate. This parameter is evaluated. + + + + + size + + An optional size parameter that is evaluated. If specified, allocates and returns an +array of type that is size members long. This parameter is evaluated. + + + + + ptr + + A pointer to the foreign object. + + + + + + + Description + + Allocates an instance of a foreign object. It returns a pointer to the object. + + + + Examples + +(def-struct ab (a :int) (b :double)) +(allocate-foreign-object 'ab) +=> #<ptr> + + + + Side Effects + None. + + + Affected by + None. + + + Exceptional Situations + None. + + + + + + + free-foreign-object + Frees memory that was allocated for a foreign boject. + + Macro + + + Syntax + + free-foreign-object ptr + + + + Arguments and Values + + + ptr + + A pointer to the allocated foreign object to free. + + + + + + + Description + + Frees the memory used by the allocation of a foreign object. + + + + Side Effects + None. + + + Affected by + None. + + + Exceptional Situations + None. + + + + + + + with-foreign-object + Wraps the allocation of a foreign object around a body of code. + + Macro + + + Syntax + + with-foreign-object (var type) &body body => form-return + + + + Arguments and Values + + + var + + The variable name to bind. + + + + + type + + The type of foreign object to allocate. This parameter is evaluated. + + + + + form-return + + The result of evaluating the body. + + + + + + + Description + +This function wraps the allocation, binding, and destruction of a foreign object. +On &cmucl; and +&lw; platforms the object is stack allocated for efficiency. Benchmarks show that &acl; performs +much better with static allocation. + + + + Examples + +(defun gethostname2 () + "Returns the hostname" + (uffi:with-foreign-object (name '(:array :unsigned-char 256)) + (if (zerop (c-gethostname (uffi:char-array-to-pointer name) 256)) + (uffi:convert-from-foreign-string name) + (error "gethostname() failed.")))) + + + + Side Effects + None. + + + Affected by + None. + + + Exceptional Situations + None. + + + + + + size-of-foreign-type + Returns the number of data bytes used by a foreign object type. + + Macro + + + Syntax + + size-of-foreign-type ftype + + + + Arguments and Values + + + ftype + + A foreign type specifier. This parameter is evaluated. + + + + + + + Description + + Returns the number of data bytes used by a foreign object type. This does not include any Lisp storage overhead. + + + + Examples + + +(size-of-foreign-object :unsigned-byte) +=> 1 +(size-of-foreign-object 'my-100-byte-vector-type) +=> 100 + + + + + Side Effects + None. + + Affected by + None. + + + Exceptional Situations + None. + + + + + + pointer-address + Returns the address of a pointer. + + Macro + + + Syntax + + pointer-address ptr => address + + + + Arguments and Values + + + ptr + + A pointer to a foreign object. + + + + + address + + An integer representing the pointer's address. + + + + + + + Description + + Returns the address as an integer of a pointer. + + + + Side Effects + None. + + + Affected by + None. + + + Exceptional Situations + None. + + + + + + + deref-pointer + Deferences a pointer. + + Macro + + + Syntax + + deref-pointer ptr type => value + + + + Arguments and Values + + + ptr + + A pointer to a foreign object. + + + + + type + + A foreign type of the object being pointed to. + + + + + value + + The value of the object where the pointer points. + + + + + + + Description + + Returns the object to which a pointer points. + + + + Examples + + +(let ((intp (allocate-foreign-object :int))) + (setf (deref-pointer intp :int) 10) + (prog1 + (deref-pointer intp :int) + (free-foreign-object intp))) +=> 10 + + + + + Notes + + The TYPE argument is ignored for CL implementations other than + AllegroCL. If you want to cast a pointer to another type use + WITH-CAST-POINTER together with DEREF-POINTER/DEREF-ARRAY. + + + + Side Effects + None. + + + Affected by + None. + + + Exceptional Situations + None. + + + + + + ensure-char-character + Ensures that a dereferenced :char pointer is +a character. + + Macro + + + Syntax + + ensure-char-character object => char + + + + Arguments and Values + + + object + + Either a character or a integer specifying a character code. + + + + + char + + A character. + + + + + + + Description + + Ensures that an objects obtained by dereferencing +:char and :unsigned-char +pointers are a lisp character. + + + + Examples + + +(let ((fs (convert-to-foreign-string "a"))) + (prog1 + (ensure-char-character (deref-pointer fs :char)) + (free-foreign-object fs))) +=> #\a + + + + + Side Effects + None. + + + Affected by + None. + + + Exceptional Situations + Depending upon the implementation and what &uffi; expects, this +macro may signal an error if the object is not a character or +integer. + + + + + + ensure-char-integer + Ensures that a dereferenced :char pointer is +an integer. + + Macro + + + Syntax + + ensure-char-integer object => int + + + + Arguments and Values + + + object + + Either a character or a integer specifying a character code. + + + + + int + + An integer. + + + + + + + Description + + Ensures that an object obtained by dereferencing a +:char pointer is an integer. + + + + Examples + + +(let ((fs (convert-to-foreign-string "a"))) + (prog1 + (ensure-char-integer (deref-pointer fs :char)) + (free-foreign-object fs))) +=> 96 + + + + + Side Effects + None. + + + Affected by + None. + + + Exceptional Situations + Depending upon the implementation and what &uffi; expects, this +macro may signal an error if the object is not a character or +integer. + + + + + + make-null-pointer + Create a &null; pointer. + + Macro + + + Syntax + + make-null-pointer type => ptr + + + + Arguments and Values + + + type + + A type of object to which the pointer refers. + + + + + ptr + + The &null; pointer of type type. + + + + + + + Description + + Creates a &null; pointer of a specified type. + + + + Side Effects + None. + + + Affected by + None. + + + Exceptional Situations + None. + + + + + + + null-pointer-p + Tests a pointer for &null; value. + + Macro + + + Syntax + + null-pointer-p ptr => is-null + + + + Arguments and Values + + + ptr + + A foreign object pointer. + + + + + is-null + + The boolean flag. + + + + + + + Description + + A predicate testing if a pointer is has a &null; value. + + + + Side Effects + None. + + + Affected by + None. + + + Exceptional Situations + None. + + + + + + + +null-cstring-pointer+ + A constant &null; cstring pointer. + + Constant + + + Description + + A &null; cstring pointer. This can be used for testing +if a cstring returned by a function is &null;. + + + + + + + with-cast-pointer + Wraps a body of code with a pointer cast to a new type. + + Macro + + + Syntax + + with-cast-pointer (binding-name ptr type) & body body => value + + + + Arguments and Values + + + binding-name + + A symbol which will be bound to the casted object. + + + + + ptr + + A pointer to a foreign object. + + + + + type + + A foreign type of the object being pointed to. + + + + + value + + The value of the object where the pointer points. + + + + + + + Description + + Executes BODY with POINTER cast to be a pointer to type TYPE. + BINDING-NAME is will be bound to this value during the execution of + BODY. + + This is a no-op in AllegroCL but will wrap BODY in a LET form if + BINDING-NAME is provided. + + This macro is meant to be used in conjunction with DEREF-POINTER or + DEREF-ARRAY. In Allegro CL the "cast" will actually take place in + DEREF-POINTER or DEREF-ARRAY. + + + + Examples + +(with-foreign-object (size :int) + ;; FOO is a foreign function returning a :POINTER-VOID + (let ((memory (foo size))) + (when (mumble) + ;; at this point we know for some reason that MEMORY points + ;; to an array of unsigned bytes + (with-cast-pointer (memory :unsigned-byte) + (dotimes (i (deref-pointer size :int)) + (do-something-with + (deref-array memory '(:array :unsigned-byte) i))))))) + + + + Side Effects + None. + + + Affected by + None. + + + Exceptional Situations + None. + + + + + + def-foreign-var + +Defines a symbol macro to access a variable in foreign code + + Macro + + + Syntax + + def-foreign-var name type module + + + + Arguments and Values + + + name + + +A string or list specificying the symbol macro's name. If it is a + string, that names the foreign variable. A Lisp name is created + by translating #\_ to #\- and by converting to upper-case in + case-insensitive Lisp implementations. If it is a list, the first + item is a string specifying the foreign variable name and the + second it is a symbol stating the Lisp name. + + + + + type + + A foreign type of the foreign variable. + + + + + module + + + A string specifying the module (or library) the foreign variable + resides in. (Required by Lispworks) + + + + + + + Description + +Defines a symbol macro which can be used to access (get and set) the +value of a variable in foreign code. + + + + Examples + + C code + + int baz = 3; + + typedef struct { + int x; + double y; + } foo_struct; + + foo_struct the_struct = { 42, 3.2 }; + + int foo () { + return baz; + } + + + +Lisp code + + (uffi:def-struct foo-struct + (x :int) + (y :double)) + + (uffi:def-function ("foo" foo) + () + :returning :int + :module "foo") + + (uffi:def-foreign-var ("baz" *baz*) :int "foo") + (uffi:def-foreign-var ("the_struct" *the-struct*) foo-struct "foo") + + +*baz* + => 3 + +(incf *baz*) + => 4 + +(foo) + => 4 + + + + + Side Effects + None. + + + Affected by + None. + + + Exceptional Situations + None. + + + + Added: branches/trunk-reorg/thirdparty/uffi-1.6.0/doc/ref_primitive.xml ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi-1.6.0/doc/ref_primitive.xml Mon Feb 11 09:23:05 2008 @@ -0,0 +1,279 @@ + + +%myents; +]> + + + Primitive Types + + Overview + + Primitive types have a single value, these include + characters, numbers, and pointers. They are all symbols in + the keyword package. + + + + :char - Signed 8-bits. A + dereferenced :char pointer returns an character. + + + + :unsigned-char - Unsigned 8-bits. A dereferenced :unsigned-char + pointer returns an character. + + + + :byte - Signed 8-bits. A + dereferenced :byte pointer returns an integer. + + + + :unsigned-byte - Unsigned 8-bits. A + dereferenced :unsigned-byte pointer returns an integer. + + + + :short - Signed 16-bits. + + + + :unsigned-short - Unsigned 16-bits. + + + + :int - Signed 32-bits. + + + :unsigned-int - Unsigned 32-bits. + + + :long - Signed 32 or 64 bits, depending upon the platform. + + + :unsigned-long - Unsigned 32 or 64 bits, depending upon the platform. + + + :float - 32-bit floating point. + + + :double - 64-bit floating point. + + + :cstring - + A &null; terminated string used for passing and returning characters strings with a &c; function. + + + + :void - + The absence of a value. Used to indicate that a function does not return a value. + + + + :pointer-void - Points to a generic object. + + + * - Used to declare a pointer to an object + + + + + + + def-constant + Binds a symbol to a constant. + + Macro + + + Syntax + + def-constant name value &key export + + + + Arguments and Values + + + name + + A symbol that will be bound to the value. + + + + + value + + An evaluated form that is bound the the name. + + + + + export + + When &t;, the name is exported from the current package. The default is &nil; + + + + + + Description + This is a thin wrapper around defconstant. It evaluates at + compile-time and optionally exports the symbol from the package. + + + + Examples + +(def-constant pi2 (* 2 pi)) +(def-constant exported-pi2 (* 2 pi) :export t) + + + + Side Effects + Creates a new special variable.. + + + Affected by + None. + + + Exceptional Situations + None. + + + + + + def-foreign-type + Defines a new foreign type. + + Macro + + + Syntax + + def-foreign-type name type + + + + Arguments and Values + + + name + + A symbol naming the new foreign type. + + + + + value + + A form that is not evaluated that defines the new + foreign type. + + + + + + + Description + Defines a new foreign type. + + + + Examples + +(def-foreign-type my-generic-pointer :pointer-void) +(def-foreign-type a-double-float :double-float) +(def-foreign-type char-ptr (* :char)) + + + + Side Effects + Defines a new foreign type. + + + + Affected by + None. + + + Exceptional Situations + None. + + + + + + null-char-p + Tests a character for &null; value. + + Macro + + + Syntax + + null-char-p char => is-null + + + + Arguments and Values + + + char + + A character or integer. + + + + + is-null + + A boolean flag indicating if char is a &null; value. + + + + + + + Description + + A predicate testing if a character or integer is &null;. This + abstracts the difference in implementations where some return a + character + and some return a + integer + whence dereferencing a + C + character pointer. + + + + Examples + +(def-array-pointer ca :unsigned-char) +(let ((fs (convert-to-foreign-string "ab"))) + (values (null-char-p (deref-array fs 'ca 0)) + (null-char-p (deref-array fs 'ca 2)))) +=> &nil; + &t; + + + + Side Effects + None. + + + + Affected by + None. + + + Exceptional Situations + None. + + + Added: branches/trunk-reorg/thirdparty/uffi-1.6.0/doc/ref_string.xml ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi-1.6.0/doc/ref_string.xml Mon Feb 11 09:23:05 2008 @@ -0,0 +1,514 @@ + + +%myents; +]> + + + Strings + + Overview + + &uffi; has functions to two types of C-compatible + strings: cstring and foreign + strings. cstrings are used only as parameters to + and from functions. In some implementations a cstring is not a foreign + type but rather the Lisp string itself. On other platforms a cstring + is a newly allocated foreign vector for storing characters. The + following is an example of using cstrings to both send and return a + value. + + + +(uffi:def-function ("getenv" c-getenv) + ((name :cstring)) + :returning :cstring) + +(defun my-getenv (key) + "Returns an environment variable, or NIL if it does not exist" + (check-type key string) + (uffi:with-cstring (key-native key) + (uffi:convert-from-cstring (c-getenv key-native)))) + + + + In contrast, foreign strings are always a foreign vector of + characters which have memory allocated. Thus, if you need to + allocate memory to hold the return value of a string, you must + use a foreign string and not a cstring. The following is an + example of using a foreign string for a return value. + + + +(uffi:def-function ("gethostname" c-gethostname) + ((name (* :unsigned-char)) + (len :int)) + :returning :int) + +(defun gethostname () + "Returns the hostname" + (let* ((name (uffi:allocate-foreign-string 256)) + (result-code (c-gethostname name 256)) + (hostname (when (zerop result-code) + (uffi:convert-from-foreign-string name)))) + ;; UFFI does not yet provide a universal way to free + ;; memory allocated by C's malloc. At this point, a program + ;; needs to call C's free function to free such memory. + (unless (zerop result-code) + (error "gethostname() failed.")))) + + + + Foreign functions that return pointers to freshly allocated + strings should in general not return cstrings, but foreign + strings. (There is no portable way to release such cstrings from + Lisp.) The following is an example of handling such a function. + + + +(uffi:def-function ("readline" c-readline) + ((prompt :cstring)) + :returning (* :char)) + +(defun readline (prompt) + "Reads a string from console with line-editing." + (with-cstring (c-prompt prompt) + (let* ((c-str (c-readline c-prompt)) + (str (convert-from-foreign-string c-str))) + (uffi:free-foreign-object c-str) + str))) + + + + + + + convert-from-cstring + Converts a cstring to a Lisp string. + Macro + + + Syntax + + convert-from-cstring + cstring + => + string + + + + Arguments and Values + + + cstring + + A cstring. + + + + + string + + A Lisp string. + + + + + + + Description + + Converts a Lisp string to a cstring. This is + most often used when processing the results of a foreign function + that returns a cstring. + + + + Side Effects + None. + + + Affected by + None. + + + Exceptional Situations + None. + + + + + + + convert-to-cstring + Converts a Lisp string to a cstring. + Macro + + + Syntax + + convert-to-cstring + string + => + cstring + + + + Arguments and Values + + + string + + A Lisp string. + + + + + cstring + + A cstring. + + + + + + + Description + + Converts a Lisp string to a cstring. The + cstring should be freed with + free-cstring. + + + + Side Effects + On some implementations, this function allocates memory. + + + Affected by + None. + + + Exceptional Situations + None. + + + + + + + free-cstring + Free memory used by cstring. + + Macro + + + Syntax + + free-cstring cstring + + + + Arguments and Values + + + cstring + + A cstring. + + + + + + + Description + + Frees any memory possibly allocated by + convert-to-cstring. On some implementions, a cstring is just the Lisp string itself. + + + + Side Effects + None. + + + Affected by + None. + + + Exceptional Situations + None. + + + + + + + with-cstring + Binds a newly created cstring. + Macro + + + Syntax + + with-cstring + (cstring string) {body} + + + + Arguments and Values + + + cstring + + A symbol naming the cstring to be created. + + + + + string + + A Lisp string that will be translated to a cstring. + + + + + body + + The body of where the cstring will be bound. + + + + + + + Description + + Binds a symbol to a cstring created from conversion of a + string. Automatically frees the cstring. + + + + Examples + + +(def-function ("getenv" c-getenv) + ((name :cstring)) + :returning :cstring) + +(defun getenv (key) + "Returns an environment variable, or NIL if it does not exist" + (check-type key string) + (with-cstring (key-cstring key) + (convert-from-cstring (c-getenv key-cstring)))) + + + + + Side Effects + None. + + + Affected by + None. + + + Exceptional Situations + None. + + + + + + + convert-from-foreign-string + Converts a foreign string into a Lisp string. + Macro + + + Syntax + + convert-from-foreign-string + foreign-string &key length null-terminated-p + => + string + + + + Arguments and Values + + + foreign-string + + A foreign string. + + + + + length + + The length of the foreign string to convert. The + default is the length of the string until a &null; + character is reached. + + + + + null-terminated-p + + A boolean flag with a default value of &t; When true, + the string is converted until the first &null; character is reached. + + + + + string + + A Lisp string. + + + + + + + Description + + Returns a Lisp string from a foreign string. + Can translated ASCII and binary strings. + + + + Side Effects + None. + + + Affected by + None. + + + Exceptional Situations + None. + + + + + + + convert-to-foreign-string + Converts a Lisp string to a foreign string. + + Macro + + + Syntax + + convert-to-foreign-string + string => + foreign-string + + + + Arguments and Values + + + string + + A Lisp string. + + + + + foreign-string + + A foreign string. + + + + + + + Description + + Converts a Lisp string to a foreign string. Memory should be + freed with free-foreign-object. + + + + Side Effects + None. + + + Affected by + None. + + + Exceptional Situations + None. + + + + + + allocate-foreign-string + Allocates space for a foreign string. + + Macro + + + Syntax + + allocate-foreign-string size + &key unsigned => + foreign-string + + + + Arguments and Values + + + size + + The size of the space to be allocated in bytes. + + + + + unsigned + + A boolean flag with a default value of &t;. When true, + marks the pointer as an :unsigned-char. + + + + + foreign-string + + A foreign string which has undefined contents. + + + + + + + Description + + Allocates space for a foreign string. Memory should + be freed with free-foreign-object. + + + + Side Effects + None. + + + Affected by + None. + + + Exceptional Situations + None. + + + + Added: branches/trunk-reorg/thirdparty/uffi-1.6.0/doc/schemas.xml ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi-1.6.0/doc/schemas.xml Mon Feb 11 09:23:05 2008 @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + Added: branches/trunk-reorg/thirdparty/uffi-1.6.0/doc/uffi.pdf ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi-1.6.0/doc/uffi.pdf Mon Feb 11 09:23:05 2008 @@ -0,0 +1,3005 @@ +%PDF-1.3 +%???? +4 0 obj +<< /Type /Info +/Producer (FOP 0.20.5) >> +endobj +5 0 obj +<< /Length 201 /Filter [ /ASCII85Decode /FlateDecode ] + >> +stream +GaqdX]*cD?&;B(lTAl),iOH at 5G$De=MG72'Yq]!?$6qt2q-EJV_Gi>/s/i"t#!0$EmK_'.Pqq^YH!T2*q~> +endstream +endobj +6 0 obj +<< /Type /Page +/Parent 1 0 R +/MediaBox [ 0 0 612 792 ] +/Resources 3 0 R +/Contents 5 0 R +>> +endobj +7 0 obj +<< /Length 965 /Filter [ /ASCII85Decode /FlateDecode ] + >> +stream +Gau0B9lo#B&A at ZcFA-9Z`S\\a;j*G?g8#gidrqVQ6.j%f at O*E0./ih(NJo,:9QS9/_s"58Dg.h\CL?1UMbsWT#Y#r/$p7>qI,Lur&,a4q*_%??q6/YH:;7_^lb<4qDmi3MlsD"m81?_JGV7i8eK99"_!XJ`"DOWS69%V?g*poDpTOD+NYulf9+Uo`GkpN\R^oiss6d1+_$n^?25[9&oja`4eNgk6:&60/TOB6uH`Wp6H>(0FlQ+&l1e).un/XO\^rLae!\j^aO6ZSR^<5QNT"!'A$fUMJ#msPP>Ik"%k+87<*#mLg"3*M3QXj@(^rV33`Ef<,$'],bHf`&KqG70S_>U at rObfN@Ksee2_<.A2Ype;4lNrOpK1OGTj>/$4**4VkH='g?99)V,6i=K%e<(Y:Igs&e7=Vacjr\mMg^u8J1&`_1/&r`fU3\Ej-d+>-1m at B"_3n-uBP>*n>-c\ZV;2gTE8kkP7[onB-ZrdueerP,n!LL?kH%o&<]GtKfIhq`rShqJdHX,L[,-5?>m[u-Lj:e[Q<)WeX49j5FHX;[#JW4TE1:c)ofX(CW*Oab`A*_g^'q18h$9,LL52At#8'F +endstream +endobj +8 0 obj +<< /Type /Page +/Parent 1 0 R +/MediaBox [ 0 0 612 792 ] +/Resources 3 0 R +/Contents 7 0 R +>> +endobj +9 0 obj +<< /Length 71 /Filter [ /ASCII85Decode /FlateDecode ] + >> +stream +Garg^iGoCd.c`?]8EV`b1=.gR0K1l>1K?+0ZOMGdU/Zh'Y!=Te%#&:?HH*JE!<<-b&VU~> +endstream +endobj +10 0 obj +<< /Type /Page +/Parent 1 0 R +/MediaBox [ 0 0 612 792 ] +/Resources 3 0 R +/Contents 9 0 R +>> +endobj +11 0 obj +<< /Length 1932 /Filter [ /ASCII85Decode /FlateDecode ] + >> +stream +Gb"/l95iQS'SZ;X'jS`aUiKdh/8_9h>bk(t/):nF0_C00,E_8Q;NUhQE(E\_P"#M9etsu?(be-:3$JCZ_`Mqc>[:&o5M\#SKG,8Le(Mh:Z4ZX)k)Xa1SbQM&`06PrDn>H;H8/.NcfKj>VI;H@"l\p$d71*d=[HZ;e6]iaHFoMre1rA5O_#mSl%s0G4kD73KrUV5)Ed at b+'0.p:t:d2^"*6lZI8H9hE8oI>QNBWjX=el&Vkq<:3n"&L*OkY16N-A9;i%d0\2lWi_CJ7*3W1C&Ir&#oud=_\\&hl?h/Dr3)_]N&O?P/SUuZMqu'b.:L[X;ugVk9AV+F'!RH;K5J7!g?(2)'mYK=OI1Q\V\C/aKa*l,UGZ-*F)%/@OmPjV7O_NW9r^/<'XS+%.8RWKh0%3d#XWN?Dd/]`gpRT?jX6n0;c56;CXTdtTnm;$NhGmc5^:UqdeR*-M.5V>&h'(E_UHE"iV1V%r6H>ia[#AMHWiW5jTsE#,G&3`b'^6k+AA69PtW!=Ar2rL!EepZ,=VeuF'W)qU^Km:8)iSIu&,rE%e]gfY/o9j;epo2[^dH_%@B-*q<\8T8d'5gPfUEY>t4(`I7h0kiFXWfoacRUGUfJY##AoHSDB#77m4A(K24c#eb]BF"lcFnAT0/#oD(BEOJq\IMZFFt&EpYHh';^lAhPf32`)R#h#W'J.9>9M#oZs5ZM]s=+8-qK;%tKGTT^T6fktR<%4ntuQ%+qVEc:\!pX)#0"?I,M!UVcZ;.4_Z2su6:Edt:(%cEk6U!Fe`!r[U0i:[g]:3N03QE)\Xr9Q]lcspdCgO2JXjZ/Po[8O;Ge"H^el,Iqgi'RQs#)ll4M\SinGP(14I+H7h%>MS$&.!A#ZItfSVi,BKEqM#IO)j$!;!RXr)WI=s!^-iFZ0jN[O>u$0P\(]uFK[OHZ!7M8SLGFjE;O??A9m'=G"i[O>3/1b1u`(&L at 1:L1)C&pSNE74F^&EJ.!D[IBi*!U>Ba^+TZdG5[PmU]aa[W&Ek+Tk^`PSR>A*6FS=k-]/FSG*B5$.=V(l2^^B2k(dPUm%nt/U/QFs*WH)Fu(,#4n"m#n!kS1n$]1[g1Oo6u:907sgoEBf;#+8j`:a;e8cGnR%b^#08_'%+2,U465lA'i$>Di2&)`5?kY^o'cP)O4e/!tJ3n-O0Mc_pj8l%BUD";;i".Zgk2chn,QUBo!~> +endstream +endobj +12 0 obj +<< /Type /Page +/Parent 1 0 R +/MediaBox [ 0 0 612 792 ] +/Resources 3 0 R +/Contents 11 0 R +/Annots 13 0 R +>> +endobj +13 0 obj +[ +14 0 R +16 0 R +18 0 R +20 0 R +22 0 R +24 0 R +26 0 R +28 0 R +30 0 R +32 0 R +34 0 R +36 0 R +38 0 R +40 0 R +42 0 R +44 0 R +46 0 R +48 0 R +50 0 R +52 0 R +54 0 R +56 0 R +58 0 R +60 0 R +62 0 R +64 0 R +66 0 R +68 0 R +70 0 R +72 0 R +74 0 R +76 0 R +78 0 R +80 0 R +82 0 R +84 0 R +86 0 R +88 0 R +90 0 R +92 0 R +94 0 R +96 0 R +98 0 R +100 0 R +102 0 R +104 0 R +106 0 R +108 0 R +110 0 R +112 0 R +114 0 R +116 0 R +118 0 R +] +endobj +14 0 obj +<< /Type /Annot +/Subtype /Link +/Rect [ 120.0 655.001 149.98 645.001 ] +/C [ 0 0 0 ] +/Border [ 0 0 0 ] +/A 15 0 R +/H /I +>> +endobj +16 0 obj +<< /Type /Annot +/Subtype /Link +/Rect [ 120.0 644.001 179.44 634.001 ] +/C [ 0 0 0 ] +/Border [ 0 0 0 ] +/A 17 0 R +/H /I +>> +endobj +18 0 obj +<< /Type /Annot +/Subtype /Link +/Rect [ 144.0 633.001 176.22 623.001 ] +/C [ 0 0 0 ] +/Border [ 0 0 0 ] +/A 19 0 R +/H /I +>> +endobj +20 0 obj +<< /Type /Annot +/Subtype /Link +/Rect [ 144.0 622.001 192.88 612.001 ] +/C [ 0 0 0 ] +/Border [ 0 0 0 ] +/A 21 0 R +/H /I +>> +endobj +22 0 obj +<< /Type /Annot +/Subtype /Link +/Rect [ 144.0 611.001 254.83 601.001 ] +/C [ 0 0 0 ] +/Border [ 0 0 0 ] +/A 23 0 R +/H /I +>> +endobj +24 0 obj +<< /Type /Annot +/Subtype /Link +/Rect [ 144.0 600.001 172.33 590.001 ] +/C [ 0 0 0 ] +/Border [ 0 0 0 ] +/A 25 0 R +/H /I +>> +endobj +26 0 obj +<< /Type /Annot +/Subtype /Link +/Rect [ 168.0 589.001 207.43 579.001 ] +/C [ 0 0 0 ] +/Border [ 0 0 0 ] +/A 27 0 R +/H /I +>> +endobj +28 0 obj +<< /Type /Annot +/Subtype /Link +/Rect [ 168.0 578.001 204.67 568.001 ] +/C [ 0 0 0 ] +/Border [ 0 0 0 ] +/A 29 0 R +/H /I +>> +endobj +30 0 obj +<< /Type /Annot +/Subtype /Link +/Rect [ 120.0 567.001 210.83 557.001 ] +/C [ 0 0 0 ] +/Border [ 0 0 0 ] +/A 31 0 R +/H /I +>> +endobj +32 0 obj +<< /Type /Annot +/Subtype /Link +/Rect [ 144.0 556.001 268.43 546.001 ] +/C [ 0 0 0 ] +/Border [ 0 0 0 ] +/A 33 0 R +/H /I +>> +endobj +34 0 obj +<< /Type /Annot +/Subtype /Link +/Rect [ 168.0 545.001 211.33 535.001 ] +/C [ 0 0 0 ] +/Border [ 0 0 0 ] +/A 35 0 R +/H /I +>> +endobj +36 0 obj +<< /Type /Annot +/Subtype /Link +/Rect [ 168.0 534.001 210.22 524.001 ] +/C [ 0 0 0 ] +/Border [ 0 0 0 ] +/A 37 0 R +/H /I +>> +endobj +38 0 obj +<< /Type /Annot +/Subtype /Link +/Rect [ 168.0 523.001 203.56 513.001 ] +/C [ 0 0 0 ] +/Border [ 0 0 0 ] +/A 39 0 R +/H /I +>> +endobj +40 0 obj +<< /Type /Annot +/Subtype /Link +/Rect [ 144.0 512.001 314.52 502.001 ] +/C [ 0 0 0 ] +/Border [ 0 0 0 ] +/A 41 0 R +/H /I +>> +endobj +42 0 obj +<< /Type /Annot +/Subtype /Link +/Rect [ 144.0 501.001 263.73 491.001 ] +/C [ 0 0 0 ] +/Border [ 0 0 0 ] +/A 43 0 R +/H /I +>> +endobj +44 0 obj +<< /Type /Annot +/Subtype /Link +/Rect [ 168.0 490.001 216.88 480.001 ] +/C [ 0 0 0 ] +/Border [ 0 0 0 ] +/A 45 0 R +/H /I +>> +endobj +46 0 obj +<< /Type /Annot +/Subtype /Link +/Rect [ 168.0 479.001 312.72 469.001 ] +/C [ 0 0 0 ] +/Border [ 0 0 0 ] +/A 47 0 R +/H /I +>> +endobj +48 0 obj +<< /Type /Annot +/Subtype /Link +/Rect [ 120.0 468.001 178.87 458.001 ] +/C [ 0 0 0 ] +/Border [ 0 0 0 ] +/A 49 0 R +/H /I +>> +endobj +50 0 obj +<< /Type /Annot +/Subtype /Link +/Rect [ 144.0 457.001 177.32 447.001 ] +/C [ 0 0 0 ] +/Border [ 0 0 0 ] +/A 51 0 R +/H /I +>> +endobj +52 0 obj +<< /Type /Annot +/Subtype /Link +/Rect [ 120.0 446.001 195.83 436.001 ] +/C [ 0 0 0 ] +/Border [ 0 0 0 ] +/A 53 0 R +/H /I +>> +endobj +54 0 obj +<< /Type /Annot +/Subtype /Link +/Rect [ 144.0 435.001 193.43 425.001 ] +/C [ 0 0 0 ] +/Border [ 0 0 0 ] +/A 55 0 R +/H /I +>> +endobj +56 0 obj +<< /Type /Annot +/Subtype /Link +/Rect [ 144.0 424.001 209.53 414.001 ] +/C [ 0 0 0 ] +/Border [ 0 0 0 ] +/A 57 0 R +/H /I +>> +endobj +58 0 obj +<< /Type /Annot +/Subtype /Link +/Rect [ 144.0 413.001 188.43 403.001 ] +/C [ 0 0 0 ] +/Border [ 0 0 0 ] +/A 59 0 R +/H /I +>> +endobj +60 0 obj +<< /Type /Annot +/Subtype /Link +/Rect [ 120.0 402.001 203.58 392.001 ] +/C [ 0 0 0 ] +/Border [ 0 0 0 ] +/A 61 0 R +/H /I +>> +endobj +62 0 obj +<< /Type /Annot +/Subtype /Link +/Rect [ 144.0 391.001 182.32 381.001 ] +/C [ 0 0 0 ] +/Border [ 0 0 0 ] +/A 63 0 R +/H /I +>> +endobj +64 0 obj +<< /Type /Annot +/Subtype /Link +/Rect [ 144.0 380.001 182.32 370.001 ] +/C [ 0 0 0 ] +/Border [ 0 0 0 ] +/A 65 0 R +/H /I +>> +endobj +66 0 obj +<< /Type /Annot +/Subtype /Link +/Rect [ 144.0 369.001 198.99 359.001 ] +/C [ 0 0 0 ] +/Border [ 0 0 0 ] +/A 67 0 R +/H /I +>> +endobj +68 0 obj +<< /Type /Annot +/Subtype /Link +/Rect [ 144.0 358.001 205.66 348.001 ] +/C [ 0 0 0 ] +/Border [ 0 0 0 ] +/A 69 0 R +/H /I +>> +endobj +70 0 obj +<< /Type /Annot +/Subtype /Link +/Rect [ 144.0 347.001 212.3 337.001 ] +/C [ 0 0 0 ] +/Border [ 0 0 0 ] +/A 71 0 R +/H /I +>> +endobj +72 0 obj +<< /Type /Annot +/Subtype /Link +/Rect [ 144.0 336.001 188.41 326.001 ] +/C [ 0 0 0 ] +/Border [ 0 0 0 ] +/A 73 0 R +/H /I +>> +endobj +74 0 obj +<< /Type /Annot +/Subtype /Link +/Rect [ 144.0 325.001 182.88 315.001 ] +/C [ 0 0 0 ] +/Border [ 0 0 0 ] +/A 75 0 R +/H /I +>> +endobj +76 0 obj +<< /Type /Annot +/Subtype /Link +/Rect [ 120.0 314.001 166.1 304.001 ] +/C [ 0 0 0 ] +/Border [ 0 0 0 ] +/A 77 0 R +/H /I +>> +endobj +78 0 obj +<< /Type /Annot +/Subtype /Link +/Rect [ 144.0 303.001 235.08 293.001 ] +/C [ 0 0 0 ] +/Border [ 0 0 0 ] +/A 79 0 R +/H /I +>> +endobj +80 0 obj +<< /Type /Annot +/Subtype /Link +/Rect [ 144.0 292.001 219.52 282.001 ] +/C [ 0 0 0 ] +/Border [ 0 0 0 ] +/A 81 0 R +/H /I +>> +endobj +82 0 obj +<< /Type /Annot +/Subtype /Link +/Rect [ 144.0 281.001 221.76 271.001 ] +/C [ 0 0 0 ] +/Border [ 0 0 0 ] +/A 83 0 R +/H /I +>> +endobj +84 0 obj +<< /Type /Annot +/Subtype /Link +/Rect [ 144.0 270.001 223.97 260.001 ] +/C [ 0 0 0 ] +/Border [ 0 0 0 ] +/A 85 0 R +/H /I +>> +endobj +86 0 obj +<< /Type /Annot +/Subtype /Link +/Rect [ 144.0 259.001 205.65 249.001 ] +/C [ 0 0 0 ] +/Border [ 0 0 0 ] +/A 87 0 R +/H /I +>> +endobj +88 0 obj +<< /Type /Annot +/Subtype /Link +/Rect [ 144.0 248.001 196.2 238.001 ] +/C [ 0 0 0 ] +/Border [ 0 0 0 ] +/A 89 0 R +/H /I +>> +endobj +90 0 obj +<< /Type /Annot +/Subtype /Link +/Rect [ 144.0 237.001 230.61 227.001 ] +/C [ 0 0 0 ] +/Border [ 0 0 0 ] +/A 91 0 R +/H /I +>> +endobj +92 0 obj +<< /Type /Annot +/Subtype /Link +/Rect [ 144.0 226.001 221.74 216.001 ] +/C [ 0 0 0 ] +/Border [ 0 0 0 ] +/A 93 0 R +/H /I +>> +endobj +94 0 obj +<< /Type /Annot +/Subtype /Link +/Rect [ 144.0 215.001 216.21 205.001 ] +/C [ 0 0 0 ] +/Border [ 0 0 0 ] +/A 95 0 R +/H /I +>> +endobj +96 0 obj +<< /Type /Annot +/Subtype /Link +/Rect [ 144.0 204.001 199.55 194.001 ] +/C [ 0 0 0 ] +/Border [ 0 0 0 ] +/A 97 0 R +/H /I +>> +endobj +98 0 obj +<< /Type /Annot +/Subtype /Link +/Rect [ 144.0 193.001 233.05 183.001 ] +/C [ 0 0 0 ] +/Border [ 0 0 0 ] +/A 99 0 R +/H /I +>> +endobj +100 0 obj +<< /Type /Annot +/Subtype /Link +/Rect [ 144.0 182.001 212.32 172.001 ] +/C [ 0 0 0 ] +/Border [ 0 0 0 ] +/A 101 0 R +/H /I +>> +endobj +102 0 obj +<< /Type /Annot +/Subtype /Link +/Rect [ 144.0 171.001 205.08 161.001 ] +/C [ 0 0 0 ] +/Border [ 0 0 0 ] +/A 103 0 R +/H /I +>> +endobj +104 0 obj +<< /Type /Annot +/Subtype /Link +/Rect [ 120.0 160.001 160.56 150.001 ] +/C [ 0 0 0 ] +/Border [ 0 0 0 ] +/A 105 0 R +/H /I +>> +endobj +106 0 obj +<< /Type /Annot +/Subtype /Link +/Rect [ 144.0 149.001 227.31 139.001 ] +/C [ 0 0 0 ] +/Border [ 0 0 0 ] +/A 107 0 R +/H /I +>> +endobj +108 0 obj +<< /Type /Annot +/Subtype /Link +/Rect [ 144.0 138.001 215.65 128.001 ] +/C [ 0 0 0 ] +/Border [ 0 0 0 ] +/A 109 0 R +/H /I +>> +endobj +110 0 obj +<< /Type /Annot +/Subtype /Link +/Rect [ 144.0 127.001 190.09 117.001 ] +/C [ 0 0 0 ] +/Border [ 0 0 0 ] +/A 111 0 R +/H /I +>> +endobj +112 0 obj +<< /Type /Annot +/Subtype /Link +/Rect [ 144.0 116.001 192.33 106.001 ] +/C [ 0 0 0 ] +/Border [ 0 0 0 ] +/A 113 0 R +/H /I +>> +endobj +114 0 obj +<< /Type /Annot +/Subtype /Link +/Rect [ 144.0 105.001 255.08 95.001 ] +/C [ 0 0 0 ] +/Border [ 0 0 0 ] +/A 115 0 R +/H /I +>> +endobj +116 0 obj +<< /Type /Annot +/Subtype /Link +/Rect [ 144.0 94.001 243.42 84.001 ] +/C [ 0 0 0 ] +/Border [ 0 0 0 ] +/A 117 0 R +/H /I +>> +endobj +118 0 obj +<< /Type /Annot +/Subtype /Link +/Rect [ 144.0 83.001 233.42 73.001 ] +/C [ 0 0 0 ] +/Border [ 0 0 0 ] +/A 119 0 R +/H /I +>> +endobj +120 0 obj +<< /Length 536 /Filter [ /ASCII85Decode /FlateDecode ] + >> +stream +Gb"/i:JZTs(rl#lMOr%8J at 25'i96md1V7>IMt)=%=\')JC`:(%/RZ[I-5ql2pkHsFDg=quGoh2Lk-6_#3$R"m-r(eA[LPT**s<0jMNUes8/+:]gW@^gRj+2>;kHJT at _Kt-U@(Z%4g)*f.]G177[]i7Q]/?n"9JWCM^W'>R at L!5'OUK]Ds at rKlh?B2h6aN!nM-A?Y8mlSkkDD-(sE=!@[e*XR;CZcXAlV[gq7q0^GM>jN-u4%5X5R'k'5P)1:2L*ZXV#%<.nc=!tZ$j8'\!Pc>L4<+Tgure)p:'\Ld#OP35F2Khj#-Xau"Q^6CYWnCIf02KR0dkJD;c"Zu0(V"C$P3lr%g3.Of%DPo*a,a*)?II35X7TlMjUq+o!saI7:+Pf]?B.h55)R=J:RV4]d4EZP3P/Q*nqblg)i'A0Lr3QXJo)GFY9514P3A**dY]TU>XMV<5?095]EPt +endstream +endobj +121 0 obj +<< /Type /Page +/Parent 1 0 R +/MediaBox [ 0 0 612 792 ] +/Resources 3 0 R +/Contents 120 0 R +/Annots 122 0 R +>> +endobj +122 0 obj +[ +123 0 R +125 0 R +127 0 R +129 0 R +131 0 R +133 0 R +135 0 R +137 0 R +] +endobj +123 0 obj +<< /Type /Annot +/Subtype /Link +/Rect [ 120.0 719.0 223.88 709.0 ] +/C [ 0 0 0 ] +/Border [ 0 0 0 ] +/A 124 0 R +/H /I +>> +endobj +125 0 obj +<< /Type /Annot +/Subtype /Link +/Rect [ 144.0 708.0 193.43 698.0 ] +/C [ 0 0 0 ] +/Border [ 0 0 0 ] +/A 126 0 R +/H /I +>> +endobj +127 0 obj +<< /Type /Annot +/Subtype /Link +/Rect [ 144.0 697.0 223.42 687.0 ] +/C [ 0 0 0 ] +/Border [ 0 0 0 ] +/A 128 0 R +/H /I +>> +endobj +129 0 obj +<< /Type /Annot +/Subtype /Link +/Rect [ 144.0 686.0 222.31 676.0 ] +/C [ 0 0 0 ] +/Border [ 0 0 0 ] +/A 130 0 R +/H /I +>> +endobj +131 0 obj +<< /Type /Annot +/Subtype /Link +/Rect [ 120.0 675.0 177.22 665.0 ] +/C [ 0 0 0 ] +/Border [ 0 0 0 ] +/A 132 0 R +/H /I +>> +endobj +133 0 obj +<< /Type /Annot +/Subtype /Link +/Rect [ 144.0 664.0 210.93 654.0 ] +/C [ 0 0 0 ] +/Border [ 0 0 0 ] +/A 134 0 R +/H /I +>> +endobj +135 0 obj +<< /Type /Annot +/Subtype /Link +/Rect [ 144.0 653.0 177.33 643.0 ] +/C [ 0 0 0 ] +/Border [ 0 0 0 ] +/A 136 0 R +/H /I +>> +endobj +137 0 obj +<< /Type /Annot +/Subtype /Link +/Rect [ 120.0 642.0 155.55 632.0 ] +/C [ 0 0 0 ] +/Border [ 0 0 0 ] +/A 138 0 R +/H /I +>> +endobj +139 0 obj +<< /Length 566 /Filter [ /ASCII85Decode /FlateDecode ] + >> +stream +Gat$u9lHOU&A at ZcHqY#iq(N#UOh+G;8gJG7H>pN,ee/A?2Oj^DcGFI8P:C:b`Uc314ruMoDj,+OK&hmAF[92rUngX=P2_gj.]4`SF[J0i8:)W.2\-+WODmjAOnL.X99Q.8K=i]^bKg1ON+Q(rP1kPs\)].p3SrP!">DO"K3Y*ff)*824n=t,IC_><<,#j52s!>!%ZCW>1S1gn)`A@/IKFT=n/BA%?4,Gc>o(/?AH`YtN!>>7<5\0^SHSO3$oD=`:q!>n>Lps5G6O299 at 2~> +endstream +endobj +140 0 obj +<< /Type /Page +/Parent 1 0 R +/MediaBox [ 0 0 612 792 ] +/Resources 3 0 R +/Contents 139 0 R +>> +endobj +141 0 obj +<< /Length 1955 /Filter [ /ASCII85Decode /FlateDecode ] + >> +stream +Gatm<968iG&AJ$Cn5a0k7ehH)<\&;?*@GjIng$"c%kn/Y(fLPFP#@iXh^&:8$]26\2T#oG_0p`6//Ga%>eI`V*'Y]_)EJsP_'q6,(SfN-qP at tAk.J!$nBZ+=>d0:,e1Ht9D%\2HQaVBOP7]mKOfIi1u>U9hXLirD'-s- at D"P03Ou5b$O[m-[_?(b`r#Ue(ekMe^u)LFD-6;(`<2Y[D7F^lWikBbF7/&2CoD6+f!V2 at i0A-eMB#1Cg*XCP&(AQkla$E_2otbm9-\\As"8CSEcVASA$H^3lSTCPmu'oK$&'m!oLco\Z/\j]T@]C$>l^H]LFi*s:7m$p5V?^Kch#jFma1uB^Si7TUn`D3p?L4rbB0bK!6dp'i#]raScBc?3AB76gZ7ZUjG/V(;[Gn+0N[)t<4s0n1(S+*3,AEmT=O'u17iW1q4(QWFY-#8UV.u\fhd/DO-^*Q3f/PY%^4Vt`Le?hj'[o%bZ4n'_,A]i-3hMNim)IDJH+*-^/P,rS+.=]QVE$Di>6aGcaq;R[gZ3h&XY.PiCZ`+33gq?[J$.IM'1 at uXd/S at EP?a.f^/CsNd+Yc+]`1]bV29(K)JEV7=Z[2$Jcqb@;s_.JCbFc0Ykqjbd(%%s&#T'asoS.("&Gc<7rXietbCDQu._d?c!56Al7jk)4T_4XGkh\ojG1%EZNU-8F74`ZGDh`a6:^#`g`Wksa+m/$^P at 6b&Q1Xs*g_ilO:E)+slQ>>9"2k0C:rYiBY41nM^SQLqTo[@p1U4j>5mtVa=P:;-V.TV#&U\'0BJQr-,s`"k'Bn0eLNWk9*IH`,hjTbUL)2#h[tjnu[K_7eG at qMVr"M%)3]XEJn>'#8D4,+mej]]3gX[__^2^5##Pap('S:qUV44]MlWFq*<6pJ`eRcbZs;$n'mk%^YBY4FJtR&P3!Ib8YP=Pj

f8Hn_gB`B[?`9@!;E`UdgIe;`$ECJQ'59l$G6*EMO;4"^j57m&5MPA?)8C at 9gfT/gG5["=[nrM"RFmm$iL3:\3fUg]2Altlpk1JX<79cr6^?+7,k7d61s=(Cj=K$.ib +endstream +endobj +142 0 obj +<< /Type /Page +/Parent 1 0 R +/MediaBox [ 0 0 612 792 ] +/Resources 3 0 R +/Contents 141 0 R +>> +endobj +143 0 obj +<< /Length 1080 /Filter [ /ASCII85Decode /FlateDecode ] + >> +stream +GasIgh/Ac:&:`#5_.+uI*oE&BG$:_;RaapqC"n7B-F"J*C7 at WXYFiX]cRE^1V7JbVj*)S/qk;YiIZ1o^6XfBtou?_9S&"Xg?f5K=o"E7C:nB"?dAE?t;82GAi9G8684^b!gt`EE&g=dGb+kBd$uq"XJIr6X',WG=gHLegZt're9Fhcj8MW*E:i\4D1B"Ie^UR4f5\X)]J:7Iql8'5a0Ve$$CcN]KbbiC6,=h">lt+;+/Xf;.Z,!f=.ecn]u0=[mRObCrkkg9`6U&>nbe3Kn-i,a&+58IGANK%ZtKf?pTSeufKJA3+.42qV0>Unfk"JT at f)6iS`?B), at oF<^Z2/(%'++NfD,4:T?@!gkMfWTlt1^sMb,fl[=iYlMTM9^)@VR$rssSs^JL1r$897kP*]Ob;b>U&A':TPEP;'pEo!)n1urb-f:V.C5a=t=B!CAVMM0j#t1X5L9AUcS;*4MXmFVQN&87&8mI$.nr at 1-*;qB,A7HBF$4omhV$C^bYHJsHlcJUpZHS/4bT<7Z5%4^Vk[Df`A9D(>4L9"o\f6/iEJi0Jpr(E3-Pkbt8YC*V)6M#jOs\;bLUR+'E7:3*9Yr#CpM[fM"qJ\,0dKmel-aL$"]qpedW*7Id$:F.LYAAk]-[+P at De@'q:.jrC'VXL[<173F->!i#(*oq>fs0qT0P&(X$un!R;(2u~> +endstream +endobj +144 0 obj +<< /Type /Page +/Parent 1 0 R +/MediaBox [ 0 0 612 792 ] +/Resources 3 0 R +/Contents 143 0 R +>> +endobj +145 0 obj +<< /Length 2312 /Filter [ /ASCII85Decode /FlateDecode ] + >> +stream +Gasar968lH%)2U?kZ2?9B(^W6Q=T8P3bd&$Ro at dg/9+a-oSO]5gg=Dd!(B_bNFS#^LlVZEJfshcIXSa&q(?XaOJQ[L*0++'F1Uo^=8mM at i\T2Cdu;7SiZ&m"n*;o4hG8NDiS=9$_Qq\9 at cuHX[f"1mSVFdk7!l4$Id\UI^2X'k%_ol^/k^duc"bQA7Ec3>R.4J2f=^)0PY\#h[CsM<'Bf4%cO4_,KoKt_nIju^kEC-6MtA9ulC+?"m`g)XZURDU`&ou2Omg9A5Bar2EHbq)YujN][nj'8n#SCj!Z&?ZkhL:_(T5M%5MZ:^Moj!HUR4c&%To='7maToB(i:,B]7[*1t6-2u at S$P;Orr"?,dPjBS$,H]I[#/[tiY:2ST:)FS3fFRqfdIRAF:+b([[B!IXD`Dh!OA,n'=A at ggV(@#iMQ%=FU`Ls7E==*f>4]0NWbG:os7ae,b]GHtY?6^]$9INF%>,hb?a*al[^k[g1V*UE"JaF+hq2eD-+:ot9`i0nJ+*`PBfkB3Tjp_ at s3hGJnp?cPIk(%1C!RgNp)?E,l9)3c%-\UGRFac3oeLn at ZTAZOWCnsLL$Gtg1Tu/`'K4UfOA(ts`nPM$DtcW`#&>XaHDr``_Ul=acuB)c].hI/2WnR/8HBsjD$Ie%Lk7++m!/XE,QVs"A1&IF\[19[6G.gM]YUs4aJ\QEd&4LfGL+^7+S8g4VgFsN?fXeLQ/BolMnmM<(a at 9d//096j5oFN":rD*E0WY,,F.8u`, at EX`/CW1?Y<,u-=XH:=:c^L--"\DFbW,q0X)]@=q`fK)2.KH%4t"Z-`mG/2%*^Q;gN>u;JS/j:j5ICV#9X^Uh=$\oAi/[T41k[S?:?,M`E at jR"iP_$"9Begm0phloOeX,ZY0T"%Hn?F-Tl',aUp[F;3TmOM<90*@$,sf7aNl7$0-7B#@2mW"hgsommqR1b3%rgP@<(oMn%$Jf'UA;f=l\s6%pWL8m7j`,BU<=pe:FRX3(`eht\QB!Pm]dEa%jXH"ckE1dgGMd5ZTJ[Z=_8r`Yl$%t;(jKRr32?>LR.$-U!F6l:^MV7c>(#@JBuE9bN&jAPnm"HF;l;dT-/Y%a9R[TpP*jAR\:F`MMLSNGjXapD9>qBEE/]2*2!&'iZWSDt_G6e8FK$Q[H=;h1NHFKIYcnB:n9=9c.7ncTMA3!d)fTNHC,iWQ7J-JCm_4;gF*2X4%o/-:0ZUqN?21p\/SAcT6i$X;on-6soX:`/X-;j//_ch0\Peb=kkrdCuEX-]TD/39j?0t`mFTgE'$0e^HH4ETV.]Dnu_P(PSI_iABNP,IZY0p8AedmP'9C?pSQU.?^C+F0Y#0lgXaPIa;N#U4HL/aGo`J*UlILrgd.)1Z6^!t[l[XUUHP]f[*M%A5H8]j\a%_r*$]rR35>c,7i#pnN[J>/AjUQ^nL&U;e>$h&k'482If0[Lb2.4YC!!q8V7Y(U0])ol5^k`p,\cg.:M;B30%eql?UKA8KKlp3Wp;Rn:>*Ljli])eg>N!gj&X0VQ!r3+2P#f#On;n0O'M$($W)43XDml,A+0@>Sa[:L2*_M/mk4OJ0H`(nT0q!>aP=?2L0Qk$:.,_].>YD+)j.CKA0q&*0Gc=G9AHg!'EME,^f+?<*M4j5M["uXWZo_8G>MR,p5#'!Oll at NRe.&Ed^?WNpOeR&uIN-QbI=s:s&"STl4q=ndQVC08'>>LRL.$QE,mV!;pA['%t)ieqFF+L/1fN'$L"hb6Ed/:;QuQEC;\a-CVJ"^etnc`O7m=Y:^(W[o!p)F!L?aii$2o='sq$--NM +endstream +endobj +146 0 obj +<< /Type /Page +/Parent 1 0 R +/MediaBox [ 0 0 612 792 ] +/Resources 3 0 R +/Contents 145 0 R +>> +endobj +147 0 obj +<< /Length 365 /Filter [ /ASCII85Decode /FlateDecode ] + >> +stream +Garo>9i$Er&;KZOMVa"RCZu'G*]MK!#GVSanPGQ$@L=Lt'E>`L at 2Eq*>UD7jpN`[-6fq\3V'r-mU.fnJQ!T9FM\(SY/4M'5M*tL+T)IFd['"9Rd+Ees5_*fA`u3dK!Uae`*:;7kDIU)C#6B-:g&75#0Tr:@a+-;\j=V.tD$O(obYmc018[2a$`B-\oc;U.=8sh1Z*hF$BHuXbjGT!!N^e/qYOm%fXiW^q`!M><7L9k)VR?1lR0!$#p._VL\cPgg7b+`sn2Bl%It)Wfku\38OdL1SZ4;uiT"Msc$1`0EMe*Yq,2E:<+sGo]qQXhZ:=XL;P`F#L`-uAOoTtDs+T*F&JT/b;>t.6+"E>4R!G(i*Y5~> +endstream +endobj +148 0 obj +<< /Type /Page +/Parent 1 0 R +/MediaBox [ 0 0 612 792 ] +/Resources 3 0 R +/Contents 147 0 R +>> +endobj +149 0 obj +<< /Length 462 /Filter [ /ASCII85Decode /FlateDecode ] + >> +stream +GarVKb>,r/&A70VHn802r.pR/8.-D6;2#]ZLdPjb_'4_gS[=Wba*kb7V93@^1:*2#lm.Xpmj/Q#bq_l],-N8A3&G#"Q-$2FY;m>^OX*]#b`[U$^';4#YkbUS_O22D-8'I0+p@";IOT4]Kqb(G$4@,c#>7IU_7J.^5hE[S?t&>$=(%.FD5V1JXd]q`h5lR;pZY!=S*<"f?3.VGhKR]i*(m2Rn)?oo(eH%Yca +endstream +endobj +150 0 obj +<< /Type /Page +/Parent 1 0 R +/MediaBox [ 0 0 612 792 ] +/Resources 3 0 R +/Contents 149 0 R +>> +endobj +151 0 obj +<< /Length 828 /Filter [ /ASCII85Decode /FlateDecode ] + >> +stream +GatU295iQ=%)1n+kdGRu3(]EHH+.m4JIYn8,2"Tl%]Ub_#3*[>GAI3Vj@:CSNpC.A/gAQ$r:ghgbOt5>NJE<#<2+Ll_ru)0&2lb)HjU^IJ:eOUXV:>:I]!g,JUX?dB7o3"?t3S0#6:I*6:_Ht7p!1X[:_$V^tEFeB2.X1:L0K'oli&0etonM*!J"a,t[91;hjnQ^ih'YDiIE:#uK at 8fl^4MN!(gWe"1/*s4Q+P8 at kYVC&:9!Q8[c(#=@\*9rnoG/d/L'\';b;Rq:0#JmYX15lW',R,m!gp7qn:*'nPo`o([oRTZlEsM_#(c,>ROGRV'U8>8r?X4&1#da[JeiD*U69oe>bNr8Tdc5OPF-Wk9F`LVY at kW(rtUNa?b]a"2.p`#KgsJVIWi7c2)K*k4)9&Qd+C.#/qA)$$QJUh>\j5F~> +endstream +endobj +152 0 obj +<< /Type /Page +/Parent 1 0 R +/MediaBox [ 0 0 612 792 ] +/Resources 3 0 R +/Contents 151 0 R +>> +endobj +153 0 obj +<< /Length 1187 /Filter [ /ASCII85Decode /FlateDecode ] + >> +stream +Gau`T966RV&AJ$CE(i;M!K$P&kqn/jViN8e[67oZD)GG*4IkrV0*44=#pY2%R8,(b at aV+Pp=j.]Hl"GRm]h<_1C12sY8oQ"fpk-BZNp6A2iM"&oD7di<5*5>#ajXtmc+RoFQ>(?rB:Osk_6]6f3I'a&U\7.oL4O>EpKjP-S#Dehq6H`2P:KiI8`#QWe20;c./DYYW]fA4+Sa*^!)?pjnP(SDS:Q?T^SA>X_piGfXufjiDqKc;Nc2"cVfQYq0rm^c\X??Ui&d/A4qGhcP8,X%1_Pn!teDJW\2$IKLX&V\4.#;1jV-Pnfj>5.^((`*R'cV,,3Vm-I\4_+of!6HN/IB%H"c8'?1 at WRDMK#Oh;!SqDseDY?"/s-^O5G'al4[C0Qq1[Yt8?'#\J+aS*mt?)$VqF/_KZ&9E^b6G2q:YVrb4f%?D6)Btn6HTHH.Xp-%9,;2MIU,JT9'I&4CHH)m@\2%#6Y*LjRd7hgu,0C;%RI#J;7'!Im(Z=9E*3nY"]S2FFT!4/o&nb.L0?,>uI at esSU>1`AiS/F]J-_:P#uUQ--XeA8pjZjpk71`0,$O.u1>Uk6bYkQLES[04"kNA;&aF&t5U7MIXCtYFp)W%>GdoMB#nuqDmag1X6pa:UTH6M=!RJZu=qEAP(\m4`Gk1!8SQ33Xga0,NF"6WAf/[a^XM;Bb:8,(dCNb#9ac-TAC0[?6pa:sJnC4k*0!W91$g=1WoB3ZkZ_hA;_5Q, at 5-%k<3YoC"eL'n-UQJ,`4S'F^oDTP_@;LQV?IFA'0q[+3Nu,S.hk.KIrDqg!T^(*5mueOR`Ri(7XD[YM'49O=%M;pTqshIDr'!AQGl.ZG4]Tl~> +endstream +endobj +154 0 obj +<< /Type /Page +/Parent 1 0 R +/MediaBox [ 0 0 612 792 ] +/Resources 3 0 R +/Contents 153 0 R +>> +endobj +155 0 obj +<< /Length 972 /Filter [ /ASCII85Decode /FlateDecode ] + >> +stream +Gasao997d\&AI`dEiPG*\@1EW:2arAV6/I:Wf>_"l+mM/7%76kZO?fIc3l]?+UAC"SG>9'TBG0[J+iE5D'9^'B)0%V[%:pOK'J+B(B\>JcN/tcQ60=\mN-X)k13n_s/&VQKqM=?TGE&s\Nq);Y)R27&+,.I<3GVEtMfana-Plo(3>F8E^[o'0m/3+]#"(o&CVJ%F%^M at NYl2i_'tB8-B/o9P>N:<.$>IXMTAHdD6CO]nhl<`%ao+3>mh:35G(>qY4Y$I#(38/+Qs^GRbpTfOWa!J!FW(CS'/53Z%rcD:A+H9VJhS=C/Q34ZAPe/W>X,)e#hs6gab)>NFYfX,$m;6j/YGY at 2o1,SRIWZqXEW\J0dJ]/5ShJddS-Yfop)6:q"_ at 1`^OO1i1DMlVL+]beeu)XoGb=Vp()Zf&*>reE!I?=p/HUr.,B`ZrM,LHHAb8'6)G_OjKpg)])#=#J24;=As'#p9]ZWb$>TH at 5KO=e(/t!'.+bHkAf/LRAS"A?t<[nfO'Ml?u*ZN>Z[RMOHES9=YQH/\U7.b=$5]k&nt/L5:]OMI+o=,&,EeL*#)aUQ5Q3nq5HX[V!_pN6ad.B43&$19>MjeYm5Z&^lP$*^qI:e1+<&PDclPH`TP0]@cRD=-?5>d_pRg$iq/i[=Qkja&s[jj]1]69g!s\M7i7PfOc+6+kFO,m_'C?WO/8#k8.X;D%@1;@AGKc`Qcu at oVl[im=m`M1/8ZeSV8p;ne>t1B25RP3t]PCZ>VGB at I7YkBD6j^OV2&/e2oSsBWHQ:!n%4s[)N&7D0<,~> +endstream +endobj +156 0 obj +<< /Type /Page +/Parent 1 0 R +/MediaBox [ 0 0 612 792 ] +/Resources 3 0 R +/Contents 155 0 R +>> +endobj +157 0 obj +<< /Length 738 /Filter [ /ASCII85Decode /FlateDecode ] + >> +stream +GauHIbDr&G']&?q?7(qVD;tkCQdMUe8falLeBOcs#>>=.9M3BJo(P#F@$2Y,;,q1;?f/a]pR-f`q>AbF=?tku0Q at ZV3>`n1_a"ch!"Tq=3/Iq;QUF]5n6DerX>.]@tUKS.QiV%;kaDL53bOaQVgnU+]e6qa?9kjjt5ZiUau7i`WXmMgoiGg5g7>Lll@">.l\.)'!@^7],[BZS<_;8K.IQcIT>fr\^FKA<$>Yb0K".+n`]sNB#ct$e'cqQ1.!,FSh4fj&,6lK2&,Crb-sfOPum+IhH:#1JJ@/T38jQA*=hfSrY&Z=4HB`b3E^.:L]fk82u?_hE_dfb0o*I$Sh^m))dolE!KgFDSHL1E3:ISMCLm)D5]1`RVTE;s+Y3coh[s2BtiW:r?Gbo)pJWBfJ at E#ukh8!=bXVI.[8+j\dYLU7FO(`<8S;-Mtc~> +endstream +endobj +158 0 obj +<< /Type /Page +/Parent 1 0 R +/MediaBox [ 0 0 612 792 ] +/Resources 3 0 R +/Contents 157 0 R +>> +endobj +159 0 obj +<< /Length 1111 /Filter [ /ASCII85Decode /FlateDecode ] + >> +stream +Gatm:9lJcG&A at sB#e`&TLugS7!\KN%Aq;P^!(GCDl5ge1Fp-H\=-D%phj5$gOcjR\Md>O5;LFunDe@)dO=oDf73WuW:82jDJC.t[,%s.S#n14[,m+Hd;7_\"?/;QP^5fotkspA8&V=VI!?D1HgBF0V+:*"Diiq7YforGqrH/faAiEsH0c#5(lFNtn<;E6,WN=L4?Wrdr:I(K_^mnLk"q9q7gtb\D`eah-"F4&&K*FJ0>]NddOMD at t8S(oT6NT]3C(^k5iXYPK;Dd\%KKFu;('?9V*1tWb"!W!T'np.n"\hQ9:(ZmN)r3MjFjKC+R\"Y`0a=!ZmXUdAF4f`o799a;)58In`G.+,C=TJb]Q%sJMui&$N&PB)d?+_I2j8Me#33 at 0oL;p?2^guQ%?)UEa=7;rX<,Q*X&TbmqGqH"]9jWKgl_.7nT4(/o$p-1m,^d[IVIBfGJ;bVGMRerlPZ**7i\5lI3ihh"PF'8TSO+b,&6#bM at 0EguC1$4+(%%>+F.G:Q\qO1\DQNai9S./]%)uQc":OmeN!KN;fT>9dNeF$6J2`iZ[6Zo1J#jU42csgd!k28,HEA]'A30?+)"70&D2V7o_2le3Y5eDmUk[Je,=(q93p"H<'JT"DJSRi"%CrGnA2c>107P'\4\%PQSW'(D^+s1_[RcJM8%Rm]h%4)G#ds1TESM![uoWGd'@Ful*j[R]Z3n0)0'5q?nim]cDBRs>K[H\6Uq7bsEMD`g28gsD4.c.Ym-7h>KYa-Tr at .'_K^Iq.)P;f-Aq'pRtV_,K*>l%co3%.<3`$76ofP+5F[9c*i>p:]90Ca0_CFpuWoda +endstream +endobj +160 0 obj +<< /Type /Page +/Parent 1 0 R +/MediaBox [ 0 0 612 792 ] +/Resources 3 0 R +/Contents 159 0 R +>> +endobj +161 0 obj +<< /Length 288 /Filter [ /ASCII85Decode /FlateDecode ] + >> +stream +GarVI]5GM?%,CLj*1`d^W!=W0%?M!(M?;Lh%RDTa*ZV)8iLk[-3K at Mm#dg+HGnDD@[LRU)^LP+/uN\;B["X,h7osd8,VjpR#":GLrEbF,<+SWN0(p[*j,3_/6[LP$>:fh[GR>Gb9C+`:%fPgVD*rMVn2[(>#OK6UN+cZ6qcT*AL(co~> +endstream +endobj +162 0 obj +<< /Type /Page +/Parent 1 0 R +/MediaBox [ 0 0 612 792 ] +/Resources 3 0 R +/Contents 161 0 R +>> +endobj +163 0 obj +<< /Length 1740 /Filter [ /ASCII85Decode /FlateDecode ] + >> +stream +GatunF!IkZ9XPF0e:!1aI]]j'^,U(TNItU\d)E9*MJLXQ/k(,^-e"q8Qh4_$XGa0)9mM_jJUPf\)1nM at mlJf[9J=#IY!+_4rhKDKgCrDPXIW94U1pkIMIq7.ekr)I/trAi"-0EWFN_3+ejX_Qt"=FQ+NkDNfR8XP&RgU\L&T1ctBo4$X$\ekl79Hr1@@(](c?pB(R7"+?H/sb/d13H!-f324cQL`[D-&kFWs!b+?TBRI;fO:kU(.F4_D3CG\S'$)6aimBU2NJH?#:p_m[#C0E9-Q$e=f>J.'M7=Z9>em*?Th3Cc2k[A;Pl%k]E%2J@)h;N;X5Xk7shhr8TSELf!S]9ksE=@?F>B&X[;3Gr]re8LD;nmLG=5r9?T^TQBeBn=[%R+=78nD>B$Y.6n)4_MnBkZ_gj"61_uDa#M;SZ(3XEjB!eL+aei'T?:kUHK3T==pb#rgBO0!IO0XEO.$jo at 7HmWQ`*P>;&9XQ4$b:C6G583Pc%<',B!$]%JF$B<+OrcBa.e]]7D(bDXZm7s2kk%,PuKY9(,Dd%V+KZN)4o(\(8mI'QOr6b8qP7!a=>l.RDEasAi-/(7q':4?fDq4-jI"ei\TrTkSneFkEgbbj//."O2cqZf>\8&`#m:%EPD^hHo at XaXI[InWF at uFU;X(3'(T3P?4+*j=0r0TH)7iIK26(7(P]r:ZGnk at 2/(Y7[4t:AQ1!cF#jHB*K)O'1e'FMcK>?f)Uf/9U'-`*NX&'X?I*m%2<[eWR%A[3>ROr$Gn'h>1AGi4c=A5Z(nta(1ReH:p48Dqj0 at Odr_4CrYMD,%2^N+[$la*1n2%cUp/%*./i1".om\GAktd8I-`=kL9HNM*hLU'Mk;'OaYk6H#3JSt!V#qLB+_oi1%pG>Cc@#>T]P(n&EbK;WQ?RF1(^Mik2>R3OG^MQn\^%5X:Jupm]_,jG.TeN%WA4L?#L]<-T;6%5WU0$-;nkcQ,2@@@3@%hl.\XVis>,BnIljSF3n2\]U*hK]r-K&P.=EWBP+oO>;kPdGT(KP6_?@'>OKfh")mep#W$?cB;an?]&%\Da"H#mf"A`qbDe`+2iCi%)1l at CBlm5fo#-%k%5YJmEiOAJ[;;7b-oDMS>0iF$F0_Sh?3+#8f/1]~> +endstream +endobj +164 0 obj +<< /Type /Page +/Parent 1 0 R +/MediaBox [ 0 0 612 792 ] +/Resources 3 0 R +/Contents 163 0 R +>> +endobj +165 0 obj +<< /Length 167 /Filter [ /ASCII85Decode /FlateDecode ] + >> +stream +Gas3+YmLOe&-U@/^LBee>^)B+0(jc2(4qWClqFMK7)Am^H?(nfgC-0]lSGZP!@fYAPlqn$83;O:fGAmHjmd3B^GbV?F4huZ at +k.?g.kjSh4X~> +endstream +endobj +166 0 obj +<< /Type /Page +/Parent 1 0 R +/MediaBox [ 0 0 612 792 ] +/Resources 3 0 R +/Contents 165 0 R +>> +endobj +167 0 obj +<< /Length 1056 /Filter [ /ASCII85Decode /FlateDecode ] + >> +stream +GatU2gQ'uA&:N^lo$f:WE.(6Cs%[bjh+kj^C%Br.TAD"?>sQklc=E$1abg+YUb6H8H*s6j%@Mn:'6-YQLMD^V&)uN=%cNo`P_=!=2a:)IX0i<$Sh6SX$37-#2_iE):tt>@SXVl\VN+o$TR$QQa)aJ.^1FqC*Jh0Z"Y/172Ft3>ENU^i4*=+T`6lE8Obqj;l1dXKNH1!CaAM/C.5![k$c1O\#X05SRQTf&.+P>aS]Y)7lehYUKn0r at fN].TI6c at b<89mC8o$#g&c^aF'6C7+1mN=/U5L(&hRscF:-t=''(t/JK=]'!H/JXJ+diESo]sDX<>(#T$nXeg$mob&iqq^4Q;L.Y)M$OAaT at nW;_lVp%HDO[K72OV29hF=O("^nNDsVGepbdf6FLOm2pK">H?shM)+-P:\I2>i//fa[Fj^2M+Ku*~> +endstream +endobj +168 0 obj +<< /Type /Page +/Parent 1 0 R +/MediaBox [ 0 0 612 792 ] +/Resources 3 0 R +/Contents 167 0 R +>> +endobj +169 0 obj +<< /Length 870 /Filter [ /ASCII85Decode /FlateDecode ] + >> +stream +Gatm:9okbt&A at Zc\97NWf/=J`Tp;ouHDo>Yg7Vc@*XFKW.fu\)gSDTuk1^"E)ekRq4dsF():,t;PAe,6Cmg(\m$`B65]^id'<3-0.0e. at 49AcCR/YM2q=#@Dfq\AdoY2dg0bI at p$If%e/e!bu!OYaXfJC(Zi`%O:JiHia"X\rL_ZjW)h7bZo3.#(:B*u61'f6QfER_1Je(rGcge!AcPdt1p9nZ7f64n0FS]KD*'PRs&.b:ehAHN/t'kD_aA8lE at hCsmmL4L0a#ERK;`ZdAB at laUfgYXJX#F:4hbDCANLpM>MK8Sb!^@pMq#Of!eb+9.GLdruj;XF!"94[jqPQHmg>J3G1leR%)+3ncc=hP!T(takFjZ2.Nc2b*8hZ&i26o*.-A?*%<.N%%j2nNXi,",_TWqpcVFbIah.E?8+Ol_/-&R/K4?5pN6*E.',OSe;1=N1O!C&G$1c'9[NUir"4nN(EE?6EmZ_BPd[!CE`?ASg@&51&n/dANeYq,n..qD)DNCVITUGH+5"h[]S9.m3eM\);Q^-mFVN^r4?''k:,sOpXM8`SmkEW7V',W'[$Tg=cAj/U2,E at 9c#0+3lASHdT0V^(EKt5L2$6=g>j#M9b,p6<@o-agGf%]dV9jTPQfMXK^m-&!uL\3UMp+d^+(/INjM2PUA]Ok*Fc64\c3J`$Uf3IH(@@p>$klPh/4/B+ONBbt.ZI4dL.on)jEJEa(Ql-e!N$nYZ;,)X"lITp$[=$I2Ee%FCN^suW5Aj.q70~> +endstream +endobj +170 0 obj +<< /Type /Page +/Parent 1 0 R +/MediaBox [ 0 0 612 792 ] +/Resources 3 0 R +/Contents 169 0 R +>> +endobj +171 0 obj +<< /Length 835 /Filter [ /ASCII85Decode /FlateDecode ] + >> +stream +Gatm:bDt:1']&?qhK;rY`_L?jMcO<:WRON\WL[]\V2GaAi$o8+R-F,7FWMeTlMSg7F at O?mPk2:H'XD8QEe#*(6(DTr304W>ei68AkRk%kW;KohnjN-[1K*JrJJ-,UkmT`VdlaD[hcl:@JhU6K-?uAilhal:7&&cpaM25Nfr$7/B0)%tMl/Z`)3JS+6GLNVI5?nSK>U;,u#Nmht[LBt4jiZbOZ)WOb_etRIe at GD7h,h4%hmF/$Zl9jk66OF@?lqdR=WUaPqf'*EFSfN7%"c-dJBD96Q,P@]klIUos +endstream +endobj +172 0 obj +<< /Type /Page +/Parent 1 0 R +/MediaBox [ 0 0 612 792 ] +/Resources 3 0 R +/Contents 171 0 R +>> +endobj +173 0 obj +<< /Length 680 /Filter [ /ASCII85Decode /FlateDecode ] + >> +stream +Gat=)9okbt&A at ZcI,#_$HMgKU=`&J`el[.9#?"L%(t=AL9rFj:b\=Z71KW:>Ju2M;_]G,.Wcn,Ie'-K4HXPRh*OO#qj/PN72GZDje)'(7FVUXR!,L"Zs'\qsIYDlieF*q.=G!UtMj#[9q\9e%VpSK_68;"LlqdchEegPrhr7qChlSM7I_K7["F-0nG:?PgOs&[PNCVQM'oh`&K2HW*rX<=[(R(o-HIbVE2!tMD)B,WJ;9XX!?P\LX"H7Edqh:JD`GcC(V\p?0OE\^7Qq-h\'DNV&2N8G-deR_VcUj:o418%=qeY#/4u\0d:729kWQrjj">VF*tWlp8BdR?6+&0A!AD*pq#~> +endstream +endobj +174 0 obj +<< /Type /Page +/Parent 1 0 R +/MediaBox [ 0 0 612 792 ] +/Resources 3 0 R +/Contents 173 0 R +>> +endobj +175 0 obj +<< /Length 1126 /Filter [ /ASCII85Decode /FlateDecode ] + >> +stream +Gatm:?#Q2d'Re<25^cf,J;\9[0PQa!2Usj2?'h9[eZoFHQkV!#b`K4-pTq\DPCt7n;l%LdptRNpH[RQB_8Qkl+9ISZ;HB`531Y6*fgck-KcVu]./2uEXVJmjY+1!UE$E_a)2b=8'cE'?^HB^(s3i_UCH]gX_e/[:tV9)>V%#QdM!rC1:g[h'dsDJ7Z+54iX3j#/FP>Dig^blj:L#6F%`"2QE/FS:g;6bCDd+hgmo=Dh269<5]rb;@Q%E<_UiQ(L6U%3)l\Z_R&;Sd2oieF4'BYEpdj$^l9,5j1L8?Grois-/D!pO]Mc_a=^>54/R.:E'r56:UhNPFSt$hG8rV*uq3oeep[6Jr,:ifK2j,)cKY+(gftlWP5rq>cm,$qsX-cK,PWaV-1q&N9cI4`Sr`-VV/W&;/NZpDf-[oH(/.d#naNdHRfnJRQfC$9>V1m95L9W#fPh*mo.!F&,?/O,?KI>s>dpGplLi3mKlS'p!GZ!fW8Y*%(Tc,rWV at cn.E?_B at D&tjgfC7c(F"tV^"&f4qKt1Ab29?b/8GL.&9r).Dke5?2Nb*X$X5Z.YKZD%K;Q(Ok<>7F4,nVj6arB&pt+L\,TXehqfAI&ILi92O>C(AJ0#<:i*nm97oW\"bOZWnpRk#@aWRcd0cHd``f,%C!o(W at BAX[l4%Jq&4-b+GK*4rD5i?6qDD75U>QGRq,.rnP"(?5S+HRC%d:U\7'F)q=pqO`FL,_UC)td?pd,MKO;$o4kXpHZnGuVS)M)L[fBqbt8SZ1d at 7n:PUG)>kkV9 at b^>Id;j%2c0SF,Nd:!4>?]H0kg2`9#IkW'%RmJ2!I;$0:Oalqu6$\H;/4B&$0 at le+jO^jn,/2!!i$+`OORkt8lfEm99:lHF[rN, at im_&/hmbC^n%10g9Y]"\)%K=r=FENP`@7r^0E\/`UR?\20$ne=2K>%`__/o#1-`.S4X8'J1_88I,r!1RU^>f~> +endstream +endobj +176 0 obj +<< /Type /Page +/Parent 1 0 R +/MediaBox [ 0 0 612 792 ] +/Resources 3 0 R +/Contents 175 0 R +>> +endobj +177 0 obj +<< /Length 235 /Filter [ /ASCII85Decode /FlateDecode ] + >> +stream +Gas3,\I-2=&-h'AT41DE1 at FLkfsF's/-KrSYm at q'J7jh6Dsugb)j+i`k4iQR`FPis(mP21$42&F+Cc"f64#1p]$uQ@;6_]r&ZXdINWg\:^p2=HnJ=f?\!m,[.aYu_iD59oMC[/UPq%Rd-ah>4Xn%1_@"tc2pbF%PpV-&VSs*2\#jNPV +endstream +endobj +178 0 obj +<< /Type /Page +/Parent 1 0 R +/MediaBox [ 0 0 612 792 ] +/Resources 3 0 R +/Contents 177 0 R +>> +endobj +179 0 obj +<< /Length 901 /Filter [ /ASCII85Decode /FlateDecode ] + >> +stream +Gatm:>Aoub'RnB3YV^'02Wh_/k\-`bJbT"qcYO)4B_#4!O8nX*_?4hPHj1'0'4O`Cd`EuP=mU'UAc=IT%B=+-ni64L#>9lo"(rSqFp80bS2p+0]Og[]F2#q?I'PHjXnR^90nS4UpKi19.%I'rON`>t`:HO0K.4l!0SIfL-QA?iDNR%$DkDK2PgRVlf=U[g3G]4)O&C`eLUTTr1%RLb^`.lpYV'8QK#ElO)2jeYEsjZSB'mWZV,2"jY>EpVm6cCVk>@H]GY-8O>N@=dLD+5&8Lahqot#Pk9V;GWU31SJ_"`]-rh!?L2#."mLB#nDtuNkc^bAE*3RandC#2G.qi.6STQ6O/GFdfVtG!%^#UZ]gT'r'QQdsH:";DA<74!5K%+JeGIEa_aKe/FiP3a[];X;LQT12eFODO[752%$P9GSYAUf3(M*u`-gu2(D)l4hYi1\PL(g at _rWacT2_+~> +endstream +endobj +180 0 obj +<< /Type /Page +/Parent 1 0 R +/MediaBox [ 0 0 612 792 ] +/Resources 3 0 R +/Contents 179 0 R +>> +endobj +181 0 obj +<< /Length 301 /Filter [ /ASCII85Decode /FlateDecode ] + >> +stream +GarnQb>,r/&A7ljp/iTmqJC;U6ktP3!IT7rUt;QH"7%u(HNW4/?<0kP44X.G"0W7WMpuIJc at V<&Kb1T_8EndSpT.Y=%1%uAZFS0c3Ai at SBXPE,\5$/uiEBp8m/PR at U/P +endstream +endobj +182 0 obj +<< /Type /Page +/Parent 1 0 R +/MediaBox [ 0 0 612 792 ] +/Resources 3 0 R +/Contents 181 0 R +>> +endobj +183 0 obj +<< /Length 973 /Filter [ /ASCII85Decode /FlateDecode ] + >> +stream +Gau0BheUt#&:Vr4 at 2Nee/=IhWQ;t@[au\`oKi,1CAIjYCV]L\c.EZ?#f2&gi>B]!eK+5RdkPLtAmaI_EU=$SK^5!Q at Tbf""kcI=qKB>NB_Z4u`V]ZDH(N$hRj*S%n'CU\mI5Y-U6dR4uUS at k,KcgXU?p:SA`-Rup6Ha)+/"*QGBtj?k at m0@ZQkmj)3QA/Rc)gcE&W*SlVqFh'/=)8@:E7VkBqm\7AQVbNT(O+q+V6tepb*glH#;POWLY3)J,fbQ_+[Zt!TgCeY'u7B6qUiefmY5Y8XjfniaBYEV"g&s0bjF,DC(S at 3K`&a9RVNl<_IFm36]ZY9dJCYKBL)++U)a(-DR$`P,/Xn-B%cNr7e,RJ]/\82[SN'gp[E at 45IAuu@,("2NX*:2@,D27n`B at 3qEa@Ee!90H=g+?WQ)Tiii/-)7Z=S#EA)&E'22X'\DpGFL#u!+LLhgk>S-3qS at 8~> +endstream +endobj +184 0 obj +<< /Type /Page +/Parent 1 0 R +/MediaBox [ 0 0 612 792 ] +/Resources 3 0 R +/Contents 183 0 R +>> +endobj +185 0 obj +<< /Length 605 /Filter [ /ASCII85Decode /FlateDecode ] + >> +stream +Gat$ua_oie&A at B[GYATZ\W]'$LiXuk!_%cKg)apqE`?/8/(820pE_9-g60O20'$^&/8sD75"e(&;Lg&=$=lSW^b3G'q%!R!+9EbK:^IW;$N.F0W[i,uIY$jl7ra'AGOV8,!%,N)'S2G,(/Zp.X:!^LE`]I2k-rIg/Q`T+*,g9=,5^,iGS5Wl&8L^c>Z\N%#5k=)FK=k*S*h_3MH8>Ri)CS?Nbg;>dARWVfQ4 at 8!*]a6goF0'sG+X[5\((!V)29:U1:0"5GgNHJ+n.*#mG0SWiG4tO.VJp"(q1e2Q(1hNi45g)Jt.PSe7r)[&oTjljCY?u;`8$2N\e5)o&7Ga at mVqrteS +endstream +endobj +186 0 obj +<< /Type /Page +/Parent 1 0 R +/MediaBox [ 0 0 612 792 ] +/Resources 3 0 R +/Contents 185 0 R +>> +endobj +187 0 obj +<< /Length 1273 /Filter [ /ASCII85Decode /FlateDecode ] + >> +stream +Gat%#hf%7-&:X@\+lm'QJ;Fpg8tlB'5gj3S6ee<8gHEc-?t at F2.Z5?:,u+F9;C!Pd[N)a^&EHSKhKR$/IcPCSq"aYDJ/LTt=I"dmfIgPCW?2sf#XgtI-\/!aYhB?^/Dnl=]+4fL(bq:nabK8c812Xfn;nK?]8gNH>pZNm[Cq^\mAu(!q at WR-[4^0f;OcJ0`Ib-+@@OaqprI:Qp,+P&^Xsf,IurF9k@*C:Lto1&KJoP>^6QY8W-A>*&t]Q.Wr'2=BSZn`L>d(39?]oGC)BeeF**q%u5K1DsNj/"kQlo6=@Z"0GAf'',UP[.s>6C@<,7qrFBl1$;OX at gdo+PgGk*V#'8hsr\N at PC9Ph+N%"id-3+LU_cj<91"B!M/X&9Qb._"&Vd1tQd5-bd:Qu]q&rl6h=+BK&d!A&P^TeN.H`uRMJcm?DK[m&']U<,*7SL7c>PZ>4nqIK;]qK]"26AWFS$:Q at ZP4_MqYE#mN-cPEl(hk.;3el9021kfY:)^j at K$Lk^\8X]9VLP+JQIh>Jj%Z=p`o_GXAi%I5`/qP:"*&1k)frfQ at eSG1o['SHL-cX\N:)u\RP[SJpZ^a]ZA=oO4s`mS8V\&8tMuV'%#5VTUDeMQ?@&#L2^Zfg-)L&Lk2!c.s/fX^ne'^Z#Z~> +endstream +endobj +188 0 obj +<< /Type /Page +/Parent 1 0 R +/MediaBox [ 0 0 612 792 ] +/Resources 3 0 R +/Contents 187 0 R +>> +endobj +189 0 obj +<< /Length 841 /Filter [ /ASCII85Decode /FlateDecode ] + >> +stream +Gat%!bDr&G']%q&fQCeWCE)"nV,ka;l(Vo_C4j*3]'t5AW5><;U.N,6jqSh%L8hJ`0DBJSnNAfA_*T)t'N.nHe7GE4j$pXUuJpoL3gKqNH_5skXhNIc?l\.7dJWoU at fo@T)p;C).`QKLSGYVBuWmrfP[qY"49]$)X at O9`Z^X4&Fnl?aT7,JJ]Ma?_Y'VJDaE7#I8'$GSG3,.A[_ThsEb]jh=JY-i^*;RqJ<.7q:=ejP(Gk49Y/X;g2:E^2V,#4)s`SXAX3Rg!+U*mUmJXeE.pYch[QmN^iX.$irt,%H1$-[Ln0E!;iQUj^l&:DLkZ$12dX2KSu?]L]G1+br0:n=YH"6*38ATU4TVQ(,>'_l=6EBjgW0e-qa?l]l*.lnMY09YZ-rGcf"e(?.CT[GaP1$Zo`j]8#<\O<(fa7QWlsD"?uF[+`)b\TC*6(olHUFXsUY=6Zjl4'sG?R*eLAdil.>Ye,Lhp=i_#5^2Zhhaa`KGoA9~> +endstream +endobj +190 0 obj +<< /Type /Page +/Parent 1 0 R +/MediaBox [ 0 0 612 792 ] +/Resources 3 0 R +/Contents 189 0 R +>> +endobj +191 0 obj +<< /Length 618 /Filter [ /ASCII85Decode /FlateDecode ] + >> +stream +Gat$ub>-hH']%q&]IPPCp%:+DJ2E'j;5oga+u[e:QuUPR9JZ9O,l%6t%jhdS9L.:`NfVMsk'hJ[r,k6UOSGbu:k+)>rnMc5d"KB#k5]6X5ommGfBT=ZR>NS at clp\3d>I3(TP7&`'94sohBl7%Q.+f([In&`_<#DhQ^cj)0gTkY`pY=4_h*&,d-->[?D"&s*RM%5JdKP"DId$6a[a6AEJo#gd&kg7)4(o,MbPfYh=J8MQ3peCPX5CpJeC=m-g/$]f?s(laUI6K];$"N`8lV`i_D2W#[DTbiVs?o>7'h&C&SjoUr!]agpD7,CnY>jTd=cXh-kICL;a'5lm>$'X~> +endstream +endobj +192 0 obj +<< /Type /Page +/Parent 1 0 R +/MediaBox [ 0 0 612 792 ] +/Resources 3 0 R +/Contents 191 0 R +>> +endobj +193 0 obj +<< /Length 1068 /Filter [ /ASCII85Decode /FlateDecode ] + >> +stream +Gat%"?#Q2d'Re<2i%]Yq`AX?P2MnkAldU&_Ji6WP*aE.['7gS5des!qI+]'o1l;ueNR'c^?I$7XNBatf`sT0RZ5#ToBM(+4MT1*AYn57rdkQAi)N):1ISHHURU.GX(&nY/)%+mG"pSfC&FfqQ7_lmF7P&7K6ZnU3Bh at nH77@F<10l#5$1!V+Cg.h)6ECdhfUtONC`R#o+L&8.q'udBXFj%mp=$o?0VMW:k52M2D]QhXUp2Eg%0:.:d0(C:e./_(e;)[Na\-)XbUdX(uVr"EY;MM&hq>GlVdo^:%,lZVa_U=\e!*'ar^\*u^C%*MI4E0_`_=1fbLQSqs*6ejU9FDcUrsWj#iES4:C//EIMOC%X:0R3&uM)@<@h`a!4V?Y4+]?5hL7`UnRhn%k?j((,"]L:WBG2!d9i4'Dc4]IDkl4Zchhrf?[i32>Rn:Q'ED,-,CdMM'HY;0."TfO7,X3d"ui)d.(lWG=sM8X0fu,cD`dMePLNdEr?qA)&#KKd95*OHQW'nC0)6B$1F6=BtCR:bT>9;J1='3kg33U$R4fXIC%)-u')t6gY^.epsHi,GI:Q&8]r9Y9&(;&!O.=KQGi\I3J)]O'CXGeND2_fe'-pQo:&3dS;DmmYLApP?_Y"P9`i4,,qg%,b\),h*(nFp(3,EIC9m1NlYX04kMk%UlaGpdIJNZTWTD(&.iV(J;q1l+DDd;pUZs8Xgp#olfWp#=hSt@^A at cpiQ:h+4hhRLptE^K8i#kJRU)M=JobWK4[hLY$I+d;D at 2*o]'?"LDF9^+WpR/jMJgb.B>L\>WgYP[q(m%T)Rq\!4jFd\9Efbr0%0H`rJGoi=, +endstream +endobj +194 0 obj +<< /Type /Page +/Parent 1 0 R +/MediaBox [ 0 0 612 792 ] +/Resources 3 0 R +/Contents 193 0 R +>> +endobj +195 0 obj +<< /Length 173 /Filter [ /ASCII85Decode /FlateDecode ] + >> +stream +Gas3+0aki`$jGQP^ETE_`oMHtCY+.J%YBd:grtUB> +endstream +endobj +196 0 obj +<< /Type /Page +/Parent 1 0 R +/MediaBox [ 0 0 612 792 ] +/Resources 3 0 R +/Contents 195 0 R +>> +endobj +197 0 obj +<< /Length 1092 /Filter [ /ASCII85Decode /FlateDecode ] + >> +stream +Gat%">AqtE'RoMSLu>+nLl$&\+G$nV:'-8DBS at 8FK9nW):n%S8L%X?`>N-o$)l@;6O6>PEqp'D5ZX1;X`?'s_=Lns1qo`4pr1_E;U-^/lb*6?;\TFAMIn*0PQI:A7f-BUNX&lI3os3A&djK>HEeL3hqA"-TQ<:6PBVlq+5f"'M"#.]"SI$F7gY!!Kb=``fIc-7:%is=j1me+V4d4fZ\L*NTE(cg=o6$E,/C>]"cXs]MQl0mQ@#pg3f4Pc0UTNK/!2pnWS)p5#NWM-0bNcg3QGjpu)S[a"X;"p:afcXlR_^%k`EmDae2IjI.jqTT1^Q3aPpgiqI#oa__B],GF9g-OVp7)X/Dp!4rC>anNLqZGN'Wm*0^]?]K(CV7Q@@Vkdik0=b24&`kD]7`ZXL1?7'Z)d9?6f&Q4LKHQ"?iIB"Al%U*d,c5^-eUkL"o9QJpRQGHL9%+`XPHT!Jf)d at uu[KeWdfTGFpaf6kR2"4R!iF(B$85'/2?LI&t2'ed!"Sf#HIHHTeu(/C#+_?md<(cB*rU!.];9JA!pePp4Q#U]h]HnCG!kf1*dgJ=/\$VRdh6Zf!=T.3k+2go'+A&_+Go+H'&aU*j=F9]>WgmSVE7pR'TFs\*gK0P318.t*]m>?b0<`)W,#A5Be*OdV:Hjj?RJ[:CUT.`~> +endstream +endobj +198 0 obj +<< /Type /Page +/Parent 1 0 R +/MediaBox [ 0 0 612 792 ] +/Resources 3 0 R +/Contents 197 0 R +>> +endobj +199 0 obj +<< /Length 1023 /Filter [ /ASCII85Decode /FlateDecode ] + >> +stream +Gat=*gQ%aW&:Ml+=Sn>JMX*?#WKhYWXOKjJWS4^49cmJHZ;_-,6e^A2YAGlr6:+nM8;uU!S2iAh_sMd?qMkXD6P=olZ9Vg,^]h(kgidYR'0)4qaS[3Q2[7BX'I`]a3:\M=K=lt$m=C5%hKk_8m*>@O;<24(T]Z#F;69?6V,rR`*@QOAMq[:O-**d'$`W1%L-YrO5qZ-23<5gQ,1+Fo8Ti@=1/@^IJ*qBq+_)e>..P+;8iPQ\f#a at dLEnX/CCcoK(F))T@=Uaes?S>_98CELOP9g$WcSNq9AhHYeoj_ at E`FgS:8nj)f at A:X<$n#mN*plLWlU10/*dV0Ou"!K:HC#]"[S\_'&UD-3:T>Li(hl&iQ<"s!r?1`"=reio5+ameWFOGW9d-i[h3o#_&;0)L0ZqjJ>)Sr6RbM:@79%H/]3`g@`qXC^VZ at r9Y;t11B4;/,bMD!09@?(Rkj*4Gn<)%N.J9`*<\"]?Ff5PZ1LHYLlAi7\FpY[&WK\DQD9g6 at 1@dqRZF@)(%cgH!qs'I.dpHB:1N"I[X7bIbrAA;!qduu5B&A`";\C at 6c\pQNGb^iiFE4#N0YqAL$.q-d75!XCPfn_s~> +endstream +endobj +200 0 obj +<< /Type /Page +/Parent 1 0 R +/MediaBox [ 0 0 612 792 ] +/Resources 3 0 R +/Contents 199 0 R +>> +endobj +201 0 obj +<< /Length 698 /Filter [ /ASCII85Decode /FlateDecode ] + >> +stream +Gat%!bAu&c']%q&ZtpPhkj%O=bd7os9^)sa_Zj5QNnbHa44qj*r&sTqYoP38Qu"&0*Z^em+27J^Da&2n)OM[s1o',CL4m,['$Yq>j[h-u&q<9_h`M)^HV8f#s-#fAK%'r`ciJZu4A^c`k#`id_/DD2G3egKS&S$.ZWf1tZ4+A at _3f+amkYms[bV0Y*cJj3KO^*lU;sGJ%jOk[aocegBjLp4R(f at e,8f.-4pPM^*[)QiqR1AE$<7O\g*]>Y3[+i(77.rc at Mb#>i(/XgN&einqlLlIj>]E;IHTBeZuUY#A:Hp6d.pF&RR)#@re"Yj)k3j/=_U9X[RJ)3uM$4832J'fGB,F[#mGR\Li#f4)Br=g'[TKJiIcAW!slJWBlrp3GZFfaSE3W+]3f$5e/=VAunbjPGY5Zau`Cts"C]@qJ2Y!=hF**^R8+dfQm~> +endstream +endobj +202 0 obj +<< /Type /Page +/Parent 1 0 R +/MediaBox [ 0 0 612 792 ] +/Resources 3 0 R +/Contents 201 0 R +>> +endobj +203 0 obj +<< /Length 666 /Filter [ /ASCII85Decode /FlateDecode ] + >> +stream +Gat%!bAQ&g&A7ef+-LNiiG+^&C*>0;?@?K/NeK/Gdu0Y%4R)>jKD;g##6:`Bi7AB^`DQqhA"WL16?T/-fZ>+C`uTXBr,1>N'i2O##cY-SencO&j.70c+nUI4;%90Wj8b;W*__LH4D6[[//qDWE!OGA1F*f"]J,RecC8JOpfJoV\9knYtT^EV$O$%pEUK at e>1":@o#37HBU6&OB([d?L-;k*=3>`Un.F!)l(N3%rM,DKIaLX`CDIl)l\lph^nUK<.9&EH!SC91`N3gttFTRBp?VJP;e`;*Vo_Og*#sh3sJ` +endstream +endobj +204 0 obj +<< /Type /Page +/Parent 1 0 R +/MediaBox [ 0 0 612 792 ] +/Resources 3 0 R +/Contents 203 0 R +>> +endobj +205 0 obj +<< /Length 432 /Filter [ /ASCII85Decode /FlateDecode ] + >> +stream +Gat$tbAMqd&A7TLHV>-Y[10S'R.PBsU.CR5WU575P9M;""`rnbQ\5nP8VnoLZe!FIGh+DikO-Fo.ZjlGV%/'96\3`/"j)jV#WW*@6aVKTaXZ/H.==DQ>dHCd;E*+$Q9a-^5QhLl7iTHA=50jHPbuOo`nfgG2QE-=_.EPk4*bI4g1kM6P3^Q7g779A$TTP#'RdOBlZ,!pOG*aMT5h/KKhic[4@] +endstream +endobj +206 0 obj +<< /Type /Page +/Parent 1 0 R +/MediaBox [ 0 0 612 792 ] +/Resources 3 0 R +/Contents 205 0 R +>> +endobj +207 0 obj +<< /Length 1572 /Filter [ /ASCII85Decode /FlateDecode ] + >> +stream +Gat=,=`<%a&:W67+S*n%&)*1>E_/<*!P+L((U947640LQ"%B=C-9Mt`ER\?f]uX=tZJ*/K1TR)4RtJ&]=\jLXZOP)FfJhCYM.o(J/Al"JQJl7_)C09a:L%D#)LkJJ at 7m_^^Q%pT9Zf4DP?hQ_NIZ`Y!V%o8CeIC5`7893Kk3,'k&FGLil[WsQX?5"0_U%oZNuUo1&&-cP8fF.La\&k1l,-u^bn,rFA!plA["q&1k at PqL(t+nca*B?MBd\1]jt&h6]A2G^]#4iG`6YMM\EED-!$Y at S9_EifhY>Lc]bQu>4:W'^M.-.X+ql2K+N<>.HTX8^85C?`5a at QZ\r/o3s^q)*@\Mn7\dPhU/cVn4C`]D\pXX_)fY6R`%j:rUbPi1r&IF\+e)'B$:"f!`%cRpJj->ciM\,,K[EC+2AH%fPHd44 at qlIigS(AG#oKcf%S=$O&S at o1=7(u8l7Fc(BM/9f[8ppa=NtF8*uV>HCcDS\]B8K#=mO[!_.ahE9u?9F_+fn3"?]ChCVju(2J*N at G`\5oPb.B]Ec$7[cU$coWcKP`]Lb!E25`r>UmMGA$RNmZO5>W]-d*PkdhI\TM^dO*TbtP3f?tKe=eGi0`VI[!,`U6Mn9k6K^JU[f*0Olb5CdLY#6lImk^V:qVXUbdauZ70Q23>]`GiAXPgsoWl$)BBu8hA:&:61OiGCDhoYD5=Z*SVC<`s%S2RddO^8l12YN5F"jI/Wdpo+h![GmSE!EZI(H;6[7]ot\gG*IkDS'kQnNYaiFNpZm?^A8Xg-/U(Z\g],g:(udk&.R.7MMDf6Qk at BeJph/WKVp7Fcjdc0iW+o:n<#>h;=7ikHWR[Bu<\Z-d3$8JM]#TqUn'YJ`Sk-Y4u at 2]1]YWiZd at aW!AdUWmWra-?L[%nW+o,e`#O#j?h*[2+O,FQB-N'?aLMqcLR;3YZ_IG^',<0/9QKDK5U-dnZ[=el<,[YrHDK\O:hLC%DP`G'Ga-9+YBS&U?emkFWdPTZZ_rjHH**^OC`SCq:rTUTAAhQd#@94-H6in`<9TtR9a.<.4o\MZ-M^gG-W2.+7#Sn_14I$[Ks0ec/=PYN2<,Jl6F1\M^J`f$$%a+#qpT9pV[#N1VN3^)'[N&XK;<]n)@HT8AOLn4TK!fTP^;OMuB5AR.B6[AN>E$P^5eOo8HusLR&Z/o[IAn0'psQ>A8GqBK+iupP*8rlcBt=^BAQ$it"#U4*'%c<'cNBjMU%jh7lK#A<5S_bhDFJ_&a^%2-+Q!9R[4a!:-]~> +endstream +endobj +208 0 obj +<< /Type /Page +/Parent 1 0 R +/MediaBox [ 0 0 612 792 ] +/Resources 3 0 R +/Contents 207 0 R +>> +endobj +209 0 obj +<< /Length 241 /Filter [ /ASCII85Decode /FlateDecode ] + >> +stream +Gas3,\IQJ1$jPWQ:Z8Pe20"X;XHgrDJ:u!u(ojT$-"mYh_;c1Wa+BD>?Tp[:?Atd#Lf$2%)^/W?#\5If<[`Nq7 at .0H#?W:kXfD9FFD\Q16)p;l@`^m at Cr3#roZnaaK:bT]!m,[.aYu`TdE%hEehhXCY-%5:;L!1$hEUbe(pm\B=iPQ`@3ZO3pE*0cTeg]9+n=JrS$5Pdnf6)lCYDUWIbU8VrKl)uill"J?EgkFkmiNE7?d~> +endstream +endobj +210 0 obj +<< /Type /Page +/Parent 1 0 R +/MediaBox [ 0 0 612 792 ] +/Resources 3 0 R +/Contents 209 0 R +>> +endobj +211 0 obj +<< /Length 1395 /Filter [ /ASCII85Decode /FlateDecode ] + >> +stream +Gat%#9on$e&A at sB#j at sg@*OQC77eqKfJG&(+t\o-kbTm5=f0b^*iq#Y@:.b=b]P$&0EfGr]d."6deA25a]t\L7VV'ArPaNQ+TJhSE*KK:dsYL"P'@ru8lE5b.:h>7%$md#F6ql^)->CR]@$ufq>HP1d#^P%Lh)"aDI,BnrU>@7r/$7Zh`f:W<`I)5][Z]mBrmn-f,9&qJOTV'5po?0)^lE#Z50i';?'h;+Y(cd>B<2NbFAB:PR?:nT<^#_Gt&f,n^&b::XTZHEmZ6#>nRY4fJ&kSPk>7qArgh]]lW'n4kobHl:S\-50)"1]o)->2OJ#lmfk0P]b*kVYmO5)\2Ep-UdCU^W<]^PT3HdWgpc-tEf at WYQq\D>k%oYOO]K*J/a492?RIP*bGs,MM(WdR^odaP1'T!(&[J1*dD35D[\gEUd,b=nQS6V3X7(Kb"pog]t`$r.Jg,m]FB6$1GVCp+'mG9S at -*hS7=nn!,cS:r at 8;oGV"5hR^5?$MKA4cRoCrJ%fEVAc!#9E9o!ZOfZS\L=^tFK-;6e_P<@s6:5Pl4YCb/iLmo=c-;WX'n]+b.kD[A?0=APk8:R!V]3kfQZ3r-D`,#4m(a4CkZ`oHJlF.ifj>p1m^DR?PNT!Ei>dg#Nas_ilue^OAQ]dY+'1h;2Fo'Vqqn"<5`2AYDnorq#~> +endstream +endobj +212 0 obj +<< /Type /Page +/Parent 1 0 R +/MediaBox [ 0 0 612 792 ] +/Resources 3 0 R +/Contents 211 0 R +>> +endobj +213 0 obj +<< /Length 571 /Filter [ /ASCII85Decode /FlateDecode ] + >> +stream +Gat$u9i'Ou&A at 7.=IaPsG-F./LfZ&=8B[]^8enn%W`l_%2A.8HP,doQYFT2_6uc at +0(sPP]f0o)ONKO5O,'+\%J>RuCHeZO>)@oT at GcIf$E&7d':Wj]m\>lEC-PAK]sIpZc6m]YdSGcL4<]SN6)]6TmLUBa!q!;P,R3A;jti/O8;=^S8qXUhhb$,s^]TMhn_7k*olTU;PTXU',61O*YeuKPB at YfS;hm%["W(J;7F?/TtR(\CR7:$*r2CBCk9ILa%mQ2:X._oX,W1r1tkpS0f#C7&W<1WoL at r$2OOle%ApNb4nJOd:eV`keQ>)DP+egD]^=U[meb`KDfoWkQ_,Gc6[;4jLP +endstream +endobj +214 0 obj +<< /Type /Page +/Parent 1 0 R +/MediaBox [ 0 0 612 792 ] +/Resources 3 0 R +/Contents 213 0 R +>> +endobj +215 0 obj +<< /Length 2102 /Filter [ /ASCII85Decode /FlateDecode ] + >> +stream +GauHM997gc&AIV:0_SBl=>P7f2Q%nc!\&^*D;A.H"4sDO6=eK?-p-k#mnfguTe%_K9:ZBY-H^IU, at jB9,t*u9>YJ!Zn2?^`p3^D?.-mFF*<8X_2n+="Vhl`FMh9Un^u2LF=E,n&TTSl4&/q1/S[0-Eh#C9BdmSj!T'nMNh$&2-daSq;P[Wt:MnMrh[T\$G'PJgf4$'QJ:q(#Mp2FtS_?Bu(J;8hR8)N[)Bf73"`WajH)"+Q9aYhc,D`=D_0C]20GUcb[,tG1&XHK4[hn]4Ts!asmdtqUMe(`fYg)SjBqE2sY*9&PG!_bPFLL+p=+35UK=>4OL0?A>XmGE2Z)8QuHl-m=&D+mb!!=?RHDPGb)Xpo)8fqApq8"fQO*bc'r^S_b:@IT\LiGnBJ89h'Fo5O!Y4'2n/R13%N>E5AFhR(p>2YSop:\\s$n-i)bgV3a at X:fZ12^11M7*pC!33[q">Q5"l"K3RCZq=_/2j#MQ%AWH6i.X0M##,\AHX#jWt5$h9>ue0Xcj5((E$6eb-JJN7FF0'ZtWAWs#(k*\@AVr6kkIpMHdebGcK(r[D>(]1Achc79sP&]9o?J2g),UHUaqS#u!7]Pl4DI,JTUF)s#ht(`/Yg)_jC.<'r5R?"[V/GTu;sQOS,-Rfj$K&\>M.*LY#FEWtV3e@,GkTiPFQi]@dJ_h)#6Aqh1aFniXg`ODc0<=4-Gr\M#3YPB3dE>6s5!.Yt&bclgNiofT/eXD'0kYJ?^(a%6`iE#i[o9a^RCN`B$*4Vu>adXRYB7ggH_Y&jg3eI=1iS-6r-^Ut:'SaT:AS%)bm"_6$T7QETu-gVkb99JcFHT(79=P!doK6I5:c`1tXX)Nk8hQEh0YVRnYQ5?-kF*/Od<$iSB$JFge2&Gl*0J:b6Fg/&u90hPZl*kO`'qc2 at GUgV58>>0I6Jf[4sA:u9LCAd\`nj,F;->#D)E@/344=0)7'[;q'p$'6B7)g/sEd%T:#O!-"6MiM+KD$/9&Y+*k]lXHp8osJ7^++I>9$sR^;I22%TIg8s3^s_K"b@>@U^sDO-GJ\i'!LSm][og)H?S0Eu-4jIs(GUM<$]ZmP8<#XWgq'iM'gc'D63Xk9e at C67lhVOuF`J*VRdFC(e`%/2jKefLmq>O:g-^&,#TDbM>f:@=VL/FE7$I2O8,Wa-#hX8ZIr'DGQ~> +endstream +endobj +216 0 obj +<< /Type /Page +/Parent 1 0 R +/MediaBox [ 0 0 612 792 ] +/Resources 3 0 R +/Contents 215 0 R +>> +endobj +217 0 obj +<< /Length 343 /Filter [ /ASCII85Decode /FlateDecode ] + >> +stream +GarWu9i&YL(^KOlT7Z*s=Xc$4^Ff$idn at JTGl,VJo=?SqbZFU.E^IZMBOuY_\=04#'ePKc~> +endstream +endobj +218 0 obj +<< /Type /Page +/Parent 1 0 R +/MediaBox [ 0 0 612 792 ] +/Resources 3 0 R +/Contents 217 0 R +>> +endobj +219 0 obj +<< /Length 726 /Filter [ /ASCII85Decode /FlateDecode ] + >> +stream +Gat%!995Pr&AI`dI,$m'p"OG!V;4$m<,JIH;(lbsPaDS&J^g'1pYXS1#T,mA'e/^4k*p;G4N>4-J6[3*dpRMjU88k&92/&033Q%I0ti']h`V8GFZI=5"Il^sCqigAEM'K]+iRN-*Ch9<4m#d\f2+haK1Q-jC-nN[VkiITIr*E1Ga*]-Pn6lM+r0=OGeWCG+W$(%?,s%ZRncHdgjMq't"(u(oB#9<+873"(9ljU7B58(R.8"*(3, at .o@^6?P++V[;[R30Uu2i+8N)"_P&6U&V(.\Fl+pmNroWpj#2V09T8cXCR0en(k]C0laLneG>.ol40r1:p]]XOJ`W(Y;.bTcsH;/lL,Q&p\s@!.P$?"aG'C2H],tF$m.5uCtkgpIq/:s81GmN.apuO]"Xe"MmEkpBfZ7i=F(46E0j/J_[OC#?\Gq$VT+Vg)]X:,Q&If[4S]g_~> +endstream +endobj +220 0 obj +<< /Type /Page +/Parent 1 0 R +/MediaBox [ 0 0 612 792 ] +/Resources 3 0 R +/Contents 219 0 R +>> +endobj +221 0 obj +<< /Length 733 /Filter [ /ASCII85Decode /FlateDecode ] + >> +stream +Gatm9bDt%*']%q&]UY+_n_;=jU_tQg"G9/WYlPW.e7g/h;3DWjIub8Tc)YPD6J^;^4nmaP\Ms86p\Fsq=@/`I&:4\!4UdGJ at 3>kE5klS1q'1e7,0ETL]EmkK;*9PLMB0W[V.2b2`fZCgCIoe?M^;X^d,`/#9b4S7KTR#L5c0]o\JFBK_c0o2gtek!*oK6^V?Z&\*a;(YaTLlgB=?h0d.MQBm;,ho6.RF8=e at .gNIP?lU8=+&(6X4"=rd^4hI>5*t2SJC8V0/B=;SsDd6NZRVAkMpT/k*ZUdCEJF=0=)9[+VAUeY?rL0Na8"^W1T7L?q[aA!YG]I,,ZTc"7N/dBXW)IF3'?"R^3;=PT%KsUN[f=%>@[&7D#nQ&T3o9JBY8Rgen%O +endstream +endobj +222 0 obj +<< /Type /Page +/Parent 1 0 R +/MediaBox [ 0 0 612 792 ] +/Resources 3 0 R +/Contents 221 0 R +>> +endobj +223 0 obj +<< /Length 666 /Filter [ /ASCII85Decode /FlateDecode ] + >> +stream +Gat$ua_oie&A at B[G]\J)j\G'-T['7pJg*N7D%DLt\LOtr,$i-:?W*%U/QUZD(C`Ngn'0&q5/b:l7gcJR,Qr*&+E.T?5k]ta,S0tgE>T#miY$XnHqI"R#C_3u]gZpkO\N'Q$NLia+ at 6,U`>p.Ne!AZ-Q=uKqg@*q93cBUt-##)D"&Y[)b!jNm"$La)o/YIcR3HU9be&XP)4H^`K^,_]U<>k3#,:/:.Amgg%qap]C.8ELMVPi_s-Nl1jYNr_SpeK-PFT9LRed>k0LRCf at I&sa$T8V)g;A=8BR+??WOn7AnkXfG\@:Ui2XfF[d0j at R0/?g[Vg'q9A!'U;Db(&a2/`7qtb@@7$cu"j9Ro'XoF%S[_)TSF'f7%,B:>5Kar#BS:LKkpL1uIWSBN8UC0PEeH`)49Tq-Hch]#ujo)LZtt#XKM&%il9`,^/h2IHg&('_jgFLW!O9K!CLNoC=(o17)#*U7t2I&MuZSLMhrrOUFE5M~> +endstream +endobj +224 0 obj +<< /Type /Page +/Parent 1 0 R +/MediaBox [ 0 0 612 792 ] +/Resources 3 0 R +/Contents 223 0 R +>> +endobj +225 0 obj +<< /Length 1061 /Filter [ /ASCII85Decode /FlateDecode ] + >> +stream +Gat%"995Pr&AI=/TU`;cj5Ll9]k,`re>cfRh5H[;#D\ZL/WUUimRC4VHOY_^&-uK[Ym5d=q. at X=ICGf]s+i8j!p!MME+W>O)745U6-D^4[N(n at c_8oNZ$n;H=Mf!X?e5([6r=?GEe+A$!/N+Wj!!>iW":VE3%T\KjAEM'Z'L2H.i'(W>Wo]WdTrQE9Fk)$&teeQa>jo]B,HkCE/r$\Mog[gZ^[>rZ67K=&;, at s3$uFlNe0Bb;Sc\c)#nUqa/^mP!mj5#e/K[?8"e@%!8 at s)Zd:.Bm$arCDf2rDcSjOKr_E$WKZ\>Fb4-t=QO-GVSSm$_5(uC:4Pb/B5?M1]ibH\[<[gGPZ*A?*B0+B\.NT81d^:W$aYo':g9[U(1ZH2'$?,jeoQ\P4=p at Za+[4Cq]obqm at rV5V'h"?jr.cW6no[WYAUQ6kllX<6-cV]]eI*<3qC=X))sB0R\g-U_fuo&n-&7Ggog0MA^r'5:J8_n46HmFAg8m7XH?\Grt?jD0+@AV4B=lTM1n0V7Uq%#V.X4R~> +endstream +endobj +226 0 obj +<< /Type /Page +/Parent 1 0 R +/MediaBox [ 0 0 612 792 ] +/Resources 3 0 R +/Contents 225 0 R +>> +endobj +227 0 obj +<< /Length 1000 /Filter [ /ASCII85Decode /FlateDecode ] + >> +stream +Gat%">AqtE'RoMSa:m8QC2>9&P6[2X0r1Kt#o;G"GjnV/NC]W!\?PsZS0k3gCRS"HWDEG_lZ\B8AN"o,+Uenc3!lm"#(u"G"]54q5V[ci8RmjD369[eO0^pVk3'Ra+T&*7EIa^rTKrY[iDr2V$ttGX6sbed>cN&mlh.oh,qkTohC)Naj`rQ#E=4c'M(plcWt*Pp#r@'X'h7-I.YXl5,&bZed>*:$0Q\i_MEh7??p:i#epE4<2)f#R":-1ljF/TnHeMuXk at R95@NYl2i"L.^.me2C;k.;._Ht]tKG1kRrmbr$25c=iV-9:nfMpC+EOd\*;g^sT+;dS+DCo&(l*ekB%1eeXaW0XM;gp?Q;-3-]K-]a7gh/c at pi(BV%[GV5C<6>rAc%K.GLZ5P@:D/4*8cGgD#ZXpNYScI^:1=3[X7#EAmHp#cKa<7^KB+O0=g!+p)HbR`PFU_b^,Ug#@;<002s_r:Cj=.]&1'[n+6pGs9Xqs6 at S9enYO$"5,g8DT`AYTJD0rjg[ZmP4%oZ2C6m+8i;8CYnL1s,Y9L^a#HU#FAe:]2Ge`-*e.kD7X[fNLhY;:J'XThQB/&I`T4TB7T@,c;$[$9eOGG6X2?*qX:"13p*CX_YSJ!dI8uGeVIDVV%'kfgX.(&$\Zie2kan&D?[Hi\_K>Du9`$]B>]AjD]IjP_X(F,632HVl at D/]FT/MX"$AKpRB8*rNnABG'C..]-,VQH\;Lh?RLg<7,I)c^t3Mu7<[:-1b3cL>KNl(G!$eO(u:U^Psma3uuZ0n@[^Lh.%Gu2^KcRq$R,)JR0nD:l&gW:/J"@TrR-o*.L",2c>7K~> +endstream +endobj +228 0 obj +<< /Type /Page +/Parent 1 0 R +/MediaBox [ 0 0 612 792 ] +/Resources 3 0 R +/Contents 227 0 R +>> +endobj +229 0 obj +<< /Length 652 /Filter [ /ASCII85Decode /FlateDecode ] + >> +stream +GauHIbDr&G']&?q?Ht+]qYaO';Pm/)ejGE"MHR\!o%uhV<])+T1:s*+7hI*9[O at UbW3ETVT(``&@L0no at U]7:L>%DR2c/k%V9;"Ui0tpRCW)aEIMX^C6tRAijmkSM+W+,jE65;GRd,:"X5[#a9Q`-`OS-!3Z76rM_Z]bBHRi+XGgK2(d4/sWkok[YopCKnh_1Xn8M)E7 at n,l)JbPjd)3MEkPYXuY+CStT8>p0jb$L`4]42jA\L=o:"Ifp8uOa^Y#0H%8J;n-BUFYqVSR^*.m5KE#!\2Sc(+$0s.p9<;YqmG[mji2C+rCP21.o"3KEgKWf_M[;7.sCm?`9!6uEC*,'o6'tNjrH5EIAP at SWf#N&=pLZh+7[CQ/1%@3[l6S?2k=*"SoKue'U<5YA3>!0E--&MXKu'tTT2YVYc67DNWRf.mEW_K_CN(("*JP/eq;$IA6tPk +endstream +endobj +230 0 obj +<< /Type /Page +/Parent 1 0 R +/MediaBox [ 0 0 612 792 ] +/Resources 3 0 R +/Contents 229 0 R +>> +endobj +231 0 obj +<< /Length 901 /Filter [ /ASCII85Decode /FlateDecode ] + >> +stream +Gau0B997OU&AIm?jFh\&C>u^T"B&;P#GadT)o2P7\>dr1:#dN1G0@)0H*ha`VL\j7`A=''*oDps\Hs(UhI@(:J:n`Y$fB\kT]_ddoJcod`rZSNUL(J%^0Z5P4*Bq=pVIFF76TiR!s:Ra+DMTa+M]_u&2MFN,V-9]FeR6#^+?4M/.s50eG\V:C?UW;@O#M"'a"a,3Upla?AVrj4c!58F at 9:FVhPn/&gWheb-mY\%q.:b!QdRr9cg9KngsO9fOK*HcJ(a8p$eU1+]7Cnb[8. at FC/SB7muT$f*nP-i8hMIi>Y-AN$$!)Q:B8VIsq^k.RI^de3a.&V`uW7=NkmUYia3r^O%RZBMS.oePT3gL4,dhejUQ2toBa5U1.00io%4?>3kL'Z$M:opmS-,(6OjS^5"e/_N>P-hBPb!=-T7g?E)8(aQ]<2WsOD>UYqnmM\dFZXDoe(fo(03,WuSrh6(O!Ys39kYi#`S7;ah&-Vr1P]"uYA)>51$!PV5!"7tPf=Ca9^^pS$5CojnN#HU"omSeM&crW_rZs*Nog70Cf!itfC*u\eK@'@,\!imZm64>gZfm#?(0a%9u`/7jA(;$jQPrr?E[2Tl~> +endstream +endobj +232 0 obj +<< /Type /Page +/Parent 1 0 R +/MediaBox [ 0 0 612 792 ] +/Resources 3 0 R +/Contents 231 0 R +>> +endobj +233 0 obj +<< /Length 197 /Filter [ /ASCII85Decode /FlateDecode ] + >> +stream +GarW2]aDVA&;9q/MQ%j:DYF&_D86ip,?uT3.Rm;Q1$\X_)FP:mAp/@Mqq9<\CA]&f%@:Ze);uZiMi\DS~> +endstream +endobj +234 0 obj +<< /Type /Page +/Parent 1 0 R +/MediaBox [ 0 0 612 792 ] +/Resources 3 0 R +/Contents 233 0 R +>> +endobj +235 0 obj +<< /Length 1416 /Filter [ /ASCII85Decode /FlateDecode ] + >> +stream +Gat%#95iiK&AJ$C#[csdTT.>l<>:BcfgKAm9 at DMd^Fq$u+t:]Y$=,V9%YsZ#P93ka?[mt8QiWEVX*P?^Rfs3eq8"1 at +:Q[B!I:+:X'P5hbnJrrgYe]3ot-G\!Z9&h;TK,/U_mg+5Sh1%@SQ-!I:t,s]Cn-bU."CY.1s]RoncWWAqX at u[S%hR7_RJ8]bpruW:bVY($e=$a$AOl-jD+o#Ee1Z/+ATsVDqS>pM*"t@#F*jdulCI&Of8T'lA:KQYAE]bVn6S5JNAVV0:\kco?@i&I6n8G&u3J,Y:7!A:q`([Q3\F.sd_l$ks#,V;c[cd=:-;TNlKnQ3$@U+V:Q6CWlO`aQ'8[n>]!Uc3crP;V)e#YeVFMa%Hbu*?i5mem_5f7k+J:j_^"D&HqQltL-S;6J^,`e^PX]8oDhq!oXIR(WrR8fEfd3.G[qffH.Tl-j3`1>FJgGQ*D^2qKGeS:n9-!\K+,9'O`ntOem4n(:H0NSq9Q9umeT?"Y:\'L[,0oM3'3:0PK0'6$$(8/_nhno9"Nik#<:80YeWA!jUF60eMN-Pj62Oo"GfT3g"D"_RPW\r\WhJuVK62T#)0c.LQUNo_.Hjq/_hNtaa+^Pm+/Wq4P]E!\[tNcrj^bSJDgnt0rB\^1S!L.BeJ>L^p,#hp25_ZZL*Z;6A4)jph:#EK$MJ\#jlDbD_0\,a4R&ns_BK(Y^D!2MJab#Ya1 +endstream +endobj +236 0 obj +<< /Type /Page +/Parent 1 0 R +/MediaBox [ 0 0 612 792 ] +/Resources 3 0 R +/Contents 235 0 R +>> +endobj +237 0 obj +<< /Length 175 /Filter [ /ASCII85Decode /FlateDecode ] + >> +stream +Gas3+0aki`$jGQP^ETE_`oNS(caBEuK-4\<-bU/uY?:)ipU!g7OXuR+a4D4\2]d[0d1S->5`j.qML.K*FsION%1fdNQQscFLpi#F_0qi71KF"En'!*N&JON)[>Arja9>q:@04b0/^bl9L23-*] +endstream +endobj +238 0 obj +<< /Type /Page +/Parent 1 0 R +/MediaBox [ 0 0 612 792 ] +/Resources 3 0 R +/Contents 237 0 R +>> +endobj +239 0 obj +<< /Length 1757 /Filter [ /ASCII85Decode /FlateDecode ] + >> +stream +Gati$&6Xj^TYHXO'1,;Wms_5Z"H2VT&IS)F8O(#E.gdKm#$eg4Dh=_arbdNJm9Zs!YgE at ZTC-r?iQE5k`,1pZhm0h"V,_;!D,*\@+$::R%VOtQe0XLQ1eFM4O4On9e8N!F&W\jTSYb7<`<"Ri#"T23E'Jh]=]u_3Dq+0[%ap9!%_^[q:R+Hm\un\rld(7o\'Ib#Qo](0=\B\QSPpshSXiLjiYsTSajV'RXUD:2/DHUYLGbto29A at Q_2M$hP-OO)Q-R7:pq.UYpe"Y#Wg*1NP$EKcl7>1_kUH)o<<[P0+1/c3X#J=feD39_9Wk2Z:KqV'&e"o^!+dQdFMYkVLGJ:'GVX-_`'9C@_'),;ZGHu+A!ssPck[LWU&>L@?PWA0HV0rRtc4.\J5Xc<=8MF3CQ*116Y5GH:]'Vn,.l[>)i@&$U9L`+6,/LJF3>hHG._uE8j&_*3o259t@'N&_-HLC$b4A!l&!,=Dg"#--oGUFrqE6>hP+fZ%:']n:7B>EuTL:0s(R>T'RYKeuU6(#G\VCpQaqj9"F&4tLoQX4k*P)Ff3u\JqoLp:S.)?IUUmrA8skfX$aKYa=KqW("[2SX/om,eOae9Ho7bdX)@\Wsk8YGD\5F611+[\hX~> +endstream +endobj +240 0 obj +<< /Type /Page +/Parent 1 0 R +/MediaBox [ 0 0 612 792 ] +/Resources 3 0 R +/Contents 239 0 R +>> +endobj +241 0 obj +<< /Length 311 /Filter [ /ASCII85Decode /FlateDecode ] + >> +stream +Gas2D]l(_1'SUb&if;=B>JU.r at j@g;\#O7E#J7t^&iD7aeFr9fj"u":.[J!2n6HMc6gc!F?lF;"VC*&fKE4f*J`]Kh;i.oF@,Bk=fRLZhO3**LnJ`mef!pu=5k43<;`"=2#%#,.-Dgo8e+JCl__F=oWog61[d`^?)'`e/YVCm"[pRGX]PDB8UH>:I[`a]sZ_!2XW-<)pim0)7ApkSdeuuqh\38/nVR%:LRdCR[>^kpB7gjk\`*(QbU4o1$Oe'&6k"6fSVI5BW0=>G%fnX6>POeRi>BhHuqNkMcQHl9mEFDM+8\^)jDMe~> +endstream +endobj +242 0 obj +<< /Type /Page +/Parent 1 0 R +/MediaBox [ 0 0 612 792 ] +/Resources 3 0 R +/Contents 241 0 R +>> +endobj +243 0 obj +<< /Length 1320 /Filter [ /ASCII85Decode /FlateDecode ] + >> +stream +Gau`S?]Us?&:`$(5[15DPo9lHN8^R5g?\0!=&l<0)tg&l"%c0qM3sfap@@TdK>BGKE[RE"RtnuCq>6ZOGl3$(=M4hY,QPg?3a;C9 at 0&Murh)amn@^6d+HE\85'_Y8^SWCTi;M](lX6Ce*EM at d`4O8u^%)<:U*9^..ml(LaZ[.bHV-0\X;_'PTOf"*!'_JPj.G"h.Z*.G[WVN]+"n/9=(gI>u&4A3eV;?`:'gV_>^:SS5p@>(.WL-.tL:LEB#`Oe'CM]S6!\"B]05L&'AL/0XQusS=i[QHo-Q>Z\27b;K2)+HsWfGR[[V9HXG]S>:Bm,/I<;/45&=R!t'"N^Z/bfcOl?p9mAO+,N[fCEo`!o6Wd;K&Bo%$^p+(`n6^G]1k at NotW`?\!_8.-&m%G(99"&r(F554 at a0Z0#Ydo*cq!I-c at K:sZka9O7OY'GpM,rV?TB&JiDBU76F+!OY41sjP\[pI)opt5dHTsqoo_?G68"n,k7Y/\Go[&RoO=75jMJ.>CcCuPM8.meoB[_otIJ\OB5+nua.]*Q\tP2g^eYSGqJ?P,V)952U(s1AD?oKjVIFc!\MN=3.#Rk?S2JITe!:?-eoh\44r7eP[OnABB>q#&_ at jBN5A=+*?4L6Y89a/PD07+e0ql2FQ&6+5W7D(,A9I1cR*'C[_uQ!seaWJc(X+)m>]kV_ at ErBV/+DD8L-cR+[;s-=5S7Q^\S/X[r?_L/2''k>+CV`61@%k4lUKG82*ud;kI>htq\*\o""6>C,b,ZS;W&lChg9e^RG>,cVWc!1$9c%@$d#Z3g4KfPCgIHY/7cY;9]s.>+jd2WH[eOA&IQ_5#64dD`1N-1D4RPHN2b(gJs,7Q?)#~> +endstream +endobj +244 0 obj +<< /Type /Page +/Parent 1 0 R +/MediaBox [ 0 0 612 792 ] +/Resources 3 0 R +/Contents 243 0 R +>> +endobj +245 0 obj +<< /Length 1048 /Filter [ /ASCII85Decode /FlateDecode ] + >> +stream +Gasao;/b2K%"?O+d+btG_Uu.?fmW1t($K'ci6Z;XYjF`!j?tpso%?dDr;2[h4,Vg`1DECU;'Pgm'Ige$c5)HQ_D*<-KU2Eb5jMR/!qR3PL*8f=8V+ki/[sruc$`_%[?A:Bd2XqHBbI3Uh;!XDT2aY9U>V$\l5'=`bOBbX%4)*&;7u_FbLh_0pmT<-7-ueo!NFFo1EpAP"k>Z6+flFMW+mIo=])7<_O'^W2V*b*TGg*C:E#8R\m`%/9Z:ki?a2ZV.CHlo`)`^o9.=U>5q@?2gdiO)q?T8*?B#+&n2;*>ok$7\WcKSh`l^F:M39h0%dgjD?%Ed(?KLmYccEUfYDm.'C;DUlR!^a0P%oDf`fbN!i8MMn)c<#fZ,E-.f$C#MC?:!4h@=JActGSDjgH_#':0r$),T<+.Q5F2N;@uRnp:QRdVM*8'm/,Ri"':ILrF!,*WStISl.Lh@`&.#+>fg5E6:beVg[nG/XUDeB`JDJ59NQ)7B,QKMqtD_h\eGlt>#-uZmIc67[g/Mjd])]h=7c=Ve5\?U+2o(#otthDDtertGqejg6VO(Tfh=5%$'`d8T"S?g2prP;Mu-7(K@%%g$m0d at EZtGbS0M4Q~> +endstream +endobj +246 0 obj +<< /Type /Page +/Parent 1 0 R +/MediaBox [ 0 0 612 792 ] +/Resources 3 0 R +/Contents 245 0 R +/Annots 247 0 R +>> +endobj +247 0 obj +[ +248 0 R +249 0 R +250 0 R +251 0 R +252 0 R +253 0 R +254 0 R +] +endobj +248 0 obj +<< /Type /Annot +/Subtype /Link +/Rect [ 345.52 637.683 367.18 627.683 ] +/C [ 0 0 0 ] +/Border [ 0 0 0 ] +/A << /URI (http://uffi.b9.com) +/S /URI >> +/H /I +>> +endobj +249 0 obj +<< /Type /Annot +/Subtype /Link +/Rect [ 373.595 637.683 444.155 627.683 ] +/C [ 0 0 0 ] +/Border [ 0 0 0 ] +/A << /URI (http://uffi.b9.com) +/S /URI >> +/H /I +>> +endobj +250 0 obj +<< /Type /Annot +/Subtype /Link +/Rect [ 582.79 626.683 614.47 616.683 ] +/C [ 0 0 0 ] +/Border [ 0 0 0 ] +/A << /URI (http://www.sourceforge.net/projects/cclan) +/S /URI >> +/H /I +>> +endobj +251 0 obj +<< /Type /Annot +/Subtype /Link +/Rect [ 626.66 626.683 641.1 616.683 ] +/C [ 0 0 0 ] +/Border [ 0 0 0 ] +/A << /URI (http://www.sourceforge.net/projects/cclan) +/S /URI >> +/H /I +>> +endobj +252 0 obj +<< /Type /Annot +/Subtype /Link +/Rect [ 120.0 615.683 280.52 605.683 ] +/C [ 0 0 0 ] +/Border [ 0 0 0 ] +/A << /URI (http://www.sourceforge.net/projects/cclan) +/S /URI >> +/H /I +>> +endobj +253 0 obj +<< /Type /Annot +/Subtype /Link +/Rect [ 156.67 604.683 172.22 594.683 ] +/C [ 0 0 0 ] +/Border [ 0 0 0 ] +/A << /URI (http://cvs.sourceforge.net/cgi-bin/viewcvs.cgi/cclan/asdf/asdf.lisp) +/S /URI >> +/H /I +>> +endobj +254 0 obj +<< /Type /Annot +/Subtype /Link +/Rect [ 178.05 604.683 440.79 594.683 ] +/C [ 0 0 0 ] +/Border [ 0 0 0 ] +/A << /URI (http://cvs.sourceforge.net/cgi-bin/viewcvs.cgi/cclan/asdf/asdf.lisp) +/S /URI >> +/H /I +>> +endobj +255 0 obj +<< /Length 280 /Filter [ /ASCII85Decode /FlateDecode ] + >> +stream +GarVI]afWJ&Dm9u2p,Oq5;7s,UROh6F[-#*#uI``q">Jf5_uu4bMDo6GDSeiPQMRYME'f4&\&tk`#",h at 0.p9YnA5D)GZ2rAY7;m]`Ycp5'X%08j(3'#8(NQ6V2iC(k5PbFbR@`!A#[Z]BLMf20j!(['ai+_Ne81r4HZkJku +endstream +endobj +256 0 obj +<< /Type /Page +/Parent 1 0 R +/MediaBox [ 0 0 612 792 ] +/Resources 3 0 R +/Contents 255 0 R +>> +endobj +259 0 obj +<< + /Title (\376\377\0\125\0\106\0\106\0\111\0\40\0\122\0\145\0\146\0\145\0\162\0\145\0\156\0\143\0\145\0\40\0\107\0\165\0\151\0\144\0\145) + /Parent 257 0 R + /Next 261 0 R + /A 258 0 R +>> endobj +261 0 obj +<< + /Title (\376\377\0\124\0\141\0\142\0\154\0\145\0\40\0\157\0\146\0\40\0\103\0\157\0\156\0\164\0\145\0\156\0\164\0\163) + /Parent 257 0 R + /Prev 259 0 R + /Next 262 0 R + /A 260 0 R +>> endobj +262 0 obj +<< + /Title (\376\377\0\120\0\162\0\145\0\146\0\141\0\143\0\145) + /Parent 257 0 R + /Prev 261 0 R + /Next 263 0 R + /A 15 0 R +>> endobj +263 0 obj +<< + /Title (\376\377\0\103\0\150\0\141\0\160\0\164\0\145\0\162\0\240\0\61\0\56\0\240\0\111\0\156\0\164\0\162\0\157\0\144\0\165\0\143\0\164\0\151\0\157\0\156) + /Parent 257 0 R + /First 264 0 R + /Last 267 0 R + /Prev 262 0 R + /Next 270 0 R + /Count -6 + /A 17 0 R +>> endobj +264 0 obj +<< + /Title (\376\377\0\120\0\165\0\162\0\160\0\157\0\163\0\145) + /Parent 263 0 R + /Next 265 0 R + /A 19 0 R +>> endobj +265 0 obj +<< + /Title (\376\377\0\102\0\141\0\143\0\153\0\147\0\162\0\157\0\165\0\156\0\144) + /Parent 263 0 R + /Prev 264 0 R + /Next 266 0 R + /A 21 0 R +>> endobj +266 0 obj +<< + /Title (\376\377\0\123\0\165\0\160\0\160\0\157\0\162\0\164\0\145\0\144\0\40\0\111\0\155\0\160\0\154\0\145\0\155\0\145\0\156\0\164\0\141\0\164\0\151\0\157\0\156\0\163) + /Parent 263 0 R + /Prev 265 0 R + /Next 267 0 R + /A 23 0 R +>> endobj +267 0 obj +<< + /Title (\376\377\0\104\0\145\0\163\0\151\0\147\0\156) + /Parent 263 0 R + /First 268 0 R + /Last 269 0 R + /Prev 266 0 R + /Count -2 + /A 25 0 R +>> endobj +268 0 obj +<< + /Title (\376\377\0\117\0\166\0\145\0\162\0\166\0\151\0\145\0\167) + /Parent 267 0 R + /Next 269 0 R + /A 27 0 R +>> endobj +269 0 obj +<< + /Title (\376\377\0\120\0\162\0\151\0\157\0\162\0\151\0\164\0\151\0\145\0\163) + /Parent 267 0 R + /Prev 268 0 R + /A 29 0 R +>> endobj +270 0 obj +<< + /Title (\376\377\0\103\0\150\0\141\0\160\0\164\0\145\0\162\0\240\0\62\0\56\0\240\0\120\0\162\0\157\0\147\0\162\0\141\0\155\0\155\0\151\0\156\0\147\0\40\0\116\0\157\0\164\0\145\0\163) + /Parent 257 0 R + /First 271 0 R + /Last 276 0 R + /Prev 263 0 R + /Next 279 0 R + /Count -8 + /A 31 0 R +>> endobj +271 0 obj +<< + /Title (\376\377\0\111\0\155\0\160\0\154\0\145\0\155\0\145\0\156\0\164\0\141\0\164\0\151\0\157\0\156\0\40\0\123\0\160\0\145\0\143\0\151\0\146\0\151\0\143\0\40\0\116\0\157\0\164\0\145\0\163) + /Parent 270 0 R + /First 272 0 R + /Last 274 0 R + /Next 275 0 R + /Count -3 + /A 33 0 R +>> endobj +272 0 obj +<< + /Title (\376\377\0\101\0\154\0\154\0\145\0\147\0\162\0\157\0\103\0\114) + /Parent 271 0 R + /Next 273 0 R + /A 35 0 R +>> endobj +273 0 obj +<< + /Title (\376\377\0\114\0\151\0\163\0\160\0\167\0\157\0\162\0\153\0\163) + /Parent 271 0 R + /Prev 272 0 R + /Next 274 0 R + /A 37 0 R +>> endobj +274 0 obj +<< + /Title (\376\377\0\103\0\115\0\125\0\103\0\114) + /Parent 271 0 R + /Prev 273 0 R + /A 39 0 R +>> endobj +275 0 obj +<< + /Title (\376\377\0\106\0\157\0\162\0\145\0\151\0\147\0\156\0\40\0\117\0\142\0\152\0\145\0\143\0\164\0\40\0\122\0\145\0\160\0\162\0\145\0\163\0\145\0\156\0\164\0\141\0\164\0\151\0\157\0\156\0\40\0\141\0\156\0\144\0\40\0\101\0\143\0\143\0\145\0\163\0\163) + /Parent 270 0 R + /Prev 271 0 R + /Next 276 0 R + /A 41 0 R +>> endobj +276 0 obj +<< + /Title (\376\377\0\117\0\160\0\164\0\151\0\155\0\151\0\172\0\151\0\156\0\147\0\40\0\103\0\157\0\144\0\145\0\40\0\125\0\163\0\151\0\156\0\147\0\40\0\125\0\106\0\106\0\111) + /Parent 270 0 R + /First 277 0 R + /Last 278 0 R + /Prev 275 0 R + /Count -2 + /A 43 0 R +>> endobj +277 0 obj +<< + /Title (\376\377\0\102\0\141\0\143\0\153\0\147\0\162\0\157\0\165\0\156\0\144) + /Parent 276 0 R + /Next 278 0 R + /A 45 0 R +>> endobj +278 0 obj +<< + /Title (\376\377\0\103\0\162\0\157\0\163\0\163\0\55\0\111\0\155\0\160\0\154\0\145\0\155\0\145\0\156\0\164\0\141\0\164\0\151\0\157\0\156\0\40\0\117\0\160\0\164\0\151\0\155\0\151\0\172\0\141\0\164\0\151\0\157\0\156) + /Parent 276 0 R + /Prev 277 0 R + /A 47 0 R +>> endobj +279 0 obj +<< + /Title (\376\377\0\104\0\145\0\143\0\154\0\141\0\162\0\141\0\164\0\151\0\157\0\156\0\163) + /Parent 257 0 R + /First 281 0 R + /Last 282 0 R + /Prev 270 0 R + /Next 283 0 R + /Count -2 + /A 49 0 R +>> endobj +281 0 obj +<< + /Title (\376\377\0\117\0\166\0\145\0\162\0\166\0\151\0\145\0\167) + /Parent 279 0 R + /Next 282 0 R + /A 280 0 R +>> endobj +282 0 obj +<< + /Title (\376\377\0\144\0\145\0\146\0\55\0\164\0\171\0\160\0\145) + /Parent 279 0 R + /Prev 281 0 R + /A 51 0 R +>> endobj +283 0 obj +<< + /Title (\376\377\0\120\0\162\0\151\0\155\0\151\0\164\0\151\0\166\0\145\0\40\0\124\0\171\0\160\0\145\0\163) + /Parent 257 0 R + /First 284 0 R + /Last 286 0 R + /Prev 279 0 R + /Next 287 0 R + /Count -3 + /A 53 0 R +>> endobj +284 0 obj +<< + /Title (\376\377\0\144\0\145\0\146\0\55\0\143\0\157\0\156\0\163\0\164\0\141\0\156\0\164) + /Parent 283 0 R + /Next 285 0 R + /A 55 0 R +>> endobj +285 0 obj +<< + /Title (\376\377\0\144\0\145\0\146\0\55\0\146\0\157\0\162\0\145\0\151\0\147\0\156\0\55\0\164\0\171\0\160\0\145) + /Parent 283 0 R + /Prev 284 0 R + /Next 286 0 R + /A 57 0 R +>> endobj +286 0 obj +<< + /Title (\376\377\0\156\0\165\0\154\0\154\0\55\0\143\0\150\0\141\0\162\0\55\0\160) + /Parent 283 0 R + /Prev 285 0 R + /A 59 0 R +>> endobj +287 0 obj +<< + /Title (\376\377\0\101\0\147\0\147\0\162\0\145\0\147\0\141\0\164\0\145\0\40\0\124\0\171\0\160\0\145\0\163) + /Parent 257 0 R + /First 288 0 R + /Last 294 0 R + /Prev 283 0 R + /Next 295 0 R + /Count -7 + /A 61 0 R +>> endobj +288 0 obj +<< + /Title (\376\377\0\144\0\145\0\146\0\55\0\145\0\156\0\165\0\155) + /Parent 287 0 R + /Next 289 0 R + /A 63 0 R +>> endobj +289 0 obj +<< + /Title (\376\377\0\144\0\145\0\146\0\55\0\163\0\164\0\162\0\165\0\143\0\164) + /Parent 287 0 R + /Prev 288 0 R + /Next 290 0 R + /A 65 0 R +>> endobj +290 0 obj +<< + /Title (\376\377\0\147\0\145\0\164\0\55\0\163\0\154\0\157\0\164\0\55\0\166\0\141\0\154\0\165\0\145) + /Parent 287 0 R + /Prev 289 0 R + /Next 291 0 R + /A 67 0 R +>> endobj +291 0 obj +<< + /Title (\376\377\0\147\0\145\0\164\0\55\0\163\0\154\0\157\0\164\0\55\0\160\0\157\0\151\0\156\0\164\0\145\0\162) + /Parent 287 0 R + /Prev 290 0 R + /Next 292 0 R + /A 69 0 R +>> endobj +292 0 obj +<< + /Title (\376\377\0\144\0\145\0\146\0\55\0\141\0\162\0\162\0\141\0\171\0\55\0\160\0\157\0\151\0\156\0\164\0\145\0\162) + /Parent 287 0 R + /Prev 291 0 R + /Next 293 0 R + /A 71 0 R +>> endobj +293 0 obj +<< + /Title (\376\377\0\144\0\145\0\162\0\145\0\146\0\55\0\141\0\162\0\162\0\141\0\171) + /Parent 287 0 R + /Prev 292 0 R + /Next 294 0 R + /A 73 0 R +>> endobj +294 0 obj +<< + /Title (\376\377\0\144\0\145\0\146\0\55\0\165\0\156\0\151\0\157\0\156) + /Parent 287 0 R + /Prev 293 0 R + /A 75 0 R +>> endobj +295 0 obj +<< + /Title (\376\377\0\117\0\142\0\152\0\145\0\143\0\164\0\163) + /Parent 257 0 R + /First 296 0 R + /Last 308 0 R + /Prev 287 0 R + /Next 309 0 R + /Count -13 + /A 77 0 R +>> endobj +296 0 obj +<< + /Title (\376\377\0\141\0\154\0\154\0\157\0\143\0\141\0\164\0\145\0\55\0\146\0\157\0\162\0\145\0\151\0\147\0\156\0\55\0\157\0\142\0\152\0\145\0\143\0\164) + /Parent 295 0 R + /Next 297 0 R + /A 79 0 R +>> endobj +297 0 obj +<< + /Title (\376\377\0\146\0\162\0\145\0\145\0\55\0\146\0\157\0\162\0\145\0\151\0\147\0\156\0\55\0\157\0\142\0\152\0\145\0\143\0\164) + /Parent 295 0 R + /Prev 296 0 R + /Next 298 0 R + /A 81 0 R +>> endobj +298 0 obj +<< + /Title (\376\377\0\167\0\151\0\164\0\150\0\55\0\146\0\157\0\162\0\145\0\151\0\147\0\156\0\55\0\157\0\142\0\152\0\145\0\143\0\164) + /Parent 295 0 R + /Prev 297 0 R + /Next 299 0 R + /A 83 0 R +>> endobj +299 0 obj +<< + /Title (\376\377\0\163\0\151\0\172\0\145\0\55\0\157\0\146\0\55\0\146\0\157\0\162\0\145\0\151\0\147\0\156\0\55\0\164\0\171\0\160\0\145) + /Parent 295 0 R + /Prev 298 0 R + /Next 300 0 R + /A 85 0 R +>> endobj +300 0 obj +<< + /Title (\376\377\0\160\0\157\0\151\0\156\0\164\0\145\0\162\0\55\0\141\0\144\0\144\0\162\0\145\0\163\0\163) + /Parent 295 0 R + /Prev 299 0 R + /Next 301 0 R + /A 87 0 R +>> endobj +301 0 obj +<< + /Title (\376\377\0\144\0\145\0\162\0\145\0\146\0\55\0\160\0\157\0\151\0\156\0\164\0\145\0\162) + /Parent 295 0 R + /Prev 300 0 R + /Next 302 0 R + /A 89 0 R +>> endobj +302 0 obj +<< + /Title (\376\377\0\145\0\156\0\163\0\165\0\162\0\145\0\55\0\143\0\150\0\141\0\162\0\55\0\143\0\150\0\141\0\162\0\141\0\143\0\164\0\145\0\162) + /Parent 295 0 R + /Prev 301 0 R + /Next 303 0 R + /A 91 0 R +>> endobj +303 0 obj +<< + /Title (\376\377\0\145\0\156\0\163\0\165\0\162\0\145\0\55\0\143\0\150\0\141\0\162\0\55\0\151\0\156\0\164\0\145\0\147\0\145\0\162) + /Parent 295 0 R + /Prev 302 0 R + /Next 304 0 R + /A 93 0 R +>> endobj +304 0 obj +<< + /Title (\376\377\0\155\0\141\0\153\0\145\0\55\0\156\0\165\0\154\0\154\0\55\0\160\0\157\0\151\0\156\0\164\0\145\0\162) + /Parent 295 0 R + /Prev 303 0 R + /Next 305 0 R + /A 95 0 R +>> endobj +305 0 obj +<< + /Title (\376\377\0\156\0\165\0\154\0\154\0\55\0\160\0\157\0\151\0\156\0\164\0\145\0\162\0\55\0\160) + /Parent 295 0 R + /Prev 304 0 R + /Next 306 0 R + /A 97 0 R +>> endobj +306 0 obj +<< + /Title (\376\377\0\53\0\156\0\165\0\154\0\154\0\55\0\143\0\163\0\164\0\162\0\151\0\156\0\147\0\55\0\160\0\157\0\151\0\156\0\164\0\145\0\162\0\53) + /Parent 295 0 R + /Prev 305 0 R + /Next 307 0 R + /A 99 0 R +>> endobj +307 0 obj +<< + /Title (\376\377\0\167\0\151\0\164\0\150\0\55\0\143\0\141\0\163\0\164\0\55\0\160\0\157\0\151\0\156\0\164\0\145\0\162) + /Parent 295 0 R + /Prev 306 0 R + /Next 308 0 R + /A 101 0 R +>> endobj +308 0 obj +<< + /Title (\376\377\0\144\0\145\0\146\0\55\0\146\0\157\0\162\0\145\0\151\0\147\0\156\0\55\0\166\0\141\0\162) + /Parent 295 0 R + /Prev 307 0 R + /A 103 0 R +>> endobj +309 0 obj +<< + /Title (\376\377\0\123\0\164\0\162\0\151\0\156\0\147\0\163) + /Parent 257 0 R + /First 310 0 R + /Last 316 0 R + /Prev 295 0 R + /Next 317 0 R + /Count -7 + /A 105 0 R +>> endobj +310 0 obj +<< + /Title (\376\377\0\143\0\157\0\156\0\166\0\145\0\162\0\164\0\55\0\146\0\162\0\157\0\155\0\55\0\143\0\163\0\164\0\162\0\151\0\156\0\147) + /Parent 309 0 R + /Next 311 0 R + /A 107 0 R +>> endobj +311 0 obj +<< + /Title (\376\377\0\143\0\157\0\156\0\166\0\145\0\162\0\164\0\55\0\164\0\157\0\55\0\143\0\163\0\164\0\162\0\151\0\156\0\147) + /Parent 309 0 R + /Prev 310 0 R + /Next 312 0 R + /A 109 0 R +>> endobj +312 0 obj +<< + /Title (\376\377\0\146\0\162\0\145\0\145\0\55\0\143\0\163\0\164\0\162\0\151\0\156\0\147) + /Parent 309 0 R + /Prev 311 0 R + /Next 313 0 R + /A 111 0 R +>> endobj +313 0 obj +<< + /Title (\376\377\0\167\0\151\0\164\0\150\0\55\0\143\0\163\0\164\0\162\0\151\0\156\0\147) + /Parent 309 0 R + /Prev 312 0 R + /Next 314 0 R + /A 113 0 R +>> endobj +314 0 obj +<< + /Title (\376\377\0\143\0\157\0\156\0\166\0\145\0\162\0\164\0\55\0\146\0\162\0\157\0\155\0\55\0\146\0\157\0\162\0\145\0\151\0\147\0\156\0\55\0\163\0\164\0\162\0\151\0\156\0\147) + /Parent 309 0 R + /Prev 313 0 R + /Next 315 0 R + /A 115 0 R +>> endobj +315 0 obj +<< + /Title (\376\377\0\143\0\157\0\156\0\166\0\145\0\162\0\164\0\55\0\164\0\157\0\55\0\146\0\157\0\162\0\145\0\151\0\147\0\156\0\55\0\163\0\164\0\162\0\151\0\156\0\147) + /Parent 309 0 R + /Prev 314 0 R + /Next 316 0 R + /A 117 0 R +>> endobj +316 0 obj +<< + /Title (\376\377\0\141\0\154\0\154\0\157\0\143\0\141\0\164\0\145\0\55\0\146\0\157\0\162\0\145\0\151\0\147\0\156\0\55\0\163\0\164\0\162\0\151\0\156\0\147) + /Parent 309 0 R + /Prev 315 0 R + /A 119 0 R +>> endobj +317 0 obj +<< + /Title (\376\377\0\106\0\165\0\156\0\143\0\164\0\151\0\157\0\156\0\163\0\40\0\46\0\40\0\114\0\151\0\142\0\162\0\141\0\162\0\151\0\145\0\163) + /Parent 257 0 R + /First 318 0 R + /Last 320 0 R + /Prev 309 0 R + /Next 321 0 R + /Count -3 + /A 124 0 R +>> endobj +318 0 obj +<< + /Title (\376\377\0\144\0\145\0\146\0\55\0\146\0\165\0\156\0\143\0\164\0\151\0\157\0\156) + /Parent 317 0 R + /Next 319 0 R + /A 126 0 R +>> endobj +319 0 obj +<< + /Title (\376\377\0\154\0\157\0\141\0\144\0\55\0\146\0\157\0\162\0\145\0\151\0\147\0\156\0\55\0\154\0\151\0\142\0\162\0\141\0\162\0\171) + /Parent 317 0 R + /Prev 318 0 R + /Next 320 0 R + /A 128 0 R +>> endobj +320 0 obj +<< + /Title (\376\377\0\146\0\151\0\156\0\144\0\55\0\146\0\157\0\162\0\145\0\151\0\147\0\156\0\55\0\154\0\151\0\142\0\162\0\141\0\162\0\171) + /Parent 317 0 R + /Prev 319 0 R + /A 130 0 R +>> endobj +321 0 obj +<< + /Title (\376\377\0\101\0\160\0\160\0\145\0\156\0\144\0\151\0\170\0\240\0\101\0\56\0\240\0\111\0\156\0\163\0\164\0\141\0\154\0\154\0\141\0\164\0\151\0\157\0\156) + /Parent 257 0 R + /First 322 0 R + /Last 323 0 R + /Prev 317 0 R + /Next 324 0 R + /Count -2 + /A 132 0 R +>> endobj +322 0 obj +<< + /Title (\376\377\0\104\0\157\0\167\0\156\0\154\0\157\0\141\0\144\0\40\0\125\0\106\0\106\0\111) + /Parent 321 0 R + /Next 323 0 R + /A 134 0 R +>> endobj +323 0 obj +<< + /Title (\376\377\0\114\0\157\0\141\0\144\0\151\0\156\0\147) + /Parent 321 0 R + /Prev 322 0 R + /A 136 0 R +>> endobj +324 0 obj +<< + /Title (\376\377\0\107\0\154\0\157\0\163\0\163\0\141\0\162\0\171) + /Parent 257 0 R + /Prev 321 0 R + /A 138 0 R +>> endobj +325 0 obj +<< /Type /Font +/Subtype /Type1 +/Name /F3 +/BaseFont /Helvetica-Bold +/Encoding /WinAnsiEncoding >> +endobj +326 0 obj +<< /Type /Font +/Subtype /Type1 +/Name /F5 +/BaseFont /Times-Roman +/Encoding /WinAnsiEncoding >> +endobj +327 0 obj +<< /Type /Font +/Subtype /Type1 +/Name /F10 +/BaseFont /Courier-Oblique +/Encoding /WinAnsiEncoding >> +endobj +328 0 obj +<< /Type /Font +/Subtype /Type1 +/Name /F1 +/BaseFont /Helvetica +/Encoding /WinAnsiEncoding >> +endobj +329 0 obj +<< /Type /Font +/Subtype /Type1 +/Name /F6 +/BaseFont /Times-Italic +/Encoding /WinAnsiEncoding >> +endobj +330 0 obj +<< /Type /Font +/Subtype /Type1 +/Name /F4 +/BaseFont /Helvetica-BoldOblique +/Encoding /WinAnsiEncoding >> +endobj +331 0 obj +<< /Type /Font +/Subtype /Type1 +/Name /F9 +/BaseFont /Courier +/Encoding /WinAnsiEncoding >> +endobj +332 0 obj +<< /Type /Font +/Subtype /Type1 +/Name /F7 +/BaseFont /Times-Bold +/Encoding /WinAnsiEncoding >> +endobj +1 0 obj +<< /Type /Pages +/Count 60 +/Kids [6 0 R 8 0 R 10 0 R 12 0 R 121 0 R 140 0 R 142 0 R 144 0 R 146 0 R 148 0 R 150 0 R 152 0 R 154 0 R 156 0 R 158 0 R 160 0 R 162 0 R 164 0 R 166 0 R 168 0 R 170 0 R 172 0 R 174 0 R 176 0 R 178 0 R 180 0 R 182 0 R 184 0 R 186 0 R 188 0 R 190 0 R 192 0 R 194 0 R 196 0 R 198 0 R 200 0 R 202 0 R 204 0 R 206 0 R 208 0 R 210 0 R 212 0 R 214 0 R 216 0 R 218 0 R 220 0 R 222 0 R 224 0 R 226 0 R 228 0 R 230 0 R 232 0 R 234 0 R 236 0 R 238 0 R 240 0 R 242 0 R 244 0 R 246 0 R 256 0 R ] >> +endobj +2 0 obj +<< /Type /Catalog +/Pages 1 0 R + /Outlines 257 0 R + /PageMode /UseOutlines + /Names << /Dests << /Names [ (preface) [ 140 0 R /XYZ 115.0 725.0 null ] (introduction) [ 142 0 R /XYZ 115.0 725.0 null ] (notes) [ 146 0 R /XYZ 115.0 725.0 null ] (ref_declarations) [ 150 0 R /XYZ 115.0 725.0 null ] (primitives) [ 154 0 R /XYZ 115.0 725.0 null ] (aggregates) [ 162 0 R /XYZ 115.0 725.0 null ] (objects) [ 182 0 R /XYZ 115.0 725.0 null ] (strings) [ 216 0 R /XYZ 115.0 725.0 null ] (func_libr) [ 234 0 R /XYZ 115.0 725.0 null ] (installation) [ 246 0 R /XYZ 115.0 725.0 null ] (glossary) [ 256 0 R /XYZ 115.0 725.0 null ] (id2452772) [ 10 0 R /XYZ 115.0 725.0 null ] ] >> >> + >> +endobj +3 0 obj +<< +/Font << /F3 325 0 R /F5 326 0 R /F10 327 0 R /F6 329 0 R /F1 328 0 R /F4 330 0 R /F9 331 0 R /F7 332 0 R >> +/ProcSet [ /PDF /ImageC /Text ] >> +endobj +15 0 obj +<< +/S /GoTo +/D [140 0 R /XYZ 115.0 725.0 null] +>> +endobj +17 0 obj +<< +/S /GoTo +/D [142 0 R /XYZ 115.0 725.0 null] +>> +endobj +19 0 obj +<< +/S /GoTo +/D [142 0 R /XYZ 115.0 687.009 null] +>> +endobj +21 0 obj +<< +/S /GoTo +/D [142 0 R /XYZ 115.0 621.683 null] +>> +endobj +23 0 obj +<< +/S /GoTo +/D [142 0 R /XYZ 115.0 459.357 null] +>> +endobj +25 0 obj +<< +/S /GoTo +/D [142 0 R /XYZ 115.0 197.031 null] +>> +endobj +27 0 obj +<< +/S /GoTo +/D [142 0 R /XYZ 115.0 163.705 null] +>> +endobj +29 0 obj +<< +/S /GoTo +/D [144 0 R /XYZ 115.0 725.0 null] +>> +endobj +31 0 obj +<< +/S /GoTo +/D [146 0 R /XYZ 115.0 725.0 null] +>> +endobj +33 0 obj +<< +/S /GoTo +/D [146 0 R /XYZ 115.0 687.009 null] +>> +endobj +35 0 obj +<< +/S /GoTo +/D [146 0 R /XYZ 115.0 643.683 null] +>> +endobj +37 0 obj +<< +/S /GoTo +/D [146 0 R /XYZ 115.0 604.244 null] +>> +endobj +39 0 obj +<< +/S /GoTo +/D [146 0 R /XYZ 115.0 564.805 null] +>> +endobj +41 0 obj +<< +/S /GoTo +/D [146 0 R /XYZ 115.0 525.366 null] +>> +endobj +43 0 obj +<< +/S /GoTo +/D [146 0 R /XYZ 115.0 405.04 null] +>> +endobj +45 0 obj +<< +/S /GoTo +/D [146 0 R /XYZ 115.0 371.714 null] +>> +endobj +47 0 obj +<< +/S /GoTo +/D [146 0 R /XYZ 115.0 224.275 null] +>> +endobj +49 0 obj +<< +/S /GoTo +/D [150 0 R /XYZ 115.0 725.0 null] +>> +endobj +51 0 obj +<< +/S /GoTo +/D [152 0 R /XYZ 115.0 725.0 null] +>> +endobj +53 0 obj +<< +/S /GoTo +/D [154 0 R /XYZ 115.0 725.0 null] +>> +endobj +55 0 obj +<< +/S /GoTo +/D [156 0 R /XYZ 115.0 725.0 null] +>> +endobj +57 0 obj +<< +/S /GoTo +/D [158 0 R /XYZ 115.0 725.0 null] +>> +endobj +59 0 obj +<< +/S /GoTo +/D [160 0 R /XYZ 115.0 725.0 null] +>> +endobj +61 0 obj +<< +/S /GoTo +/D [162 0 R /XYZ 115.0 725.0 null] +>> +endobj +63 0 obj +<< +/S /GoTo +/D [164 0 R /XYZ 115.0 725.0 null] +>> +endobj +65 0 obj +<< +/S /GoTo +/D [168 0 R /XYZ 115.0 725.0 null] +>> +endobj +67 0 obj +<< +/S /GoTo +/D [170 0 R /XYZ 115.0 725.0 null] +>> +endobj +69 0 obj +<< +/S /GoTo +/D [172 0 R /XYZ 115.0 725.0 null] +>> +endobj +71 0 obj +<< +/S /GoTo +/D [174 0 R /XYZ 115.0 725.0 null] +>> +endobj +73 0 obj +<< +/S /GoTo +/D [176 0 R /XYZ 115.0 725.0 null] +>> +endobj +75 0 obj +<< +/S /GoTo +/D [180 0 R /XYZ 115.0 725.0 null] +>> +endobj +77 0 obj +<< +/S /GoTo +/D [182 0 R /XYZ 115.0 725.0 null] +>> +endobj +79 0 obj +<< +/S /GoTo +/D [184 0 R /XYZ 115.0 725.0 null] +>> +endobj +81 0 obj +<< +/S /GoTo +/D [186 0 R /XYZ 115.0 725.0 null] +>> +endobj +83 0 obj +<< +/S /GoTo +/D [188 0 R /XYZ 115.0 725.0 null] +>> +endobj +85 0 obj +<< +/S /GoTo +/D [190 0 R /XYZ 115.0 725.0 null] +>> +endobj +87 0 obj +<< +/S /GoTo +/D [192 0 R /XYZ 115.0 725.0 null] +>> +endobj +89 0 obj +<< +/S /GoTo +/D [194 0 R /XYZ 115.0 725.0 null] +>> +endobj +91 0 obj +<< +/S /GoTo +/D [198 0 R /XYZ 115.0 725.0 null] +>> +endobj +93 0 obj +<< +/S /GoTo +/D [200 0 R /XYZ 115.0 725.0 null] +>> +endobj +95 0 obj +<< +/S /GoTo +/D [202 0 R /XYZ 115.0 725.0 null] +>> +endobj +97 0 obj +<< +/S /GoTo +/D [204 0 R /XYZ 115.0 725.0 null] +>> +endobj +99 0 obj +<< +/S /GoTo +/D [206 0 R /XYZ 115.0 725.0 null] +>> +endobj +101 0 obj +<< +/S /GoTo +/D [208 0 R /XYZ 115.0 725.0 null] +>> +endobj +103 0 obj +<< +/S /GoTo +/D [212 0 R /XYZ 115.0 725.0 null] +>> +endobj +105 0 obj +<< +/S /GoTo +/D [216 0 R /XYZ 115.0 725.0 null] +>> +endobj +107 0 obj +<< +/S /GoTo +/D [220 0 R /XYZ 115.0 725.0 null] +>> +endobj +109 0 obj +<< +/S /GoTo +/D [222 0 R /XYZ 115.0 725.0 null] +>> +endobj +111 0 obj +<< +/S /GoTo +/D [224 0 R /XYZ 115.0 725.0 null] +>> +endobj +113 0 obj +<< +/S /GoTo +/D [226 0 R /XYZ 115.0 725.0 null] +>> +endobj +115 0 obj +<< +/S /GoTo +/D [228 0 R /XYZ 115.0 725.0 null] +>> +endobj +117 0 obj +<< +/S /GoTo +/D [230 0 R /XYZ 115.0 725.0 null] +>> +endobj +119 0 obj +<< +/S /GoTo +/D [232 0 R /XYZ 115.0 725.0 null] +>> +endobj +124 0 obj +<< +/S /GoTo +/D [234 0 R /XYZ 115.0 725.0 null] +>> +endobj +126 0 obj +<< +/S /GoTo +/D [236 0 R /XYZ 115.0 725.0 null] +>> +endobj +128 0 obj +<< +/S /GoTo +/D [240 0 R /XYZ 115.0 725.0 null] +>> +endobj +130 0 obj +<< +/S /GoTo +/D [244 0 R /XYZ 115.0 725.0 null] +>> +endobj +132 0 obj +<< +/S /GoTo +/D [246 0 R /XYZ 115.0 725.0 null] +>> +endobj +134 0 obj +<< +/S /GoTo +/D [246 0 R /XYZ 115.0 687.009 null] +>> +endobj +136 0 obj +<< +/S /GoTo +/D [246 0 R /XYZ 115.0 599.683 null] +>> +endobj +138 0 obj +<< +/S /GoTo +/D [256 0 R /XYZ 115.0 725.0 null] +>> +endobj +257 0 obj +<< + /First 259 0 R + /Last 324 0 R +>> endobj +258 0 obj +<< +/S /GoTo +/D [10 0 R /XYZ 115.0 725.0 null] +>> +endobj +260 0 obj +<< +/S /GoTo +/D [12 0 R /XYZ 115.0 715.0 null] +>> +endobj +280 0 obj +<< +/S /GoTo +/D [150 0 R /XYZ 115.0 678.347 null] +>> +endobj +xref +0 333 +0000000000 65535 f +0000087357 00000 n +0000087884 00000 n +0000088571 00000 n +0000000015 00000 n +0000000071 00000 n +0000000363 00000 n +0000000469 00000 n +0000001525 00000 n +0000001631 00000 n +0000001792 00000 n +0000001899 00000 n +0000003924 00000 n +0000004047 00000 n +0000004448 00000 n +0000088736 00000 n +0000004584 00000 n +0000088802 00000 n +0000004720 00000 n +0000088868 00000 n +0000004856 00000 n +0000088936 00000 n +0000004992 00000 n +0000089004 00000 n +0000005128 00000 n +0000089072 00000 n +0000005264 00000 n +0000089140 00000 n +0000005400 00000 n +0000089208 00000 n +0000005536 00000 n +0000089274 00000 n +0000005672 00000 n +0000089340 00000 n +0000005808 00000 n +0000089408 00000 n +0000005944 00000 n +0000089476 00000 n +0000006080 00000 n +0000089544 00000 n +0000006216 00000 n +0000089612 00000 n +0000006352 00000 n +0000089680 00000 n +0000006488 00000 n +0000089747 00000 n +0000006624 00000 n +0000089815 00000 n +0000006760 00000 n +0000089883 00000 n +0000006896 00000 n +0000089949 00000 n +0000007032 00000 n +0000090015 00000 n +0000007168 00000 n +0000090081 00000 n +0000007304 00000 n +0000090147 00000 n +0000007440 00000 n +0000090213 00000 n +0000007576 00000 n +0000090279 00000 n +0000007712 00000 n +0000090345 00000 n +0000007848 00000 n +0000090411 00000 n +0000007984 00000 n +0000090477 00000 n +0000008120 00000 n +0000090543 00000 n +0000008256 00000 n +0000090609 00000 n +0000008391 00000 n +0000090675 00000 n +0000008527 00000 n +0000090741 00000 n +0000008663 00000 n +0000090807 00000 n +0000008798 00000 n +0000090873 00000 n +0000008934 00000 n +0000090939 00000 n +0000009070 00000 n +0000091005 00000 n +0000009206 00000 n +0000091071 00000 n +0000009342 00000 n +0000091137 00000 n +0000009478 00000 n +0000091203 00000 n +0000009613 00000 n +0000091269 00000 n +0000009749 00000 n +0000091335 00000 n +0000009885 00000 n +0000091401 00000 n +0000010021 00000 n +0000091467 00000 n +0000010157 00000 n +0000091533 00000 n +0000010293 00000 n +0000091599 00000 n +0000010431 00000 n +0000091666 00000 n +0000010569 00000 n +0000091733 00000 n +0000010707 00000 n +0000091800 00000 n +0000010845 00000 n +0000091867 00000 n +0000010983 00000 n +0000091934 00000 n +0000011121 00000 n +0000092001 00000 n +0000011259 00000 n +0000092068 00000 n +0000011396 00000 n +0000092135 00000 n +0000011532 00000 n +0000092202 00000 n +0000011668 00000 n +0000012297 00000 n +0000012423 00000 n +0000012508 00000 n +0000092269 00000 n +0000012642 00000 n +0000092336 00000 n +0000012776 00000 n +0000092403 00000 n +0000012910 00000 n +0000092470 00000 n +0000013044 00000 n +0000092537 00000 n +0000013178 00000 n +0000092604 00000 n +0000013312 00000 n +0000092673 00000 n +0000013446 00000 n +0000092742 00000 n +0000013580 00000 n +0000014239 00000 n +0000014349 00000 n +0000016398 00000 n +0000016508 00000 n +0000017682 00000 n +0000017792 00000 n +0000020198 00000 n +0000020308 00000 n +0000020766 00000 n +0000020876 00000 n +0000021431 00000 n +0000021541 00000 n +0000022462 00000 n +0000022572 00000 n +0000023853 00000 n +0000023963 00000 n +0000025028 00000 n +0000025138 00000 n +0000025969 00000 n +0000026079 00000 n +0000027284 00000 n +0000027394 00000 n +0000027775 00000 n +0000027885 00000 n +0000029719 00000 n +0000029829 00000 n +0000030089 00000 n +0000030199 00000 n +0000031349 00000 n +0000031459 00000 n +0000032422 00000 n +0000032532 00000 n +0000033460 00000 n +0000033570 00000 n +0000034343 00000 n +0000034453 00000 n +0000035673 00000 n +0000035783 00000 n +0000036111 00000 n +0000036221 00000 n +0000037215 00000 n +0000037325 00000 n +0000037719 00000 n +0000037829 00000 n +0000038895 00000 n +0000039005 00000 n +0000039703 00000 n +0000039813 00000 n +0000041180 00000 n +0000041290 00000 n +0000042224 00000 n +0000042334 00000 n +0000043045 00000 n +0000043155 00000 n +0000044317 00000 n +0000044427 00000 n +0000044693 00000 n +0000044803 00000 n +0000045989 00000 n +0000046099 00000 n +0000047216 00000 n +0000047326 00000 n +0000048117 00000 n +0000048227 00000 n +0000048986 00000 n +0000049096 00000 n +0000049621 00000 n +0000049731 00000 n +0000051397 00000 n +0000051507 00000 n +0000051841 00000 n +0000051951 00000 n +0000053440 00000 n +0000053550 00000 n +0000054214 00000 n +0000054324 00000 n +0000056520 00000 n +0000056630 00000 n +0000057066 00000 n +0000057176 00000 n +0000057995 00000 n +0000058105 00000 n +0000058931 00000 n +0000059041 00000 n +0000059800 00000 n +0000059910 00000 n +0000061065 00000 n +0000061175 00000 n +0000062269 00000 n +0000062379 00000 n +0000063124 00000 n +0000063234 00000 n +0000064228 00000 n +0000064338 00000 n +0000064628 00000 n +0000064738 00000 n +0000066248 00000 n +0000066358 00000 n +0000066626 00000 n +0000066736 00000 n +0000068587 00000 n +0000068697 00000 n +0000069101 00000 n +0000069211 00000 n +0000070625 00000 n +0000070735 00000 n +0000071877 00000 n +0000072003 00000 n +0000072080 00000 n +0000072251 00000 n +0000072424 00000 n +0000072618 00000 n +0000072811 00000 n +0000073004 00000 n +0000073224 00000 n +0000073444 00000 n +0000073817 00000 n +0000092809 00000 n +0000092863 00000 n +0000073927 00000 n +0000092929 00000 n +0000074131 00000 n +0000074332 00000 n +0000074474 00000 n +0000074752 00000 n +0000074879 00000 n +0000075039 00000 n +0000075288 00000 n +0000075451 00000 n +0000075584 00000 n +0000075729 00000 n +0000076036 00000 n +0000076335 00000 n +0000076474 00000 n +0000076628 00000 n +0000076743 00000 n +0000077079 00000 n +0000077359 00000 n +0000077504 00000 n +0000077785 00000 n +0000092995 00000 n +0000077999 00000 n +0000078133 00000 n +0000078265 00000 n +0000078496 00000 n +0000078652 00000 n +0000078846 00000 n +0000078995 00000 n +0000079226 00000 n +0000079358 00000 n +0000079517 00000 n +0000079699 00000 n +0000079893 00000 n +0000080093 00000 n +0000080258 00000 n +0000080396 00000 n +0000080581 00000 n +0000080802 00000 n +0000081014 00000 n +0000081226 00000 n +0000081443 00000 n +0000081632 00000 n +0000081809 00000 n +0000082033 00000 n +0000082245 00000 n +0000082445 00000 n +0000082627 00000 n +0000082855 00000 n +0000083056 00000 n +0000083230 00000 n +0000083415 00000 n +0000083619 00000 n +0000083826 00000 n +0000083998 00000 n +0000084170 00000 n +0000084430 00000 n +0000084678 00000 n +0000084900 00000 n +0000085166 00000 n +0000085323 00000 n +0000085542 00000 n +0000085746 00000 n +0000086032 00000 n +0000086195 00000 n +0000086323 00000 n +0000086457 00000 n +0000086571 00000 n +0000086682 00000 n +0000086798 00000 n +0000086907 00000 n +0000087019 00000 n +0000087140 00000 n +0000087247 00000 n +trailer +<< +/Size 333 +/Root 2 0 R +/Info 4 0 R +>> +startxref +93064 +%%EOF Added: branches/trunk-reorg/thirdparty/uffi-1.6.0/doc/uffi.xml ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi-1.6.0/doc/uffi.xml Mon Feb 11 09:23:05 2008 @@ -0,0 +1,24 @@ + + + +%myents; +%xinclude; +]> + + + + + + + + + + + + + + + + Added: branches/trunk-reorg/thirdparty/uffi-1.6.0/doc/xinclude.mod ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi-1.6.0/doc/xinclude.mod Mon Feb 11 09:23:05 2008 @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + Added: branches/trunk-reorg/thirdparty/uffi-1.6.0/examples/Makefile ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi-1.6.0/examples/Makefile Mon Feb 11 09:23:05 2008 @@ -0,0 +1,45 @@ +# FILE IDENTIFICATION +# +# Name: Makefile +# Purpose: Makefile for UFFI examples +# Programer: Kevin M. Rosenberg +# Date Started: Mar 2002 +# +# CVS Id: $Id: Makefile 10614 2005-07-06 01:05:14Z kevin $ +# +# This file, part of UFFI, is Copyright (c) 2002-2005 by Kevin M. Rosenberg +# + +SUBDIRS:= + +include ../Makefile.common + +.PHONY: distclean +distclean: clean + + +base=c-test-fns +source=$(base).c +object=$(base).o +shared_lib=$(base).so + +.PHONY: all +all: $(shared_lib) + +linux: $(source) Makefile + gcc -fPIC -DPIC -c $(source) -o $(object) + gcc -shared $(object) -o $(shared_lib) + rm $(object) + +mac: + cc -dynamic -c $(source) -o $(object) + ld -bundle /usr/lib/bundle1.o -flat_namespace -undefined suppress -o $(base).dylib $(object) + ld -bundle /usr/lib/bundle1.o -flat_namespace -undefined suppress /usr/lib/libz.dylib -o z.dylib + +solaris: + cc -KPIC -c $(source) -o $(object) + cc -G $(object) -o $(shared_lib) + +aix-acl: + gcc -c -D_BSD -D_NO_PROTO -D_NONSTD_TYPES -D_MBI=void $(source) + make_shared -o $(shared_lib) $(object) Added: branches/trunk-reorg/thirdparty/uffi-1.6.0/examples/Makefile.msvc ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi-1.6.0/examples/Makefile.msvc Mon Feb 11 09:23:05 2008 @@ -0,0 +1,27 @@ +# FILE IDENTIFICATION +# +# Name: Makefile.msvc +# Purpose: Makefile for the CLSQL UFFI helper package (MSVC) +# Programer: Kevin M. Rosenberg +# Date Started: Mar 2002 +# +# CVS Id: $Id: Makefile.msvc,v 1.1 2002/03/23 10:26:03 kevin Exp $ +# +# This file, part of CLSQL, is Copyright (c) 2002-2005 by Kevin M. Rosenberg + +BASE=c-test-fns + +# Nothing to configure beyond here + +SRC=$(BASE).c +OBJ=$(BASE).obj +DLL=$(BASE).dll + +$(DLL): $(SRC) + cl /MD /LD -D_MT /DWIN32=1 $(SRC) + del $(OBJ) $(BASE).exp + +clean: + del /q $(DLL) + + Added: branches/trunk-reorg/thirdparty/uffi-1.6.0/examples/acl-compat-tester.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi-1.6.0/examples/acl-compat-tester.lisp Mon Feb 11 09:23:05 2008 @@ -0,0 +1,600 @@ +;; tester.cl +;; A test harness for Allegro CL. +;; +;; copyright (c) 1985-1986 Franz Inc, Alameda, CA +;; copyright (c) 1986-2001 Franz Inc, Berkeley, CA - All rights reserved. +;; +;; This code is free software; you can redistribute it and/or +;; modify it under the terms of the version 2.1 of +;; the GNU Lesser General Public License as published by +;; the Free Software Foundation, as clarified by the Franz +;; preamble to the LGPL found in +;; http://opensource.franz.com/preamble.html. +;; +;; This code is distributed in the hope that it will be useful, +;; but without any warranty; without even the implied warranty of +;; merchantability or fitness for a particular purpose. See the GNU +;; Lesser General Public License for more details. +;; +;; Version 2.1 of the GNU Lesser General Public License can be +;; found at http://opensource.franz.com/license.html. +;; If it is not present, you can access it from +;; http://www.gnu.org/copyleft/lesser.txt (until superseded by a newer +;; version) or write to the Free Software Foundation, Inc., 59 Temple +;; Place, Suite 330, Boston, MA 02111-1307 USA +;; +;;;; from the original ACL 6.1 sources: +;; $Id: acl-compat-tester.lisp 7061 2003-09-07 06:34:45Z kevin $ + + +(defpackage :util.test + (:use :common-lisp) + (:shadow #:test) + (:export +;;;; Control variables: + #:*break-on-test-failures* + #:*error-protect-tests* + #:*test-errors* + #:*test-successes* + #:*test-unexpected-failures* + +;;;; The test macros: + #:test + #:test-error + #:test-no-error + #:test-warning + #:test-no-warning + + #:with-tests + )) + +(in-package :util.test) + +#+cmu +(unless (find-class 'break nil) + (define-condition break (simple-condition) ())) + +(define-condition simple-break (error simple-condition) ()) + +;; the if* macro used in Allegro: +;; +;; This is in the public domain... please feel free to put this definition +;; in your code or distribute it with your version of lisp. + +(eval-when (:compile-toplevel :load-toplevel :execute) + (defvar if*-keyword-list '("then" "thenret" "else" "elseif"))) + +(defmacro if* (&rest args) + (do ((xx (reverse args) (cdr xx)) + (state :init) + (elseseen nil) + (totalcol nil) + (lookat nil nil) + (col nil)) + ((null xx) + (cond ((eq state :compl) + `(cond , at totalcol)) + (t (error "if*: illegal form ~s" args)))) + (cond ((and (symbolp (car xx)) + (member (symbol-name (car xx)) + if*-keyword-list + :test #'string-equal)) + (setq lookat (symbol-name (car xx))))) + + (cond ((eq state :init) + (cond (lookat (cond ((string-equal lookat "thenret") + (setq col nil + state :then)) + (t (error + "if*: bad keyword ~a" lookat)))) + (t (setq state :col + col nil) + (push (car xx) col)))) + ((eq state :col) + (cond (lookat + (cond ((string-equal lookat "else") + (cond (elseseen + (error + "if*: multiples elses"))) + (setq elseseen t) + (setq state :init) + (push `(t , at col) totalcol)) + ((string-equal lookat "then") + (setq state :then)) + (t (error "if*: bad keyword ~s" + lookat)))) + (t (push (car xx) col)))) + ((eq state :then) + (cond (lookat + (error + "if*: keyword ~s at the wrong place " (car xx))) + (t (setq state :compl) + (push `(,(car xx) , at col) totalcol)))) + ((eq state :compl) + (cond ((not (string-equal lookat "elseif")) + (error "if*: missing elseif clause "))) + (setq state :init))))) + + + + +(defvar *break-on-test-failures* nil + "When a test failure occurs, common-lisp:break is called, allowing +interactive debugging of the failure.") + +(defvar *test-errors* 0 + "The value is the number of test errors which have occurred.") +(defvar *test-successes* 0 + "The value is the number of test successes which have occurred.") +(defvar *test-unexpected-failures* 0 + "The value is the number of unexpected test failures which have occurred.") + +(defvar *error-protect-tests* nil + "Protect each test from errors. If an error occurs, then that will be +taken as a test failure unless test-error is being used.") + +(defmacro test-values-errorset (form &optional announce catch-breaks) + ;; internal macro + (let ((g-announce (gensym)) + (g-catch-breaks (gensym))) + `(let* ((,g-announce ,announce) + (,g-catch-breaks ,catch-breaks)) + (handler-case (cons t (multiple-value-list ,form)) + (condition (condition) + (if* (and (null ,g-catch-breaks) + (typep condition 'simple-break)) + then (break condition) + elseif ,g-announce + then (format *error-output* "~&Condition type: ~a~%" + (class-of condition)) + (format *error-output* "~&Message: ~a~%" condition)) + condition))))) + +(defmacro test-values (form &optional announce catch-breaks) + ;; internal macro + (if* *error-protect-tests* + then `(test-values-errorset ,form ,announce ,catch-breaks) + else `(cons t (multiple-value-list ,form)))) + +(defmacro test (expected-value test-form + &key (test #'eql test-given) + (multiple-values nil multiple-values-given) + (fail-info nil fail-info-given) + (known-failure nil known-failure-given) + +;;;;;;;;;; internal, undocumented keywords: +;;;; Note about these keywords: if they were documented, we'd have a +;;;; problem, since they break the left-to-right order of evaluation. +;;;; Specifically, errorset breaks it, and I don't see any way around +;;;; that. `errorset' is used by the old test.cl module (eg, +;;;; test-equal-errorset). + errorset + reported-form + (wanted-message nil wanted-message-given) + (got-message nil got-message-given)) + "Perform a single test. `expected-value' is the reference value for the +test. `test-form' is a form that will produce the value to be compared to +the expected-value. If the values are not the same, then an error is +logged, otherwise a success is logged. + +Normally the comparison of values is done with `eql'. The `test' keyword +argument can be used to specify other comparison functions, such as eq, +equal,equalp, string=, string-equal, etc. + +Normally, only the first return value from the test-form is considered, +however if `multiple-values' is t, then all values returned from test-form +are considered. + +`fail-info' allows more information to be printed with a test failure. + +`known-failure' marks the test as a known failure. This allows for +programs that do regression analysis on the output from a test run to +discriminate on new versus known failures." + `(test-check + :expected-result ,expected-value + :test-results + (,(if errorset 'test-values-errorset 'test-values) ,test-form t) + ,@(when test-given `(:predicate ,test)) + ,@(when multiple-values-given `(:multiple-values ,multiple-values)) + ,@(when fail-info-given `(:fail-info ,fail-info)) + ,@(when known-failure-given `(:known-failure ,known-failure)) + :test-form ',(if reported-form reported-form test-form) + ,@(when wanted-message-given `(:wanted-message ,wanted-message)) + ,@(when got-message-given `(:got-message ,got-message)))) + +(defmethod conditionp ((thing condition)) t) +(defmethod conditionp ((thing t)) nil) + +(defmacro test-error (form &key announce + catch-breaks + (fail-info nil fail-info-given) + (known-failure nil known-failure-given) + (condition-type ''simple-error) + (include-subtypes nil include-subtypes-given) + (format-control nil format-control-given) + (format-arguments nil format-arguments-given)) + "Test that `form' signals an error. The order of evaluation of the +arguments is keywords first, then test form. + +If `announce' is non-nil, then cause the error message to be printed. + +The `catch-breaks' is non-nil then consider a call to common-lisp:break an +`error'. + +`fail-info' allows more information to be printed with a test failure. + +`known-failure' marks the test as a known failure. This allows for +programs that do regression analysis on the output from a test run to +discriminate on new versus known failures. + +If `condition-type' is non-nil, it should be a symbol naming a condition +type, which is used to check against the signalled condition type. The +test will fail if they do not match. + +`include-subtypes', used with `condition-type', can be used to match a +condition to an entire subclass of the condition type hierarchy. + +`format-control' and `format-arguments' can be used to check the error +message itself." + (let ((g-announce (gensym)) + (g-catch-breaks (gensym)) + (g-fail-info (gensym)) + (g-known-failure (gensym)) + (g-condition-type (gensym)) + (g-include-subtypes (gensym)) + (g-format-control (gensym)) + (g-format-arguments (gensym)) + (g-c (gensym))) + `(let* ((,g-announce ,announce) + (,g-catch-breaks ,catch-breaks) + ,@(when fail-info-given `((,g-fail-info ,fail-info))) + ,@(when known-failure-given `((,g-known-failure ,known-failure))) + (,g-condition-type ,condition-type) + ,@(when include-subtypes-given + `((,g-include-subtypes ,include-subtypes))) + ,@(when format-control-given + `((,g-format-control ,format-control))) + ,@(when format-arguments-given + `((,g-format-arguments ,format-arguments))) + (,g-c (test-values-errorset ,form ,g-announce ,g-catch-breaks))) + (test-check + :predicate #'eq + :expected-result t + :test-results + (test-values (and (conditionp ,g-c) + ,@(if* include-subtypes-given + then `((if* ,g-include-subtypes + then (typep ,g-c ,g-condition-type) + else (eq (class-of ,g-c) + (find-class + ,g-condition-type)))) + else `((eq (class-of ,g-c) + (find-class ,g-condition-type)))) + ,@(when format-control-given + `((or + (null ,g-format-control) + (string= + (concatenate 'simple-string + "~1@<" ,g-format-control "~:@>") + (simple-condition-format-control ,g-c))))) + ,@(when format-arguments-given + `((or + (null ,g-format-arguments) + (equal + ,g-format-arguments + (simple-condition-format-arguments ,g-c)))))) + t) + :test-form ',form + ,@(when fail-info-given `(:fail-info ,g-fail-info)) + ,@(when known-failure-given `(:known-failure ,g-known-failure)) + :condition-type ,g-condition-type + :condition ,g-c + ,@(when include-subtypes-given + `(:include-subtypes ,g-include-subtypes)) + ,@(when format-control-given + `(:format-control ,g-format-control)) + ,@(when format-arguments-given + `(:format-arguments ,g-format-arguments)))))) + +(defmacro test-no-error (form &key announce + catch-breaks + (fail-info nil fail-info-given) + (known-failure nil known-failure-given)) + "Test that `form' does not signal an error. The order of evaluation of +the arguments is keywords first, then test form. + +If `announce' is non-nil, then cause the error message to be printed. + +The `catch-breaks' is non-nil then consider a call to common-lisp:break an +`error'. + +`fail-info' allows more information to be printed with a test failure. + +`known-failure' marks the test as a known failure. This allows for +programs that do regression analysis on the output from a test run to +discriminate on new versus known failures." + (let ((g-announce (gensym)) + (g-catch-breaks (gensym)) + (g-fail-info (gensym)) + (g-known-failure (gensym)) + (g-c (gensym))) + `(let* ((,g-announce ,announce) + (,g-catch-breaks ,catch-breaks) + ,@(when fail-info-given `((,g-fail-info ,fail-info))) + ,@(when known-failure-given `((,g-known-failure ,known-failure))) + (,g-c (test-values-errorset ,form ,g-announce ,g-catch-breaks))) + (test-check + :predicate #'eq + :expected-result t + :test-results (test-values (not (conditionp ,g-c))) + :test-form ',form + :condition ,g-c + ,@(when fail-info-given `(:fail-info ,g-fail-info)) + ,@(when known-failure-given `(:known-failure ,g-known-failure)))))) + +(defvar *warn-cookie* (cons nil nil)) + +(defmacro test-warning (form &key fail-info known-failure) + "Test that `form' signals a warning. The order of evaluation of +the arguments is keywords first, then test form. + +`fail-info' allows more information to be printed with a test failure. + +`known-failure' marks the test as a known failure. This allows for +programs that do regression analysis on the output from a test run to +discriminate on new versus known failures." + (let ((g-fail-info (gensym)) + (g-known-failure (gensym)) + (g-value (gensym))) + `(let* ((,g-fail-info ,fail-info) + (,g-known-failure ,known-failure) + (,g-value (test-values-errorset ,form nil t))) + (test + *warn-cookie* + (if* (or (typep ,g-value 'simple-warning) (typep ,g-value 'warning)) + then *warn-cookie* + else ;; test produced no warning + nil) + :test #'eq + :reported-form ,form ;; quoted by test macro + :wanted-message "a warning" + :got-message "no warning" + :fail-info ,g-fail-info + :known-failure ,g-known-failure)))) + +(defmacro test-no-warning (form &key fail-info known-failure) + "Test that `form' does not signal a warning. The order of evaluation of +the arguments is keywords first, then test form. + +`fail-info' allows more information to be printed with a test failure. + +`known-failure' marks the test as a known failure. This allows for +programs that do regression analysis on the output from a test run to +discriminate on new versus known failures." + (let ((g-fail-info (gensym)) + (g-known-failure (gensym)) + (g-value (gensym))) + `(let* ((,g-fail-info ,fail-info) + (,g-known-failure ,known-failure) + (,g-value (test-values-errorset ,form nil t))) + (test + *warn-cookie* + (if* (or (typep ,g-value 'simple-warning) (typep ,g-value 'warning)) + then nil ;; test produced warning + else *warn-cookie*) + :test #'eq + :reported-form ',form + :wanted-message "no warning" + :got-message "a warning" + :fail-info ,g-fail-info + :known-failure ,g-known-failure)))) + +(defvar *announce-test* nil) ;; if true announce each test that was done + +(defmacro errorset (form &optional announce catch-breaks) + ;; Evaluate FORM, and if there are no errors and FORM returns + ;; values v1,v2,...,vn, then return values t,v1,v2,...,vn. If an + ;; error occurs while evaluating FORM, then return nil immediately. + ;; If ANNOUNCE is t, then the error message will be printed out. + (if catch-breaks + `(handler-case (values-list (cons t (multiple-value-list ,form))) + (error (condition) + (declare (ignorable condition)) + ,@(if announce `((format *error-output* "~&Error: ~a~%" condition))) + nil) + (simple-break (condition) + (declare (ignorable condition)) + ,@(if announce `((format *error-output* "~&Warning: ~a~%" condition)) +) + nil)) + `(handler-case (values-list (cons t (multiple-value-list ,form))) + (error (condition) + (declare (ignorable condition)) + ,@(if announce `((format *error-output* "~&Error: ~a~%" condition))) + nil)))) + +(defun test-check (&key (predicate #'eql) + expected-result test-results test-form + multiple-values fail-info known-failure + wanted-message got-message condition-type condition + include-subtypes format-control format-arguments + &aux fail predicate-failed got wanted) + ;; for debugging large/complex test sets: + (when *announce-test* + (format t "Just did test ~s~%" test-form) + (force-output)) + + ;; this is an internal function + (flet ((check (expected-result result) + (let* ((results + (multiple-value-list + (errorset (funcall predicate expected-result result) t))) + (failed (null (car results)))) + (if* failed + then (setq predicate-failed t) + nil + else (cadr results))))) + (when (conditionp test-results) + (setq condition test-results) + (setq test-results nil)) + (when (null (car test-results)) + (setq fail t)) + (if* (and (not fail) (not multiple-values)) + then ;; should be a single result + ;; expected-result is the single result wanted + (when (not (and (cdr test-results) + (check expected-result (cadr test-results)))) + (setq fail t)) + (when (and (not fail) (cddr test-results)) + (setq fail 'single-got-multiple)) + else ;; multiple results wanted + ;; expected-result is a list of results, each of which + ;; should be checked against the corresponding test-results + ;; using the predicate + (do ((got (cdr test-results) (cdr got)) + (want expected-result (cdr want))) + ((or (null got) (null want)) + (when (not (and (null want) (null got))) + (setq fail t))) + (when (not (check (car got) (car want))) + (return (setq fail t))))) + (if* fail + then (when (not known-failure) + (format *error-output* + "~& * * * UNEXPECTED TEST FAILURE * * *~%") + (incf *test-unexpected-failures*)) + (format *error-output* "~&Test failed: ~@[known failure: ~*~]~s~%" + known-failure test-form) + (if* (eq 'single-got-multiple fail) + then (format + *error-output* + "~ +Reason: additional value were returned from test form.~%") + elseif predicate-failed + then (format *error-output* "Reason: predicate error.~%") + elseif (null (car test-results)) + then (format *error-output* "~ +Reason: an error~@[ (of type `~s')~] was detected.~%" + (when condition (class-of condition))) + elseif condition + then (if* (not (conditionp condition)) + then (format *error-output* "~ +Reason: expected but did not detect an error of type `~s'.~%" + condition-type) + elseif (null condition-type) + then (format *error-output* "~ +Reason: detected an unexpected error of type `~s': + ~a.~%" + (class-of condition) + condition) + elseif (not (if* include-subtypes + then (typep condition condition-type) + else (eq (class-of condition) + (find-class condition-type)))) + then (format *error-output* "~ +Reason: detected an incorrect condition type.~%") + (format *error-output* + " wanted: ~s~%" condition-type) + (format *error-output* + " got: ~s~%" (class-of condition)) + elseif (and format-control + (not (string= + (setq got + (concatenate 'simple-string + "~1@<" format-control "~:@>")) + (setq wanted + (simple-condition-format-control + condition))))) + then ;; format control doesn't match + (format *error-output* "~ +Reason: the format-control was incorrect.~%") + (format *error-output* " wanted: ~s~%" wanted) + (format *error-output* " got: ~s~%" got) + elseif (and format-arguments + (not (equal + (setq got format-arguments) + (setq wanted + (simple-condition-format-arguments + condition))))) + then (format *error-output* "~ +Reason: the format-arguments were incorrect.~%") + (format *error-output* " wanted: ~s~%" wanted) + (format *error-output* " got: ~s~%" got) + else ;; what else???? + (error "internal-error")) + else (let ((*print-length* 50) + (*print-level* 10)) + (if* wanted-message + then (format *error-output* + " wanted: ~a~%" wanted-message) + else (if* (not multiple-values) + then (format *error-output* + " wanted: ~s~%" + expected-result) + else (format + *error-output* + " wanted values: ~{~s~^, ~}~%" + expected-result))) + (if* got-message + then (format *error-output* + " got: ~a~%" got-message) + else (if* (not multiple-values) + then (format *error-output* " got: ~s~%" + (second test-results)) + else (format + *error-output* + " got values: ~{~s~^, ~}~%" + (cdr test-results)))))) + (when fail-info + (format *error-output* "Additional info: ~a~%" fail-info)) + (incf *test-errors*) + (when *break-on-test-failures* + (break "~a is non-nil." '*break-on-test-failures*)) + else (when known-failure + (format *error-output* + "~&Expected test failure for ~s did not occur.~%" + test-form) + (when fail-info + (format *error-output* "Additional info: ~a~%" fail-info)) + (setq fail t)) + (incf *test-successes*)) + (not fail))) + +(defmacro with-tests ((&key (name "unnamed")) &body body) + (let ((g-name (gensym))) + `(flet ((doit () , at body)) + (let ((,g-name ,name) + (*test-errors* 0) + (*test-successes* 0) + (*test-unexpected-failures* 0)) + (format *error-output* "Begin ~a test~%" ,g-name) + (if* *break-on-test-failures* + then (doit) + else (handler-case (doit) + (error (c) + (format + *error-output* + "~ +~&Test ~a aborted by signalling an uncaught error:~%~a~%" + ,g-name c)))) + #+allegro + (let ((state (sys:gsgc-switch :print))) + (setf (sys:gsgc-switch :print) nil) + (format t "~&**********************************~%" ,g-name) + (format t "End ~a test~%" ,g-name) + (format t "Errors detected in this test: ~s " *test-errors*) + (unless (zerop *test-unexpected-failures*) + (format t "UNEXPECTED: ~s" *test-unexpected-failures*)) + (format t "~%Successes this test:~s~%" *test-successes*) + (setf (sys:gsgc-switch :print) state)) + #-allegro + (progn + (format t "~&**********************************~%" ,g-name) + (format t "End ~a test~%" ,g-name) + (format t "Errors detected in this test: ~s " *test-errors*) + (unless (zerop *test-unexpected-failures*) + (format t "UNEXPECTED: ~s" *test-unexpected-failures*)) + (format t "~%Successes this test:~s~%" *test-successes*)) + )))) + +(provide :tester #+module-versions 1.1) Added: branches/trunk-reorg/thirdparty/uffi-1.6.0/examples/arrays.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi-1.6.0/examples/arrays.lisp Mon Feb 11 09:23:05 2008 @@ -0,0 +1,63 @@ +;;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Base: 10 -*- +;;;; ************************************************************************* +;;;; FILE IDENTIFICATION +;;;; +;;;; Name: arrays.cl +;;;; Purpose: UFFI Example file to test arrays +;;;; Programmer: Kevin M. Rosenberg +;;;; Date Started: Mar 2002 +;;;; +;;;; $Id: arrays.lisp 10608 2005-07-01 00:39:48Z kevin $ +;;;; +;;;; This file, part of UFFI, is Copyright (c) 2002-2005 by Kevin M. Rosenberg +;;;; +;;;; ************************************************************************* + +(in-package :cl-user) + +(uffi:def-constant +column-length+ 10) +(uffi:def-constant +row-length+ 10) + +(uffi:def-foreign-type long-ptr (* :long)) + +(defun test-array-1d () + "Tests vector" + (let ((a (uffi:allocate-foreign-object :long +column-length+))) + (dotimes (i +column-length+) + (setf (uffi:deref-array a '(:array :long) i) (* i i))) + (dotimes (i +column-length+) + (format t "~&~D => ~D" i (uffi:deref-array a '(:array :long) i))) + (uffi:free-foreign-object a)) + (values)) + +(defun test-array-2d () + "Tests 2d array" + (let ((a (uffi:allocate-foreign-object 'long-ptr +row-length+))) + (dotimes (r +row-length+) + (declare (fixnum r)) + (setf (uffi:deref-array a '(:array (* :long)) r) + (uffi:allocate-foreign-object :long +column-length+)) + (let ((col (uffi:deref-array a '(:array (* :long)) r))) + (dotimes (c +column-length+) + (declare (fixnum c)) + (setf (uffi:deref-array col '(:array :long) c) (+ (* r +column-length+) c))))) + + (dotimes (r +row-length+) + (declare (fixnum r)) + (format t "~&Row ~D: " r) + (let ((col (uffi:deref-array a '(:array (* :long)) r))) + (dotimes (c +column-length+) + (declare (fixnum c)) + (let ((result (uffi:deref-array col '(:array :long) c))) + (format t "~d " result))))) + + (uffi:free-foreign-object a)) + (values)) + +#+examples-uffi +(test-array-1d) + +#+examples-uffi +(test-array-2d) + + Added: branches/trunk-reorg/thirdparty/uffi-1.6.0/examples/atoifl.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi-1.6.0/examples/atoifl.lisp Mon Feb 11 09:23:05 2008 @@ -0,0 +1,56 @@ +;;;; -*- Mode: Lisp; Syntax: ANSI-Common-Lisp; Base: 10 -*- +;;;; ************************************************************************* +;;;; FILE IDENTIFICATION +;;;; +;;;; Name: atoifl.cl +;;;; Purpose: UFFI Example file to atoi/atof/atol +;;;; Programmer: Kevin M. Rosenberg +;;;; Date Started: Mar 2002 +;;;; +;;;; $Id: atoifl.lisp 10608 2005-07-01 00:39:48Z kevin $ +;;;; +;;;; This file, part of UFFI, is Copyright (c) 2002-2005 by Kevin M. Rosenberg +;;;; +;;;; ************************************************************************* + +(in-package :cl-user) + +(uffi:def-function ("atoi" c-atoi) + ((str :cstring)) + :returning :int) + +(uffi:def-function ("atol" c-atol) + ((str :cstring)) + :returning :long) + +(uffi:def-function ("atof" c-atof) + ((str :cstring)) + :returning :double) + +(defun atoi (str) + "Returns a int from a string." + (uffi:with-cstring (str-cstring str) + (c-atoi str-cstring))) + +(defun atof (str) + "Returns a double float from a string." + (uffi:with-cstring (str-cstring str) + (c-atof str-cstring))) + +#+examples-uffi +(progn + (flet ((print-results (str) + (format t "~&(atoi ~S) => ~S" str (atoi str)))) + (print-results "55"))) + + +#+test-uffi +(progn + (util.test:test (atoi "123") 123 :test #'eql + :fail-info "Error with atoi") + (util.test:test (atoi "") 0 :test #'eql + :fail-info "Error with atoi") + (util.test:test (atof "2.23") 2.23d0 :test #'eql + :fail-info "Error with atof") + ) + Added: branches/trunk-reorg/thirdparty/uffi-1.6.0/examples/c-test-fns.c ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi-1.6.0/examples/c-test-fns.c Mon Feb 11 09:23:05 2008 @@ -0,0 +1,91 @@ +/*************************************************************************** + * FILE IDENTIFICATION + * + * Name: c-test-fns.c + * Purpose: Test functions in C for UFFI library + * Programer: Kevin M. Rosenberg + * Date Started: Mar 2002 + * + * CVS Id: $Id: c-test-fns.c 10614 2005-07-06 01:05:14Z kevin $ + * + * This file, part of UFFI, is Copyright (c) 2002-2005 by Kevin M. Rosenberg + * + * These variables are correct for GCC + * you'll need to modify these for other compilers + ***************************************************************************/ + +#ifdef WIN32 +#include + +BOOL WINAPI DllEntryPoint(HINSTANCE hinstdll, + DWORD fdwReason, + LPVOID lpvReserved) +{ + return 1; +} + +#define DLLEXPORT __declspec(dllexport) + +#else +#define DLLEXPORT +#endif + +#include +#include +#include + + +/* Test of constant input string */ +DLLEXPORT +int +cs_count_upper (char* psz) +{ + int count = 0; + + if (psz) { + while (*psz) { + if (isupper (*psz)) + ++count; + ++psz; + } + return count; + } else + return -1; +} + +/* Test of input and output of a string */ +DLLEXPORT +void +cs_to_upper (char* psz) +{ + if (psz) { + while (*psz) { + *psz = toupper (*psz); + ++psz; + } + } +} + +/* Test of an output only string */ +DLLEXPORT +void +cs_make_random (int size, char* buffer) +{ + int i; + for (i = 0; i < size; i++) + buffer[i] = 'A' + (rand() % 26); +} + + +/* Test of input/output vector */ +DLLEXPORT +void +half_double_vector (int size, double* vec) +{ + int i; + for (i = 0; i < size; i++) + vec[i] /= 2.; +} + + + Added: branches/trunk-reorg/thirdparty/uffi-1.6.0/examples/c-test-fns.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi-1.6.0/examples/c-test-fns.lisp Mon Feb 11 09:23:05 2008 @@ -0,0 +1,118 @@ +;;;; -*- Mode: Lisp; Syntax: ANSI-Common-Lisp; Base: 10 -*- +;;;; ************************************************************************* +;;;; FILE IDENTIFICATION +;;;; +;;;; Name: c-test-fns.cl +;;;; Purpose: UFFI Example file for zlib compression +;;;; Programmer: Kevin M. Rosenberg +;;;; Date Started: Mar 2002 +;;;; +;;;; $Id: c-test-fns.lisp 10608 2005-07-01 00:39:48Z kevin $ +;;;; +;;;; This file, part of UFFI, is Copyright (c) 2002-2005 by Kevin M. Rosenberg +;;;; +;;;; ************************************************************************* + +(in-package :cl-user) + +(unless (uffi:load-foreign-library + (uffi:find-foreign-library "c-test-fns" + (list *load-truename* "/home/kevin/debian/src/uffi/examples/")) + :supporting-libraries '("c")) + (warn "Unable to load c-test-fns library")) + +(uffi:def-function ("cs_to_upper" cs-to-upper) + ((input (* :unsigned-char))) + :returning :void + ) + +(defun string-to-upper (str) + (uffi:with-foreign-string (str-foreign str) + (cs-to-upper str-foreign) + (uffi:convert-from-foreign-string str-foreign))) + +(uffi:def-function ("cs_count_upper" cs-count-upper) + ((input :cstring)) + :returning :int + ) + +(defun string-count-upper (str) + (uffi:with-cstring (str-cstring str) + (cs-count-upper str-cstring))) + +(uffi:def-function ("half_double_vector" half-double-vector) + ((size :int) + (vec (* :double))) + :returning :void) + +(uffi:def-constant +double-vec-length+ 10) +(defun test-half-double-vector () + (let ((vec (uffi:allocate-foreign-object :double +double-vec-length+)) + results) + (dotimes (i +double-vec-length+) + (setf (uffi:deref-array vec '(:array :double) i) + (coerce i 'double-float))) + (half-double-vector +double-vec-length+ vec) + (dotimes (i +double-vec-length+) + (push (uffi:deref-array vec '(:array :double) i) results)) + (uffi:free-foreign-object vec) + (nreverse results))) + +(defun t2 () + (let ((vec (make-array +double-vec-length+ :element-type 'double-float))) + (dotimes (i +double-vec-length+) + (setf (aref vec i) (coerce i 'double-float))) + (half-double-vector +double-vec-length+ vec) + vec)) + +#+(or cmu scl) +(defun t3 () + (let ((vec (make-array +double-vec-length+ :element-type 'double-float))) + (dotimes (i +double-vec-length+) + (setf (aref vec i) (coerce i 'double-float))) + (system:without-gcing + (half-double-vector +double-vec-length+ (system:vector-sap vec))) + vec)) + +#+examples-uffi +(format t "~&(string-to-upper \"this is a test\") => ~A" + (string-to-upper "this is a test")) + +#+examples-uffi +(format t "~&(string-to-upper nil) => ~A" + (string-to-upper nil)) + +#+examples-uffi +(format t "~&(string-count-upper \"This is a Test\") => ~A" + (string-count-upper "This is a Test")) + +#+examples-uffi +(format t "~&(string-count-upper nil) => ~A" + (string-count-upper nil)) + +#+examples-uffi +(format t "~&Half vector: ~S" (test-half-double-vector)) + + + +#+test-uffi +(progn + (util.test:test (string= (string-to-upper "this is a test") "THIS IS A TEST") + t + :test #'eql + :fail-info "Error with string-to-upper") + (util.test:test (string-to-upper nil) nil + :fail-info "string-to-upper with nil failed") + (util.test:test (string-count-upper "This is a Test") + 2 + :test #'eql + :fail-info "Error with string-count-upper") + (util.test:test (string-count-upper nil) -1 + :test #'eql + :fail-info "string-count-upper with nil failed") + + (util.test:test (test-half-double-vector) + '(0.0d0 0.5d0 1.0d0 1.5d0 2.0d0 2.5d0 3.0d0 3.5d0 4.0d0 4.5d0) + :test #'equal + :fail-info "Error comparing half-double-vector") + ) Added: branches/trunk-reorg/thirdparty/uffi-1.6.0/examples/compress.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi-1.6.0/examples/compress.lisp Mon Feb 11 09:23:05 2008 @@ -0,0 +1,116 @@ +;;;; -*- Mode: Lisp; Syntax: ANSI-Common-Lisp; Base: 10 -*- +;;;; ************************************************************************* +;;;; FILE IDENTIFICATION +;;;; +;;;; Name: compress.cl +;;;; Purpose: UFFI Example file for zlib compression +;;;; Programmer: Kevin M. Rosenberg +;;;; Date Started: Feb 2002 +;;;; +;;;; $Id: compress.lisp 10608 2005-07-01 00:39:48Z kevin $ +;;;; +;;;; This file, part of UFFI, is Copyright (c) 2002-2005 by Kevin M. Rosenberg +;;;; +;;;; ************************************************************************* + +(in-package :cl-user) + +(eval-when (:load-toplevel :execute) + (unless (uffi:load-foreign-library + #-(or macosx darwin) + (uffi:find-foreign-library + "libz" + '("/usr/local/lib/" "/usr/lib/" "/zlib/") + :types '("so" "a")) + #+(or macosx darwin) + (uffi:find-foreign-library "z" + `(,(pathname-directory *load-pathname*))) + :module "zlib" + :supporting-libraries '("c")) + (warn "Unable to load zlib"))) + +(uffi:def-function ("compress" c-compress) + ((dest (* :unsigned-char)) + (destlen (* :long)) + (source :cstring) + (source-len :long)) + :returning :int + :module "zlib") + +(defun compress (source) + "Returns two values: array of bytes containing the compressed data + and the numbe of compressed bytes" + (let* ((sourcelen (length source)) + (destsize (+ 12 (ceiling (* sourcelen 1.01)))) + (dest (uffi:allocate-foreign-string destsize :unsigned t)) + (destlen (uffi:allocate-foreign-object :long))) + (setf (uffi:deref-pointer destlen :long) destsize) + (uffi:with-cstring (source-native source) + (let ((result (c-compress dest destlen source-native sourcelen)) + (newdestlen (uffi:deref-pointer destlen :long))) + (unwind-protect + (if (zerop result) + (values (uffi:convert-from-foreign-string + dest + :length newdestlen + :null-terminated-p nil) + newdestlen) + (error "zlib error, code ~D" result)) + (progn + (uffi:free-foreign-object destlen) + (uffi:free-foreign-object dest))))))) + +(uffi:def-function ("uncompress" c-uncompress) + ((dest (* :unsigned-char)) + (destlen (* :long)) + (source :cstring) + (source-len :long)) + :returning :int + :module "zlib") + +(defun uncompress (source) + (let* ((sourcelen (length source)) + (destsize 200000) ;adjust as needed + (dest (uffi:allocate-foreign-string destsize :unsigned t)) + (destlen (uffi:allocate-foreign-object :long))) + (setf (uffi:deref-pointer destlen :long) destsize) + (uffi:with-cstring (source-native source) + (let ((result (c-uncompress dest destlen source-native sourcelen)) + (newdestlen (uffi:deref-pointer destlen :long))) + (unwind-protect + (if (zerop result) + (uffi:convert-from-foreign-string + dest + :length newdestlen + :null-terminated-p nil) + (error "zlib error, code ~D" result)) + (progn + (uffi:free-foreign-object destlen) + (uffi:free-foreign-object dest))))))) + +#+examples-uffi +(progn + (flet ((print-results (str) + (multiple-value-bind (compressed len) (compress str) + (let ((*print-length* nil)) + (format t "~&(compress ~S) => " str) + (format t "~S~%" (map 'list #'char-code compressed)))))) + (print-results "") + (print-results "test") + (print-results "test2"))) + +#+test-uffi +(progn + (flet ((test-compress (str) + (multiple-value-bind (compressed len) (compress str) + (multiple-value-bind (uncompressed len2) (uncompress compressed) + (util.test:test str uncompressed :test #'string= + :fail-info "Error uncompressing a compressed string"))))) + (test-compress "") + (test-compress "test") + (test-compress "test2"))) + +;; Results of the above on my system: +;; (compress "") => 789c300001,8 +;; (compress "test") => 789c2b492d2e1045d1c1,12 +;; (compress "test2") => 789c2b492d2e31206501f3,13 Added: branches/trunk-reorg/thirdparty/uffi-1.6.0/examples/file-socket.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi-1.6.0/examples/file-socket.lisp Mon Feb 11 09:23:05 2008 @@ -0,0 +1,39 @@ +;;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Base: 10 -*- +;;;; ************************************************************************* +;;;; FILE IDENTIFICATION +;;;; +;;;; Name: file-socket.cl +;;;; Purpose: UFFI Example file to get a socket on a file +;;;; Programmer: Kevin M. Rosenberg +;;;; Date Started: Jul 2002 +;;;; +;;;; $Id: file-socket.lisp 10608 2005-07-01 00:39:48Z kevin $ +;;;; +;;;; This file, part of UFFI, is Copyright (c) 2002-2005 by Kevin M. Rosenberg +;;;; +;;;; ************************************************************************* + +(in-package :cl-user) + +;; Values for linux +(uffi:def-constant PF_UNIX 1) +(uffi:def-constant SOCK_STREAM 1) + +(uffi:def-function ("socket" c-socket) + ((family :int) + (type :int) + (protocol :int)) + :returning :int) + +(uffi:def-function ("connect" c-connect) + ((sockfd :int) + (serv-addr :void-pointer) + (addr-len :int)) + :returning :int) + +(defun connect-to-file-socket (filename) + (let ((socket (c-socket PF_UNIX SOCK_STREAM 0))) + (if (plusp socket) + (let ((stream (c-connect socket filename (length filename)))) + stream) + (error "Unable to create socket")))) Added: branches/trunk-reorg/thirdparty/uffi-1.6.0/examples/getenv.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi-1.6.0/examples/getenv.lisp Mon Feb 11 09:23:05 2008 @@ -0,0 +1,44 @@ +;;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Base: 10 -*- +;;;; ************************************************************************* +;;;; FILE IDENTIFICATION +;;;; +;;;; Name: getenv.cl +;;;; Purpose: UFFI Example file to get environment variable +;;;; Programmer: Kevin M. Rosenberg +;;;; Date Started: Feb 2002 +;;;; +;;;; $Id: getenv.lisp 10608 2005-07-01 00:39:48Z kevin $ +;;;; +;;;; This file, part of UFFI, is Copyright (c) 2002-2005 by Kevin M. Rosenberg +;;;; +;;;; ************************************************************************* + +(in-package :cl-user) + + +(uffi:def-function ("getenv" c-getenv) + ((name :cstring)) + :returning :cstring) + +(defun my-getenv (key) + "Returns an environment variable, or NIL if it does not exist" + (check-type key string) + (uffi:with-cstring (key-native key) + (uffi:convert-from-cstring (c-getenv key-native)))) + +#+examples-uffi +(progn + (flet ((print-results (str) + (format t "~&(getenv ~S) => ~S" str (my-getenv str)))) + (print-results "USER") + (print-results "_FOO_"))) + + +#+test-uffi +(progn + (util.test:test (my-getenv "_FOO_") nil :fail-info "Error retrieving non-existent getenv") + (util.test:test (and (stringp (my-getenv "USER")) + (< 0 (length (my-getenv "USER")))) + t :fail-info "Error retrieving getenv") +) + Added: branches/trunk-reorg/thirdparty/uffi-1.6.0/examples/gethostname.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi-1.6.0/examples/gethostname.lisp Mon Feb 11 09:23:05 2008 @@ -0,0 +1,63 @@ +;;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Base: 10 -*- +;;;; ************************************************************************* +;;;; FILE IDENTIFICATION +;;;; +;;;; Name: gethostname.cl +;;;; Purpose: UFFI Example file to get hostname of system +;;;; Programmer: Kevin M. Rosenberg +;;;; Date Started: Feb 2002 +;;;; +;;;; $Id: gethostname.lisp 10608 2005-07-01 00:39:48Z kevin $ +;;;; +;;;; This file, part of UFFI, is Copyright (c) 2002-2005 by Kevin M. Rosenberg +;;;; +;;;; ************************************************************************* + +(in-package :cl-user) + + +;;; This example is inspired by the example on the CL-Cookbook web site + +(uffi:def-function ("gethostname" c-gethostname) + ((name (* :unsigned-char)) + (len :int)) + :returning :int) + +(defun gethostname () + "Returns the hostname" + (let* ((name (uffi:allocate-foreign-string 256)) + (result-code (c-gethostname name 256)) + (hostname (when (zerop result-code) + (uffi:convert-from-foreign-string name)))) + (uffi:free-foreign-object name) + (unless (zerop result-code) + (error "gethostname() failed.")) + hostname)) + +(defun gethostname2 () + "Returns the hostname" + (uffi:with-foreign-object (name '(:array :unsigned-char 256)) + (if (zerop (c-gethostname (uffi:char-array-to-pointer name) 256)) + (uffi:convert-from-foreign-string name) + (error "gethostname() failed.")))) + +#+examples-uffi +(progn + (format t "~&Hostname (technique 1): ~A" (gethostname)) + (format t "~&Hostname (technique 2): ~A" (gethostname2))) + +#+test-uffi +(progn + (let ((hostname1 (gethostname)) + (hostname2 (gethostname2))) + + (util.test:test (and (stringp hostname1) (stringp hostname2)) t + :fail-info "gethostname not string") + (util.test:test (and (not (zerop (length hostname1))) + (not (zerop (length hostname2)))) t + :fail-info "gethostname length 0") + (util.test:test (string= hostname1 hostname1) t + :fail-info "gethostname techniques don't match")) + ) + + Added: branches/trunk-reorg/thirdparty/uffi-1.6.0/examples/getshells.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi-1.6.0/examples/getshells.lisp Mon Feb 11 09:23:05 2008 @@ -0,0 +1,44 @@ +;;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Base: 10 -*- +;;;; ************************************************************************* +;;;; FILE IDENTIFICATION +;;;; +;;;; Name: getshells.cl +;;;; Purpose: UFFI Example file to get lisp of legal shells +;;;; Programmer: Kevin M. Rosenberg +;;;; Date Started: Mar 2002 +;;;; +;;;; $Id: getshells.lisp 10608 2005-07-01 00:39:48Z kevin $ +;;;; +;;;; This file, part of UFFI, is Copyright (c) 2002-2005 by Kevin M. Rosenberg +;;;; +;;;; ************************************************************************* + +(in-package :cl-user) + + +(uffi:def-function "setusershell" + nil + :returning :void) + +(uffi:def-function "endusershell" + nil + :returning :void) + +(uffi:def-function "getusershell" + nil + :returning :cstring) + +(defun getshells () + "Returns list of valid shells" + (setusershell) + (let (shells) + (do ((shell (uffi:convert-from-cstring (getusershell)) + (uffi:convert-from-cstring (getusershell)))) + ((null shell)) + (push shell shells)) + (endusershell) + (nreverse shells))) + +#+examples-uffi +(format t "~&Shells: ~S" (getshells)) + Added: branches/trunk-reorg/thirdparty/uffi-1.6.0/examples/gettime.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi-1.6.0/examples/gettime.lisp Mon Feb 11 09:23:05 2008 @@ -0,0 +1,73 @@ +;;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Base: 10 -*- +;;;; ************************************************************************* +;;;; FILE IDENTIFICATION +;;;; +;;;; Name: gettime +;;;; Purpose: UFFI Example file to get time, use C structures +;;;; Programmer: Kevin M. Rosenberg +;;;; Date Started: Feb 2002 +;;;; +;;;; $Id: gettime.lisp 10608 2005-07-01 00:39:48Z kevin $ +;;;; +;;;; This file, part of UFFI, is Copyright (c) 2002-2005 by Kevin M. Rosenberg +;;;; +;;;; ************************************************************************* + +(in-package :cl-user) + +(uffi:def-foreign-type time-t :unsigned-long) + +(uffi:def-struct tm + (sec :int) + (min :int) + (hour :int) + (mday :int) + (mon :int) + (year :int) + (wday :int) + (yday :int) + (isdst :int)) + +(uffi:def-function ("time" c-time) + ((time (* time-t))) + :returning time-t) + +(uffi:def-function ("localtime" c-localtime) + ((time (* time-t))) + :returning (* tm)) + +(uffi:def-type time-t :unsigned-long) +(uffi:def-type tm-pointer (* tm)) + +(defun gettime () + "Returns the local time" + (uffi:with-foreign-object (time 'time-t) +;; (declare (type time-t time)) + (c-time time) + (let ((tm-ptr (the tm-pointer (c-localtime time)))) + (declare (type tm-pointer tm-ptr)) + (let ((time-string (format nil "~2d/~2,'0d/~d ~2d:~2,'0d:~2,'0d" + (1+ (uffi:get-slot-value tm-ptr 'tm 'mon)) + (uffi:get-slot-value tm-ptr 'tm 'mday) + (+ 1900 (uffi:get-slot-value tm-ptr 'tm 'year)) + (uffi:get-slot-value tm-ptr 'tm 'hour) + (uffi:get-slot-value tm-ptr 'tm 'min) + (uffi:get-slot-value tm-ptr 'tm 'sec) + ))) + time-string)))) + + + + +#+examples-uffi +(format t "~&~A" (gettime)) + +#+test-uffi +(progn + (let ((time (gettime))) + (util.test:test (stringp time) t :fail-info "Time is not a string") + (util.test:test (plusp (parse-integer time :junk-allowed t)) + t + :fail-info "time string does not start with a number"))) + + Added: branches/trunk-reorg/thirdparty/uffi-1.6.0/examples/run-examples.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi-1.6.0/examples/run-examples.lisp Mon Feb 11 09:23:05 2008 @@ -0,0 +1,36 @@ +;;;; -*- Mode: Lisp; Syntax: ANSI-Common-Lisp; Base: 10 -*- +;;;; ************************************************************************* +;;;; FILE IDENTIFICATION +;;;; +;;;; Name: run-examples.cl +;;;; Purpose: Load and execute all examples for UFFI +;;;; Programmer: Kevin M. Rosenberg +;;;; Date Started: Feb 2002 +;;;; +;;;; $Id: run-examples.lisp 10608 2005-07-01 00:39:48Z kevin $ +;;;; +;;;; This file, part of UFFI, is Copyright (c) 2002-2005 by Kevin M. Rosenberg +;;;; +;;;; ************************************************************************* + +#-uffi (asdf:oos 'asdf:load-op :uffi) + +(pushnew :examples-uffi cl:*features*) + +(flet ((load-test (name) + (load (make-pathname :defaults *load-truename* :name name)))) + (load-test "c-test-fns") + (load-test "arrays") + (load-test "union") + (load-test "strtol") + (load-test "atoifl") + (load-test "gettime") + (load-test "getenv") + (load-test "gethostname") + (load-test "getshells") + (load-test "compress")) + +(setq cl:*features* (remove :examples-uffi cl:*features*)) + + + Added: branches/trunk-reorg/thirdparty/uffi-1.6.0/examples/strtol.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi-1.6.0/examples/strtol.lisp Mon Feb 11 09:23:05 2008 @@ -0,0 +1,80 @@ +;;;; -*- Mode: Lisp; Syntax: ANSI-Common-Lisp; Base: 10 -*- +;;;; ************************************************************************* +;;;; FILE IDENTIFICATION +;;;; +;;;; Name: strtol.cl +;;;; Purpose: UFFI Example file to strtol, uses pointer arithmetic +;;;; Programmer: Kevin M. Rosenberg +;;;; Date Started: Feb 2002 +;;;; +;;;; $Id: strtol.lisp 10608 2005-07-01 00:39:48Z kevin $ +;;;; +;;;; This file, part of UFFI, is Copyright (c) 2002-2005 by Kevin M. Rosenberg +;;;; +;;;; ************************************************************************* + +(in-package :cl-user) + +(uffi:def-foreign-type char-ptr (* :unsigned-char)) + +;; This example does not use :cstring to pass the input string since +;; the routine needs to do pointer arithmetic to see how many characters +;; were parsed + +(uffi:def-function ("strtol" c-strtol) + ((nptr char-ptr) + (endptr (* char-ptr)) + (base :int)) + :returning :long) + +(defun strtol (str &optional (base 10)) + "Returns a long int from a string. Returns number and condition flag. +Condition flag is T if all of string parses as a long, NIL if +their was no string at all, or an integer indicating position in string +of first non-valid character" + (let* ((str-native (uffi:convert-to-foreign-string str)) + (endptr (uffi:allocate-foreign-object 'char-ptr)) + (value (c-strtol str-native endptr base)) + (endptr-value (uffi:deref-pointer endptr 'char-ptr))) + + (unwind-protect + (if (uffi:null-pointer-p endptr-value) + (values value t) + (let ((next-char-value (uffi:deref-pointer endptr-value :unsigned-char)) + (chars-parsed (- (uffi:pointer-address endptr-value) + (uffi:pointer-address str-native)))) + (cond + ((zerop chars-parsed) + (values nil nil)) + ((uffi:null-char-p next-char-value) + (values value t)) + (t + (values value chars-parsed))))) + (progn + (uffi:free-foreign-object str-native) + (uffi:free-foreign-object endptr))))) + + + +#+examples-uffi +(progn + (flet ((print-results (str) + (multiple-value-bind (result flag) (strtol str) + (format t "~&(strtol ~S) => ~S,~S" str result flag)))) + (print-results "55") + (print-results "55.3") + (print-results "a"))) + +#+test-uffi +(progn + (flet ((test-strtol (str results) + (util.test:test (multiple-value-list (strtol str)) results + :test #'equal + :fail-info "Error testing strtol"))) + (test-strtol "123" '(123 t)) + (test-strtol "0" '(0 t)) + (test-strtol "55a" '(55 2)) + (test-strtol "a" '(nil nil)))) + + + Added: branches/trunk-reorg/thirdparty/uffi-1.6.0/examples/test-examples.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi-1.6.0/examples/test-examples.lisp Mon Feb 11 09:23:05 2008 @@ -0,0 +1,40 @@ +;;;; -*- Mode: Lisp; Syntax: ANSI-Common-Lisp; Base: 10 -*- +;;;; ************************************************************************* +;;;; FILE IDENTIFICATION +;;;; +;;;; Name: test-examples.cl +;;;; Purpose: Load and execute all examples for UFFI +;;;; Programmer: Kevin M. Rosenberg +;;;; Date Started: Feb 2002 +;;;; +;;;; $Id: test-examples.lisp 10608 2005-07-01 00:39:48Z kevin $ +;;;; +;;;; This file, part of UFFI, is Copyright (c) 2002-2005 by Kevin M. Rosenberg +;;;; +;;;; ************************************************************************* + +#-uffi (asdf:oos 'asdf:load-op :uffi) + +(unless (ignore-errors (find-package :util.test)) + (load (make-pathname :name "acl-compat-tester" :defaults *load-truename*))) + +(defun do-tests () + (pushnew :test-uffi cl:*features*) + (util.test:with-tests (:name "UFFI-Tests") + (setq util.test:*break-on-test-failures* nil) + (flet ((load-test (name) + (load (make-pathname :name name :defaults *load-truename*)))) + (load-test "c-test-fns") + (load-test "arrays") + (load-test "union") + (load-test "strtol") + (load-test "atoifl") + (load-test "gettime") + (load-test "getenv") + (load-test "gethostname") + (load-test "getshells") + (load-test "compress")) + (setq cl:*features* (remove :test-uffi cl:*features*)))) + +(do-tests) + Added: branches/trunk-reorg/thirdparty/uffi-1.6.0/examples/union.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi-1.6.0/examples/union.lisp Mon Feb 11 09:23:05 2008 @@ -0,0 +1,86 @@ +;;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Base: 10 -*- +;;;; ************************************************************************* +;;;; FILE IDENTIFICATION +;;;; +;;;; Name: union.cl +;;;; Purpose: UFFI Example file to test unions +;;;; Programmer: Kevin M. Rosenberg +;;;; Date Started: Mar 2002 +;;;; +;;;; $Id: union.lisp 10917 2006-04-18 00:07:09Z kevin $ +;;;; +;;;; This file, part of UFFI, is Copyright (c) 2002-2005 by Kevin M. Rosenberg +;;;; +;;;; ************************************************************************* + +(in-package :cl-user) + +(uffi:def-union tunion1 + (char :char) + (int :int) + (uint :unsigned-int) + (sf :float) + (df :double)) + +(defun run-union-1 () + (let ((u (uffi:allocate-foreign-object 'tunion1))) + (setf (uffi:get-slot-value u 'tunion1 'uint) + ;; little endian + #-(or sparc sparc-v9 powerpc ppc big-endian) + (+ (* 1 (char-code #\A)) + (* 256 (char-code #\B)) + (* 65536 (char-code #\C)) + (* 16777216 255)) + ;; big endian + #+(or sparc sparc-v9 powerpc ppc big-endian) + (+ (* 16777216 (char-code #\A)) + (* 65536 (char-code #\B)) + (* 256 (char-code #\C)) + (* 1 255))) + (format *standard-output* "~&Should be #\A: ~S" + (uffi:ensure-char-character + (uffi:get-slot-value u 'tunion1 'char))) +;; (format *standard-output* "~&Should be negative number: ~D" +;; (uffi:get-slot-value u 'tunion1 'int)) + (format *standard-output* "~&Should be positive number: ~D" + (uffi:get-slot-value u 'tunion1 'uint)) + (uffi:free-foreign-object u)) + (values)) + +#+test-uffi +(defun test-union-1 () + (let ((u (uffi:allocate-foreign-object 'tunion1))) + (setf (uffi:get-slot-value u 'tunion1 'uint) + #-(or sparc sparc-v9 powerpc ppc) + (+ (* 1 (char-code #\A)) + (* 256 (char-code #\B)) + (* 65536 (char-code #\C)) + (* 16777216 128)) + #+(or sparc sparc-v9 powerpc ppc) + (+ (* 16777216 (char-code #\A)) + (* 65536 (char-code #\B)) + (* 256 (char-code #\C)) + (* 1 128))) ;set signed bit + (util.test:test (uffi:ensure-char-character + (uffi:get-slot-value u 'tunion1 'char)) + #\A + :test #'eql + :fail-info "Error with union character") + #-(or sparc sparc-v9 openmcl digitool) +;; (util.test:test (> 0 (uffi:get-slot-value u 'tunion1 'int)) +;; t +;; :fail-info +;; "Error with negative int in union") + (util.test:test (plusp (uffi:get-slot-value u 'tunion1 'uint)) + t + :fail-info + "Error with unsigned int in union") + (uffi:free-foreign-object u)) + (values)) + +#+examples-uffi +(run-union-1) + + +#+test-uffi +(test-union-1) Added: branches/trunk-reorg/thirdparty/uffi-1.6.0/src/Makefile ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi-1.6.0/src/Makefile Mon Feb 11 09:23:05 2008 @@ -0,0 +1,6 @@ +SUBDIRS := + +include ../Makefile.common + +.PHONY: distclean +distclean: clean Added: branches/trunk-reorg/thirdparty/uffi-1.6.0/src/aggregates.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi-1.6.0/src/aggregates.lisp Mon Feb 11 09:23:05 2008 @@ -0,0 +1,262 @@ +;;;; -*- Mode: Lisp; Syntax: ANSI-Common-Lisp; Base: 10; Package: UFFI -*- +;;;; ************************************************************************* +;;;; FILE IDENTIFICATION +;;;; +;;;; Name: aggregates.lisp +;;;; Purpose: UFFI source to handle aggregate types +;;;; Programmer: Kevin M. Rosenberg +;;;; Date Started: Feb 2002 +;;;; +;;;; $Id: aggregates.lisp 10917 2006-04-18 00:07:09Z kevin $ +;;;; +;;;; This file, part of UFFI, is Copyright (c) 2005 by Kevin M. Rosenberg +;;;; +;;;; ************************************************************************* + +(in-package #:uffi) + +(defmacro def-enum (enum-name args &key (separator-string "#")) + "Creates a constants for a C type enum list, symbols are created +in the created in the current package. The symbol is the concatenation +of the enum-name name, separator-string, and field-name" + (let ((counter 0) + (cmds nil) + (constants nil)) + (declare (fixnum counter)) + (dolist (arg args) + (let ((name (if (listp arg) (car arg) arg)) + (value (if (listp arg) + (prog1 + (setq counter (cadr arg)) + (incf counter)) + (prog1 + counter + (incf counter))))) + (setq name (intern (concatenate 'string + (symbol-name enum-name) + separator-string + (symbol-name name)))) + (push `(uffi:def-constant ,name ,value) constants))) + (setf cmds (append '(progn) + #+allegro `((ff:def-foreign-type ,enum-name :int)) + #+lispworks `((fli:define-c-typedef ,enum-name :int)) + #+(or cmu scl) `((alien:def-alien-type ,enum-name alien:signed)) + #+sbcl `((sb-alien:define-alien-type ,enum-name sb-alien:signed)) + #+digitool `((def-mcl-type ,enum-name :integer)) + #+openmcl `((ccl::def-foreign-type ,enum-name :int)) + (nreverse constants))) + cmds)) + + +(defmacro def-array-pointer (name-array type) + #+allegro + `(ff:def-foreign-type ,name-array + (:array ,(convert-from-uffi-type type :array))) + #+lispworks + `(fli:define-c-typedef ,name-array + (:c-array ,(convert-from-uffi-type type :array))) + #+(or cmu scl) + `(alien:def-alien-type ,name-array + (* ,(convert-from-uffi-type type :array))) + #+sbcl + `(sb-alien:define-alien-type ,name-array + (* ,(convert-from-uffi-type type :array))) + #+digitool + `(def-mcl-type ,name-array '(:array ,type)) + #+openmcl + `(ccl::def-foreign-type ,name-array (:array ,(convert-from-uffi-type type :array))) + ) + +(defun process-struct-fields (name fields &optional (variant nil)) + (let (processed) + (dolist (field fields) + (let* ((field-name (car field)) + (type (cadr field)) + (def (append (list field-name) + (if (eq type :pointer-self) + #+(or cmu scl) `((* (alien:struct ,name))) + #+sbcl `((* (sb-alien:struct ,name))) + #+(or openmcl digitool) `((:* (:struct ,name))) + #+lispworks `((:pointer ,name)) + #-(or cmu sbcl scl openmcl digitool lispworks) `((* ,name)) + `(,(convert-from-uffi-type type :struct)))))) + (if variant + (push (list def) processed) + (push def processed)))) + (nreverse processed))) + + +(defmacro def-struct (name &rest fields) + #+(or cmu scl) + `(alien:def-alien-type ,name (alien:struct ,name ,@(process-struct-fields name fields))) + #+sbcl + `(sb-alien:define-alien-type ,name (sb-alien:struct ,name ,@(process-struct-fields name fields))) + #+allegro + `(ff:def-foreign-type ,name (:struct ,@(process-struct-fields name fields))) + #+lispworks + `(fli:define-c-struct ,name ,@(process-struct-fields name fields)) + #+digitool + `(ccl:defrecord ,name ,@(process-struct-fields name fields)) + #+openmcl + `(ccl::def-foreign-type + nil + (:struct ,name ,@(process-struct-fields name fields))) + ) + + +(defmacro get-slot-value (obj type slot) + #+(or lispworks cmu sbcl scl) (declare (ignore type)) + #+allegro + `(ff:fslot-value-typed ,type :c ,obj ,slot) + #+lispworks + `(fli:foreign-slot-value ,obj ,slot) + #+(or cmu scl) + `(alien:slot ,obj ,slot) + #+sbcl + `(sb-alien:slot ,obj ,slot) + #+(or openmcl digitool) + `(ccl:pref ,obj ,(read-from-string (format nil ":~a.~a" (keyword type) (keyword slot)))) + ) + +#+(or openmcl digitool) +(defmacro set-slot-value (obj type slot value) ;use setf to set values + `(setf (ccl:pref ,obj ,(read-from-string (format nil ":~a.~a" (keyword type) (keyword slot)))) ,value)) + +#+(or openmcl digitool) +(defsetf get-slot-value set-slot-value) + + +(defmacro get-slot-pointer (obj type slot) + #+(or lispworks cmu sbcl scl) (declare (ignore type)) + #+allegro + `(ff:fslot-value-typed ,type :c ,obj ,slot) + #+lispworks + `(fli:foreign-slot-pointer ,obj ,slot) + #+(or cmu scl) + `(alien:slot ,obj ,slot) + #+sbcl + `(sb-alien:slot ,obj ,slot) + #+digitool + `(ccl:%int-to-ptr (+ (ccl:%ptr-to-int ,obj) (the fixnum (ccl:field-info ,type ,slot)))) + #+openmcl + `(let ((field (ccl::%find-foreign-record-type-field ,type ,slot))) + (ccl:%int-to-ptr (+ (ccl:%ptr-to-int ,obj) (the fixnum (ccl::foreign-record-field-offset field))))) +) + +;; necessary to eval at compile time for openmcl to compile convert-from-foreign-usb8 +;; below +(eval-when (:compile-toplevel :load-toplevel :execute) + ;; so we could allow '(:array :long) or deref with other type like :long only + #+(or openmcl digitool) + (defun array-type (type) + (let ((result type)) + (when (listp type) + (let ((type-list (if (eq (car type) 'quote) (nth 1 type) type))) + (when (and (listp type-list) (eq (car type-list) :array)) + (setf result (cadr type-list))))) + result)) + + + (defmacro deref-array (obj type i) + "Returns a field from a row" + #+(or lispworks cmu sbcl scl) (declare (ignore type)) + #+(or cmu scl) `(alien:deref ,obj ,i) + #+sbcl `(sb-alien:deref ,obj ,i) + #+lispworks `(fli:dereference ,obj :index ,i :copy-foreign-object nil) + #+allegro `(ff:fslot-value-typed (quote ,(convert-from-uffi-type type :type)) :c ,obj ,i) + #+openmcl + (let* ((array-type (array-type type)) + (local-type (convert-from-uffi-type array-type :allocation)) + (element-size-in-bits (ccl::%foreign-type-or-record-size local-type :bits))) + (ccl::%foreign-access-form + obj + (ccl::%foreign-type-or-record local-type) + `(* ,i ,element-size-in-bits) + nil)) + #+digitool + (let* ((array-type (array-type type)) + (local-type (convert-from-uffi-type array-type :allocation)) + (accessor (first (macroexpand `(ccl:pref obj ,local-type))))) + `(,accessor + ,obj + (* (the fixnum ,i) ,(size-of-foreign-type local-type)))) + )) + +; this expands to the %set-xx functions which has different params than %put-xx +#+digitool +(defmacro deref-array-set (obj type i value) + (let* ((array-type (array-type type)) + (local-type (convert-from-uffi-type array-type :allocation)) + (accessor (first (macroexpand `(ccl:pref obj ,local-type)))) + (settor (first (macroexpand `(setf (,accessor obj ,local-type) value))))) + `(,settor + ,obj + (* (the fixnum ,i) ,(size-of-foreign-type local-type)) + ,value))) + +#+digitool +(defsetf deref-array deref-array-set) + +(defmacro def-union (name &rest fields) + #+allegro + `(ff:def-foreign-type ,name (:union ,@(process-struct-fields name fields))) + #+lispworks + `(fli:define-c-union ,name ,@(process-struct-fields name fields)) + #+(or cmu scl) + `(alien:def-alien-type ,name (alien:union ,name ,@(process-struct-fields name fields))) + #+sbcl + `(sb-alien:define-alien-type ,name (sb-alien:union ,name ,@(process-struct-fields name fields))) + #+digitool + `(ccl:defrecord ,name (:variant ,@(process-struct-fields name fields t))) + #+openmcl + `(ccl::def-foreign-type nil + (:union ,name ,@(process-struct-fields name fields))) +) + + +#-(or sbcl cmu) +(defun convert-from-foreign-usb8 (s len) + (declare (optimize (speed 3) (space 0) (safety 0) (compilation-speed 0)) + (fixnum len)) + (let ((a (make-array len :element-type '(unsigned-byte 8)))) + (dotimes (i len a) + (declare (fixnum i)) + (setf (aref a i) (uffi:deref-array s '(:array :unsigned-byte) i))))) + +#+sbcl +(eval-when (:compile-toplevel :load-toplevel :execute) + (sb-ext:without-package-locks + (defvar *system-copy-fn* (if (fboundp (intern "COPY-FROM-SYSTEM-AREA" "SB-KERNEL")) + (intern "COPY-FROM-SYSTEM-AREA" "SB-KERNEL") + (intern "COPY-UB8-FROM-SYSTEM-AREA" "SB-KERNEL"))) + (defconstant +system-copy-offset+ (if (fboundp (intern "COPY-FROM-SYSTEM-AREA" "SB-KERNEL")) + (* sb-vm:vector-data-offset sb-vm:n-word-bits) + 0)) + (defconstant +system-copy-multiplier+ (if (fboundp (intern "COPY-FROM-SYSTEM-AREA" "SB-KERNEL")) + sb-vm:n-byte-bits + 1)))) + + +#+sbcl +(defun convert-from-foreign-usb8 (s len) + (let ((sap (sb-alien:alien-sap s))) + (declare (type sb-sys:system-area-pointer sap)) + (locally + (declare (optimize (speed 3) (safety 0))) + (let ((result (make-array len :element-type '(unsigned-byte 8)))) + (funcall *system-copy-fn* sap 0 result +system-copy-offset+ + (* len +system-copy-multiplier+)) + result)))) + +#+cmu +(defun convert-from-foreign-usb8 (s len) + (let ((sap (alien:alien-sap s))) + (declare (type system:system-area-pointer sap)) + (locally + (declare (optimize (speed 3) (safety 0))) + (let ((result (make-array len :element-type '(unsigned-byte 8)))) + (kernel:copy-from-system-area sap 0 + result (* vm:vector-data-offset + vm:word-bits) + (* len vm:byte-bits)) + result)))) Added: branches/trunk-reorg/thirdparty/uffi-1.6.0/src/corman/corman-notes.txt ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi-1.6.0/src/corman/corman-notes.txt Mon Feb 11 09:23:05 2008 @@ -0,0 +1,17 @@ +some notes: + we need the :pascal (:stdcall) calling conventions for + (def-function names args &key module returning calling-convention) + so I added this. calling-convention defaults to :cdecl + but on win32 we mostly use :stdcall + + #+corman is invalid, #+cormanlisp instead + + cormanlisp doesn't need to load and register the dll, since the underlying + LoadLibrary() call does this. we need the module keyword for def-function +instead. + (should probably default to kernel32.dll) + I'll think about library.cl, but we'll need more real-world win32 examples. + (ideally the complete winapi :) + I also have to look at valentina. + +patch -p0 < corman.diff Added: branches/trunk-reorg/thirdparty/uffi-1.6.0/src/corman/getenv-ccl.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi-1.6.0/src/corman/getenv-ccl.lisp Mon Feb 11 09:23:05 2008 @@ -0,0 +1,81 @@ +;;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Base: 10 -*- +;;;; ************************************************************************* +;;;; FILE IDENTIFICATION +;;;; +;;;; Name: getenv-ccl.cl +;;;; Purpose: cormanlisp version +;;;; Programmer: "Joe Marshall" +;;;; Date Started: Feb 2002 +;;;; +;;;; $Id: getenv-ccl.lisp 10614 2005-07-06 01:05:14Z kevin $ +;;;; +;;;; ************************************************************************* + +(in-package :cl-user) + +(ct:defun-dll c-getenv ((lpname LPSTR) + (lpbuffer LPSTR) + (nsize LPDWORD)) + :library-name "kernel32.dll" + :return-type DWORD + :entry-name "GetEnvironmentVariableA" + :linkage-type :pascal) + +(defun getenv (name) + (let ((nsizebuf (ct:malloc (sizeof :long))) + (buffer (ct:malloc 1)) + (cname (ct:lisp-string-to-c-string name))) + (setf (ct:cref lpdword nsizebuf 0) 0) + (let* ((needed-size (c-getenv cname buffer nsizebuf)) + (buffer1 (ct:malloc (1+ needed-size)))) + (setf (ct:cref lpdword nsizebuf 0) needed-size) + (prog1 (if (zerop (c-getenv cname buffer1 nsizebuf)) + nil + (ct:c-string-to-lisp-string buffer1)) + (ct:free buffer1) + (ct:free nsizebuf))))) + +(defun cl:user-homedir-pathname (&optional host) + (cond ((or (stringp host) + (and (consp host) + (every #'stringp host))) nil) + ((or (eq host :unspecific) + (null host)) + (let ((homedrive (getenv "HOMEDRIVE")) + (homepath (getenv "HOMEPATH"))) + (parse-namestring + (if (and (stringp homedrive) + (stringp homepath) + (= (length homedrive) 2) + (> (length homepath) 0)) + (concatenate 'string homedrive homepath "\\") + "C:\\")))) + (t (error "HOST must be a string, list of strings, NIL or :unspecific")))) + +;| +(uffi:def-function ("getenv" c-getenv) + ((name :cstring)) + :returning :cstring) + +(defun my-getenv (key) + "Returns an environment variable, or NIL if it does not exist" + (check-type key string) + (uffi:with-cstring (key-native key) + (uffi:convert-from-cstring (c-getenv key-native)))) + +#examples-uffi +(progn + (flet ((print-results (str) + (format t "~&(getenv ~S) => ~S" str (my-getenv str)))) + (print-results "USER") + (print-results "_FOO_"))) + + +#test-uffi +(progn + (util.test:test (my-getenv "_FOO_") nil :fail-info "Error retrieving non-existent getenv") + (util.test:test (and (stringp (my-getenv "USER")) + (< 0 (length (my-getenv "USER")))) + t :fail-info "Error retrieving getenv") +) + Added: branches/trunk-reorg/thirdparty/uffi-1.6.0/src/functions.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi-1.6.0/src/functions.lisp Mon Feb 11 09:23:05 2008 @@ -0,0 +1,239 @@ +;;;; -*- Mode: Lisp; Syntax: ANSI-Common-Lisp; Base: 10; Package: UFFI -*- +;;;; ************************************************************************* +;;;; FILE IDENTIFICATION +;;;; +;;;; Name: function.lisp +;;;; Purpose: UFFI source to C function definitions +;;;; Programmer: Kevin M. Rosenberg +;;;; Date Started: Feb 2002 +;;;; +;;;; $Id: functions.lisp 11615 2007-04-13 05:49:01Z kevin $ +;;;; +;;;; This file, part of UFFI, is Copyright (c) 2005 by Kevin M. Rosenberg +;;;; +;;;; ************************************************************************* + +(in-package #:uffi) + +(defun process-function-args (args) + (if (null args) + #+(or lispworks cmu sbcl scl cormanlisp digitool) nil + #+allegro '(:void) + #+openmcl (values nil nil) + + ;; args not null + #+(or lispworks allegro cmu sbcl scl digitool cormanlisp) + (let (processed) + (dolist (arg args) + (push (process-one-function-arg arg) processed)) + (nreverse processed)) + #+openmcl + (let ((processed nil) + (params nil)) + (dolist (arg args) + (let ((name (car arg)) + (type (convert-from-uffi-type (cadr arg) :routine))) + ;;(when (and (listp type) (eq (car type) :address)) + ;;(setf type :address)) + (push name params) + (push type processed) + (push name processed))) + (values (nreverse params) (nreverse processed))) + )) + +(defun process-one-function-arg (arg) + (let ((name (car arg)) + (type (convert-from-uffi-type (cadr arg) :routine))) + #+(or cmu sbcl scl) + ;(list name type :in) + `(,name ,type ,@(if (= (length arg) 3) (list (third arg)) (values))) + #+(or allegro lispworks digitool) + (if (and (listp type) (listp (car type))) + (append (list name) type) + (list name type)) + #+openmcl + (declare (ignore name type)) + )) + + +(defun allegro-convert-return-type (type) + (if (and (listp type) (not (listp (car type)))) + (list type) + type)) + +(defun funcallable-lambda-list (args) + (let ((ll nil)) + (dolist (arg args) + (push (car arg) ll)) + (nreverse ll))) + +#| +(defmacro def-funcallable (name args &key returning) + (let ((result-type (convert-from-uffi-type returning :return)) + (function-args (process-function-args args))) + #+lispworks + `(fli:define-foreign-funcallable ,name ,function-args + :result-type ,result-type + :language :ansi-c + :calling-convention :cdecl) + #+(or cmu scl sbcl) + ;; requires the type of the function pointer be declared correctly! + (let* ((ptrsym (gensym)) + (ll (funcallable-lambda-list args))) + `(defun ,name ,(cons ptrsym ll) + (alien::alien-funcall ,ptrsym , at ll))) + #+openmcl + (multiple-value-bind (params args) (process-function-args args) + (let ((ptrsym (gensym))) + `(defun ,name ,(cons ptrsym params) + (ccl::ff-call ,ptrsym , at args ,result-type)))) + #+allegro + ;; this is most definitely wrong + (let* ((ptrsym (gensym)) + (ll (funcallable-lambda-list args))) + `(defun ,name ,(cons ptrsym ll) + (system::ff-funcall ,ptrsym , at ll))) + )) +|# + +(defun convert-lispworks-args (args) + (loop for arg in args + with processed = nil + do + (if (and (= (length arg) 3) (eq (third arg) :out)) + (push (list (first arg) + (list :reference-return (second arg))) processed) + (push (subseq arg 0 2) processed)) + finally (return (nreverse processed)))) + +(defun preprocess-names (names) + (let ((fname (gensym))) + (if (atom names) + (values (list names fname) fname (uffi::make-lisp-name names)) + (values (list (first names) fname) fname (second names))))) + +(defun preprocess-args (args) + (loop for arg in args + with lisp-args = nil and out = nil and processed = nil + do + (if (= (length arg) 3) + (ecase (third arg) + (:in + (progn + (push (first arg) lisp-args) + (push (list (first arg) (second arg)) processed))) + (:out + (progn + (push (list (first arg) (second arg)) out) + (push (list (first arg) (list '* (second arg))) processed)))) + (progn + (push (first arg) lisp-args) + (push arg processed))) + finally (return (values (nreverse lisp-args) + (nreverse out) + (nreverse processed))))) + + +(defmacro def-function (names args &key module returning) + (multiple-value-bind (lisp-args out processed) + (preprocess-args args) + (declare (ignorable lisp-args processed)) + (if (= (length out) 0) + `(%def-function ,names ,args + ,@(if module (list :module module) (values)) + ,@(if returning (list :returning returning) (values))) + + #+(or cmu scl sbcl) + `(%def-function ,names ,args + ,@(if returning (list :returning returning) (values))) + #+(and lispworks lispworks5) + (multiple-value-bind (name-pair fname lisp-name) + (preprocess-names names) + `(progn + (%def-function ,name-pair ,(convert-lispworks-args args) + ,@(if module (list :module module) (values)) + ,@(if returning (list :returning returning) (values))) + (defun ,lisp-name ,lisp-args + (,fname ,@(mapcar + #'(lambda (arg) + (cond ((member (first arg) lisp-args) + (first arg)) + ((member (first arg) out :key #'first) + t))) + args))))) + #+(and lispworks (not lispworks5)) + `(%def-function ,names ,(convert-lispworks-args args) + ,@(if module (list :module module) (values)) + ,@(if returning (list :returning returning) (values))) + #-(or cmu scl sbcl lispworks) + (multiple-value-bind (name-pair fname lisp-name) + (preprocess-names names) + `(progn + (%def-function ,name-pair ,processed + :module ,module :returning ,returning) + ;(declaim (inline ,fname)) + (defun ,lisp-name ,lisp-args + (with-foreign-objects ,out + (values (,fname ,@(mapcar #'first args)) + ,@(mapcar #'(lambda (arg) + (list 'deref-pointer + (first arg) + (second arg))) out)))))) + ))) + + +;; name is either a string representing foreign name, or a list +;; of foreign-name as a string and lisp name as a symbol +(defmacro %def-function (names args &key module returning) + #+(or cmu sbcl scl allegro openmcl digitool cormanlisp) (declare (ignore module)) + + (let* ((result-type (convert-from-uffi-type returning :return)) + (function-args (process-function-args args)) + (foreign-name (if (atom names) names (car names))) + (lisp-name (if (atom names) (make-lisp-name names) (cadr names)))) + ;; todo: calling-convention :stdcall for cormanlisp + #+allegro + `(ff:def-foreign-call (,lisp-name ,foreign-name) + ,function-args + :returning ,(allegro-convert-return-type result-type) + :call-direct t + :strings-convert nil) + #+(or cmu scl) + `(alien:def-alien-routine (,foreign-name ,lisp-name) + ,result-type + , at function-args) + #+sbcl + `(sb-alien:define-alien-routine (,foreign-name ,lisp-name) + ,result-type + , at function-args) + #+lispworks + `(fli:define-foreign-function (,lisp-name ,foreign-name :source) + ,function-args + ,@(if module (list :module module) (values)) + :result-type ,result-type + :language :ansi-c + #+:win32 :calling-convention #+:win32 :cdecl) + #+digitool + `(eval-when (:compile-toplevel :load-toplevel :execute) + (ccl:define-entry-point (,lisp-name ,foreign-name) + ,function-args + ,result-type)) + #+openmcl + (declare (ignore function-args)) + #+(and openmcl darwinppc-target) + (setf foreign-name (concatenate 'string "_" foreign-name)) + #+openmcl + (multiple-value-bind (params args) (process-function-args args) + `(defun ,lisp-name ,params + (ccl::external-call ,foreign-name , at args ,result-type))) + #+cormanlisp + `(ct:defun-dll ,lisp-name (,function-args) + :return-type ,result-type + ,@(if module (list :library-name module) (values)) + :entry-name ,foreign-name + :linkage-type ,calling-convention) ; we need :pascal + )) + + + + Added: branches/trunk-reorg/thirdparty/uffi-1.6.0/src/libraries.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi-1.6.0/src/libraries.lisp Mon Feb 11 09:23:05 2008 @@ -0,0 +1,134 @@ +;;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Base: 10; Package: UFFI -*- +;;;; ************************************************************************* +;;;; FILE IDENTIFICATION +;;;; +;;;; Name: libraries.lisp +;;;; Purpose: UFFI source to load foreign libraries +;;;; Programmer: Kevin M. Rosenberg +;;;; Date Started: Feb 2002 +;;;; +;;;; $Id: libraries.lisp 11764 2007-07-22 19:09:39Z kevin $ +;;;; +;;;; This file, part of UFFI, is Copyright (c) 2002-2005 by Kevin M. Rosenberg +;;;; +;;;; ************************************************************************* + +(in-package #:uffi) + +(defvar *loaded-libraries* nil + "List of foreign libraries loaded. Used to prevent reloading a library") + +(defun default-foreign-library-type () + "Returns string naming default library type for platform" + #+(or win32 cygwin mswindows) "dll" + #+(or macosx darwin ccl-5.0) "dylib" + #-(or win32 cygwin mswindows macosx darwin ccl-5.0) "so" +) + +(defun foreign-library-types () + "Returns list of string naming possible library types for platform, sorted by preference" + #+(or win32 mswindows) '("dll" "lib") + #+(or macosx darwin ccl-5.0) '("dylib" "bundle") + #-(or win32 mswindows macosx darwin ccl-5.0) '("so" "a" "o") +) + +(defun find-foreign-library (names directories &key types drive-letters) + "Looks for a foreign library. directories can be a single +string or a list of strings of candidate directories. Use default +library type if type is not specified." + (unless types + (setq types (foreign-library-types))) + (unless (listp types) + (setq types (list types))) + (unless (listp names) + (setq names (list names))) + (unless (listp directories) + (setq directories (list directories))) + #+(or win32 mswindows) + (unless (listp drive-letters) + (setq drive-letters (list drive-letters))) + #-(or win32 mswindows) + (setq drive-letters '(nil)) + (dolist (drive-letter drive-letters) + (dolist (name names) + (dolist (dir directories) + (dolist (type types) + (let ((path (make-pathname + #+lispworks :host + #+lispworks (when drive-letter drive-letter) + #-lispworks :device + #-lispworks (when drive-letter drive-letter) + :name name + :type type + :directory + (etypecase dir + (pathname + (pathname-directory dir)) + (list + dir) + (string + (pathname-directory + (parse-namestring dir))))))) + (when (probe-file path) + (return-from find-foreign-library path))))))) + nil) + + +(defun load-foreign-library (filename &key module supporting-libraries + force-load) + #+(or allegro openmcl digitool sbcl) (declare (ignore module supporting-libraries)) + #+(or cmu scl) (declare (ignore module)) + #+lispworks (declare (ignore supporting-libraries)) + + (flet ((load-failure () + (error "Unable to load foreign library \"~A\"." filename))) + (when (and filename (or (null (pathname-directory filename)) + (probe-file filename))) + (if (pathnamep filename) ;; ensure filename is a string to check if already loaded + (setq filename (namestring (if (null (pathname-directory filename)) + filename + ;; lispworks treats as UNC, so use truename + #+(and lispworks win32) (truename filename) + #-(and lispworks win32) filename)))) + + (if (and (not force-load) + (find filename *loaded-libraries* :test #'string-equal)) + t ;; return T, but don't reload library + (progn + #+cmu + (let ((type (pathname-type (parse-namestring filename)))) + (if (string-equal type "so") + (unless + (sys::load-object-file filename) + (load-failure)) + (alien:load-foreign filename + :libraries + (convert-supporting-libraries-to-string + supporting-libraries)))) + #+scl + (let ((type (pathname-type (parse-namestring filename)))) + (alien:load-foreign filename + :libraries + (convert-supporting-libraries-to-string + supporting-libraries))) + #+sbcl + (handler-case (sb-alien::load-1-foreign filename) + (sb-int:unsupported-operator (c) + (if (fboundp (intern "LOAD-SHARED-OBJECT" :sb-alien)) + (funcall (intern "LOAD-SHARED-OBJECT" :sb-alien) filename) + (error c)))) + + #+lispworks (fli:register-module module :real-name filename + :connection-style :immediate) + #+allegro (load filename) + #+openmcl (ccl:open-shared-library filename) + #+digitool (ccl:add-to-shared-library-search-path filename t) + + (push filename *loaded-libraries*) + t))))) + +(defun convert-supporting-libraries-to-string (libs) + (let (lib-load-list) + (dolist (lib libs) + (push (format nil "-l~A" lib) lib-load-list)) + (nreverse lib-load-list))) Added: branches/trunk-reorg/thirdparty/uffi-1.6.0/src/objects.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi-1.6.0/src/objects.lisp Mon Feb 11 09:23:05 2008 @@ -0,0 +1,291 @@ +;;;; -*- Mode: Lisp; Syntax: ANSI-Common-Lisp; Base: 10; Package: UFFI -*- +;;;; ************************************************************************* +;;;; FILE IDENTIFICATION +;;;; +;;;; Name: objects.lisp +;;;; Purpose: UFFI source to handle objects and pointers +;;;; Programmer: Kevin M. Rosenberg +;;;; Date Started: Feb 2002 +;;;; +;;;; $Id: objects.lisp 11022 2006-08-14 04:26:22Z kevin $ +;;;; +;;;; This file, part of UFFI, is Copyright (c) 2002-2005 by Kevin M. Rosenberg +;;;; +;;;; ************************************************************************* + +(in-package #:uffi) + +(eval-when (:compile-toplevel :load-toplevel :execute) + (defun size-of-foreign-type (type) + #+lispworks (fli:size-of type) + #+allegro (ff:sizeof-fobject type) + #+(or cmu scl) (ash (eval `(alien:alien-size ,type)) -3) ;; convert from bits to bytes + #+sbcl (ash (eval `(sb-alien:alien-size ,type)) -3) ;; convert from bits to bytes + #+clisp (values (ffi:size-of type)) + #+digitool + (let ((mcl-type (ccl:find-mactype type nil t))) + (if mcl-type + (ccl::mactype-record-size mcl-type) + (ccl::record-descriptor-length (ccl:find-record-descriptor type t t)))) ;error if not a record + #+openmcl (ccl::%foreign-type-or-record-size type :bytes) + )) + +(defmacro allocate-foreign-object (type &optional (size :unspecified)) + "Allocates an instance of TYPE. If size is specified, then allocate +an array of TYPE with size SIZE. The TYPE parameter is evaluated." + (if (eq size :unspecified) + (progn + #+(or cmu scl) + `(alien:make-alien ,(convert-from-uffi-type (eval type) :allocation)) + #+sbcl + `(sb-alien:make-alien ,(convert-from-uffi-type (eval type) :allocation)) + #+lispworks + `(fli:allocate-foreign-object :type ',(convert-from-uffi-type type :allocate)) + #+allegro + `(ff:allocate-fobject ',(convert-from-uffi-type type :allocate) :c) + #+(or openmcl digitool) + `(new-ptr ,(size-of-foreign-type (convert-from-uffi-type type :allocation))) + ) + (progn + #+(or cmu scl) + `(alien:make-alien ,(convert-from-uffi-type (eval type) :allocation) ,size) + #+sbcl + `(sb-alien:make-alien ,(convert-from-uffi-type (eval type) :allocation) ,size) + #+lispworks + `(fli:allocate-foreign-object :type ',(convert-from-uffi-type type :allocate) :nelems ,size) + #+allegro + `(ff:allocate-fobject (list :array (quote ,(convert-from-uffi-type type :allocate)) ,size) :c) + #+(or openmcl digitool) + `(new-ptr (* ,size ,(size-of-foreign-type (convert-from-uffi-type type :allocation)))) + ))) + +(defmacro free-foreign-object (obj) + #+(or cmu scl) + `(alien:free-alien ,obj) + #+sbcl + `(sb-alien:free-alien ,obj) + #+lispworks + `(fli:free-foreign-object ,obj) + #+allegro + `(ff:free-fobject ,obj) + #+(or openmcl digitool) + `(dispose-ptr ,obj) + ) + +(defmacro null-pointer-p (obj) + #+lispworks `(fli:null-pointer-p ,obj) + #+allegro `(zerop ,obj) + #+(or cmu scl) `(alien:null-alien ,obj) + #+sbcl `(sb-alien:null-alien ,obj) + #+(or openmcl digitool) `(ccl:%null-ptr-p ,obj) + ) + +(defmacro make-null-pointer (type) + #+(or allegro openmcl digitool) (declare (ignore type)) + #+(or cmu scl) `(alien:sap-alien (system:int-sap 0) (* ,(convert-from-uffi-type (eval type) :type))) + #+sbcl `(sb-alien:sap-alien (sb-sys:int-sap 0) (* ,(convert-from-uffi-type (eval type) :type))) + #+lispworks `(fli:make-pointer :address 0 :type (quote ,(convert-from-uffi-type (eval type) :type))) + #+allegro 0 + #+(or openmcl digitool) `(ccl:%null-ptr) + ) + +(defmacro make-pointer (addr type) + #+(or allegro openmcl digitool) (declare (ignore type)) + #+(or cmu scl) `(alien:sap-alien (system:int-sap ,addr) (* ,(convert-from-uffi-type (eval type) :type))) + #+sbcl `(sb-alien:sap-alien (sb-sys:int-sap ,addr) (* ,(convert-from-uffi-type (eval type) :type))) + #+lispworks `(fli:make-pointer :address ,addr :type (quote ,(convert-from-uffi-type (eval type) :type))) + #+allegro addr + #+(or openmcl digitool) `(ccl:%int-to-ptr ,addr) + ) + + +(defmacro char-array-to-pointer (obj) + #+(or cmu scl) `(alien:cast ,obj (* (alien:unsigned 8))) + #+sbcl `(sb-alien:cast ,obj (* (sb-alien:unsigned 8))) + #+lispworks `(fli:make-pointer :type '(:unsigned :char) + :address (fli:pointer-address ,obj)) + #+allegro obj + #+(or openmcl digitool) obj + ) + +(defmacro deref-pointer (ptr type) + "Returns a object pointed" + #+(or cmu sbcl lispworks scl) (declare (ignore type)) + #+(or cmu scl) `(alien:deref ,ptr) + #+sbcl `(sb-alien:deref ,ptr) + #+lispworks `(fli:dereference ,ptr) + #+allegro `(ff:fslot-value-typed (quote ,(convert-from-uffi-type type :deref)) :c ,ptr) + #+(or openmcl digitool) `(ccl:pref ,ptr ,(convert-from-uffi-type type :deref)) + ) + +#+digitool +(defmacro deref-pointer-set (ptr type value) + `(setf (ccl:pref ,ptr ,(convert-from-uffi-type type :deref)) ,value)) + +#+digitool +(defsetf deref-pointer deref-pointer-set) + +(defmacro ensure-char-character (obj) + #+(or digitool) obj + #+(or allegro cmu sbcl scl openmcl) `(code-char ,obj) + ;; lispworks varies whether deref'ing array vs. slot access of a char + #+lispworks `(if (characterp ,obj) ,obj (code-char ,obj))) + +(defmacro ensure-char-integer (obj) + #+(or digitool) `(char-code ,obj) + #+(or allegro cmu sbcl scl openmcl) obj + ;; lispworks varies whether deref'ing array vs. slot access of a char + #+lispworks + `(if (integerp ,obj) ,obj (char-code ,obj))) + +(defmacro ensure-char-storable (obj) + #+(or digitool (and lispworks (not lispworks5))) obj + #+(or allegro cmu lispworks5 openmcl sbcl scl) + `(char-code ,obj)) + +(defmacro pointer-address (obj) + #+(or cmu scl) + `(system:sap-int (alien:alien-sap ,obj)) + #+sbcl + `(sb-sys:sap-int (sb-alien:alien-sap ,obj)) + #+lispworks + `(fli:pointer-address ,obj) + #+allegro + obj + #+(or openmcl digitool) + `(ccl:%ptr-to-int ,obj) + ) + +;; TYPE is evaluated. +#-(or openmcl digitool) +(defmacro with-foreign-object ((var type) &rest body) + #-(or cmu sbcl lispworks scl) ; default version + `(let ((,var (allocate-foreign-object ,type))) + (unwind-protect + (progn , at body) + (free-foreign-object ,var))) + #+(or cmu scl) + (let ((obj (gensym)) + (ctype (convert-from-uffi-type (eval type) :allocate))) + (if (and (consp ctype) (eq 'array (car ctype))) + `(alien:with-alien ((,obj ,ctype)) + (let* ((,var ,obj)) + , at body)) + `(alien:with-alien ((,obj ,ctype)) + (let* ((,var (alien:addr ,obj))) + , at body)))) + #+sbcl + (let ((obj (gensym)) + (ctype (convert-from-uffi-type (eval type) :allocate))) + (if (and (consp ctype) (eq 'array (car ctype))) + `(sb-alien:with-alien ((,obj ,ctype)) + (let* ((,var ,obj)) + , at body)) + `(sb-alien:with-alien ((,obj ,ctype)) + (let* ((,var (sb-alien:addr ,obj))) + , at body)))) + #+lispworks + `(fli:with-dynamic-foreign-objects ((,var ,(convert-from-uffi-type + (eval type) :allocate))) + , at body) + ) + +#-(or openmcl digitool) +(defmacro with-foreign-objects (bindings &rest body) + (if bindings + `(with-foreign-object ,(car bindings) + (with-foreign-objects ,(cdr bindings) + , at body)) + `(progn , at body))) + +#+(or openmcl digitool) +(defmacro with-foreign-objects (bindings &rest body) + (let ((params nil) type count) + (dolist (spec (reverse bindings)) ;keep order - macroexpands to let* + (setf type (convert-from-uffi-type (eval (nth 1 spec)) :allocate)) + (setf count 1) + (when (and (listp type) (eq (first type) :array)) + (setf count (nth 2 type)) + (unless (integerp count) (error "Invalid size for array: ~a" type)) + (setf type (nth 1 type))) + (push (list (first spec) (* count (size-of-foreign-type type))) params)) + `(ccl:%stack-block ,params , at body))) + +#+(or openmcl digitool) +(defmacro with-foreign-object ((var type) &rest body) + `(with-foreign-objects ((,var ,type)) + , at body)) + +#+lispworks +(defmacro with-cast-pointer ((binding-name pointer type) &body body) + `(fli:with-coerced-pointer (,binding-name + :type ',(convert-from-uffi-type (eval type) :type)) + ,pointer + , at body)) + +#+(or cmu scl sbcl) +(defmacro with-cast-pointer ((binding-name pointer type) &body body) + `(let ((,binding-name + (#+(or cmu scl) alien:cast + #+sbcl sb-alien:cast + ,pointer (* ,(convert-from-uffi-type (eval type) :type))))) + , at body)) + +#+(or allegro openmcl) +(defmacro with-cast-pointer ((binding-name pointer type) &body body) + (declare (ignore type)) + `(let ((,binding-name ,pointer)) + , at body)) + +#-(or lispworks cmu scl sbcl allegro openmcl) +(defmacro with-cast-pointer ((binding-name pointer type) &body body) + (declare (ignore binding-name pointer type body)) + '(error "WITH-CAST-POINTER not (yet) implemented for ~A" + (lisp-implementation-type))) + +#+(or allegro openmcl) +(defun convert-external-name (name) + "Add an underscore to NAME if necessary for the ABI." + #+(or macosx darwinppc-target) (concatenate 'string "_" name) + #-(or macosx darwinppc-target) name) + +(defmacro def-foreign-var (names type module) + #-lispworks (declare (ignore module)) + (let ((foreign-name (if (atom names) names (first names))) + (lisp-name (if (atom names) (make-lisp-name names) (second names))) + #-allegro + (var-type (convert-from-uffi-type type :type))) + #+(or cmu scl) + `(alien:def-alien-variable (,foreign-name ,lisp-name) ,var-type) + #+sbcl + `(sb-alien:define-alien-variable (,foreign-name ,lisp-name) ,var-type) + #+allegro + `(define-symbol-macro ,lisp-name + (ff:fslot-value-typed (quote ,(convert-from-uffi-type type :deref)) + :c (ff:get-entry-point ,(convert-external-name foreign-name)))) + #+lispworks + `(progn + (fli:define-foreign-variable (,lisp-name ,foreign-name) + :accessor :address-of + :type ,var-type + :module ,module) + (define-symbol-macro ,lisp-name (fli:dereference (,lisp-name) + :copy-foreign-object nil))) + #+openmcl + `(define-symbol-macro ,lisp-name + (deref-pointer (ccl:foreign-symbol-address + ,(convert-external-name foreign-name)) ,var-type)) + #-(or allegro cmu scl sbcl lispworks openmcl) + `(define-symbol-macro ,lisp-name + '(error "DEF-FOREIGN-VAR not (yet) defined for ~A" + (lisp-implementation-type))))) + + +;;; Define a special variable, like DEFVAR, that will be initialized +;;; to a pointer which may need to be reset when a saved image is +;;; loaded. This is needed for OpenMCL, which sets pointers to "dead +;;; macptrs" when a saved image is loaded. +;; This may possibly be needed for sbcl's SAVE-LISP-AND-DIE +(defmacro def-pointer-var (name value &optional doc) + #-openmcl `(defvar ,name ,value ,@(if doc (list doc))) + #+openmcl `(ccl::defloadvar ,name ,value ,doc)) Added: branches/trunk-reorg/thirdparty/uffi-1.6.0/src/os.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi-1.6.0/src/os.lisp Mon Feb 11 09:23:05 2008 @@ -0,0 +1,79 @@ +;;;; -*- Mode: Lisp; Syntax: ANSI-Common-Lisp; Base: 10; Package: UFFI -*- +;;;; ************************************************************************* +;;;; FILE IDENTIFICATION +;;;; +;;;; Name: os.lisp +;;;; Purpose: Operating system interface for UFFI +;;;; Programmer: Kevin M. Rosenberg +;;;; Date Started: Sep 2002 +;;;; +;;;; $Id: os.lisp 10917 2006-04-18 00:07:09Z kevin $ +;;;; +;;;; This file, part of UFFI, is Copyright (c) 2002-2005 by Kevin M. Rosenberg. +;;;; +;;;; ************************************************************************* + +(in-package #:uffi) + + +(defun getenv (var) + "Return the value of the environment variable." + #+allegro (sys::getenv (string var)) + #+clisp (sys::getenv (string var)) + #+cmu (cdr (assoc (string var) ext:*environment-list* :test #'equalp + :key #'string)) + #+gcl (si:getenv (string var)) + #+lispworks (lw:environment-variable (string var)) + #+lucid (lcl:environment-variable (string var)) + #+(or openmcl digitool) (ccl::getenv var) + #+sbcl (sb-ext:posix-getenv var) + #-(or allegro clisp cmu gcl lispworks lucid openmcl digitool sbcl) + (error 'not-implemented :proc (list 'getenv var))) + + +;; modified from function ASDF -- Copyright Dan Barlow and Contributors + +(defun run-shell-command (control-string &rest args &key output) + "Interpolate ARGS into CONTROL-STRING as if by FORMAT, and +synchronously execute the result using a Bourne-compatible shell, with +output to *trace-output*. Returns the shell's exit code." + (unless output + (setq output *trace-output*)) + + (let ((command (apply #'format nil control-string args))) + #+sbcl + (sb-impl::process-exit-code + (sb-ext:run-program + "/bin/sh" + (list "-c" command) + :input nil :output output)) + + #+(or cmu scl) + (ext:process-exit-code + (ext:run-program + "/bin/sh" + (list "-c" command) + :input nil :output output)) + + #+allegro + (excl:run-shell-command command :input nil :output output) + + #+lispworks + (system:call-system-showing-output + command + :shell-type "/bin/sh" + :output-stream output) + + #+clisp ;XXX not exactly *trace-output*, I know + (ext:run-shell-command command :output :terminal :wait t) + + #+openmcl + (nth-value 1 + (ccl:external-process-status + (ccl:run-program "/bin/sh" (list "-c" command) + :input nil :output output + :wait t))) + + #-(or openmcl clisp lispworks allegro scl cmu sbcl) + (error "RUN-SHELL-PROGRAM not implemented for this Lisp.") + )) Added: branches/trunk-reorg/thirdparty/uffi-1.6.0/src/package.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi-1.6.0/src/package.lisp Mon Feb 11 09:23:05 2008 @@ -0,0 +1,84 @@ +;;;; -*- Mode: Lisp; Syntax: ANSI-Common-Lisp; Base: 10; Package: UFFI -*- +;;;; ************************************************************************* +;;;; FILE IDENTIFICATION +;;;; +;;;; Name: package.lisp +;;;; Purpose: Defines UFFI package +;;;; Programmer: Kevin M. Rosenberg +;;;; Date Started: Feb 2002 +;;;; +;;;; This file, part of UFFI, is Copyright (c) 2002-2005 by Kevin M. Rosenberg +;;;; +;;;; ************************************************************************* + +(in-package #:cl-user) + +(defpackage #:uffi + (:use #:cl) + (:export + + ;; immediate types + #:def-constant + #:def-foreign-type + #:def-type + #:null-char-p + + ;; aggregate types + #:def-enum + #:def-struct + #:get-slot-value + #:get-slot-pointer + #:def-array-pointer + #:deref-array + #:def-union + + ;; objects + #:allocate-foreign-object + #:free-foreign-object + #:with-foreign-object + #:with-foreign-objects + #:size-of-foreign-type + #:pointer-address + #:deref-pointer + #:ensure-char-character + #:ensure-char-integer + #:ensure-char-storable + #:null-pointer-p + #:make-null-pointer + #:make-pointer + #:pointer-address + #:+null-cstring-pointer+ + #:char-array-to-pointer + #:with-cast-pointer + #:def-foreign-var + #:convert-from-foreign-usb8 + #:def-pointer-var + + ;; string functions + #:convert-from-cstring + #:convert-to-cstring + #:free-cstring + #:with-cstring + #:with-cstrings + #:convert-from-foreign-string + #:convert-to-foreign-string + #:allocate-foreign-string + #:with-foreign-string + #:with-foreign-strings + #:foreign-string-length + + ;; function call + #:def-function + + ;; Libraries + #:find-foreign-library + #:load-foreign-library + #:default-foreign-library-type + #:foreign-library-types + + ;; OS + #:run-shell-command + #:getenv + )) + + Added: branches/trunk-reorg/thirdparty/uffi-1.6.0/src/primitives.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi-1.6.0/src/primitives.lisp Mon Feb 11 09:23:05 2008 @@ -0,0 +1,311 @@ +;;;; -*- Mode: Lisp; Syntax: ANSI-Common-Lisp; Base: 10; Package: UFFI -*- +;;;; ************************************************************************* +;;;; FILE IDENTIFICATION +;;;; +;;;; Name: primitives.lisp +;;;; Purpose: UFFI source to handle immediate types +;;;; Programmer: Kevin M. Rosenberg +;;;; Date Started: Feb 2002 +;;;; +;;;; $Id: primitives.lisp 10917 2006-04-18 00:07:09Z kevin $ +;;;; +;;;; This file, part of UFFI, is Copyright (c) 2002-2005 by Kevin M. Rosenberg +;;;; +;;;; ************************************************************************* + +(in-package #:uffi) + +#+(or openmcl digitool) +(defvar *keyword-package* (find-package "KEYWORD")) + +#+(or openmcl digitool) +; MCL and OpenMCL expect a lot of FFI elements to be keywords (e.g. struct field names in OpenMCL) +; So this provides a function to convert any quoted symbols to keywords. +(defun keyword (obj) + (cond ((keywordp obj) + obj) + ((null obj) + nil) + ((symbolp obj) + (intern (symbol-name obj) *keyword-package*)) + ((and (listp obj) (eq (car obj) 'cl:quote)) + (keyword (cadr obj))) + ((stringp obj) + (intern obj *keyword-package*)) + (t + obj))) + +; Wrapper for unexported function we have to use +#+digitool +(defmacro def-mcl-type (name type) + `(ccl::def-mactype ,(keyword name) (ccl:find-mactype ,type))) + +(defmacro def-constant (name value &key (export nil)) + "Macro to define a constant and to export it" + `(eval-when (:compile-toplevel :load-toplevel :execute) + (defconstant ,name ,value) + ,(when export (list 'export `(quote ,name))) + ',name)) + +(defmacro def-type (name type) + "Generates a (deftype) statement for CL. Currently, only CMUCL +supports takes advantage of this optimization." + #+(or lispworks allegro openmcl digitool cormanlisp) (declare (ignore type)) + #+(or lispworks allegro openmcl digitool cormanlisp) `(deftype ,name () t) + #+(or cmu scl) + `(deftype ,name () '(alien:alien ,(convert-from-uffi-type type :declare))) + #+sbcl + `(deftype ,name () '(sb-alien:alien ,(convert-from-uffi-type type :declare))) + ) + +(defmacro null-char-p (val) + "Returns T if character is NULL" + `(zerop ,val)) + +(defmacro def-foreign-type (name type) + #+lispworks `(fli:define-c-typedef ,name ,(convert-from-uffi-type type :type)) + #+allegro `(ff:def-foreign-type ,name ,(convert-from-uffi-type type :type)) + #+(or cmu scl) `(alien:def-alien-type ,name ,(convert-from-uffi-type type :type)) + #+sbcl `(sb-alien:define-alien-type ,name ,(convert-from-uffi-type type :type)) + #+cormanlisp `(ct:defctype ,name ,(convert-from-uffi-type type :type)) + #+(or openmcl digitool) + (let ((mcl-type (convert-from-uffi-type type :type))) + (unless (or (keywordp mcl-type) (consp mcl-type)) + (setf mcl-type `(quote ,mcl-type))) + #+digitool + `(def-mcl-type ,(keyword name) ,mcl-type) + #+openmcl + `(ccl::def-foreign-type ,(keyword name) ,mcl-type)) + ) + +(eval-when (:compile-toplevel :load-toplevel :execute) + (defvar +type-conversion-hash+ (make-hash-table :size 20 :test #'eq)) + #+(or cmu sbcl scl) (defvar *cmu-def-type-hash* + (make-hash-table :size 20 :test #'eq)) + ) + +#+(or cmu scl) +(defvar *cmu-sbcl-def-type-list* + '((:char . (alien:signed 8)) + (:unsigned-char . (alien:unsigned 8)) + (:byte . (alien:signed 8)) + (:unsigned-byte . (alien:unsigned 8)) + (:short . (alien:signed 16)) + (:unsigned-short . (alien:unsigned 16)) + (:int . (alien:signed 32)) + (:unsigned-int . (alien:unsigned 32)) + #-x86-64 (:long . (alien:signed 32)) + #-x86-64 (:unsigned-long . (alien:unsigned 32)) + #+x86-64 (:long . (alien:signed 64)) + #+x86-64 (:unsigned-long . (alien:unsigned 64)) + (:float . alien:single-float) + (:double . alien:double-float) + (:void . t) + ) + "Conversions in CMUCL for def-foreign-type are different than in def-function") + +#+sbcl +(defvar *cmu-sbcl-def-type-list* + '((:char . (sb-alien:signed 8)) + (:unsigned-char . (sb-alien:unsigned 8)) + (:byte . (sb-alien:signed 8)) + (:unsigned-byte . (sb-alien:unsigned 8)) + (:short . (sb-alien:signed 16)) + (:unsigned-short . (sb-alien:unsigned 16)) + (:int . (sb-alien:signed 32)) + (:unsigned-int . (sb-alien:unsigned 32)) + #-x86-64 (:long . (sb-alien:signed 32)) + #-x86-64 (:unsigned-long . (sb-alien:unsigned 32)) + #+x86-64 (:long . (sb-alien:signed 64)) + #+x86-64 (:unsigned-long . (sb-alien:unsigned 64)) + (:float . sb-alien:single-float) + (:double . sb-alien:double-float) + (:void . t) + ) + "Conversions in SBCL for def-foreign-type are different than in def-function") + +(defvar *type-conversion-list* nil) + +#+(or cmu scl) +(setq *type-conversion-list* + '((* . *) (:void . c-call:void) + (:pointer-void . (* t)) + (:cstring . c-call:c-string) + (:char . c-call:char) + (:unsigned-char . (alien:unsigned 8)) + (:byte . (alien:signed 8)) + (:unsigned-byte . (alien:unsigned 8)) + (:short . c-call:short) + (:unsigned-short . c-call:unsigned-short) + (:int . alien:integer) (:unsigned-int . c-call:unsigned-int) + (:long . c-call:long) (:unsigned-long . c-call:unsigned-long) + (:float . c-call:float) (:double . c-call:double) + (:array . alien:array))) + +#+sbcl +(setq *type-conversion-list* + '((* . *) (:void . sb-alien:void) + (:pointer-void . (* t)) + #-sb-unicode(:cstring . sb-alien:c-string) + #+sb-unicode(:cstring . sb-alien:utf8-string) + (:char . sb-alien:char) + (:unsigned-char . (sb-alien:unsigned 8)) + (:byte . (sb-alien:signed 8)) + (:unsigned-byte . (sb-alien:unsigned 8)) + (:short . sb-alien:short) + (:unsigned-short . sb-alien:unsigned-short) + (:int . sb-alien:int) (:unsigned-int . sb-alien:unsigned-int) + (:long . sb-alien:long) (:unsigned-long . sb-alien:unsigned-long) + (:float . sb-alien:float) (:double . sb-alien:double) + (:array . sb-alien:array))) + +#+(or allegro cormanlisp) +(setq *type-conversion-list* + '((* . *) (:void . :void) + (:short . :short) + (:pointer-void . (* :void)) + (:cstring . (* :unsigned-char)) + (:byte . :char) + (:unsigned-byte . :unsigned-char) + (:char . :char) + (:unsigned-char . :unsigned-char) + (:int . :int) (:unsigned-int . :unsigned-int) + (:long . :long) (:unsigned-long . :unsigned-long) + (:float . :float) (:double . :double) + (:array . :array))) + +#+lispworks +(setq *type-conversion-list* + '((* . :pointer) (:void . :void) + (:short . :short) + (:pointer-void . (:pointer :void)) + (:cstring . (:reference-pass (:ef-mb-string :external-format + (:latin-1 :eol-style :lf)) + :allow-null t)) + (:cstring-returning . (:reference (:ef-mb-string :external-format + (:latin-1 :eol-style :lf)) + :allow-null t)) + (:byte . :byte) + (:unsigned-byte . (:unsigned :byte)) + (:char . :char) + (:unsigned-char . (:unsigned :char)) + (:int . :int) (:unsigned-int . (:unsigned :int)) + (:long . :long) (:unsigned-long . (:unsigned :long)) + (:float . :float) (:double . :double) + (:array . :c-array))) + +#+digitool +(setq *type-conversion-list* + '((* . :pointer) (:void . :void) + (:short . :short) (:unsigned-short . :unsigned-short) + (:pointer-void . :pointer) + (:cstring . :string) + (:char . :character) + (:unsigned-char . :unsigned-byte) + (:byte . :signed-byte) (:unsigned-byte . :unsigned-byte) + (:int . :long) (:unsigned-int . :unsigned-long) + (:long . :long) (:unsigned-long . :unsigned-long) + (:float . :single-float) (:double . :double-float) + (:array . :array))) + +#+openmcl +(setq *type-conversion-list* + '((* . :address) (:void . :void) + (:short . :short) (:unsigned-short . :unsigned-short) + (:pointer-void . :address) + (:cstring . :address) + (:char . :signed-char) + (:unsigned-char . :unsigned-char) + (:byte . :signed-byte) (:unsigned-byte . :unsigned-byte) + (:int . :int) (:unsigned-int . :unsigned-int) + (:long . :long) (:unsigned-long . :unsigned-long) + (:long-long . :signed-doubleword) (:unsigned-long-long . :unsigned-doubleword) + (:float . :single-float) (:double . :double-float) + (:array . :array))) + +(dolist (type *type-conversion-list*) + (setf (gethash (car type) +type-conversion-hash+) (cdr type))) + +#+(or cmu sbcl scl) +(dolist (type *cmu-sbcl-def-type-list*) + (setf (gethash (car type) *cmu-def-type-hash*) (cdr type))) + +(defun basic-convert-from-uffi-type (type) + (let ((found-type (gethash type +type-conversion-hash+))) + (if found-type + found-type + #-(or openmcl digitool) type + #+(or openmcl digitool) (keyword type)))) + +(defun %convert-from-uffi-type (type context) + "Converts from a uffi type to an implementation specific type" + (if (atom type) + (cond + #+(or allegro cormanlisp) + ((and (or (eq context :routine) (eq context :return)) + (eq type :cstring)) + (setq type '((* :char) integer))) + #+(or cmu sbcl scl) + ((eq context :type) + (let ((cmu-type (gethash type *cmu-def-type-hash*))) + (if cmu-type + cmu-type + (basic-convert-from-uffi-type type)))) + #+lispworks + ((and (eq context :return) + (eq type :cstring)) + (basic-convert-from-uffi-type :cstring-returning)) + #+digitool + ((and (eq type :void) (eq context :return)) nil) + (t + (basic-convert-from-uffi-type type))) + (let ((sub-type (car type))) + (case sub-type + (cl:quote + (convert-from-uffi-type (cadr type) context)) + (:struct-pointer + #+(or openmcl digitool) `(:* (:struct ,(%convert-from-uffi-type (cadr type) :struct))) + #-(or openmcl digitool) (%convert-from-uffi-type (list '* (cadr type)) :struct) + ) + (:struct + #+(or openmcl digitool) `(:struct ,(%convert-from-uffi-type (cadr type) :struct)) + #-(or openmcl digitool) (%convert-from-uffi-type (cadr type) :struct) + ) + (:union + #+(or openmcl digitool) `(:union ,(%convert-from-uffi-type (cadr type) :union)) + #-(or openmcl digitool) (%convert-from-uffi-type (cadr type) :union) + ) + (t + (cons (%convert-from-uffi-type (first type) context) + (%convert-from-uffi-type (rest type) context))))))) + +(defun convert-from-uffi-type (type context) + (let ((result (%convert-from-uffi-type type context))) + (cond + ((atom result) result) + #+openmcl + ((eq (car result) :address) + (if (eq context :struct) + (append '(:*) (cdr result)) + :address)) + #+digitool + ((and (eq (car result) :pointer) (eq context :allocation) :pointer)) + (t result)))) + +(eval-when (:compile-toplevel :load-toplevel :execute) + (when (char= #\a (schar (symbol-name '#:a) 0)) + (pushnew :uffi-lowercase-reader *features*)) + (when (not (string= (symbol-name '#:a) + (symbol-name '#:A))) + (pushnew :uffi-case-sensitive *features*))) + +(defun make-lisp-name (name) + (let ((converted (substitute #\- #\_ name))) + (intern + #+uffi-case-sensitive converted + #+(and (not uffi-lowercase-reader) (not uffi-case-sensitive)) (string-upcase converted) + #+(and uffi-lowercase-reader (not uffi-case-sensitive)) (string-downcase converted)))) + +(eval-when (:compile-toplevel :load-toplevel :execute) + (setq cl:*features* (delete :uffi-lowercase-reader *features*)) + (setq cl:*features* (delete :uffi-case-sensitive *features*))) Added: branches/trunk-reorg/thirdparty/uffi-1.6.0/src/readmacros-mcl.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi-1.6.0/src/readmacros-mcl.lisp Mon Feb 11 09:23:05 2008 @@ -0,0 +1,35 @@ +;;;; -*- Mode: Lisp; Syntax: ANSI-Common-Lisp; Base: 10; Package: UFFI -*- +;;;; ************************************************************************* +;;;; FILE IDENTIFICATION +;;;; +;;;; Name: readmacros-mcl.lisp +;;;; Purpose: This file holds functions using read macros for MCL +;;;; Programmer: Kevin M. Rosenberg/John Desoi +;;;; Date Started: Feb 2002 +;;;; +;;;; $Id: readmacros-mcl.lisp 10917 2006-04-18 00:07:09Z kevin $ +;;;; +;;;; This file, part of UFFI, is Copyright (c) 2002-2005 by Kevin M. Rosenberg +;;;; +;;;; ************************************************************************* + +(in-package #:uffi) + + +;; trap macros don't work right directly in the macros +#+digitool +(defun new-ptr (size) + (#_NewPtr size)) + +#+digitool +(defun dispose-ptr (ptr) + (#_DisposePtr ptr)) + +#+openmcl +(defmacro new-ptr (size) + `(ccl::malloc ,size)) + +#+openmcl +(defmacro dispose-ptr (ptr) + `(ccl::free ,ptr)) + Added: branches/trunk-reorg/thirdparty/uffi-1.6.0/src/strings.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi-1.6.0/src/strings.lisp Mon Feb 11 09:23:05 2008 @@ -0,0 +1,412 @@ +;;;; -*- Mode: Lisp; Syntax: ANSI-Common-Lisp; Base: 10; Package: UFFI -*- +;;;; ************************************************************************* +;;;; FILE IDENTIFICATION +;;;; +;;;; Name: strings.lisp +;;;; Purpose: UFFI source to handle strings, cstring and foreigns +;;;; Programmer: Kevin M. Rosenberg +;;;; Date Started: Feb 2002 +;;;; +;;;; $Id: strings.lisp 11023 2006-08-14 06:25:09Z kevin $ +;;;; +;;;; This file, part of UFFI, is Copyright (c) 2002-2005 by Kevin M. Rosenberg +;;;; ************************************************************************* + +(in-package #:uffi) + + +(def-pointer-var +null-cstring-pointer+ + #+(or cmu sbcl scl) nil + #+allegro 0 + #+lispworks (fli:make-pointer :address 0 :type '(:unsigned :char)) + #+(or openmcl digitool) (ccl:%null-ptr) +) + +(defmacro convert-from-cstring (obj) + "Converts a string from a c-call. Same as convert-from-foreign-string, except +that LW/CMU automatically converts strings from c-calls." + #+(or cmu sbcl lispworks scl) obj + #+allegro + (let ((stored (gensym))) + `(let ((,stored ,obj)) + (if (zerop ,stored) + nil + (values (excl:native-to-string ,stored))))) + #+(or openmcl digitool) + (let ((stored (gensym))) + `(let ((,stored ,obj)) + (if (ccl:%null-ptr-p ,stored) + nil + (values (ccl:%get-cstring ,stored))))) + ) + +(defmacro convert-to-cstring (obj) + #+(or cmu sbcl scl lispworks) obj + #+allegro + (let ((stored (gensym))) + `(let ((,stored ,obj)) + (if (null ,stored) + 0 + (values (excl:string-to-native ,stored))))) + #+(or openmcl digitool) + (let ((stored (gensym))) + `(let ((,stored ,obj)) + (if (null ,stored) + +null-cstring-pointer+ + (let ((ptr (new-ptr (1+ (length ,stored))))) + (ccl::%put-cstring ptr ,stored) + ptr)))) + ) + +(defmacro free-cstring (obj) + #+(or cmu sbcl scl lispworks) (declare (ignore obj)) + #+allegro + (let ((stored (gensym))) + `(let ((,stored ,obj)) + (unless (zerop ,stored) + (ff:free-fobject ,stored)))) + #+(or openmcl digitool) + (let ((stored (gensym))) + `(let ((,stored ,obj)) + (unless (ccl:%null-ptr-p ,stored) + (dispose-ptr ,stored)))) + ) + +(defmacro with-cstring ((cstring lisp-string) &body body) + #+(or cmu sbcl scl lispworks) + `(let ((,cstring ,lisp-string)) , at body) + #+allegro + (let ((acl-native (gensym)) + (stored-lisp-string (gensym))) + `(let ((,stored-lisp-string ,lisp-string)) + (excl:with-native-string (,acl-native ,stored-lisp-string) + (let ((,cstring (if ,stored-lisp-string ,acl-native 0))) + , at body)))) + #+(or openmcl digitool) + (let ((stored-lisp-string (gensym))) + `(let ((,stored-lisp-string ,lisp-string)) + (if (stringp ,stored-lisp-string) + (ccl:with-cstrs ((,cstring ,stored-lisp-string)) + , at body) + (let ((,cstring +null-cstring-pointer+)) + , at body)))) + ) + +(defmacro with-cstrings (bindings &rest body) + (if bindings + `(with-cstring ,(car bindings) + (with-cstrings ,(cdr bindings) + , at body)) + `(progn , at body))) + +;;; Foreign string functions + +(defmacro convert-to-foreign-string (obj) + #+lispworks + (let ((stored (gensym))) + `(let ((,stored ,obj)) + (if (null ,stored) + +null-cstring-pointer+ + (fli:convert-to-foreign-string + ,stored + :external-format '(:latin-1 :eol-style :lf))))) + #+allegro + (let ((stored (gensym))) + `(let ((,stored ,obj)) + (if (null ,stored) + 0 + (values (excl:string-to-native ,stored))))) + #+(or cmu scl) + (let ((size (gensym)) + (storage (gensym)) + (stored-obj (gensym)) + (i (gensym))) + `(let ((,stored-obj ,obj)) + (etypecase ,stored-obj + (null + (alien:sap-alien (system:int-sap 0) (* (alien:unsigned 8)))) + (string + (let* ((,size (length ,stored-obj)) + (,storage (alien:make-alien (alien:unsigned 8) (1+ ,size)))) + (setq ,storage (alien:cast ,storage (* (alien:unsigned 8)))) + (locally + (declare (optimize (speed 3) (safety 0))) + (dotimes (,i ,size) + (declare (fixnum ,i)) + (setf (alien:deref ,storage ,i) + (char-code (char ,stored-obj ,i)))) + (setf (alien:deref ,storage ,size) 0)) + ,storage))))) + #+sbcl + (let ((size (gensym)) + (storage (gensym)) + (stored-obj (gensym)) + (i (gensym))) + `(let ((,stored-obj ,obj)) + (etypecase ,stored-obj + (null + (sb-alien:sap-alien (sb-sys:int-sap 0) (* (sb-alien:unsigned 8)))) + (string + (let* ((,size (length ,stored-obj)) + (,storage (sb-alien:make-alien (sb-alien:unsigned 8) (1+ ,size)))) + (setq ,storage (sb-alien:cast ,storage (* (sb-alien:unsigned 8)))) + (locally + (declare (optimize (speed 3) (safety 0))) + (dotimes (,i ,size) + (declare (fixnum ,i)) + (setf (sb-alien:deref ,storage ,i) + (char-code (char ,stored-obj ,i)))) + (setf (sb-alien:deref ,storage ,size) 0)) + ,storage))))) + #+(or openmcl digitool) + (let ((stored-obj (gensym))) + `(let ((,stored-obj ,obj)) + (if (null ,stored-obj) + +null-cstring-pointer+ + (let ((ptr (new-ptr (1+ (length ,stored-obj))))) + (ccl::%put-cstring ptr ,stored-obj) + ptr)))) + ) + +;; Either length or null-terminated-p must be non-nil +(defmacro convert-from-foreign-string (obj &key + length + (locale :default) + (null-terminated-p t)) + #+allegro + (let ((stored-obj (gensym))) + `(let ((,stored-obj ,obj)) + (if (zerop ,stored-obj) + nil + (if (eq ,locale :none) + (fast-native-to-string ,stored-obj ,length) + (values + (excl:native-to-string + ,stored-obj + ,@(when length (list :length length)) + :truncate (not ,null-terminated-p))))))) + #+lispworks + (let ((stored-obj (gensym))) + `(let ((,stored-obj ,obj)) + (if (fli:null-pointer-p ,stored-obj) + nil + (if (eq ,locale :none) + (fast-native-to-string ,stored-obj ,length) + (fli:convert-from-foreign-string + ,stored-obj + ,@(when length (list :length length)) + :null-terminated-p ,null-terminated-p + :external-format '(:latin-1 :eol-style :lf)))))) + #+(or cmu scl) + (let ((stored-obj (gensym))) + `(let ((,stored-obj ,obj)) + (if (null-pointer-p ,stored-obj) + nil + (cmucl-naturalize-cstring (alien:alien-sap ,stored-obj) + :length ,length + :null-terminated-p ,null-terminated-p)))) + + #+sbcl + (let ((stored-obj (gensym))) + `(let ((,stored-obj ,obj)) + (if (null-pointer-p ,stored-obj) + nil + (sbcl-naturalize-cstring (sb-alien:alien-sap ,stored-obj) + :length ,length + :null-terminated-p ,null-terminated-p)))) + #+(or openmcl digitool) + (declare (ignore null-terminated-p)) + #+(or openmcl digitool) + (let ((stored-obj (gensym))) + `(let ((,stored-obj ,obj)) + (if (ccl:%null-ptr-p ,stored-obj) + nil + #+digitool (ccl:%get-cstring + ,stored-obj 0 + ,@(if length (list length) nil)) + #+openmcl ,@(if length + `((ccl:%str-from-ptr ,stored-obj ,length)) + `((ccl:%get-cstring ,stored-obj)))))) + ) + + +(defmacro allocate-foreign-string (size &key (unsigned t)) + #+ignore + (let ((array-def (gensym))) + `(let ((,array-def (list 'alien:array 'c-call:char ,size))) + (eval `(alien:cast (alien:make-alien ,,array-def) + ,(if ,unsigned + '(* (alien:unsigned 8)) + '(* (alien:signed 8))))))) + + #+(or cmu scl) + `(alien:make-alien ,(if unsigned + '(alien:unsigned 8) + '(alien:signed 8)) + ,size) + + #+sbcl + `(sb-alien:make-alien ,(if unsigned + '(sb-alien:unsigned 8) + '(sb-alien:signed 8)) + ,size) + + #+lispworks + `(fli:allocate-foreign-object :type + ,(if unsigned + ''(:unsigned :char) + :char) + :nelems ,size) + #+allegro + (declare (ignore unsigned)) + #+allegro + `(ff:allocate-fobject :char :c ,size) + #+(or openmcl digitool) + (declare (ignore unsigned)) + #+(or openmcl digitool) + `(new-ptr ,size) + ) + +(defun foreign-string-length (foreign-string) + #+allegro `(ff:foreign-strlen ,foreign-string) + #-allegro + `(loop with size = 0 + until (char= (deref-array ,foreign-string '(:array :unsigned-char) size) #\Null) + do (incf size) + finally return size)) + + +(defmacro with-foreign-string ((foreign-string lisp-string) &body body) + (let ((result (gensym))) + `(let* ((,foreign-string (convert-to-foreign-string ,lisp-string)) + (,result (progn , at body))) + (declare (dynamic-extent ,foreign-string)) + (free-foreign-object ,foreign-string) + ,result))) + +(defmacro with-foreign-strings (bindings &body body) + `(with-foreign-string ,(car bindings) + ,@(if (cdr bindings) + `((with-foreign-strings ,(cdr bindings) , at body)) + body))) + +;; Modified from CMUCL's source to handle non-null terminated strings +#+cmu +(defun cmucl-naturalize-cstring (sap &key length (null-terminated-p t)) + (declare (type system:system-area-pointer sap)) + (locally + (declare (optimize (speed 3) (safety 0))) + (let ((null-terminated-length + (when null-terminated-p + (loop + for offset of-type fixnum upfrom 0 + until (zerop (system:sap-ref-8 sap offset)) + finally (return offset))))) + (if length + (if (and null-terminated-length + (> (the fixnum length) (the fixnum null-terminated-length))) + (setq length null-terminated-length)) + (setq length null-terminated-length))) + (let ((result (make-string length))) + (kernel:copy-from-system-area sap 0 + result (* vm:vector-data-offset + vm:word-bits) + (* length vm:byte-bits)) + result))) + +#+scl +;; kernel:copy-from-system-area doesn't work like it does on CMUCL or SBCL, +;; so have to iteratively copy from sap +(defun cmucl-naturalize-cstring (sap &key length (null-terminated-p t)) + (declare (type system:system-area-pointer sap)) + (locally + (declare (optimize (speed 3) (safety 0))) + (let ((null-terminated-length + (when null-terminated-p + (loop + for offset of-type fixnum upfrom 0 + until (zerop (system:sap-ref-8 sap offset)) + finally (return offset))))) + (if length + (if (and null-terminated-length + (> (the fixnum length) (the fixnum null-terminated-length))) + (setq length null-terminated-length)) + (setq length null-terminated-length))) + (let ((result (make-string length))) + (dotimes (i length) + (declare (type fixnum i)) + (setf (char result i) (code-char (system:sap-ref-8 sap i)))) + result))) + +#+(and sbcl (not sb-unicode)) +(defun sbcl-naturalize-cstring (sap &key length (null-terminated-p t)) + (declare (type sb-sys:system-area-pointer sap) + (type (or null fixnum) length)) + (locally + (declare (optimize (speed 3) (safety 0))) + (let ((null-terminated-length + (when null-terminated-p + (loop + for offset of-type fixnum upfrom 0 + until (zerop (sb-sys:sap-ref-8 sap offset)) + finally (return offset))))) + (if length + (if (and null-terminated-length + (> (the fixnum length) (the fixnum null-terminated-length))) + (setq length null-terminated-length)) + (setq length null-terminated-length))) + (let ((result (make-string length))) + (funcall *system-copy-fn* sap 0 result +system-copy-offset+ + (* length +system-copy-multiplier+)) + result))) + +#+(and sbcl sb-unicode) +(defun sbcl-naturalize-cstring (sap &key length (null-terminated-p t)) + (declare (type sb-sys:system-area-pointer sap) + (type (or null fixnum) length)) + (locally + (declare (optimize (speed 3) (safety 0))) + (cond + (null-terminated-p + (let ((casted (sb-alien:cast (sb-alien:sap-alien sap (* char)) + #+sb-unicode sb-alien:utf8-string + #-sb-unicode sb-alien:c-string))) + (if length + (copy-seq (subseq casted 0 length)) + (copy-seq casted)))) + (t + (let ((result (make-string length))) + ;; this will not work in sb-unicode + (funcall *system-copy-fn* sap 0 result +system-copy-offset+ + (* length +system-copy-multiplier+)) + result))))) + + +(eval-when (:compile-toplevel :load-toplevel :execute) + (def-function "strlen" + ((str (* :unsigned-char))) + :returning :unsigned-int)) + +(def-type char-ptr-def (* :unsigned-char)) + +#+(or (and allegro (not ics)) (and lispworks (not lispworks5))) +(defun fast-native-to-string (s len) + (declare (optimize (speed 3) (space 0) (safety 0) (compilation-speed 0)) + (type char-ptr-def s)) + (let* ((len (or len (strlen s))) + (str (make-string len))) + (declare (fixnum len) + (type (simple-array #+lispworks base-char + #-lispworks (signed-byte 8) (*)) str)) + (dotimes (i len str) + (setf (aref str i) + (uffi:deref-array s '(:array :char) i))))) + +#+(or (and allegro ics) lispworks5) +(defun fast-native-to-string (s len) + (declare (optimize (speed 3) (space 0) (safety 0) (compilation-speed 0)) + (type char-ptr-def s)) + (let* ((len (or len (strlen s))) + (str (make-string len))) + (dotimes (i len str) + (setf (schar str i) (code-char (uffi:deref-array s '(:array :unsigned-byte) i)))))) Added: branches/trunk-reorg/thirdparty/uffi-1.6.0/tests/Makefile ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi-1.6.0/tests/Makefile Mon Feb 11 09:23:05 2008 @@ -0,0 +1,30 @@ +# FILE IDENTIFICATION +# +# Name: Makefile +# Purpose: Makefile for UFFI examples +# Programer: Kevin M. Rosenberg +# Date Started: Mar 2002 +# +# CVS Id: $Id: Makefile 10614 2005-07-06 01:05:14Z kevin $ +# +# This file, part of UFFI, is Copyright (c) 2002-2005 by Kevin M. Rosenberg + +SUBDIRS= + +include ../Makefile.common + +base=uffi-c-test +source=$(base).c +object=$(base).o +shared_lib=$(base).so + +.PHONY: all +all: $(shared_lib) + +$(shared_lib): $(source) Makefile + BASE=$(base) OBJECT=$(object) SOURCE=$(source) SHARED_LIB=$(shared_lib) sh make.sh + rm $(object) + +.PHONY: distclean +distclean: clean + rm -f $(base).dylib $(base).dylib $(base).so $(base).o Added: branches/trunk-reorg/thirdparty/uffi-1.6.0/tests/Makefile.msvc ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi-1.6.0/tests/Makefile.msvc Mon Feb 11 09:23:05 2008 @@ -0,0 +1,28 @@ +# FILE IDENTIFICATION +# +# Name: Makefile.msvc +# Purpose: Makefile for the CLSQL UFFI helper package (MSVC) +# Programer: Kevin M. Rosenberg +# Date Started: Mar 2002 +# +# CVS Id: $Id: Makefile.msvc,v 1.1 2002/03/23 10:26:03 kevin Exp $ +# +# This file, part of CLSQL, is Copyright (c) 2002-2005 by Kevin M. Rosenberg +# + +BASE=c-test-fns + +# Nothing to configure beyond here + +SRC=$(BASE).c +OBJ=$(BASE).obj +DLL=$(BASE).dll + +$(DLL): $(SRC) + cl /MD /LD -D_MT /DWIN32=1 $(SRC) + del $(OBJ) $(BASE).exp + +clean: + del /q $(DLL) + + Added: branches/trunk-reorg/thirdparty/uffi-1.6.0/tests/arrays.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi-1.6.0/tests/arrays.lisp Mon Feb 11 09:23:05 2008 @@ -0,0 +1,57 @@ +;;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Base: 10 -*- +;;;; ************************************************************************* +;;;; FILE IDENTIFICATION +;;;; +;;;; Name: arrays.lisp +;;;; Purpose: UFFI test arrays +;;;; Author: Kevin M. Rosenberg +;;;; Date Started: Mar 2002 +;;;; +;;;; $Id: arrays.lisp 10608 2005-07-01 00:39:48Z kevin $ +;;;; +;;;; This file, part of UFFI, is Copyright (c) 2002-2005 by Kevin M. Rosenberg +;;;; +;;;; ************************************************************************* + +(in-package #:uffi-tests) + +(uffi:def-constant +column-length+ 10) +(uffi:def-constant +row-length+ 10) + +(uffi:def-foreign-type long-ptr (* :long)) + +(deftest :array.1 + (let ((a (uffi:allocate-foreign-object :long +column-length+)) + (results nil)) + (dotimes (i +column-length+) + (setf (uffi:deref-array a '(:array :long) i) (* i i))) + (dotimes (i +column-length+) + (push (uffi:deref-array a '(:array :long) i) results)) + (uffi:free-foreign-object a) + (nreverse results)) + (0 1 4 9 16 25 36 49 64 81)) + + +(deftest :array.2 + (let ((a (uffi:allocate-foreign-object 'long-ptr +row-length+)) + (results nil)) + (dotimes (r +row-length+) + (declare (fixnum r)) + (setf (uffi:deref-array a '(:array (* :long)) r) + (uffi:allocate-foreign-object :long +column-length+)) + (let ((col (uffi:deref-array a '(:array (* :long)) r))) + (dotimes (c +column-length+) + (declare (fixnum c)) + (setf (uffi:deref-array col '(:array :long) c) (+ (* r +column-length+) c))))) + + (dotimes (r +row-length+) + (declare (fixnum r)) + (let ((col (uffi:deref-array a '(:array (* :long)) r))) + (dotimes (c +column-length+) + (declare (fixnum c)) + (push (uffi:deref-array col '(:array :long) c) results)))) + (uffi:free-foreign-object a) + (nreverse results)) + (0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99)) + + Added: branches/trunk-reorg/thirdparty/uffi-1.6.0/tests/atoifl.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi-1.6.0/tests/atoifl.lisp Mon Feb 11 09:23:05 2008 @@ -0,0 +1,42 @@ +;;;; -*- Mode: Lisp; Syntax: ANSI-Common-Lisp; Base: 10 -*- +;;;; ************************************************************************* +;;;; FILE IDENTIFICATION +;;;; +;;;; Name: atoifl.lisp +;;;; Purpose: UFFI Example file to atoi/atof/atol +;;;; Programmer: Kevin M. Rosenberg +;;;; Date Started: Mar 2002 +;;;; +;;;; $Id: atoifl.lisp 10608 2005-07-01 00:39:48Z kevin $ +;;;; +;;;; This file, part of UFFI, is Copyright (c) 2002-2005 by Kevin M. Rosenberg +;;;; +;;;; ************************************************************************* + +(in-package #:uffi-tests) + +(uffi:def-function ("atoi" c-atoi) + ((str :cstring)) + :returning :int) + +(uffi:def-function ("atol" c-atol) + ((str :cstring)) + :returning :long) + +(uffi:def-function ("atof" c-atof) + ((str :cstring)) + :returning :double) + +(defun atoi (str) + "Returns a int from a string." + (uffi:with-cstring (str-cstring str) + (c-atoi str-cstring))) + +(defun atof (str) + "Returns a double float from a string." + (uffi:with-cstring (str-cstring str) + (c-atof str-cstring))) + +(deftest :atoi.1 (atoi "123") 123) +(deftest :atoi.2 (atoi "") 0) +(deftest :atof.3 (atof "2.23") 2.23d0) Added: branches/trunk-reorg/thirdparty/uffi-1.6.0/tests/casts.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi-1.6.0/tests/casts.lisp Mon Feb 11 09:23:05 2008 @@ -0,0 +1,51 @@ +;;;; -*- Mode: Lisp; Syntax: ANSI-Common-Lisp; Base: 10 -*- +;;;; ************************************************************************* +;;;; FILE IDENTIFICAION +;;;; +;;;; Name: casts.lisp +;;;; Purpose: Tests of with-cast-pointer +;;;; Programmer: Kevin M. Rosenberg / Edi Weitz +;;;; Date Started: Aug 2003 +;;;; +;;;; $Id: casts.lisp 10608 2005-07-01 00:39:48Z kevin $ +;;;; +;;;; This file, part of UFFI, is Copyright (c) 2003-2005 by Kevin M. Rosenberg +;;;; +;;;; ************************************************************************* + +(in-package #:uffi-tests) + +(uffi:def-function ("cast_test_int" cast-test-int) + () + :module "uffi_tests" + :returning :pointer-void) + +(uffi:def-function ("cast_test_float" cast-test-float) + () + :module "uffi_tests" + :returning :pointer-void) + +(deftest :cast.1 + (progn + (uffi:with-cast-pointer (temp (cast-test-int) :int) + (assert (= (uffi:deref-pointer temp :int) 23))) + (let ((result (cast-test-int))) + (uffi:with-cast-pointer (result2 result :int) + (assert (= (uffi:deref-pointer result2 :int) 23))) + (uffi:with-cast-pointer (temp result :int) + (assert (= (uffi:deref-pointer temp :int) 23)))) + t) + t) + +(deftest :cast.2 + (progn + (uffi:with-cast-pointer (temp (cast-test-float) :double) + (assert (= (uffi:deref-pointer temp :double) 3.21d0))) + (let ((result (cast-test-float))) + (uffi:with-cast-pointer (result2 result :double) + (assert (= (uffi:deref-pointer result2 :double) 3.21d0))) + (uffi:with-cast-pointer (temp result :double) + (assert (= (uffi:deref-pointer temp :double) 3.21d0)))) + t) + t) + Added: branches/trunk-reorg/thirdparty/uffi-1.6.0/tests/compress.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi-1.6.0/tests/compress.lisp Mon Feb 11 09:23:05 2008 @@ -0,0 +1,92 @@ +;;;; -*- Mode: Lisp; Syntax: ANSI-Common-Lisp; Base: 10 -*- +;;;; ************************************************************************* +;;;; FILE IDENTIFICATION +;;;; +;;;; Name: compress.lisp +;;;; Purpose: UFFI Example file for zlib compression +;;;; Author: Kevin M. Rosenberg +;;;; Date Started: Feb 2002 +;;;; +;;;; $Id: compress.lisp 10608 2005-07-01 00:39:48Z kevin $ +;;;; +;;;; This file, part of UFFI, is Copyright (c) 2002-2005 by Kevin M. Rosenberg +;;;; +;;;; ************************************************************************* + +(in-package #:uffi-tests) + +(uffi:def-function ("compress" c-compress) + ((dest (* :unsigned-char)) + (destlen (* :long)) + (source :cstring) + (source-len :long)) + :returning :int + :module "zlib") + +(defun compress (source) + "Returns two values: array of bytes containing the compressed data + and the numbe of compressed bytes" + (let* ((sourcelen (length source)) + (destsize (+ 12 (ceiling (* sourcelen 1.01)))) + (dest (uffi:allocate-foreign-string destsize :unsigned t)) + (destlen (uffi:allocate-foreign-object :long))) + (setf (uffi:deref-pointer destlen :long) destsize) + (uffi:with-cstring (source-native source) + (let ((result (c-compress dest destlen source-native sourcelen)) + (newdestlen (uffi:deref-pointer destlen :long))) + (unwind-protect + (if (zerop result) + (values (uffi:convert-from-foreign-usb8 + dest newdestlen) + newdestlen) + (error "zlib error, code ~D" result)) + (progn + (uffi:free-foreign-object destlen) + (uffi:free-foreign-object dest))))))) + +(uffi:def-function ("uncompress" c-uncompress) + ((dest (* :unsigned-char)) + (destlen (* :long)) + (source :cstring) + (source-len :long)) + :returning :int + :module "zlib") + +(defun uncompress (source) + (let* ((sourcelen (length source)) + (destsize 200000) ;adjust as needed + (dest (uffi:allocate-foreign-string destsize :unsigned t)) + (destlen (uffi:allocate-foreign-object :long))) + (setf (uffi:deref-pointer destlen :long) destsize) + (uffi:with-cstring (source-native source) + (let ((result (c-uncompress dest destlen source-native sourcelen)) + (newdestlen (uffi:deref-pointer destlen :long))) + (unwind-protect + (if (zerop result) + (uffi:convert-from-foreign-string + dest + :length newdestlen + :null-terminated-p nil) + (error "zlib error, code ~D" result)) + (progn + (uffi:free-foreign-object destlen) + (uffi:free-foreign-object dest))))))) + +(deftest :compress.1 (compress "") + #(120 156 3 0 0 0 0 1) 8) +(deftest :compress.2 (compress "test") + #(120 156 43 73 45 46 1 0 4 93 1 193) 12) +(deftest :compress.3 (compress "test2") + #(120 156 43 73 45 46 49 2 0 6 80 1 243) 13) + +(defun compress-uncompress (str) + (multiple-value-bind (compressed len) (compress str) + (declare (ignore len)) + (multiple-value-bind (uncompressed len2) (uncompress compressed) + (declare (ignore len2)) + uncompressed))) + + +(deftest :uncompress.1 "" "") +(deftest :uncompress.2 "test" "test") +(deftest :uncompress.3 "test2" "test2") Added: branches/trunk-reorg/thirdparty/uffi-1.6.0/tests/foreign-loader.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi-1.6.0/tests/foreign-loader.lisp Mon Feb 11 09:23:05 2008 @@ -0,0 +1,47 @@ +;;;; -*- Mode: Lisp; Syntax: ANSI-Common-Lisp; Base: 10 -*- +;;;; ************************************************************************* +;;;; FILE IDENTIFICATION +;;;; +;;;; Name: foreign-loader.lisp +;;;; Purpose: Loads foreign libraries +;;;; Author: Kevin M. Rosenberg +;;;; Date Started: Feb 2002 +;;;; +;;;; $Id: foreign-loader.lisp 11021 2006-08-14 04:22:28Z kevin $ +;;;; +;;;; This file, part of UFFI, is Copyright (c) 2002-2005 by Kevin M. Rosenberg +;;;; +;;;; ************************************************************************* + +;;; For CMUCL, it's necessary to load foreign files separate from their +;;; usage + +(in-package uffi-tests) + +#+clisp (uffi:load-foreign-library "/usr/lib/libz.so" :module "z") +#-clisp +(unless (uffi:load-foreign-library + (uffi:find-foreign-library + #-(or macosx darwin) + "libz" + #+(or macosx darwin) + "z" + (list (pathname-directory *load-pathname*) + "/usr/local/lib/" #+(or 64bit x86-64) "/usr/lib64/" + "/usr/lib/" "/zlib/")) + :module "zlib" + :supporting-libraries '("c")) + (warn "Unable to load zlib")) + +#+clisp (uffi:load-foreign-library "/home/kevin/debian/src/uffi/tests/uffi-c-test.so" :module "uffi_tests") +#-clisp +(unless (uffi:load-foreign-library + (uffi:find-foreign-library + '(#+(or 64bit x86-64) "uffi-c-test64" "uffi-c-test") + (list (pathname-directory *load-truename*) + "/usr/lib/uffi/" + "/home/kevin/debian/src/uffi/tests/")) + :supporting-libraries '("c") + :module "uffi_tests") + (warn "Unable to load uffi-c-test library")) + Added: branches/trunk-reorg/thirdparty/uffi-1.6.0/tests/foreign-var.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi-1.6.0/tests/foreign-var.lisp Mon Feb 11 09:23:05 2008 @@ -0,0 +1,88 @@ +;;;; -*- Mode: Lisp; Syntax: ANSI-Common-Lisp; Base: 10 -*- +;;;; ************************************************************************* +;;;; FILE IDENTIFICATION +;;;; +;;;; Name: foreign-var +;;;; Purpose: Tests of foreign variables +;;;; Authors: Kevin M. Rosenberg and Edi Weitz +;;;; Date Started: Aug 2003 +;;;; +;;;; $Id: foreign-var.lisp 10608 2005-07-01 00:39:48Z kevin $ +;;;; +;;;; This file, part of UFFI, is Copyright (c) 2003-2005 by Kevin M. Rosenberg +;;; +;;;; ************************************************************************* + +(in-package #:uffi-tests) + +(def-foreign-var "uchar_13" :unsigned-byte "uffi_tests") +(def-foreign-var "schar_neg_120" :byte "uffi_tests") +(def-foreign-var "uword_257" :unsigned-short "uffi_tests") +(def-foreign-var "sword_neg_321" :short "uffi_tests") +(def-foreign-var "uint_1234567" :int "uffi_tests") +(def-foreign-var "sint_neg_123456" :int "uffi_tests") +(def-foreign-var "float_neg_4_5" :float "uffi_tests") +(def-foreign-var "double_3_1" :double "uffi_tests") + +(deftest :fvar.1 uchar-13 13) +(deftest :fvar.2 schar-neg-120 -120) +(deftest :fvar.3 uword-257 257) +(deftest :fvar.4 sword-neg-321 -321) +(deftest :fvar.5 uint-1234567 1234567) +(deftest :fvar.6 sint-neg-123456 -123456) +(deftest :fvar.7 float-neg-4-5 -4.5f0) +(deftest :fvar.8 double-3-1 3.1d0) + +(uffi:def-foreign-var ("fvar_addend" *fvar-addend*) :int "uffi_tests") + +(uffi:def-struct fvar-struct + (i :int) + (d :double)) + +(uffi:def-foreign-var ("fvar_struct" *fvar-struct*) fvar-struct + "uffi_tests") + +(uffi:def-function ("fvar_struct_int" fvar-struct-int) + () + :returning :int + :module "uffi_tests") + + (uffi:def-function ("fvar_struct_double" fvar-struct-double) + () + :returning :double + :module "uffi_tests") + +(deftest :fvarst.1 *fvar-addend* 3) +(deftest :fvarst.2 (uffi:get-slot-value *fvar-struct* 'fvar-struct 'i) 42) +(deftest :fvarst.3 (= (+ *fvar-addend* + (uffi:get-slot-value *fvar-struct* 'fvar-struct 'i)) + (fvar-struct-int)) + t) +(deftest :fvarst.4 (uffi:get-slot-value *fvar-struct* 'fvar-struct 'd) 3.2d0) +(deftest :fvarst.5 (= (uffi:get-slot-value *fvar-struct* 'fvar-struct 'd) + (fvar-struct-double)) + t) + +(deftest fvarst.6 + (let ((orig *fvar-addend*)) + (incf *fvar-addend* 3) + (prog1 + *fvar-addend* + (setf *fvar-addend* orig))) + 6) + +(deftest fvarst.7 + (let ((orig *fvar-addend*)) + (incf *fvar-addend* 3) + (prog1 + (fvar-struct-int) + (setf *fvar-addend* orig))) + 48) + +(deftest fvarst.8 + (let ((orig (uffi:get-slot-value *fvar-struct* 'fvar-struct 'i))) + (decf (uffi:get-slot-value *fvar-struct* 'fvar-struct 'i) 10) + (prog1 + (fvar-struct-int) + (setf (uffi:get-slot-value *fvar-struct* 'fvar-struct 'i) orig))) + 35) Added: branches/trunk-reorg/thirdparty/uffi-1.6.0/tests/getenv.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi-1.6.0/tests/getenv.lisp Mon Feb 11 09:23:05 2008 @@ -0,0 +1,64 @@ +;;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Base: 10 -*- +;;;; ************************************************************************* +;;;; FILE IDENTIFICATION +;;;; +;;;; Name: getenv.lisp +;;;; Purpose: UFFI Example file to get environment variable +;;;; Programmer: Kevin M. Rosenberg +;;;; Date Started: Feb 2002 +;;;; +;;;; $Id: getenv.lisp 10608 2005-07-01 00:39:48Z kevin $ +;;;; +;;;; This file, part of UFFI, is Copyright (c) 2002-2005 by Kevin M. Rosenberg +;;;; +;;;; ************************************************************************* + +(in-package #:uffi-tests) + + +(uffi:def-function ("getenv" c-getenv) + ((name :cstring)) + :returning :cstring) + +(uffi:def-function ("setenv" c-setenv) + ((name :cstring) + (value :cstring) + (overwrite :int)) + :returning :int) + +(uffi:def-function ("unsetenv" c-unsetenv) + ((name :cstring)) + :returning :void) + +(defun my-getenv (key) + "Returns an environment variable, or NIL if it does not exist" + (check-type key string) + (uffi:with-cstring (key-native key) + (uffi:convert-from-cstring (c-getenv key-native)))) + +(defun my-setenv (key name &optional (overwrite t)) + "Returns an environment variable, or NIL if it does not exist" + (check-type key string) + (check-type name string) + (setq overwrite (if overwrite 1 0)) + (uffi:with-cstrings ((key-native key) + (name-native name)) + (c-setenv key-native name-native (if overwrite 1 0)))) + +(defun my-unsetenv (key) + "Returns an environment variable, or NIL if it does not exist" + (check-type key string) + (uffi:with-cstrings ((key-native key)) + (c-unsetenv key-native))) + +(deftest :getenv.1 (progn + (my-unsetenv "__UFFI_FOO1__") + (my-getenv "__UFFI_FOO1__")) + nil) +(deftest :getenv.2 (progn + (my-setenv "__UFFI_FOO1__" "UFFI-TEST") + (my-getenv "__UFFI_FOO1__")) + "UFFI-TEST") + + + Added: branches/trunk-reorg/thirdparty/uffi-1.6.0/tests/gethostname.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi-1.6.0/tests/gethostname.lisp Mon Feb 11 09:23:05 2008 @@ -0,0 +1,52 @@ +;;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Base: 10 -*- +;;;; ************************************************************************* +;;;; FILE IDENTIFICATION +;;;; +;;;; Name: gethostname.lisp +;;;; Purpose: UFFI Example file to get hostname of system +;;;; Programmer: Kevin M. Rosenberg +;;;; Date Started: Feb 2002 +;;;; +;;;; $Id: gethostname.lisp 10608 2005-07-01 00:39:48Z kevin $ +;;;; +;;;; This file, part of UFFI, is Copyright (c) 2002-2005 by Kevin M. Rosenberg +;;;; +;;;; ************************************************************************* + +(in-package #:uffi-tests) + + +;;; This example is inspired by the example on the CL-Cookbook web site + +(eval-when (:compile-toplevel :load-toplevel :execute) + (uffi:def-function ("gethostname" c-gethostname) + ((name (* :unsigned-char)) + (len :int)) + :returning :int) + + (defun gethostname () + "Returns the hostname" + (let* ((name (uffi:allocate-foreign-string 256)) + (result-code (c-gethostname name 256)) + (hostname (when (zerop result-code) + (uffi:convert-from-foreign-string name)))) + (uffi:free-foreign-object name) + (unless (zerop result-code) + (error "gethostname() failed.")) + hostname)) + + (defun gethostname2 () + "Returns the hostname" + (uffi:with-foreign-object (name '(:array :unsigned-char 256)) + (if (zerop (c-gethostname (uffi:char-array-to-pointer name) 256)) + (uffi:convert-from-foreign-string name) + (error "gethostname() failed."))))) + +(deftest :gethostname.1 (stringp (gethostname)) t) +(deftest :gethostname.2 (stringp (gethostname2)) t) +(deftest :gethostname.3 (plusp (length (gethostname))) t) +(deftest :gethostname.4 (plusp (length (gethostname2))) t) +(deftest :gethostname.5 (string= (gethostname) (gethostname2)) t) + + + Added: branches/trunk-reorg/thirdparty/uffi-1.6.0/tests/make.sh ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi-1.6.0/tests/make.sh Mon Feb 11 09:23:05 2008 @@ -0,0 +1,45 @@ +#!/bin/sh + +case "`uname`" in + Linux) os_linux=1 ;; + FreeBSD) os_freebsd=1 ;; + GNU/kFreeBSD) os_gnukfreebsd=1;; + Darwin) os_darwin=1 ;; + SunOS) os_sunos=1 ;; + AIX) os_aix=1 ;; + GNU) os_gnu=1 ;; + *) echo "Unable to identify uname " `uname` + exit 1 ;; +esac + +if [ "$os_linux" ]; then + gcc -fPIC -DPIC -c $SOURCE -o $OBJECT + gcc -shared $OBJECT -o $SHARED_LIB + +elif [ "$os_gnu" ]; then + gcc -fPIC -DPIC -c $SOURCE -o $OBJECT + gcc -shared $OBJECT -o $SHARED_LIB + +elif [ "$os_freebsd" ]; then + gcc -fPIC -DPIC -c $SOURCE -o $OBJECT + gcc -shared $OBJECT -o $SHARED_LIB + +elif [ "$os_gnukfreebsd" ]; then + gcc -fPIC -DPIC -c $SOURCE -o $OBJECT + gcc -shared $OBJECT -o $SHARED_LIB + +elif [ "$os_darwin" ]; then + cc -dynamic -c $SOURCE -o $OBJECT + ld -bundle /usr/lib/bundle1.o -flat_namespace -undefined suppress -o $BASE.dylib $OBJECT + ld -bundle /usr/lib/bundle1.o -flat_namespace -undefined suppress /usr/lib/libz.dylib -o z.dylib + +elif [ "$os_sunos" ]; then + cc -KPIC -c $SOURCE -o $OBJECT + cc -G $OBJECT -o $SHARED_LIB + +elif [ "$os_aix" ]; then + gcc -c -D_BSD -D_NO_PROTO -D_NONSTD_TYPES -D_MBI=void $SOURCE + make_shared -o $SHARED_LIB $OBJECT +fi + +exit 0 Added: branches/trunk-reorg/thirdparty/uffi-1.6.0/tests/objects.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi-1.6.0/tests/objects.lisp Mon Feb 11 09:23:05 2008 @@ -0,0 +1,70 @@ +;;;; -*- Mode: Lisp; Syntax: ANSI-Common-Lisp; Base: 10 -*- +;;;; ************************************************************************* +;;;; FILE IDENTIFICATION +;;;; +;;;; Name: pointers.lisp +;;;; Purpose: Test file for UFFI pointers +;;;; Programmer: Kevin M. Rosenberg +;;;; Date Started: Aug 2003 +;;;; +;;;; $Id: objects.lisp 10608 2005-07-01 00:39:48Z kevin $ +;;;; +;;;; This file, part of UFFI, is Copyright (c) 2003-2005 by Kevin M. Rosenberg +;;;; +;;;; ************************************************************************* + +(in-package #:uffi-tests) + +(deftest :chptr.1 + (let ((native-string "test string")) + (uffi:with-foreign-string (fs native-string) + (ensure-char-character + (deref-pointer fs :char)))) + #\t) + +(deftest :chptr.2 + (let ((native-string "test string")) + (uffi:with-foreign-string (fs native-string) + (ensure-char-character + (deref-pointer fs :unsigned-char)))) + #\t) + +(deftest :chptr.3 + (let ((native-string "test string")) + (uffi:with-foreign-string (fs native-string) + (ensure-char-integer + (deref-pointer fs :unsigned-char)))) + 116) + +(deftest :chptr.4 + (let ((native-string "test string")) + (uffi:with-foreign-string (fs native-string) + (integerp + (ensure-char-integer + (deref-pointer fs :unsigned-char))))) + t) + +(deftest :chptr.5 + (let ((fs (uffi:allocate-foreign-object :unsigned-char 128))) + (setf (uffi:deref-array fs '(:array :unsigned-char) 0) + (uffi:ensure-char-storable #\a)) + (setf (uffi:deref-array fs '(:array :unsigned-char) 1) + (uffi:ensure-char-storable (code-char 0))) + (uffi:convert-from-foreign-string fs)) + "a") + +;; This produces an array which needs fli:foreign-aref to access +;; rather than fli:dereference + +#-lispworks +(deftest :chptr.6 + (uffi:with-foreign-object (fs '(:array :unsigned-char 128)) + (setf (uffi:deref-array fs '(:array :unsigned-char) 0) + (uffi:ensure-char-storable #\a)) + (setf (uffi:deref-array fs '(:array :unsigned-char) 1) + (uffi:ensure-char-storable (code-char 0))) + (uffi:convert-from-foreign-string fs)) + "a") + + + Added: branches/trunk-reorg/thirdparty/uffi-1.6.0/tests/package.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi-1.6.0/tests/package.lisp Mon Feb 11 09:23:05 2008 @@ -0,0 +1,20 @@ +;;;; -*- Mode: Lisp; Syntax: ANSI-Common-Lisp; Base: 10 -*- +;;;; ************************************************************************* +;;;; FILE IDENTIFICATION +;;;; +;;;; Name: package.lisp +;;;; Purpose: Package file uffi testing suite +;;;; Author: Kevin M. Rosenberg +;;;; Date Started: Apr 2003 +;;;; +;;;; This file, part of UFFI, is Copyright (c) 2003-2005 by Kevin M. Rosenberg +;;;; +;;;; $Id: package.lisp 10608 2005-07-01 00:39:48Z kevin $ +;;;; ************************************************************************* + +(defpackage #:uffi-tests + (:use #:asdf #:cl #:uffi #:rtest) + (:shadowing-import-from #:uffi #:run-shell-command)) + +(in-package #:uffi-tests) + Added: branches/trunk-reorg/thirdparty/uffi-1.6.0/tests/rt.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi-1.6.0/tests/rt.lisp Mon Feb 11 09:23:05 2008 @@ -0,0 +1,254 @@ +#|----------------------------------------------------------------------------| + | Copyright 1990 by the Massachusetts Institute of Technology, Cambridge MA. | + | | + | Permission to use, copy, modify, and distribute this software and its | + | documentation for any purpose and without fee is hereby granted, provided | + | that this copyright and permission notice appear in all copies and | + | supporting documentation, and that the name of M.I.T. not be used in | + | advertising or publicity pertaining to distribution of the software | + | without specific, written prior permission. M.I.T. makes no | + | representations about the suitability of this software for any purpose. | + | It is provided "as is" without express or implied warranty. | + | | + | M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING | + | ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL | + | M.I.T. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR | + | ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, | + | WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, | + | ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS | + | SOFTWARE. | + |----------------------------------------------------------------------------|# + +(defpackage #:regression-test + (:nicknames #:rtest #-lispworks #:rt) + (:use #:cl) + (:export #:*do-tests-when-defined* #:*test* #:continue-testing + #:deftest #:do-test #:do-tests #:get-test #:pending-tests + #:rem-all-tests #:rem-test) + (:documentation "The MIT regression tester with pfdietz's modifications")) + +(in-package :regression-test) + +(defvar *test* nil "Current test name") +(defvar *do-tests-when-defined* nil) +(defvar *entries* '(nil) "Test database") +(defvar *in-test* nil "Used by TEST") +(defvar *debug* nil "For debugging") +(defvar *catch-errors* t + "When true, causes errors in a test to be caught.") +(defvar *print-circle-on-failure* nil + "Failure reports are printed with *PRINT-CIRCLE* bound to this value.") +(defvar *compile-tests* nil + "When true, compile the tests before running them.") +(defvar *optimization-settings* '((safety 3))) +(defvar *expected-failures* nil + "A list of test names that are expected to fail.") + +(defstruct (entry (:conc-name nil) + (:type list)) + pend name form) + +(defmacro vals (entry) `(cdddr ,entry)) + +(defmacro defn (entry) `(cdr ,entry)) + +(defun pending-tests () + (do ((l (cdr *entries*) (cdr l)) + (r nil)) + ((null l) (nreverse r)) + (when (pend (car l)) + (push (name (car l)) r)))) + +(defun rem-all-tests () + (setq *entries* (list nil)) + nil) + +(defun rem-test (&optional (name *test*)) + (do ((l *entries* (cdr l))) + ((null (cdr l)) nil) + (when (equal (name (cadr l)) name) + (setf (cdr l) (cddr l)) + (return name)))) + +(defun get-test (&optional (name *test*)) + (defn (get-entry name))) + +(defun get-entry (name) + (let ((entry (find name (cdr *entries*) + :key #'name + :test #'equal))) + (when (null entry) + (report-error t + "~%No test with name ~:@(~S~)." + name)) + entry)) + +(defmacro deftest (name form &rest values) + `(add-entry '(t ,name ,form .,values))) + +(defun add-entry (entry) + (setq entry (copy-list entry)) + (do ((l *entries* (cdr l))) (nil) + (when (null (cdr l)) + (setf (cdr l) (list entry)) + (return nil)) + (when (equal (name (cadr l)) + (name entry)) + (setf (cadr l) entry) + (report-error nil + "Redefining test ~:@(~S~)" + (name entry)) + (return nil))) + (when *do-tests-when-defined* + (do-entry entry)) + (setq *test* (name entry))) + +(defun report-error (error? &rest args) + (cond (*debug* + (apply #'format t args) + (if error? (throw '*debug* nil))) + (error? (apply #'error args)) + (t (apply #'warn args)))) + +(defun do-test (&optional (name *test*)) + (do-entry (get-entry name))) + +(defun equalp-with-case (x y) + "Like EQUALP, but doesn't do case conversion of characters." + (cond + ((eq x y) t) + ((consp x) + (and (consp y) + (equalp-with-case (car x) (car y)) + (equalp-with-case (cdr x) (cdr y)))) + ((and (typep x 'array) + (= (array-rank x) 0)) + (equalp-with-case (aref x) (aref y))) + ((typep x 'vector) + (and (typep y 'vector) + (let ((x-len (length x)) + (y-len (length y))) + (and (eql x-len y-len) + (loop + for e1 across x + for e2 across y + always (equalp-with-case e1 e2)))))) + ((and (typep x 'array) + (typep y 'array) + (not (equal (array-dimensions x) + (array-dimensions y)))) + nil) + ((typep x 'array) + (and (typep y 'array) + (let ((size (array-total-size x))) + (loop for i from 0 below size + always (equalp-with-case (row-major-aref x i) + (row-major-aref y i)))))) + (t (eql x y)))) + +(defun do-entry (entry &optional + (s *standard-output*)) + (catch '*in-test* + (setq *test* (name entry)) + (setf (pend entry) t) + (let* ((*in-test* t) + ;; (*break-on-warnings* t) + (aborted nil) + r) + ;; (declare (special *break-on-warnings*)) + + (block aborted + (setf r + (flet ((%do + () + (if *compile-tests* + (multiple-value-list + (funcall (compile + nil + `(lambda () + (declare + (optimize ,@*optimization-settings*)) + ,(form entry))))) + (multiple-value-list + (eval (form entry)))))) + (if *catch-errors* + (handler-bind + ((style-warning #'muffle-warning) + (error #'(lambda (c) + (setf aborted t) + (setf r (list c)) + (return-from aborted nil)))) + (%do)) + (%do))))) + + (setf (pend entry) + (or aborted + (not (equalp-with-case r (vals entry))))) + + (when (pend entry) + (let ((*print-circle* *print-circle-on-failure*)) + (format s "~&Test ~:@(~S~) failed~ + ~%Form: ~S~ + ~%Expected value~P: ~ + ~{~S~^~%~17t~}~%" + *test* (form entry) + (length (vals entry)) + (vals entry)) + (format s "Actual value~P: ~ + ~{~S~^~%~15t~}.~%" + (length r) r))))) + (when (not (pend entry)) *test*)) + +(defun continue-testing () + (if *in-test* + (throw '*in-test* nil) + (do-entries *standard-output*))) + +(defun do-tests (&optional + (out *standard-output*)) + (dolist (entry (cdr *entries*)) + (setf (pend entry) t)) + (if (streamp out) + (do-entries out) + (with-open-file + (stream out :direction :output) + (do-entries stream)))) + +(defun do-entries (s) + (format s "~&Doing ~A pending test~:P ~ + of ~A tests total.~%" + (count t (cdr *entries*) + :key #'pend) + (length (cdr *entries*))) + (dolist (entry (cdr *entries*)) + (when (pend entry) + (format s "~@[~<~%~:; ~:@(~S~)~>~]" + (do-entry entry s)))) + (let ((pending (pending-tests)) + (expected-table (make-hash-table :test #'equal))) + (dolist (ex *expected-failures*) + (setf (gethash ex expected-table) t)) + (let ((new-failures + (loop for pend in pending + unless (gethash pend expected-table) + collect pend))) + (if (null pending) + (format s "~&No tests failed.") + (progn + (format s "~&~A out of ~A ~ + total tests failed: ~ + ~:@(~{~<~% ~1:;~S~>~ + ~^, ~}~)." + (length pending) + (length (cdr *entries*)) + pending) + (if (null new-failures) + (format s "~&No unexpected failures.") + (when *expected-failures* + (format s "~&~A unexpected failures: ~ + ~:@(~{~<~% ~1:;~S~>~ + ~^, ~}~)." + (length new-failures) + new-failures))) + )) + (null pending)))) Added: branches/trunk-reorg/thirdparty/uffi-1.6.0/tests/strtol.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi-1.6.0/tests/strtol.lisp Mon Feb 11 09:23:05 2008 @@ -0,0 +1,64 @@ +;;;; -*- Mode: Lisp; Syntax: ANSI-Common-Lisp; Base: 10 -*- +;;;; ************************************************************************* +;;;; FILE IDENTIFICATION +;;;; +;;;; Name: strtol.lisp +;;;; Purpose: UFFI Example file to strtol, uses pointer arithmetic +;;;; Programmer: Kevin M. Rosenberg +;;;; Date Started: Feb 2002 +;;;; +;;;; $Id: strtol.lisp 10608 2005-07-01 00:39:48Z kevin $ +;;;; +;;;; This file, part of UFFI, is Copyright (c) 2002-2005 by Kevin M. Rosenberg +;;;; +;;;; ************************************************************************* + +(in-package #:uffi-tests) + +(uffi:def-foreign-type char-ptr (* :unsigned-char)) + +;; This example does not use :cstring to pass the input string since +;; the routine needs to do pointer arithmetic to see how many characters +;; were parsed + +(uffi:def-function ("strtol" c-strtol) + ((nptr char-ptr) + (endptr (* char-ptr)) + (base :int)) + :returning :long) + +(defun strtol (str &optional (base 10)) + "Returns a long int from a string. Returns number and condition flag. +Condition flag is T if all of string parses as a long, NIL if +their was no string at all, or an integer indicating position in string +of first non-valid character" + (let* ((str-native (uffi:convert-to-foreign-string str)) + (endptr (uffi:allocate-foreign-object 'char-ptr)) + (value (c-strtol str-native endptr base)) + (endptr-value (uffi:deref-pointer endptr 'char-ptr))) + + (unwind-protect + (if (uffi:null-pointer-p endptr-value) + (values value t) + (let ((next-char-value (uffi:deref-pointer endptr-value :unsigned-char)) + (chars-parsed (- (uffi:pointer-address endptr-value) + (uffi:pointer-address str-native)))) + (cond + ((zerop chars-parsed) + (values nil nil)) + ((uffi:null-char-p next-char-value) + (values value t)) + (t + (values value chars-parsed))))) + (progn + (uffi:free-foreign-object str-native) + (uffi:free-foreign-object endptr))))) + +(deftest :strtol.1 (strtol "123") 123 t) +(deftest :strtol.2 (strtol "0") 0 t) +(deftest :strtol.3 (strtol "55a") 55 2) +(deftest :strtol.4 (strtol "a") nil nil) + + + + Added: branches/trunk-reorg/thirdparty/uffi-1.6.0/tests/structs.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi-1.6.0/tests/structs.lisp Mon Feb 11 09:23:05 2008 @@ -0,0 +1,36 @@ +;;;; -*- Mode: Lisp; Syntax: ANSI-Common-Lisp; Base: 10 -*- +;;;; ************************************************************************* +;;;; FILE IDENTIFICATION +;;;; +;;;; Name: structs.lisp +;;;; Purpose: Test file for UFFI structures +;;;; Programmer: Kevin M. Rosenberg +;;;; Date Started: Feb 2002 +;;;; +;;;; $Id: structs.lisp 10608 2005-07-01 00:39:48Z kevin $ +;;;; +;;;; This file, part of UFFI, is Copyright (c) 2002-2005 by Kevin M. Rosenberg +;;;; +;;;; ************************************************************************* + +(in-package #:uffi-tests) + +;; Compilation failure as reported by Edi Weitz + + +(uffi:def-struct foo + (bar :pointer-self)) + +(uffi:def-foreign-type foo-ptr (* foo)) + +;; tests that compilation worked +(deftest :structs.1 + (with-foreign-object (p 'foo) + t) + t) + +(deftest :structs.2 + (progn + (uffi:def-foreign-type foo-struct (:struct foo)) + t) + t) Added: branches/trunk-reorg/thirdparty/uffi-1.6.0/tests/time.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi-1.6.0/tests/time.lisp Mon Feb 11 09:23:05 2008 @@ -0,0 +1,110 @@ +;;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Base: 10 -*- +;;;; ************************************************************************* +;;;; FILE IDENTIFICATION +;;;; +;;;; Name: time.lisp +;;;; Purpose: UFFI test file, time, use C structures +;;;; Author: Kevin M. Rosenberg +;;;; Date Started: Feb 2002 +;;;; +;;;; $Id: time.lisp 10608 2005-07-01 00:39:48Z kevin $ +;;;; +;;;; This file, part of UFFI, is Copyright (c) 2002-2005 by Kevin M. Rosenberg +;;;; +;;;; ************************************************************************* + +(in-package #:uffi-tests) + +(uffi:def-foreign-type time-t :unsigned-long) + +(uffi:def-struct tm + (sec :int) + (min :int) + (hour :int) + (mday :int) + (mon :int) + (year :int) + (wday :int) + (yday :int) + (isdst :int) + ;; gmoffset present on SusE SLES9 + (gmoffset :long)) + +(uffi:def-function ("time" c-time) + ((time (* time-t))) + :returning time-t) + +(uffi:def-function "gmtime" + ((time (* time-t))) + :returning (:struct-pointer tm)) + +(uffi:def-function "asctime" + ((time (:struct-pointer tm))) + :returning :cstring) + +(uffi:def-type time-t :unsigned-long) +(uffi:def-type tm-pointer (:struct-pointer tm)) + +(deftest :time.1 + (uffi:with-foreign-object (time 'time-t) + (setf (uffi:deref-pointer time :unsigned-long) 7381) + (uffi:deref-pointer time :unsigned-long)) + 7381) + +(deftest :time.2 + (uffi:with-foreign-object (time 'time-t) + (setf (uffi:deref-pointer time :unsigned-long) 7381) + (let ((tm-ptr (the tm-pointer (gmtime time)))) + (values (1+ (uffi:get-slot-value tm-ptr 'tm 'mon)) + (uffi:get-slot-value tm-ptr 'tm 'mday) + (+ 1900 (uffi:get-slot-value tm-ptr 'tm 'year)) + (uffi:get-slot-value tm-ptr 'tm 'hour) + (uffi:get-slot-value tm-ptr 'tm 'min) + (uffi:get-slot-value tm-ptr 'tm 'sec) + ))) + 1 1 1970 2 3 1) + + +(uffi:def-struct timeval + (secs :long) + (usecs :long)) + +(uffi:def-struct timezone + (minutes-west :int) + (dsttime :int)) + +(uffi:def-function ("gettimeofday" c-gettimeofday) + ((tv (* timeval)) + (tz (* timezone))) + :returning :int) + +(defun get-utime () + (uffi:with-foreign-object (tv 'timeval) + (let ((res (c-gettimeofday tv (uffi:make-null-pointer 'timezone)))) + (values + (+ (* 1000000 (uffi:get-slot-value tv 'timeval 'secs)) + (uffi:get-slot-value tv 'timeval 'usecs)) + res)))) + +(deftest :timeofday.1 + (multiple-value-bind (t1 res1) (get-utime) + (multiple-value-bind (t2 res2) (get-utime) + (and (or (= t2 t1) (> t2 t1)) + (> t1 1000000000) + (> t2 1000000000) + (zerop res1) + (zerop res2)))) + t) + +(defun posix-time-to-asctime (secs) + "Converts number of seconds elapsed since 00:00:00 on January 1, 1970, Coordinated Universal Time (UTC)" + (string-right-trim + '(#\newline #\return) + (uffi:convert-from-cstring + (uffi:with-foreign-object (time 'time-t) + (setf (uffi:deref-pointer time :unsigned-long) secs) + (asctime (gmtime time)))))) + +(deftest :time.3 + (posix-time-to-asctime 0) + "Thu Jan 1 00:00:00 1970") Added: branches/trunk-reorg/thirdparty/uffi-1.6.0/tests/uffi-c-test-lib.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi-1.6.0/tests/uffi-c-test-lib.lisp Mon Feb 11 09:23:05 2008 @@ -0,0 +1,98 @@ +;;;; -*- Mode: Lisp; Syntax: ANSI-Common-Lisp; Base: 10 -*- +;;;; ************************************************************************* +;;;; FILE IDENTIFICATION +;;;; +;;;; Name: uffi-c-test-lib.lisp +;;;; Purpose: UFFI Example file for zlib compression +;;;; Programmer: Kevin M. Rosenberg +;;;; Date Started: Mar 2002 +;;;; +;;;; $Id: uffi-c-test-lib.lisp 10608 2005-07-01 00:39:48Z kevin $ +;;;; +;;;; This file, part of UFFI, is Copyright (c) 2002-2005 by Kevin M. Rosenberg +;;;; +;;;; ************************************************************************* + +(in-package #:uffi-tests) + + +(uffi:def-function ("cs_to_upper" cs-to-upper) + ((input (* :unsigned-char))) + :returning :void + :module "uffi_tests") + +(defun string-to-upper (str) + (uffi:with-foreign-string (str-foreign str) + (cs-to-upper str-foreign) + (uffi:convert-from-foreign-string str-foreign))) + +(uffi:def-function ("cs_count_upper" cs-count-upper) + ((input :cstring)) + :returning :int + :module "uffi_tests") + +(defun string-count-upper (str) + (uffi:with-cstring (str-cstring str) + (cs-count-upper str-cstring))) + +(uffi:def-function ("half_double_vector" half-double-vector) + ((size :int) + (vec (* :double))) + :returning :void + :module "uffi_tests") + +(uffi:def-function ("return_long_negative_one" return-long-negative-one) + () + :returning :long + :module "uffi_tests") + +(uffi:def-function ("return_int_negative_one" return-int-negative-one) + () + :returning :int + :module "uffi_tests") + +(uffi:def-function ("return_short_negative_one" return-short-negative-one) + () + :returning :short + :module "uffi_tests") + + +(uffi:def-constant +double-vec-length+ 10) +(defun test-half-double-vector () + (let ((vec (uffi:allocate-foreign-object :double +double-vec-length+)) + results) + (dotimes (i +double-vec-length+) + (setf (uffi:deref-array vec '(:array :double) i) + (coerce i 'double-float))) + (half-double-vector +double-vec-length+ vec) + (dotimes (i +double-vec-length+) + (push (uffi:deref-array vec '(:array :double) i) results)) + (uffi:free-foreign-object vec) + (nreverse results))) + +(defun t2 () + (let ((vec (make-array +double-vec-length+ :element-type 'double-float))) + (dotimes (i +double-vec-length+) + (setf (aref vec i) (coerce i 'double-float))) + (half-double-vector +double-vec-length+ vec) + vec)) + +#+(or cmu scl) +(defun t3 () + (let ((vec (make-array +double-vec-length+ :element-type 'double-float))) + (dotimes (i +double-vec-length+) + (setf (aref vec i) (coerce i 'double-float))) + (system:without-gcing + (half-double-vector +double-vec-length+ (system:vector-sap vec))) + vec)) + +(deftest :c-test.1 (string-to-upper "this is a test") "THIS IS A TEST") +(deftest :c-test.2 (string-to-upper nil) nil) +(deftest :c-test.3 (string-count-upper "This is a Test") 2) +(deftest :c-test.4 (string-count-upper nil) -1) +(deftest :c-test.5 (test-half-double-vector) + (0.0d0 0.5d0 1.0d0 1.5d0 2.0d0 2.5d0 3.0d0 3.5d0 4.0d0 4.5d0)) +(deftest :c-test.6 (return-long-negative-one) -1) +(deftest :c-test.7 (return-int-negative-one) -1) +(deftest :c-test.8 (return-short-negative-one) -1) + Added: branches/trunk-reorg/thirdparty/uffi-1.6.0/tests/uffi-c-test.c ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi-1.6.0/tests/uffi-c-test.c Mon Feb 11 09:23:05 2008 @@ -0,0 +1,158 @@ +/*************************************************************************** + * FILE IDENTIFICATION + * + * Name: c-test-fns.c + * Purpose: Test functions in C for UFFI library + * Programer: Kevin M. Rosenberg + * Date Started: Mar 2002 + * + * CVS Id: $Id: uffi-c-test.c 10614 2005-07-06 01:05:14Z kevin $ + * + * This file, part of UFFI, is Copyright (c) 2002-2005 by Kevin M. Rosenberg + * + * These variables are correct for GCC + * you'll need to modify these for other compilers + ***************************************************************************/ + +#ifdef WIN32 +#include + +BOOL WINAPI DllEntryPoint(HINSTANCE hinstdll, + DWORD fdwReason, + LPVOID lpvReserved) +{ + return 1; +} + +#define DLLEXPORT __declspec(dllexport) + +#else +#define DLLEXPORT +#endif + +#include +#include +#include + + +DLLEXPORT unsigned char uchar_13 = 13; +DLLEXPORT signed char schar_neg_120 = -120; +DLLEXPORT unsigned short uword_257 = 257; +DLLEXPORT signed short sword_neg_321 = -321; +DLLEXPORT unsigned int uint_1234567 = 1234567; +DLLEXPORT signed int sint_neg_123456 = -123456; +DLLEXPORT double double_3_1 = 3.1; +DLLEXPORT float float_neg_4_5 = -4.5; + +/* Test of constant input string */ +DLLEXPORT +int +cs_count_upper (char* psz) +{ + int count = 0; + + if (psz) { + while (*psz) { + if (isupper (*psz)) + ++count; + ++psz; + } + return count; + } else + return -1; +} + +/* Test of input and output of a string */ +DLLEXPORT +void +cs_to_upper (char* psz) +{ + if (psz) { + while (*psz) { + *psz = toupper (*psz); + ++psz; + } + } +} + +/* Test of an output only string */ +DLLEXPORT +void +cs_make_random (int size, char* buffer) +{ + int i; + for (i = 0; i < size; i++) + buffer[i] = 'A' + (rand() % 26); +} + + +/* Test of input/output vector */ +DLLEXPORT +void +half_double_vector (int size, double* vec) +{ + int i; + for (i = 0; i < size; i++) + vec[i] /= 2.; +} + + + +DLLEXPORT +void * +cast_test_int () { + int *x = (int *) malloc(sizeof(int)); + *x = 23; + return x; +} + +DLLEXPORT +void * +cast_test_float () +{ + double *y = (double *) malloc(sizeof(double)); + *y = 3.21; + return y; +} + +DLLEXPORT +long +return_long_negative_one () +{ + return -1; +} + +DLLEXPORT +int +return_int_negative_one () +{ + return -1; +} + +DLLEXPORT +short +return_short_negative_one () +{ + return -1; +} + +DLLEXPORT int fvar_addend = 3; + +typedef struct { + int i; + double d; +} fvar_struct_type; + +fvar_struct_type fvar_struct = {42, 3.2}; + +DLLEXPORT +int fvar_struct_int () { + return (fvar_addend + fvar_struct.i); +} + +DLLEXPORT +double fvar_struct_double () { + return fvar_struct.d; +} + + Added: branches/trunk-reorg/thirdparty/uffi-1.6.0/tests/union.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi-1.6.0/tests/union.lisp Mon Feb 11 09:23:05 2008 @@ -0,0 +1,71 @@ +;;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Base: 10 -*- +;;;; ************************************************************************* +;;;; FILE IDENTIFICATION +;;;; +;;;; Name: union.lisp +;;;; Purpose: UFFI Example file to test unions +;;;; Programmer: Kevin M. Rosenberg +;;;; Date Started: Mar 2002 +;;;; +;;;; $Id: union.lisp 10917 2006-04-18 00:07:09Z kevin $ +;;;; +;;;; This file, part of UFFI, is Copyright (c) 2002-2005 by Kevin M. Rosenberg +;;;; +;;;; ************************************************************************* + +(in-package #:uffi-tests) + +(uffi:def-union tunion1 + (char :char) + (int :int) + (uint :unsigned-int) + (sf :float) + (df :double)) + +(defvar *u* (uffi:allocate-foreign-object 'tunion1)) +(setf (uffi:get-slot-value *u* 'tunion1 'uint) + #-(or sparc sparc-v9 powerpc ppc) + (+ (* 1 (char-code #\A)) + (* 256 (char-code #\B)) + (* 65536 (char-code #\C)) + (* 16777216 128)) + #+(or sparc sparc-v9 powerpc ppc) + (+ (* 16777216 (char-code #\A)) + (* 65536 (char-code #\B)) + (* 256 (char-code #\C)) + (* 1 128))) + +(deftest :union.1 + (uffi:ensure-char-character + (uffi:get-slot-value *u* 'tunion1 'char)) + #\A) + +(deftest :union.2 + (uffi:ensure-char-integer + (uffi:get-slot-value *u* 'tunion1 'char)) + 65) + +#-(or sparc sparc-v9 openmcl digitool) +(deftest :union.3 (plusp (uffi:get-slot-value *u* 'tunion1 'uint)) t) + + +(uffi:def-union foo-u + (bar :pointer-self)) + +(uffi:def-foreign-type foo-u-ptr (* foo-u)) + +;; tests that compilation worked +(deftest :unions.4 + (with-foreign-object (p 'foo-u) + t) + t) + +(deftest :unions.5 + (progn + (uffi:def-foreign-type foo-union (:union foo-u)) + t) + t) + + + + Added: branches/trunk-reorg/thirdparty/uffi-1.6.0/uffi-tests.asd ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi-1.6.0/uffi-tests.asd Mon Feb 11 09:23:05 2008 @@ -0,0 +1,95 @@ +;;;; -*- Mode: Lisp; Syntax: ANSI-Common-Lisp; Base: 10 -*- +;;;; ************************************************************************* +;;;; FILE IDENTIFICATION +;;;; +;;;; Name: uffi-tests.asd +;;;; Purpose: ASDF system definitionf for uffi testing package +;;;; Author: Kevin M. Rosenberg +;;;; Date Started: Apr 2003 +;;;; +;;;; $Id: uffi-tests.asd 10586 2005-06-08 21:51:30Z kevin $ +;;;; ************************************************************************* + +(defpackage #:uffi-tests-system + (:use #:asdf #:cl)) +(in-package #:uffi-tests-system) + +(operate 'load-op 'uffi) + +(defvar *library-file-dir* (append (pathname-directory *load-truename*) + (list "tests"))) + +(defclass uffi-test-source-file (c-source-file) + ()) + +(defmethod output-files ((o compile-op) (c uffi-test-source-file)) + (let* ((library-file-type + (funcall (intern (symbol-name'#:default-foreign-library-type) + (symbol-name '#:uffi)))) + (found + (some #'(lambda (dir) + (probe-file (make-pathname + :directory dir + :name (component-name c) + :type library-file-type))) + '((:absolute "usr" "lib" "uffi"))))) + (list (if found + found + (make-pathname :name (component-name c) + :type library-file-type + :directory *library-file-dir*))))) + +(defmethod perform ((o load-op) (c uffi-test-source-file)) + nil) ;;; library will be loaded by a loader file + +(defmethod operation-done-p ((o load-op) (c uffi-test-source-file)) + (and (symbol-function (intern (symbol-name '#:cs-count-upper) + (find-package '#:uffi-tests))) + t)) + +(defmethod perform ((o compile-op) (c uffi-test-source-file)) + (unless (operation-done-p o c) + #-(or win32 mswindows) + (unless (zerop (run-shell-command + #-freebsd "cd ~A; make" + #+freebsd "cd ~A; gmake" + (namestring (make-pathname :name nil + :type nil + :directory *library-file-dir*)))) + (error 'operation-error :component c :operation o)))) + +(defmethod operation-done-p ((o compile-op) (c uffi-test-source-file)) + (or (and (probe-file #p"/usr/lib/uffi/uffi-c-test.so") t) + (let ((lib (make-pathname :defaults (component-pathname c) + :type (uffi:default-foreign-library-type)))) + (and (probe-file lib) + (> (file-write-date lib) (file-write-date (component-pathname c))))))) + +(defsystem uffi-tests + :depends-on (:uffi) + :components + ((:module tests + :components + ((:file "rt") + (:file "package" :depends-on ("rt")) + (:uffi-test-source-file "uffi-c-test" :depends-on ("package")) + (:file "strtol" :depends-on ("package")) + (:file "atoifl" :depends-on ("package")) + (:file "getenv" :depends-on ("package")) + (:file "gethostname" :depends-on ("package")) + (:file "union" :depends-on ("package")) + (:file "arrays" :depends-on ("package")) + (:file "structs" :depends-on ("package")) + (:file "objects" :depends-on ("package")) + (:file "time" :depends-on ("package")) + (:file "foreign-loader" :depends-on ("package" "uffi-c-test")) + (:file "uffi-c-test-lib" :depends-on ("foreign-loader")) + (:file "compress" :depends-on ("foreign-loader")) + (:file "casts" :depends-on ("foreign-loader")) + (:file "foreign-var" :depends-on ("foreign-loader")) + )))) + +(defmethod perform ((o test-op) (c (eql (find-system :uffi-tests)))) + (or (funcall (intern (symbol-name '#:do-tests) + (find-package '#:regression-test))) + (error "test-op failed"))) Added: branches/trunk-reorg/thirdparty/uffi-1.6.0/uffi.asd ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/uffi-1.6.0/uffi.asd Mon Feb 11 09:23:05 2008 @@ -0,0 +1,48 @@ +;;;; -*- Mode: Lisp; Syntax: ANSI-Common-Lisp; Base: 10 -*- +;;;; ************************************************************************* +;;;; FILE IDENTIFICATION +;;;; +;;;; Name: uffi.asd +;;;; Purpose: ASDF system definition file for UFFI package +;;;; Author: Kevin M. Rosenberg +;;;; Date Started: Aug 2002 +;;;; +;;;; $Id: uffi.asd 10917 2006-04-18 00:07:09Z kevin $ +;;;; +;;;; This file, part of UFFI, is Copyright (c) 2002-2005 by Kevin M. Rosenberg +;;;; +;;;; ************************************************************************* + +(defpackage #:uffi-system (:use #:asdf #:cl)) +(in-package #:uffi-system) + +#+(or allegro lispworks cmu openmcl digitool cormanlisp sbcl scl) +(defsystem uffi + :name "uffi" + :author "Kevin Rosenberg " + :version "1.2.x" + :maintainer "Kevin M. Rosenberg " + :licence "Lessor Lisp General Public License" + :description "Universal Foreign Function Library for Common Lisp" + :long-description "UFFI provides a universal foreign function interface (FFI) for Common Lisp. UFFI supports CMUCL, Lispworks, and AllegroCL." + + :components + ((:module :src + :components + ((:file "package") + (:file "primitives" :depends-on ("package")) + #+(or openmcl digitool) (:file "readmacros-mcl" :depends-on ("package")) + (:file "objects" :depends-on ("primitives")) + (:file "aggregates" :depends-on ("primitives")) + (:file "strings" :depends-on ("primitives" "functions" "aggregates" "objects")) + (:file "functions" :depends-on ("primitives")) + (:file "libraries" :depends-on ("package")) + (:file "os" :depends-on ("package")))) + )) + +#+(or allegro lispworks cmu openmcl digitool cormanlisp sbcl scl) +(defmethod perform ((o test-op) (c (eql (find-system 'uffi)))) + (oos 'load-op 'uffi-tests) + (oos 'test-op 'uffi-tests :force t)) + + From hhubner at common-lisp.net Mon Feb 11 14:25:00 2008 From: hhubner at common-lisp.net (hhubner at common-lisp.net) Date: Mon, 11 Feb 2008 09:25:00 -0500 (EST) Subject: [bknr-cvs] r2475 - in branches/trunk-reorg/thirdparty/slime: . CVS contrib contrib/CVS Message-ID: <20080211142500.2D6EA7A00B@common-lisp.net> Author: hhubner Date: Mon Feb 11 09:24:55 2008 New Revision: 2475 Modified: branches/trunk-reorg/thirdparty/slime/CVS/Entries branches/trunk-reorg/thirdparty/slime/ChangeLog branches/trunk-reorg/thirdparty/slime/contrib/CVS/Entries branches/trunk-reorg/thirdparty/slime/contrib/ChangeLog branches/trunk-reorg/thirdparty/slime/contrib/slime-fancy-inspector.el branches/trunk-reorg/thirdparty/slime/contrib/slime-fancy.el branches/trunk-reorg/thirdparty/slime/contrib/swank-fancy-inspector.lisp branches/trunk-reorg/thirdparty/slime/slime.el branches/trunk-reorg/thirdparty/slime/swank-abcl.lisp branches/trunk-reorg/thirdparty/slime/swank-allegro.lisp branches/trunk-reorg/thirdparty/slime/swank-backend.lisp branches/trunk-reorg/thirdparty/slime/swank-clisp.lisp branches/trunk-reorg/thirdparty/slime/swank-cmucl.lisp branches/trunk-reorg/thirdparty/slime/swank-corman.lisp branches/trunk-reorg/thirdparty/slime/swank-ecl.lisp branches/trunk-reorg/thirdparty/slime/swank-lispworks.lisp branches/trunk-reorg/thirdparty/slime/swank-openmcl.lisp branches/trunk-reorg/thirdparty/slime/swank-sbcl.lisp branches/trunk-reorg/thirdparty/slime/swank-scl.lisp branches/trunk-reorg/thirdparty/slime/swank.lisp Log: update slime from cvs Modified: branches/trunk-reorg/thirdparty/slime/CVS/Entries ============================================================================== --- branches/trunk-reorg/thirdparty/slime/CVS/Entries (original) +++ branches/trunk-reorg/thirdparty/slime/CVS/Entries Mon Feb 11 09:24:55 2008 @@ -1,7 +1,6 @@ D/contrib//// D/doc//// /.cvsignore/1.5/Thu Oct 11 14:10:25 2007// -/ChangeLog/1.1282/Thu Feb 7 08:07:30 2008// /HACKING/1.8/Thu Oct 11 14:10:25 2007// /NEWS/1.9/Sun Dec 2 04:22:09 2007// /PROBLEMS/1.8/Thu Oct 11 14:10:25 2007// @@ -12,24 +11,25 @@ /nregex.lisp/1.4/Thu Oct 11 14:10:25 2007// /sbcl-pprint-patch.lisp/1.1/Thu Oct 11 14:10:25 2007// /slime-autoloads.el/1.4/Thu Feb 7 08:07:30 2008// -/slime.el/1.901/Thu Feb 7 08:07:31 2008// -/swank-abcl.lisp/1.45/Thu Feb 7 08:07:31 2008// -/swank-allegro.lisp/1.99/Thu Feb 7 08:07:31 2008// -/swank-backend.lisp/1.127/Thu Feb 7 08:07:31 2008// -/swank-clisp.lisp/1.65/Thu Feb 7 08:07:31 2008// -/swank-cmucl.lisp/1.176/Thu Feb 7 08:07:31 2008// -/swank-corman.lisp/1.13/Thu Feb 7 08:07:31 2008// -/swank-ecl.lisp/1.12/Thu Feb 7 08:07:31 2008// /swank-gray.lisp/1.10/Thu Oct 11 14:10:25 2007// -/swank-lispworks.lisp/1.94/Thu Feb 7 08:07:31 2008// /swank-loader.lisp/1.77/Thu Feb 7 08:07:31 2008// -/swank-openmcl.lisp/1.122/Thu Feb 7 08:07:31 2008// -/swank-sbcl.lisp/1.189/Thu Feb 7 08:07:31 2008// -/swank-scl.lisp/1.15/Thu Feb 7 08:07:31 2008// /swank-source-file-cache.lisp/1.8/Thu Oct 11 14:10:25 2007// /swank-source-path-parser.lisp/1.18/Thu Feb 7 07:59:36 2008// /swank.asd/1.5/Thu Oct 11 14:10:25 2007// -/swank.lisp/1.527/Thu Feb 7 08:07:31 2008// /test-all.sh/1.2/Thu Oct 11 14:10:25 2007// /test.sh/1.9/Thu Oct 11 14:10:25 2007// /xref.lisp/1.2/Thu Oct 11 14:10:25 2007// +/ChangeLog/1.1289/Mon Feb 11 14:20:11 2008// +/slime.el/1.904/Mon Feb 11 14:20:11 2008// +/swank-abcl.lisp/1.47/Mon Feb 11 14:20:11 2008// +/swank-allegro.lisp/1.101/Mon Feb 11 14:20:11 2008// +/swank-backend.lisp/1.129/Mon Feb 11 14:20:11 2008// +/swank-clisp.lisp/1.67/Mon Feb 11 14:20:11 2008// +/swank-cmucl.lisp/1.178/Mon Feb 11 14:20:11 2008// +/swank-corman.lisp/1.15/Mon Feb 11 14:20:11 2008// +/swank-ecl.lisp/1.14/Mon Feb 11 14:20:11 2008// +/swank-lispworks.lisp/1.97/Mon Feb 11 14:20:11 2008// +/swank-openmcl.lisp/1.124/Mon Feb 11 14:20:11 2008// +/swank-sbcl.lisp/1.191/Mon Feb 11 14:20:11 2008// +/swank-scl.lisp/1.18/Mon Feb 11 14:20:11 2008// +/swank.lisp/1.531/Mon Feb 11 14:20:11 2008// Modified: branches/trunk-reorg/thirdparty/slime/ChangeLog ============================================================================== --- branches/trunk-reorg/thirdparty/slime/ChangeLog (original) +++ branches/trunk-reorg/thirdparty/slime/ChangeLog Mon Feb 11 09:24:55 2008 @@ -1,3 +1,78 @@ +2008-02-10 Helmut Eller + + Remove remaining traces of make-default-inspector. + + * swank-scl.lisp (make-default-inspector, scl-inspector): Deleted. + * swank-lispworks.lisp (make-default-inspector) + (lispworks-inspector): Deleted. + +2008-02-09 Helmut Eller + + Drop the first return value of emacs-inspect. + + * swank.lisp (emacs-inspect): Drop the first return value. It + wasn't used anymore. Update all methods and callers. + +2008-02-09 Helmut Eller + + Remove obsolete *slime-inspect-contents-limit*. + + * swank.lisp (*slime-inspect-contents-limit*): Deleted and all its + uses. The new implementation isn't specific to hash-tables or + arrays. + +2008-02-09 Helmut Eller + + Limit the length of the inspector content. + That's similar to the limitation of the length of backtraces in + the debugger. + + * swank.lisp (*inspectee-content*): New variable. + (content-range): New function. + (inspect-object): Use it with a length of 1000. + (inspector-range): New function. Called from Emacs. + + * slime.el (slime-inspector-insert-content) + (slime-inspector-insert-range, slime-inspector-insert-range-button) + (slime-inspector-fetch-range): New functions. + (slime-inspector-operate-on-point): Handle range-buttons. + +2008-02-09 Helmut Eller + + Make slime-property-bounds more useful. + + * slime.el (slime-property-bounds): Remove special casing for + whitespace at the end. + (slime-repl-send-input): Don't mark the newline with the + slime-repl-old-input property. + (sldb-frame-region): Use slime-property-bounds. + +2008-02-09 Helmut Eller + + Inspector cleanups. + + * swank.lisp (emacs-inspect): Renamed from inspect-for-emacs. + Changed all method-defs accordingly. + (common-seperated-spec, inspector-princ): Moved to + swank-fancy-inspector.lisp. + (inspector-content): Renamed from inspector-content-for-emacs. + (value-part): Renamed from value-part-for-emacs. + (action-part): Renamed from action-part-for-emacs. + (inspect-list): Renamed from inspect-for-emacs-list. + (inspect-list-aux): New. + (inspect-cons): Renamed from inspect-for-emacs-simple-cons. + (*inspect-length*): Deleted. + (inspect-list): Ignore max-length stuff. + (inspector-content): Don't allow nil elements. + (emacs-inspect array): Make the label of element type more + consistent with the others. + +2008-02-09 Helmut Eller + + Cleanup slime-repl-set-package. + + * slime.el (slime-repl-set-package): Make it fit within 80 columns. + 2008-02-05 Marco Baringer * slime.el (slime-search-buffer-package): Ask the lisp to read the Modified: branches/trunk-reorg/thirdparty/slime/contrib/CVS/Entries ============================================================================== --- branches/trunk-reorg/thirdparty/slime/contrib/CVS/Entries (original) +++ branches/trunk-reorg/thirdparty/slime/contrib/CVS/Entries Mon Feb 11 09:24:55 2008 @@ -1,4 +1,3 @@ -/ChangeLog/1.87/Thu Feb 7 08:07:31 2008// /README/1.3/Thu Oct 11 14:10:25 2007// /bridge.el/1.1/Thu Oct 11 14:10:25 2007// /inferior-slime.el/1.2/Thu Oct 11 14:10:25 2007// @@ -7,8 +6,6 @@ /slime-banner.el/1.4/Thu Oct 11 14:10:25 2007// /slime-c-p-c.el/1.8/Thu Oct 11 14:10:25 2007// /slime-editing-commands.el/1.6/Thu Feb 7 07:59:35 2008// -/slime-fancy-inspector.el/1.2/Thu Oct 11 14:10:25 2007// -/slime-fancy.el/1.4/Thu Oct 11 14:10:25 2007// /slime-fuzzy.el/1.6/Thu Feb 7 07:59:35 2008// /slime-highlight-edits.el/1.3/Thu Oct 11 14:10:25 2007// /slime-indentation.el/1.1/Sun Feb 3 18:45:14 2008// @@ -25,7 +22,6 @@ /swank-arglists.lisp/1.20/Thu Feb 7 08:07:31 2008// /swank-asdf.lisp/1.1/Thu Oct 11 14:10:25 2007// /swank-c-p-c.lisp/1.2/Thu Oct 11 14:10:25 2007// -/swank-fancy-inspector.lisp/1.7/Thu Feb 7 08:07:32 2008// /swank-fuzzy.lisp/1.7/Thu Feb 7 07:59:35 2008// /swank-goo.goo/1.1/Thu Feb 7 08:07:32 2008// /swank-indentation.lisp/1.1/Sun Feb 3 18:45:14 2008// @@ -34,4 +30,8 @@ /swank-motd.lisp/1.1/Sun Feb 3 18:39:23 2008// /swank-presentation-streams.lisp/1.5/Thu Feb 7 08:07:32 2008// /swank-presentations.lisp/1.4/Thu Oct 11 14:10:25 2007// +/ChangeLog/1.89/Mon Feb 11 14:20:11 2008// +/slime-fancy-inspector.el/1.3/Mon Feb 11 14:20:11 2008// +/slime-fancy.el/1.5/Mon Feb 11 14:20:11 2008// +/swank-fancy-inspector.lisp/1.11/Mon Feb 11 14:20:11 2008// D Modified: branches/trunk-reorg/thirdparty/slime/contrib/ChangeLog ============================================================================== --- branches/trunk-reorg/thirdparty/slime/contrib/ChangeLog (original) +++ branches/trunk-reorg/thirdparty/slime/contrib/ChangeLog Mon Feb 11 09:24:55 2008 @@ -1,3 +1,16 @@ +2008-02-10 Helmut Eller + + Fix some bugs introduced by the recent reorganization. + + * swank-fancy-inspector.lisp (emacs-inspect pathname): Fix it + again. + + * slime-fancy-inspector.el: Use slime-require. + + * slime-fancy.el: slime-fancy-inspector-init no longer exists, so + don't call it. Once loaded, it's also no longer possible to turn + the fancy inspector off. + 2008-02-04 Marco Baringer * swank-presentation-streams.lisp (presenting-object-1): Add Modified: branches/trunk-reorg/thirdparty/slime/contrib/slime-fancy-inspector.el ============================================================================== --- branches/trunk-reorg/thirdparty/slime/contrib/slime-fancy-inspector.el (original) +++ branches/trunk-reorg/thirdparty/slime/contrib/slime-fancy-inspector.el Mon Feb 11 09:24:55 2008 @@ -3,26 +3,7 @@ ;; Author: Marco Baringer and others ;; License: GNU GPL (same license as Emacs) ;; -;;; Installation -;; -;; Add this to your .emacs: -;; -;; (add-to-list 'load-path "") -;; (add-hook 'slime-load-hook (lambda () (require 'slime-fancy-inspector))) -;; (add-hook 'slime-connected-hook 'slime-install-fancy-inspector) - -(defun slime-install-fancy-inspector () - (slime-eval-async '(swank:swank-require :swank-fancy-inspector) - (lambda (_) - (slime-eval-async '(swank:fancy-inspector-init))))) - -(defun slime-deinstall-fancy-inspector () - (slime-eval-async '(swank:fancy-inspector-unload))) - -(defun slime-fancy-inspector-init () - (add-hook 'slime-connected-hook 'slime-install-fancy-inspector)) -(defun slime-fancy-inspector-unload () - (remove-hook 'slime-connected-hook 'slime-install-fancy-inspector)) +(slime-require :swank-fancy-inspector) (provide 'slime-fancy-inspector) \ No newline at end of file Modified: branches/trunk-reorg/thirdparty/slime/contrib/slime-fancy.el ============================================================================== --- branches/trunk-reorg/thirdparty/slime/contrib/slime-fancy.el (original) +++ branches/trunk-reorg/thirdparty/slime/contrib/slime-fancy.el Mon Feb 11 09:24:55 2008 @@ -31,9 +31,8 @@ (require 'slime-editing-commands) (slime-editing-commands-init) -;; Makes the inspector fancier. +;; Makes the inspector fancier. (Once loaded, can't be turned off.) (require 'slime-fancy-inspector) -(slime-fancy-inspector-init) ;; Just adds the command C-c M-i. We do not make fuzzy completion the ;; default completion invoked by TAB. --mkoeppe Modified: branches/trunk-reorg/thirdparty/slime/contrib/swank-fancy-inspector.lisp ============================================================================== --- branches/trunk-reorg/thirdparty/slime/contrib/swank-fancy-inspector.lisp (original) +++ branches/trunk-reorg/thirdparty/slime/contrib/swank-fancy-inspector.lisp Mon Feb 11 09:24:55 2008 @@ -6,14 +6,12 @@ (in-package :swank) -(defmethod inspect-for-emacs ((symbol symbol)) +(defmethod emacs-inspect ((symbol symbol)) (let ((package (symbol-package symbol))) (multiple-value-bind (_symbol status) (and package (find-symbol (string symbol) package)) (declare (ignore _symbol)) - (values - "A symbol." - (append + (append (label-value-line "Its name is" (symbol-name symbol)) ;; ;; Value @@ -77,7 +75,7 @@ ;; More package (if (find-package symbol) (label-value-line "It names the package" (find-package symbol))) - ))))) + )))) (defun docstring-ispec (label object kind) "Return a inspector spec if OBJECT has a docstring of of kind KIND." @@ -89,16 +87,15 @@ (t (list label ": " '(:newline) " " docstring '(:newline)))))) -(defmethod inspect-for-emacs ((f function)) - (values "A function." - (append +(defmethod emacs-inspect ((f function)) + (append (label-value-line "Name" (function-name f)) `("Its argument list is: " ,(inspector-princ (arglist f)) (:newline)) (docstring-ispec "Documentation" f t) (if (function-lambda-expression f) (label-value-line "Lambda Expression" - (function-lambda-expression f)))))) + (function-lambda-expression f))))) (defun method-specializers-for-inspect (method) "Return a \"pretty\" list of the method's specializers. Normal @@ -122,11 +119,10 @@ (swank-mop:method-qualifiers method) (method-specializers-for-inspect method))) -(defmethod inspect-for-emacs ((object standard-object)) +(defmethod emacs-inspect ((object standard-object)) (let ((class (class-of object))) - (values "An object." `("Class: " (:value ,class) (:newline) - ,@(all-slots-for-inspector object))))) + ,@(all-slots-for-inspector object)))) (defvar *gf-method-getter* 'methods-by-applicability "This function is called to get the methods of a generic function. @@ -224,11 +220,9 @@ append slot-presentation collect '(:newline)))))) -(defmethod inspect-for-emacs ((gf standard-generic-function)) +(defmethod emacs-inspect ((gf standard-generic-function)) (flet ((lv (label value) (label-value-line label value))) - (values - "A generic function." - (append + (append (lv "Name" (swank-mop:generic-function-name gf)) (lv "Arguments" (swank-mop:generic-function-lambda-list gf)) (docstring-ispec "Documentation" gf t) @@ -247,10 +241,9 @@ (remove-method gf m)))) (:newline))) `((:newline)) - (all-slots-for-inspector gf))))) + (all-slots-for-inspector gf)))) -(defmethod inspect-for-emacs ((method standard-method)) - (values "A method." +(defmethod emacs-inspect ((method standard-method)) `("Method defined on the generic function " (:value ,(swank-mop:method-generic-function method) ,(inspector-princ @@ -267,10 +260,9 @@ (:newline) "Method function: " (:value ,(swank-mop:method-function method)) (:newline) - ,@(all-slots-for-inspector method)))) + ,@(all-slots-for-inspector method))) -(defmethod inspect-for-emacs ((class standard-class)) - (values "A class." +(defmethod emacs-inspect ((class standard-class)) `("Name: " (:value ,(class-name class)) (:newline) "Super classes: " @@ -326,10 +318,9 @@ `(:value ,(swank-mop:class-prototype class)) '"#") (:newline) - ,@(all-slots-for-inspector class)))) + ,@(all-slots-for-inspector class))) -(defmethod inspect-for-emacs ((slot swank-mop:standard-slot-definition)) - (values "A slot." +(defmethod emacs-inspect ((slot swank-mop:standard-slot-definition)) `("Name: " (:value ,(swank-mop:slot-definition-name slot)) (:newline) ,@(when (swank-mop:slot-definition-documentation slot) @@ -342,7 +333,7 @@ "#") (:newline) "Init function: " (:value ,(swank-mop:slot-definition-initfunction slot)) (:newline) - ,@(all-slots-for-inspector slot)))) + ,@(all-slots-for-inspector slot))) ;; Wrapper structure over the list of symbols of a package that should @@ -434,10 +425,10 @@ (:newline) ))))) -(defmethod inspect-for-emacs ((%container %package-symbols-container)) +(defmethod emacs-inspect ((%container %package-symbols-container)) (with-struct (%container. title description symbols grouping-kind) %container - (values title - `(, at description + `(,title (:newline) + , at description (:newline) " " ,(ecase grouping-kind (:symbol @@ -449,9 +440,9 @@ ,(lambda () (setf grouping-kind :symbol)) :refreshp t))) (:newline) (:newline) - ,@(make-symbols-listing grouping-kind symbols))))) + ,@(make-symbols-listing grouping-kind symbols)))) -(defmethod inspect-for-emacs ((package package)) +(defmethod emacs-inspect ((package package)) (let ((package-name (package-name package)) (package-nicknames (package-nicknames package)) (package-use-list (package-use-list package)) @@ -479,8 +470,6 @@ external-symbols (sort external-symbols #'string<)) ; SBCL 0.9.18. - (values - "A package." `("" ; dummy to preserve indentation. "Name: " (:value ,package-name) (:newline) @@ -542,27 +531,27 @@ (:newline) ,(display-link "shadowed" shadowed-symbols (length shadowed-symbols) :title (format nil "All shadowed symbols of package \"~A\"" package-name) - :description nil))))))) + :description nil)))))) -(defmethod inspect-for-emacs ((pathname pathname)) - (values (if (wild-pathname-p pathname) - "A wild pathname." - "A pathname.") - (append (label-value-line* - ("Namestring" (namestring pathname)) - ("Host" (pathname-host pathname)) - ("Device" (pathname-device pathname)) - ("Directory" (pathname-directory pathname)) - ("Name" (pathname-name pathname)) - ("Type" (pathname-type pathname)) - ("Version" (pathname-version pathname))) - (unless (or (wild-pathname-p pathname) - (not (probe-file pathname))) - (label-value-line "Truename" (truename pathname)))))) +(defmethod emacs-inspect ((pathname pathname)) + `(,(if (wild-pathname-p pathname) + "A wild pathname." + "A pathname.") + (:newline) + ,@(label-value-line* + ("Namestring" (namestring pathname)) + ("Host" (pathname-host pathname)) + ("Device" (pathname-device pathname)) + ("Directory" (pathname-directory pathname)) + ("Name" (pathname-name pathname)) + ("Type" (pathname-type pathname)) + ("Version" (pathname-version pathname))) + ,@ (unless (or (wild-pathname-p pathname) + (not (probe-file pathname))) + (label-value-line "Truename" (truename pathname))))) -(defmethod inspect-for-emacs ((pathname logical-pathname)) - (values "A logical pathname." +(defmethod emacs-inspect ((pathname logical-pathname)) (append (label-value-line* ("Namestring" (namestring pathname)) @@ -579,10 +568,10 @@ ("Type" (pathname-type pathname)) ("Version" (pathname-version pathname)) ("Truename" (if (not (wild-pathname-p pathname)) - (probe-file pathname))))))) + (probe-file pathname)))))) -(defmethod inspect-for-emacs ((n number)) - (values "A number." `("Value: " ,(princ-to-string n)))) +(defmethod emacs-inspect ((n number)) + `("Value: " ,(princ-to-string n))) (defun format-iso8601-time (time-value &optional include-timezone-p) "Formats a universal time TIME-VALUE in ISO 8601 format, with @@ -604,8 +593,7 @@ year month day hour minute second include-timezone-p (format-iso8601-timezone zone))))) -(defmethod inspect-for-emacs ((i integer)) - (values "A number." +(defmethod emacs-inspect ((i integer)) (append `(,(format nil "Value: ~D = #x~8,'0X = #o~O = #b~,,' ,8:B~@[ = ~E~]" i i i i (ignore-errors (coerce i 'float))) @@ -614,23 +602,20 @@ (label-value-line "Code-char" (code-char i))) (label-value-line "Integer-length" (integer-length i)) (ignore-errors - (label-value-line "Universal-time" (format-iso8601-time i t)))))) + (label-value-line "Universal-time" (format-iso8601-time i t))))) -(defmethod inspect-for-emacs ((c complex)) - (values "A complex number." +(defmethod emacs-inspect ((c complex)) (label-value-line* ("Real part" (realpart c)) - ("Imaginary part" (imagpart c))))) + ("Imaginary part" (imagpart c)))) -(defmethod inspect-for-emacs ((r ratio)) - (values "A non-integer ratio." +(defmethod emacs-inspect ((r ratio)) (label-value-line* ("Numerator" (numerator r)) ("Denominator" (denominator r)) - ("As float" (float r))))) + ("As float" (float r)))) -(defmethod inspect-for-emacs ((f float)) - (values "A floating point number." +(defmethod emacs-inspect ((f float)) (cond ((> f most-positive-long-float) (list "Positive infinity.")) @@ -647,13 +632,11 @@ (:value ,significand) " * " (:value ,(float-radix f)) "^" (:value ,exponent) (:newline)) (label-value-line "Digits" (float-digits f)) - (label-value-line "Precision" (float-precision f)))))))) + (label-value-line "Precision" (float-precision f))))))) -(defmethod inspect-for-emacs ((stream file-stream)) - (multiple-value-bind (title content) +(defmethod emacs-inspect ((stream file-stream)) + (multiple-value-bind (content) (call-next-method) - (declare (ignore title)) - (values "A file stream." (append `("Pathname: " (:value ,(pathname stream)) @@ -665,14 +648,13 @@ (ed-in-emacs `(,pathname :charpos ,position)))) :refreshp nil) (:newline)) - content)))) + content))) -(defmethod inspect-for-emacs ((condition stream-error)) - (multiple-value-bind (title content) +(defmethod emacs-inspect ((condition stream-error)) + (multiple-value-bind (content) (call-next-method) (let ((stream (stream-error-stream condition))) (if (typep stream 'file-stream) - (values "A stream error." (append `("Pathname: " (:value ,(pathname stream)) @@ -684,16 +666,22 @@ (ed-in-emacs `(,pathname :charpos ,position)))) :refreshp nil) (:newline)) - content)) - (values title content))))) + content) + content)))) -(defvar *fancy-inpector-undo-list* nil) - -(defslimefun fancy-inspector-init () - t) - -(defslimefun fancy-inspector-unload () - (loop while *fancy-inpector-undo-list* do - (funcall (pop *fancy-inpector-undo-list*)))) +(defun common-seperated-spec (list &optional (callback (lambda (v) + `(:value ,v)))) + (butlast + (loop + for i in list + collect (funcall callback i) + collect ", "))) + +(defun inspector-princ (list) + "Like princ-to-string, but don't rewrite (function foo) as #'foo. +Do NOT pass circular lists to this function." + (let ((*print-pprint-dispatch* (copy-pprint-dispatch))) + (set-pprint-dispatch '(cons (member function)) nil) + (princ-to-string list))) (provide :swank-fancy-inspector) Modified: branches/trunk-reorg/thirdparty/slime/slime.el ============================================================================== --- branches/trunk-reorg/thirdparty/slime/slime.el (original) +++ branches/trunk-reorg/thirdparty/slime/slime.el Mon Feb 11 09:24:55 2008 @@ -2267,11 +2267,7 @@ (save-excursion (when (or (re-search-backward regexp nil t) (re-search-forward regexp nil t)) - ;; package name can be a string designator, convert it to a string. - ;;(slime-eval `(cl:string (cl:second (cl:read-from-string ,(match-string-no-properties 0)))) - ;; "COMMON-LISP-USER") - (match-string-no-properties 2) - )))) + (match-string-no-properties 2))))) ;;; Synchronous requests are implemented in terms of asynchronous ;;; ones. We make an asynchronous request with a continuation function @@ -3176,14 +3172,14 @@ (let ((end (point))) ; end of input, without the newline (slime-repl-add-to-input-history (buffer-substring slime-repl-input-start-mark end)) - (when newline - (insert "\n") - (slime-repl-show-maximum-output)) (let ((inhibit-read-only t)) (add-text-properties slime-repl-input-start-mark (point) `(slime-repl-old-input ,(incf slime-repl-old-input-counter)))) + (when newline + (insert "\n") + (slime-repl-show-maximum-output)) (let ((overlay (make-overlay slime-repl-input-start-mark end))) ;; These properties are on an overlay so that they won't be taken ;; by kill/yank. @@ -3216,25 +3212,9 @@ (defun slime-property-bounds (prop) "Return two the positions of the previous and next changes to PROP. PROP is the name of a text property." - (let* ((beg (save-excursion - ;; previous-single-char-property-change searches for a - ;; property change from the previous character, but we - ;; want to look for a change from the point. We step - ;; forward one char to avoid doing the wrong thing if - ;; we're at the beginning of the old input. -luke - ;; (18/Jun/2004) - (unless (not (get-text-property (point) prop)) - ;; alanr unless we are sitting right after it May 19, 2005 - (ignore-errors (forward-char))) - (previous-single-char-property-change (point) prop))) - (end (save-excursion - (if (get-text-property (point) prop) - (progn (goto-char (next-single-char-property-change - (point) prop)) - (skip-chars-backward "\n \t\r" beg) - (point)) - (point))))) - (values beg end))) + (assert (get-text-property (point) prop)) + (let ((end (next-single-char-property-change (point) prop))) + (list (previous-single-char-property-change end prop) end))) (defun slime-repl-closing-return () "Evaluate the current input string after closing all open lists." @@ -3321,12 +3301,11 @@ (defun slime-repl-set-package (package) "Set the package of the REPL buffer to PACKAGE." - (interactive (list (slime-read-package-name "Package: " - (if (string= (slime-current-package) - (with-current-buffer (slime-repl-buffer) - (slime-current-package))) - nil - (slime-pretty-find-buffer-package))))) + (interactive (list (slime-read-package-name + "Package: " + (if (equal (slime-current-package) (slime-lisp-package)) + nil + (slime-pretty-find-buffer-package))))) (with-current-buffer (slime-output-buffer) (let ((unfinished-input (slime-repl-current-input))) (destructuring-bind (name prompt-string) @@ -6821,11 +6800,7 @@ (get-text-property (point) 'details-visible-p))) (defun sldb-frame-region () - (save-excursion - (goto-char (next-single-property-change (point) 'frame nil (point-max))) - (backward-char) - (values (previous-single-property-change (point) 'frame) - (next-single-property-change (point) 'frame nil (point-max))))) + (slime-property-bounds 'frame)) (defun sldb-forward-frame () (goto-char (next-single-char-property-change (point) 'frame))) @@ -7540,8 +7515,8 @@ (while (eq (char-before) ?\n) (backward-delete-char 1)) (insert "\n" (fontify label "--------------------") "\n") - (save-excursion - (mapc slime-inspector-insert-ispec-function content)) + (save-excursion + (slime-inspector-insert-content content)) (pop-to-buffer (current-buffer)) (when point (check-type point cons) @@ -7549,6 +7524,22 @@ (goto-line (car point)) (move-to-column (cdr point))))))))) +(defun slime-inspector-insert-content (content) + (destructuring-bind (ispecs len start end) content + (slime-inspector-insert-range ispecs len start end t t))) + +(defun slime-inspector-insert-range (ispecs len start end prev next) + "Insert ISPECS at point. +LEN is the length of the entire content on the Lisp side. +START and END are the positions of the subsequnce that ISPECS represents. +If PREV resp. NEXT are true insert range-buttons as needed." + (let ((limit 2000)) + (when (and prev (> start 0)) + (slime-inspector-insert-range-button (max 0 (- start limit)) start t)) + (mapc #'slime-inspector-insert-ispec ispecs) + (when (and next (< end len)) + (slime-inspector-insert-range-button end (min len (+ end limit)) nil)))) + (defun slime-inspector-insert-ispec (ispec) (if (stringp ispec) (insert ispec) @@ -7580,10 +7571,14 @@ (current-column)))) (defun slime-inspector-operate-on-point () - "If point is on a value then recursivly call the inspector on - that value. If point is on an action then call that action." + "Invoke the command for the text at point. +1. If point is on a value then recursivly call the inspector on +that value. +2. If point is on an action then call that action. +3. If point is on a range-button fetch and insert the range." (interactive) (let ((part-number (get-text-property (point) 'slime-part-number)) + (range-button (get-text-property (point) 'slime-range-button)) (action-number (get-text-property (point) 'slime-action-number)) (opener (lexical-let ((point (slime-inspector-position))) (lambda (parts) @@ -7593,6 +7588,8 @@ (slime-eval-async `(swank:inspect-nth-part ,part-number) opener) (push (slime-inspector-position) slime-inspector-mark-stack)) + (range-button + (slime-inspector-fetch-range range-button)) (action-number (slime-eval-async `(swank::inspector-call-nth-action ,action-number) opener))))) @@ -7693,7 +7690,6 @@ (progn (goto-char maxpos) (setq previously-wrapped-p t)) (error "No inspectable objects"))))))) - (defun slime-inspector-previous-inspectable-object (arg) "Move point to the previous inspectable object. With optional ARG, move across that many objects. @@ -7717,6 +7713,25 @@ (lambda (parts) (slime-open-inspector parts point))))) +(defun slime-inspector-insert-range-button (start end previous) + (slime-insert-propertized + (list 'slime-range-button (list start end previous) + 'mouse-face 'highlight + 'face 'slime-inspector-action-face) + (if previous " [--more--]\n" " [--more--]"))) + +(defun slime-inspector-fetch-range (button) + (destructuring-bind (start end previous) button + (slime-eval-async + `(swank:inspector-range ,start ,end) + (slime-rcurry + (lambda (content prev) + (let ((inhibit-read-only t)) + (apply #'delete-region (slime-property-bounds 'slime-range-button)) + (destructuring-bind (i l s e) content + (slime-inspector-insert-range i l s e prev (not prev))))) + previous)))) + (slime-define-keys slime-inspector-mode-map ([return] 'slime-inspector-operate-on-point) ((kbd "M-RET") 'slime-inspector-copy-down) @@ -9630,7 +9645,7 @@ ;; Local Variables: ;; outline-regexp: ";;;;+" ;; indent-tabs-mode: nil -;; coding: latin-1-unix! +;; coding: latin-1-unix ;; unibyte: t ;; compile-command: "emacs -batch -L . -eval '(byte-compile-file \"slime.el\")' ; rm -v slime.elc" ;; End: Modified: branches/trunk-reorg/thirdparty/slime/swank-abcl.lisp ============================================================================== --- branches/trunk-reorg/thirdparty/slime/swank-abcl.lisp (original) +++ branches/trunk-reorg/thirdparty/slime/swank-abcl.lisp Mon Feb 11 09:24:55 2008 @@ -421,8 +421,7 @@ ;;;; Inspecting -(defmethod inspect-for-emacs ((slot mop::slot-definition)) - (values "A slot." +(defmethod emacs-inspect ((slot mop::slot-definition)) `("Name: " (:value ,(mop::%slot-definition-name slot)) (:newline) "Documentation:" (:newline) @@ -434,10 +433,9 @@ `(:value ,(mop::%slot-definition-initform slot)) "#") (:newline) " Function: " (:value ,(mop::%slot-definition-initfunction slot)) - (:newline)))) + (:newline))) -(defmethod inspect-for-emacs ((f function)) - (values "A function." +(defmethod emacs-inspect ((f function)) `(,@(when (function-name f) `("Name: " ,(princ-to-string (function-name f)) (:newline))) @@ -449,19 +447,18 @@ `("Documentation:" (:newline) ,(documentation f t) (:newline))) ,@(when (function-lambda-expression f) `("Lambda expression:" - (:newline) ,(princ-to-string (function-lambda-expression f)) (:newline)))))) + (:newline) ,(princ-to-string (function-lambda-expression f)) (:newline))))) #| -(defmethod inspect-for-emacs ((o t)) +(defmethod emacs-inspect ((o t)) (let* ((class (class-of o)) (slots (mop::class-slots class))) - (values (format nil "~A~% is a ~A" o class) (mapcar (lambda (slot) (let ((name (mop::slot-definition-name slot))) (cons (princ-to-string name) (slot-value o name)))) - slots)))) + slots))) |# ;;;; Multithreading Modified: branches/trunk-reorg/thirdparty/slime/swank-allegro.lisp ============================================================================== --- branches/trunk-reorg/thirdparty/slime/swank-allegro.lisp (original) +++ branches/trunk-reorg/thirdparty/slime/swank-allegro.lisp Mon Feb 11 09:24:55 2008 @@ -564,23 +564,22 @@ ;;;; Inspecting -(defmethod inspect-for-emacs ((f function)) - (values "A function." +(defmethod emacs-inspect ((f function)) (append (label-value-line "Name" (function-name f)) `("Formals" ,(princ-to-string (arglist f)) (:newline)) (let ((doc (documentation (excl::external-fn_symdef f) 'function))) (when doc - `("Documentation:" (:newline) ,doc)))))) + `("Documentation:" (:newline) ,doc))))) -(defmethod inspect-for-emacs ((o t)) - (values "A value." (allegro-inspect o))) +(defmethod emacs-inspect ((o t)) + (allegro-inspect o)) -(defmethod inspect-for-emacs ((o function)) - (values "A function." (allegro-inspect o))) +(defmethod emacs-inspect ((o function)) + (allegro-inspect o)) -(defmethod inspect-for-emacs ((o standard-object)) - (values (format nil "~A is a standard-object." o) (allegro-inspect o))) +(defmethod emacs-inspect ((o standard-object)) + (allegro-inspect o)) (defun allegro-inspect (o) (loop for (d dd) on (inspect::inspect-ctl o) Modified: branches/trunk-reorg/thirdparty/slime/swank-backend.lisp ============================================================================== --- branches/trunk-reorg/thirdparty/slime/swank-backend.lisp (original) +++ branches/trunk-reorg/thirdparty/slime/swank-backend.lisp Mon Feb 11 09:24:55 2008 @@ -33,11 +33,7 @@ #:declaration-arglist #:type-specifier-arglist ;; inspector related symbols - #:inspector - #:backend-inspector - #:inspect-for-emacs - #:raw-inspection - #:fancy-inspection + #:emacs-inspect #:label-value-line #:label-value-line* #:with-struct @@ -840,13 +836,11 @@ ;;;; Inspector -(defgeneric inspect-for-emacs (object) +(defgeneric emacs-inspect (object) (:documentation "Explain to Emacs how to inspect OBJECT. -Returns two values: a string which will be used as the title of -the inspector buffer and a list specifying how to render the -object for inspection. +Returns a list specifying how to render the object for inspection. Every element of the list must be either a string, which will be inserted into the buffer as is, or a list of the form: @@ -861,20 +855,17 @@ string) which when clicked will call LAMBDA. If REFRESH is non-NIL the currently inspected object will be re-inspected after calling the lambda. +")) - NIL - do nothing.")) - -(defmethod inspect-for-emacs ((object t)) +(defmethod emacs-inspect ((object t)) "Generic method for inspecting any kind of object. Since we don't know how to deal with OBJECT we simply dump the output of CL:DESCRIBE." - (values - "A value." `("Type: " (:value ,(type-of object)) (:newline) "Don't know how to inspect the object, dumping output of CL:DESCRIBE:" (:newline) (:newline) - ,(with-output-to-string (desc) (describe object desc))))) + ,(with-output-to-string (desc) (describe object desc)))) ;;; Utilities for inspector methods. ;;; Modified: branches/trunk-reorg/thirdparty/slime/swank-clisp.lisp ============================================================================== --- branches/trunk-reorg/thirdparty/slime/swank-clisp.lisp (original) +++ branches/trunk-reorg/thirdparty/slime/swank-clisp.lisp Mon Feb 11 09:24:55 2008 @@ -627,7 +627,7 @@ ;;;; Inspecting -(defmethod inspect-for-emacs ((o t)) +(defmethod emacs-inspect ((o t)) (let* ((*print-array* nil) (*print-pretty* t) (*print-circle* t) (*print-escape* t) (*print-lines* custom:*inspect-print-lines*) @@ -638,9 +638,10 @@ (*package* tmp-pack) (sys::*inspect-unbound-value* (intern "#" tmp-pack))) (let ((inspection (sys::inspect-backend o))) - (values (format nil "~S~% ~A~{~%~A~}" o + (append (list + (format nil "~S~% ~A~{~%~A~}~%" o (sys::insp-title inspection) - (sys::insp-blurb inspection)) + (sys::insp-blurb inspection))) (loop with count = (sys::insp-num-slots inspection) for i below count append (multiple-value-bind (value name) Modified: branches/trunk-reorg/thirdparty/slime/swank-cmucl.lisp ============================================================================== --- branches/trunk-reorg/thirdparty/slime/swank-cmucl.lisp (original) +++ branches/trunk-reorg/thirdparty/slime/swank-cmucl.lisp Mon Feb 11 09:24:55 2008 @@ -1822,11 +1822,6 @@ ;;;; Inspecting -(defclass cmucl-inspector (backend-inspector) ()) - -(defimplementation make-default-inspector () - (make-instance 'cmucl-inspector)) - (defconstant +lowtag-symbols+ '(vm:even-fixnum-type vm:function-pointer-type @@ -1869,10 +1864,9 @@ :key #'symbol-value))) (format t ", type: ~A" type-symbol)))))) -(defmethod inspect-for-emacs ((o t)) +(defmethod emacs-inspect ((o t)) (cond ((di::indirect-value-cell-p o) - (values (format nil "~A is a value cell." o) - `("Value: " (:value ,(c:value-cell-ref o))))) + `("Value: " (:value ,(c:value-cell-ref o)))) ((alien::alien-value-p o) (inspect-alien-value o)) (t @@ -1880,63 +1874,59 @@ (defun cmucl-inspect (o) (destructuring-bind (text labeledp . parts) (inspect::describe-parts o) - (values (format nil "~A~%" text) - (if labeledp - (loop for (label . value) in parts - append (label-value-line label value)) - (loop for value in parts for i from 0 - append (label-value-line i value)))))) + (list* (format nil "~A~%" text) + (if labeledp + (loop for (label . value) in parts + append (label-value-line label value)) + (loop for value in parts for i from 0 + append (label-value-line i value)))))) -(defmethod inspect-for-emacs ((o function)) +(defmethod emacs-inspect ((o function)) (let ((header (kernel:get-type o))) (cond ((= header vm:function-header-type) - (values (format nil "~A is a function." o) - (append (label-value-line* - ("Self" (kernel:%function-self o)) - ("Next" (kernel:%function-next o)) - ("Name" (kernel:%function-name o)) - ("Arglist" (kernel:%function-arglist o)) - ("Type" (kernel:%function-type o)) - ("Code" (kernel:function-code-header o))) - (list - (with-output-to-string (s) - (disassem:disassemble-function o :stream s)))))) + (append (label-value-line* + ("Self" (kernel:%function-self o)) + ("Next" (kernel:%function-next o)) + ("Name" (kernel:%function-name o)) + ("Arglist" (kernel:%function-arglist o)) + ("Type" (kernel:%function-type o)) + ("Code" (kernel:function-code-header o))) + (list + (with-output-to-string (s) + (disassem:disassemble-function o :stream s))))) ((= header vm:closure-header-type) - (values (format nil "~A is a closure" o) - (append - (label-value-line "Function" (kernel:%closure-function o)) - `("Environment:" (:newline)) - (loop for i from 0 below (1- (kernel:get-closure-length o)) - append (label-value-line - i (kernel:%closure-index-ref o i)))))) + (list* (format nil "~A is a closure.~%" o) + (append + (label-value-line "Function" (kernel:%closure-function o)) + `("Environment:" (:newline)) + (loop for i from 0 below (1- (kernel:get-closure-length o)) + append (label-value-line + i (kernel:%closure-index-ref o i)))))) ((eval::interpreted-function-p o) (cmucl-inspect o)) (t (call-next-method))))) -(defmethod inspect-for-emacs ((o kernel:funcallable-instance)) - (values - (format nil "~A is a funcallable-instance." o) - (append (label-value-line* - (:function (kernel:%funcallable-instance-function o)) - (:lexenv (kernel:%funcallable-instance-lexenv o)) - (:layout (kernel:%funcallable-instance-layout o))) - (nth-value 1 (cmucl-inspect o))))) - -(defmethod inspect-for-emacs ((o kernel:code-component)) - (values (format nil "~A is a code data-block." o) - (append - (label-value-line* - ("code-size" (kernel:%code-code-size o)) - ("entry-points" (kernel:%code-entry-points o)) - ("debug-info" (kernel:%code-debug-info o)) - ("trace-table-offset" (kernel:code-header-ref - o vm:code-trace-table-offset-slot))) - `("Constants:" (:newline)) - (loop for i from vm:code-constants-offset - below (kernel:get-header-data o) - append (label-value-line i (kernel:code-header-ref o i))) - `("Code:" (:newline) +(defmethod emacs-inspect ((o kernel:funcallable-instance)) + (append (label-value-line* + (:function (kernel:%funcallable-instance-function o)) + (:lexenv (kernel:%funcallable-instance-lexenv o)) + (:layout (kernel:%funcallable-instance-layout o))) + (cmucl-inspect o))) + +(defmethod emacs-inspect ((o kernel:code-component)) + (append + (label-value-line* + ("code-size" (kernel:%code-code-size o)) + ("entry-points" (kernel:%code-entry-points o)) + ("debug-info" (kernel:%code-debug-info o)) + ("trace-table-offset" (kernel:code-header-ref + o vm:code-trace-table-offset-slot))) + `("Constants:" (:newline)) + (loop for i from vm:code-constants-offset + below (kernel:get-header-data o) + append (label-value-line i (kernel:code-header-ref o i))) + `("Code:" (:newline) , (with-output-to-string (s) (cond ((kernel:%code-debug-info o) (disassem:disassemble-code-component o :stream s)) @@ -1948,63 +1938,57 @@ (* vm:code-constants-offset vm:word-bytes)) (ash 1 vm:lowtag-bits)) (ash (kernel:%code-code-size o) vm:word-shift) - :stream s)))))))) + :stream s))))))) -(defmethod inspect-for-emacs ((o kernel:fdefn)) - (values (format nil "~A is a fdenf object." o) - (label-value-line* - ("name" (kernel:fdefn-name o)) - ("function" (kernel:fdefn-function o)) - ("raw-addr" (sys:sap-ref-32 - (sys:int-sap (kernel:get-lisp-obj-address o)) - (* vm:fdefn-raw-addr-slot vm:word-bytes)))))) +(defmethod emacs-inspect ((o kernel:fdefn)) + (label-value-line* + ("name" (kernel:fdefn-name o)) + ("function" (kernel:fdefn-function o)) + ("raw-addr" (sys:sap-ref-32 + (sys:int-sap (kernel:get-lisp-obj-address o)) + (* vm:fdefn-raw-addr-slot vm:word-bytes))))) -(defmethod inspect-for-emacs ((o array)) +#+(or) +(defmethod emacs-inspect ((o array)) (if (typep o 'simple-array) (call-next-method) - (values (format nil "~A is an array." o) - (label-value-line* - (:header (describe-primitive-type o)) - (:rank (array-rank o)) - (:fill-pointer (kernel:%array-fill-pointer o)) - (:fill-pointer-p (kernel:%array-fill-pointer-p o)) - (:elements (kernel:%array-available-elements o)) - (:data (kernel:%array-data-vector o)) - (:displacement (kernel:%array-displacement o)) - (:displaced-p (kernel:%array-displaced-p o)) - (:dimensions (array-dimensions o)))))) - -(defmethod inspect-for-emacs ((o simple-vector)) - (values (format nil "~A is a simple-vector." o) - (append - (label-value-line* - (:header (describe-primitive-type o)) - (:length (c::vector-length o))) - (loop for i below (length o) - append (label-value-line i (aref o i)))))) + (label-value-line* + (:header (describe-primitive-type o)) + (:rank (array-rank o)) + (:fill-pointer (kernel:%array-fill-pointer o)) + (:fill-pointer-p (kernel:%array-fill-pointer-p o)) + (:elements (kernel:%array-available-elements o)) + (:data (kernel:%array-data-vector o)) + (:displacement (kernel:%array-displacement o)) + (:displaced-p (kernel:%array-displaced-p o)) + (:dimensions (array-dimensions o))))) + +(defmethod emacs-inspect ((o simple-vector)) + (append + (label-value-line* + (:header (describe-primitive-type o)) + (:length (c::vector-length o))) + (loop for i below (length o) + append (label-value-line i (aref o i))))) (defun inspect-alien-record (alien) - (values - (format nil "~A is an alien value." alien) - (with-struct (alien::alien-value- sap type) alien - (with-struct (alien::alien-record-type- kind name fields) type - (append - (label-value-line* - (:sap sap) - (:kind kind) - (:name name)) - (loop for field in fields - append (let ((slot (alien::alien-record-field-name field))) - (label-value-line slot (alien:slot alien slot))))))))) + (with-struct (alien::alien-value- sap type) alien + (with-struct (alien::alien-record-type- kind name fields) type + (append + (label-value-line* + (:sap sap) + (:kind kind) + (:name name)) + (loop for field in fields + append (let ((slot (alien::alien-record-field-name field))) + (label-value-line slot (alien:slot alien slot)))))))) (defun inspect-alien-pointer (alien) - (values - (format nil "~A is an alien value." alien) - (with-struct (alien::alien-value- sap type) alien - (label-value-line* - (:sap sap) - (:type type) - (:to (alien::deref alien)))))) + (with-struct (alien::alien-value- sap type) alien + (label-value-line* + (:sap sap) + (:type type) + (:to (alien::deref alien))))) (defun inspect-alien-value (alien) (typecase (alien::alien-value-type alien) Modified: branches/trunk-reorg/thirdparty/slime/swank-corman.lisp ============================================================================== --- branches/trunk-reorg/thirdparty/slime/swank-corman.lisp (original) +++ branches/trunk-reorg/thirdparty/slime/swank-corman.lisp Mon Feb 11 09:24:55 2008 @@ -393,8 +393,7 @@ collect (funcall callback e) collect ", "))) -(defmethod inspect-for-emacs ((class standard-class)) - (values "A class." +(defmethod emacs-inspect ((class standard-class)) `("Name: " (:value ,(class-name class)) (:newline) "Super classes: " @@ -428,12 +427,11 @@ (lambda (class) `(:value ,class ,(princ-to-string (class-name class))))) '("#")) - (:newline)))) + (:newline))) -(defmethod inspect-for-emacs ((slot cons)) +(defmethod emacs-inspect ((slot cons)) ;; Inspects slot definitions (if (eq (car slot) :name) - (values "A slot." `("Name: " (:value ,(swank-mop:slot-definition-name slot)) (:newline) ,@(when (swank-mop:slot-definition-documentation slot) @@ -445,13 +443,14 @@ `(:value ,(swank-mop:slot-definition-initform slot)) "#") (:newline) "Init function: " (:value ,(swank-mop:slot-definition-initfunction slot)) - (:newline))) + (:newline)) (call-next-method))) -(defmethod inspect-for-emacs ((pathname pathnames::pathname-internal)) - (values (if (wild-pathname-p pathname) +(defmethod emacs-inspect ((pathname pathnames::pathname-internal)) + (list* (if (wild-pathname-p pathname) "A wild pathname." "A pathname.") + '(:newline) (append (label-value-line* ("Namestring" (namestring pathname)) ("Host" (pathname-host pathname)) @@ -464,13 +463,11 @@ (not (probe-file pathname))) (label-value-line "Truename" (truename pathname)))))) -(defmethod inspect-for-emacs ((o t)) +(defmethod emacs-inspect ((o t)) (cond ((cl::structurep o) (inspect-structure o)) (t (call-next-method)))) (defun inspect-structure (o) - (values - (format nil "~A is a structure" o) (let* ((template (cl::uref o 1)) (num-slots (cl::struct-template-num-slots template))) (cond ((symbolp template) @@ -479,7 +476,7 @@ (t (loop for i below num-slots append (label-value-line (elt template (+ 6 (* i 5))) - (cl::uref o (+ 2 i))))))))) + (cl::uref o (+ 2 i)))))))) ;;; Threads Modified: branches/trunk-reorg/thirdparty/slime/swank-ecl.lisp ============================================================================== --- branches/trunk-reorg/thirdparty/slime/swank-ecl.lisp (original) +++ branches/trunk-reorg/thirdparty/slime/swank-ecl.lisp Mon Feb 11 09:24:55 2008 @@ -248,12 +248,12 @@ ;;;; Inspector -(defmethod inspect-for-emacs ((o t)) +(defmethod emacs-inspect ((o t)) ; ecl clos support leaves some to be desired (cond ((streamp o) - (values - (format nil "~S is an ordinary stream" o) + (list* + (format nil "~S is an ordinary stream~%" o) (append (list "Open for " @@ -285,7 +285,7 @@ (t (let* ((cl (si:instance-class o)) (slots (clos:class-slots cl))) - (values (format nil "~S is an instance of class ~A" + (list* (format nil "~S is an instance of class ~A~%" o (clos::class-name cl)) (loop for x in slots append (let* ((name (clos:slot-definition-name x)) Modified: branches/trunk-reorg/thirdparty/slime/swank-lispworks.lisp ============================================================================== --- branches/trunk-reorg/thirdparty/slime/swank-lispworks.lisp (original) +++ branches/trunk-reorg/thirdparty/slime/swank-lispworks.lisp Mon Feb 11 09:24:55 2008 @@ -624,32 +624,27 @@ append (frob-locs dspec (dspec:dspec-definition-locations dspec))))) ;;; Inspector -(defclass lispworks-inspector (backend-inspector) ()) -(defimplementation make-default-inspector () - (make-instance 'lispworks-inspector)) - -(defmethod inspect-for-emacs ((o t)) +(defmethod emacs-inspect ((o t)) (lispworks-inspect o)) -(defmethod inspect-for-emacs ((o function)) +(defmethod emacs-inspect ((o function)) (lispworks-inspect o)) ;; FIXME: slot-boundp-using-class in LW works with names so we can't ;; use our method in swank.lisp. -(defmethod inspect-for-emacs ((o standard-object)) +(defmethod emacs-inspect ((o standard-object)) (lispworks-inspect o)) (defun lispworks-inspect (o) (multiple-value-bind (names values _getter _setter type) (lw:get-inspector-values o nil) (declare (ignore _getter _setter)) - (values "A value." (append (label-value-line "Type" type) (loop for name in names for value in values - append (label-value-line name value)))))) + append (label-value-line name value))))) ;;; Miscellaneous Modified: branches/trunk-reorg/thirdparty/slime/swank-openmcl.lisp ============================================================================== --- branches/trunk-reorg/thirdparty/slime/swank-openmcl.lisp (original) +++ branches/trunk-reorg/thirdparty/slime/swank-openmcl.lisp Mon Feb 11 09:24:55 2008 @@ -802,7 +802,7 @@ (string (gethash typecode *value2tag*)) (string (nth typecode '(tag-fixnum tag-list tag-misc tag-imm)))))) -(defmethod inspect-for-emacs ((o t)) +(defmethod emacs-inspect ((o t)) (let* ((i (inspector::make-inspector o)) (count (inspector::compute-line-count i)) (lines @@ -814,24 +814,16 @@ collect " = " collect `(:value ,value) collect '(:newline)))) - (values (with-output-to-string (s) - (let ((*print-lines* 1) - (*print-right-margin* 80)) - (pprint o s))) - lines))) + lines)) -(defmethod inspect-for-emacs :around ((o t)) +(defmethod emacs-inspect :around ((o t)) (if (or (uvector-inspector-p o) (not (ccl:uvectorp o))) (call-next-method) - (multiple-value-bind (title content) - (call-next-method) - (values - title - (append content + (append (call-next-method) `((:newline) (:value ,(make-instance 'uvector-inspector :object o) - "Underlying UVECTOR"))))))) + "Underlying UVECTOR"))))) (defclass uvector-inspector () ((object :initarg :object))) @@ -840,15 +832,14 @@ (:method ((object t)) nil) (:method ((object uvector-inspector)) t)) -(defmethod inspect-for-emacs ((uv uvector-inspector)) +(defmethod emacs-inspect ((uv uvector-inspector)) (with-slots (object) uv - (values (format nil "The UVECTOR for ~S." object) (loop for index below (ccl::uvsize object) collect (format nil "~D: " index) collect `(:value ,(ccl::uvref object index)) - collect `(:newline))))) + collect `(:newline)))) (defun closure-closed-over-values (closure) (let ((howmany (nth-value 8 (ccl::function-args (ccl::closure-function closure))))) @@ -860,9 +851,9 @@ (cellp (ccl::closed-over-value-p value))) (list label (if cellp (ccl::closed-over-value value) value)))))) -(defmethod inspect-for-emacs ((c ccl::compiled-lexical-closure)) - (values - (format nil "A closure: ~a" c) +(defmethod emacs-inspect ((c ccl::compiled-lexical-closure)) + (list* + (format nil "A closure: ~a~%" c) `(,@(if (arglist c) (list "Its argument list is: " (funcall (intern "INSPECTOR-PRINC" 'swank) (arglist c))) Modified: branches/trunk-reorg/thirdparty/slime/swank-sbcl.lisp ============================================================================== --- branches/trunk-reorg/thirdparty/slime/swank-sbcl.lisp (original) +++ branches/trunk-reorg/thirdparty/slime/swank-sbcl.lisp Mon Feb 11 09:24:55 2008 @@ -1001,41 +1001,38 @@ ;;;; Inspector -(defmethod inspect-for-emacs ((o t)) +(defmethod emacs-inspect ((o t)) (cond ((sb-di::indirect-value-cell-p o) - (values "A value cell." (label-value-line* - (:value (sb-kernel:value-cell-ref o))))) + (label-value-line* (:value (sb-kernel:value-cell-ref o)))) (t (multiple-value-bind (text label parts) (sb-impl::inspected-parts o) - (if label - (values text (loop for (l . v) in parts - append (label-value-line l v))) - (values text (loop for value in parts for i from 0 - append (label-value-line i value)))))))) + (list* (format nil "~a~%" text) + (if label + (loop for (l . v) in parts + append (label-value-line l v)) + (loop for value in parts for i from 0 + append (label-value-line i value)))))))) -(defmethod inspect-for-emacs ((o function)) +(defmethod emacs-inspect ((o function)) (let ((header (sb-kernel:widetag-of o))) (cond ((= header sb-vm:simple-fun-header-widetag) - (values "A simple-fun." (label-value-line* (:name (sb-kernel:%simple-fun-name o)) (:arglist (sb-kernel:%simple-fun-arglist o)) (:self (sb-kernel:%simple-fun-self o)) (:next (sb-kernel:%simple-fun-next o)) (:type (sb-kernel:%simple-fun-type o)) - (:code (sb-kernel:fun-code-header o))))) + (:code (sb-kernel:fun-code-header o)))) ((= header sb-vm:closure-header-widetag) - (values "A closure." (append (label-value-line :function (sb-kernel:%closure-fun o)) `("Closed over values:" (:newline)) (loop for i below (1- (sb-kernel:get-closure-length o)) append (label-value-line - i (sb-kernel:%closure-index-ref o i)))))) + i (sb-kernel:%closure-index-ref o i))))) (t (call-next-method o))))) -(defmethod inspect-for-emacs ((o sb-kernel:code-component)) - (values (format nil "~A is a code data-block." o) +(defmethod emacs-inspect ((o sb-kernel:code-component)) (append (label-value-line* (:code-size (sb-kernel:%code-code-size o)) @@ -1060,28 +1057,24 @@ sb-vm:n-word-bytes)) (ash 1 sb-vm:n-lowtag-bits)) (ash (sb-kernel:%code-code-size o) sb-vm:word-shift) - :stream s)))))))) + :stream s))))))) -(defmethod inspect-for-emacs ((o sb-ext:weak-pointer)) - (values "A weak pointer." +(defmethod emacs-inspect ((o sb-ext:weak-pointer)) (label-value-line* - (:value (sb-ext:weak-pointer-value o))))) + (:value (sb-ext:weak-pointer-value o)))) -(defmethod inspect-for-emacs ((o sb-kernel:fdefn)) - (values "A fdefn object." +(defmethod emacs-inspect ((o sb-kernel:fdefn)) (label-value-line* (:name (sb-kernel:fdefn-name o)) - (:function (sb-kernel:fdefn-fun o))))) + (:function (sb-kernel:fdefn-fun o)))) -(defmethod inspect-for-emacs :around ((o generic-function)) - (multiple-value-bind (title contents) (call-next-method) - (values title +(defmethod emacs-inspect :around ((o generic-function)) (append - contents + (call-next-method) (label-value-line* (:pretty-arglist (sb-pcl::generic-function-pretty-arglist o)) (:initial-methods (sb-pcl::generic-function-initial-methods o)) - ))))) + ))) ;;;; Multiprocessing Modified: branches/trunk-reorg/thirdparty/slime/swank-scl.lisp ============================================================================== --- branches/trunk-reorg/thirdparty/slime/swank-scl.lisp (original) +++ branches/trunk-reorg/thirdparty/slime/swank-scl.lisp Mon Feb 11 09:24:55 2008 @@ -1693,11 +1693,6 @@ ;;;; Inspecting -(defclass scl-inspector (backend-inspector) ()) - -(defimplementation make-default-inspector () - (make-instance 'scl-inspector)) - (defconstant +lowtag-symbols+ '(vm:even-fixnum-type vm:instance-pointer-type @@ -1740,10 +1735,9 @@ :key #'symbol-value))) (format t ", type: ~A" type-symbol)))))) -(defmethod inspect-for-emacs ((o t)) +(defmethod emacs-inspect ((o t)) (cond ((di::indirect-value-cell-p o) - (values (format nil "~A is a value cell." o) - `("Value: " (:value ,(c:value-cell-ref o))))) + `("Value: " (:value ,(c:value-cell-ref o)))) ((alien::alien-value-p o) (inspect-alien-value o)) (t @@ -1752,17 +1746,17 @@ (defun scl-inspect (o) (destructuring-bind (text labeledp . parts) (inspect::describe-parts o) - (values (format nil "~A~%" text) + (list* (format nil "~A~%" text) (if labeledp (loop for (label . value) in parts append (label-value-line label value)) (loop for value in parts for i from 0 append (label-value-line i value)))))) -(defmethod inspect-for-emacs ((o function)) +(defmethod emacs-inspect ((o function)) (let ((header (kernel:get-type o))) (cond ((= header vm:function-header-type) - (values (format nil "~A is a function." o) + (list* (format nil "~A is a function.~%" o) (append (label-value-line* ("Self" (kernel:%function-self o)) ("Next" (kernel:%function-next o)) @@ -1774,7 +1768,7 @@ (with-output-to-string (s) (disassem:disassemble-function o :stream s)))))) ((= header vm:closure-header-type) - (values (format nil "~A is a closure" o) + (list* (format nil "~A is a closure.~%" o) (append (label-value-line "Function" (kernel:%closure-function o)) `("Environment:" (:newline)) @@ -1788,8 +1782,7 @@ (call-next-method))))) -(defmethod inspect-for-emacs ((o kernel:code-component)) - (values (format nil "~A is a code data-block." o) +(defmethod emacs-inspect ((o kernel:code-component)) (append (label-value-line* ("code-size" (kernel:%code-code-size o)) @@ -1813,20 +1806,19 @@ (* vm:code-constants-offset vm:word-bytes)) (ash 1 vm:lowtag-bits)) (ash (kernel:%code-code-size o) vm:word-shift) - :stream s)))))))) + :stream s))))))) -(defmethod inspect-for-emacs ((o kernel:fdefn)) - (values (format nil "~A is a fdenf object." o) - (label-value-line* +(defmethod emacs-inspect ((o kernel:fdefn)) + (label-value-line* ("name" (kernel:fdefn-name o)) ("function" (kernel:fdefn-function o)) ("raw-addr" (sys:sap-ref-32 (sys:int-sap (kernel:get-lisp-obj-address o)) - (* vm:fdefn-raw-addr-slot vm:word-bytes)))))) + (* vm:fdefn-raw-addr-slot vm:word-bytes))))) -(defmethod inspect-for-emacs ((o array)) +(defmethod emacs-inspect ((o array)) (cond ((kernel:array-header-p o) - (values (format nil "~A is an array." o) + (list* (format nil "~A is an array.~%" o) (label-value-line* (:header (describe-primitive-type o)) (:rank (array-rank o)) @@ -1838,13 +1830,13 @@ (:displaced-p (kernel:%array-displaced-p o)) (:dimensions (array-dimensions o))))) (t - (values (format nil "~A is an simple-array." o) + (list* (format nil "~A is an simple-array.~%" o) (label-value-line* (:header (describe-primitive-type o)) (:length (length o))))))) -(defmethod inspect-for-emacs ((o simple-vector)) - (values (format nil "~A is a vector." o) +(defmethod emacs-inspect ((o simple-vector)) + (list* (format nil "~A is a vector.~%" o) (append (label-value-line* (:header (describe-primitive-type o)) @@ -1854,8 +1846,6 @@ append (label-value-line i (aref o i))))))) (defun inspect-alien-record (alien) - (values - (format nil "~A is an alien value." alien) (with-struct (alien::alien-value- sap type) alien (with-struct (alien::alien-record-type- kind name fields) type (append @@ -1865,16 +1855,14 @@ (:name name)) (loop for field in fields append (let ((slot (alien::alien-record-field-name field))) - (label-value-line slot (alien:slot alien slot))))))))) + (label-value-line slot (alien:slot alien slot)))))))) (defun inspect-alien-pointer (alien) - (values - (format nil "~A is an alien value." alien) - (with-struct (alien::alien-value- sap type) alien + (with-struct (alien::alien-value- sap type) alien (label-value-line* (:sap sap) (:type type) - (:to (alien::deref alien)))))) + (:to (alien::deref alien))))) (defun inspect-alien-value (alien) (typecase (alien::alien-value-type alien) Modified: branches/trunk-reorg/thirdparty/slime/swank.lisp ============================================================================== --- branches/trunk-reorg/thirdparty/slime/swank.lisp (original) +++ branches/trunk-reorg/thirdparty/slime/swank.lisp Mon Feb 11 09:24:55 2008 @@ -13,7 +13,7 @@ ;;; available to us here via the `SWANK-BACKEND' package. (defpackage :swank - (:use :common-lisp :swank-backend) + (:use :cl :swank-backend) (:export #:startup-multiprocessing #:start-server #:create-server @@ -24,8 +24,8 @@ #:print-indentation-lossage #:swank-debugger-hook #:run-after-init-hook - #:inspect-for-emacs - #:inspect-slot-for-emacs + #:emacs-inspect + ;;#:inspect-slot-for-emacs ;; These are user-configurable variables: #:*communication-style* #:*dont-close* @@ -2677,176 +2677,19 @@ ;;;; Inspecting -(defun common-seperated-spec (list &optional (callback (lambda (v) - `(:value ,v)))) - (butlast - (loop - for i in list - collect (funcall callback i) - collect ", "))) - -(defun inspector-princ (list) - "Like princ-to-string, but don't rewrite (function foo) as #'foo. -Do NOT pass circular lists to this function." - (let ((*print-pprint-dispatch* (copy-pprint-dispatch))) - (set-pprint-dispatch '(cons (member function)) nil) - (princ-to-string list))) - -(defmethod inspect-for-emacs ((object cons)) - (if (consp (cdr object)) - (inspect-for-emacs-list object) - (inspect-for-emacs-simple-cons object))) - -(defun inspect-for-emacs-simple-cons (cons) - (values "A cons cell." - (label-value-line* - ('car (car cons)) - ('cdr (cdr cons))))) - -(defun inspect-for-emacs-list (list) - (let ((maxlen 40)) - (multiple-value-bind (length tail) (safe-length list) - (flet ((frob (title list) - (let (lines) - (loop for i from 0 for rest on list do - (if (consp (cdr rest)) ; e.g. (A . (B . ...)) - (push (label-value-line i (car rest)) lines) - (progn ; e.g. (A . NIL) or (A . B) - (push (label-value-line i (car rest) :newline nil) lines) - (when (cdr rest) - (push '((:newline)) lines) - (push (label-value-line ':tail () :newline nil) lines)) - (loop-finish))) - finally - (setf lines (reduce #'append (nreverse lines) :from-end t))) - (values title (append '("Elements:" (:newline)) lines))))) - - (cond ((not length) ; circular - (frob "A circular list." - (cons (car list) - (ldiff (cdr list) list)))) - ((and (<= length maxlen) (not tail)) - (frob "A proper list." list)) - (tail - (frob "An improper list." list)) - (t - (frob "A proper list." list))))))) - -;; (inspect-for-emacs-list '#1=(a #1# . #1# )) - -(defun safe-length (list) - "Similar to `list-length', but avoid errors on improper lists. -Return two values: the length of the list and the last cdr. -NIL is returned if the list is circular." - (do ((n 0 (+ n 2)) ;Counter. - (fast list (cddr fast)) ;Fast pointer: leaps by 2. - (slow list (cdr slow))) ;Slow pointer: leaps by 1. - (nil) - (cond ((null fast) (return (values n nil))) - ((not (consp fast)) (return (values n fast))) - ((null (cdr fast)) (return (values (1+ n) (cdr fast)))) - ((and (eq fast slow) (> n 0)) (return nil)) - ((not (consp (cdr fast))) (return (values (1+ n) (cdr fast))))))) - -(defvar *slime-inspect-contents-limit* nil "How many elements of - a hash table or array to show by default. If table has more than - this then offer actions to view more. Set to nil for no limit." ) - -(defmethod inspect-for-emacs ((ht hash-table)) - (values (prin1-to-string ht) - (append - (label-value-line* - ("Count" (hash-table-count ht)) - ("Size" (hash-table-size ht)) - ("Test" (hash-table-test ht)) - ("Rehash size" (hash-table-rehash-size ht)) - ("Rehash threshold" (hash-table-rehash-threshold ht))) - (let ((weakness (hash-table-weakness ht))) - (when weakness - `("Weakness: " (:value ,weakness) (:newline)))) - (unless (zerop (hash-table-count ht)) - `((:action "[clear hashtable]" ,(lambda () (clrhash ht))) (:newline) - "Contents: " (:newline))) - (if (and *slime-inspect-contents-limit* - (>= (hash-table-count ht) *slime-inspect-contents-limit*)) - (inspect-bigger-piece-actions ht (hash-table-count ht)) - nil) - (loop for key being the hash-keys of ht - for value being the hash-values of ht - repeat (or *slime-inspect-contents-limit* most-positive-fixnum) - append `((:value ,key) " = " (:value ,value) - " " (:action "[remove entry]" - ,(let ((key key)) - (lambda () (remhash key ht)))) - (:newline)))))) - -(defun inspect-bigger-piece-actions (thing size) - (append - (if (> size *slime-inspect-contents-limit*) - (list (inspect-show-more-action thing) - '(:newline)) - nil) - (list (inspect-whole-thing-action thing size) - '(:newline)))) - -(defun inspect-whole-thing-action (thing size) - `(:action ,(format nil "Inspect all ~a elements." - size) - ,(lambda() - (let ((*slime-inspect-contents-limit* nil)) - (swank::inspect-object thing))))) - -(defun inspect-show-more-action (thing) - `(:action ,(format nil "~a elements shown. Prompt for how many to inspect..." - *slime-inspect-contents-limit* ) - ,(lambda() - (let ((*slime-inspect-contents-limit* - (progn (format t "How many elements should be shown? ") (read)))) - (swank::inspect-object thing))))) - -(defmethod inspect-for-emacs ((array array)) - (values "An array." - (append - (label-value-line* - ("Dimensions" (array-dimensions array)) - ("Its element type is" (array-element-type array)) - ("Total size" (array-total-size array)) - ("Adjustable" (adjustable-array-p array))) - (when (array-has-fill-pointer-p array) - (label-value-line "Fill pointer" (fill-pointer array))) - '("Contents:" (:newline)) - (if (and *slime-inspect-contents-limit* - (>= (array-total-size array) *slime-inspect-contents-limit*)) - (inspect-bigger-piece-actions array (length array)) - nil) - (loop for i below (or *slime-inspect-contents-limit* (array-total-size array)) - append (label-value-line i (row-major-aref array i)))))) - -(defmethod inspect-for-emacs ((char character)) - (values "A character." - (append - (label-value-line* - ("Char code" (char-code char)) - ("Lower cased" (char-downcase char)) - ("Upper cased" (char-upcase char))) - (if (get-macro-character char) - `("In the current readtable (" - (:value ,*readtable*) ") it is a macro character: " - (:value ,(get-macro-character char))))))) - (defvar *inspectee*) +(defvar *inspectee-content*) (defvar *inspectee-parts*) (defvar *inspectee-actions*) -(defvar *inspector-stack* '()) -(defvar *inspector-history* (make-array 10 :adjustable t :fill-pointer 0)) -(declaim (type vector *inspector-history*)) -(defvar *inspect-length* 30) +(defvar *inspector-stack*) +(defvar *inspector-history*) (defun reset-inspector () (setq *inspectee* nil - *inspector-stack* nil + *inspectee-content* nil *inspectee-parts* (make-array 10 :adjustable t :fill-pointer 0) *inspectee-actions* (make-array 10 :adjustable t :fill-pointer 0) + *inspector-stack* '() *inspector-history* (make-array 10 :adjustable t :fill-pointer 0))) (defslimefun init-inspector (string) @@ -2854,54 +2697,57 @@ (reset-inspector) (inspect-object (eval (read-from-string string))))) -(defun print-part-to-string (value) - (let ((string (to-string value)) - (pos (position value *inspector-history*))) - (if pos - (format nil "#~D=~A" pos string) - string))) +(defun inspect-object (o) + (push (setq *inspectee* o) *inspector-stack*) + (unless (find o *inspector-history*) + (vector-push-extend o *inspector-history*)) + (let ((*print-pretty* nil) ; print everything in the same line + (*print-circle* t) + (*print-readably* nil)) + (setq *inspectee-content* (inspector-content (emacs-inspect o)))) + (list :title (with-output-to-string (s) + (print-unreadable-object (o s :type t :identity t))) + :id (assign-index o *inspectee-parts*) + :content (content-range *inspectee-content* 0 500))) -(defun inspector-content-for-emacs (specs) +(defun inspector-content (specs) (loop for part in specs collect (etypecase part - (null ; XXX encourages sloppy programming - nil) + ;;(null ; XXX encourages sloppy programming + ;; nil) (string part) (cons (destructure-case part ((:newline) - (string #\newline)) + '#.(string #\newline)) ((:value obj &optional str) - (value-part-for-emacs obj str)) + (value-part obj str)) ((:action label lambda &key (refreshp t)) - (action-part-for-emacs label lambda refreshp))))))) + (action-part label lambda refreshp))))))) (defun assign-index (object vector) (let ((index (fill-pointer vector))) (vector-push-extend object vector) index)) -(defun value-part-for-emacs (object string) +(defun value-part (object string) (list :value (or string (print-part-to-string object)) (assign-index object *inspectee-parts*))) -(defun action-part-for-emacs (label lambda refreshp) +(defun action-part (label lambda refreshp) (list :action label (assign-index (list lambda refreshp) *inspectee-actions*))) -(defun inspect-object (object) - (push (setq *inspectee* object) *inspector-stack*) - (unless (find object *inspector-history*) - (vector-push-extend object *inspector-history*)) - (let ((*print-pretty* nil) ; print everything in the same line - (*print-circle* t) - (*print-readably* nil)) - (multiple-value-bind (_ content) (inspect-for-emacs object) - (declare (ignore _)) - (list :title (with-output-to-string (s) - (print-unreadable-object (object s :type t :identity t))) - :id (assign-index object *inspectee-parts*) - :content (inspector-content-for-emacs content))))) +(defun print-part-to-string (value) + (let ((string (to-string value)) + (pos (position value *inspector-history*))) + (if pos + (format nil "#~D=~A" pos string) + string))) + +(defun content-range (list start end) + (let* ((len (length list)) (end (min len end))) + (list (subseq list start end) len start end))) (defslimefun inspector-nth-part (index) (aref *inspectee-parts* index)) @@ -2910,18 +2756,20 @@ (with-buffer-syntax () (inspect-object (inspector-nth-part index)))) +(defslimefun inspector-range (from to) + (content-range *inspectee-content* from to)) + (defslimefun inspector-call-nth-action (index &rest args) - (destructuring-bind (action-lambda refreshp) - (aref *inspectee-actions* index) - (apply action-lambda args) + (destructuring-bind (fun refreshp) (aref *inspectee-actions* index) + (apply fun args) (if refreshp (inspect-object (pop *inspector-stack*)) ;; tell emacs that we don't want to refresh the inspector buffer nil))) (defslimefun inspector-pop () - "Drop the inspector stack and inspect the second element. Return -nil if there's no second element." + "Drop the inspector stack and inspect the second element. +Return nil if there's no second element." (with-buffer-syntax () (cond ((cdr *inspector-stack*) (pop *inspector-stack*) @@ -2931,10 +2779,10 @@ (defslimefun inspector-next () "Inspect the next element in the *inspector-history*." (with-buffer-syntax () - (let ((position (position *inspectee* *inspector-history*))) - (cond ((= (1+ position) (length *inspector-history*)) + (let ((pos (position *inspectee* *inspector-history*))) + (cond ((= (1+ pos) (length *inspector-history*)) nil) - (t (inspect-object (aref *inspector-history* (1+ position)))))))) + (t (inspect-object (aref *inspector-history* (1+ pos)))))))) (defslimefun inspector-reinspect () (inspect-object *inspectee*)) @@ -2968,6 +2816,111 @@ (reset-inspector) (inspect-object (frame-var-value frame var)))) +;;;;; Lists + +(defmethod emacs-inspect ((o cons)) + (if (consp (cdr o)) + (inspect-list o) + (inspect-cons o))) + +(defun inspect-cons (cons) + (label-value-line* + ('car (car cons)) + ('cdr (cdr cons)))) + +;; (inspect-list '#1=(a #1# . #1# )) +;; (inspect-list (list* 'a 'b 'c)) +;; (inspect-list (make-list 10000)) + +(defun inspect-list (list) + (multiple-value-bind (length tail) (safe-length list) + (flet ((frob (title list) + (list* title '(:newline) (inspect-list-aux list)))) + (cond ((not length) + (frob "A circular list:" + (cons (car list) + (ldiff (cdr list) list)))) + ((not tail) + (frob "A proper list:" list)) + (t + (frob "An improper list:" list)))))) + +(defun inspect-list-aux (list) + (loop for i from 0 for rest on list while (consp rest) append + (cond ((consp (cdr rest)) + (label-value-line i (car rest))) + ((cdr rest) + (label-value-line* (i (car rest)) + (:tail (cdr rest)))) + (t + (label-value-line i (car rest)))))) + +(defun safe-length (list) + "Similar to `list-length', but avoid errors on improper lists. +Return two values: the length of the list and the last cdr. +Return NIL if LIST is circular." + (do ((n 0 (+ n 2)) ;Counter. + (fast list (cddr fast)) ;Fast pointer: leaps by 2. + (slow list (cdr slow))) ;Slow pointer: leaps by 1. + (nil) + (cond ((null fast) (return (values n nil))) + ((not (consp fast)) (return (values n fast))) + ((null (cdr fast)) (return (values (1+ n) (cdr fast)))) + ((and (eq fast slow) (> n 0)) (return nil)) + ((not (consp (cdr fast))) (return (values (1+ n) (cdr fast))))))) + +;;;;; Hashtables + +(defmethod emacs-inspect ((ht hash-table)) + (append + (label-value-line* + ("Count" (hash-table-count ht)) + ("Size" (hash-table-size ht)) + ("Test" (hash-table-test ht)) + ("Rehash size" (hash-table-rehash-size ht)) + ("Rehash threshold" (hash-table-rehash-threshold ht))) + (let ((weakness (hash-table-weakness ht))) + (when weakness + (label-value-line "Weakness:" weakness))) + (unless (zerop (hash-table-count ht)) + `((:action "[clear hashtable]" + ,(lambda () (clrhash ht))) (:newline) + "Contents: " (:newline))) + (loop for key being the hash-keys of ht + for value being the hash-values of ht + append `((:value ,key) " = " (:value ,value) + " " (:action "[remove entry]" + ,(let ((key key)) + (lambda () (remhash key ht)))) + (:newline))))) + +;;;;; Arrays + +(defmethod emacs-inspect ((array array)) + (append + (label-value-line* + ("Dimensions" (array-dimensions array)) + ("Element type" (array-element-type array)) + ("Total size" (array-total-size array)) + ("Adjustable" (adjustable-array-p array))) + (when (array-has-fill-pointer-p array) + (label-value-line "Fill pointer" (fill-pointer array))) + '("Contents:" (:newline)) + (loop for i below (array-total-size array) + append (label-value-line i (row-major-aref array i))))) + +;;;;; Chars + +(defmethod emacs-inspect ((char character)) + (append + (label-value-line* + ("Char code" (char-code char)) + ("Lower cased" (char-downcase char)) + ("Upper cased" (char-upcase char))) + (if (get-macro-character char) + `("In the current readtable (" + (:value ,*readtable*) ") it is a macro character: " + (:value ,(get-macro-character char)))))) ;;;; Thread listing From hhubner at common-lisp.net Mon Feb 11 14:27:46 2008 From: hhubner at common-lisp.net (hhubner at common-lisp.net) Date: Mon, 11 Feb 2008 09:27:46 -0500 (EST) Subject: [bknr-cvs] r2476 - branches/trunk-reorg/thirdparty/cl-gd-0.5.6 Message-ID: <20080211142746.23D081603B@common-lisp.net> Author: hhubner Date: Mon Feb 11 09:27:45 2008 New Revision: 2476 Modified: branches/trunk-reorg/thirdparty/cl-gd-0.5.6/ (props changed) branches/trunk-reorg/thirdparty/cl-gd-0.5.6/cl-gd.asd Log: ignore .so file, fix conflict Modified: branches/trunk-reorg/thirdparty/cl-gd-0.5.6/cl-gd.asd ============================================================================== --- branches/trunk-reorg/thirdparty/cl-gd-0.5.6/cl-gd.asd (original) +++ branches/trunk-reorg/thirdparty/cl-gd-0.5.6/cl-gd.asd Mon Feb 11 09:27:45 2008 @@ -54,9 +54,5 @@ (:file "drawing") (:file "strings") (:file "misc")) -<<<<<<< .mine :depends-on (#-clisp :uffi #+clisp :cffi-uffi-compat)) -======= - :depends-on (:uffi)) ->>>>>>> .r2473 From ksprotte at common-lisp.net Mon Feb 11 17:22:23 2008 From: ksprotte at common-lisp.net (ksprotte at common-lisp.net) Date: Mon, 11 Feb 2008 12:22:23 -0500 (EST) Subject: [bknr-cvs] r2477 - branches/trunk-reorg/thirdparty/kmrcl-1.97 Message-ID: <20080211172223.D90EB68223@common-lisp.net> Author: ksprotte Date: Mon Feb 11 12:22:22 2008 New Revision: 2477 Modified: branches/trunk-reorg/thirdparty/kmrcl-1.97/package.lisp Log: kmrcl removed two offending symbols from export list Modified: branches/trunk-reorg/thirdparty/kmrcl-1.97/package.lisp ============================================================================== --- branches/trunk-reorg/thirdparty/kmrcl-1.97/package.lisp (original) +++ branches/trunk-reorg/thirdparty/kmrcl-1.97/package.lisp Mon Feb 11 12:22:22 2008 @@ -119,7 +119,7 @@ #:cwd #:quit #:command-line-arguments - #:copy-file + ;; #:copy-file #:run-shell-command ;; lists.lisp @@ -253,7 +253,7 @@ #:init/repl ;; From web-utils - #:*base-url* + ;; #:*base-url* #:base-url! #:make-url #:*standard-html-header* From ksprotte at common-lisp.net Mon Feb 11 17:22:52 2008 From: ksprotte at common-lisp.net (ksprotte at common-lisp.net) Date: Mon, 11 Feb 2008 12:22:52 -0500 (EST) Subject: [bknr-cvs] r2478 - branches/trunk-reorg/thirdparty/arnesi Message-ID: <20080211172252.41E1268243@common-lisp.net> Author: ksprotte Date: Mon Feb 11 12:22:52 2008 New Revision: 2478 Modified: branches/trunk-reorg/thirdparty/arnesi/arnesi.asd Log: removed slime dependency Modified: branches/trunk-reorg/thirdparty/arnesi/arnesi.asd ============================================================================== --- branches/trunk-reorg/thirdparty/arnesi/arnesi.asd (original) +++ branches/trunk-reorg/thirdparty/arnesi/arnesi.asd Mon Feb 11 12:22:52 2008 @@ -35,7 +35,7 @@ (:file "lisp1" :depends-on ("packages" "lambda-list" "one-liners" "walk" "unwalk")) (:file "lexenv" :depends-on ("packages" "one-liners")) (:file "list" :depends-on ("packages" "one-liners" "accumulation" "flow-control")) - (:file "log" :depends-on ("packages" "numbers" "hash" "io")) + ;; (:file "log" :depends-on ("packages" "numbers" "hash" "io")) (:file "matcher" :depends-on ("packages" "hash" "list" "flow-control" "one-liners")) (:file "mop" :depends-on ("packages" "mopp")) (:file "mopp" :depends-on ("packages" "list" "flow-control")) @@ -63,7 +63,7 @@ :components ((:file "accumulation" :depends-on ("suite")) (:file "call-cc" :depends-on ("suite")) (:file "http" :depends-on ("suite")) - (:file "log" :depends-on ("suite")) + ;; (:file "log" :depends-on ("suite")) (:file "matcher" :depends-on ("suite")) (:file "numbers" :depends-on ("suite")) (:file "queue" :depends-on ("suite")) From ksprotte at common-lisp.net Mon Feb 11 17:24:44 2008 From: ksprotte at common-lisp.net (ksprotte at common-lisp.net) Date: Mon, 11 Feb 2008 12:24:44 -0500 (EST) Subject: [bknr-cvs] r2479 - in branches/trunk-reorg/projects/bos: m2 web Message-ID: <20080211172444.B4E3A1603F@common-lisp.net> Author: ksprotte Date: Mon Feb 11 12:24:41 2008 New Revision: 2479 Modified: branches/trunk-reorg/projects/bos/m2/m2.lisp branches/trunk-reorg/projects/bos/m2/mail-generator.lisp branches/trunk-reorg/projects/bos/m2/packages.lisp branches/trunk-reorg/projects/bos/web/allocation-area-handlers.lisp branches/trunk-reorg/projects/bos/web/allocation-cache-handlers.lisp branches/trunk-reorg/projects/bos/web/boi-handlers.lisp branches/trunk-reorg/projects/bos/web/bos.web.asd branches/trunk-reorg/projects/bos/web/contract-handlers.lisp branches/trunk-reorg/projects/bos/web/contract-image-handler.lisp branches/trunk-reorg/projects/bos/web/kml-handlers.lisp branches/trunk-reorg/projects/bos/web/languages-handler.lisp branches/trunk-reorg/projects/bos/web/map-browser-handler.lisp branches/trunk-reorg/projects/bos/web/map-handlers.lisp branches/trunk-reorg/projects/bos/web/news-handlers.lisp branches/trunk-reorg/projects/bos/web/packages.lisp branches/trunk-reorg/projects/bos/web/poi-handlers.lisp branches/trunk-reorg/projects/bos/web/reports-xml-handler.lisp branches/trunk-reorg/projects/bos/web/sponsor-handlers.lisp branches/trunk-reorg/projects/bos/web/web-macros.lisp branches/trunk-reorg/projects/bos/web/web-utils.lisp branches/trunk-reorg/projects/bos/web/webserver.lisp Log: bos changes for trunk-reorg; unfinished, committed for backup Modified: branches/trunk-reorg/projects/bos/m2/m2.lisp ============================================================================== --- branches/trunk-reorg/projects/bos/m2/m2.lisp (original) +++ branches/trunk-reorg/projects/bos/m2/m2.lisp Mon Feb 11 12:24:41 2008 @@ -189,8 +189,8 @@ (defclass editor-only-handler () ()) -(defmethod bknr.web:authorized-p ((handler editor-only-handler) req) - (editor-p (bknr-request-user req))) +(defmethod bknr.web:authorized-p ((handler editor-only-handler)) + (editor-p bknr.web:*user*)) ;;;; CONTRACT @@ -446,11 +446,12 @@ (incf retval (length (contract-m2s contract)))) retval)) -(defun string-safe (string) - (if string - (escape-nl (with-output-to-string (s) - (net.html.generator::emit-safe s string))) - "")) +;; trunk-reorg adaption +;; (defun string-safe (string) +;; (if string +;; (escape-nl (with-output-to-string (s) +;; (net.html.generator::emit-safe s string))) +;; "")) (defun make-m2-javascript (sponsor) "Erzeugt das Quadratmeter-Javascript f?r die angegebenen Contracts" Modified: branches/trunk-reorg/projects/bos/m2/mail-generator.lisp ============================================================================== --- branches/trunk-reorg/projects/bos/m2/mail-generator.lisp (original) +++ branches/trunk-reorg/projects/bos/m2/mail-generator.lisp Mon Feb 11 12:24:41 2008 @@ -251,8 +251,8 @@ (ignore-errors (delete-file (contract-pdf-pathname contract :print t)))) -(defun mail-backoffice-sponsor-data (contract req) - (with-query-params (req numsqm country email name address date language) +(defun mail-backoffice-sponsor-data (contract) + (with-query-params (numsqm country email name address date language) (let ((parts (list (make-html-part (format nil " @@ -294,7 +294,7 @@ (mail-contract-data contract "Manually entered sponsor" parts)))) (defun mail-manual-sponsor-data (req) - (with-query-params (req contract-id vorname name strasse plz ort email telefon want-print donationcert-yearly) + (with-query-params (contract-id vorname name strasse plz ort email telefon want-print donationcert-yearly) (let* ((contract (store-object-with-id (parse-integer contract-id))) (sponsor-id (store-object-id (contract-sponsor contract))) (parts (list (make-html-part (format nil " @@ -363,7 +363,7 @@ (error "cannot find WorldPay callback params for contract ~A~%" contract-id))) (defun mail-worldpay-sponsor-data (req) - (with-query-params (req contract-id) + (with-query-params (contract-id) (let* ((contract (store-object-with-id (parse-integer contract-id))) (params (get-worldpay-params contract-id)) (parts (list (make-html-part (format nil " Modified: branches/trunk-reorg/projects/bos/m2/packages.lisp ============================================================================== --- branches/trunk-reorg/projects/bos/m2/packages.lisp (original) +++ branches/trunk-reorg/projects/bos/m2/packages.lisp Mon Feb 11 12:24:41 2008 @@ -54,7 +54,7 @@ :bknr.statistics :bknr.rss :bos.m2.config - :net.post-office + :cl-smtp :kmrcl :cxml :cl-mime Modified: branches/trunk-reorg/projects/bos/web/allocation-area-handlers.lisp ============================================================================== --- branches/trunk-reorg/projects/bos/web/allocation-area-handlers.lisp (original) +++ branches/trunk-reorg/projects/bos/web/allocation-area-handlers.lisp Mon Feb 11 12:24:41 2008 @@ -6,8 +6,8 @@ (defclass allocation-area-handler (admin-only-handler edit-object-handler) ()) -(defmethod handle-object-form ((handler allocation-area-handler) action (allocation-area (eql nil)) req) - (with-bos-cms-page (req :title "Allocation Areas") +(defmethod handle-object-form ((handler allocation-area-handler) action (allocation-area (eql nil))) + (with-bos-cms-page (:title "Allocation Areas") (html (:h2 "Defined allocation areas") ((:table :border "1") @@ -27,8 +27,8 @@ (:td (:princ-safe (round (allocation-area-percent-used allocation-area))) "%"))))) (:p (cmslink "create-allocation-area" "Create new allocation area"))))) -(defmethod handle-object-form ((handler allocation-area-handler) action allocation-area req) - (with-bos-cms-page (req :title "Allocation Area") +(defmethod handle-object-form ((handler allocation-area-handler) action allocation-area) + (with-bos-cms-page (:title "Allocation Area") (with-slots (active-p left top width height) allocation-area (html ((:table :border "1") @@ -75,15 +75,15 @@ do (html (:td ((:a :href #?"/enlarge-overview/$(tile-x)/$(tile-y)") ((:img :width "90" :height "90" :border "0" :src #?"/overview/$(tile-x)/$(tile-y)")))))))))))))) -(defmethod handle-object-form ((handler allocation-area-handler) (action (eql :delete)) allocation-area req) +(defmethod handle-object-form ((handler allocation-area-handler) (action (eql :delete)) allocation-area) (delete-object allocation-area) - (with-bos-cms-page (req :title "Allocation area has been deleted") + (with-bos-cms-page (:title "Allocation area has been deleted") (:h2 "The allocation area has been deleted"))) (defclass allocation-area-gfx-handler (editor-only-handler object-handler) ()) -(defmethod handle-object ((handler allocation-area-gfx-handler) allocation-area req) +(defmethod handle-object ((handler allocation-area-gfx-handler) allocation-area) (cl-gd:with-image* ((allocation-area-width allocation-area) (allocation-area-height allocation-area) t) (with-slots (left top width height) allocation-area @@ -128,29 +128,27 @@ (defclass create-allocation-area-handler (admin-only-handler form-handler) ()) -(defmethod handle-form ((handler create-allocation-area-handler) action req) - (with-query-params (req x y left top) +(defmethod handle-form ((handler create-allocation-area-handler) action) + (with-query-params (x y left top) (cond ((and x y left top) (destructuring-bind (x y left top) (mapcar #'parse-integer (list x y left top)) (if (or (some (complement #'plusp) (list x y left top)) (<= x left) (<= y top)) - (with-bos-cms-page (req :title "Invalid area selected") + (with-bos-cms-page (:title "Invalid area selected") (:h2 "Choose upper left corner first, then lower-right corner")) (redirect (format nil "/allocation-area/~D" (store-object-id - (make-allocation-rectangle left top (- x left) (- y top)))) - req)))) + (make-allocation-rectangle left top (- x left) (- y top)))))))) ((and x y) (redirect (format nil "/map-browser/~A/~A?heading=~A&chosen-url=~A&" x y (uriencode-string "Choose lower right point of allocation area") (uriencode-string (format nil "~A?left=~A&top=~A&" - (uri-path (request-uri req)) - x y))) - req)) + (uri-path (hunchentoot:request-uri)) + x y))))) (t - (with-bos-cms-page (req :title "Create allocation area") + (with-bos-cms-page (:title "Create allocation area") ((:form :method "POST" :enctype "multipart/form-data")) ((:table :border "0") (:tr ((:td :colspan "2") @@ -163,23 +161,22 @@ (:tr (:td "Start-Y") (:td (text-field "start-y" :value 0 :size 5))) (:tr (:td (submit-button "rectangle" "rectangle"))))))))) -(defmethod handle-form ((handler create-allocation-area-handler) (action (eql :rectangle)) req) - (with-query-params (req start-x start-y) +(defmethod handle-form ((handler create-allocation-area-handler) (action (eql :rectangle))) + (with-query-params (start-x start-y) (redirect (format nil "/map-browser/~A/~A?heading=~A&chosen-url=~A&" start-x start-y (uriencode-string "Choose upper left point of allocation area") - (uriencode-string (format nil "~A?" (uri-path (request-uri req))))) - req))) + (uriencode-string (format nil "~A?" (uri-path (hunchentoot:request-uri)))))))) -(defmethod handle-form ((handler create-allocation-area-handler) (action (eql :upload)) req) - (let ((uploaded-text-file (cdr (find "text-file" (request-uploaded-files req) :test #'equal :key #'car)))) +(defmethod handle-form ((handler create-allocation-area-handler) (action (eql :upload))) + (let ((uploaded-text-file (cdr (find "text-file" (request-uploaded-files) :test #'equal :key #'car)))) (cond ((not uploaded-text-file) - (with-bos-cms-page (req :title "No Text file uploaded") + (with-bos-cms-page (:title "No Text file uploaded") (:h2 "File not uploaded") (:p "Please upload your text file containing the allocation polygon UTM coordinates"))) (t - (with-bos-cms-page (req :title #?"Importing allocation polygons from text file $(uploaded-text-file)") + (with-bos-cms-page (:title #?"Importing allocation polygons from text file $(uploaded-text-file)") (handler-case (let* ((vertices (polygon-from-text-file uploaded-text-file)) (existing-area (find (coerce vertices 'list) Modified: branches/trunk-reorg/projects/bos/web/allocation-cache-handlers.lisp ============================================================================== --- branches/trunk-reorg/projects/bos/web/allocation-cache-handlers.lisp (original) +++ branches/trunk-reorg/projects/bos/web/allocation-cache-handlers.lisp Mon Feb 11 12:24:41 2008 @@ -5,8 +5,8 @@ (defclass allocation-cache-handler (admin-only-handler page-handler) ()) -(defmethod handle ((handler allocation-cache-handler) req) - (with-bos-cms-page (req :title "Allocation Cache") +(defmethod handle ((handler allocation-cache-handler)) + (with-bos-cms-page (:title "Allocation Cache") (html (:pre (:princ (with-output-to-string (*standard-output*) Modified: branches/trunk-reorg/projects/bos/web/boi-handlers.lisp ============================================================================== --- branches/trunk-reorg/projects/bos/web/boi-handlers.lisp (original) +++ branches/trunk-reorg/projects/bos/web/boi-handlers.lisp Mon Feb 11 12:24:41 2008 @@ -6,8 +6,8 @@ (defclass boi-handler (page-handler) ()) -(defmethod authorized-p ((handler boi-handler) req) - (bos.m2:editor-p (bknr-request-user req))) +(defmethod authorized-p ((handler boi-handler)) + (bos.m2:editor-p bknr.web:*user*)) (defclass create-contract-handler (boi-handler) ()) @@ -20,9 +20,9 @@ (error "Invalid sponsor ID (wrong type)")) sponsor)) -(defmethod handle ((handler create-contract-handler) req) - (with-xml-error-handler (req) - (with-query-params (req num-sqm country sponsor-id name paid expires) +(defmethod handle ((handler create-contract-handler)) + (with-xml-error-handler () + (with-query-params (num-sqm country sponsor-id name paid expires) (setf num-sqm (ignore-errors (parse-integer num-sqm :junk-allowed t))) (unless num-sqm (error "missing or invalid num-sqm parameter")) @@ -53,9 +53,9 @@ (defclass pay-contract-handler (boi-handler) ()) -(defmethod handle ((handler pay-contract-handler) req) - (with-xml-error-handler (req) - (with-query-params (req contract-id name) +(defmethod handle ((handler pay-contract-handler)) + (with-xml-error-handler () + (with-query-params (contract-id name) (unless contract-id (error "missing contract-id parameter")) (let ((contract (get-contract (or (ignore-errors (parse-integer contract-id)) @@ -65,7 +65,7 @@ (with-transaction (:contract-paid) (contract-set-paidp contract (format nil "~A: manually set paid by ~A" (format-date-time) - (user-login (bknr-request-user req)))) + (user-login bknr.web:*user*))) (when name (setf (user-full-name (contract-sponsor contract)) name)))) (with-xml-response () @@ -77,9 +77,9 @@ (defclass cancel-contract-handler (boi-handler) ()) -(defmethod handle ((handler cancel-contract-handler) req) - (with-xml-error-handler (req) - (with-query-params (req contract-id) +(defmethod handle ((handler cancel-contract-handler)) + (with-xml-error-handler () + (with-query-params (contract-id) (unless contract-id (error "missing contract-id parameter")) (let ((contract (get-contract (or (ignore-errors (parse-integer contract-id)) Modified: branches/trunk-reorg/projects/bos/web/bos.web.asd ============================================================================== --- branches/trunk-reorg/projects/bos/web/bos.web.asd (original) +++ branches/trunk-reorg/projects/bos/web/bos.web.asd Mon Feb 11 12:24:41 2008 @@ -16,7 +16,7 @@ :description "worldpay test web server" :long-description "" - :depends-on (:bknr-web :bknr-modules :bos.m2 :cxml) + :depends-on (:bknr-web :bknr-modules :bos.m2 :cxml :acl-compat) :components ((:file "packages") (:file "utf-8" :depends-on ("packages")) Modified: branches/trunk-reorg/projects/bos/web/contract-handlers.lisp ============================================================================== --- branches/trunk-reorg/projects/bos/web/contract-handlers.lisp (original) +++ branches/trunk-reorg/projects/bos/web/contract-handlers.lisp Mon Feb 11 12:24:41 2008 @@ -9,8 +9,8 @@ (defparameter *show-m2s* 5) -(defmethod handle-object ((handler contract-handler) contract req) - (with-bos-cms-page (req :title "Displaying contract details") +(defmethod handle-object ((handler contract-handler) contract) + (with-bos-cms-page (:title "Displaying contract details") ((:table :border "0") (:tr (:td "sponsor") (:td (html-edit-link (contract-sponsor contract)))) Modified: branches/trunk-reorg/projects/bos/web/contract-image-handler.lisp ============================================================================== --- branches/trunk-reorg/projects/bos/web/contract-image-handler.lisp (original) +++ branches/trunk-reorg/projects/bos/web/contract-image-handler.lisp Mon Feb 11 12:24:41 2008 @@ -17,7 +17,7 @@ ;; We manipulate pixels in a temporary array which is copied to the GD image as ;; a whole for performance reasons. The FFI is way too slow to manipulate individual pixels. (let ((work-array (make-array (list width height) :element-type 'fixnum :initial-element 0)) - (color (parse-color (or (second (decoded-handler-path handler req)) "ffff00")))) + (color (parse-color (or (second (decoded-handler-path handler)) "ffff00")))) (flet ((set-pixel (x y) (decf x left) (decf y top) Modified: branches/trunk-reorg/projects/bos/web/kml-handlers.lisp ============================================================================== --- branches/trunk-reorg/projects/bos/web/kml-handlers.lisp (original) +++ branches/trunk-reorg/projects/bos/web/kml-handlers.lisp Mon Feb 11 12:24:41 2008 @@ -40,7 +40,7 @@ (defclass contract-kml-handler (object-handler) ()) -(defmethod handle-object ((handler contract-kml-handler) (contract contract) req) +(defmethod handle-object ((handler contract-kml-handler) (contract contract)) (with-xml-response (:content-type "application/vnd.google-earth.kml+xml" :root-element "kml") ;; when name is xmlns, the attribute does not show up - why (?) ;; (attribute "xmlns" "http://earth.google.com/kml/2.2") @@ -77,5 +77,5 @@ (with-element "coordinates" (text (kml-format-points (list (contract-center-lon-lat c))))))))))))) -(defmethod handle-object ((handle-object contract-kml-handler) (object null) req) +(defmethod handle-object ((handle-object contract-kml-handler) (object null)) (error "Contract not found.")) Modified: branches/trunk-reorg/projects/bos/web/languages-handler.lisp ============================================================================== --- branches/trunk-reorg/projects/bos/web/languages-handler.lisp (original) +++ branches/trunk-reorg/projects/bos/web/languages-handler.lisp Mon Feb 11 12:24:41 2008 @@ -5,11 +5,11 @@ (defclass languages-handler (admin-only-handler form-handler) ()) -(defmethod handle-form ((handler languages-handler) action req) - (with-bos-cms-page (req :title "Languages") +(defmethod handle-form ((handler languages-handler) action) + (with-bos-cms-page (:title "Languages") (case action (:add (handler-case - (with-query-params (req code name) + (with-query-params (code name) (when (and code name) (make-object 'website-language :code code :name name) (html (:h2 "Language " (:princ-safe code) " (" (:princ-safe name) ") created")))) @@ -17,7 +17,7 @@ (html (:h2 "Error creating language") (:pre (:princ-safe e)))))) (:delete (handler-case - (with-query-params (req delete-code) + (with-query-params (delete-code) (when delete-code (delete-object (language-with-code delete-code)) (html (:h2 "Language " (:princ-safe delete-code) " deleted")))) Modified: branches/trunk-reorg/projects/bos/web/map-browser-handler.lisp ============================================================================== --- branches/trunk-reorg/projects/bos/web/map-browser-handler.lisp (original) +++ branches/trunk-reorg/projects/bos/web/map-browser-handler.lisp Mon Feb 11 12:24:41 2008 @@ -18,7 +18,7 @@ (defclass map-browser-handler (prefix-handler) ()) -(defun decode-coords-in-handler-path (handler req) +(defun decode-coords-in-handler-path (handler) (labels ((ensure-valid-coordinates (x y) (setq x (parse-integer x)) (setq y (parse-integer y)) @@ -30,30 +30,29 @@ (<= 0 y 10800)) (error "invalid coordinates ~A/~A" x y)) (list x y))) - (with-query-params (req xcoord ycoord) + (with-query-params (xcoord ycoord) (when (and xcoord ycoord) (return-from decode-coords-in-handler-path (ensure-valid-coordinates xcoord ycoord)))) - (let ((handler-arguments (decoded-handler-path handler req))) + (let ((handler-arguments (decoded-handler-path handler))) (when (and handler-arguments (< 1 (length handler-arguments))) (apply #'ensure-valid-coordinates handler-arguments))))) -(defmethod handle ((handler map-browser-handler) req) - (with-query-params (req chosen-url) +(defmethod handle ((handler map-browser-handler)) + (with-query-params (chosen-url) (when chosen-url (setf (session-variable :chosen-url) chosen-url))) - (with-query-params (req view-x view-y) - (destructuring-bind (&optional click-x click-y) (decode-ismap-query-string req) - (destructuring-bind (&optional point-x point-y) (decode-coords-in-handler-path handler req) - (with-query-params (req action) + (with-query-params (view-x view-y) + (destructuring-bind (&optional click-x click-y) (decode-ismap-query-string) + (destructuring-bind (&optional point-x point-y) (decode-coords-in-handler-path handler) + (with-query-params (action) (when (equal action "save") (if (session-variable :chosen-url) (redirect (format nil "~Ax=~D&y=~D" (session-variable :chosen-url) point-x - point-y) - req) - (with-bos-cms-page (req :title "Map Point Chooser") + point-y)) + (with-bos-cms-page (:title "Map Point Chooser") (html (:princ-safe "You chose " point-x " / " point-y)))) (return-from handle t))) (cond @@ -71,14 +70,14 @@ (click-coord-y (+ (tile-nw-y start-tile) click-y))) (setq point-x click-coord-x point-y click-coord-y) - (redirect (format nil "/map-browser/~D/~D" click-coord-x click-coord-y) req) + (redirect (format nil "/map-browser/~D/~D" click-coord-x click-coord-y)) (return-from handle t))) (cond ((and click-y (not point-y)) - (redirect (format nil "/map-browser/~D/~D" (* 30 click-x) (* 30 click-y)) req)) + (redirect (format nil "/map-browser/~D/~D" (* 30 click-x) (* 30 click-y)))) (point-y - (with-bos-cms-page (req :title "Map Point Chooser") - (with-query-params (req heading) + (with-bos-cms-page (:title "Map Point Chooser") + (with-query-params (heading) (when heading (html (:h2 (:princ-safe heading))))) (html @@ -133,7 +132,7 @@ ((:img :src "/images/map-cursor.png"))))))) (map-navigator req point-x point-y "/map-browser/" :formcheck "return updateCoords();"))) (t - (with-bos-cms-page (req :title "Map Point Chooser") + (with-bos-cms-page (:title "Map Point Chooser") (html ((:a :href "/map-browser/") ((:img :ismap "ismap" :src "/image/sl_all")))))))))))) \ No newline at end of file Modified: branches/trunk-reorg/projects/bos/web/map-handlers.lisp ============================================================================== --- branches/trunk-reorg/projects/bos/web/map-handlers.lisp (original) +++ branches/trunk-reorg/projects/bos/web/map-handlers.lisp Mon Feb 11 12:24:41 2008 @@ -34,7 +34,7 @@ (:tr (:td "Y:") (:td (text-field "ycoord" :size "5" :value y))) (:tr ))) (:td - (with-query-params (req background areas contracts) + (with-query-params (background areas contracts) ;; xxx should use tile-layers (unless (or background areas contracts) (setq background t @@ -52,15 +52,15 @@ (defclass image-tile-handler (object-handler) ()) -(defmethod object-handler-get-object ((handler image-tile-handler) req) - (destructuring-bind (x y &rest operations) (decoded-handler-path handler req) +(defmethod object-handler-get-object ((handler image-tile-handler)) + (destructuring-bind (x y &rest operations) (decoded-handler-path handler) (declare (ignore operations)) (setf x (parse-integer x)) (setf y (parse-integer y)) (ensure-map-tile x y))) -(defmethod handle-object ((handler image-tile-handler) (tile (eql nil)) req) - (error-404 req)) +(defmethod handle-object ((handler image-tile-handler) (tile (eql nil))) + (error-404)) (defun parse-operations (&rest operation-strings) (mapcar #'(lambda (operation-string) @@ -68,32 +68,33 @@ (apply #'list (make-keyword-from-string operation) arguments))) operation-strings)) -(defmethod handle-object ((handler image-tile-handler) tile req) - ;; xxx parse url another time - the parse result of - ;; object-handler-get-object should really be kept in the request - (destructuring-bind (x y &rest operation-strings) (decoded-handler-path handler req) - (declare (ignore x y)) - (let ((changed-time (image-tile-changed-time tile)) - (ims (header-slot-value req :if-modified-since))) - (setf (net.aserve::last-modified *ent*) changed-time) - #+(or) - (format t "; image-tile-handler handle-object: changed-time: ~A if-modified-since: ~A~%" (format-date-time changed-time) ims) - (if (or (not ims) - (> changed-time (date-to-universal-time ims))) - (let ((image (image-tile-image tile (apply #'parse-operations operation-strings)))) - (emit-image-to-browser req image :png - :date changed-time - :max-age 60) - (cl-gd:destroy-image image)) - (with-http-response (req *ent*) - (with-http-body (req *ent*) - ; do nothing - )))))) +;; trunk-reorg adaption +;; (defmethod handle-object ((handler image-tile-handler) tile) +;; ;; xxx parse url another time - the parse result of +;; ;; object-handler-get-object should really be kept in the request +;; (destructuring-bind (x y &rest operation-strings) (decoded-handler-path handler) +;; (declare (ignore x y)) +;; (let ((changed-time (image-tile-changed-time tile)) +;; (ims (header-slot-value req :if-modified-since))) +;; (format t "Warning: not setting last-modified of *ent* to changed-time") +;; #+(or) +;; (format t "; image-tile-handler handle-object: changed-time: ~A if-modified-since: ~A~%" (format-date-time changed-time) ims) +;; (if (or (not ims) +;; (> changed-time (date-to-universal-time ims))) +;; (let ((image (image-tile-image tile (apply #'parse-operations operation-strings)))) +;; (emit-image-to-browser req image :png +;; :date changed-time +;; :max-age 60) +;; (cl-gd:destroy-image image)) +;; (with-http-response (*ent*) +;; (with-http-body () +;; ; do nothing +;; )))))) (defclass enlarge-tile-handler (image-tile-handler) ()) -(defun tile-active-layers-from-request-params (tile req) +(defun tile-active-layers-from-request-params (tile) (let (active-layers (all-layer-names (mapcar #'symbol-name (image-tile-layers tile)))) (dolist (layer-name all-layer-names) @@ -101,25 +102,27 @@ (push layer-name active-layers))) (or (reverse active-layers) all-layer-names))) -(defun tile-url (tile x y req) +(defun tile-url (tile x y) (format nil "/overview/~D/~D~(~{/~A~}~)" x y - (tile-active-layers-from-request-params tile req))) + (tile-active-layers-from-request-params tile))) + +;; trunk-reorg adaption +;; (defmethod handle-object ((handler enlarge-tile-handler) tile) +;; (let ((ismap-coords (decode-ismap-query-string req)) +;; (tile-x (tile-nw-x tile)) +;; (tile-y (tile-nw-y tile))) +;; (if ismap-coords +;; (let* ((x (+ (floor (first ismap-coords) 4) tile-x)) +;; (y (+ (floor (second ismap-coords) 4) tile-y)) +;; (m2 (get-m2 x y)) +;; (contract-id (and m2 (m2-contract m2) (store-object-id (m2-contract m2))))) +;; (if contract-id +;; (redirect #?"/contract/$(contract-id)") +;; (with-bos-cms-page (:title "Not sold") +;; (html (:h2 "this square meter has not been sold yet"))))) +;; (with-bos-cms-page (:title "Browsing tile") +;; (:a ((:a :href (uri-path (hunchentoot:request-uri))) +;; ((:img :width "360" :ismap "ismap" :height "360" :border "0" :src (tile-url tile tile-x tile-y req))))) +;; (map-navigator req tile-x tile-y "/enlarge-overview/"))))) -(defmethod handle-object ((handler enlarge-tile-handler) tile req) - (let ((ismap-coords (decode-ismap-query-string req)) - (tile-x (tile-nw-x tile)) - (tile-y (tile-nw-y tile))) - (if ismap-coords - (let* ((x (+ (floor (first ismap-coords) 4) tile-x)) - (y (+ (floor (second ismap-coords) 4) tile-y)) - (m2 (get-m2 x y)) - (contract-id (and m2 (m2-contract m2) (store-object-id (m2-contract m2))))) - (if contract-id - (redirect #?"/contract/$(contract-id)" req) - (with-bos-cms-page (req :title "Not sold") - (html (:h2 "this square meter has not been sold yet"))))) - (with-bos-cms-page (req :title "Browsing tile") - (:a ((:a :href (uri-path (request-uri req))) - ((:img :width "360" :ismap "ismap" :height "360" :border "0" :src (tile-url tile tile-x tile-y req))))) - (map-navigator req tile-x tile-y "/enlarge-overview/"))))) \ No newline at end of file Modified: branches/trunk-reorg/projects/bos/web/news-handlers.lisp ============================================================================== --- branches/trunk-reorg/projects/bos/web/news-handlers.lisp (original) +++ branches/trunk-reorg/projects/bos/web/news-handlers.lisp Mon Feb 11 12:24:41 2008 @@ -9,10 +9,10 @@ (defclass edit-news-handler (editor-only-handler edit-object-handler) ()) -(defmethod handle-object-form ((handler edit-news-handler) action (news-item (eql nil)) req) +(defmethod handle-object-form ((handler edit-news-handler) action (news-item (eql nil))) (let ((language (session-variable :language))) - (with-bos-cms-page (req :title "Edit news items") - (content-language-chooser req) + (with-bos-cms-page (:title "Edit news items") + (content-language-chooser) (:h2 "Create new item") ((:form :method "post") (submit-button "new" "new")) @@ -29,13 +29,13 @@ (html (:h2 "No news items created yet")))))) -(defmethod handle-object-form ((handler edit-news-handler) (action (eql :new)) (news-item (eql nil)) req) - (redirect (format nil "/edit-news/~D" (store-object-id (make-news-item))) req)) +(defmethod handle-object-form ((handler edit-news-handler) (action (eql :new)) (news-item (eql nil))) + (redirect (format nil "/edit-news/~D" (store-object-id (make-news-item))))) -(defmethod handle-object-form ((handler edit-news-handler) action news-item req) +(defmethod handle-object-form ((handler edit-news-handler) action news-item) (let ((language (session-variable :language))) - (with-bos-cms-page (req :title "Edit news item") - (content-language-chooser req) + (with-bos-cms-page (:title "Edit news item") + (content-language-chooser) ((:script :type "text/javascript") "tinyMCE.init({ mode : 'textareas', theme : 'advanced' });") ((:form :method "post") @@ -48,15 +48,15 @@ :value (news-item-text news-item language)))) (:tr (:td (submit-button "save" "save") (submit-button "delete" "delete" :confirm "Really delete the news item?")))))))) -(defmethod handle-object-form ((handler edit-news-handler) (action (eql :save)) news-item req) +(defmethod handle-object-form ((handler edit-news-handler) (action (eql :save)) news-item) (let ((language (session-variable :language))) - (with-query-params (req title text) + (with-query-params (title text) (update-news-item news-item language :title title :text text) - (with-bos-cms-page (req :title "News item updated") + (with-bos-cms-page (:title "News item updated") (:h2 "Your changes have been saved") "You may " (cmslink (edit-object-url news-item) "continue editing the news item"))))) -(defmethod handle-object-form ((handler edit-news-handler) (action (eql :delete)) news-item req) +(defmethod handle-object-form ((handler edit-news-handler) (action (eql :delete)) news-item) (delete-object news-item) - (with-bos-cms-page (req :title "News item has been deleted") + (with-bos-cms-page (:title "News item has been deleted") (:h2 "The news item has been deleted"))) \ No newline at end of file Modified: branches/trunk-reorg/projects/bos/web/packages.lisp ============================================================================== --- branches/trunk-reorg/projects/bos/web/packages.lisp (original) +++ branches/trunk-reorg/projects/bos/web/packages.lisp Mon Feb 11 12:24:41 2008 @@ -8,8 +8,6 @@ :cl-user :cl-interpol :cl-ppcre - :net.aserve - :net.aserve.client :xhtml-generator :cxml :puri @@ -27,6 +25,5 @@ :bos.m2.config) (:nicknames :web :worldpay-test) (:shadowing-import-from :cl-interpol #:quote-meta-chars) - (:shadowing-import-from :acl-compat.mp #:process-kill #:process-wait) - (:import-from :net.html.generator #:*html-stream*) + (:shadowing-import-from :acl-compat.mp #:process-kill #:process-wait) (:export)) Modified: branches/trunk-reorg/projects/bos/web/poi-handlers.lisp ============================================================================== --- branches/trunk-reorg/projects/bos/web/poi-handlers.lisp (original) +++ branches/trunk-reorg/projects/bos/web/poi-handlers.lisp Mon Feb 11 12:24:41 2008 @@ -6,26 +6,26 @@ (defclass make-poi-handler (page-handler) ()) -(defmethod handle ((handler make-poi-handler) req) - (with-query-params (req name) +(defmethod handle ((handler make-poi-handler)) + (with-query-params (name) (cond ((find-store-object name :class 'poi) - (with-bos-cms-page (req :title "Duplicate POI name") + (with-bos-cms-page (:title "Duplicate POI name") (html (:h2 "Duplicate POI name") "A POI with that name exists already, please choose a unique name"))) ((not (scan #?r"(?i)^[a-z][-a-z0-9_]+$" name)) - (with-bos-cms-page (req :title "Bad technical name") + (with-bos-cms-page (:title "Bad technical name") (html (:h2 "Bad technical name") "Please use only alphanumerical characters, - and _ for technical POI names"))) (t - (redirect (edit-object-url (make-poi (session-variable :language) name)) req))))) + (redirect (edit-object-url (make-poi (session-variable :language) name))))))) (defclass edit-poi-handler (editor-only-handler edit-object-handler) () (:default-initargs :object-class 'poi :query-function #'find-poi)) -(defmethod handle-object-form ((handler edit-poi-handler) action (object (eql nil)) req) - (with-bos-cms-page (req :title "Choose POI") +(defmethod handle-object-form ((handler edit-poi-handler) action (object (eql nil))) + (with-bos-cms-page (:title "Choose POI") (if (store-objects-with-class 'poi) (html (:h2 "Choose a POI to edit") @@ -50,8 +50,8 @@ (html ((:img :src #?"/images/$(icon).gif"))))) (defmethod handle-object-form ((handler edit-poi-handler) - action (poi poi) req) - (with-query-params (req language shift shift-by) + action (poi poi)) + (with-query-params (language shift shift-by) (unless language (setq language (session-variable :language))) (when shift ;; change image order @@ -66,8 +66,8 @@ (setf (nth (+ shift-by old-position) new-images) tmp) (change-slot-values poi 'bos.m2::images new-images))) (setf (session-variable :language) language) - (with-bos-cms-page (req :title "Edit POI") - (content-language-chooser req) + (with-bos-cms-page (:title "Edit POI") + (content-language-chooser) (unless (poi-complete poi language) (html (:h2 "This POI is not complete in the current language - Please check that " "the location and all text fields are set and that at least one image " @@ -95,11 +95,11 @@ (html (:princ-safe (format nil "~D/~D " (first (poi-area poi)) (second (poi-area poi))))) (cmslink (format nil "map-browser/~A/~A?chosen-url=~A" (first (poi-area poi)) (second (poi-area poi)) - (uriencode-string (format nil "~A?action=save&" (uri-path (request-uri req))))) + (uriencode-string (format nil "~A?action=save&" (uri-path (hunchentoot:request-uri))))) "[relocate]")) (t (cmslink (format nil "map-browser/?chosen-url=~A" - (uriencode-string (format nil "~A?action=save&" (uri-path (request-uri req))))) + (uriencode-string (format nil "~A?action=save&" (uri-path (hunchentoot:request-uri))))) "[choose]"))))) (:tr (:td "icon") (:td (icon-chooser "icon" (poi-icon poi)))) @@ -167,8 +167,8 @@ (submit-button "delete" "delete" :confirm "Really delete the POI?")))))))) (defmethod handle-object-form ((handler edit-poi-handler) - (action (eql :save)) (poi poi) req) - (with-query-params (req published title subtitle description language x y icon movie) + (action (eql :save)) (poi poi)) + (with-query-params (published title subtitle description language x y icon movie) (unless language (setq language (session-variable :language))) (let ((args (list :title title :published published @@ -180,21 +180,20 @@ (when movie (setq args (append args (list :movies (list movie))))) (apply #'update-poi poi language args)) - (with-bos-cms-page (req :title "POI has been updated") + (with-bos-cms-page (:title "POI has been updated") (html (:h2 "Your changes have been saved") "You may " (cmslink (edit-object-url poi) "continue editing the POI") ".")))) (defmethod handle-object-form ((handler edit-poi-handler) (action (eql :upload-airal)) - (poi poi) - req) - (let ((uploaded-file (cdr (find "image-file" (request-uploaded-files req) :test #'equal :key #'car)))) + (poi poi)) + (let ((uploaded-file (cdr (find "image-file" (request-uploaded-files) :test #'equal :key #'car)))) (unless uploaded-file (error "no file uploaded in upload handler")) (cl-gd:with-image-from-file* (uploaded-file) (unless (and (eql (cl-gd:image-width) *poi-image-width*) (eql (cl-gd:image-height) *poi-image-height*)) - (with-bos-cms-page (req :title "Invalid image size") + (with-bos-cms-page (:title "Invalid image size") (:h2 "Invalid image size") (:p "The image needs to be " (:princ-safe *poi-image-width*) " pixels wide and " @@ -207,30 +206,27 @@ (change-slot-values poi 'airals (list (import-image uploaded-file :class-name 'store-image)))) (redirect (format nil "/edit-poi/~D" - (store-object-id poi)) req)) + (store-object-id poi)))) (defmethod handle-object-form ((handler edit-poi-handler) (action (eql :delete-airal)) - (poi poi) - req) + (poi poi)) (let ((airals (poi-airals poi))) (change-slot-values poi 'airals nil) (mapc #'delete-object airals)) (redirect (format nil "/edit-poi/~D" - (store-object-id poi)) req)) + (store-object-id poi)))) (defmethod handle-object-form ((handler edit-poi-handler) (action (eql :delete-movie)) - (poi poi) - req) + (poi poi)) (change-slot-values poi 'movies nil) - (redirect (format nil "/edit-poi/~D" (store-object-id poi)) req)) + (redirect (format nil "/edit-poi/~D" (store-object-id poi)))) (defmethod handle-object-form ((handler edit-poi-handler) (action (eql :upload-panorama)) - (poi poi) - req) - (let ((uploaded-file (cdr (find "image-file" (request-uploaded-files req) :test #'equal :key #'car)))) + (poi poi)) + (let ((uploaded-file (cdr (find "image-file" (request-uploaded-files) :test #'equal :key #'car)))) (unless uploaded-file (error "no file uploaded in upload handler")) (cl-gd:with-image-from-file* (uploaded-file) @@ -240,23 +236,22 @@ :class-name 'store-image) (poi-panoramas poi)))) (redirect (format nil "/edit-poi/~D" - (store-object-id poi)) req)) + (store-object-id poi)))) (defmethod handle-object-form ((handler edit-poi-handler) (action (eql :delete-panorama)) - (poi poi) - req) - (with-query-params (req panorama-id) + (poi poi)) + (with-query-params (panorama-id) (let ((panorama (find-store-object (parse-integer panorama-id)))) (change-slot-values poi 'panoramas (remove panorama (poi-panoramas poi))) (mapc #'delete-object panorama))) (redirect (format nil "/edit-poi/~D" - (store-object-id poi)) req)) + (store-object-id poi)))) (defmethod handle-object-form ((handler edit-poi-handler) - (action (eql :delete)) (poi poi) req) + (action (eql :delete)) (poi poi)) (delete-object poi) - (with-bos-cms-page (req :title "POI has been deleted") + (with-bos-cms-page (:title "POI has been deleted") (html (:h2 "POI has been deleted") "The POI has been deleted"))) @@ -266,9 +261,9 @@ () (:default-initargs :object-class 'poi-image)) -(defmethod handle-object-form ((handler edit-poi-image-handler) action (object (eql nil)) req) - (with-query-params (req poi) - (with-bos-cms-page (req :title "Upload new POI image") +(defmethod handle-object-form ((handler edit-poi-image-handler) action (object (eql nil))) + (with-query-params (poi) + (with-bos-cms-page (:title "Upload new POI image") (html (:h2 "Upload new image") ((:form :method "POST" :enctype "multipart/form-data")) @@ -276,16 +271,16 @@ (:p "Choose a file: " ((:input :type "file" :name "image-file"))) (:p (submit-button "upload" "upload")))))) -(defmethod handle-object-form ((handler edit-poi-image-handler) (action (eql :upload)) poi-image req) - (with-query-params (req poi) +(defmethod handle-object-form ((handler edit-poi-image-handler) (action (eql :upload)) poi-image) + (with-query-params (poi) (setq poi (find-store-object (parse-integer poi) :class 'poi)) - (let ((uploaded-file (cdr (find "image-file" (request-uploaded-files req) :test #'equal :key #'car)))) + (let ((uploaded-file (cdr (find "image-file" (request-uploaded-files) :test #'equal :key #'car)))) (unless uploaded-file (error "no file uploaded in upload handler")) (cl-gd:with-image-from-file* (uploaded-file) (unless (and (eql (cl-gd:image-width) *poi-image-width*) (eql (cl-gd:image-height) *poi-image-height*)) - (with-bos-cms-page (req :title "Invalid image size") + (with-bos-cms-page (:title "Invalid image size") (:h2 "Invalid image size") (:p "The image needs to be " (:princ-safe *poi-image-width*) " pixels wide and " @@ -302,15 +297,15 @@ :initargs `(:poi ,poi)))) (redirect (format nil "/edit-poi-image/~D?poi=~D" (store-object-id poi-image) - (store-object-id poi)) req)))) + (store-object-id poi)))))) -(defmethod handle-object-form ((handler edit-poi-image-handler) action poi-image req) - (with-query-params (req language poi) +(defmethod handle-object-form ((handler edit-poi-image-handler) action poi-image) + (with-query-params (language poi) (unless language (setq language (session-variable :language))) - (with-bos-cms-page (req :title "Edit POI Image") + (with-bos-cms-page (:title "Edit POI Image") (html (cmslink (edit-object-url (poi-image-poi poi-image)) "Back to POI") - (content-language-chooser req) + (content-language-chooser) ((:form :method "post" :enctype "multipart/form-data") ((:input :type "hidden" :name "poi" :value poi)) (:table (:tr (:td "thumbnail") @@ -334,21 +329,21 @@ :cols 40))) (:tr (:td (submit-button "save" "save") (submit-button "delete" "delete" :confirm "Really delete the image?"))))))))) -(defmethod handle-object-form ((handler edit-poi-image-handler) (action (eql :save)) poi-image req) - (with-query-params (req title subtitle description language) +(defmethod handle-object-form ((handler edit-poi-image-handler) (action (eql :save)) poi-image) + (with-query-params (title subtitle description language) (unless language (setq language (session-variable :language))) (update-poi-image poi-image language :title title :subtitle subtitle :description description) - (with-bos-cms-page (req :title "POI image has been updated") + (with-bos-cms-page (:title "POI image has been updated") (:h2 "The POI image information has been updated") "You may " (cmslink (edit-object-url poi-image) "continue editing the POI image")))) -(defmethod handle-object-form ((handler edit-poi-image-handler) (action (eql :delete)) poi-image req) +(defmethod handle-object-form ((handler edit-poi-image-handler) (action (eql :delete)) poi-image) (let ((poi (poi-image-poi poi-image))) (delete-object poi-image) - (with-bos-cms-page (req :title "POI image has been deleted") + (with-bos-cms-page (:title "POI image has been deleted") (:h2 "The POI image has been deleted") "You may " (cmslink (edit-object-url poi) "continue editing the POI")))) @@ -363,12 +358,12 @@ (sponsor-country (contract-sponsor contract)) (length (contract-m2s contract)))) -(defmethod handle ((handler poi-javascript-handler) req) - (with-bknr-http-response (req :content-type "text/html; charset=UTF-8") - (setf (reply-header-slot-value req :cache-control) "no-cache") - (setf (reply-header-slot-value req :pragma) "no-cache") - (setf (reply-header-slot-value req :expires) "-1") - (with-http-body (req *ent*) +(defmethod handle ((handler poi-javascript-handler)) + (with-http-response (:content-type "text/html; charset=UTF-8") + (setf (hunchentoot:header-out :cache-control) "no-cache") + (setf (hunchentoot:header-out :pragma) "no-cache") + (setf (hunchentoot:header-out :expires) "-1") + (with-http-body () (let ((*standard-output* *html-stream*)) (princ "~%" (cond - ((eq (find-class 'sponsor) (class-of (bknr-request-user req))) + ((eq (find-class 'sponsor) (class-of bknr.web:*user*)) "logged-in") (__sponsorid "login-failed") @@ -295,8 +294,8 @@ () (:default-initargs :class 'contract)) -(defmethod object-handler-get-object ((handler cert-regen-handler) req) - (let* ((object-id-string (first (decoded-handler-path handler req))) +(defmethod object-handler-get-object ((handler cert-regen-handler)) + (let* ((object-id-string (first (decoded-handler-path handler))) (object (store-object-with-id (parse-integer object-id-string)))) (cond ((contract-p object) @@ -305,8 +304,8 @@ (first (sponsor-contracts object))) (t (error "invalid sponsor or contract id ~A" object-id-string))))) -(defmethod handle-object-form ((handler cert-regen-handler) action (contract contract) req) - (with-bos-cms-page (req :title (format nil "Re-generate Certificate~@[~*s~]" +(defmethod handle-object-form ((handler cert-regen-handler) action (contract contract)) + (with-bos-cms-page (:title (format nil "Re-generate Certificate~@[~*s~]" (not (contract-download-only-p contract)))) (html ((:form :name "form") @@ -322,10 +321,10 @@ (html (:tr (:td (submit-button "regenerate" "regenerate"))))))))) -(defmethod handle-object-form ((handler cert-regen-handler) (action (eql :regenerate)) (contract contract) req) - (with-query-params (req name address language) +(defmethod handle-object-form ((handler cert-regen-handler) (action (eql :regenerate)) (contract contract)) + (with-query-params (name address language) (contract-issue-cert contract name :address address :language language)) - (with-bos-cms-page (req :title "Certificate has been recreated") + (with-bos-cms-page (:title "Certificate has been recreated") (html "The certificates for the sponsor have been re-generated." :br) (unless (contract-download-only-p contract) (mail-print-pdf contract) Modified: branches/trunk-reorg/projects/bos/web/web-macros.lisp ============================================================================== --- branches/trunk-reorg/projects/bos/web/web-macros.lisp (original) +++ branches/trunk-reorg/projects/bos/web/web-macros.lisp Mon Feb 11 12:24:41 2008 @@ -2,26 +2,25 @@ (enable-interpol-syntax) -(defmacro with-bos-cms-page ((req &key title response) &rest body) - `(with-bknr-page (,req :title ,title :response ,response) +(defmacro with-bos-cms-page ((&key title response) &rest body) + `(with-bknr-page (:title ,title :response ,response) , at body)) (defvar *xml-sink*) (defmacro with-xml-response ((&key (content-type "text/xml") (root-element "response")) &body body) - `(with-http-response (*req* *ent* :content-type ,content-type) - (with-query-params (*req* download) + `(with-http-response (:content-type ,content-type) + (with-query-params (download) (when download - (setf (reply-header-slot-value *req* :content-disposition) - (format nil "attachment; filename=~A" download)))) - (with-http-body (*req* *ent*) - (let ((*xml-sink* (make-character-stream-sink net.html.generator:*html-stream* :canonical nil))) + (setf (hunchentoot:header-out :content-disposition) + (format nil "attachment; filename=~A" download)))) + (with-http-body () + (let ((*xml-sink* (make-character-stream-sink xhtml-generator:*html-sink* :canonical nil))) (with-xml-output *xml-sink* (with-element ,root-element , at body)))))) -(defmacro with-xml-error-handler (req &body body) - (declare (ignore req)) +(defmacro with-xml-error-handler (() &body body) `(handler-case (progn , at body) (error (e) @@ -29,3 +28,5 @@ (with-element "status" (attribute "failure" 1) (text (princ-to-string e))))))) + + Modified: branches/trunk-reorg/projects/bos/web/web-utils.lisp ============================================================================== --- branches/trunk-reorg/projects/bos/web/web-utils.lisp (original) +++ branches/trunk-reorg/projects/bos/web/web-utils.lisp Mon Feb 11 12:24:41 2008 @@ -46,20 +46,20 @@ (setf (session-variable :language) *default-language*)) (session-variable :language)) -(defun content-language-chooser (req) +(defun content-language-chooser () (html ((:p :class "languages") "Content languages: " (loop for (language-symbol language-name) in (website-languages) do (labels ((show-language-link () - (html (cmslink (format nil "~A?language=~A" (uri-path (request-uri req)) language-symbol) + (html (cmslink (format nil "~A?language=~A" (uri-path (hunchentoot:request-uri)) language-symbol) (:princ-safe language-name))))) (if (equal (session-variable :language) language-symbol) (html "[" (show-language-link) "]") (html (show-language-link))) (html " ")))))) -(defun decode-ismap-query-string (req) +(defun decode-ismap-query-string () (let ((coord-string (caar (request-query req)))) (when (and coord-string (scan #?r"^\d*,\d*$" coord-string)) (mapcar #'parse-integer (split "," coord-string))))) Modified: branches/trunk-reorg/projects/bos/web/webserver.lisp ============================================================================== --- branches/trunk-reorg/projects/bos/web/webserver.lisp (original) +++ branches/trunk-reorg/projects/bos/web/webserver.lisp Mon Feb 11 12:24:41 2008 @@ -53,7 +53,7 @@ "index" template-name))))) (call-next-method handler template-name)) -(defmethod initial-template-environment ((expander worldpay-template-handler) req) +(defmethod initial-template-environment ((expander worldpay-template-handler)) (append (list (cons :website-url *website-url*)) (call-next-method))) @@ -74,7 +74,7 @@ (when (website-supports-language language) language))) -(defun find-browser-prefered-language (req) +(defun find-browser-prefered-language () "Determine the language prefered by the user, as determined by the Accept-Language header present in the HTTP request. Header decoding is done according to RFC2616, considering individual language preference weights." @@ -99,42 +99,41 @@ (defclass index-handler (page-handler) ()) -(defmethod handle ((handler index-handler) req) - (redirect (format nil "/~A/index" (or (find-browser-prefered-language req) +(defmethod handle ((handler index-handler)) + (redirect (format nil "/~A/index" (or (find-browser-prefered-language) *default-language*)) - req - *response-moved-permanently*)) + :permanently *response-moved-permanently*)) (defclass infosystem-handler (page-handler) ()) -(defmethod handle ((handler infosystem-handler) req) +(defmethod handle ((handler infosystem-handler)) ;; XXX hier logout-parameter implementieren - (with-query-params (req logout) + (with-query-params (logout) (when logout - (bknr.web::drop-session (bknr-request-session req)))) + (bknr.web::drop-session *session*))) (let ((language (session-variable :language))) - (redirect #?"/infosystem/$(language)/satellitenkarte.htm" req))) + (redirect #?"/infosystem/$(language)/satellitenkarte.htm"))) (defclass certificate-handler (object-handler) () (:default-initargs :class 'contract)) -(defmethod handle-object ((handler certificate-handler) contract req) +(defmethod handle-object ((handler certificate-handler) contract) (unless contract - (setf contract (find-if #'contract-pdf-pathname (sponsor-contracts (bknr-request-user req))))) - (redirect (format nil "/certificates/~D.pdf" (store-object-id contract)) req)) + (setf contract (find-if #'contract-pdf-pathname (sponsor-contracts bknr.web:*user*)))) + (redirect (format nil "/certificates/~D.pdf" (store-object-id contract)))) (defclass statistics-handler (editor-only-handler prefix-handler) ()) -(defmethod handle ((handler statistics-handler) req) +(defmethod handle ((handler statistics-handler)) (let ((stats-name (parse-url req))) (cond (stats-name - (redirect (format nil "~A.svg" stats-name) req)) + (redirect (format nil "~A.svg" stats-name))) (t - (with-bos-cms-page (req :title "Statistics browser") + (with-bos-cms-page (:title "Statistics browser") (:p ((:select :id "selector" :onchange "return statistic_selected()") (dolist (file (directory (merge-pathnames #p"images/statistics/*.svg" *website-directory*))) @@ -146,15 +145,15 @@ (defclass admin-handler (editor-only-handler page-handler) ()) -(defmethod handle ((handler admin-handler) req) - (with-bos-cms-page (req :title "CMS and Administration") +(defmethod handle ((handler admin-handler)) + (with-bos-cms-page (:title "CMS and Administration") "Please choose an administration activity from the menu above")) (defclass bos-authorizer (bknr-authorizer) ()) -(defmethod find-user-from-request-parameters ((authorizer bos-authorizer) req) - (with-query-params (req __sponsorid __password) +(defmethod find-user-from-request-parameters ((authorizer bos-authorizer)) + (with-query-params (__sponsorid __password) (if (and __sponsorid __password) (handler-case (let ((sponsor (find-store-object (parse-integer __sponsorid) :class 'sponsor))) @@ -172,13 +171,13 @@ (defmethod authorize :after ((authorizer bos-authorizer) (req http-request) (ent net.aserve::entity)) - (let ((new-language (or (language-from-url (uri-path (request-uri req))) + (let ((new-language (or (language-from-url (uri-path (hunchentoot:request-uri))) (query-param req "language"))) - (current-language (gethash :language (bknr-session-variables (bknr-request-session req))))) + (current-language (gethash :language (bknr-session-variables *session*)))) (when (or (not current-language) (and new-language (not (equal new-language current-language)))) - (setf (gethash :language (bknr-session-variables (bknr-request-session req))) + (setf (gethash :language (bknr-session-variables *session*)) (or new-language (find-browser-prefered-language req) *default-language*))))) From ksprotte at common-lisp.net Tue Feb 12 12:18:12 2008 From: ksprotte at common-lisp.net (ksprotte at common-lisp.net) Date: Tue, 12 Feb 2008 07:18:12 -0500 (EST) Subject: [bknr-cvs] r2480 - branches/trunk-reorg/xhtmlgen Message-ID: <20080212121812.8546716042@common-lisp.net> Author: ksprotte Date: Tue Feb 12 07:18:11 2008 New Revision: 2480 Modified: branches/trunk-reorg/xhtmlgen/xhtmlgen.lisp Log: it seems that a rune is a character nowadays Modified: branches/trunk-reorg/xhtmlgen/xhtmlgen.lisp ============================================================================== --- branches/trunk-reorg/xhtmlgen/xhtmlgen.lisp (original) +++ branches/trunk-reorg/xhtmlgen/xhtmlgen.lisp Tue Feb 12 07:18:11 2008 @@ -131,7 +131,7 @@ ;; das ist fuer WPDISPLAY (let ((s (cxml::chained-handler *html-sink*))) (cxml::maybe-close-tag s) - (map nil (lambda (c) (cxml::write-rune (char-code c) s)) str))) + (map nil (lambda (c) (cxml::write-rune c s)) str))) (defun princ-http (val) #+(or) From ksprotte at common-lisp.net Tue Feb 12 12:19:26 2008 From: ksprotte at common-lisp.net (ksprotte at common-lisp.net) Date: Tue, 12 Feb 2008 07:19:26 -0500 (EST) Subject: [bknr-cvs] r2481 - branches/trunk-reorg/projects/bos/web Message-ID: <20080212121926.60DA15E006@common-lisp.net> Author: ksprotte Date: Tue Feb 12 07:19:24 2008 New Revision: 2481 Modified: branches/trunk-reorg/projects/bos/web/allocation-area-handlers.lisp branches/trunk-reorg/projects/bos/web/contract-image-handler.lisp branches/trunk-reorg/projects/bos/web/map-handlers.lisp branches/trunk-reorg/projects/bos/web/reports-xml-handler.lisp branches/trunk-reorg/projects/bos/web/sponsor-handlers.lisp branches/trunk-reorg/projects/bos/web/startup.lisp branches/trunk-reorg/projects/bos/web/webserver.lisp Log: bos trunk-reorg compiles for the first time Modified: branches/trunk-reorg/projects/bos/web/allocation-area-handlers.lisp ============================================================================== --- branches/trunk-reorg/projects/bos/web/allocation-area-handlers.lisp (original) +++ branches/trunk-reorg/projects/bos/web/allocation-area-handlers.lisp Tue Feb 12 07:19:24 2008 @@ -123,7 +123,7 @@ do (incf dest-x copy-width)) do (incf dest-y copy-height)) (cl-gd:draw-polygon vertices :color (elt colors 1)) - (emit-image-to-browser req cl-gd:*default-image* :png))))) + (emit-image-to-browser cl-gd:*default-image* :png))))) (defclass create-allocation-area-handler (admin-only-handler form-handler) ()) Modified: branches/trunk-reorg/projects/bos/web/contract-image-handler.lisp ============================================================================== --- branches/trunk-reorg/projects/bos/web/contract-image-handler.lisp (original) +++ branches/trunk-reorg/projects/bos/web/contract-image-handler.lisp Tue Feb 12 07:19:24 2008 @@ -7,7 +7,7 @@ () (:default-initargs :class 'contract)) -(defmethod handle-object ((handler contract-image-handler) contract req) +(defmethod handle-object ((handler contract-image-handler) contract) "Create and return a GD image of the contract. The returned rectangular image will have the size of the contracts' bounding box. All square meters will have yellow color, the background will be transparent." @@ -27,4 +27,4 @@ (cl-gd:do-rows (y) (cl-gd:do-pixels-in-row (x) (setf (cl-gd:raw-pixel) (aref work-array x y))))) - (emit-image-to-browser req cl-gd:*default-image* :png :cache-sticky t)))) \ No newline at end of file + (emit-image-to-browser cl-gd:*default-image* :png :cache-sticky t)))) \ No newline at end of file Modified: branches/trunk-reorg/projects/bos/web/map-handlers.lisp ============================================================================== --- branches/trunk-reorg/projects/bos/web/map-handlers.lisp (original) +++ branches/trunk-reorg/projects/bos/web/map-handlers.lisp Tue Feb 12 07:19:24 2008 @@ -82,7 +82,7 @@ ;; (if (or (not ims) ;; (> changed-time (date-to-universal-time ims))) ;; (let ((image (image-tile-image tile (apply #'parse-operations operation-strings)))) -;; (emit-image-to-browser req image :png +;; (emit-image-to-browser image :png ;; :date changed-time ;; :max-age 60) ;; (cl-gd:destroy-image image)) @@ -98,7 +98,7 @@ (let (active-layers (all-layer-names (mapcar #'symbol-name (image-tile-layers tile)))) (dolist (layer-name all-layer-names) - (when (query-param req layer-name) + (when (query-param layer-name) (push layer-name active-layers))) (or (reverse active-layers) all-layer-names))) Modified: branches/trunk-reorg/projects/bos/web/reports-xml-handler.lisp ============================================================================== --- branches/trunk-reorg/projects/bos/web/reports-xml-handler.lisp (original) +++ branches/trunk-reorg/projects/bos/web/reports-xml-handler.lisp Tue Feb 12 07:19:24 2008 @@ -19,7 +19,7 @@ (declare (ignore second minute hour date month day-of-week is-dst tz)) year)) -(defmethod handle ((handler reports-xml-handler) req) +(defmethod handle ((handler reports-xml-handler)) (with-xml-response () (destructuring-bind (name &optional *year* &rest arguments) (decoded-handler-path handler) (setf *year* (and *year* (parse-integer *year*))) Modified: branches/trunk-reorg/projects/bos/web/sponsor-handlers.lisp ============================================================================== --- branches/trunk-reorg/projects/bos/web/sponsor-handlers.lisp (original) +++ branches/trunk-reorg/projects/bos/web/sponsor-handlers.lisp Tue Feb 12 07:19:24 2008 @@ -178,14 +178,14 @@ (let (changed) (with-bos-cms-page (:title "Saving sponsor data") (dolist (field-name '(full-name email password country language info-text)) - (let ((field-value (query-param req (string-downcase (symbol-name field-name))))) + (let ((field-value (query-param (string-downcase (symbol-name field-name))))) (when (and field-value (not (equal field-value (slot-value sponsor field-name)))) (change-slot-values sponsor field-name field-value) (setf changed t) (html (:p "Changed " (:princ-safe (string-downcase (symbol-name field-name)))))))) (dolist (contract (sponsor-contracts sponsor)) - (when (and (query-param req (contract-checkbox-name contract)) + (when (and (query-param (contract-checkbox-name contract)) (not (contract-paidp contract))) (change-slot-values contract 'paidp t) (setf changed t) @@ -249,8 +249,8 @@ (defclass m2-javascript-handler (prefix-handler) ()) -(defmethod handle ((handler m2-javascript-handler) req) - (multiple-value-bind (sponsor-id-or-x y) (parse-url req) +(defmethod handle ((handler m2-javascript-handler)) + (multiple-value-bind (sponsor-id-or-x y) (parse-url) (let ((sponsor (cond (y (let ((m2 (get-m2 (parse-integer sponsor-id-or-x) (parse-integer y)))) Modified: branches/trunk-reorg/projects/bos/web/startup.lisp ============================================================================== --- branches/trunk-reorg/projects/bos/web/startup.lisp (original) +++ branches/trunk-reorg/projects/bos/web/startup.lisp Tue Feb 12 07:19:24 2008 @@ -42,10 +42,6 @@ :website-url *website-url* :worldpay-test-mode *worldpay-test-mode*) (format t "~&; Starting aserve~@[ in debug mode~].~%" debug) - (force-output) - (setq *webserver* - (if debug - (progn (net.aserve::debug-on :notrap) - (net.aserve:start :port *port* :listeners 0)) - (progn (net.aserve::debug-off :all) - (net.aserve:start :port *port* :listeners *listeners*))))) + (force-output) + (setq hunchentoot:*catch-errors-p* (not debug)) + (hunchentoot:start-server :port *port*)) Modified: branches/trunk-reorg/projects/bos/web/webserver.lisp ============================================================================== --- branches/trunk-reorg/projects/bos/web/webserver.lisp (original) +++ branches/trunk-reorg/projects/bos/web/webserver.lisp Tue Feb 12 07:19:24 2008 @@ -22,13 +22,13 @@ ;; If the requested URL is /handle-sale, we do the sales processing ;; and change the template name according to the outcome. -(defmethod find-template-pathname ((handler worldpay-template-handler) template-name &key request) +(defmethod find-template-pathname ((Handler worldpay-template-handler) template-name) (cond ((scan #?r"(^|.*/)handle-sale" template-name) - (with-query-params (request cartId name address country transStatus lang MC_gift) + (with-query-params (cartId name address country transStatus lang MC_gift) (unless (website-supports-language lang) (setf lang *default-language*)) - (bos.m2::remember-worldpay-params cartId (all-request-params request)) + (bos.m2::remember-worldpay-params cartId (all-request-params)) (let ((contract (get-contract (parse-integer cartId)))) (sponsor-set-language (contract-sponsor contract) lang) (cond @@ -128,7 +128,7 @@ ()) (defmethod handle ((handler statistics-handler)) - (let ((stats-name (parse-url req))) + (let ((stats-name (parse-url))) (cond (stats-name (redirect (format nil "~A.svg" stats-name))) @@ -168,19 +168,20 @@ (call-next-method))) (call-next-method)))) -(defmethod authorize :after ((authorizer bos-authorizer) - (req http-request) - (ent net.aserve::entity)) - (let ((new-language (or (language-from-url (uri-path (hunchentoot:request-uri))) - (query-param req "language"))) - (current-language (gethash :language (bknr-session-variables *session*)))) - (when (or (not current-language) - (and new-language - (not (equal new-language current-language)))) - (setf (gethash :language (bknr-session-variables *session*)) - (or new-language - (find-browser-prefered-language req) - *default-language*))))) +;; trunk-reorg adaption +;; (defmethod authorize :after ((authorizer bos-authorizer) +;; (req http-request) +;; (ent net.aserve::entity)) +;; (let ((new-language (or (language-from-url (uri-path (hunchentoot:request-uri))) +;; (query-param "language"))) +;; (current-language (gethash :language (bknr-session-variables *session*)))) +;; (when (or (not current-language) +;; (and new-language +;; (not (equal new-language current-language)))) +;; (setf (gethash :language (bknr-session-variables *session*)) +;; (or new-language +;; (find-browser-prefered-language req) +;; *default-language*))))) (defun publish-website (&key website-directory website-url (worldpay-test-mode t) (vhosts :wild)) (setf *website-directory* website-directory) From dverna at common-lisp.net Tue Feb 12 14:13:33 2008 From: dverna at common-lisp.net (dverna at common-lisp.net) Date: Tue, 12 Feb 2008 09:13:33 -0500 (EST) Subject: [bknr-cvs] r2482 - trunk/projects/lisp-ecoop/website/templates Message-ID: <20080212141333.79ED65D162@common-lisp.net> Author: dverna Date: Tue Feb 12 09:13:32 2008 New Revision: 2482 Modified: trunk/projects/lisp-ecoop/website/templates/home.xml trunk/projects/lisp-ecoop/website/templates/programme.xml trunk/projects/lisp-ecoop/website/templates/submissions.xml Log: Updated the deadlines Modified: trunk/projects/lisp-ecoop/website/templates/home.xml ============================================================================== --- trunk/projects/lisp-ecoop/website/templates/home.xml (original) +++ trunk/projects/lisp-ecoop/website/templates/home.xml Tue Feb 12 09:13:32 2008 @@ -27,9 +27,9 @@

Important Dates

    -
  • Submission deadline: May 18, 2008
  • -
  • Notification of acceptance: June 08, 2008
  • -
  • ECOOP early registration deadline: June 15, 2008
  • +
  • Submission deadline: May 04, 2008
  • +
  • Notification of acceptance: May 19, 2008
  • +
  • ECOOP early registration deadline: June 01, 2008

Overview

Modified: trunk/projects/lisp-ecoop/website/templates/programme.xml ============================================================================== --- trunk/projects/lisp-ecoop/website/templates/programme.xml (original) +++ trunk/projects/lisp-ecoop/website/templates/programme.xml Tue Feb 12 09:13:32 2008 @@ -5,7 +5,7 @@

Workshop Programme

-The programme will be available by the end of June. +The programme will be available in June. -The list of accepted submissions will be available by the end of June. +The list of accepted submissions will be available in June.

Papers

From ksprotte at common-lisp.net Tue Feb 12 16:56:57 2008 From: ksprotte at common-lisp.net (ksprotte at common-lisp.net) Date: Tue, 12 Feb 2008 11:56:57 -0500 (EST) Subject: [bknr-cvs] r2483 - branches/trunk-reorg/bknr/web/src/web Message-ID: <20080212165657.870CD5D162@common-lisp.net> Author: ksprotte Date: Tue Feb 12 11:56:56 2008 New Revision: 2483 Modified: branches/trunk-reorg/bknr/web/src/web/handlers.lisp Log: (script-name) from hunchentoot returns a string and must be parsed here into an uri Modified: branches/trunk-reorg/bknr/web/src/web/handlers.lisp ============================================================================== --- branches/trunk-reorg/bknr/web/src/web/handlers.lisp (original) +++ branches/trunk-reorg/bknr/web/src/web/handlers.lisp Tue Feb 12 11:56:56 2008 @@ -233,7 +233,7 @@ (if (not (authorized-p handler)) (progn (setf (session-value :login-redirect-uri) - (redirect-uri (script-name))) + (redirect-uri (parse-uri (script-name)))) (redirect (website-make-path *website* "login"))) (if *catch-errors-p* (handle handler) From ksprotte at common-lisp.net Tue Feb 12 16:58:36 2008 From: ksprotte at common-lisp.net (ksprotte at common-lisp.net) Date: Tue, 12 Feb 2008 11:58:36 -0500 (EST) Subject: [bknr-cvs] r2484 - in branches/trunk-reorg/projects/bos: m2 web Message-ID: <20080212165836.0D17A2F060@common-lisp.net> Author: ksprotte Date: Tue Feb 12 11:58:31 2008 New Revision: 2484 Modified: branches/trunk-reorg/projects/bos/m2/m2.lisp branches/trunk-reorg/projects/bos/m2/mail-generator.lisp branches/trunk-reorg/projects/bos/m2/utils.lisp branches/trunk-reorg/projects/bos/web/allocation-area-handlers.lisp branches/trunk-reorg/projects/bos/web/map-browser-handler.lisp branches/trunk-reorg/projects/bos/web/map-handlers.lisp branches/trunk-reorg/projects/bos/web/news-handlers.lisp branches/trunk-reorg/projects/bos/web/news-tags.lisp branches/trunk-reorg/projects/bos/web/poi-handlers.lisp branches/trunk-reorg/projects/bos/web/sponsor-handlers.lisp branches/trunk-reorg/projects/bos/web/startup.lisp branches/trunk-reorg/projects/bos/web/tags.lisp branches/trunk-reorg/projects/bos/web/web-utils.lisp branches/trunk-reorg/projects/bos/web/webserver.lisp Log: more changes for bos trunk-reorg Modified: branches/trunk-reorg/projects/bos/m2/m2.lisp ============================================================================== --- branches/trunk-reorg/projects/bos/m2/m2.lisp (original) +++ branches/trunk-reorg/projects/bos/m2/m2.lisp Tue Feb 12 11:58:31 2008 @@ -446,12 +446,10 @@ (incf retval (length (contract-m2s contract)))) retval)) -;; trunk-reorg adaption -;; (defun string-safe (string) -;; (if string -;; (escape-nl (with-output-to-string (s) -;; (net.html.generator::emit-safe s string))) -;; "")) +(defun string-safe (string) + (if string + (escape-nl (arnesi:escape-as-html string)) + "")) (defun make-m2-javascript (sponsor) "Erzeugt das Quadratmeter-Javascript f?r die angegebenen Contracts" Modified: branches/trunk-reorg/projects/bos/m2/mail-generator.lisp ============================================================================== --- branches/trunk-reorg/projects/bos/m2/mail-generator.lisp (original) +++ branches/trunk-reorg/projects/bos/m2/mail-generator.lisp Tue Feb 12 11:58:31 2008 @@ -275,7 +275,7 @@ email country language)) - (make-contract-xml-part (store-object-id contract) (all-request-params req)) + (make-contract-xml-part (store-object-id contract) (all-request-params)) (make-vcard-part (store-object-id contract) (make-vcard :sponsor-id (store-object-id (contract-sponsor contract)) :note (format nil "Paid-by: Back office @@ -293,7 +293,7 @@ :email email))))) (mail-contract-data contract "Manually entered sponsor" parts)))) -(defun mail-manual-sponsor-data (req) +(defun mail-manual-sponsor-data () (with-query-params (contract-id vorname name strasse plz ort email telefon want-print donationcert-yearly) (let* ((contract (store-object-with-id (parse-integer contract-id))) (sponsor-id (store-object-id (contract-sponsor contract))) @@ -327,7 +327,7 @@ (if want-print "yes" "no") (if donationcert-yearly "yes" "no") *website-url* contract-id email)) - (make-contract-xml-part contract-id (all-request-params req)) + (make-contract-xml-part contract-id (all-request-params)) (make-vcard-part contract-id (make-vcard :sponsor-id sponsor-id :note (format nil "Paid-by: Manual money transfer Contract ID: ~A @@ -362,7 +362,7 @@ (remhash contract-id *worldpay-params-hash*)) (error "cannot find WorldPay callback params for contract ~A~%" contract-id))) -(defun mail-worldpay-sponsor-data (req) +(defun mail-worldpay-sponsor-data () (with-query-params (contract-id) (let* ((contract (store-object-with-id (parse-integer contract-id))) (params (get-worldpay-params contract-id)) Modified: branches/trunk-reorg/projects/bos/m2/utils.lisp ============================================================================== --- branches/trunk-reorg/projects/bos/m2/utils.lisp (original) +++ branches/trunk-reorg/projects/bos/m2/utils.lisp Tue Feb 12 11:58:31 2008 @@ -5,4 +5,8 @@ (defun escape-nl (string) (if string (regex-replace-all #?r"[\n\r]+" string #?"
") - "")) \ No newline at end of file + "")) + +(defun random-elt (choices) + (when choices + (elt choices (random (length choices))))) \ No newline at end of file Modified: branches/trunk-reorg/projects/bos/web/allocation-area-handlers.lisp ============================================================================== --- branches/trunk-reorg/projects/bos/web/allocation-area-handlers.lisp (original) +++ branches/trunk-reorg/projects/bos/web/allocation-area-handlers.lisp Tue Feb 12 11:58:31 2008 @@ -145,7 +145,7 @@ x y (uriencode-string "Choose lower right point of allocation area") (uriencode-string (format nil "~A?left=~A&top=~A&" - (uri-path (hunchentoot:request-uri)) + (hunchentoot:request-uri) x y))))) (t (with-bos-cms-page (:title "Create allocation area") @@ -166,7 +166,7 @@ (redirect (format nil "/map-browser/~A/~A?heading=~A&chosen-url=~A&" start-x start-y (uriencode-string "Choose upper left point of allocation area") - (uriencode-string (format nil "~A?" (uri-path (hunchentoot:request-uri)))))))) + (uriencode-string (format nil "~A?" (hunchentoot:request-uri))))))) (defmethod handle-form ((handler create-allocation-area-handler) (action (eql :upload))) (let ((uploaded-text-file (cdr (find "text-file" (request-uploaded-files) :test #'equal :key #'car)))) Modified: branches/trunk-reorg/projects/bos/web/map-browser-handler.lisp ============================================================================== --- branches/trunk-reorg/projects/bos/web/map-browser-handler.lisp (original) +++ branches/trunk-reorg/projects/bos/web/map-browser-handler.lisp Tue Feb 12 11:58:31 2008 @@ -41,15 +41,15 @@ (defmethod handle ((handler map-browser-handler)) (with-query-params (chosen-url) (when chosen-url - (setf (session-variable :chosen-url) chosen-url))) + (setf (hunchentoot:session-value :chosen-url) chosen-url))) (with-query-params (view-x view-y) (destructuring-bind (&optional click-x click-y) (decode-ismap-query-string) (destructuring-bind (&optional point-x point-y) (decode-coords-in-handler-path handler) (with-query-params (action) (when (equal action "save") - (if (session-variable :chosen-url) + (if (hunchentoot:session-value :chosen-url) (redirect (format nil "~Ax=~D&y=~D" - (session-variable :chosen-url) + (hunchentoot:session-value :chosen-url) point-x point-y)) (with-bos-cms-page (:title "Map Point Chooser") @@ -130,7 +130,7 @@ ((:div :id "cursor" :style #?"position:absolute; left:$(cursor-x)px; top:$(cursor-y)px; visibility:visible") ((:img :src "/images/map-cursor.png"))))))) - (map-navigator req point-x point-y "/map-browser/" :formcheck "return updateCoords();"))) + (map-navigator point-x point-y "/map-browser/" :formcheck "return updateCoords();"))) (t (with-bos-cms-page (:title "Map Point Chooser") (html Modified: branches/trunk-reorg/projects/bos/web/map-handlers.lisp ============================================================================== --- branches/trunk-reorg/projects/bos/web/map-handlers.lisp (original) +++ branches/trunk-reorg/projects/bos/web/map-handlers.lisp Tue Feb 12 11:58:31 2008 @@ -2,7 +2,7 @@ (enable-interpol-syntax) -(defun map-navigator (req x y base-url &key formcheck) +(defun map-navigator (x y base-url &key formcheck) (labels ((pfeil-image (name) (html ((:img :border "0" :width "16" :height "16" :src (format nil "/images/~:[trans.gif~;~:*pfeil-~A.gif~]" name))))) (td-link-to (x y name &optional (link-format (concatenate 'string base-url "~D/~D"))) @@ -69,27 +69,27 @@ operation-strings)) ;; trunk-reorg adaption -;; (defmethod handle-object ((handler image-tile-handler) tile) -;; ;; xxx parse url another time - the parse result of -;; ;; object-handler-get-object should really be kept in the request -;; (destructuring-bind (x y &rest operation-strings) (decoded-handler-path handler) -;; (declare (ignore x y)) -;; (let ((changed-time (image-tile-changed-time tile)) -;; (ims (header-slot-value req :if-modified-since))) -;; (format t "Warning: not setting last-modified of *ent* to changed-time") -;; #+(or) -;; (format t "; image-tile-handler handle-object: changed-time: ~A if-modified-since: ~A~%" (format-date-time changed-time) ims) -;; (if (or (not ims) -;; (> changed-time (date-to-universal-time ims))) -;; (let ((image (image-tile-image tile (apply #'parse-operations operation-strings)))) -;; (emit-image-to-browser image :png -;; :date changed-time -;; :max-age 60) -;; (cl-gd:destroy-image image)) -;; (with-http-response (*ent*) -;; (with-http-body () -;; ; do nothing -;; )))))) +(defmethod handle-object ((handler image-tile-handler) tile) + ;; xxx parse url another time - the parse result of + ;; object-handler-get-object should really be kept in the request + (destructuring-bind (x y &rest operation-strings) (decoded-handler-path handler) + (declare (ignore x y)) + (let ((changed-time (image-tile-changed-time tile)) + (ims (hunchentoot:header-in :if-modified-since))) + (format t "Warning: not setting last-modified of *ent* to changed-time") + #+(or) + (format t "; image-tile-handler handle-object: changed-time: ~A if-modified-since: ~A~%" (format-date-time changed-time) ims) + (if (or (not ims) + (> changed-time (date-to-universal-time ims))) + (let ((image (image-tile-image tile (apply #'parse-operations operation-strings)))) + (emit-image-to-browser image :png + :date changed-time + :max-age 60) + (cl-gd:destroy-image image)) + (with-http-response () + (with-http-body () + ;; do nothing + )))))) (defclass enlarge-tile-handler (image-tile-handler) ()) @@ -107,22 +107,21 @@ x y (tile-active-layers-from-request-params tile))) -;; trunk-reorg adaption -;; (defmethod handle-object ((handler enlarge-tile-handler) tile) -;; (let ((ismap-coords (decode-ismap-query-string req)) -;; (tile-x (tile-nw-x tile)) -;; (tile-y (tile-nw-y tile))) -;; (if ismap-coords -;; (let* ((x (+ (floor (first ismap-coords) 4) tile-x)) -;; (y (+ (floor (second ismap-coords) 4) tile-y)) -;; (m2 (get-m2 x y)) -;; (contract-id (and m2 (m2-contract m2) (store-object-id (m2-contract m2))))) -;; (if contract-id -;; (redirect #?"/contract/$(contract-id)") -;; (with-bos-cms-page (:title "Not sold") -;; (html (:h2 "this square meter has not been sold yet"))))) -;; (with-bos-cms-page (:title "Browsing tile") -;; (:a ((:a :href (uri-path (hunchentoot:request-uri))) -;; ((:img :width "360" :ismap "ismap" :height "360" :border "0" :src (tile-url tile tile-x tile-y req))))) -;; (map-navigator req tile-x tile-y "/enlarge-overview/"))))) +(defmethod handle-object ((handler enlarge-tile-handler) tile) + (let ((ismap-coords (decode-ismap-query-string)) + (tile-x (tile-nw-x tile)) + (tile-y (tile-nw-y tile))) + (if ismap-coords + (let* ((x (+ (floor (first ismap-coords) 4) tile-x)) + (y (+ (floor (second ismap-coords) 4) tile-y)) + (m2 (get-m2 x y)) + (contract-id (and m2 (m2-contract m2) (store-object-id (m2-contract m2))))) + (if contract-id + (redirect #?"/contract/$(contract-id)") + (with-bos-cms-page (:title "Not sold") + (html (:h2 "this square meter has not been sold yet"))))) + (with-bos-cms-page (:title "Browsing tile") + (:a ((:a :href (hunchentoot:request-uri)) + ((:img :width "360" :ismap "ismap" :height "360" :border "0" :src (tile-url tile tile-x tile-y))))) + (map-navigator tile-x tile-y "/enlarge-overview/"))))) Modified: branches/trunk-reorg/projects/bos/web/news-handlers.lisp ============================================================================== --- branches/trunk-reorg/projects/bos/web/news-handlers.lisp (original) +++ branches/trunk-reorg/projects/bos/web/news-handlers.lisp Tue Feb 12 11:58:31 2008 @@ -10,7 +10,7 @@ ()) (defmethod handle-object-form ((handler edit-news-handler) action (news-item (eql nil))) - (let ((language (session-variable :language))) + (let ((language (hunchentoot:session-value :language))) (with-bos-cms-page (:title "Edit news items") (content-language-chooser) (:h2 "Create new item") @@ -33,7 +33,7 @@ (redirect (format nil "/edit-news/~D" (store-object-id (make-news-item))))) (defmethod handle-object-form ((handler edit-news-handler) action news-item) - (let ((language (session-variable :language))) + (let ((language (hunchentoot:session-value :language))) (with-bos-cms-page (:title "Edit news item") (content-language-chooser) ((:script :type "text/javascript") @@ -49,7 +49,7 @@ (:tr (:td (submit-button "save" "save") (submit-button "delete" "delete" :confirm "Really delete the news item?")))))))) (defmethod handle-object-form ((handler edit-news-handler) (action (eql :save)) news-item) - (let ((language (session-variable :language))) + (let ((language (hunchentoot:session-value :language))) (with-query-params (title text) (update-news-item news-item language :title title :text text) (with-bos-cms-page (:title "News item updated") Modified: branches/trunk-reorg/projects/bos/web/news-tags.lisp ============================================================================== --- branches/trunk-reorg/projects/bos/web/news-tags.lisp (original) +++ branches/trunk-reorg/projects/bos/web/news-tags.lisp Tue Feb 12 11:58:31 2008 @@ -7,17 +7,17 @@ do (html (:princ-safe line) :br))) (define-bknr-tag news-headlines (&key archive) - (let ((language (session-variable :language))) + (let ((language (hunchentoot:session-value :language))) (let* ((now (get-universal-time)) - (news-items (subseq - (sort (if archive - (all-news-items language) - (remove-if #'(lambda (news-item) - (> (- now (news-item-time news-item)) *maximum-news-item-age*)) - (all-news-items language))) - #'> - :key #'news-item-time) - 0 (unless archive 3)))) + (news-items (if archive + (all-news-items language) + (let ((items (sort (remove-if + #'(lambda (news-item) + (> (- now (news-item-time news-item)) *maximum-news-item-age*)) + (all-news-items language)) + #'> + :key #'news-item-time))) + (subseq items 0 (min (length items) 3)))))) (labels ((show-news-entry (news-item) (html ((:a :href (format nil "javascript:window_news('news/~a')" (store-object-id news-item)) :class "more") @@ -25,16 +25,16 @@ :br (:princ-safe (news-item-title news-item language))))))) (loop for news-item in news-items - for index from 1 - do (if archive - (html (show-news-entry news-item) - :br :br) - (html ((:div :id (format nil "newsbox~a" index)) - (show-news-entry news-item))))))))) + for index from 1 + do (if archive + (html (show-news-entry news-item) + :br :br) + (html ((:div :id (format nil "newsbox~a" index)) + (show-news-entry news-item))))))))) (define-bknr-tag news-item () (let ((news-item (find-store-object (parse-integer (nth-value 1 (parse-url (get-template-var :request)))))) - (language (session-variable :language))) + (language (hunchentoot:session-value :language))) (html ((:h1 :class "extra") (:princ-safe (format-date-time (news-item-time news-item) :show-time nil)) ", " Modified: branches/trunk-reorg/projects/bos/web/poi-handlers.lisp ============================================================================== --- branches/trunk-reorg/projects/bos/web/poi-handlers.lisp (original) +++ branches/trunk-reorg/projects/bos/web/poi-handlers.lisp Tue Feb 12 11:58:31 2008 @@ -18,7 +18,7 @@ (html (:h2 "Bad technical name") "Please use only alphanumerical characters, - and _ for technical POI names"))) (t - (redirect (edit-object-url (make-poi (session-variable :language) name))))))) + (redirect (edit-object-url (make-poi (hunchentoot:session-value :language) name))))))) (defclass edit-poi-handler (editor-only-handler edit-object-handler) () @@ -34,7 +34,7 @@ do (html (:li (cmslink (edit-object-url poi) (:princ-safe (poi-name poi)) " - " - (:princ-safe (slot-string poi 'title (session-variable :language))))))))) + (:princ-safe (slot-string poi 'title (hunchentoot:session-value :language))))))))) (html (:h2 "No POIs created yet"))) ((:form :method "post" :action "/make-poi") "Make new POI named " @@ -52,7 +52,7 @@ (defmethod handle-object-form ((handler edit-poi-handler) action (poi poi)) (with-query-params (language shift shift-by) - (unless language (setq language (session-variable :language))) + (unless language (setq language (hunchentoot:session-value :language))) (when shift ;; change image order (setq shift (find-store-object (parse-integer shift))) @@ -65,7 +65,7 @@ (setf (nth old-position new-images) (nth (+ shift-by old-position) new-images)) (setf (nth (+ shift-by old-position) new-images) tmp) (change-slot-values poi 'bos.m2::images new-images))) - (setf (session-variable :language) language) + (setf (hunchentoot:session-value :language) language) (with-bos-cms-page (:title "Edit POI") (content-language-chooser) (unless (poi-complete poi language) @@ -95,11 +95,11 @@ (html (:princ-safe (format nil "~D/~D " (first (poi-area poi)) (second (poi-area poi))))) (cmslink (format nil "map-browser/~A/~A?chosen-url=~A" (first (poi-area poi)) (second (poi-area poi)) - (uriencode-string (format nil "~A?action=save&" (uri-path (hunchentoot:request-uri))))) + (uriencode-string (format nil "~A?action=save&" (hunchentoot:request-uri)))) "[relocate]")) (t (cmslink (format nil "map-browser/?chosen-url=~A" - (uriencode-string (format nil "~A?action=save&" (uri-path (hunchentoot:request-uri))))) + (uriencode-string (format nil "~A?action=save&" (hunchentoot:request-uri)))) "[choose]"))))) (:tr (:td "icon") (:td (icon-chooser "icon" (poi-icon poi)))) @@ -169,7 +169,7 @@ (defmethod handle-object-form ((handler edit-poi-handler) (action (eql :save)) (poi poi)) (with-query-params (published title subtitle description language x y icon movie) - (unless language (setq language (session-variable :language))) + (unless language (setq language (hunchentoot:session-value :language))) (let ((args (list :title title :published published :subtitle subtitle @@ -301,7 +301,7 @@ (defmethod handle-object-form ((handler edit-poi-image-handler) action poi-image) (with-query-params (language poi) - (unless language (setq language (session-variable :language))) + (unless language (setq language (hunchentoot:session-value :language))) (with-bos-cms-page (:title "Edit POI Image") (html (cmslink (edit-object-url (poi-image-poi poi-image)) "Back to POI") @@ -331,7 +331,7 @@ (defmethod handle-object-form ((handler edit-poi-image-handler) (action (eql :save)) poi-image) (with-query-params (title subtitle description language) - (unless language (setq language (session-variable :language))) + (unless language (setq language (hunchentoot:session-value :language))) (update-poi-image poi-image language :title title :subtitle subtitle @@ -366,7 +366,7 @@ (with-http-body () (let ((*standard-output* *html-stream*)) (princ "") (terpri))))) Modified: branches/trunk-reorg/projects/bos/web/sponsor-handlers.lisp ============================================================================== --- branches/trunk-reorg/projects/bos/web/sponsor-handlers.lisp (original) +++ branches/trunk-reorg/projects/bos/web/sponsor-handlers.lisp Tue Feb 12 11:58:31 2008 @@ -192,7 +192,7 @@ (html (:p "Changed contract status to \"paid\"")))) (unless changed (html (:p "No changes have been made"))) - (html (cmslink (uri-path (hunchentoot:request-uri)) + (html (cmslink (hunchentoot:request-uri) "Return to sponsor profile"))))) (defmethod handle-object-form ((handler edit-sponsor-handler) (action (eql :delete)) sponsor) Modified: branches/trunk-reorg/projects/bos/web/startup.lisp ============================================================================== --- branches/trunk-reorg/projects/bos/web/startup.lisp (original) +++ branches/trunk-reorg/projects/bos/web/startup.lisp Tue Feb 12 11:58:31 2008 @@ -36,12 +36,15 @@ (defun reinit (&key debug) (format t "~&; Publishing BOS handlers.~%") - (unpublish :all t) + (unpublish) (bos.web::publish-website :website-directory *website-directory* :vhosts *vhosts* :website-url *website-url* :worldpay-test-mode *worldpay-test-mode*) - (format t "~&; Starting aserve~@[ in debug mode~].~%" debug) + (format t "~&; Starting hunchentoot~@[ in debug mode~].~%" debug) (force-output) (setq hunchentoot:*catch-errors-p* (not debug)) - (hunchentoot:start-server :port *port*)) + (when *webserver* + (hunchentoot:stop-server *webserver*)) + (setf *hunchentoot-default-external-format* (flex:make-external-format :utf-8 :eol-style :lf)) + (setq *webserver* (hunchentoot:start-server :port *port*))) Modified: branches/trunk-reorg/projects/bos/web/tags.lisp ============================================================================== --- branches/trunk-reorg/projects/bos/web/tags.lisp (original) +++ branches/trunk-reorg/projects/bos/web/tags.lisp Tue Feb 12 11:58:31 2008 @@ -41,7 +41,7 @@ (let ((contract (find-store-object (parse-integer (get-template-var :contract-id))))) (when (equal want-print "no") (contract-set-download-only-p contract t)) - (contract-issue-cert contract name :address address :language (session-variable :language)) + (contract-issue-cert contract name :address address :language (hunchentoot:session-value :language)) (mail-worldpay-sponsor-data (get-template-var :request)) (bknr.web::redirect-request :target (if gift "index" (format nil "profil_setup?name=~A&email=~A&sponsor-id=~A" @@ -78,7 +78,7 @@ (manual-transfer (or (scan #?r"rweisen" action) (scan #?r"rweisung" action) (scan #?r"verf" action))) - (language (session-variable :language)) + (language (hunchentoot:session-value :language)) (sponsor (make-sponsor :language language)) (contract (make-contract sponsor numsqm :download-only download-only @@ -120,8 +120,7 @@ (bknr.web::redirect-request :target "allocation-areas-exhausted")))) (define-bknr-tag mail-transfer () - (with-query-params ((get-template-var :request) - country + (with-query-params (country contract-id name vorname strasse plz ort) (let* ((contract (store-object-with-id (parse-integer contract-id))) @@ -134,7 +133,7 @@ vorname name strasse plz ort) - :language (session-variable :language)) + :language (hunchentoot:session-value :language)) (mail-manual-sponsor-data (get-template-var :request))))) (define-bknr-tag when-certificate (&key children) Modified: branches/trunk-reorg/projects/bos/web/web-utils.lisp ============================================================================== --- branches/trunk-reorg/projects/bos/web/web-utils.lisp (original) +++ branches/trunk-reorg/projects/bos/web/web-utils.lisp Tue Feb 12 11:58:31 2008 @@ -42,9 +42,9 @@ (cadr (assoc language-short-name (website-languages) :test #'equal))) (defun current-website-language () - (unless (session-variable :language) - (setf (session-variable :language) *default-language*)) - (session-variable :language)) + (unless (hunchentoot:session-value :language) + (setf (hunchentoot:session-value :language) *default-language*)) + (hunchentoot:session-value :language)) (defun content-language-chooser () (html @@ -52,9 +52,9 @@ "Content languages: " (loop for (language-symbol language-name) in (website-languages) do (labels ((show-language-link () - (html (cmslink (format nil "~A?language=~A" (uri-path (hunchentoot:request-uri)) language-symbol) + (html (cmslink (format nil "~A?language=~A" (hunchentoot:request-uri) language-symbol) (:princ-safe language-name))))) - (if (equal (session-variable :language) language-symbol) + (if (equal (hunchentoot:session-value :language) language-symbol) (html "[" (show-language-link) "]") (html (show-language-link))) (html " ")))))) Modified: branches/trunk-reorg/projects/bos/web/webserver.lisp ============================================================================== --- branches/trunk-reorg/projects/bos/web/webserver.lisp (original) +++ branches/trunk-reorg/projects/bos/web/webserver.lisp Tue Feb 12 11:58:31 2008 @@ -46,8 +46,8 @@ (setf template-name (if (and MC_gift (equal MC_gift "1")) #?"/$(lang)/versand_geschenk" #?"/$(lang)/versand_info"))))))) ((and (not (scan "/" template-name)) (not (probe-file (merge-pathnames (make-pathname :name template-name :type "xml") - (template-handler-destination handler))))) - (setf template-name (format nil "~A/~A" (or (find-browser-prefered-language request) + (bknr.web::template-expander-destination handler))))) + (setf template-name (format nil "~A/~A" (or (find-browser-prefered-language) *default-language*) (if (equal "" template-name) "index" template-name))))) @@ -78,7 +78,7 @@ "Determine the language prefered by the user, as determined by the Accept-Language header present in the HTTP request. Header decoding is done according to RFC2616, considering individual language preference weights." - (let ((accept-language (header-slot-value req :accept-language))) + (let ((accept-language (hunchentoot:header-in :accept-language))) (dolist (language (mapcar #'car (sort (mapcar #'(lambda (language-spec-string) (if (find #\; language-spec-string) @@ -102,7 +102,7 @@ (defmethod handle ((handler index-handler)) (redirect (format nil "/~A/index" (or (find-browser-prefered-language) *default-language*)) - :permanently *response-moved-permanently*)) + :permanently t)) (defclass infosystem-handler (page-handler) ()) @@ -112,7 +112,7 @@ (with-query-params (logout) (when logout (bknr.web::drop-session *session*))) - (let ((language (session-variable :language))) + (let ((language (hunchentoot:session-value :language))) (redirect #?"/infosystem/$(language)/satellitenkarte.htm"))) (defclass certificate-handler (object-handler) @@ -172,7 +172,7 @@ ;; (defmethod authorize :after ((authorizer bos-authorizer) ;; (req http-request) ;; (ent net.aserve::entity)) -;; (let ((new-language (or (language-from-url (uri-path (hunchentoot:request-uri))) +;; (let ((new-language (or (language-from-url (hunchentoot:request-uri)) ;; (query-param "language"))) ;; (current-language (gethash :language (bknr-session-variables *session*)))) ;; (when (or (not current-language) @@ -180,9 +180,13 @@ ;; (not (equal new-language current-language)))) ;; (setf (gethash :language (bknr-session-variables *session*)) ;; (or new-language -;; (find-browser-prefered-language req) +;; (find-browser-prefered-language) ;; *default-language*))))) +;;; TODOreorg +(defun publish-directory (&key prefix destination) + (push (hunchentoot:create-folder-dispatcher-and-handler prefix destination) hunchentoot:*dispatch-table*)) + (defun publish-website (&key website-directory website-url (worldpay-test-mode t) (vhosts :wild)) (setf *website-directory* website-directory) @@ -231,8 +235,8 @@ ("/index" index-handler) ("/" worldpay-template-handler :destination ,(namestring (merge-pathnames #p"templates/" website-directory)) - :command-packages ((:bos . :bos.web) - (:bknr . :bknr.web)))) + :command-packages (("http://headcraft.de/bos" . :bos.web) + ("http://bknr.net" . :bknr.web)))) :modules '(user images stats) :navigation '(("sponsor" . "edit-sponsor/") ("statistics" . "statistics/") @@ -256,4 +260,4 @@ (publish-directory :prefix "/infosystem/" :destination (namestring (merge-pathnames "infosystem/" website-directory))) (publish-directory :prefix "/certificates/" - :destination (namestring *cert-download-directory*))) + :destination (namestring *cert-download-directory*))) \ No newline at end of file From hhubner at common-lisp.net Wed Feb 13 10:15:14 2008 From: hhubner at common-lisp.net (hhubner at common-lisp.net) Date: Wed, 13 Feb 2008 05:15:14 -0500 (EST) Subject: [bknr-cvs] r2485 - branches/trunk-reorg/bknr/web/src/web Message-ID: <20080213101514.0379817046@common-lisp.net> Author: hhubner Date: Wed Feb 13 05:15:12 2008 New Revision: 2485 Modified: branches/trunk-reorg/bknr/web/src/web/template-handler.lisp Log: Fix templater so that top-level element can be user-defined again. Modified: branches/trunk-reorg/bknr/web/src/web/template-handler.lisp ============================================================================== --- branches/trunk-reorg/bknr/web/src/web/template-handler.lisp (original) +++ branches/trunk-reorg/bknr/web/src/web/template-handler.lisp Wed Feb 13 05:15:12 2008 @@ -147,8 +147,9 @@ (let ((*tag-children* children)) (apply (find-tag-function expander name ns) (append (loop for (key name) in attrs + unless (consp key) ; ignore attributes with namespace collect (make-keyword-from-string key) - collect (expand-variables name #'get-template-var)))))) + and collect (expand-variables name #'get-template-var)))))) (t (sax:start-element *html-sink* nil nil name (xmls-attributes-to-sax (rcurry #'expand-variables #'get-template-var) attrs)) @@ -164,7 +165,7 @@ (sax:start-element *html-sink* (node-ns toplevel) (node-name toplevel) (node-name toplevel) (cxml-xmls::compute-attributes/lnames toplevel t)) (let ((*template-expander* expander)) - (mapc (curry #'emit-template-node expander) (node-children toplevel))) + (emit-template-node expander toplevel)) (sax:end-element *html-sink* (node-ns toplevel) (node-name toplevel) (node-name toplevel))) (defun find-template (dir components) From hhubner at common-lisp.net Wed Feb 13 19:40:27 2008 From: hhubner at common-lisp.net (hhubner at common-lisp.net) Date: Wed, 13 Feb 2008 14:40:27 -0500 (EST) Subject: [bknr-cvs] r2486 - in branches/trunk-reorg/thirdparty/slime: . contrib contrib/CVS Message-ID: <20080213194027.4DB114F01A@common-lisp.net> Author: hhubner Date: Wed Feb 13 14:40:19 2008 New Revision: 2486 Modified: branches/trunk-reorg/thirdparty/slime/contrib/CVS/Entries branches/trunk-reorg/thirdparty/slime/contrib/ChangeLog branches/trunk-reorg/thirdparty/slime/contrib/slime-c-p-c.el branches/trunk-reorg/thirdparty/slime/contrib/slime-xref-browser.el branches/trunk-reorg/thirdparty/slime/slime.el branches/trunk-reorg/thirdparty/slime/swank-backend.lisp branches/trunk-reorg/thirdparty/slime/swank-loader.lisp branches/trunk-reorg/thirdparty/slime/swank.asd branches/trunk-reorg/thirdparty/slime/swank.lisp Log: update and add marcos patch to allow for repeated loading of the swank system Modified: branches/trunk-reorg/thirdparty/slime/contrib/CVS/Entries ============================================================================== --- branches/trunk-reorg/thirdparty/slime/contrib/CVS/Entries (original) +++ branches/trunk-reorg/thirdparty/slime/contrib/CVS/Entries Wed Feb 13 14:40:19 2008 @@ -4,34 +4,34 @@ /slime-asdf.el/1.3/Thu Oct 11 14:10:25 2007// /slime-autodoc.el/1.7/Thu Feb 7 07:59:35 2008// /slime-banner.el/1.4/Thu Oct 11 14:10:25 2007// -/slime-c-p-c.el/1.8/Thu Oct 11 14:10:25 2007// /slime-editing-commands.el/1.6/Thu Feb 7 07:59:35 2008// /slime-fuzzy.el/1.6/Thu Feb 7 07:59:35 2008// /slime-highlight-edits.el/1.3/Thu Oct 11 14:10:25 2007// -/slime-indentation.el/1.1/Sun Feb 3 18:45:14 2008// -/slime-motd.el/1.1/Sun Feb 3 18:39:23 2008// /slime-parse.el/1.10/Thu Feb 7 07:59:35 2008// /slime-presentation-streams.el/1.2/Thu Oct 11 14:10:25 2007// /slime-presentations.el/1.12/Thu Feb 7 07:59:35 2008// /slime-references.el/1.4/Thu Oct 11 14:10:25 2007// -/slime-scheme.el/1.1/Thu Feb 7 08:07:31 2008// /slime-scratch.el/1.4/Thu Oct 11 14:10:25 2007// /slime-tramp.el/1.2/Thu Oct 11 14:10:25 2007// /slime-typeout-frame.el/1.6/Thu Feb 7 07:59:35 2008// -/slime-xref-browser.el/1.1/Thu Oct 11 14:10:25 2007// /swank-arglists.lisp/1.20/Thu Feb 7 08:07:31 2008// /swank-asdf.lisp/1.1/Thu Oct 11 14:10:25 2007// /swank-c-p-c.lisp/1.2/Thu Oct 11 14:10:25 2007// /swank-fuzzy.lisp/1.7/Thu Feb 7 07:59:35 2008// -/swank-goo.goo/1.1/Thu Feb 7 08:07:32 2008// -/swank-indentation.lisp/1.1/Sun Feb 3 18:45:14 2008// -/swank-kawa.scm/1.1/Thu Feb 7 08:07:32 2008// /swank-listener-hooks.lisp/1.1/Thu Oct 11 14:10:25 2007// -/swank-motd.lisp/1.1/Sun Feb 3 18:39:23 2008// /swank-presentation-streams.lisp/1.5/Thu Feb 7 08:07:32 2008// /swank-presentations.lisp/1.4/Thu Oct 11 14:10:25 2007// -/ChangeLog/1.89/Mon Feb 11 14:20:11 2008// /slime-fancy-inspector.el/1.3/Mon Feb 11 14:20:11 2008// /slime-fancy.el/1.5/Mon Feb 11 14:20:11 2008// /swank-fancy-inspector.lisp/1.11/Mon Feb 11 14:20:11 2008// +/ChangeLog/1.91/Wed Feb 13 19:38:01 2008// +/slime-c-p-c.el/1.9/Wed Feb 13 19:38:01 2008// +/slime-indentation.el/1.1/Wed Feb 13 19:38:02 2008// +/slime-motd.el/1.1/Wed Feb 13 19:38:02 2008// +/slime-scheme.el/1.1/Wed Feb 13 19:38:02 2008// +/slime-xref-browser.el/1.2/Wed Feb 13 19:38:02 2008// +/swank-goo.goo/1.1/Wed Feb 13 19:38:03 2008// +/swank-indentation.lisp/1.1/Wed Feb 13 19:38:03 2008// +/swank-kawa.scm/1.1/Wed Feb 13 19:38:03 2008// +/swank-motd.lisp/1.1/Wed Feb 13 19:38:03 2008// D Modified: branches/trunk-reorg/thirdparty/slime/contrib/ChangeLog ============================================================================== --- branches/trunk-reorg/thirdparty/slime/contrib/ChangeLog (original) +++ branches/trunk-reorg/thirdparty/slime/contrib/ChangeLog Wed Feb 13 14:40:19 2008 @@ -1,3 +1,16 @@ +2008-02-13 Helmut Eller + + * slime-c-p-c.el (slime-c-p-c-init): Use slime-require instead of + a connected-hook. + +2008-02-13 Helmut Eller + + Track tree-widget change: :dynarg is now called :expander. + + * slime-xref-browser.el (slime-expand-class-node) + (slime-browse-classes, slime-expand-xrefs, slime-browse-xrefs): + :dynargs is obsolete, it is now called :expander. + 2008-02-10 Helmut Eller Fix some bugs introduced by the recent reorganization. @@ -10,7 +23,7 @@ * slime-fancy.el: slime-fancy-inspector-init no longer exists, so don't call it. Once loaded, it's also no longer possible to turn the fancy inspector off. - + 2008-02-04 Marco Baringer * swank-presentation-streams.lisp (presenting-object-1): Add Modified: branches/trunk-reorg/thirdparty/slime/contrib/slime-c-p-c.el ============================================================================== --- branches/trunk-reorg/thirdparty/slime/contrib/slime-c-p-c.el (original) +++ branches/trunk-reorg/thirdparty/slime/contrib/slime-c-p-c.el Wed Feb 13 14:40:19 2008 @@ -13,7 +13,7 @@ ;; Add this to your .emacs: ;; ;; (add-to-list 'load-path "") -;; (add-hook 'slime-load-hook (lambda () (require 'slime-c-p-c))) +;; (slime-setup '(slime-c-p-c ... possibly other packages ...)) ;; @@ -177,6 +177,7 @@ (defvar slime-c-p-c-init-undo-stack nil) (defun slime-c-p-c-init () + (slime-require :swank-arglists) ;; save current state for unload (push `(progn @@ -188,13 +189,9 @@ ',(lookup-key slime-repl-mode-map "\C-c\C-s"))) slime-c-p-c-init-undo-stack) (setq slime-complete-symbol-function 'slime-complete-symbol*) - (add-hook 'slime-connected-hook 'slime-c-p-c-on-connect) (define-key slime-mode-map "\C-c\C-s" 'slime-complete-form) (define-key slime-repl-mode-map "\C-c\C-s" 'slime-complete-form)) -(defun slime-c-p-c-on-connect () - (slime-eval-async '(swank:swank-require :swank-arglists))) - (defun slime-c-p-c-unload () (while slime-c-p-c-init-undo-stack (eval (pop slime-c-p-c-init-undo-stack)))) Modified: branches/trunk-reorg/thirdparty/slime/contrib/slime-xref-browser.el ============================================================================== --- branches/trunk-reorg/thirdparty/slime/contrib/slime-xref-browser.el (original) +++ branches/trunk-reorg/thirdparty/slime/contrib/slime-xref-browser.el Wed Feb 13 14:40:19 2008 @@ -8,7 +8,7 @@ ;; Add this to your .emacs: ;; ;; (add-to-list 'load-path "") -;; (add-hook 'slime-load-hook (lambda () (require 'slime-xref-browser))) +;; (slime-setup '(slime-xref-browser ... possibly other packages ...)) ;; @@ -19,7 +19,7 @@ (let ((name (widget-get widget :tag))) (loop for kid in (slime-eval `(swank:mop :subclasses ,name)) collect `(tree-widget :tag ,kid - :dynargs slime-expand-class-node + :expander slime-expand-class-node :has-children t))))) (defun slime-browse-classes (name) @@ -29,7 +29,7 @@ "*slime class browser*" (slime-current-package) "Class Browser" (lambda () (widget-create 'tree-widget :tag name - :dynargs 'slime-expand-class-node + :expander 'slime-expand-class-node :has-echildren t)))) (defvar slime-browser-map nil @@ -84,7 +84,7 @@ collect `(tree-widget :tag ,label :xref-type ,type :xref-dspec ,dspec - :dynargs slime-expand-xrefs + :expander slime-expand-xrefs :has-children t))))) (defun slime-browse-xrefs (name type) @@ -99,6 +99,6 @@ "*slime xref browser*" (slime-current-package) "Xref Browser" (lambda () (widget-create 'tree-widget :tag name :xref-type type :xref-dspec name - :dynargs 'slime-expand-xrefs :has-echildren t)))) + :expander 'slime-expand-xrefs :has-echildren t)))) -(provide 'slime-xref-browser) \ No newline at end of file +(provide 'slime-xref-browser) Modified: branches/trunk-reorg/thirdparty/slime/slime.el ============================================================================== --- branches/trunk-reorg/thirdparty/slime/slime.el (original) +++ branches/trunk-reorg/thirdparty/slime/slime.el Wed Feb 13 14:40:19 2008 @@ -1432,6 +1432,7 @@ (format "%S\n\n" `(progn (load ,(expand-file-name loader) :verbose t) + (funcall (read-from-string "swank-loader:load-swank")) (funcall (read-from-string "swank:start-server") ,port-filename :coding-system ,encoding))))) Modified: branches/trunk-reorg/thirdparty/slime/swank-backend.lisp ============================================================================== --- branches/trunk-reorg/thirdparty/slime/swank-backend.lisp (original) +++ branches/trunk-reorg/thirdparty/slime/swank-backend.lisp Wed Feb 13 14:40:19 2008 @@ -10,7 +10,11 @@ ;;; separately for each Lisp. Each is declared as a generic function ;;; for which swank-.lisp provides methods. -(defpackage :swank-backend +;(cl:eval-when (:compile-toplevel :load-toplevel :execute) +; (cl:when (cl:find-package :swank-backend) +; (cl:delete-package :swank-backend))) + +(cl:defpackage :swank-backend (:use :common-lisp) (:export #:sldb-condition #:original-condition @@ -39,7 +43,11 @@ #:with-struct )) -(defpackage :swank-mop +(cl:eval-when (:compile-toplevel :load-toplevel :execute) + (cl:when (cl:find-package :swank-mop) + (cl:delete-package :swank-mop))) + +(cl:defpackage :swank-mop (:use) (:export ;; classes Modified: branches/trunk-reorg/thirdparty/slime/swank-loader.lisp ============================================================================== --- branches/trunk-reorg/thirdparty/slime/swank-loader.lisp (original) +++ branches/trunk-reorg/thirdparty/slime/swank-loader.lisp Wed Feb 13 14:40:19 2008 @@ -18,11 +18,11 @@ ;; (defparameter swank-loader::*fasl-directory* "/tmp/fasl/") ;; (load ".../swank-loader.lisp") -(eval-when (:compile-toplevel :load-toplevel :execute) - (when (find-package :swank) - (delete-package :swank) - (delete-package :swank-io-package) - (delete-package :swank-backend))) +;(cl:eval-when (:compile-toplevel :load-toplevel :execute) +; (cl:when (cl:find-package :swank) +; (cl:delete-package :swank-loader) +; (cl:delete-package :swank) +; (cl:delete-package :swank-backend))) (cl:defpackage :swank-loader (:use :cl) @@ -139,7 +139,7 @@ (ignore-errors (delete-file binary-pathname))) (abort)) -(defun compile-files-if-needed-serially (files fasl-directory load) +(defun compile-files-if-needed-serially (files fasl-directory &key load force) "Compile each file in FILES if the source is newer than its corresponding binary, or the file preceding it was recompiled." @@ -149,7 +149,8 @@ fasl-directory))) (handler-case (progn - (when (or needs-recompile + (when (or force + needs-recompile (not (probe-file binary-pathname)) (file-newer-p source-pathname binary-pathname)) ;; need a to recompile source-pathname, so we'll @@ -220,18 +221,17 @@ (source-directory *source-directory*) (fasl-directory *fasl-directory*) (contrib-fasl-directory - (append-dir fasl-directory "contrib"))) + (append-dir fasl-directory "contrib")) + (force nil)) (compile-files-if-needed-serially (swank-source-files source-directory) - fasl-directory t) + fasl-directory :load t :force force) (compile-files-if-needed-serially (contrib-source-files source-directory) - contrib-fasl-directory nil)) - -(load-swank) + contrib-fasl-directory :load nil :force force) -(setq swank::*swank-wire-protocol-version* (slime-version-string)) -(setq swank::*load-path* - (append swank::*load-path* (list (contrib-src-dir *source-directory*)))) -(swank-backend::warn-unimplemented-interfaces) -(load-site-init-file *source-directory*) -(load-user-init-file) -(swank:run-after-init-hook) + (setf (symbol-value (read-from-string "swank::*swank-wire-protocol-version*")) (slime-version-string)) + (push (contrib-src-dir *source-directory*) + (symbol-value (read-from-string "swank::*load-path*"))) + (funcall (read-from-string "swank-backend::warn-unimplemented-interfaces")) + (load-site-init-file *source-directory*) + (load-user-init-file) + (funcall (read-from-string "swank:run-after-init-hook"))) Modified: branches/trunk-reorg/thirdparty/slime/swank.asd ============================================================================== --- branches/trunk-reorg/thirdparty/slime/swank.asd (original) +++ branches/trunk-reorg/thirdparty/slime/swank.asd Wed Feb 13 14:40:19 2008 @@ -24,25 +24,32 @@ (in-package :swank-loader) -(defclass cl-script-file (asdf:source-file) ()) +(defclass swank-loader-file (asdf:source-file) ()) -(defmethod asdf:perform ((o asdf:compile-op) (f cl-script-file)) - t) -(defmethod asdf:perform ((o asdf:load-op) (f cl-script-file)) - (mapcar #'load (asdf:input-files o f))) -(defmethod asdf:output-files ((o asdf:compile-op) (f cl-script-file)) - nil) -(defmethod asdf:input-files ((o asdf:load-op) (c cl-script-file)) - (list (asdf:component-pathname c))) -(defmethod asdf:operation-done-p ((o asdf:compile-op) (c cl-script-file)) - t) -(defmethod asdf:source-file-type ((c cl-script-file) (s asdf:module)) +;; asdf:compile-op does nothing for swank. + +(defmethod asdf:perform ((o asdf:compile-op) (f swank-loader-file)) t) + +(defmethod asdf:operation-done-p ((o asdf:compile-op) (f swank-loader-file)) t) + +(defmethod asdf:output-files ((o asdf:compile-op) (f swank-loader-file)) '()) + +;; asdf:load-op acutally loads it + +(defmethod asdf:perform ((o asdf:load-op) (f swank-loader-file)) + (if (find-package :swank) + (warn "Attempting to load re-load swank into this image. Ignoring request.") + (progn + (load (merge-pathnames (asdf:component-pathname f))) + (funcall (read-from-string "swank-loader:load-swank") + :source-directory (asdf:component-pathname (asdf:find-system :swank)))))) + +(defmethod asdf:operation-done-p ((o asdf:load-op) (f swank-loader-file)) + (find-package :swank)) + +(defmethod asdf:source-file-type ((c swank-loader-file) (s asdf:module)) "lisp") (asdf:defsystem :swank - :default-component-class cl-script-file + :default-component-class swank-loader-file :components ((:file "swank-loader"))) - -(defparameter *source-directory* - (asdf:component-pathname (asdf:find-system :swank))) - Modified: branches/trunk-reorg/thirdparty/slime/swank.lisp ============================================================================== --- branches/trunk-reorg/thirdparty/slime/swank.lisp (original) +++ branches/trunk-reorg/thirdparty/slime/swank.lisp Wed Feb 13 14:40:19 2008 @@ -12,7 +12,11 @@ ;;; them separately for each Lisp implementation. These extensions are ;;; available to us here via the `SWANK-BACKEND' package. -(defpackage :swank +;(cl:eval-when (:compile-toplevel :load-toplevel :execute) +; (cl:when (cl:find-package :swank) +; (cl:delete-package :swank))) + +(cl:defpackage :swank (:use :cl :swank-backend) (:export #:startup-multiprocessing #:start-server From hhubner at common-lisp.net Wed Feb 13 19:41:11 2008 From: hhubner at common-lisp.net (hhubner at common-lisp.net) Date: Wed, 13 Feb 2008 14:41:11 -0500 (EST) Subject: [bknr-cvs] r2487 - in branches/trunk-reorg/thirdparty/drakma-0.11.3: . doc Message-ID: <20080213194111.D4CDB702E7@common-lisp.net> Author: hhubner Date: Wed Feb 13 14:41:09 2008 New Revision: 2487 Added: branches/trunk-reorg/thirdparty/drakma-0.11.3/ branches/trunk-reorg/thirdparty/drakma-0.11.3/CHANGELOG.txt (contents, props changed) branches/trunk-reorg/thirdparty/drakma-0.11.3/cookies.lisp (contents, props changed) branches/trunk-reorg/thirdparty/drakma-0.11.3/doc/ branches/trunk-reorg/thirdparty/drakma-0.11.3/doc/index.html (contents, props changed) branches/trunk-reorg/thirdparty/drakma-0.11.3/drakma.asd (contents, props changed) branches/trunk-reorg/thirdparty/drakma-0.11.3/packages.lisp (contents, props changed) branches/trunk-reorg/thirdparty/drakma-0.11.3/read.lisp (contents, props changed) branches/trunk-reorg/thirdparty/drakma-0.11.3/request.lisp (contents, props changed) branches/trunk-reorg/thirdparty/drakma-0.11.3/specials.lisp (contents, props changed) branches/trunk-reorg/thirdparty/drakma-0.11.3/util.lisp (contents, props changed) Log: Add drakma Added: branches/trunk-reorg/thirdparty/drakma-0.11.3/CHANGELOG.txt ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/drakma-0.11.3/CHANGELOG.txt Wed Feb 13 14:41:09 2008 @@ -0,0 +1,147 @@ +Version 0.11.3 +2008-01-14 +The previous change is only needed for Windows + +Version 0.11.2 +2008-01-14 +Disable WRITE-TIMEOUT for LW5.0 if SSL is used (reported by Nico de Jager) + +Version 0.11.1 +2007-10-11 +Make Drakma work with AllegroCL's "modern" mode (patch by Ross Jekel) +Needs at least Chunga 0.4.1 and FLEXI-STREAMS 0.13.1 + +Version 0.11.0 +2007-10-01 +Added *TEXT-CONTENT-TYPES* and *BODY-FORMAT-FUNCTION* (suggested by Peter Eddy) + +Version 0.10.2 +2007-09-29 +Fixed bug introduced in latest change... (reported by Ross Jekel) + +Version 0.10.1 +2007-09-25 +Use parameters in URI if they weren't used up for the content body (suggested by Jan Rychter) + +Version 0.10.0 +2007-09-18 +Added support for "HttpOnly" cookie attribute (due to a bug report by Alexey Goldin) + +Version 0.9.1 +2007-07-12 +Improved CL+SSL support (patch by David Lichteblau) + +Version 0.9.0 +2007-06-30 +Added reason phrase to return values (patch by Holger D?rer) + +Version 0.8.0 +2007-06-25 +In cookie dates, accept time zones different from "GMT" (reported by Didier Verna) +Added *ignore-unparseable-cookie-dates-p* + +Version 0.7.1 +2007-06-17 +Allow streams or functions as file designators (suggested by Andrei Stebakov) + +Version 0.7.0 +2007-04-07 +Switched from trivial-sockets to usocket (patch by Erik Huelsmann) + +Version 0.6.2 +2007-03-09 +Fixed release dates (thanks to Jeffrey Cunningham) + +Version 0.6.1 +2007-03-08 +Changed SPLIT-STRING so that it doesn't rely on unspecified behaviour (reported by Jianshi Huang) + +Version 0.6.0 +2007-02-08 +Make sure stream is closed in case of early errors (thanks to Chris Dean for test data) +Robustified cookie parsing +Send all outgoing cookies in one fell swoop (for Sun's buggy web server) +Deal with empty Location headers +Deal with corrupted Content-Type headers + +Version 0.5.5 +2007-02-05 +Fixed socket leak in case of redirects (bug report by Chris Dean) + +Version 0.5.4 +2006-12-01 +Workaround for servers which send headers after 100 status line (provided by Donavon Keithley) + +Version 0.5.3 +2006-10-11 +Set stream element type for binary streams as needed for CLISP (reported by Magnus Henoch) + +Version 0.5.2 +2006-10-08 +Adhere to user-provided content length if FORM-DATA is true + +Version 0.5.1 +2006-10-07 +Take Content-Encoding header into account (due to a bug report by Gregory Tod) + +Version 0.5.0 +2006-09-25 +Fixed bug where body sometimes wasn't read (reported by Ivan Toshkov) +Added AUTO-REFERER feature (thanks to Colin Simmonds) + +Version 0.4.4 +2006-09-24 +Treat "localhost" special for cookies (reported by Ivan Toshkov) + +Version 0.4.3 +2006-09-24 +Circumvent CL+SSL for AllegroCL (suggested by David Lichteblau) + +Version 0.4.2 +2006-09-07 +Fixed :OPTIONS* method + +Version 0.4.1 +2006-09-07 +Added more methods including :OPTIONS* pseudo method (suggested by Ralf Mattes) +Always (except for POST) add parameters to URI query +Always read body (unless there's no chunking and no content length) + +Version 0.4.0 +2006-09-05 +Added file uploads +Added multipart/form-data +Added enforced computation of request bodies in RAM +Use LF line endings in default external format + +Version 0.3.1 +2006-09-04 +Don't use underlying streams of flexi streams anymore +Returned streams now have element type OCTET when FORCE-BINARY is true +Better default "User-Agent" header for some Lisps +Added info about mailing lists +Added note about Gentoo + +Version 0.3.0 +2006-09-02 +Added client-side chunked encoding and various ways to send the content + +Version 0.2.0 +2006-09-01 +Completely re-factored for portability, chunking code is in Chunga now + +Version 0.1.3 +2006-08-30 +REQUIRE "comm" before WITH-STREAM-INPUT-BUFFER is used + +Version 0.1.2 +2006-08-27 +Notes about SSL and listener font + +Version 0.1.1 +2006-08-27 +Note about CL-BASE64 and KMRCL + +Version 0.1.0 +2006-08-27 +First public release Added: branches/trunk-reorg/thirdparty/drakma-0.11.3/cookies.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/drakma-0.11.3/cookies.lisp Wed Feb 13 14:41:09 2008 @@ -0,0 +1,309 @@ +;;; -*- Mode: LISP; Syntax: COMMON-LISP; Package: DRAKMA; Base: 10 -*- +;;; $Header: /usr/local/cvsrep/drakma/cookies.lisp,v 1.15 2008/01/14 01:57:01 edi Exp $ + +;;; Copyright (c) 2006-2008, Dr. Edmund Weitz. All rights reserved. + +;;; Redistribution and use in source and binary forms, with or without +;;; modification, are permitted provided that the following conditions +;;; are met: + +;;; * Redistributions of source code must retain the above copyright +;;; notice, this list of conditions and the following disclaimer. + +;;; * Redistributions in binary form must reproduce the above +;;; copyright notice, this list of conditions and the following +;;; disclaimer in the documentation and/or other materials +;;; provided with the distribution. + +;;; THIS SOFTWARE IS PROVIDED BY THE AUTHOR 'AS IS' AND ANY EXPRESSED +;;; OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +;;; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +;;; ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +;;; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +;;; DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +;;; GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +;;; INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +;;; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +;;; NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +;;; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +(in-package :drakma) + +(defclass cookie () + ((name :initarg :name + :initform (error "A cookie must have a name.") + :accessor cookie-name + :documentation "The name of the cookie.") + (value :initarg :value + :initform "" + :accessor cookie-value + :documentation "The cookie's value.") + (domain :initarg :domain + :initform (error "A cookie must have a domain.") + :accessor cookie-domain + :documentation "The domain the cookie is valid for.") + (path :initarg :path + :initform "/" + :accessor cookie-path + :documentation "The path prefix the cookie is valid for.") + (expires :initarg :expires + :initform nil + :accessor cookie-expires + :documentation "When the cookie expires. A Lisp +universal time or NIL.") + (securep :initarg :securep + :initform nil + :accessor cookie-securep + :documentation "Whether the cookie must only be +transmitted over secure connections.") + (http-only-p :initarg :http-only-p + :initform nil + :accessor cookie-http-only-p + :documentation "Whether the cookie should not be +accessible from Javascript. + +This is a Microsoft extension that has been implemented in Firefox as +well. See .")) + (:documentation "Elements of this class represent HTTP cookies.")) + +(defun render-cookie-date (time) + "Returns a string representation of the universal time TIME +which can be used for cookie headers." + (multiple-value-bind (second minute hour date month year weekday) + (decode-universal-time time 0) + (format nil "~A, ~2,'0d-~2,'0d-~4,'0d ~2,'0d:~2,'0d:~2,'0d GMT" + (aref #("Mon" "Tue" "Wed" "Thu" "Fri" "Sat" "Sun") weekday) + date month year hour minute second))) + +(defmethod print-object ((cookie cookie) stream) + "Prints a representation of COOKIE similar to a `Set-Cookie' header." + (print-unreadable-object (cookie stream :type t) + (with-slots (name value expires path domain securep http-only-p) + cookie + (format stream "~A~@[=~A~]~@[; expires=~A~]~@[; path=~A~]~@[; domain=~A~]~@[; secure~]~@[; HttpOnly~]" + name (and (plusp (length value)) value) + (and expires (render-cookie-date expires)) + path domain securep http-only-p)))) + +(defun normalize-cookie-domain (domain) + "Adds a dot at the beginning of the string DOMAIN unless there +is already one." + (cond ((starts-with-p domain ".") domain) + (t (format nil ".~A" domain)))) + +(defun valid-cookie-domain-p (domain) + "Checks if the string DOMAIN contains enough dots to be +acceptable." + (or (string-equal domain "localhost") + (> (count #\. (normalize-cookie-domain domain) :test #'char=) 1))) + +(defun cookie-domain-matches (domain uri) + "Checks if the domain DOMAIN \(a string) matches the \(PURI) URI URI." + (ends-with-p (normalize-cookie-domain (uri-host uri)) + (normalize-cookie-domain domain))) + +(defun send-cookie-p (cookie uri force-ssl) + "Checks if the cookie COOKIE should be sent to the server +depending on the \(PURI) URI URI and the value of FORCE-SSL \(as +in HTTP-REQUEST)." + (and ;; check domain + (cookie-domain-matches (cookie-domain cookie) uri) + ;; check path + (starts-with-p (uri-path uri) (cookie-path cookie)) + ;; check expiry date + (let ((expires (cookie-expires cookie))) + (or (null expires) + (> expires (get-universal-time)))) + ;; check if connection must be secure + (or (null (cookie-securep cookie)) + force-ssl + (eq (uri-scheme uri) :https)))) + +(defun check-cookie (cookie) + "Checks if the slots of the COOKIE object COOKIE have valid +values and raises a corresponding error otherwise." + (with-slots (name value domain path expires) + cookie + (unless (and (stringp name) (plusp (length name))) + (error "Cookie name ~S must be a non-empty string." name)) + (unless (stringp value) + (error "Cookie value ~S must be a non-empty string." value)) + (unless (valid-cookie-domain-p domain) + (error "Invalid cookie domain ~S." domain)) + (unless (and (stringp path) (plusp (length path))) + (error "Cookie path ~S must be a non-empty string." path)) + (unless (or (null expires) + (and (integerp expires) + (plusp expires))) + (error "Cookie expiry ~S should have been NIL or a universal time." expires)))) + +(defmethod initialize-instance :after ((cookie cookie) &rest initargs) + "Check cookie validity after creation." + (declare (ignore initargs)) + (check-cookie cookie)) + +(defmethod (setf cookie-name) :after (new-value (cookie cookie)) + "Check cookie validity after name change." + (declare (ignore new-value)) + (check-cookie cookie)) + +(defmethod (setf cookie-value) :after (new-value (cookie cookie)) + "Check cookie validity after value change." + (declare (ignore new-value)) + (check-cookie cookie)) + +(defmethod (setf cookie-domain) :after (new-value (cookie cookie)) + "Check cookie validity after domain change." + (declare (ignore new-value)) + (check-cookie cookie)) + +(defmethod (setf cookie-path) :after (new-value (cookie cookie)) + "Check cookie validity after path change." + (declare (ignore new-value)) + (check-cookie cookie)) + +(defmethod (setf cookie-expires) :after (new-value (cookie cookie)) + "Check cookie validity after expiry change." + (declare (ignore new-value)) + (check-cookie cookie)) + +(defun cookie= (cookie1 cookie2) + "Returns true if the cookies COOKIE1 and COOKIE2 are equal. +Two cookies are considered to be equal if name and path are +equal." + (and (string= (cookie-name cookie1) (cookie-name cookie2)) + (string= (cookie-path cookie1) (cookie-path cookie2)))) + +(defclass cookie-jar () + ((cookies :initarg :cookies + :initform nil + :accessor cookie-jar-cookies + :documentation "A list of the cookies in this cookie jar.")) + (:documentation "A COOKIE-JAR object is a collection of cookies.")) + +(defmethod print-object ((cookie-jar cookie-jar) stream) + "Print a cookie jar, showing the number of cookies it contains." + (print-unreadable-object (cookie-jar stream :type t :identity t) + (format stream "(with ~A cookie~:P)" (length (cookie-jar-cookies cookie-jar))))) + +(defun parse-cookie-date (string) + "Parses a cookie expiry date and returns it as a Lisp universal +time. Currently understands the following formats: + + \"Wed, 06-Feb-2008 21:01:38 GMT\" + \"Wed, 06-Feb-08 21:01:38 GMT\" + \"Tue Feb 13 08:00:00 2007 GMT\" + \"Wednesday, 07-February-2027 08:55:23 GMT\" + \"Wed, 07-02-2017 10:34:45 GMT\" + +Instead of \"GMT\" time zone abbreviations like \"CEST\" and UTC +offsets like \"GMT-01:30\" are also allowed." + ;; it seems like everybody and their sister invents their own format + ;; for this, so (as there's no real standard for it) we'll have to + ;; make this function more flexible once we come across something + ;; new; as an alternative we could use net-telent-date, but it also + ;; fails to parse some of the stuff you encounter in the wild; or we + ;; could try to employ CL-PPCRE, but that'd add a new dependency + ;; without making this code much cleaner + (handler-case + (let* ((last-space-pos (or (position #\Space string :test #'char= :from-end t) + (error "Can't parse cookie date ~S, no space found." string))) + (time-zone-string (subseq string (1+ last-space-pos))) + (time-zone (interpret-as-time-zone time-zone-string)) + second minute hour day month year) + (dolist (part (rest (split-string (subseq string 0 last-space-pos)))) + (when (and day month) + (cond ((every #'digit-char-p part) + (when year + (error "Can't parse cookie date ~S, confused by ~S part." string part)) + (setq year (parse-integer part))) + ((= (count #\: part :test #'char=) 2) + (let ((h-m-s (mapcar #'safe-parse-integer (split-string part ":")))) + (setq hour (first h-m-s) + minute (second h-m-s) + second (third h-m-s)))) + (t (error "Can't parse cookie date ~S, confused by ~S part." string part)))) + (cond ((null day) + (unless (setq day (safe-parse-integer part)) + (setq month (interpret-as-month part)))) + ((null month) + (setq month (interpret-as-month part))))) + (unless (and second minute hour day month year) + (error "Can't parse cookie date ~S, component missing." string)) + (when (< year 100) + (setq year (+ year 2000))) + (encode-universal-time second minute hour day month year time-zone)) + (error (condition) + (cond (*ignore-unparseable-cookie-dates-p* + (warn "~A" condition) + nil) + (t (error condition)))))) + +(defun parse-set-cookie (string) + "Parses the `Set-Cookie' header line STRING and returns a list +of three-element lists where each one contains the name of the +cookie, the value of the cookie, and an attribute/value list for +the optional cookie parameters." + (with-input-from-string (stream string) + (loop with *current-error-message* = (format nil "While parsing cookie header ~S:" string) + for first = t then nil + for next = (and (skip-whitespace stream) + (or first (assert-char stream #\,)) + (skip-whitespace stream) + (skip-more-commas stream)) + for name/value = (and next (read-name-value-pair stream + :cookie-syntax t)) + for parameters = (and name/value (read-name-value-pairs stream + :value-required-p nil + :cookie-syntax t)) + while name/value + collect (list (car name/value) (cdr name/value) parameters)))) + +(defun get-cookies (headers uri) + "Returns a list of COOKIE objects corresponding to the +`Set-Cookie' header as found in HEADERS \(an alist as returned by +HTTP-REQUEST). Collects only cookies which match the domain of +the \(PURI) URI URI." + (loop with set-cookie-header = (header-value :set-cookie headers) + with parsed-cookies = (and set-cookie-header (parse-set-cookie set-cookie-header)) + for (name value parameters) in parsed-cookies + for expires = (parameter-value "expires" parameters) + for domain = (or (parameter-value "domain" parameters) (uri-host uri)) + when (and (valid-cookie-domain-p domain) + (cookie-domain-matches domain uri)) + collect (make-instance 'cookie + :name name + :value value + :path (or (parameter-value "path" parameters) + (uri-path uri) + "/") + :expires (and expires + (plusp (length expires)) + (parse-cookie-date expires)) + :domain domain + :securep (not (not (parameter-present-p "secure" parameters))) + :http-only-p (not (not (parameter-present-p "HttpOnly" parameters)))))) + +(defun update-cookies (new-cookies cookie-jar) + "Updates the cookies in COOKIE-JAR by replacing those which are +equal to a cookie in \(the list) NEW-COOKIES with the corresponding +`new' cookie and adding those which are really new." + (setf (cookie-jar-cookies cookie-jar) + (let ((updated-cookies + (loop for old-cookie in (cookie-jar-cookies cookie-jar) + collect (or (find old-cookie new-cookies :test #'cookie=) + old-cookie)))) + (union updated-cookies + (set-difference new-cookies updated-cookies)))) + cookie-jar) + +(defun delete-old-cookies (cookie-jar) + "Removes all cookies from COOKIE-JAR which have either expired +or which don't have an expiry date." + (setf (cookie-jar-cookies cookie-jar) + (loop with now = (get-universal-time) + for cookie in (cookie-jar-cookies cookie-jar) + for expires = (cookie-expires cookie) + unless (or (null expires) (< expires now)) + collect cookie)) + cookie-jar) Added: branches/trunk-reorg/thirdparty/drakma-0.11.3/doc/index.html ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/drakma-0.11.3/doc/index.html Wed Feb 13 14:41:09 2008 @@ -0,0 +1,1472 @@ + + + + + + DRAKMA - A Common Lisp web client + + + + + +

DRAKMA - A Common Lisp web client

+ +
+
 

Abstract

+ +Drakma is a fully-featured web client (implemented in Common Lisp) +that knows how to handle HTTP/1.1 +chunking, persistent +connections, re-usable +sockets, SSL, continuable +uploads, file uploads, cookies, and other +things. And it's probably a result of +my NIH +syndrome... +

+Drakma was developed and tested +with LispWorks, but it should +also work with a couple of other Common Lisp implementations depending +on the supporting libraries. Some tests +with SBCL seem to confirm this. +

+The code comes with +a BSD-style +license so you can basically do with it whatever you want. + +

+Download shortcut: http://weitz.de/files/drakma.tar.gz. +

+ +
 

Contents

+
    +
  1. Examples +
  2. Download and installation +
  3. Support and mailing lists +
  4. The Drakma dictionary +
      +
    1. The request +
        +
      1. http-request +
      2. *drakma-default-external-format* +
      3. *text-content-types* +
      4. *body-format-function* +
      5. *header-stream* +
      +
    2. Cookies +
        +
      1. cookie +
      2. cookie-name +
      3. cookie-value +
      4. cookie-domain +
      5. cookie-path +
      6. cookie-expires +
      7. cookie-securep +
      8. cookie-http-only-p +
      9. cookie-jar +
      10. cookie-jar-cookies +
      11. cookie= +
      12. delete-old-cookies +
      13. *ignore-unparseable-cookie-dates-p* +
      +
    3. Headers +
        +
      1. header-value +
      2. split-tokens +
      3. read-tokens-and-parameters +
      4. parameter-present-p +
      5. parameter-value +
      6. get-content-type +
      +
    +
  5. Potential problems +
  6. Acknowledgements +
+ +
 

Examples

+ +Here's an example session with Drakma 0.3.0 which demonstrates +some of its features. (Some linebreaks were added or removed to +enhance legibility.) Note that this doesn't necessarily reflect the +current versions of Drakma and Hunchentoot. The examples should work +nevertheless - kind of... + +
+;; create a log file of this sessions
+CL-USER 1 > (dribble "/tmp/drakma_dribble")
+; Loading C:\Program Files\LispWorks\lib\5-0-0-0\load-on-demand\ccl\dribble.ofasl on demand...
+
+;; load Drakma
+CL-USER 2 > (asdf:oos 'asdf:load-op :drakma)
+; loading system definition from c:\home\lisp\drakma\drakma.asd into
+; #<The ASDF0 package, 0/16 internal, 0/16 external>
+; Loading text file c:\home\lisp\drakma\drakma.asd
+; registering #<SYSTEM :DRAKMA 21D6D24F> as DRAKMA
+;; Creating system COMMON-LISP-USER::DRAKMA
+; loading system definition from c:\home\lisp\chunga\chunga.asd into
+; #<The ASDF0 package, 0/16 internal, 0/16 external>
+; Loading text file c:\home\lisp\chunga\chunga.asd
+; registering #<SYSTEM :CHUNGA 200B12A3> as CHUNGA
+;; Creating system COMMON-LISP-USER::CHUNGA
+; loading system definition from c:\home\lisp\flexi-streams\flexi-streams.asd into
+; #<The ASDF0 package, 0/16 internal, 0/16 external>
+; Loading text file c:\home\lisp\flexi-streams\flexi-streams.asd
+; registering #<SYSTEM :FLEXI-STREAMS 200E8017> as FLEXI-STREAMS
+;; Creating system COMMON-LISP-USER::FLEXI-STREAMS
+; loading system definition from c:\home\lisp\trivial-gray-streams\trivial-gray-streams.asd into
+; #<The ASDF0 package, 0/16 internal, 0/16 external>
+; Loading text file c:\home\lisp\trivial-gray-streams\trivial-gray-streams.asd
+; registering #<SYSTEM :TRIVIAL-GRAY-STREAMS 21D6741F> as TRIVIAL-GRAY-STREAMS
+;; Creating system COMMON-LISP-USER::TRIVIAL-GRAY-STREAMS
+; loading system definition from c:\home\lisp\cl-base64-3.3.2\cl-base64.asd into
+; #<The ASDF0 package, 0/16 internal, 0/16 external>
+; Loading text file c:\home\lisp\cl-base64-3.3.2\cl-base64.asd
+; registering #<SYSTEM CL-BASE64 21D6D277> as CL-BASE64
+;; Creating system COMMON-LISP-USER::CL-BASE64
+; registering #<SYSTEM CL-BASE64-TESTS 2009701B> as CL-BASE64-TESTS
+;; Creating system COMMON-LISP-USER::CL-BASE64-TESTS
+; loading system definition from c:\home\lisp\puri-1.5\puri.asd into
+; #<The ASDF0 package, 0/16 internal, 0/16 external>
+; Loading text file c:\home\lisp\puri-1.5\puri.asd
+; registering #<SYSTEM PURI 21D6B093> as PURI
+;; Creating system COMMON-LISP-USER::PURI
+; registering #<SYSTEM PURI-TESTS 200CFEEF> as PURI-TESTS
+;; Creating system COMMON-LISP-USER::PURI-TESTS
+; Loading fasl file c:\home\lisp\trivial-gray-streams\package.ofasl
+; Loading fasl file c:\home\lisp\trivial-gray-streams\mixin.ofasl
+; Loading fasl file c:\home\lisp\flexi-streams\packages.ofasl
+; Loading fasl file c:\home\lisp\flexi-streams\ascii.ofasl
+; Loading fasl file c:\home\lisp\flexi-streams\iso-8859.ofasl
+; Loading fasl file c:\home\lisp\flexi-streams\code-pages.ofasl
+; Loading fasl file c:\home\lisp\flexi-streams\specials.ofasl
+; Loading fasl file c:\home\lisp\flexi-streams\util.ofasl
+; Loading fasl file c:\home\lisp\flexi-streams\external-format.ofasl
+; Loading fasl file c:\home\lisp\flexi-streams\in-memory.ofasl
+; Loading fasl file c:\home\lisp\flexi-streams\stream.ofasl
+; Loading fasl file c:\home\lisp\flexi-streams\output.ofasl
+; Loading fasl file c:\home\lisp\flexi-streams\input.ofasl
+; Loading fasl file c:\home\lisp\flexi-streams\strings.ofasl
+; Loading fasl file c:\home\lisp\chunga\packages.ofasl
+; Loading fasl file c:\home\lisp\chunga\specials.ofasl
+; Loading fasl file c:\home\lisp\chunga\util.ofasl
+; Loading fasl file c:\home\lisp\chunga\read.ofasl
+; Loading fasl file c:\home\lisp\chunga\streams.ofasl
+; Loading fasl file c:\home\lisp\chunga\input.ofasl
+; Loading fasl file c:\home\lisp\chunga\output.ofasl
+; Loading fasl file c:\home\lisp\cl-base64-3.3.2\package.ofasl
+; Loading fasl file c:\home\lisp\cl-base64-3.3.2\encode.ofasl
+; Loading fasl file c:\home\lisp\cl-base64-3.3.2\decode.ofasl
+; Loading fasl file c:\home\lisp\puri-1.5\src.ofasl
+; Loading fasl file c:\home\lisp\drakma\packages.ofasl
+; Loading fasl file c:\home\lisp\drakma\specials.ofasl
+; Loading fasl file c:\home\lisp\drakma\util.ofasl
+; Loading c:\Program Files\LispWorks\lib\5-0-0-0\load-on-demand\processes\comm-defsys.lisp on demand...
+;; Creating system COMM
+
+;  Loading text file c:\Program Files\LispWorks\lib\5-0-0-0\load-on-demand\processes\comm-pkg.lisp
+;  Loading fasl file c:\Program Files\LispWorks\lib\5-0-0-0\load-on-demand\processes\sockets.ofasl
+;  Loading fasl file c:\Program Files\LispWorks\lib\5-0-0-0\load-on-demand\processes\ssl-constants.ofasl
+;  Loading fasl file c:\Program Files\LispWorks\lib\5-0-0-0\load-on-demand\processes\ssl-foreign-types.ofasl
+;  Loading fasl file c:\Program Files\LispWorks\lib\5-0-0-0\load-on-demand\processes\ssl.ofasl
+;  Loading fasl file c:\Program Files\LispWorks\lib\5-0-0-0\load-on-demand\processes\ssl-certs.ofasl
+;  Loading fasl file c:\Program Files\LispWorks\lib\5-0-0-0\patches\comm\0001\0001.ofasl
+; Loaded public patch COMM 1.1
+
+;  Loading fasl file c:\Program Files\LispWorks\lib\5-0-0-0\patches\comm\0001\0002.ofasl
+; Loaded public patch COMM 1.2
+
+;  Loading fasl file c:\Program Files\LispWorks\lib\5-0-0-0\patches\comm\0001\0003.ofasl
+; Loaded public patch COMM 1.3
+
+;  Loading fasl file c:\Program Files\LispWorks\lib\5-0-0-0\patches\comm\0001\0004.ofasl
+; Loaded public patch COMM 1.4
+
+; Loading fasl file c:\home\lisp\drakma\read.ofasl
+; Loading fasl file c:\home\lisp\drakma\cookies.ofasl
+; Loading fasl file c:\home\lisp\drakma\request.ofasl
+NIL
+
+;; create a package to work in
+CL-USER 3 > (defpackage :drakma-user (:use :cl :drakma))
+#<The DRAKMA-USER package, 0/16 internal, 0/16 external>
+
+;; switch to this package
+CL-USER 4 > (in-package :drakma-user)
+#<The DRAKMA-USER package, 0/16 internal, 0/16 external>
+
+;; log headers, so we can see what happens -
+;; output to *HEADER-STREAM* will be shown in green below
+DRAKMA-USER 5 > (setq *header-stream* *standard-output*)
+#<Broadcast stream to (#<Echo Stream Input = #<EDITOR::RUBBER-STREAM #<EDITOR:BUFFER CAPI interactive-pane 2> 2198ECD7>,
+                                     Output = #<STREAM::LATIN-1-FILE-STREAM c:\tmp\drakma_dribble>>
+                       #<EDITOR::RUBBER-STREAM #<EDITOR:BUFFER CAPI interactive-pane 2> 2198ECD7>)>
+
+;; note how Drakma automatically follows the 301 redirect and how the fourth return value shows the new URI
+DRAKMA-USER 6 > (http-request "http://lisp.org/")
+GET / HTTP/1.1
+Host: lisp.org
+User-Agent: Drakma/0.3.0 (LispWorks 5.0.0; Windows NT; Windows XP: 5.1 (build 2600) Service Pack 2; http://weitz.de/drakma/)
+Accept: */*
+Connection: close
+
+HTTP/1.1 301  Moved Permanently
+Date: Sat, 26 Aug 2006 15:46:31 GMT
+Connection: Close
+Server: AllegroServe/1.2.37
+Transfer-Encoding: chunked
+LOCATION: /index.html
+
+GET /index.html HTTP/1.1
+Host: lisp.org
+User-Agent: Drakma/0.3.0 (LispWorks 5.0.0; Windows NT; Windows XP: 5.1 (build 2600) Service Pack 2; http://weitz.de/drakma/)
+Accept: */*
+Connection: close
+
+HTTP/1.1 200  OK
+Date: Sat, 26 Aug 2006 15:46:32 GMT
+Connection: Close
+Server: AllegroServe/1.2.37
+Content-Type: text/html
+Content-Length: 82
+LAST-MODIFIED: Mon, 16 Feb 2004 09:30:02 GMT
+
+"<title>redirect...</title>
+<meta http-equiv=\"Refresh\" content=\"0; url=/alu/home\">
+"
+200
+((:DATE . "Sat, 26 Aug 2006 15:46:32 GMT")
+ (:CONNECTION . "Close")
+ (:SERVER . "AllegroServe/1.2.37")
+ (:CONTENT-TYPE . "text/html")
+ (:CONTENT-LENGTH . "82")
+ (:LAST-MODIFIED . "Mon, 16 Feb 2004 09:30:02 GMT"))
+#<URI http://lisp.org/index.html>
+#<FLEXI-STREAMS:FLEXI-IO-STREAM 201017D3>
+T
+
+;; here, Drakma automatically interprets the 'charset=utf-8' part correctly -
+;; might look a bit different in your listener depending on the font you've chosen
+DRAKMA-USER 7 > (subseq (http-request "http://www.cl.cam.ac.uk/~mgk25/ucs/examples/digraphs.txt") 0 298)
+GET /~mgk25/ucs/examples/digraphs.txt HTTP/1.1
+Host: www.cl.cam.ac.uk
+User-Agent: Drakma/0.3.0 (LispWorks 5.0.0; Windows NT; Windows XP: 5.1 (build 2600) Service Pack 2; http://weitz.de/drakma/)
+Accept: */*
+Connection: close
+
+HTTP/1.1 200 OK
+Date: Sat, 26 Aug 2006 16:02:56 GMT
+Server: Apache/1.3.37 (Unix) mod_ucam_webauth/1.2.2
+Last-Modified: Thu, 05 Jan 2006 20:49:55 GMT
+ETag: "17cd62-298-43bd8673"
+Accept-Ranges: bytes
+Content-Length: 664
+Connection: close
+Content-Type: text/plain; charset=utf-8
+
+"Latin Digraphs and Ligatures in ISO10646-1
+
+A short table of ligatures and digraphs follows. Some of these may not be
+ligatures/digraphs in the technical sense, (for example, ? is a seperate
+letter in English), but visually they behave that way.
+
+A?E : U+00C6
+a?e : U+00E6
+ſ?s : U+00DF
+IIJJ : U+0132"
+
+;; a vector of octets is returned for (non-text) binary data - a picture in this case
+DRAKMA-USER 8 > (http-request "http://zappa.com/favicon.ico")
+GET /favicon.ico HTTP/1.1
+Host: zappa.com
+User-Agent: Drakma/0.3.0 (LispWorks 5.0.0; Windows NT; Windows XP: 5.1 (build 2600) Service Pack 2; http://weitz.de/drakma/)
+Accept: */*
+Connection: close
+
+HTTP/1.1 200 OK
+Date: Sat, 26 Aug 2006 16:02:59 GMT
+Server: Apache/2.0.46 (Red Hat)
+Last-Modified: Fri, 17 Mar 2006 08:11:07 GMT
+ETag: "3a4080-b6-59d5bcc0"
+Accept-Ranges: bytes
+Content-Length: 182
+Connection: close
+Content-Type: image/gif
+
+#(71 73 70 56 57 97 17 0 17 0 179 1 0 150 151 153 255 255 255 37 37 36 112 114 115
+  201 202 204 0 0 0 80 83 84 26 28 26 230 231 231 249 249 249 12 13 14 219 221 222
+  18 21 22 239 240 241 52 52 54 64 66 66 33 249 4 1 0 0 1 0 44 0 0 0 0 17 0 17 0 0
+  4 99 48 200 73 107 109 54 172 101 129 120 196 180 12 12 51 80 64 161 42 3 48 28
+  170 106 72 141 16 223 120 113 166 121 95 0 14 95 239 33 236 41 98 10 129 114 185
+  188 29 127 25 201 224 73 60 4 8 0 130 22 59 64 52 96 135 148 35 96 80 152 159 186
+  192 64 183 112 0 200 61 65 0 1 192 76 214 185 113 102 241 88 26 90 8 81 18 8 94 
+  130 134 22 17 0 59)
+200
+((:DATE . "Sat, 26 Aug 2006 16:02:59 GMT")
+ (:SERVER . "Apache/2.0.46 (Red Hat)")
+ (:LAST-MODIFIED . "Fri, 17 Mar 2006 08:11:07 GMT")
+ (:ETAG . "\"3a4080-b6-59d5bcc0\"")
+ (:ACCEPT-RANGES . "bytes")
+ (:CONTENT-LENGTH . "182")
+ (:CONNECTION . "close")
+ (:CONTENT-TYPE . "image/gif"))
+#<URI http://zappa.com/favicon.ico>
+#<FLEXI-STREAMS:FLEXI-IO-STREAM 200D59BF>
+T
+
+;; a secure connection (see below) -
+;; also note that the server uses chunked transfer encoding for its reply
+DRAKMA-USER 9 > (ppcre:scan-to-strings "(?s)You have.*your data."
+                                       (http-request "https://www.fortify.net/cgi/ssl_2.pl"))
+GET /cgi/ssl_2.pl HTTP/1.1
+Host: www.fortify.net
+User-Agent: Drakma/0.3.0 (LispWorks 5.0.0; Windows NT; Windows XP: 5.1 (build 2600) Service Pack 2; http://weitz.de/drakma/)
+Accept: */*
+Connection: close
+
+HTTP/1.1 200 OK
+Date: Sat, 26 Aug 2006 16:10:06 GMT
+Server: Apache
+Connection: close
+Transfer-Encoding: chunked
+Content-Type: text/html
+
+
+"You have connected to this web server using the DHE-RSA-AES256-SHA encryption cipher
+ with a key length of 256 bits.
+ <p>
+ This is a high-grade encryption connection, regarded by most experts as being suitable
+ for sending or receiving even the most sensitive or valuable information
+ across a network.
+ <p>
+ In a crude analogy, using this cipher is similar to sending or storing your data inside
+ a high quality safe - compared to an export-grade cipher which is similar to using
+ a paper envelope to protect your data."
+#()
+
+;; using a different 'User-Agent' header
+DRAKMA-USER 10 > (ppcre:regex-replace-all
+                  "<.*?>"
+                  (ppcre:scan-to-strings "(?s)Your browser reports.*?</table>" 
+                                         (http-request "http://bcheck.scanit.be/bcheck/"
+                                                       :user-agent :explorer))
+                  "")
+GET /bcheck/ HTTP/1.1
+Host: bcheck.scanit.be
+User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)
+Accept: */*
+Connection: close
+
+HTTP/1.1 200 OK
+Date: Sat, 26 Aug 2006 16:21:50 GMT
+Server: Apache
+Connection: close
+Transfer-Encoding: chunked
+Content-Type: text/html
+
+
+"Your browser reports to be:
+
+Browser name: MSIE
+Version: 6.0
+Platform: Windows NT 5.1
+"
+
+;; sending parameters in a POST request and working with cookies -
+;; note how Drakma sends the cookie back in the second request
+DRAKMA-USER 11 > (let ((cookie-jar (make-instance 'cookie-jar)))
+                   (http-request "http://www.phpsecurepages.com/test/test.php"
+                                 :method :post
+                                 :parameters '(("entered_login" . "test")
+                                               ("entered_password" . "test"))
+                                 :cookie-jar cookie-jar)
+                   (http-request "http://www.phpsecurepages.com/test/test2.php"
+                                 :cookie-jar cookie-jar)
+                   (cookie-jar-cookies cookie-jar))
+POST /test/test.php HTTP/1.1
+Host: www.phpsecurepages.com
+User-Agent: Drakma/0.3.0 (LispWorks 5.0.0; Windows NT; Windows XP: 5.1 (build 2600) Service Pack 2; http://weitz.de/drakma/)
+Accept: */*
+Content-Length: 40
+Content-Type: application/x-www-form-urlencoded
+Connection: close
+
+HTTP/1.1 200 OK
+Date: Sat, 26 Aug 2006 18:26:17 GMT
+Server: Apache/2.0.51 (Fedora)
+X-Powered-By: PHP/4.3.10
+Expires: Thu, 19 Nov 1981 08:52:00 GMT
+Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
+Pragma: no-cache
+Set-Cookie: PHPSESSID=3ce33aa3e326ab4bf5da7feecc3248b4; path=/
+Connection: close
+Transfer-Encoding: chunked
+Content-Type: text/html
+
+
+GET /test/test2.php HTTP/1.1
+Host: www.phpsecurepages.com
+User-Agent: Drakma/0.3.0 (LispWorks 5.0.0; Windows NT; Windows XP: 5.1 (build 2600) Service Pack 2; http://weitz.de/drakma/)
+Accept: */*
+Cookie: PHPSESSID=3ce33aa3e326ab4bf5da7feecc3248b4
+Connection: close
+
+HTTP/1.1 200 OK
+Date: Sat, 26 Aug 2006 18:26:18 GMT
+Server: Apache/2.0.51 (Fedora)
+X-Powered-By: PHP/4.3.10
+Expires: Thu, 19 Nov 1981 08:52:00 GMT
+Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
+Pragma: no-cache
+Connection: close
+Transfer-Encoding: chunked
+Content-Type: text/html
+
+
+(#<COOKIE PHPSESSID=3ce33aa3e326ab4bf5da7feecc3248b4; path=/; domain=www.phpsecurepages.com>)
+
+;; now we are going to re-use a socket for the second connection to the same server
+;; this will also work with chunked encoding
+DRAKMA-USER 12 > (let ((stream (nth-value 4 (http-request "http://www.lispworks.com/" :close nil))))
+                   (nth-value 2 (http-request "http://www.lispworks.com/success-stories/index.html"
+                                              :stream stream)))
+GET / HTTP/1.1
+Host: www.lispworks.com
+User-Agent: Drakma/0.3.0 (LispWorks 5.0.0; Windows NT; Windows XP: 5.1 (build 2600) Service Pack 2; http://weitz.de/drakma/)
+Accept: */*
+
+HTTP/1.1 200 OK
+Date: Sat, 26 Aug 2006 18:34:20 GMT
+Server: Apache/1.3.37 Ben-SSL/1.57 (Unix)
+Last-Modified: Tue, 08 Aug 2006 18:20:49 GMT
+ETag: "28ee4f0-22db-44d8d601"
+Accept-Ranges: bytes
+Content-Length: 8923
+Content-Type: text/html
+
+GET /success-stories/index.html HTTP/1.1
+Host: www.lispworks.com
+User-Agent: Drakma/0.3.0 (LispWorks 5.0.0; Windows NT; Windows XP: 5.1 (build 2600) Service Pack 2; http://weitz.de/drakma/)
+Accept: */*
+Connection: close
+
+HTTP/1.1 200 OK
+Date: Sat, 26 Aug 2006 18:34:20 GMT
+Server: Apache/1.3.37 Ben-SSL/1.57 (Unix)
+Last-Modified: Tue, 08 Aug 2006 18:22:19 GMT
+ETag: "28f3f42-2325-44d8d65b"
+Accept-Ranges: bytes
+Content-Length: 8997
+Connection: close
+Content-Type: text/html
+
+((:DATE . "Sat, 26 Aug 2006 18:34:20 GMT")
+ (:SERVER . "Apache/1.3.37 Ben-SSL/1.57 (Unix)")
+ (:LAST-MODIFIED . "Tue, 08 Aug 2006 18:22:19 GMT")
+ (:ETAG . "\"28f3f42-2325-44d8d65b\"")
+ (:ACCEPT-RANGES . "bytes")
+ (:CONTENT-LENGTH . "8997")
+ (:CONNECTION . "close")
+ (:CONTENT-TYPE . "text/html"))
+
+;; testing basic authorization against a local Hunchentoot server
+DRAKMA-USER 13 > (nth-value 1 (http-request "http://localhost:4242/tbnl/test/authorization.html"))
+GET /tbnl/test/authorization.html HTTP/1.1
+Host: localhost:4242
+User-Agent: Drakma/0.3.0 (LispWorks 5.0.0; Windows NT; Windows XP: 5.1 (build 2600) Service Pack 2; http://weitz.de/drakma/)
+Accept: */*
+Connection: close
+
+HTTP/1.1 401 Authorization Required
+Content-Length: 563
+Content-Type: text/html; charset=iso-8859-1
+Date: Sat, 26 Aug 2006 18:38:58 GMT
+Server: Hunchentoot 0.1.5 (TBNL 0.10.0)
+Connection: Close
+WWW-Authenticate: Basic realm="TBNL"
+
+401
+
+DRAKMA-USER 14 > (nth-value 1 (http-request "http://localhost:4242/tbnl/test/authorization.html"
+                                            :basic-authorization '("nanook" "igloo")))
+GET /tbnl/test/authorization.html HTTP/1.1
+Host: localhost:4242
+User-Agent: Drakma/0.3.0 (LispWorks 5.0.0; Windows NT; Windows XP: 5.1 (build 2600) Service Pack 2; http://weitz.de/drakma/)
+Authorization: Basic bmFub29rOmlnbG9v
+Accept: */*
+Connection: close
+
+HTTP/1.1 200 OK
+Content-Length: 884
+Content-Type: text/html; charset=iso-8859-1
+Date: Sat, 26 Aug 2006 18:39:19 GMT
+Server: Hunchentoot 0.1.5 (TBNL 0.10.0)
+Connection: Close
+
+200
+
+;; now we ask Drakma to return a stream and read from it directly
+DRAKMA-USER 15 > (let ((stream (http-request "http://www.jalat.com/blogs/lisp?id=3" 
+                                             :want-stream t)))
+                   (loop for i below 41
+                         for line = (read-line stream)
+                         when (> i 35)
+                         do (write-line line))
+                   (close stream)
+                   (values))
+GET /blogs/lisp?id=3 HTTP/1.1
+Host: www.jalat.com
+User-Agent: Drakma/0.3.0 (LispWorks 5.0.0; Windows NT; Windows XP: 5.1 (build 2600) Service Pack 2; http://weitz.de/drakma/)
+Accept: */*
+Connection: close
+
+HTTP/1.1 200 OK
+Content-Length: 21453
+Content-Type: text/html; charset=iso-8859-1
+Date: Sat, 26 Aug 2006 19:53:37 GMT
+Server: Hunchentoot 0.1.3 (TBNL 0.9.7)
+Connection: Close
+
+Bill Clementson has <a
+href="http://bc.tech.coop/blog/041111.html">written</a> about getting
+TBNL up and running with apache and mod_lisp. In this example I'm
+going to use <a href="http://weitz.de/hunchentoot/">hunchentoot</a>, a
+pure lisp web server by (again) Edi Weitz.
+
+;; let's test a POST request without content length and with chunked transfer encoding -
+;; we build the content in several steps using different types of data
+;; (note: doesn't work anymore, probably due to server changes)
+DRAKMA-USER 16 > (let ((temp-file (ensure-directories-exist #p"/tmp/quux.txt"))
+                       (continuation (http-request "http://meme.b9.com/login.html"
+                                                   :method :post
+                                                   :content :continuation)))
+                   (funcall continuation "username=" t)
+                   (funcall continuation (list (char-code #\n) (char-code #\a)) t)
+                   (funcall continuation (lambda (stream)
+                                           (write-char #\n stream)) t)
+                   (with-open-file (out temp-file
+                                        :direction :output
+                                        :if-does-not-exist :create
+                                        :if-exists :supersede)
+                     (write-string "ook" out))
+                   (funcall continuation temp-file t)
+                   (ppcre:scan-to-strings "(?i)[a-z ]+nanook[a-z .]+"
+                                          (funcall continuation "&password=igloo")))
+POST /login.html HTTP/1.1
+Host: meme.b9.com
+User-Agent: Drakma/0.3.0 (LispWorks 5.0.0; Windows NT; Windows XP: 5.1 (build 2600) Service Pack 2; http://weitz.de/drakma/)
+Accept: */*
+Connection: close
+Content-Type: application/x-www-form-urlencoded
+Transfer-Encoding: chunked
+
+HTTP/1.0 200 OK
+Date: Sat, 02 Sep 2006 00:25:24 GMT
+Connection: close
+Server: AllegroServe/1.2.45
+Content-Type: text/html
+Content-Length: 2922
+PRAGMA: no-cache
+CACHE-CONTROL: no-cache
+SET-COOKIE: meme=1834b91d26f9be983a0ed9ca; path=/
+
+"The username nanook is not in our database."
+#()
+
+;; finally, we send additional headers to ask for a range
+DRAKMA-USER 17 > (ppcre:regex-replace-all
+                  "<.*?>"
+                  (format nil "~A~A"
+                          (http-request "http://users.cableaz.com/~lantz/pages/hunchentoot.html"
+                                        :additional-headers '(("Range" . "bytes=959-999")))
+                          (http-request "http://users.cableaz.com/~lantz/pages/hunchentoot.html"
+                                        :additional-headers '(("Range" . "bytes=1165-1201"))))
+                  "")
+GET /~lantz/pages/hunchentoot.html HTTP/1.1
+Host: users.cableaz.com
+User-Agent: Drakma/0.3.0 (LispWorks 5.0.0; Windows NT; Windows XP: 5.1 (build 2600) Service Pack 2; http://weitz.de/drakma/)
+Accept: */*
+Connection: close
+Range: bytes=959-999
+
+HTTP/1.1 206 Partial Content
+Date: Sat, 26 Aug 2006 19:07:44 GMT
+Server: Apache/2.0.16 (Unix)
+Last-Modified: Sun, 24 Apr 2005 04:08:45 GMT
+ETag: "35298d-2fea-d8f4cd40"
+Accept-Ranges: bytes
+Content-Length: 41
+Content-Range: bytes 959-999/12266
+Content-Type: text/html; charset=ISO-8859-1
+Connection: close
+
+GET /~lantz/pages/hunchentoot.html HTTP/1.1
+Host: users.cableaz.com
+User-Agent: Drakma/0.3.0 (LispWorks 5.0.0; Windows NT; Windows XP: 5.1 (build 2600) Service Pack 2; http://weitz.de/drakma/)
+Accept: */*
+Connection: close
+Range: bytes=1165-1201
+
+HTTP/1.1 206 Partial Content
+Date: Sat, 26 Aug 2006 19:07:45 GMT
+Server: Apache/2.0.16 (Unix)
+Last-Modified: Sun, 24 Apr 2005 04:08:45 GMT
+ETag: "35298d-2fea-d8f4cd40"
+Accept-Ranges: bytes
+Content-Length: 37
+Content-Range: bytes 1165-1201/12266
+Content-Type: text/html; charset=ISO-8859-1
+Connection: close
+
+"DRAKMA (Queen of Cosmic Greed)
+HUNCHENTOOT (The Giant Spider)"
+
+ +
 

Download and installation

+ +Drakma together with this documentation can be downloaded +from http://weitz.de/files/drakma.tar.gz. +The current version is 0.11.3. Drakma can be installed +via ASDF and depends on the +open source +libraries CL-BASE64 (use +3.3.2 or higher to avoid an unneeded dependency +on KMRCL), Puri, and Chunga. If +you're not using LispWorks, you'll also +need usocket (0.3.2 or newer) +and (except for AllegroCL) CL+SSL. +Try to use the newest versions of all these libraries - use the CVS +versions if in doubt. Installation +via asdf-install +should also be possible, and +there's a port for Gentoo +Linux thanks to Matthew Kennedy. +

+For SSL, you +will need to +have the +corresponding C libraries as well. You'll usually have them +already unless you're on Windows. +

+Luís Oliveira maintains a darcs +repository of Drakma +at http://common-lisp.net/~loliveira/ediware/. +

+A Mercurial +repository of older versions is available +at http://arcanes.fr.eu.org/~pierre/2007/02/weitz/ +thanks to Pierre Thierry. + +
 

Support and mailing lists

+ +For questions, bug reports, feature requests, improvements, or patches +please use the drakma-devel +mailing list. If you want to be notified about future releases +subscribe to the drakma-announce +mailing list. These mailing lists were made available thanks to +the services of common-lisp.net. +

+If you want to send patches, please read this first. + + +
 

The Drakma dictionary

+ +

The request

+ +The HTTP-REQUEST function is +the heart of Drakma. It is used to send requests to web servers and +will either return the message body of the server's reply or (if the +user so wishes) a stream one can read from. The wealth of keyword +parameters might look a bit intimidating first, but you will rarely +need more than two or three of them - the default behaviour of Drakma +is (hopefully) designed to do The Right Thing[TM] in most cases. +

+You can use +the *HEADER-STREAM* +variable to debug requests handled by Drakma in a way similar +to LiveHTTPHeaders. + + + +


[Function]
http-request uri &key protocol method force-ssl parameters form-data content content-length content-type cookie-jar basic-authorization user-agent accept proxy proxy-basic-authorization additional-headers redirect redirect-methods auto-referer keep-alive close external-format-out external-format-in force-binary want-stream stream connection-timeout read-timeout write-timeout
=> body-or-stream, status-code, headers, uri, stream, must-close, reason-phrase
+


+ +Sends an HTTP request to a web server and returns its reply. +uri is where the +request is sent to, and it is either a string denoting +a uniform +resource identifier or +a PURI:URI +object. The scheme of uri must be 'http' or +'https'. The function returns seven values - the body of the +reply (but see below), the status code as an integer, +an alist +of the headers sent by the server where for each element +the car +(the name of the header) is a keyword and +the cdr +(the value of the header) is a string, the URI the reply comes from +(which might be different from the URI the request was sent to in case +of redirects), the stream the reply was read +from, +a generalized +boolean which denotes whether the stream should be closed (and +which you can usually ignore), and finally the reason phrase from the +status line as a string. +

+protocol is the HTTP protocol which is going to be used in the +request line, it must be one of the keywords :HTTP/1.0 or +:HTTP/1.1 (the default). method is the method used in the +request line, +a keyword +(like :GET or :HEAD) denoting a +valid HTTP/1.1 +or WebDAV request method. +Additionally, you can also use the pseudo method :OPTIONS* which is like +:OPTIONS but means that an "OPTIONS *" +request line will be sent, i.e. the URI's path and query parts will be +ignored. +

+If force-ssl is true, +SSL +will be attached to the socket stream which connects Drakma with the +web server. Usually, you don't have to provide this argument, as SSL +will be attached anyway if the scheme of uri is 'https'. +

+parameters is +an alist +of name/value pairs +(the car +and +the cdr +each being a string) which denotes the parameters which are added to +the query part of the URI or (in the case of a POST request) comprise +the request body. (But +see content below.) The +name/value pairs +are URL-encoded +using the external format external-format-out +before they are sent to the server, unless form-data is true in which +case the POST request body is sent +as multipart/form-data +using +external-format-out. The values of +the parameters alist can also be pathnames, unary +functions, open binary input streams, or lists where the first element +is of one of the former types. These values denote files which should +be sent as part of the request body, i.e. if such file designators are +present in parameters, the content type of the +request is always multipart/form-data. If the +value denoting a file is a list, the part of the list behind the first +element is treated as +a plist +which can be used to optionally specify a content type (the default is +"application/octet-stream") and/or a filename (the default is the +result of +applying FILE-NAMESTRING +to the pathname) for the file. So, for example, a full file upload +request could look like this: +

+(http-request "http://www.whatever.com/file_upload/"
+              :method :post
+              ;; the following line is only needed if the receiving server doesn't accept
+              ;; chunked transfer encoding (like for example Apache 1.x)
+              :content-length t
+              :parameters '(("file1" #p"/tmp/top_secret_stuff.doc" :content-type "application/msword" :filename "upload.doc")
+                            ("file2" . #p"/tmp/portrait.jpg")
+                            ("lname" . "Duck") ("fname" . "Donald")))
+
+

+external-format-out (the default is the value of *DRAKMA-DEFAULT-EXTERNAL-FORMAT*) must be the name of a FLEXI-STREAMS external +format. +

content, if not NIL, is +used as the request body - parameters is ignored +in this case. content can be a string, a +sequence of octets, a pathname, an open binary input stream, or a +function +designator. If content is a sequence, it will +be directly sent to the server (using external-format-out in the case of strings). If content is a +pathname, the binary contents of the corresponding file will be sent +to the server. If content is a stream, everything +that can be read from the stream +until EOF +will be sent to the server. If content is a +function designator, the corresponding function will be called with +one argument, the stream to the server, to which it should send data. +

+Finally, content can also be the +keyword :CONTINUATION in which +case HTTP-REQUEST returns +only one value - a "continuation" function. This function has one +required argument and one optional argument. The first argument will +be interpreted like content above (but it cannot +be a keyword), i.e. it will be sent to the server according to its +type. If the second argument is true, the continuation function can +be called again to send more content, if it is NIL, the +continuation function returns +what HTTP-REQUEST would have +returned. See above for an +example on how to use a continuation function and different types of +content. +

+If content is a sequence, Drakma will +use LENGTH +to determine its length and will use the result for the +'Content-Length' header sent to the server. You can overwrite this +with the content-length parameter +(a non-negative integer) which you can also use for the cases where +Drakma can't or won't determine the content length itself. You can +also explicitly provide a content-length argument +of NIL which will imply that no 'Content-Length' header +will be sent even if Drakma could compute the value. If no +'Content-Length' header is sent, Drakma will +use chunked encoding to send the +content body. Note that this will not work with some older web +servers. +

+A non-NIL content-length argument +means that Drakma must build the request body in RAM and +compute the content length even if it would have otherwise used +chunked encoding - for example in the case of file uploads. A special +case is the value T +for content-length which means that Drakma should +compute the content length after building the request body. +

+content-type is the +corresponding 'Content-Type' header to be sent and will be ignored +unless content is provided as well. +

+Note that a +query already contained in uri will always be sent +with the request line anyway in addition to other parameters sent by +Drakma. +

+cookie-jar is a cookie +jar containing cookies which will potentially be sent to the +server (if the domain matches, if they haven't expired, etc.) - this +cookie jar will be modified according to the 'Set-Cookie' header(s) +sent back by the server. +

+basic-authorization, if not NIL, +should be a list of two strings (username and password) which will be +sent to the server for basic +authorization. user-agent, if +not NIL, denotes which 'User-Agent' header will be sent +with the request. It can be one of the keywords :DRAKMA +(the +default), :FIREFOX, :EXPLORER, :OPERA, +or +:SAFARI which denote the current version of Drakma or, in +the latter four cases, a fixed string corresponding to a more or less +recent (as of August 2006) version of the corresponding browser. Or +it can be a string which is used +directly. accept, if not NIL, is the +'Accept' header sent - the default is "*/*". +

+If proxy is not NIL, it should be a +string denoting +a proxy server +through which the request should be sent. Or it can be a list of two +values - a string denoting the proxy server and an integer denoting +the port to use (which will default to 80 otherwise). +proxy-basic-authorization is used like basic-authorization, but for +the proxy, and only if proxy is true. +

+additional-headers is a +name/value alist +(like parameters) of additional HTTP headers which +should be sent with the request. +

+If redirect is +not NIL, it must be a non-negative integer +or T. If redirect is true, Drakma +will follow redirects (return codes 301, 302, 303, or 307) +unless redirect is 0. +If redirect is an integer, it will be decreased +by 1 with each redirect. Drakma will only follow +redirects if method is a member of the list redirect-methods the +initial value of which is (:GET :HEAD). +Furthermore, if auto-referer is true when following redirects, +Drakma will populate the 'Referer' (sic!) header with the URI that +triggered the redirection, overwriting an existing 'Referer' +header (in additional-headers) if necessary. +

+If keep-alive is T, the server will +be asked to keep the connection alive, i.e. not to close it after the +reply has been sent. (Note that +this not necessary +if both the client and the server use HTTP 1.1.) +If close is T, the server is +explicitly asked to close the connection after the reply has been +sent. keep-alive and close +are obviously mutually +exclusive. The default for close is T, the default for keep-alive is NIL. +

+HTTP-REQUEST will always +close the stream to the server before it returns unless +want-stream is true or if the headers exchanged +between Drakma and the server determine that the connection will be +kept alive - for example if both client and server used the +HTTP 1.1 protocol and no +explicit "Connection: close" header was sent. In +these cases you will have to close the stream manually. +

+If the message body sent by the server has a +text content +type, Drakma will try to return it as a Lisp string. +It'll first check if the 'Content-Type' header denotes an encoding +(charset) to be used, or otherwise it will use the external-format-in +(the default is the value +of *DRAKMA-DEFAULT-EXTERNAL-FORMAT*) +argument. The body is decoded +using FLEXI-STREAMS. If +FLEXI-STREAMS doesn't know the external format, the body is returned +as an array of octets. If the message body doesn't have a text +content type or if +force-binary +is true, the body is always returned as an array of octets. (But +see *TEXT-CONTENT-TYPES* +and *BODY-FORMAT-FUNCTION*.) +

+If want-stream is true, the +message body is not read and instead the (open) socket stream +is returned as the first return value. If the sixth return value +(must-close) +of HTTP-REQUEST is true, +Drakma deduced from the reply headers that the server will close the +stream on its side, so you can't re-use it - you'll have to close it +instead. Of course, no matter what the sixth return value is, it's +alway your responsibility to close the stream once you're done with +it. The +stream returned is a flexi +stream with a chunked stream +as its underlying stream. +

+Drakma will usually +create a +new socket connection for each HTTP request. However, you can use +the stream argument to provide an open socket stream which should be +re-used instead. stream must be a stream returned by a previous invocation of +HTTP-REQUEST where the sixth return value wasn't true. Obviously, it +must also be connected to the correct server and at the right position +(i.e. the message body, if any, must have been read). Drakma will +never attach SSL to a stream provided as the stream argument. +

+connection-timeout is the time (in seconds) Drakma +will wait until it considers an attempt to connect to a server as a +failure. read-timeout +and write-timeout are the read and write timeouts +(in seconds) for the socket stream to the server. All three timeout +arguments can also be NIL (meaning no timeout), and they +don't apply if an existing stream is re-used. All timeout keyword +arguments are only available for +LispWorks, write-timeout is only available for +LispWorks 5.0 or higher. + +

+ + + + + + + +


[Special variable]
*drakma-default-external-format* +


+ +The default value for the two external format keyword arguments of +HTTP-REQUEST. The value of +this variable will be interpreted +by FLEXI-STREAMS. The +initial value is the keyword :LATIN-1. (Note that Drakma +binds *DEFAULT-EOL-STYLE* +to :LF.) + +
+ + + + + + +


[Special variable]
*text-content-types* +


+ +A list of conses which are used by the default value of *BODY-FORMAT-FUNCTION* to decide +whether a 'Content-Type' header denotes text content. The car and cdr +of each cons should each be a string or NIL. A content type matches +one of these entries (and thus denotes text) if the type part is +STRING-EQUAL +to the car or if the car is NIL and if the subtype part +is STRING-EQUAL +to the cdr or if the cdr is NIL. +

+The initial value of this variable is the list +

+(("text" . nil))
+
+which means that every content type that starts with "text/" is +regarded as text, no matter what the subtype is. + +
+ + + + + +


[Special variable]
*body-format-function* +


+ +A function which determines whether the content body returned by the +server is text and should be treated as such or not. The function is +called after the request headers have been read +and it must accept two arguments, headers +and external-format-in, where headers is like the +third return value of HTTP-REQUEST while external-format-in is the +HTTP-REQUEST argument of the +same name. It should return NIL if the body should be +regarded as binary content, or +a FLEXI-STREAMS external +format (which will be used to read the body) otherwise. +

+This function will only be called if +the force-binary +argument to HTTP-REQUEST is NIL. +

+The initial value of this variable is a function which uses +*TEXT-CONTENT-TYPES* +to determine whether the body is text and then proceeds as described +in the HTTP-REQUEST +documentation entry. + +

+ + + + + +


[Special variable]
*header-stream* +


+ +If this variable is not NIL, it should be bound to a +stream to which incoming and outgoing headers will be written for +debugging purposes. + +
+ + + +

Cookies

+ +HTTP-REQUEST can deal +with cookies if +it gets a cookie jar, a collection +of COOKIE objects, as +its cookie-jar argument. Cookies sent by the web +server will be added to the cookie jar (or updated) if appropriate and +cookies already in the cookie jar will be sent to the server together +with the request. +

+Drakma will never remove cookies from a cookie jar +automatically - you have to do it manually +using DELETE-OLD-COOKIES. + + + +


[Standard class]
cookie +


+ +Elements of this class +represent HTTP +cookies. If you need to create your own cookies, you should +use MAKE-INSTANCE +with the +initargs :NAME, :DOMAIN, :VALUE, :PATH, :EXPIRES, +:SECUREP, and :HTTP-ONLY-P all of which are +optional except for the first two. The meaning of these initargs +and the corresponding accessors should be +pretty clear if one looks at +the original +cookie specification (and +at this +page for the HttpOnly extension). + +
+DRAKMA-USER 18 > (make-instance 'cookie :name "Foo" 
+                                        :value "Bar"
+                                        :expires (+ (get-universal-time) 3600)
+                                        :domain ".weitz.de")
+#<COOKIE Foo=Bar; expires=Sat, 26-08-2006 23:14:27 GMT; path=/; domain=.weitz.de>
+
+ +
+ + + + +


[Specialized accessors]
cookie-name (cookie cookie) => name +
(setf (cookie-name (cookie cookie)) name) +
cookie-value (cookie cookie) => value +
(setf (cookie-value (cookie cookie)) value) +
cookie-domain (cookie cookie) => domain +
(setf (cookie-domain (cookie cookie)) domain) +
cookie-path (cookie cookie) => path +
(setf (cookie-path (cookie cookie)) path) +
cookie-expires (cookie cookie) => expiry +
(setf (cookie-expires (cookie cookie)) expiry) +
cookie-securep (cookie cookie) => securep +
(setf (cookie-securep (cookie cookie)) securep) +
cookie-http-only-p (cookie cookie) => http-only-p +
(setf (cookie-http-only-p (cookie cookie)) http-only-p) +


+ +These +are accessors +to get and set the corresponding slots of +a COOKIE object. Note that expiry is a universal time +and securep and http-only-p are generalized +booleans. All other values are strings. + +
+ + + +


[Standard class]
cookie-jar +


+ +An object of this class encapsulates a collection (a list, actually) +of COOKIE objects. You create a +new cookie jar with +(MAKE-INSTANCE 'COOKIE-JAR) +where you can optionally provide a list +of COOKIE objects with +the :COOKIES initarg. The cookies in a cookie jar are +accessed +with COOKIE-JAR-COOKIES. + +
+ + + + + + +


[Specialized accessor]
cookie-jar-cookies (cookie-jar cookie-jar) => list +
(setf (cookie-jar-cookies (cookie-jar cookie-jar)) list) +


+ +This accessor +is used to get and set the cookies comprised in a cookie +jar. list is a list +of COOKIE objects. +

+Note that list should not contain two cookies which are equal according to COOKIE=. + +

+ + + + + + +


[Function]
cookie= cookie1 cookie2 => result +


+ +Returns true +if the cookies cookie1 +and cookie2 are equal. Two cookies are considered +to be equal if their names and paths are equal. + +
+ + + + + + +


[Function]
delete-old-cookies cookie-jar => cookie-jar +


+ +Removes all cookies from the cookie +jar cookie-jar which have either expired or +which don't have an expiry date. + +
+ + + + + + +


[Special variable]
*ignore-unparseable-cookie-dates-p* +


+ +Whether Drakma is allowed to treat Expires dates in +cookie headers as non-existent if it can't parse them. If the value +of this variable is NIL (which is the default), an error +will be signalled instead. +

+Note that Drakma tries hard to parse every date representation its +author has so far seen in the wild. As everybody and their sister +seems to invent their own format, this feels like an uphill battle, +though. Nevertheless, if you're confronted with something Drakma +can't parse, report it to the mailing list and set +this variable to a true value only as a temporary workaround. + +

+ + + +

Headers

+ +This section assembles a couple of convenience functions which can be +used to access information returned as the third +value (headers) +of HTTP-REQUEST. +

+Note that if the header +sends multiple headers +with the same name, these are comprised into one entry by +HTTP-REQUEST where the values +are separated by commas. + + + +


[Function]
header-value name headers => value +


+ +If headers is an alist of headers as returned by HTTP-REQUEST +and name is a keyword naming a header, this function returns the +corresponding value of this header (or NIL if it's not in +headers). +
+DRAKMA-USER 19 > (setq *header-stream* nil)
+NIL
+DRAKMA-USER 20 > (header-value :server
+                               (nth-value 2 (http-request "http://www.jalat.com/blogs/lisp?id=5")))
+"Hunchentoot 0.1.3 (TBNL 0.9.7)"
+
+ +
+ + + + + +


[Function]
split-tokens string => string-list +


+ +Splits the string string into a list of substrings separated +by commas and optional whitespace. Empty substrings are +ignored. +
+DRAKMA-USER 21 > (split-tokens "chunked, identity")
+("chunked" "identity")
+
+ +
+ + + + + + +


[Function]
read-tokens-and-parameters string &key value-required-p => list +


+ +Reads a comma-separated list +of tokens from the +string string. Each token can be followed by an +optional, semicolon-separated list +of attribute/value +pairs where the attributes are tokens followed by +a #\= character and a token or +a quoted string. +Returned is a list where each element is either a string (for a simple +token) or +a cons +of a string (the token) and +an alist +(the attribute/value pairs). If value-required-p +is NIL (the default is T), the value part +(including the #\= character) of each attribute/value +pair is optional. +

+An example of an HTTP header which uses a syntax which can be parsed +with this function is the 'Transfer-Encoding' header. +

+DRAKMA-USER 21 > (read-tokens-and-parameters "iso-8859-5, unicode-1-1;q=0.8")
+("iso-8859-5" ("unicode-1-1" ("q" . "0.8")))
+
+ +
+ + + + + +


[Function]
parameter-present-p name parameters => generalized-boolean +


+ +If parameters is +an alist +of parameters (i.e. of attribute/value pairs) as returned by, for +example, READ-TOKENS-AND-PARAMETERS and name is a string naming a +parameter, this function returns the full parameter (name and value) - +or NIL if it's not in parameters. +
+DRAKMA-USER 23 > (parameter-present-p "frob" '(("charset" . "latin-1") ("frob" . "quux")))
+("frob" . "quux")
+
+DRAKMA-USER 24 > (parameter-present-p "foo" '(("charset" . "latin-1") ("frob" . "quux")))
+NIL
+
+
+ + + + + + +


[Function]
parameter-value name parameters => value +


+ +If parameters is an alist of parameters (i.e. of attribute/value pairs) as returned by, for +example, READ-TOKENS-AND-PARAMETERS and name is a string naming a +parameter, this function returns the value of this parameter - or +NIL if it's not in parameters. +
+DRAKMA-USER 25 > (parameter-value "frob" '(("charset" . "latin-1") ("frob" . "quux")))
+"quux"
+
+DRAKMA-USER 26 > (parameter-value "foo" '(("charset" . "latin-1") ("frob" . "quux")))
+NIL
+
+
+ + + + + +


[Function]
get-content-type headers => type, subtype, parameters +


+ +Reads and parses a 'Content-Type' header and returns it as +three values - the type, the subtype, and an alist (possibly +empty) of name/value pairs for the optional parameters. headers +is supposed to be an alist of HTTP headers as returned by +HTTP-REQUEST. Returns NIL if there is no 'Content-Type' header amongst +headers. +
+DRAKMA-USER 27 > (get-content-type 
+                  (nth-value 2 (http-request "http://weitz.de/")))
+"text"
+"html"
+(("charset" . "iso-8859-1"))
+
+
+ + + +
 

Potential problems

+ +Some web servers (notably Paul Graham's +Arc web +server +and some +very old ones) use wrong line endings when sending the HTTP +headers. By default, Drakma won't be able to understand them, but +see Chunga's *ACCEPT-BOGUS-EOLS*. + + +
 

Acknowledgements

+ +Initial versions of Drakma used code +from ACL-COMPAT, +specifically the chunking code from Jochen Schmidt. (This has been replaced by Chunga.) +The API of +Drakma's HTTP-REQUEST was +inspired by John +Foderaro's DO-HTTP-REQUEST. +And greetings to Bob Hutchinson who +already anticipated this +library in 2005... :) + +

+This documentation was prepared with DOCUMENTATION-TEMPLATE. +

+

+$Header: /usr/local/cvsrep/drakma/doc/index.html,v 1.83 2008/01/14 18:51:40 edi Exp $ +

BACK TO MY HOMEPAGE + + + Added: branches/trunk-reorg/thirdparty/drakma-0.11.3/drakma.asd ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/drakma-0.11.3/drakma.asd Wed Feb 13 14:41:09 2008 @@ -0,0 +1,60 @@ +;;; -*- Mode: LISP; Syntax: COMMON-LISP; Package: CL-USER; Base: 10 -*- +;;; $Header: /usr/local/cvsrep/drakma/drakma.asd,v 1.46 2008/01/14 18:51:38 edi Exp $ + +;;; Copyright (c) 2006-2008, Dr. Edmund Weitz. All rights reserved. + +;;; Redistribution and use in source and binary forms, with or without +;;; modification, are permitted provided that the following conditions +;;; are met: + +;;; * Redistributions of source code must retain the above copyright +;;; notice, this list of conditions and the following disclaimer. + +;;; * Redistributions in binary form must reproduce the above +;;; copyright notice, this list of conditions and the following +;;; disclaimer in the documentation and/or other materials +;;; provided with the distribution. + +;;; THIS SOFTWARE IS PROVIDED BY THE AUTHOR 'AS IS' AND ANY EXPRESSED +;;; OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +;;; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +;;; ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +;;; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +;;; DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +;;; GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +;;; INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +;;; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +;;; NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +;;; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +(in-package :cl-user) + +#+:lispworks +(unless (find-symbol "STREAM-WRITE-TIMEOUT" :stream) + (pushnew :lw-does-not-have-write-timeout *features*)) + +(defpackage :drakma-asd + (:use :cl :asdf)) + +(in-package :drakma-asd) + +(defvar *drakma-version-string* "0.11.3" + "Drakma's version number as a string.") + +;; we export its name so we can import it later +(export '*drakma-version-string*) + +(defsystem :drakma + :serial t + :version #.*drakma-version-string* + :components ((:file "packages") + (:file "specials") + (:file "util") + (:file "read") + (:file "cookies") + (:file "request")) + :depends-on (:puri + :cl-base64 + :chunga + #-:lispworks :usocket + #-(or :lispworks :allegro) :cl+ssl)) Added: branches/trunk-reorg/thirdparty/drakma-0.11.3/packages.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/drakma-0.11.3/packages.lisp Wed Feb 13 14:41:09 2008 @@ -0,0 +1,59 @@ +;;; -*- Mode: LISP; Syntax: COMMON-LISP; Package: CL-USER; Base: 10 -*- +;;; $Header: /usr/local/cvsrep/drakma/packages.lisp,v 1.22 2008/01/14 01:57:01 edi Exp $ + +;;; Copyright (c) 2006-2008, Dr. Edmund Weitz. All rights reserved. + +;;; Redistribution and use in source and binary forms, with or without +;;; modification, are permitted provided that the following conditions +;;; are met: + +;;; * Redistributions of source code must retain the above copyright +;;; notice, this list of conditions and the following disclaimer. + +;;; * Redistributions in binary form must reproduce the above +;;; copyright notice, this list of conditions and the following +;;; disclaimer in the documentation and/or other materials +;;; provided with the distribution. + +;;; THIS SOFTWARE IS PROVIDED BY THE AUTHOR 'AS IS' AND ANY EXPRESSED +;;; OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +;;; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +;;; ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +;;; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +;;; DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +;;; GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +;;; INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +;;; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +;;; NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +;;; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +(in-package :cl-user) + +(defpackage :drakma + (:use :cl :puri :flexi-streams :chunga) + ;; the variable defined in the ASDF system definition + (:import-from :drakma-asd :*drakma-version-string*) + (:export :*body-format-function* + :*drakma-default-external-format* + :*header-stream* + :*ignore-unparseable-cookie-dates-p* + :*text-content-types* + :cookie + :cookie-domain + :cookie-expires + :cookie-http-only-p + :cookie-jar + :cookie-jar-cookies + :cookie-name + :cookie-path + :cookie-securep + :cookie-value + :cookie= + :delete-old-cookies + :get-content-type + :header-value + :http-request + :parameter-present-p + :parameter-value + :read-tokens-and-parameters + :split-tokens)) Added: branches/trunk-reorg/thirdparty/drakma-0.11.3/read.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/drakma-0.11.3/read.lisp Wed Feb 13 14:41:09 2008 @@ -0,0 +1,127 @@ +;;; -*- Mode: LISP; Syntax: COMMON-LISP; Package: DRAKMA; Base: 10 -*- +;;; $Header: /usr/local/cvsrep/drakma/read.lisp,v 1.15 2008/01/14 01:57:01 edi Exp $ + +;;; Copyright (c) 2006-2008, Dr. Edmund Weitz. All rights reserved. + +;;; Redistribution and use in source and binary forms, with or without +;;; modification, are permitted provided that the following conditions +;;; are met: + +;;; * Redistributions of source code must retain the above copyright +;;; notice, this list of conditions and the following disclaimer. + +;;; * Redistributions in binary form must reproduce the above +;;; copyright notice, this list of conditions and the following +;;; disclaimer in the documentation and/or other materials +;;; provided with the distribution. + +;;; THIS SOFTWARE IS PROVIDED BY THE AUTHOR 'AS IS' AND ANY EXPRESSED +;;; OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +;;; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +;;; ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +;;; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +;;; DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +;;; GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +;;; INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +;;; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +;;; NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +;;; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +(in-package :drakma) + +(defmacro ignore-eof (&body body) + "This macro is similar to IGNORE-ERRORS but it only ignores +conditions of type END-OF-FILE." + `(handler-case + (progn , at body) + (end-of-file () nil))) + +(defun read-status-line (stream &optional log-stream) + "Reads one line from STREAM \(using Chunga's READ-LINE*) and +interprets it as a HTTP status line. Returns a list of two or +three values - the protocol \(HTTP version) as a keyword, the +status code as an integer, and optionally the reason phrase." + (let* ((*current-error-message* "While reading status line:") + (line (read-line* stream log-stream)) + (first-space-pos (or (position #\Space line :test #'char=) + (error "No space in status line ~S." line))) + (second-space-pos (position #\Space line + :test #'char= + :start (1+ first-space-pos)))) + (list (cond ((string-equal line "HTTP/1.0" :end1 first-space-pos) :http/1.0) + ((string-equal line "HTTP/1.1" :end1 first-space-pos) :http/1.1) + (t (error "Unknown protocol in ~S." line))) + (or (ignore-errors (parse-integer line + :start (1+ first-space-pos) + :end second-space-pos)) + (error "Status code in ~S is not an integer." line)) + (and second-space-pos (subseq line (1+ second-space-pos)))))) + +(defun get-content-type (headers) + "Reads and parses a `Content-Type' header and returns it as +three values - the type, the subtype, and an alist \(possibly +empty) of name/value pairs for the optional parameters. HEADERS +is supposed to be an alist of headers as returned by +HTTP-REQUEST. Returns NIL if there is no such header amongst +HEADERS." + (when-let (content-type (header-value :content-type headers)) + (with-input-from-string (stream content-type) + (let* ((*current-error-message* "Corrupted Content-Type header:") + (type (read-token stream)) + (subtype (and (assert-char stream #\/) + (read-token stream))) + (parameters (read-name-value-pairs stream))) + (values type subtype parameters))))) + +(defun read-token-and-parameters (stream) + "Reads and returns \(as a two-element list) from STREAM a token +and an optional list of parameters \(attribute/value pairs) +following the token." + (skip-whitespace stream) + (list (read-token stream) + (read-name-value-pairs stream))) + +(defun skip-more-commas (stream) + "Reads and consumes from STREAM any number of commas and +whitespace. Returns the following character or NIL in case of +END-OF-FILE." + (loop while (eql (ignore-eof (peek-char nil stream)) #\,) + do (read-char stream) (skip-whitespace stream)) + (skip-whitespace stream)) + +(defun read-tokens-and-parameters (string &key (value-required-p t)) + "Reads a comma-separated list of tokens from the string STRING. +Each token can be followed by an optional, semicolon-separated +list of attribute/value pairs where the attributes are tokens +followed by a #\\= character and a token or a quoted string. +Returned is a list where each element is either a string \(for a +simple token) or a cons of a string \(the token) and an alist +\(the attribute/value pairs). If VALUE-REQUIRED-P is NIL, the +value part \(including the #\\= character) of each attribute/value +pair is optional." + (with-input-from-string (stream string) + (loop with *current-error-message* = (format nil "While parsing ~S:" string) + for first = t then nil + for next = (and (skip-whitespace stream) + (or first (assert-char stream #\,)) + (skip-whitespace stream) + (skip-more-commas stream)) + for token = (and next (read-token stream)) + for parameters = (and token + (read-name-value-pairs stream + :value-required-p value-required-p)) + while token + collect (if parameters (cons token parameters) token)))) + +(defun split-tokens (string) + "Splits the string STRING into a list of substrings separated +by commas and optional whitespace. Empty substrings are +ignored." + (loop for old-position = -1 then position + for position = (and old-position + (position #\, string :test #'char= :start (1+ old-position))) + for substring = (and old-position + (trim-whitespace (subseq string (1+ old-position) position))) + while old-position + when (plusp (length substring)) + collect substring)) Added: branches/trunk-reorg/thirdparty/drakma-0.11.3/request.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/drakma-0.11.3/request.lisp Wed Feb 13 14:41:09 2008 @@ -0,0 +1,666 @@ +;;; -*- Mode: LISP; Syntax: COMMON-LISP; Package: DRAKMA; Base: 10 -*- +;;; $Header: /usr/local/cvsrep/drakma/request.lisp,v 1.54 2008/01/14 18:51:38 edi Exp $ + +;;; Copyright (c) 2006-2008, Dr. Edmund Weitz. All rights reserved. + +;;; Redistribution and use in source and binary forms, with or without +;;; modification, are permitted provided that the following conditions +;;; are met: + +;;; * Redistributions of source code must retain the above copyright +;;; notice, this list of conditions and the following disclaimer. + +;;; * Redistributions in binary form must reproduce the above +;;; copyright notice, this list of conditions and the following +;;; disclaimer in the documentation and/or other materials +;;; provided with the distribution. + +;;; THIS SOFTWARE IS PROVIDED BY THE AUTHOR 'AS IS' AND ANY EXPRESSED +;;; OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +;;; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +;;; ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +;;; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +;;; DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +;;; GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +;;; INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +;;; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +;;; NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +;;; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +(in-package :drakma) + +(defun determine-body-format (headers external-format-in) + "The default function used by Drakma to determine how the content +body is to be read. See the docstring of *BODY-FORMAT-FUNCTION* for +more info." + (handler-case + (let ((transfer-encodings (header-value :transfer-encoding headers)) + (content-encodings (header-value :content-encoding headers))) + (when transfer-encodings + (setq transfer-encodings (split-tokens transfer-encodings))) + (when content-encodings + (setq content-encodings (split-tokens content-encodings))) + (multiple-value-bind (type subtype params) + (get-content-type headers) + (when (and (text-content-type-p type subtype) + (null (set-difference transfer-encodings + '("chunked" "identity") + :test #'equalp)) + (null (set-difference content-encodings + '("identity") + :test #'equalp))) + (let* ((charset (parameter-value "charset" params)) + (name (cond (charset (as-keyword charset)) + (t external-format-in)))) + (make-external-format name :eol-style :lf))))) + (error (condition) + (warn "Problems determining charset \(falling back to binary):~%~A" + condition)))) + +(defun send-content (content stream &optional external-format-out) + "Sends CONTENT to the stream STREAM as part of the request body +depending on the type of CONTENT." + (when content + (cond ((stringp content) + (setf (flexi-stream-external-format stream) external-format-out) + (write-string content stream) + (setf (flexi-stream-external-format stream) +latin-1+)) + ((or (arrayp content) (listp content)) + (write-sequence content stream)) + ((and (streamp content) + (input-stream-p content) + (open-stream-p content) + (subtypep (stream-element-type content) 'octet)) + (let ((buf (make-array +buffer-size+ :element-type 'octet))) + (loop + (let ((pos (read-sequence buf content))) + (when (zerop pos) (return)) + (write-sequence buf stream :end pos))))) + ((pathnamep content) + (with-open-file (from content :element-type 'octet) + ;; calls itself with a stream now + (send-content from stream))) + ((or (functionp content) + (and (symbolp content) + (fboundp content))) + (funcall content stream)) + (t (error "Don't know how to send content ~S to server." content))))) + +(defun make-form-data-function (parameters boundary) + "Creates and returns a closure which can be used as an argument for +SEND-CONTENT to send PARAMETERS as a `multipart/form-data' request +body using the boundary BOUNDARY." + (lambda (stream) + (flet ((crlf () + "Sends carriage return and linefeed to STREAM." + (write-char #\Return stream) + (write-char #\Linefeed stream))) + (dolist (name/value parameters) + (destructuring-bind (name . value) + name/value + (when (or (pathnamep value) + (streamp value) + (functionp value)) + (setq value (list value))) + (format stream "--~A" boundary) + (crlf) + (format stream "Content-Disposition: form-data; name=\"~A\"" name) + (cond ((stringp value) + (crlf) (crlf) + (format stream "~A" value)) + ((listp value) + (let* ((file-source (first value)) + (filename (or (if (functionp file-source) "user-closure") + (if (streamp file-source) "user-stream") + (getf (rest value) :filename) + (file-namestring file-source))) + (content-type (or (getf (rest value) :content-type) + "application/octet-stream"))) + (format stream "; filename=\"~A\"" filename) + (crlf) + (format stream "Content-Type: ~A" content-type) + (crlf) (crlf) + ;; use SEND-CONTENT to send file as binary data + (send-content file-source stream))) + (t (error "Don't know what to do with ~S in multipart/form-data body." value))) + (crlf))) + (format stream "--~A--" boundary) + (crlf)))) + +(defun read-body (stream headers must-close textp) + "Reads the message body from the HTTP stream STREAM using the +information contained in HEADERS \(as produced by HTTP-REQUEST). If +TEXTP is true, the body is assumed to be of content type `text' and +will be returned as a string. Otherwise an array of octets \(or NIL +for an empty body) is returned. Returns the optional `trailer' HTTP +headers of the chunked stream \(if any) as a second value." + (let ((content-length (ignore-errors + (parse-integer (header-value :content-length headers)))) + (element-type (if textp + #+:lispworks 'lw:simple-char #-:lispworks 'character + 'octet)) + (chunkedp (chunked-stream-input-chunking-p (flexi-stream-stream stream)))) + (multiple-value-prog1 + (values (cond ((eql content-length 0) nil) + (content-length + (when chunkedp + ;; see RFC 2616, section 4.4 + (error "Got Content-Length header although input chunking is on.")) + (let ((result (make-array content-length + :element-type element-type + :fill-pointer t))) + (setf (fill-pointer result) + (read-sequence result stream)) + result)) + ((or chunkedp must-close) + ;; no content length, read until EOF (or end of chunking) + (let ((buffer (make-array +buffer-size+ + :element-type element-type)) + (result (make-array 0 + :element-type element-type + :adjustable t))) + (loop for index = 0 then (+ index pos) + for pos = (read-sequence buffer stream) + do (adjust-array result (+ index pos)) + (replace result buffer :start1 index :end2 pos) + while (= pos +buffer-size+)) + result))) + (chunked-input-stream-trailers stream))))) + +(defun http-request (uri &rest args + &key (protocol :http/1.1) + (method :get) + force-ssl + parameters + content + (content-type "application/x-www-form-urlencoded") + (content-length nil content-length-provided-p) + form-data + cookie-jar + basic-authorization + (user-agent :drakma) + (accept "*/*") + proxy + proxy-basic-authorization + additional-headers + (redirect 5) + (redirect-methods '(:get :head)) + auto-referer + keep-alive + (close t) + (external-format-out *drakma-default-external-format*) + (external-format-in *drakma-default-external-format*) + force-binary + want-stream + stream + #+:lispworks (connection-timeout 20) + #+:lispworks (read-timeout 20) + #+(and :lispworks (not :lw-does-not-have-write-timeout)) + (write-timeout 20 write-timeout-provided-p)) + "Sends an HTTP request to a web server and returns its reply. URI +is where the request is sent to, and it is either a string denoting a +uniform resource identifier or a PURI:URI object. The scheme of URI +must be `http' or `https'. The function returns SEVEN values - the +body of the reply \(but see below), the status code as an integer, an +alist of the headers sent by the server where for each element the car +\(the name of the header) is a keyword and the cdr \(the value of the +header) is a string, the URI the reply comes from \(which might be +different from the URI the request was sent to in case of redirects), +the stream the reply was read from, a generalized boolean which +denotes whether the stream should be closed \(and which you can +usually ignore), and finally the reason phrase from the status line as +a string. + +PROTOCOL is the HTTP protocol which is going to be used in the +request line, it must be one of the keywords :HTTP/1.0 or +:HTTP/1.1. METHOD is the method used in the request line, a +keyword \(like :GET or :HEAD) denoting a valid HTTP/1.1 or WebDAV +request method. Additionally, you can also use the pseudo +method :OPTIONS* which is like :OPTIONS but means that an +\"OPTIONS *\" request line will be sent, i.e. the URI's path and +query parts will be ignored. + +If FORCE-SSL is true, SSL will be attached to the socket stream +which connects Drakma with the web server. Usually, you don't +have to provide this argument, as SSL will be attached anyway if +the scheme of URI is `https'. + +PARAMETERS is an alist of name/value pairs \(the car and the cdr each +being a string) which denotes the parameters which are added to the +query part of the URL or \(in the case of a POST request) comprise the +body of the request. (But see CONTENT below.) The name/value pairs +are URL-encoded using the FLEXI-STREAMS external format +EXTERNAL-FORMAT-OUT before they are sent to the server unless +FORM-DATA is true in which case the POST request body is sent as +`multipart/form-data' using EXTERNAL-FORMAT-OUT. The values of the +PARAMETERS alist can also be pathnames, open binary input streams, +unary functions, or lists where the first element is of one of the +former types. These values denote files which should be sent as part +of the request body, i.e. if files are present in PARAMETERS, the +content type of the request is always `multipart/form-data'. If the +value is a list, the part of the list behind the first element is +treated as a plist which can be used to specify a content type and/or +a filename for the file, i.e. such a value could look like, e.g., +\(#p\"/tmp/my_file.doc\" :content-type \"application/msword\" +:filename \"upload.doc\"). + +CONTENT, if not NIL, is used as the request body - PARAMETERS is +ignored in this case. CONTENT can be a string, a sequence of +octets, a pathname, an open binary input stream, or a function +designator. If CONTENT is a sequence, it will be directly sent +to the server \(using EXTERNAL-FORMAT-OUT in the case of +strings). If CONTENT is a pathname, the binary contents of the +corresponding file will be sent to the server. If CONTENT is a +stream, everything that can be read from the stream until EOF +will be sent to the server. If CONTENT is a function designator, +the corresponding function will be called with one argument, the +stream to the server, to which it should send data. + +Finally, CONTENT can also be the keyword :CONTINUATION in which case +HTTP-REQUEST returns only one value - a `continuation' function. This +function has one required argument and one optional argument. The +first argument will be interpreted like CONTENT above \(but it cannot +be a keyword), i.e. it will be sent to the server according to its +type. If the second argument is true, the continuation function can +be called again to send more content, if it is NIL the continuation +function returns what HTTP-REQUEST would have returned. + +If CONTENT is a sequence, Drakma will use LENGTH to determine its +length and will use the result for the `Content-Length' header sent to +the server. You can overwrite this with the CONTENT-LENGTH parameter +\(a non-negative integer) which you can also use for the cases where +Drakma can't or won't determine the content length itself. You can +also explicitly provide a CONTENT-LENGTH argument of NIL which will +imply that no `Content-Length' header will be sent in any case. If no +`Content-Length' header is sent, Drakma will use chunked encoding to +send the content body. Note that this will not work with older web +servers. + +A non-NIL CONTENT-LENGTH argument means that Drakma /must/ build the +request body in RAM and compute the content length even if it would +have otherwise used chunked encoding, for example in the case of file +uploads. A special case is the value T for CONTENT-LENGTH which means +that Drakma should compute the content length after building the +request body. + +CONTENT-TYPE is the corresponding `Content-Type' header to be sent and +will be ignored unless CONTENT is provided as well. + +Note that a query already contained in URI will always be sent with +the request line anyway in addition to other parameters sent by +Drakma. + +COOKIE-JAR is a cookie jar containing cookies which will +potentially be sent to the server \(if the domain matches, if +they haven't expired, etc.) - this cookie jar will be modified +according to the `Set-Cookie' header\(s) sent back by the server. + +BASIC-AUTHORIZATION, if not NIL, should be a list of two strings +\(username and password) which will be sent to the server for +basic authorization. USER-AGENT, if not NIL, denotes which +`User-Agent' header will be sent with the request. It can be one +of the keywords :DRAKMA, :FIREFOX, :EXPLORER, :OPERA, or :SAFARI +which denote the current version of Drakma or, in the latter four +cases, a fixed string corresponding to a more or less recent \(as +of August 2006) version of the corresponding browser. Or it can +be a string which is used directly. ACCEPT, if not NIL, is the +`Accept' header sent. + +If PROXY is not NIL, it should be a string denoting a proxy +server through which the request should be sent. Or it can be a +list of two values - a string denoting the proxy server and an +integer denoting the port to use \(which will default to 80 +otherwise). PROXY-BASIC-AUTHORIZATION is used like +BASIC-AUTHORIZATION, but for the proxy, and only if PROXY is +true. + +ADDITIONAL-HEADERS is a name/value alist \(like PARAMETERS) of +additional HTTP headers which should be sent with the request. + +If REDIRECT is not NIL, it must be a non-negative integer or T. +If REDIRECT is true, Drakma will follow redirects \(return codes +301, 302, 303, or 307) unless REDIRECT is 0. If REDIRECT is an +integer, it will be decreased by 1 with each redirect. +Furthermore, if AUTO-REFERER is true when following redirects, +Drakma will populate the `Referer' header with the URI that +triggered the redirection, overwriting an existing `Referer' +header (in ADDITIONAL-HEADERS) if necessary. + +If KEEP-ALIVE is T, the server will be asked to keep the +connection alive, i.e. not to close it after the reply has been +sent. \(Note that this not necessary if both the client and the +server use HTTP 1.1.) If CLOSE is T, the server is explicitly +asked to close the connection after the reply has been sent. +KEEP-ALIVE and CLOSE are obviously mutually exclusive. + +If the message body sent by the server has a text content type, +Drakma will try to return it as a Lisp string. It'll first check +if the `Content-Type' header denotes an encoding to be used, or +otherwise it will use the EXTERNAL-FORMAT-IN argument. The body +is decoded using FLEXI-STREAMS. If FLEXI-STREAMS doesn't know +the external format, the body is returned as an array of octets. + +If the message body doesn't have a text content type or if +FORCE-BINARY is true, the body is always returned as an array of +octets. + +If WANT-STREAM is true, the message body is NOT read and instead the +\(open) socket stream is returned as the first return value. If the +sixth value of HTTP-REQUEST is true, the stream should be closed \(and +not be re-used) after the body has been read. The stream returned is +a flexi stream \(see http://weitz.de/flexi-streams/) with a chunked +stream \(see http://weitz.de/chunga/) as its underlying stream. If +you want to read binary data from this stream, read from the +underlying stream which you can get with FLEXI-STREAM-STREAM. + +Drakma will usually create a new socket connection for each HTTP +request. However, you can use the STREAM argument to provide an +open socket stream which should be re-used. STREAM MUST be a +stream returned by a previous invocation of HTTP-REQUEST where +the sixth return value wasn't true. Obviously, it must also be +connected to the correct server and at the right position +\(i.e. the message body, if any, must have been read). Drakma +will NEVER attach SSL to a stream provided as the STREAM +argument. + +CONNECTION-TIMEOUT is the time \(in seconds) Drakma will wait until it +considers an attempt to connect to a server as a failure. +READ-TIMEOUT and WRITE-TIMEOUT are the read and write timeouts \(in +seconds) for the socket stream to the server. All three timeout +arguments can also be NIL \(meaning no timeout), and they don't apply +if an existing stream is re-used. All timeout keyword arguments are +only available for LispWorks, WRITE-TIMEOUT is only available for +LispWorks 5.0 or higher." + (unless (member protocol '(:http/1.0 :http/1.1) :test #'eq) + (error "Don't know how to handle protocol ~S." protocol)) + (setq uri (cond ((uri-p uri) (copy-uri uri)) + (t (parse-uri uri)))) + (unless (member method +known-methods+ :test #'eq) + (error "Don't know how to handle method ~S." method)) + (unless (member (uri-scheme uri) '(:http :https) :test #'eq) + (error "Don't know how to handle scheme ~S." (uri-scheme uri))) + (when (and close keep-alive) + (error "CLOSE and KEEP-ALIVE must not be both true.")) + (when (and (eq content :continuation) content-length) + (error "CONTENT-LENGTH must be NIL if CONTENT is :CONTINUATION.")) + (when (and form-data (not (eq method :post))) + (error "FORM-DATA makes only sense with POST requests.")) + ;; convert PROXY argument to canonical form + (when proxy + (when (atom proxy) + (setq proxy (list proxy 80)))) + ;; make sure we don't get :CRLF on Windows + (let ((*default-eol-style* :lf) + (file-parameters-p (find-if-not #'stringp parameters :key #'cdr)) + parameters-used-p) + (when (and file-parameters-p (not (eq method :post))) + (error "Don't know how to handle parameters in ~S, as this is not a POST request." + parameters)) + (when (eq method :post) + ;; create content body for POST unless it was provided + (unless content + ;; mark PARAMETERS argument as used up, so we don't use it + ;; again below + (setq parameters-used-p t) + (cond ((or form-data file-parameters-p) + (let ((boundary (format nil "----------~A" (make-random-string)))) + (setq content (make-form-data-function parameters boundary) + content-type (format nil "multipart/form-data; boundary=~A" boundary))) + (unless (or file-parameters-p content-length-provided-p) + (setq content-length (or content-length t)))) + (t + (setq content (alist-to-url-encoded-string parameters external-format-out) + content-type "application/x-www-form-urlencoded"))))) + (let (http-stream must-close done) + (unwind-protect + (progn + (let ((host (or (and proxy (first proxy)) + (uri-host uri))) + (port (cond (proxy (second proxy)) + ((uri-port uri)) + (t (default-port uri)))) + (use-ssl (or force-ssl + (eq (uri-scheme uri) :https)))) + #+(and :lispworks5.0 :mswindows + (not :lw-does-not-have-write-timeout)) + (when use-ssl + (when (and write-timeout write-timeout-provided-p) + (warn "Disabling WRITE-TIMEOUT because it doesn't mix well with SSL.")) + (setq write-timeout nil)) + (setq http-stream (or stream + #+:lispworks + (comm:open-tcp-stream host port + :element-type 'octet + :timeout connection-timeout + :read-timeout read-timeout + #-:lw-does-not-have-write-timeout + #-:lw-does-not-have-write-timeout + :write-timeout write-timeout + :errorp t) + #-:lispworks + (usocket:socket-stream + (usocket:socket-connect host port :element-type 'octet)))) + (when (and use-ssl + ;; don't attach SSL to existing streams + (not stream)) + #+:lispworks + (comm:attach-ssl http-stream :ssl-side :client) + #-:lispworks + (setq http-stream + #+:allegro + (socket:make-ssl-client-stream http-stream) + #-:allegro + (let ((s http-stream)) + (cl+ssl:make-ssl-client-stream + (cl+ssl:stream-fd s) + :close-callback (lambda () (close s))))))) + (cond (stream + (setf (flexi-stream-element-type http-stream) + #+:lispworks 'lw:simple-char #-:lispworks 'character + (flexi-stream-external-format http-stream) +latin-1+)) + (t + (setq http-stream + (make-flexi-stream (make-chunked-stream http-stream) + :external-format +latin-1+)))) + (labels ((write-http-line (fmt &rest args) + (when *header-stream* + (format *header-stream* "~?~%" fmt args)) + (format http-stream "~?~C~C" fmt args #\Return #\Linefeed)) + (write-header (name value-fmt &rest value-args) + (write-http-line "~A: ~?" name value-fmt value-args))) + (when (and (not parameters-used-p) + parameters) + (setf (uri-query uri) + ;; append parameters to existing query of URI + (format nil "~@[~A~]~:*~:[~;&~]~A" + (uri-query uri) + (alist-to-url-encoded-string parameters external-format-out)))) + (when (eq method :options*) + ;; special pseudo-method + (setf method :options + (uri-path uri) "*" + (uri-query uri) nil)) + (write-http-line "~A ~A ~A" + (string-upcase method) + (cond (proxy (render-uri uri nil)) + (t (format nil "~A~@[?~A~]" + (or (uri-path uri) "/") + (uri-query uri)))) + (string-upcase protocol)) + (write-header "Host" "~A~@[:~A~]" (uri-host uri) (non-default-port uri)) + (when user-agent + (write-header "User-Agent" (user-agent-string user-agent))) + (when basic-authorization + (write-header "Authorization" "Basic ~A" + (base64:string-to-base64-string + (format nil "~A:~A" + (first basic-authorization) + (second basic-authorization))))) + (when (and proxy proxy-basic-authorization) + (write-header "Proxy-Authorization" "Basic ~A" + (base64:string-to-base64-string + (format nil "~A:~A" + (first proxy-basic-authorization) + (second proxy-basic-authorization))))) + (when accept + (write-header "Accept" "~A" accept)) + (when cookie-jar + ;; write all cookies in one fell swoop, so even Sun's + ;; web server has a change to get it + (when-let (cookies (loop for cookie in (cookie-jar-cookies cookie-jar) + when (send-cookie-p cookie uri force-ssl) + collect (cookie-name cookie) and + collect (cookie-value cookie))) + (write-header "Cookie" "~{~A=~A~^; ~}" cookies))) + (when keep-alive + (write-header "Connection" "Keep-Alive")) + (when close + (setq must-close close) + (write-header "Connection" "close")) + (loop for (name . value) in additional-headers + do (write-header name "~A" value)) + (when content + (when content-type + (write-header "Content-Type" "~A" content-type)) + (when (and content-length + (not (or (arrayp content) + (listp content) + (eq content :continuation)))) + ;; CONTENT-LENGTH forces us to compute request body + ;; in RAM + (setq content + (with-output-to-sequence (bin-out) + (let ((out (make-flexi-stream bin-out :external-format +latin-1+))) + (send-content content out))))) + (when (and (or (not content-length-provided-p) + (eq content-length t)) + (or (arrayp content) (listp content))) + (setq content-length (length content))) + (cond (content-length + (write-header "Content-Length" "~D" content-length)) + (t + (write-header "Transfer-Encoding" "chunked")))) + ;; end of request headers + (when *header-stream* + (terpri *header-stream*)) + (format http-stream "~C~C" #\Return #\Linefeed) + (force-output http-stream) + (when (and content (null content-length)) + (setf (chunked-stream-output-chunking-p + (flexi-stream-stream http-stream)) t)) + (labels ((finish-request (content &optional continuep) + (send-content content http-stream external-format-out) + (when continuep + (force-output http-stream) + (return-from finish-request)) + (setf (chunked-stream-output-chunking-p + (flexi-stream-stream http-stream)) nil) + (finish-output http-stream) + (multiple-value-bind (server-protocol status-code status-text) + ;; loop until status is NOT 100 + (loop for (server-protocol status-code status-text) + = (read-status-line http-stream *header-stream*) + when (= status-code 100) + ;; ignore headers sent until non-100 status is seen + do (read-http-headers http-stream *header-stream*) + until (/= status-code 100) + finally (return (values server-protocol status-code status-text))) + (let ((headers (read-http-headers http-stream *header-stream*)) + body external-format-body) + (let ((connections (header-value :connection headers))) + (when connections + (setq connections (split-tokens connections))) + (when (or (member "close" connections :test #'string-equal) + (not (or (and (eq protocol :http/1.1) + (eq server-protocol :http/1.1)) + (member "Keep-Alive" connections + :test #'string-equal)))) + (setq must-close t))) + (when cookie-jar + (update-cookies (get-cookies headers uri) cookie-jar)) + (when (and redirect + (member status-code +redirect-codes+) + (member method redirect-methods)) + (unless (or (eq redirect t) + (and (integerp redirect) + (plusp redirect))) + (cerror "Continue anyway." + "Status code was ~A, but ~ +~:[REDIRECT is ~S~;redirection limit has been exceeded~]." + status-code (integerp redirect) redirect)) + (when auto-referer + (setq additional-headers (set-referer uri additional-headers))) + (let* ((location (header-value :location headers)) + (new-uri (merge-uris (cond ((or (null location) + (zerop (length location))) + (warn "Empty `Location' header, assuming \"/\".") + "/") + (t location)) + uri)) + ;; can we re-use the stream? + (old-server-p (and (string= (uri-host new-uri) + (uri-host uri)) + (eql (uri-port new-uri) + (uri-port uri)) + (eq (uri-scheme new-uri) + (uri-scheme uri))))) + (unless old-server-p + (setq must-close t + want-stream nil)) + ;; try to re-use the stream, but only + ;; if the user hasn't opted for a + ;; connection which is always secure + (let ((re-use-stream (and old-server-p + (not must-close) + (not force-ssl)))) + ;; close stream if we can't re-use it + (unless re-use-stream + (ignore-errors (close http-stream))) + (setq done t) + (return-from http-request + (apply #'http-request new-uri + :redirect (cond ((integerp redirect) (1- redirect)) + (t redirect)) + :stream (and re-use-stream http-stream) + :additional-headers additional-headers + args))))) + (let ((transfer-encodings (header-value :transfer-encoding headers))) + (when transfer-encodings + (setq transfer-encodings (split-tokens transfer-encodings))) + (when (member "chunked" transfer-encodings :test #'equalp) + (setf (chunked-stream-input-chunking-p + (flexi-stream-stream http-stream)) t))) + (when (setq external-format-body + (and (not force-binary) + (funcall *body-format-function* + headers external-format-in))) + (setf (flexi-stream-external-format http-stream) + external-format-body)) + (when force-binary + (setf (flexi-stream-element-type http-stream) 'octet)) + (unless (or want-stream (eq method :head)) + (let (trailers) + (multiple-value-setq (body trailers) + (read-body http-stream headers must-close external-format-body)) + (when trailers + (warn "Adding trailers from chunked encoding to HTTP headers.") + (setq headers (nconc headers trailers))))) + (setq done t) + (values (cond (want-stream http-stream) + (t body)) + status-code + headers + uri + http-stream + must-close + status-text))))) + (when (eq content :continuation) + (return-from http-request #'finish-request)) + (finish-request content)))) + ;; the cleanup form of the UNWIND-PROTECT above + (when (and http-stream + (or (not done) + (and must-close + (not want-stream))) + (not (eq content :continuation))) + (ignore-errors (close http-stream))))))) Added: branches/trunk-reorg/thirdparty/drakma-0.11.3/specials.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/drakma-0.11.3/specials.lisp Wed Feb 13 14:41:09 2008 @@ -0,0 +1,208 @@ +;;; -*- Mode: LISP; Syntax: COMMON-LISP; Package: DRAKMA; Base: 10 -*- +;;; $Header: /usr/local/cvsrep/drakma/specials.lisp,v 1.19 2008/01/14 01:57:02 edi Exp $ + +;;; Copyright (c) 2006-2008, Dr. Edmund Weitz. All rights reserved. + +;;; Redistribution and use in source and binary forms, with or without +;;; modification, are permitted provided that the following conditions +;;; are met: + +;;; * Redistributions of source code must retain the above copyright +;;; notice, this list of conditions and the following disclaimer. + +;;; * Redistributions in binary form must reproduce the above +;;; copyright notice, this list of conditions and the following +;;; disclaimer in the documentation and/or other materials +;;; provided with the distribution. + +;;; THIS SOFTWARE IS PROVIDED BY THE AUTHOR 'AS IS' AND ANY EXPRESSED +;;; OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +;;; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +;;; ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +;;; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +;;; DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +;;; GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +;;; INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +;;; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +;;; NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +;;; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +(in-package :drakma) + +(defmacro define-constant (name value &optional doc) + "A version of DEFCONSTANT for, cough, /strict/ CL implementations." + ;; See + `(defconstant ,name (if (boundp ',name) (symbol-value ',name) ,value) + ,@(when doc (list doc)))) + +(define-constant +latin-1+ (make-external-format :latin-1 :eol-style :lf) + "Default external format when reading headers.") + +(define-constant +redirect-codes+ '(301 302 303 307) + "A list of all HTTP return codes that redirect us to another URI.") + +(define-constant +known-methods+ '(:copy + :delete + :delete + :get + :head + :lock + :mkcol + :move + :options + :options* + :post + :propfind + :proppatch + :put + :trace + :unlock) + "The HTTP methods \(including WebDAV methods) Drakma knows.") + +(defconstant +buffer-size+ 8192) + +(defvar *drakma-default-external-format* ':latin-1 + "The default value for the external format keyword arguments of +HTTP-REQUEST.") + +(defvar *header-stream* nil + "If this variable is not NIL, it should be bound to a stream to +which incoming and outgoing headers will be written for debugging +purposes.") + +(defvar *ignore-unparseable-cookie-dates-p* nil + "Whether Drakma is allowed to treat `Expires' dates in cookie +headers as non-existent if it can't parse them. If the value of this +variable is NIL \(which is the default), an error will be signalled +instead.") + +(defvar *text-content-types* '(("text" . nil)) + "A list of conses which are used by DETERMINE-BODY-FORMAT to decide +whether a `Content-Type' header denotes text content. The car and cdr +of each cons should each be a string or NIL. A content type matches +one of these entries \(and thus denotes text) if the type part is +STRING-EQUAL to the car or if the car is NIL and if the subtype part +is STRING-EQUAL to the cdr or if the cdr is NIL.") + +(defvar *body-format-function* 'determine-body-format + "A function which determines whether the content body returned by +the server is text and should be treated as such or not. The function +is called after the request headers have been read and it must accept +two arguments, HEADERS and EXTERNAL-FORMAT-IN where HEADERS is like +the third return value of HTTP-REQUEST while EXTERNAL-FORMAT-IN is the +HTTP-REQUEST argument of the same name. It should return NIL if the +body should be regarded as binary content, or a FLEXI-STREAMS external +format \(which will be used to read the body) otherwise. + +This function will only be called if the FORCE-BINARY argument to +HTTP-REQUEST was NIL.") + +(defvar *time-zone-map* + ;; list taken from + ;; + '(("A" . -1) + ("ACDT" . -10.5) + ("ACST" . -9.5) + ("ADT" . 3) + ("AEDT" . -11) + ("AEST" . -10) + ("AKDT" . 8) + ("AKST" . 9) + ("AST" . 4) + ("AWDT" . -9) + ("AWST" . -8) + ("B" . -2) + ("BST" . -1) + ("C" . -3) + ("CDT" . 5) + ("CEDT" . -2) + ("CEST" . -2) + ("CET" . -1) + ("CST" . -10.5) + ("CST" . -9.5) + ("CST" . 6) + ("CXT" . -7) + ("D" . -4) + ("E" . -5) + ("EDT" . 4) + ("EEDT" . -3) + ("EEST" . -3) + ("EET" . -2) + ("EST" . -11) + ("EST" . -10) + ("EST" . 5) + ("F" . -6) + ("G" . -7) + ("GMT" . 0) + ("H" . -8) + ("HAA" . 3) + ("HAC" . 5) + ("HADT" . 9) + ("HAE" . 4) + ("HAP" . 7) + ("HAR" . 6) + ("HAST" . 10) + ("HAT" . 2.5) + ("HAY" . 8) + ("HNA" . 4) + ("HNC" . 6) + ("HNE" . 5) + ("HNP" . 8) + ("HNR" . 7) + ("HNT" . 3.5) + ("HNY" . 9) + ("I" . -9) + ("IST" . -1) + ("K" . -10) + ("L" . -11) + ("M" . -12) + ("MDT" . 6) + ("MESZ" . -2) + ("MEZ" . -1) + ("MST" . 7) + ("N" . 1) + ("NDT" . 2.5) + ("NFT" . -11.5) + ("NST" . 3.5) + ("O" . 2) + ("P" . 3) + ("PDT" . 7) + ("PST" . 8) + ("Q" . 4) + ("R" . 5) + ("S" . 6) + ("T" . 7) + ("U" . 8) + ("UTC" . 0) + ("V" . 9) + ("W" . 10) + ("WEDT" . -1) + ("WEST" . -1) + ("WET" . 0) + ("WST" . -9) + ("WST" . -8) + ("X" . 11) + ("Y" . 12) + ("Z" . 0)) + "An alist which maps time zone abbreviations to Common Lisp +timezones.") + +;; stuff for Nikodemus Siivola's HYPERDOC +;; see +;; and +;; also used by LW-ADD-ONS + +(defvar *hyperdoc-base-uri* "http://weitz.de/drakma/") + +(let ((exported-symbols-alist + (loop for symbol being the external-symbols of :drakma + collect (cons symbol + (concatenate 'string + "#" + (string-downcase symbol)))))) + (defun hyperdoc-lookup (symbol type) + (declare (ignore type)) + (cdr (assoc symbol + exported-symbols-alist + :test #'eq)))) + Added: branches/trunk-reorg/thirdparty/drakma-0.11.3/util.lisp ============================================================================== --- (empty file) +++ branches/trunk-reorg/thirdparty/drakma-0.11.3/util.lisp Wed Feb 13 14:41:09 2008 @@ -0,0 +1,287 @@ +;;; -*- Mode: LISP; Syntax: COMMON-LISP; Package: DRAKMA; Base: 10 -*- +;;; $Header: /usr/local/cvsrep/drakma/util.lisp,v 1.35 2008/01/14 01:57:02 edi Exp $ + +;;; Copyright (c) 2006-2008, Dr. Edmund Weitz. All rights reserved. + +;;; Redistribution and use in source and binary forms, with or without +;;; modification, are permitted provided that the following conditions +;;; are met: + +;;; * Redistributions of source code must retain the above copyright +;;; notice, this list of conditions and the following disclaimer. + +;;; * Redistributions in binary form must reproduce the above +;;; copyright notice, this list of conditions and the following +;;; disclaimer in the documentation and/or other materials +;;; provided with the distribution. + +;;; THIS SOFTWARE IS PROVIDED BY THE AUTHOR 'AS IS' AND ANY EXPRESSED +;;; OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +;;; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +;;; ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +;;; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +;;; DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +;;; GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +;;; INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +;;; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +;;; NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +;;; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +(in-package :drakma) + +#+:lispworks +(require "comm") + +#+:lispworks +(eval-when (:compile-toplevel :load-toplevel :execute) + (import 'lw:when-let)) + +#-:lispworks +(defmacro when-let ((var expr) &body body) + "Evaluates EXPR, binds it to VAR, and executes BODY if VAR has +a true value." + `(let ((,var ,expr)) + (when ,var + , at body))) + +#+:lispworks +(eval-when (:compile-toplevel :load-toplevel :execute) + (import 'lw:with-unique-names)) + +#-:lispworks +(defmacro with-unique-names ((&rest bindings) &body body) + "Syntax: WITH-UNIQUE-NAMES ( { var | (var x) }* ) declaration* form* + +Executes a series of forms with each VAR bound to a fresh, +uninterned symbol. The uninterned symbol is as if returned by a call +to GENSYM with the string denoted by X - or, if X is not supplied, the +string denoted by VAR - as argument. + +The variable bindings created are lexical unless special declarations +are specified. The scopes of the name bindings and declarations do not +include the Xs. + +The forms are evaluated in order, and the values of all but the last +are discarded \(that is, the body is an implicit PROGN)." + ;; reference implementation posted to comp.lang.lisp as + ;; by Vebjorn Ljosa - see also + ;; + `(let ,(mapcar #'(lambda (binding) + (check-type binding (or cons symbol)) + (if (consp binding) + (destructuring-bind (var x) binding + (check-type var symbol) + `(,var (gensym ,(etypecase x + (symbol (symbol-name x)) + (character (string x)) + (string x))))) + `(,binding (gensym ,(symbol-name binding))))) + bindings) + , at body)) + +(defun ends-with-p (seq suffix &key (test #'char-equal)) + "Returns true if the sequence SEQ ends with the sequence +SUFFIX. Individual elements are compared with TEST." + (let ((mismatch (mismatch seq suffix :from-end t :test test))) + (or (null mismatch) + (= mismatch (- (length seq) (length suffix)))))) + +(defun starts-with-p (seq prefix &key (test #'char-equal)) + "Returns true if the sequence SEQ starts with the sequence +PREFIX whereby the elements are compared using TEST." + (let ((mismatch (mismatch seq prefix :test test))) + (or (null mismatch) + (= mismatch (length prefix))))) + +(defun url-encode (string external-format) + "Returns a URL-encoded version of the string STRING using the +LispWorks external format EXTERNAL-FORMAT." + (with-output-to-string (out) + (loop for octet across (string-to-octets (or string "") + :external-format external-format) + for char = (code-char octet) + do (cond ((or (char<= #\0 char #\9) + (char<= #\a char #\z) + (char<= #\A char #\Z) + (find char "$-_.!*'()," :test #'char=)) + (write-char char out)) + ((char= char #\Space) + (write-char #\+ out)) + (t (format out "%~2,'0x" (char-code char))))))) + +(defun alist-to-url-encoded-string (alist external-format) + "ALIST is supposed to be an alist of name/value pairs where both +names and values are strings. This function returns a string where +this list is represented as for the content type +`application/x-www-form-urlencoded', i.e. the values are URL-encoded +using the external format EXTERNAL-FORMAT, the pairs are joined with a +#\\& character, and each name is separated from its value with a #\\= +character." + (with-output-to-string (out) + (loop for first = t then nil + for (name . value) in alist + unless first do (write-char #\& out) + do (format out "~A=~A" + (url-encode name external-format) + (url-encode value external-format))))) + +(defun default-port (uri) + "Returns the default port number for the \(PURI) URI URI. +Works only with the http and https schemes." + (ecase (uri-scheme uri) + (:http 80) + (:https 443))) + +(defun non-default-port (uri) + "If the \(PURI) URI specifies an explicit port number which is +different from the default port its scheme, this port number is +returned, otherwise NIL." + (when-let (port (uri-port uri)) + (when (/= port (default-port uri)) + port))) + +(defun user-agent-string (token) + "Returns a corresponding user agent string if TOKEN is one of +the keywords :DRAKMA, :FIREFOX, :EXPLORER, :OPERA, or :SAFARI. +Returns TOKEN itself otherwise." + (case token + (:drakma + (format nil "Drakma/~A (~A~@[ ~A~]; ~A;~@[ ~A;~] http://weitz.de/drakma/)" + *drakma-version-string* + (or (lisp-implementation-type) "Common Lisp") + (or (lisp-implementation-version) "") + (or #-:clisp (software-type) + #+(or :win32 :mswindows) "Windows" + #-(or :win32 :mswindows) "Unix") + (or #-:clisp (software-version)))) + (:firefox + "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.0.6) Gecko/20060728 Firefox/1.5.0.6") + (:explorer + "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)") + (:opera + "Opera/9.01 (Windows NT 5.1; U; en)") + (:safari + "Mozilla/5.0 (Macintosh; U; Intel Mac OS X; en) AppleWebKit/418.8 (KHTML, like Gecko) Safari/419.3") + (otherwise token))) + +(defun header-value (name headers) + "If HEADERS is an alist of headers as returned by HTTP-REQUEST +and NAME is a keyword naming a header, this function returns the +corresponding value of this header \(or NIL if it's not in +HEADERS)." + (cdr (assoc name headers :test #'eq))) + +(defun parameter-present-p (name parameters) + "If PARAMETERS is an alist of parameters as returned by, for +example, READ-TOKENS-AND-PARAMETERS and NAME is a string naming a +parameter, this function returns the full parameter \(name and +value) - or NIL if it's not in PARAMETERS." + (assoc name parameters :test #'string-equal)) + +(defun parameter-value (name parameters) + "If PARAMETERS is an alist of parameters as returned by, for +example, READ-TOKENS-AND-PARAMETERS and NAME is a string naming a +parameter, this function returns the value of this parameter - or +NIL if it's not in PARAMETERS." + (cdr (parameter-present-p name parameters))) + +(defun make-random-string (&optional (length 50)) + "Generates and returns a random string length LENGTH. The +string will consist solely of decimal digits and ASCII letters." + (with-output-to-string (s) + (dotimes (i length) + (write-char (ecase (random 5) + ((0 1) (code-char (+ #.(char-code #\a) (random 26)))) + ((2 3) (code-char (+ #.(char-code #\A) (random 26)))) + ((4) (code-char (+ #.(char-code #\0) (random 10))))) + s)))) + +(defun split-string (string &optional (separators " ,-")) + "Splits STRING into a list of substrings \(which is returned) +separated by the characters in the sequence SEPARATORS. Empty +substrings aren't collected." + (flet ((make-collector () + (make-array 0 + :adjustable t + :fill-pointer t + :element-type #+:lispworks 'lw:simple-char + #-:lispworks 'character))) + (loop with collector = (make-collector) + for char across string + for counter downfrom (1- (length string)) + when (find char separators :test #'char=) + when (plusp (length collector)) + collect collector + and do (setq collector (make-collector)) end + else + do (vector-push-extend char collector) + and when (zerop counter) + collect collector))) + +(defun safe-parse-integer (string) + "Like PARSE-INTEGER, but returns NIL instead of signalling an error." + (ignore-errors (parse-integer string))) + +(defun interpret-as-month (string) + "Tries to interpret STRING as a string denoting a month and returns +the corresponding number of the month. Accepts three-letter +abbreviations like \"Feb\" and full month names likes \"February\". +Finally, the function also accepts strings representing integers from +one to twelve." + (or (when-let (pos (position (subseq string 0 (min 3 (length string))) + '("Jan" "Feb" "Mar" "Apr" "May" "Jun" + "Jul" "Aug" "Sep" "Oct" "Nov" "Dec") + :test #'string=)) + (1+ pos)) + (when-let (num (safe-parse-integer string)) + (when (<= 1 num 12) + num)))) + +(defun interpret-as-time-zone (string) + "Tries to interpret STRING as a time zone abbreviation which can +either be something like \"PST\" or \"GMT\" with an offset like +\"GMT-02:00\"." + (when-let (zone (cdr (assoc string *time-zone-map* :test #'string=))) + (return-from interpret-as-time-zone zone)) + (unless (and (= (length string) 9) + (starts-with-p string "GMT") + (find (char string 3) "+-" :test #'char=) + (char= (char string 6) #\:) + (every (lambda (pos) + (digit-char-p (char string pos))) + '(4 5 7 8))) + (error "Can't interpret ~S as a time zone." string)) + (let ((hours (parse-integer string :start 4 :end 6)) + (minutes (parse-integer string :start 7 :end 9))) + (* (if (char= (char string 3) #\+) -1 1) + (+ hours (/ minutes 60))))) + +(defun set-referer (referer-uri &optional alist) + "Returns a fresh copy of the HTTP header list ALIST with the +`Referer' header set to REFERER-URI. If REFERER-URI is NIL, the +result will be a list of headers without a `Referer' header." + (let ((alist-sans-referer (remove "Referer" alist :key #'car :test #'string=))) + (cond (referer-uri (acons "Referer" referer-uri alist-sans-referer)) + (t alist-sans-referer)))) + +(defun text-content-type-p (type subtype) + "Returns a true value iff the combination of TYPE and SUBTYPE +matches an entry of *TEXT-CONTENT-TYPES*. See docstring of +*TEXT-CONTENT-TYPES* for more info." + (loop for (candidate-type . candidate-subtype) in *text-content-types* + thereis (and (or (null candidate-type) + (string-equal type candidate-type)) + (or (null candidate-subtype) + (string-equal subtype candidate-subtype))))) + +(defun as-keyword (string) + "Converts the string STRING to a keyword where all characters are +uppercase or lowercase, taking into account the current readtable +case." + (intern (funcall + (if (eq (readtable-case *readtable*) :upcase) + #'string-upcase + #'string-downcase) + string) + :keyword)) + From hhubner at common-lisp.net Wed Feb 13 20:22:23 2008 From: hhubner at common-lisp.net (hhubner at common-lisp.net) Date: Wed, 13 Feb 2008 15:22:23 -0500 (EST) Subject: [bknr-cvs] r2488 - in branches/trunk-reorg: bknr/web/src/images bknr/web/src/web projects/bos/web projects/quickhoney/src xhtmlgen Message-ID: <20080213202223.F122D7A01E@common-lisp.net> Author: hhubner Date: Wed Feb 13 15:22:21 2008 New Revision: 2488 Modified: branches/trunk-reorg/bknr/web/src/images/imageproc-handler.lisp branches/trunk-reorg/bknr/web/src/web/tags.lisp branches/trunk-reorg/projects/bos/web/webserver.lisp branches/trunk-reorg/projects/quickhoney/src/imageproc.lisp branches/trunk-reorg/projects/quickhoney/src/tags.lisp branches/trunk-reorg/xhtmlgen/xhtmlgen.lisp Log: Fixes for templater and toplevel, BOS templates now work a bit better. Modified: branches/trunk-reorg/bknr/web/src/images/imageproc-handler.lisp ============================================================================== --- branches/trunk-reorg/bknr/web/src/images/imageproc-handler.lisp (original) +++ branches/trunk-reorg/bknr/web/src/images/imageproc-handler.lisp Wed Feb 13 15:22:21 2008 @@ -16,35 +16,35 @@ (defun apply-imageproc-operation (operation-name args image) (apply (or (gethash (make-keyword-from-string operation-name) *imageproc-operations*) - (error "invalid imageproc operation name ~A" operation-name)) - image args)) + (error "invalid imageproc operation name ~A" operation-name)) + image args)) (defun imageproc (image operations) (with-store-image (input-image image) (setf (save-alpha-p :image input-image) t) (let ((working-image input-image)) (dolist (operation operations) - (destructuring-bind (operation-name &rest args) (substitute nil "" (split "," operation) :test #'equal) - (let ((returned-image (apply-imageproc-operation operation-name args working-image))) - (unless (not returned-image) - (unless (or (eq working-image returned-image) - (eq working-image input-image)) - (destroy-image working-image)) - (setf working-image returned-image))))) + (destructuring-bind (operation-name &rest args) (substitute nil "" (split "," operation) :test #'equal) + (let ((returned-image (apply-imageproc-operation operation-name args working-image))) + (unless (not returned-image) + (unless (or (eq working-image returned-image) + (eq working-image input-image)) + (destroy-image working-image)) + (setf working-image returned-image))))) (when (and (true-color-p working-image) - (not (true-color-p input-image))) - (true-color-to-palette :dither t :image working-image :colors-wanted 256)) + (not (true-color-p input-image))) + (true-color-to-palette :dither t :image working-image :colors-wanted 256)) (let ((stream (send-headers))) - (setf (flex:flexi-stream-element-type stream) 'flex:octet) - (write-image-to-stream stream (image-type-keyword image) :image working-image)) + (setf (flex:flexi-stream-element-type stream) 'flex:octet) + (write-image-to-stream stream (image-type-keyword image) :image working-image)) (unless (eq working-image input-image) - (destroy-image working-image))))) + (destroy-image working-image))))) #+(or) (unless (member type '(:jpg :jpeg)) (when (true-color-p input-image) (true-color-to-palette :dither t :image input-image - :colors-wanted 256))) + :colors-wanted 256))) (defparameter *cell-border-width* 5) @@ -54,38 +54,38 @@ (setf bgcolor (if (and (stringp bgcolor) (not (zerop (length bgcolor)))) bgcolor nil)) (setq border-width (if border-width (parse-integer border-width) *cell-border-width*)) (let* ((width (image-width input-image)) - (height (image-height input-image)) - (ratio (max (/ width (- cell-width (* border-width 2))) - (/ height (- cell-height (* border-width 2))))) - (thumbnail-width (min width (round (/ width ratio)))) - (thumbnail-height (min height (round (/ height ratio)))) - (x-offset (round (/ (- cell-width thumbnail-width) 2))) - (y-offset (round (/ (- cell-height thumbnail-height) 2))) - (cell (create-image cell-width cell-height t))) + (height (image-height input-image)) + (ratio (max (/ width (- cell-width (* border-width 2))) + (/ height (- cell-height (* border-width 2))))) + (thumbnail-width (min width (round (/ width ratio)))) + (thumbnail-height (min height (round (/ height ratio)))) + (x-offset (round (/ (- cell-width thumbnail-width) 2))) + (y-offset (round (/ (- cell-height thumbnail-height) 2))) + (cell (create-image cell-width cell-height t))) (with-default-image (cell) (let ((color (if bgcolor - (parse-color bgcolor) - (allocate-color 255 255 255)))) - (fill-image 0 0 :color color) - (copy-image input-image cell - 0 0 - x-offset - y-offset - width height - :resize t :resample t - :dest-width thumbnail-width :dest-height thumbnail-height) - (unless bgcolor - (setf (transparent-color) color) - (let ((cr (ldb (byte 8 16) color)) - (cg (ldb (byte 8 8) color)) - (cb (ldb (byte 8 0) color))) - (flet ((color-distance (c) - (+ (abs (- (ldb (byte 8 16) c) cr)) - (abs (- (ldb (byte 8 8) c) cg)) - (abs (- (ldb (byte 8 0) c) cb))))) - (do-pixels () - (when (< (color-distance (raw-pixel)) 6) - (setf (raw-pixel) color)))))))) + (parse-color bgcolor) + (allocate-color 255 255 255)))) + (fill-image 0 0 :color color) + (copy-image input-image cell + 0 0 + x-offset + y-offset + width height + :resize t :resample t + :dest-width thumbnail-width :dest-height thumbnail-height) + (unless bgcolor + (setf (transparent-color) color) + (let ((cr (ldb (byte 8 16) color)) + (cg (ldb (byte 8 8) color)) + (cb (ldb (byte 8 0) color))) + (flet ((color-distance (c) + (+ (abs (- (ldb (byte 8 16) c) cr)) + (abs (- (ldb (byte 8 8) c) cg)) + (abs (- (ldb (byte 8 0) c) cb))))) + (do-pixels () + (when (< (color-distance (raw-pixel)) 6) + (setf (raw-pixel) color)))))))) cell)) (define-imageproc-handler thumbnail (input-image &optional bgcolor max-width max-height) @@ -93,50 +93,50 @@ (setf max-width (if max-width (parse-integer max-width) *thumbnail-max-width*)) (setf max-height (if max-height (parse-integer max-height) *thumbnail-max-height*)) (let ((width (image-width input-image)) - (height (image-height input-image))) + (height (image-height input-image))) (when (or (< max-width width) - (< max-height height)) + (< max-height height)) (let* ((ratio (max (/ width max-width) - (/ height max-height))) - (thumbnail-width (round (/ width ratio))) - (thumbnail-height (round (/ height ratio))) - (thumbnail (create-image thumbnail-width - thumbnail-height - t))) - (with-default-image (thumbnail) - (fill-image 0 0 :color (parse-color bgcolor)) - (copy-image input-image thumbnail - 0 0 0 0 - width height - :resize t :resample t - :dest-width thumbnail-width :dest-height thumbnail-height)) - thumbnail)))) + (/ height max-height))) + (thumbnail-width (round (/ width ratio))) + (thumbnail-height (round (/ height ratio))) + (thumbnail (create-image thumbnail-width + thumbnail-height + t))) + (with-default-image (thumbnail) + (fill-image 0 0 :color (parse-color bgcolor)) + (copy-image input-image thumbnail + 0 0 0 0 + width height + :resize t :resample t + :dest-width thumbnail-width :dest-height thumbnail-height)) + thumbnail)))) (define-imageproc-handler double (input-image &optional (times "2")) (let* ((width (image-width input-image)) - (height (image-height input-image)) - (ratio (/ 1 (parse-integer times))) - (double-image-width (round (/ width ratio))) - (double-image-height (round (/ height ratio))) - (double-image (create-image double-image-width double-image-height nil))) + (height (image-height input-image)) + (ratio (/ 1 (parse-integer times))) + (double-image-width (round (/ width ratio))) + (double-image-height (round (/ height ratio))) + (double-image (create-image double-image-width double-image-height nil))) (with-default-image (double-image) (setf (transparent-color double-image) - (find-color-from-image (transparent-color input-image) input-image :alpha t :resolve t)) + (find-color-from-image (transparent-color input-image) input-image :alpha t :resolve t)) (fill-image 0 0 :color (transparent-color double-image)) (copy-image input-image double-image - 0 0 0 0 width height - :resize t - :dest-width double-image-width :dest-height double-image-height)) + 0 0 0 0 width height + :resize t + :dest-width double-image-width :dest-height double-image-height)) double-image)) (define-imageproc-handler color (input-image &rest color-mappings) (with-default-image (input-image) (let ((colors (loop for (old new) on color-mappings by #'cddr - collect (cons (parse-color old) (parse-color new))))) + collect (cons (parse-color old) (parse-color new))))) (do-pixels (input-image) - (let ((new-color (assoc (ldb (byte 24 0) (raw-pixel)) colors))) - (when (cdr new-color) - (setf (raw-pixel) (cdr new-color))))))) + (let ((new-color (assoc (ldb (byte 24 0) (raw-pixel)) colors))) + (when (cdr new-color) + (setf (raw-pixel) (cdr new-color))))))) input-image) (defun image-url (image &key process (prefix "/image")) @@ -146,19 +146,19 @@ (if (string-equal color-string "transparent") (transparent-color image) (let ((components (multiple-value-bind (match strings) - (scan-to-strings "^#?(..)(..)(..)?$" color-string) - (if match - (mapcar #'(lambda (string) (when string (parse-integer string :radix 16))) - (coerce strings 'list)) - (progn - (warn "can't parse color spec ~a" color-string) - '(0 0 0)))))) - (let ((color (find-color (first components) (second components) (third components) - :exact t :image image))) - (unless color - (setf color (find-color (first components) (second components) (third components) - :exact nil :resolve t :image image))) - color)))) + (scan-to-strings "^#?(..)(..)(..)?$" color-string) + (if match + (mapcar #'(lambda (string) (when string (parse-integer string :radix 16))) + (coerce strings 'list)) + (progn + (warn "can't parse color spec ~a" color-string) + '(0 0 0)))))) + (let ((color (find-color (first components) (second components) (third components) + :exact t :image image))) + (unless color + (setf color (find-color (first components) (second components) (third components) + :exact nil :resolve t :image image))) + color)))) (defclass imageproc-handler (image-handler) ()) @@ -174,14 +174,14 @@ #+(or) (with-http-response (:content-type (image-content-type (image-type-keyword image))) (let ((ims (header-in :if-modified-since)) - (changed-time (blob-timestamp image))) + (changed-time (blob-timestamp image))) (setf (header-out :last-modified) (rfc-1123-date changed-time)) - (if (and ims - (<= changed-time (date-to-universal-time ims))) - (progn - (setf (return-code) +http-not-modified+) - (format t "; image ~A not changed~%" image) - (with-http-body ())) - (with-http-body () - (imageproc image (cdr (decoded-handler-path page-handler)))))))) + (if (and ims + (<= changed-time (date-to-universal-time ims))) + (progn + (setf (return-code) +http-not-modified+) + (format t "; image ~A not changed~%" image) + (with-http-body ())) + (with-http-body () + (imageproc image (cdr (decoded-handler-path page-handler)))))))) Modified: branches/trunk-reorg/bknr/web/src/web/tags.lisp ============================================================================== --- branches/trunk-reorg/bknr/web/src/web/tags.lisp (original) +++ branches/trunk-reorg/bknr/web/src/web/tags.lisp Wed Feb 13 15:22:21 2008 @@ -4,7 +4,7 @@ (defvar *toplevel-children*) -(define-bknr-tag toplevel (&key children title (template "toplevel")) +(define-bknr-tag toplevel (&key title (template "toplevel")) (setf (get-template-var :title) title) (when (and (not (scan "^/" template)) (scan "/" (request-variable :template-path))) @@ -14,8 +14,8 @@ (let* ((expander *template-expander*) (pathname (find-template-pathname expander template)) (toplevel (get-cached-template pathname expander)) - (*toplevel-children* children)) - (emit-template-node toplevel))) + (*toplevel-children* *tag-children*)) + (emit-template-node *template-expander* toplevel))) (define-bknr-tag tag-body () (let ((*tag-children* *toplevel-children*)) Modified: branches/trunk-reorg/projects/bos/web/webserver.lisp ============================================================================== --- branches/trunk-reorg/projects/bos/web/webserver.lisp (original) +++ branches/trunk-reorg/projects/bos/web/webserver.lisp Wed Feb 13 15:22:21 2008 @@ -195,6 +195,7 @@ (setf *worldpay-test-mode* worldpay-test-mode) (setf bknr.web:*upload-file-size-limit* 20000000) + (setf hunchentoot::*hunchentoot-default-external-format* (flex:make-external-format :utf-8 :eol-style :lf)) (make-instance 'bos-website :name "create-rainforest.org CMS" Modified: branches/trunk-reorg/projects/quickhoney/src/imageproc.lisp ============================================================================== --- branches/trunk-reorg/projects/quickhoney/src/imageproc.lisp (original) +++ branches/trunk-reorg/projects/quickhoney/src/imageproc.lisp Wed Feb 13 15:22:21 2008 @@ -4,36 +4,35 @@ (define-imageproc-handler cutout-button (input-image &optional keyword (background-color "ffffff")) (let ((button-image (create-image *button-size* *button-size* t)) - (square-size (min (image-width input-image) (image-height input-image))) - (x-offset (if (> (image-width input-image) (image-height input-image)) - (round (/ (- (image-width input-image) (image-height input-image)) 2)) - 0))) + (square-size (min (image-width input-image) (image-height input-image))) + (x-offset (if (> (image-width input-image) (image-height input-image)) + (round (/ (- (image-width input-image) (image-height input-image)) 2)) + 0))) (copy-image input-image button-image - x-offset 0 - 0 0 - square-size square-size - :resize t :resample t - :dest-width *button-size* :dest-height *button-size*) + x-offset 0 + 0 0 + square-size square-size + :resize t :resample t + :dest-width *button-size* :dest-height *button-size*) (when keyword (let ((type-store-image (store-image-with-name (format nil "type-~(~A~)" keyword)))) - (unless type-store-image - (error "can't find type image for keyword ~A" keyword)) - (with-store-image (type-image type-store-image) - (copy-image type-image button-image - 0 0 - 0 0 - (image-width type-image) (image-height type-image))))) + (unless type-store-image + (error "can't find type image for keyword ~A" keyword)) + (with-store-image (type-image type-store-image) + (copy-image type-image button-image + 0 0 + 0 0 + (image-width type-image) (image-height type-image))))) (with-store-image (mask-image (store-image-with-name "button-mask")) - #-(or) ;; notyet (let ((color (parse-color background-color :image mask-image)) - (white (parse-color "ffffff" :image mask-image))) - (do-pixels (mask-image) - (if (eql (ldb (byte 24 0) (raw-pixel)) white) - (setf (raw-pixel) color)))) + (white (parse-color "ffffff" :image mask-image))) + (do-pixels (mask-image) + (when t (eql (ldb (byte 24 0) (raw-pixel)) white) + (setf (raw-pixel) color)))) (copy-image mask-image button-image - 0 0 - 0 0 - *button-size* *button-size*)) + 0 0 + 0 0 + *button-size* *button-size*)) button-image)) (define-imageproc-handler center-thumbnail (input-image width height) Modified: branches/trunk-reorg/projects/quickhoney/src/tags.lisp ============================================================================== --- branches/trunk-reorg/projects/quickhoney/src/tags.lisp (original) +++ branches/trunk-reorg/projects/quickhoney/src/tags.lisp Wed Feb 13 15:22:21 2008 @@ -2,6 +2,8 @@ (define-bknr-tag version-and-last-change (&rest args) (format *debug-io* "hello world: ~A~%" args) - (html "v1.1 | updated " (:princ-safe (string-downcase - (substitute #\Space #\- - (format-date-time (last-image-upload-timestamp) :vms-style t :show-time nil)))))) \ No newline at end of file + (html "v1.1 | updated " + (:princ-safe (string-downcase + (substitute #\Space #\- + (format-date-time (last-image-upload-timestamp) + :vms-style t :show-time nil)))))) \ No newline at end of file Modified: branches/trunk-reorg/xhtmlgen/xhtmlgen.lisp ============================================================================== --- branches/trunk-reorg/xhtmlgen/xhtmlgen.lisp (original) +++ branches/trunk-reorg/xhtmlgen/xhtmlgen.lisp Wed Feb 13 15:22:21 2008 @@ -129,6 +129,8 @@ (defun emit-without-quoting (str) ;; das ist fuer WPDISPLAY + (format t "emit-without-quoting does not work~%") + #+(or) (let ((s (cxml::chained-handler *html-sink*))) (cxml::maybe-close-tag s) (map nil (lambda (c) (cxml::write-rune c s)) str))) From ksprotte at common-lisp.net Thu Feb 14 05:56:36 2008 From: ksprotte at common-lisp.net (ksprotte at common-lisp.net) Date: Thu, 14 Feb 2008 00:56:36 -0500 (EST) Subject: [bknr-cvs] r2489 - branches/trunk-reorg/projects/bos/m2 Message-ID: <20080214055636.4EE5816054@common-lisp.net> Author: ksprotte Date: Thu Feb 14 00:56:35 2008 New Revision: 2489 Modified: branches/trunk-reorg/projects/bos/m2/bos.m2.asd Log: in bos.m2.asd: m2.lisp depends-on on geometry dont know why this never became apparent earlier Modified: branches/trunk-reorg/projects/bos/m2/bos.m2.asd ============================================================================== --- branches/trunk-reorg/projects/bos/m2/bos.m2.asd (original) +++ branches/trunk-reorg/projects/bos/m2/bos.m2.asd Thu Feb 14 00:56:35 2008 @@ -15,7 +15,8 @@ "utils" "make-certificate" "mail-generator" - "geo-utm")) + "geo-utm" + "geometry")) (:file "contract-expiry" :depends-on ("m2")) (:file "allocation" :depends-on ("m2")) (:file "allocation-cache" :depends-on ("packages" "geometry")) From hhubner at common-lisp.net Thu Feb 14 08:10:52 2008 From: hhubner at common-lisp.net (hhubner at common-lisp.net) Date: Thu, 14 Feb 2008 03:10:52 -0500 (EST) Subject: [bknr-cvs] r2490 - branches/trunk-reorg/projects/quickhoney/src Message-ID: <20080214081052.6264C5B074@common-lisp.net> Author: hhubner Date: Thu Feb 14 03:10:49 2008 New Revision: 2490 Modified: branches/trunk-reorg/projects/quickhoney/src/imageproc.lisp Log: Fix bug that was not a bug Modified: branches/trunk-reorg/projects/quickhoney/src/imageproc.lisp ============================================================================== --- branches/trunk-reorg/projects/quickhoney/src/imageproc.lisp (original) +++ branches/trunk-reorg/projects/quickhoney/src/imageproc.lisp Thu Feb 14 03:10:49 2008 @@ -27,8 +27,8 @@ (let ((color (parse-color background-color :image mask-image)) (white (parse-color "ffffff" :image mask-image))) (do-pixels (mask-image) - (when t (eql (ldb (byte 24 0) (raw-pixel)) white) - (setf (raw-pixel) color)))) + (when (eql (ldb (byte 24 0) (raw-pixel)) white) + (setf (raw-pixel) color)))) (copy-image mask-image button-image 0 0 0 0 From hhubner at common-lisp.net Thu Feb 14 09:02:24 2008 From: hhubner at common-lisp.net (hhubner at common-lisp.net) Date: Thu, 14 Feb 2008 04:02:24 -0500 (EST) Subject: [bknr-cvs] r2491 - in branches/trunk-reorg/thirdparty: slime uffi-1.6.0/src Message-ID: <20080214090224.0D63B4083@common-lisp.net> Author: hhubner Date: Thu Feb 14 04:02:22 2008 New Revision: 2491 Modified: branches/trunk-reorg/thirdparty/slime/swank.lisp branches/trunk-reorg/thirdparty/uffi-1.6.0/src/primitives.lisp Log: Fixes for thirdparty packages to make quickhoney run on CCL (and it does!): UFFI: Support pointer-to-pointer in structures SLIME: Fix Marco's package deletion fix again Modified: branches/trunk-reorg/thirdparty/slime/swank.lisp ============================================================================== --- branches/trunk-reorg/thirdparty/slime/swank.lisp (original) +++ branches/trunk-reorg/thirdparty/slime/swank.lisp Thu Feb 14 04:02:22 2008 @@ -82,9 +82,12 @@ "Abbreviate dotted package names to their last component if T.") (defvar *swank-io-package* - (let ((package (make-package :swank-io-package :use '()))) - (import '(nil t quote) package) - package)) + (progn + (when (find-package :swank-io-package) + (delete-package :swank-io-package)) + (let ((package (make-package :swank-io-package :use '()))) + (import '(nil t quote) package) + package))) (defconstant default-server-port 4005 "The default TCP port for the server (when started manually).") Modified: branches/trunk-reorg/thirdparty/uffi-1.6.0/src/primitives.lisp ============================================================================== --- branches/trunk-reorg/thirdparty/uffi-1.6.0/src/primitives.lisp (original) +++ branches/trunk-reorg/thirdparty/uffi-1.6.0/src/primitives.lisp Thu Feb 14 04:02:22 2008 @@ -286,7 +286,10 @@ #+openmcl ((eq (car result) :address) (if (eq context :struct) - (append '(:*) (cdr result)) + (append '(:*) (if (listp (cadr result)) + ;; hack to make pointers to pointers work + (list (convert-from-uffi-type (cadr result) context)) + (cdr result))) :address)) #+digitool ((and (eq (car result) :pointer) (eq context :allocation) :pointer)) From hhubner at common-lisp.net Thu Feb 14 12:12:34 2008 From: hhubner at common-lisp.net (hhubner at common-lisp.net) Date: Thu, 14 Feb 2008 07:12:34 -0500 (EST) Subject: [bknr-cvs] r2492 - branches/trunk-reorg/bknr/web/src/web Message-ID: <20080214121234.D819F6D08E@common-lisp.net> Author: hhubner Date: Thu Feb 14 07:12:33 2008 New Revision: 2492 Modified: branches/trunk-reorg/bknr/web/src/web/handlers.lisp Log: Fix with-bknr-page Modified: branches/trunk-reorg/bknr/web/src/web/handlers.lisp ============================================================================== --- branches/trunk-reorg/bknr/web/src/web/handlers.lisp (original) +++ branches/trunk-reorg/bknr/web/src/web/handlers.lisp Thu Feb 14 07:12:33 2008 @@ -534,7 +534,8 @@ (setf (return-code) response) (handler-case (let ((body (with-output-to-string (*html-stream*) - (website-show-page *website* fn title)))) + (let ((*html-sink* (cxml:make-character-stream-sink *html-stream* :canonical nil :indentation 3))) + (website-show-page *website* fn title))))) (with-http-response (:content-type "text/html; charset=UTF-8" :response response) (with-http-body () (princ body *html-stream*)))) From ksprotte at common-lisp.net Thu Feb 14 12:23:15 2008 From: ksprotte at common-lisp.net (ksprotte at common-lisp.net) Date: Thu, 14 Feb 2008 07:23:15 -0500 (EST) Subject: [bknr-cvs] r2493 - branches/trunk-reorg/projects/hello-web/src Message-ID: <20080214122315.68D102F04E@common-lisp.net> Author: ksprotte Date: Thu Feb 14 07:23:14 2008 New Revision: 2493 Modified: branches/trunk-reorg/projects/hello-web/src/config.lisp branches/trunk-reorg/projects/hello-web/src/hello-web.asd branches/trunk-reorg/projects/hello-web/src/init.lisp branches/trunk-reorg/projects/hello-web/src/packages.lisp branches/trunk-reorg/projects/hello-web/src/webserver.lisp Log: ported hello-web for trunk-reorg Modified: branches/trunk-reorg/projects/hello-web/src/config.lisp ============================================================================== --- branches/trunk-reorg/projects/hello-web/src/config.lisp (original) +++ branches/trunk-reorg/projects/hello-web/src/config.lisp Thu Feb 14 07:23:14 2008 @@ -3,10 +3,15 @@ ;; URL f?r BASE HREFs (defparameter *website-url* "http://hello-web.bknr.net") -(defparameter *root-directory* #p"home:bknr-svn/projects/hello-web/") +(defparameter *root-directory* + (let ((system-path (asdf:component-pathname (asdf:find-system :hello-web)))) + (truename + (merge-pathnames (make-pathname :directory '(:relative :up) :defaults system-path) + system-path)))) (defparameter *store-directory* (merge-pathnames #p"datastore/" *root-directory*)) (defparameter *website-directory* (merge-pathnames #p"website/" *root-directory*)) -(defparameter *webserver-port* 8080) \ No newline at end of file +(defparameter *webserver-port* 8080) +(defvar *webserver* nil) Modified: branches/trunk-reorg/projects/hello-web/src/hello-web.asd ============================================================================== --- branches/trunk-reorg/projects/hello-web/src/hello-web.asd (original) +++ branches/trunk-reorg/projects/hello-web/src/hello-web.asd Thu Feb 14 07:23:14 2008 @@ -17,8 +17,7 @@ :long-description "" :depends-on (:cl-interpol - :cl-ppcre - :aserve + :cl-ppcre :cxml :bknr-modules) Modified: branches/trunk-reorg/projects/hello-web/src/init.lisp ============================================================================== --- branches/trunk-reorg/projects/hello-web/src/init.lisp (original) +++ branches/trunk-reorg/projects/hello-web/src/init.lisp Thu Feb 14 07:23:14 2008 @@ -1,17 +1,29 @@ (in-package :hello-web) -(defun startup () +(defun startup (&key debug) (when *store* (close-store)) + ;; XXX hack hack hack + (mapcar #'cl-gd::load-foreign-library + '("/usr/lib/libcrypto.so" + "/usr/lib/libssl.so" + "/usr/local/lib/libgd.so" + "/home/hans/bknr-svn/thirdparty/cl-gd-0.5.6/cl-gd-glue.so")) + (setf *hunchentoot-default-external-format* (flex:make-external-format :utf-8 :eol-style :lf)) (make-instance 'store :directory *store-directory* :subsystems (list (make-instance 'store-object-subsystem) (make-instance 'blob-subsystem :n-blobs-per-directory 1000))) (unless (find-user "anonymous") - (make-user "anonymous") ; used for all anonymous sessions + (make-user "anonymous") ; used for all anonymous sessions (make-user "admin" :password "admin" :full-name "Administrator" :flags '(:admin)) - (import-image "bknr-logo.png" :keywords '(:banner :bknr)) + (import-image (merge-pathnames #p"src/bknr-logo.png" hello-web.config:*root-directory*) + :keywords '(:banner :bknr)) (make-rss-channel "default" "BKNR Hello Web" "default RSS channel of the BKNR hello web site" *website-url*)) - (publish-hello-web)) + (publish-hello-web) + (setq hunchentoot:*catch-errors-p* (not debug)) + (when *webserver* + (hunchentoot:stop-server *webserver*)) + (setq *webserver* (hunchentoot:start-server :port *webserver-port*))) Modified: branches/trunk-reorg/projects/hello-web/src/packages.lisp ============================================================================== --- branches/trunk-reorg/projects/hello-web/src/packages.lisp (original) +++ branches/trunk-reorg/projects/hello-web/src/packages.lisp Thu Feb 14 07:23:14 2008 @@ -6,17 +6,17 @@ (:export #:*website-url* #:*website-directory* #:*webserver-port* - #:*store-directory*)) + #:*webserver* + #:*store-directory* + #:*root-directory*)) (defpackage :hello-web.tags (:use :cl :cl-user - :ext :bknr.web :xhtml-generator :hello-web.config) - (:shadowing-import-from :cl-interpol #:quote-meta-chars) - (:shadowing-import-from :acl-compat.mp #:process-kill #:process-wait) + (:shadowing-import-from :cl-interpol #:quote-meta-chars) (:export #:hello)) (defpackage :hello-web.imageproc @@ -31,7 +31,6 @@ (defpackage :hello-web (:use :cl :cl-user - :ext :cl-interpol :cl-ppcre :bknr.utils Modified: branches/trunk-reorg/projects/hello-web/src/webserver.lisp ============================================================================== --- branches/trunk-reorg/projects/hello-web/src/webserver.lisp (original) +++ branches/trunk-reorg/projects/hello-web/src/webserver.lisp Thu Feb 14 07:23:14 2008 @@ -7,29 +7,27 @@ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -(defun publish-hello-web (&key (port *webserver-port*) (listeners 20)) - +(defun publish-hello-web () (make-instance 'website :name "Hello Web CMS" :handler-definitions `(("/hello-object" hello-object-handler) ("/" redirect-handler - :prefix "/" :to "/index") + :prefix "/" :to "/index") ("/rss" rss-handler) ("/" template-handler - :prefix "/" - :destination ,(namestring (merge-pathnames #p"templates/" *website-directory*)) - :command-packages ((:hello-web . :hello-web.tags) - (:bknr . :bknr.web) - (:menu . :bknr.site-menu))) + :prefix "/" + :destination ,(namestring (merge-pathnames #p"templates/" *website-directory*)) + :command-packages (("http://hello-web.bknr.net" . :hello-web.tags) + ("http://bknr.net" . :bknr.web))) + images + user ("/static" directory-handler - :destination ,(unix-namestring (merge-pathnames #p"static/" *website-directory*)))) - :modules '(images user) + :destination ,(namestring (merge-pathnames #p"static/" *website-directory*)))) :admin-navigation '(("user" . "/user/") ("images" . "/edit-images") ("import" . "/import") ("logout" . "/logout")) :authorizer (make-instance 'bknr-authorizer) :style-sheet-urls '("/static/styles.css") - :javascript-urls '("/static/javascript.js")) + :javascript-urls '("/static/javascript.js"))) - (start :port port :listeners listeners)) From ksprotte at common-lisp.net Thu Feb 14 12:25:24 2008 From: ksprotte at common-lisp.net (ksprotte at common-lisp.net) Date: Thu, 14 Feb 2008 07:25:24 -0500 (EST) Subject: [bknr-cvs] r2494 - branches/trunk-reorg Message-ID: <20080214122524.9B6285C180@common-lisp.net> Author: ksprotte Date: Thu Feb 14 07:25:23 2008 New Revision: 2494 Modified: branches/trunk-reorg/ (props changed) Log: svn property ignore asd dir on the rootlevel From hhubner at common-lisp.net Thu Feb 14 14:13:32 2008 From: hhubner at common-lisp.net (hhubner at common-lisp.net) Date: Thu, 14 Feb 2008 09:13:32 -0500 (EST) Subject: [bknr-cvs] r2495 - branches/trunk-reorg/projects/quickhoney/src Message-ID: <20080214141332.E8495691A3@common-lisp.net> Author: hhubner Date: Thu Feb 14 09:13:32 2008 New Revision: 2495 Modified: branches/trunk-reorg/projects/quickhoney/src/webserver.lisp Log: Fix handler order so that /image-detail template is seen before /image prefix handler Modified: branches/trunk-reorg/projects/quickhoney/src/webserver.lisp ============================================================================== --- branches/trunk-reorg/projects/quickhoney/src/webserver.lisp (original) +++ branches/trunk-reorg/projects/quickhoney/src/webserver.lisp Thu Feb 14 09:13:32 2008 @@ -33,17 +33,17 @@ ("/admin" admin-handler) ("/" redirect-handler :to "/frontpage") + ("/" template-handler + :destination ,(namestring (merge-pathnames "templates/" *website-directory*)) + :command-packages (("http://quickhoney.com/" . :quickhoney.tags) + ("http://bknr.net/" . :bknr.web))) user images ("/static" directory-handler :destination ,(merge-pathnames #p"static/" *website-directory*)) ("/favicon.ico" file-handler :destination ,(merge-pathnames #p"static/favicon.ico" *website-directory*) - :content-type "application/x-icon") - ("/" template-handler - :destination ,(namestring (merge-pathnames "templates/" *website-directory*)) - :command-packages (("http://quickhoney.com/" . :quickhoney.tags) - ("http://bknr.net/" . :bknr.web)))) + :content-type "application/x-icon")) :admin-navigation '(("user" . "/user/") ("images" . "/edit-images") ("import" . "/import") From ksprotte at common-lisp.net Thu Feb 14 15:42:55 2008 From: ksprotte at common-lisp.net (ksprotte at common-lisp.net) Date: Thu, 14 Feb 2008 10:42:55 -0500 (EST) Subject: [bknr-cvs] r2496 - branches/trunk-reorg/bknr/web/src/web Message-ID: <20080214154255.8F218690E5@common-lisp.net> Author: ksprotte Date: Thu Feb 14 10:42:55 2008 New Revision: 2496 Modified: branches/trunk-reorg/bknr/web/src/web/handlers.lisp branches/trunk-reorg/bknr/web/src/web/web-macros.lisp Log: tweaked with-http-body and website-show-error-page Modified: branches/trunk-reorg/bknr/web/src/web/handlers.lisp ============================================================================== --- branches/trunk-reorg/bknr/web/src/web/handlers.lisp (original) +++ branches/trunk-reorg/bknr/web/src/web/handlers.lisp Thu Feb 14 10:42:55 2008 @@ -499,10 +499,9 @@ (ensure-directories-exist spool-dir) spool-dir)) -(defmethod website-show-page ((website website) fn title) - (html - (princ "" *html-stream*) - (princ #\Newline *html-stream*) +(defmethod website-show-page ((website website) fn title) + (html + (:html (:head (header :title title)) @@ -515,34 +514,11 @@ (funcall fn) (session-info))))) -(defmethod website-show-error-page ((website website) error) - (if (website-template-handler website) - (send-error-response (website-template-handler website) (princ-to-string error)) - (html - (princ "" *html-stream*) - (princ #\Newline *html-stream*) - (:html - (:head - (header :title "Error processing your request")) - ((:body :class "cms") - (:h1 "Error processing your request") - (:p "While processing your request, an error occured:") - ((:div :class "error") - (:princ-safe error))))))) - (defun show-page-with-error-handlers (fn &key (response +http-ok+) title) (setf (return-code) response) - (handler-case - (let ((body (with-output-to-string (*html-stream*) - (let ((*html-sink* (cxml:make-character-stream-sink *html-stream* :canonical nil :indentation 3))) - (website-show-page *website* fn title))))) - (with-http-response (:content-type "text/html; charset=UTF-8" :response response) - (with-http-body () - (princ body *html-stream*)))) - (serious-condition (c) - (with-http-response (:content-type "text/html; charset=UTF-8" :response +http-internal-server-error+) - (with-http-body () - (website-show-error-page *website* c)))))) + (with-http-response (:content-type "text/html; charset=UTF-8" :response response) + (with-http-body () + (website-show-page *website* fn title)))) (defmacro with-bknr-page ((&rest args) &body body) `(show-page-with-error-handlers (lambda () (html , at body)) , at args)) Modified: branches/trunk-reorg/bknr/web/src/web/web-macros.lisp ============================================================================== --- branches/trunk-reorg/bknr/web/src/web/web-macros.lisp (original) +++ branches/trunk-reorg/bknr/web/src/web/web-macros.lisp Thu Feb 14 10:42:55 2008 @@ -54,7 +54,14 @@ (defmacro with-http-body ((&key external-format) &body body) `(with-output-to-string (*html-stream*) - , at body)) + (let ((*html-sink* (cxml:make-character-stream-sink *html-stream* :canonical nil :indentation 3))) + (sax:start-document *html-sink*) + (sax:start-dtd *html-sink* + "html" + "-//W3C//DTD XHTML 1.0 Transitional//EN" + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd") + , at body + (sax:end-document *html-sink*)))) (defmacro with-image-from-uri ((image-variable prefix) &rest body) `(multiple-value-bind From hhubner at common-lisp.net Thu Feb 14 16:11:05 2008 From: hhubner at common-lisp.net (hhubner at common-lisp.net) Date: Thu, 14 Feb 2008 11:11:05 -0500 (EST) Subject: [bknr-cvs] r2497 - in branches/trunk-reorg: bknr/datastore/src/utils bknr/web/src/images bknr/web/src/sysclasses bknr/web/src/web xhtmlgen Message-ID: <20080214161105.B8A305C189@common-lisp.net> Author: hhubner Date: Thu Feb 14 11:11:03 2008 New Revision: 2497 Modified: branches/trunk-reorg/bknr/datastore/src/utils/crypt-md5.lisp branches/trunk-reorg/bknr/web/src/images/image-handlers.lisp branches/trunk-reorg/bknr/web/src/images/imageproc-handler.lisp branches/trunk-reorg/bknr/web/src/sysclasses/user.lisp branches/trunk-reorg/bknr/web/src/web/authorizer.lisp branches/trunk-reorg/bknr/web/src/web/handlers.lisp branches/trunk-reorg/bknr/web/src/web/web-macros.lisp branches/trunk-reorg/xhtmlgen/package.lisp branches/trunk-reorg/xhtmlgen/xhtmlgen.lisp Log: if-modified-since fixed for images password checking fixed login works again, needs more testing xhtmlgen fixed, new macro with-xhtml to set up doctype Modified: branches/trunk-reorg/bknr/datastore/src/utils/crypt-md5.lisp ============================================================================== --- branches/trunk-reorg/bknr/datastore/src/utils/crypt-md5.lisp (original) +++ branches/trunk-reorg/bknr/datastore/src/utils/crypt-md5.lisp Thu Feb 14 11:11:03 2008 @@ -66,7 +66,7 @@ (unless (string-equal (subseq saltpw 0 3) "$1$") (error "not a md5 password ~a" saltpw)) (let ((salt (extract-salt saltpw))) - (string-equal (crypt-md5 password salt) saltpw))) + (string-equal (crypt-md5 (coerce password 'simple-string) salt) saltpw))) ;; 0 6 12 (4) ;; 1 7 13 (4) Modified: branches/trunk-reorg/bknr/web/src/images/image-handlers.lisp ============================================================================== --- branches/trunk-reorg/bknr/web/src/images/image-handlers.lisp (original) +++ branches/trunk-reorg/bknr/web/src/images/image-handlers.lisp Thu Feb 14 11:11:03 2008 @@ -34,7 +34,8 @@ (defmethod object-handler-get-object ((handler image-handler)) (let ((id-or-name (parse-url))) - (find-store-object id-or-name :class 'store-image :query-function #'store-image-with-name))) + (when id-or-name + (find-store-object id-or-name :class 'store-image :query-function #'store-image-with-name)))) (defclass browse-image-handler (image-handler) ()) Modified: branches/trunk-reorg/bknr/web/src/images/imageproc-handler.lisp ============================================================================== --- branches/trunk-reorg/bknr/web/src/images/imageproc-handler.lisp (original) +++ branches/trunk-reorg/bknr/web/src/images/imageproc-handler.lisp Thu Feb 14 11:11:03 2008 @@ -167,21 +167,8 @@ (error-404)) (defmethod handle-object ((page-handler imageproc-handler) image) - (format t "if-modfied-since not implemented for hunchentoot~%") (with-http-response (:content-type (image-content-type (image-type-keyword image))) - (with-http-body () - (imageproc image (cdr (decoded-handler-path page-handler))))) - #+(or) - (with-http-response (:content-type (image-content-type (image-type-keyword image))) - (let ((ims (header-in :if-modified-since)) - (changed-time (blob-timestamp image))) - (setf (header-out :last-modified) (rfc-1123-date changed-time)) - (if (and ims - (<= changed-time (date-to-universal-time ims))) - (progn - (setf (return-code) +http-not-modified+) - (format t "; image ~A not changed~%" image) - (with-http-body ())) - (with-http-body () - (imageproc image (cdr (decoded-handler-path page-handler)))))))) + (handle-if-modified-since (blob-timestamp image)) + (setf (header-out "Last-Modified") (rfc-1123-date (blob-timestamp image))) + (imageproc image (cdr (decoded-handler-path page-handler))))) Modified: branches/trunk-reorg/bknr/web/src/sysclasses/user.lisp ============================================================================== --- branches/trunk-reorg/bknr/web/src/sysclasses/user.lisp (original) +++ branches/trunk-reorg/bknr/web/src/sysclasses/user.lisp Thu Feb 14 11:11:03 2008 @@ -110,10 +110,11 @@ (defmethod verify-password ((user user) password) (when password (let ((upw (user-password user))) - (if (string-equal "$1$" (subseq upw 0 3)) + (if (equal "$1$" (and (> (length upw) 3) (subseq upw 0 3))) (verify-md5-password password (user-password user)) - (equal upw - (crypt password (subseq upw 0 +salt-length+))))))) + (when (> (length upw) +salt-length+) + (equal upw + (crypt password (subseq upw 0 +salt-length+)))))))) (defmethod user-disabled ((user user)) (user-has-flag user :disabled)) Modified: branches/trunk-reorg/bknr/web/src/web/authorizer.lisp ============================================================================== --- branches/trunk-reorg/bknr/web/src/web/authorizer.lisp (original) +++ branches/trunk-reorg/bknr/web/src/web/authorizer.lisp Thu Feb 14 11:11:03 2008 @@ -21,15 +21,24 @@ "check whether the request has a valid session id in either the bknr-sessionid cookie or query parameter" (session-value 'bknr-session)) -(defmethod find-user-from-request-parameters ((authorizer bknr-authorizer)) +(define-condition login-failure (serious-condition) + () + (:report (lambda (c s) + (declare (ignore c)) + (format s "Login failed")))) + +(defun find-user-from-request-parameters () (with-query-params (__username __password) - (when (and __username (not (equal __username ""))) - (let ((user (find-user __username))) - (when user - (if (and (not (user-disabled user)) + (unless (and __username __password + (not (equal __username "")) + (not (equal __password ""))) + (return-from find-user-from-request-parameters nil)) + (let ((user (find-user __username))) + (when (and user + (not (user-disabled user)) (verify-password user __password)) - user - (warn "login failure for user ~a~%" user))))))) + (return-from find-user-from-request-parameters user))) + (error 'login-failure))) (defmethod authorize ((authorizer bknr-authorizer)) ;; Catch any errors that occur during request body processing Modified: branches/trunk-reorg/bknr/web/src/web/handlers.lisp ============================================================================== --- branches/trunk-reorg/bknr/web/src/web/handlers.lisp (original) +++ branches/trunk-reorg/bknr/web/src/web/handlers.lisp Thu Feb 14 11:11:03 2008 @@ -221,10 +221,6 @@ t))) (defmethod invoke-handler ((handler page-handler)) - (start-session) - (unless (session-value 'bknr-session) - (setf (session-value 'bknr-session) - (make-instance 'bknr-session :user (find-user "anonymous")))) (let* ((*website* (page-handler-site handler)) (*req-var-hash* (or *req-var-hash* (make-hash-table)))) @@ -255,10 +251,28 @@ (defvar *handlers* nil) +(defun ensure-bknr-session () + "Ensure that the BKNR-SESSION session variable is set and that it +belongs to the user that is specified in the request." + (let ((request-user (find-user-from-request-parameters))) + (unless (and (session-value 'bknr-session) + (equal (bknr-session-user) + (find-user-from-request-parameters))) + (setf (session-value 'bknr-session) + (make-instance 'bknr-session :user (or request-user + (find-user "anonymous"))))))) + (defun bknr-dispatch (request) (declare (ignore request)) - (when-let ((handler (find-if #'handler-matches (website-handlers *website*)))) - (curry #'invoke-handler handler))) + (let ((handler (find-if #'handler-matches (website-handlers *website*)))) + (cond + (handler + (start-session) + (ensure-bknr-session) + (when (authorize (website-authorizer *website*)) + (curry #'invoke-handler handler))) + (t + 'error-404)))) (defmethod publish-handler ((website website) (handler page-handler)) (setf *handlers* (append *handlers* (list handler)))) @@ -309,6 +323,12 @@ (defclass prefix-handler (page-handler) ()) +#+(or) +(defmethod initialize-instance :after ((handler prefix-handler) &key) + (unless (eql #\/ (aref (page-handler-prefix handler) + (1- (length (page-handler-prefix handler))))) + (warn "prefix handler ~A does not have prefix ending with / - may match unexpectedly" handler))) + (defmethod handler-matches ((handler prefix-handler)) (and (>= (length (script-name)) (length (page-handler-prefix handler))) Modified: branches/trunk-reorg/bknr/web/src/web/web-macros.lisp ============================================================================== --- branches/trunk-reorg/bknr/web/src/web/web-macros.lisp (original) +++ branches/trunk-reorg/bknr/web/src/web/web-macros.lisp Thu Feb 14 11:11:03 2008 @@ -24,10 +24,10 @@ (let ((vars (loop for param in params when (and (symbolp param) (not (null param))) - collect (list param `(get-parameter ,(symbol-name param))) + collect (list param `(get-parameter ,(string-downcase (symbol-name param)))) when (consp param) collect (list (car param) - `(or (get-parameter ,(symbol-name (car param))) + `(or (get-parameter ,(string-downcase (symbol-name (car param)))) ,(second param)))))) (if vars `(let ,vars @@ -54,14 +54,8 @@ (defmacro with-http-body ((&key external-format) &body body) `(with-output-to-string (*html-stream*) - (let ((*html-sink* (cxml:make-character-stream-sink *html-stream* :canonical nil :indentation 3))) - (sax:start-document *html-sink*) - (sax:start-dtd *html-sink* - "html" - "-//W3C//DTD XHTML 1.0 Transitional//EN" - "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd") - , at body - (sax:end-document *html-sink*)))) + (with-xhtml (*html-stream*) + , at body))) (defmacro with-image-from-uri ((image-variable prefix) &rest body) `(multiple-value-bind Modified: branches/trunk-reorg/xhtmlgen/package.lisp ============================================================================== --- branches/trunk-reorg/xhtmlgen/package.lisp (original) +++ branches/trunk-reorg/xhtmlgen/package.lisp Thu Feb 14 11:11:03 2008 @@ -4,6 +4,6 @@ (:use :common-lisp) (:export #:html #:html-stream - #:*html-sink* - #:set-string-encoding)) + #:with-xhtml + #:*html-sink*)) Modified: branches/trunk-reorg/xhtmlgen/xhtmlgen.lisp ============================================================================== --- branches/trunk-reorg/xhtmlgen/xhtmlgen.lisp (original) +++ branches/trunk-reorg/xhtmlgen/xhtmlgen.lisp Thu Feb 14 11:11:03 2008 @@ -53,13 +53,26 @@ (,body) (let ((*html-sink* (cxml:make-character-stream-sink *standard-output* :canonical nil :indentation 3))) (,body) - (sax:end-document *html-sink*)))))) + (sax:end-document *html-sink*)))))) (defmacro html-stream (stream &rest forms &environment env) `(let ((*html-sink* (cxml:make-character-stream-sink ,stream :canonical nil :indentation 3))) ,(process-html-forms forms env) (sax:end-document *html-sink*))) +(defmacro with-xhtml ((&optional stream &key (indentation 3)) &body body) + `(let ((*html-sink* (cxml:make-character-stream-sink ,stream :canonical nil :indentation ,indentation))) + (sax:start-document *html-sink*) + (sax:start-dtd *html-sink* + "html" + "-//W3C//DTD XHTML 1.0 Transitional//EN" + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd") + (sax:end-dtd *html-sink*) + (multiple-value-prog1 + (html + , at body) + (sax:end-document *html-sink*)))) + (defun get-process (form) (let ((ent (gethash form *html-process-table*))) (unless ent From hhubner at common-lisp.net Fri Feb 15 06:42:31 2008 From: hhubner at common-lisp.net (hhubner at common-lisp.net) Date: Fri, 15 Feb 2008 01:42:31 -0500 (EST) Subject: [bknr-cvs] r2498 - branches/bos/projects/bos/web Message-ID: <20080215064231.A524C5F061@common-lisp.net> Author: hhubner Date: Fri Feb 15 01:42:26 2008 New Revision: 2498 Modified: branches/bos/projects/bos/web/sponsor-handlers.lisp Log: merge 2462, fix password setting through CMS Modified: branches/bos/projects/bos/web/sponsor-handlers.lisp ============================================================================== --- branches/bos/projects/bos/web/sponsor-handlers.lisp (original) +++ branches/bos/projects/bos/web/sponsor-handlers.lisp Fri Feb 15 01:42:26 2008 @@ -181,9 +181,7 @@ (let ((field-value (query-param req (string-downcase (symbol-name field-name))))) (when (and field-value (not (equal field-value (slot-value sponsor field-name)))) - (if (eq field-name 'password) - (set-user-password sponsor field-value) - (change-slot-values sponsor field-name field-value)) + (change-slot-values sponsor field-name field-value) (setf changed t) (html (:p "Changed " (:princ-safe (string-downcase (symbol-name field-name)))))))) (dolist (contract (sponsor-contracts sponsor)) From ksprotte at common-lisp.net Fri Feb 15 11:51:11 2008 From: ksprotte at common-lisp.net (ksprotte at common-lisp.net) Date: Fri, 15 Feb 2008 06:51:11 -0500 (EST) Subject: [bknr-cvs] r2499 - in branches/trunk-reorg/projects/bos: m2 web Message-ID: <20080215115111.14AC54F052@common-lisp.net> Author: ksprotte Date: Fri Feb 15 06:51:09 2008 New Revision: 2499 Modified: branches/trunk-reorg/projects/bos/m2/geometry.lisp branches/trunk-reorg/projects/bos/m2/make-certificate.lisp branches/trunk-reorg/projects/bos/m2/packages.lisp branches/trunk-reorg/projects/bos/web/tags.lisp Log: manually merged over some chs from bos branch Modified: branches/trunk-reorg/projects/bos/m2/geometry.lisp ============================================================================== --- branches/trunk-reorg/projects/bos/m2/geometry.lisp (original) +++ branches/trunk-reorg/projects/bos/m2/geometry.lisp Fri Feb 15 06:51:09 2008 @@ -214,3 +214,56 @@ (traverse boundary-point initial-direction) (nreverse polygon)))) + +;;; formatting +;; proposed by Michael Weber on alexandria-devel +(defun format-mixed-radix-number (stream number radix-list format-list + &key lsb-first leading-zeros + (trailing-zeros t)) + "Prints NUMBER to STREAM in mixed-radix RADIX. +representation-LIST is a list of radixes, least-significant first. +FORMAT-LIST is a list of format directives, one for each digit. +When LSB-FIRST is nil (default), print most-significant digit first, +otherwise least-significant digit first. +When LEADING-ZEROS and TRAILING-ZEROS are nil, leading and +trailing zero digits are not printed, respectively. \(default: remove +leading zeros, keep trailing zeros)" + (let ((format-pairs + (loop with digit and fraction + initially (setf (values number fraction) + (truncate number)) + for f-list on format-list + and r-list = radix-list then (rest r-list) + collect (list (first f-list) + (cond ((endp r-list) + (shiftf number 0)) + ((rest f-list) + (setf (values number digit) + (truncate number (first r-list))) + digit) + (t number))) + into list + finally (progn + (incf (cadar list) fraction) + (return (nreverse list)))))) + (unless trailing-zeros + (setf format-pairs (member-if #'plusp format-pairs :key + #'second))) + (when lsb-first + (setf format-pairs (nreverse format-pairs))) + (unless leading-zeros + (setf format-pairs (member-if #'plusp format-pairs :key + #'second))) + (format stream "~{~{~@?~}~}" format-pairs))) + + +(defun format-decimal-degree (degree) + (format-mixed-radix-number nil (* 60 60 degree) '(60 60 360) '(" ~,2F??" " ~D?" "~D?"))) + +(defun format-lon-lat (stream lon lat) + (format stream "~A ~:[S~;N~], ~A ~:[W~;E~]" + (format-decimal-degree (abs lat)) + (plusp lat) + (format-decimal-degree (abs lon)) + (plusp lon))) + Modified: branches/trunk-reorg/projects/bos/m2/make-certificate.lisp ============================================================================== --- branches/trunk-reorg/projects/bos/m2/make-certificate.lisp (original) +++ branches/trunk-reorg/projects/bos/m2/make-certificate.lisp Fri Feb 15 06:51:09 2008 @@ -42,8 +42,19 @@ :sponsor-id (sponsor-id sponsor) :master-code (sponsor-master-code sponsor) :sqm-count (length (contract-m2s contract)) - :sqm-ids (with-output-to-string (s) - (loop for group in (group-by (mapcar #'m2-num-string (contract-m2s contract)) *num-coords-per-line*) - do (loop for nums on group - do (princ (car nums) s) - do (princ (if (cdr nums) #\Tab #\Newline) s))))))) + ;; :sqm-ids (with-output-to-string (s) + ;; (loop for group in (group-by (mapcar #'m2-num-string (contract-m2s contract)) *num-coords-per-line*) + ;; do (loop for nums on group + ;; do (princ (car nums) s) + ;; do (princ (if (cdr nums) #\Tab #\Newline) s)))) + ;; should later be called :sqm-coordinates + :sqm-ids + (flet ((format-point (stream x y) + (apply #'geometry:format-lon-lat stream + (geo-utm:utm-x-y-to-lon-lat (+ +nw-utm-x+ x) + (- +nw-utm-y+ y) +utm-zone+ t)))) + (destructuring-bind (left top width height) + (contract-bounding-box contract) + (with-output-to-string (out) + (format-point out left top) (terpri out) + (format-point out (+ left width) (+ top height)) (terpri out))))))) Modified: branches/trunk-reorg/projects/bos/m2/packages.lisp ============================================================================== --- branches/trunk-reorg/projects/bos/m2/packages.lisp (original) +++ branches/trunk-reorg/projects/bos/m2/packages.lisp Fri Feb 15 06:51:09 2008 @@ -9,7 +9,8 @@ #:point-in-polygon-p #:point-in-circle-p #:find-boundary-point - #:region-to-polygon)) + #:region-to-polygon + #:format-lon-lat)) (defpackage :geo-utm (:use :cl) Modified: branches/trunk-reorg/projects/bos/web/tags.lisp ============================================================================== --- branches/trunk-reorg/projects/bos/web/tags.lisp (original) +++ branches/trunk-reorg/projects/bos/web/tags.lisp Fri Feb 15 06:51:09 2008 @@ -167,8 +167,14 @@ (setf (get-template-var :country) (sponsor-country sponsor)) (setf (get-template-var :infotext) (sponsor-info-text sponsor)) (setf (get-template-var :name) (user-full-name sponsor)) - (setf (get-template-var :sqm-x) (format nil "~,3f" (m2-utm-x (first (contract-m2s contract))))) - (setf (get-template-var :sqm-y) (format nil "~,3f" (m2-utm-y (first (contract-m2s contract))))) + (setf (get-template-var :sqm-x) (format nil "~,3f" (m2-utm-x (first (contract-m2s contract))))) + (setf (get-template-var :sqm-y) (format nil "~,3f" (m2-utm-y (first (contract-m2s contract))))) + (setf (get-template-var :geo-coord) (destructuring-bind (left top . ignore) + (contract-bounding-box contract) + (declare (ignore ignore)) + (apply #'geometry:format-lon-lat nil + (geo-utm:utm-x-y-to-lon-lat (+ +nw-utm-x+ left) + (- +nw-utm-y+ top) +utm-zone+ t)))) (setf (get-template-var :numsqm) (format nil "~D" (apply #'+ (mapcar #'(lambda (contract) (length (contract-m2s contract))) (sponsor-contracts sponsor)))))) From ksprotte at common-lisp.net Fri Feb 15 12:21:24 2008 From: ksprotte at common-lisp.net (ksprotte at common-lisp.net) Date: Fri, 15 Feb 2008 07:21:24 -0500 (EST) Subject: [bknr-cvs] r2500 - in branches/bos/projects/bos: payment-website/infosystem payment-website/templates/da payment-website/templates/de payment-website/templates/en web Message-ID: <20080215122124.1F1C32F067@common-lisp.net> Author: ksprotte Date: Fri Feb 15 07:21:20 2008 New Revision: 2500 Modified: branches/bos/projects/bos/payment-website/infosystem/javascript.js branches/bos/projects/bos/payment-website/templates/da/profil.xml branches/bos/projects/bos/payment-website/templates/de/profil.xml branches/bos/projects/bos/payment-website/templates/en/profil.xml branches/bos/projects/bos/web/sponsor-handlers.lisp Log: removed Google Earth links Modified: branches/bos/projects/bos/payment-website/infosystem/javascript.js ============================================================================== --- branches/bos/projects/bos/payment-website/infosystem/javascript.js (original) +++ branches/bos/projects/bos/payment-website/infosystem/javascript.js Fri Feb 15 07:21:20 2008 @@ -397,9 +397,6 @@ + ' m? ' + msg('seit') + ':' + n_profil.contracts[0].date + ' ' - + 'Google Earth View' - + ' ' + ' ' + n_profil['nachricht'] + ''; Modified: branches/bos/projects/bos/payment-website/templates/da/profil.xml ============================================================================== --- branches/bos/projects/bos/payment-website/templates/da/profil.xml (original) +++ branches/bos/projects/bos/payment-website/templates/da/profil.xml Fri Feb 15 07:21:20 2008 @@ -55,8 +55,7 @@ kvardratmeter - til v?rdi af $(numsqm) m? er blevet opk?bt

kordinater: $(geo-coord) -
Your square metres in Google Earth + til v?rdi af $(numsqm) m? er blevet opk?bt

kordinater: $(geo-coord) Modified: branches/bos/projects/bos/payment-website/templates/de/profil.xml ============================================================================== --- branches/bos/projects/bos/payment-website/templates/de/profil.xml (original) +++ branches/bos/projects/bos/payment-website/templates/de/profil.xml Fri Feb 15 07:21:20 2008 @@ -60,8 +60,7 @@ Quadratmeter - Insgesamt $(numsqm) Quadratmeter gekauft
Koordinate: $(geo-coord) -
Ihre Quadratmeter in Google Earth + Insgesamt $(numsqm) Quadratmeter gekauft
Koordinate: $(geo-coord) Modified: branches/bos/projects/bos/payment-website/templates/en/profil.xml ============================================================================== --- branches/bos/projects/bos/payment-website/templates/en/profil.xml (original) +++ branches/bos/projects/bos/payment-website/templates/en/profil.xml Fri Feb 15 07:21:20 2008 @@ -60,8 +60,7 @@ square metres - a total of $(numsqm) m? has been bought
coordinate: $(geo-coord) -
Your square metres in Google Earth + a total of $(numsqm) m? has been bought
coordinate: $(geo-coord) Modified: branches/bos/projects/bos/web/sponsor-handlers.lisp ============================================================================== --- branches/bos/projects/bos/web/sponsor-handlers.lisp (original) +++ branches/bos/projects/bos/web/sponsor-handlers.lisp Fri Feb 15 07:21:20 2008 @@ -160,9 +160,7 @@ (m2-utm-x (first (contract-m2s (first (sponsor-contracts sponsor))))) (m2-utm-y (first (contract-m2s (first (sponsor-contracts sponsor)))))))) (:td (:princ-safe (if (contract-paidp contract) "paid" "not paid"))) - (:td (cmslink (format nil "contract-kml/~A" (store-object-id contract)) "Google Earth") - :br - (cmslink (format nil "cert-regen/~A" (store-object-id contract)) "Regenerate Certificate") + (:td (cmslink (format nil "cert-regen/~A" (store-object-id contract)) "Regenerate Certificate") (when (probe-file (contract-pdf-pathname contract)) (html :br (cmslink (contract-pdf-url contract) "Show Certificate"))) (when (contract-worldpay-trans-id contract) From ksprotte at common-lisp.net Fri Feb 15 12:36:38 2008 From: ksprotte at common-lisp.net (ksprotte at common-lisp.net) Date: Fri, 15 Feb 2008 07:36:38 -0500 (EST) Subject: [bknr-cvs] r2501 - branches/bos/projects/bos/web Message-ID: <20080215123638.7D4CC44052@common-lisp.net> Author: ksprotte Date: Fri Feb 15 07:36:38 2008 New Revision: 2501 Modified: branches/bos/projects/bos/web/sponsor-handlers.lisp Log: fix in sponsor-handlers for changing password by explicitly using SET-USER-PASSWORD Modified: branches/bos/projects/bos/web/sponsor-handlers.lisp ============================================================================== --- branches/bos/projects/bos/web/sponsor-handlers.lisp (original) +++ branches/bos/projects/bos/web/sponsor-handlers.lisp Fri Feb 15 07:36:38 2008 @@ -179,7 +179,9 @@ (let ((field-value (query-param req (string-downcase (symbol-name field-name))))) (when (and field-value (not (equal field-value (slot-value sponsor field-name)))) - (change-slot-values sponsor field-name field-value) + (case field-name + (password (set-user-password sponsor field-value)) + (t (change-slot-values sponsor field-name field-value))) (setf changed t) (html (:p "Changed " (:princ-safe (string-downcase (symbol-name field-name)))))))) (dolist (contract (sponsor-contracts sponsor)) From ksprotte at common-lisp.net Fri Feb 15 12:39:33 2008 From: ksprotte at common-lisp.net (ksprotte at common-lisp.net) Date: Fri, 15 Feb 2008 07:39:33 -0500 (EST) Subject: [bknr-cvs] r2502 - branches/trunk-reorg/projects/bos/web Message-ID: <20080215123933.E287469139@common-lisp.net> Author: ksprotte Date: Fri Feb 15 07:39:33 2008 New Revision: 2502 Modified: branches/trunk-reorg/projects/bos/web/sponsor-handlers.lisp Log: fix in sponsor-handlers for changing password by explicitly using SET-USER-PASSWORD Modified: branches/trunk-reorg/projects/bos/web/sponsor-handlers.lisp ============================================================================== --- branches/trunk-reorg/projects/bos/web/sponsor-handlers.lisp (original) +++ branches/trunk-reorg/projects/bos/web/sponsor-handlers.lisp Fri Feb 15 07:39:33 2008 @@ -181,7 +181,9 @@ (let ((field-value (query-param (string-downcase (symbol-name field-name))))) (when (and field-value (not (equal field-value (slot-value sponsor field-name)))) - (change-slot-values sponsor field-name field-value) + (case field-name + (password (set-user-password sponsor field-value)) + (t (change-slot-values sponsor field-name field-value))) (setf changed t) (html (:p "Changed " (:princ-safe (string-downcase (symbol-name field-name)))))))) (dolist (contract (sponsor-contracts sponsor)) From hhubner at common-lisp.net Fri Feb 15 13:41:20 2008 From: hhubner at common-lisp.net (hhubner at common-lisp.net) Date: Fri, 15 Feb 2008 08:41:20 -0500 (EST) Subject: [bknr-cvs] r2503 - branches/trunk-reorg/bknr/datastore/src/data Message-ID: <20080215134120.D1F216913C@common-lisp.net> Author: hhubner Date: Fri Feb 15 08:41:20 2008 New Revision: 2503 Modified: branches/trunk-reorg/bknr/datastore/src/data/object.lisp Log: Rename and document some things. Modified: branches/trunk-reorg/bknr/datastore/src/data/object.lisp ============================================================================== --- branches/trunk-reorg/bknr/datastore/src/data/object.lisp (original) +++ branches/trunk-reorg/bknr/datastore/src/data/object.lisp Fri Feb 15 08:41:20 2008 @@ -5,8 +5,9 @@ (cl-interpol:enable-interpol-syntax) (defclass store-object-subsystem () - ((id-counter :initform 0 - :accessor id-counter))) + ((next-object-id :initform 0 + :accessor next-object-id + :documentation "Next object ID to assign to a new object"))) (defun store-object-subsystem () (let ((subsystem (find-if (lambda (subsystem) @@ -163,17 +164,16 @@ (anonymous-transaction-transactions *current-transaction*))) (call-next-method))) -(defmethod initialize-instance :after - ((object store-object) &key id &allow-other-keys) +(defmethod initialize-instance :after ((object store-object) &key id &allow-other-keys) (let ((subsystem (store-object-subsystem))) (cond (id ;; during restore, use the given ID - (when (>= id (id-counter subsystem)) - (setf (id-counter subsystem) (1+ id)))) + (when (>= id (next-object-id subsystem)) + (setf (next-object-id subsystem) (1+ id)))) (t ;; normal transaction: assign a new ID - (setf id (id-counter subsystem)) - (incf (id-counter subsystem)) + (setf id (next-object-id subsystem)) + (incf (next-object-id subsystem)) (setf (slot-value object 'id) id))))) (defmethod print-object ((object store-object) stream) @@ -476,9 +476,9 @@ id slot-name (type-of container) (store-object-id container)) (warn "Reference to inexistent object with id ~A from unnamed container, returning NIL." id)) - ;; noch die ID hochzaehlen wenn notwendig - (when (>= id (id-counter (store-object-subsystem))) - (setf (id-counter (store-object-subsystem)) (1+ id))) + ;; Possibly determine new "current object id" + (when (>= id (next-object-id (store-object-subsystem))) + (setf (next-object-id (store-object-subsystem)) (1+ id))) nil) (t (error "Reference to inexistent object with id ~A from slot ~A of object ~A with ID ~A." id slot-name (type-of container) @@ -512,7 +512,7 @@ ;;; check on first instatiation of a class? (dolist (class-name (cons 'store-object (all-store-classes))) (clear-class-indices (find-class class-name))) - (setf (id-counter subsystem) 0) + (setf (next-object-id subsystem) 0) (when (probe-file snapshot) (format *trace-output* "loading snapshot file ~A~%" snapshot) (with-open-file (s snapshot @@ -586,7 +586,7 @@ (execute (make-instance 'transaction :function-symbol 'tx-make-object :args (append (list class-name - :id (id-counter (store-object-subsystem))) + :id (next-object-id (store-object-subsystem))) initargs)))) (defun tx-delete-object (id) From hhubner at common-lisp.net Fri Feb 15 16:33:57 2008 From: hhubner at common-lisp.net (hhubner at common-lisp.net) Date: Fri, 15 Feb 2008 11:33:57 -0500 (EST) Subject: [bknr-cvs] r2504 - in branches/trunk-reorg/projects/quickhoney: src website/static website/templates Message-ID: <20080215163357.8AE8D490A1@common-lisp.net> Author: hhubner Date: Fri Feb 15 11:33:56 2008 New Revision: 2504 Modified: branches/trunk-reorg/projects/quickhoney/src/handlers.lisp branches/trunk-reorg/projects/quickhoney/src/tags.lisp branches/trunk-reorg/projects/quickhoney/website/static/javascript.js branches/trunk-reorg/projects/quickhoney/website/templates/index.xml Log: Fix Javascript handling so that it works with current CXML. Fix direct navigation to category page. Reformats. Modified: branches/trunk-reorg/projects/quickhoney/src/handlers.lisp ============================================================================== --- branches/trunk-reorg/projects/quickhoney/src/handlers.lisp (original) +++ branches/trunk-reorg/projects/quickhoney/src/handlers.lisp Fri Feb 15 11:33:56 2008 @@ -5,13 +5,17 @@ (defclass javascript-handler () ()) +(defvar *js-stream*) + (defmethod handle :around ((handler javascript-handler)) (with-http-response (:content-type "text/html; charset=UTF-8") (no-cache) (with-http-body () - (format *html-stream* "~%")))) + (html + ((:script :language "JavaScript") + (:princ + (with-output-to-string (*js-stream*) + (call-next-method)))))))) (defclass random-image-handler (object-handler) ()) @@ -29,7 +33,7 @@ (let ((content-type (blob-type (quickhoney-animation-image-animation animation)))) (with-http-response (:content-type content-type) (with-http-body () - (blob-to-stream (quickhoney-animation-image-animation animation) *html-stream*))))) + (blob-to-stream (quickhoney-animation-image-animation animation) *js-stream*))))) (defclass image-query-js-handler (javascript-handler object-handler) ()) @@ -62,19 +66,19 @@ (format t "]~%"))) (defmethod handle-object ((handler image-query-js-handler) images) - (format *html-stream* "parent.process_query_result(~%") + (format *js-stream* "parent.process_query_result(~%") (with-query-params (layout) (princ (layout-to-javascript (make-instance (case (make-keyword-from-string layout) (:smallworld 'quickhoney-name-layout) (t 'quickhoney-standard-layout)) - :objects images)) *html-stream*)) - (format *html-stream* ");~%")) + :objects images)) *js-stream*)) + (format *js-stream* ");~%")) (defclass login-js-handler (javascript-handler page-handler) ()) (defmethod handle ((handler login-js-handler)) - (format *html-stream* "parent.login_complete(~A, ~S);~%" + (format *js-stream* "parent.login_complete(~A, ~S);~%" (if (admin-p (bknr-session-user)) "true" "false") (user-login (bknr-session-user)))) @@ -84,7 +88,7 @@ (defmethod handle ((handler clients-js-handler)) (let ((clients (sort (remove "" (all-clients) :test #'equal) #'string-lessp))) - (format *html-stream* "parent.set_clients([~S~{, ~S~}]);~%" + (format *js-stream* "parent.set_clients([~S~{, ~S~}]);~%" (car clients) (cdr clients)))) (defclass edit-image-js-handler (admin-only-handler javascript-handler edit-object-handler) @@ -97,11 +101,11 @@ (defmethod handle-object-form ((handler edit-image-js-handler) (action (eql :edit)) image) (with-query-params (client) (change-slot-values image 'client client) - (format *html-stream* "parent.image_edited()~%"))) + (format *js-stream* "parent.image_edited()~%"))) (defmethod handle-object-form ((handler edit-image-js-handler) (action (eql :delete)) (image quickhoney-image)) (delete-object image) - (format *html-stream* "parent.image_deleted();~%")) + (format *js-stream* "parent.image_deleted();~%")) (defclass buttons-js-handler (javascript-handler prefix-handler) ()) @@ -138,11 +142,11 @@ collect (list category subcategory (button-for-category category subcategory background-color)))))) (defmethod handle ((handler buttons-js-handler)) - (format *html-stream* "var buttons = [];~%") + (format *js-stream* "var buttons = [];~%") (loop for (category subcategory image-url) in (find-button-images (decoded-handler-path handler)) when image-url - do (format *html-stream* "buttons['~(~A/~A~)'] = ~S;~%" category subcategory image-url)) - (format *html-stream* "parent.set_button_images(buttons);~%")) + do (format *js-stream* "buttons['~(~A/~A~)'] = ~S;~%" category subcategory image-url)) + (format *js-stream* "parent.set_button_images(buttons);~%")) (defclass upload-image-handler (admin-only-handler prefix-handler) ()) @@ -259,7 +263,9 @@ (error "invalid image size, buttons must be 208 by 208 pixels")) (let* ((image (make-store-image :name (pathname-name uploaded-file) :class-name 'store-image - :keywords (list :button (make-keyword-from-string directory) (make-keyword-from-string subdirectory))))) + :keywords (list :button + (make-keyword-from-string directory) + (make-keyword-from-string subdirectory))))) (with-http-response () (with-http-body () (html (:html Modified: branches/trunk-reorg/projects/quickhoney/src/tags.lisp ============================================================================== --- branches/trunk-reorg/projects/quickhoney/src/tags.lisp (original) +++ branches/trunk-reorg/projects/quickhoney/src/tags.lisp Fri Feb 15 11:33:56 2008 @@ -1,7 +1,6 @@ (in-package :quickhoney.tags) (define-bknr-tag version-and-last-change (&rest args) - (format *debug-io* "hello world: ~A~%" args) (html "v1.1 | updated " (:princ-safe (string-downcase (substitute #\Space #\- Modified: branches/trunk-reorg/projects/quickhoney/website/static/javascript.js ============================================================================== --- branches/trunk-reorg/projects/quickhoney/website/static/javascript.js (original) +++ branches/trunk-reorg/projects/quickhoney/website/static/javascript.js Fri Feb 15 11:33:56 2008 @@ -607,8 +607,10 @@ var components = document.jump_to.split("/"); document.jump_to = null; show_page(components[0]); - subdirectory(components[1]); - document.show_picture = components[2]; + if (components[1]) { + subdirectory(components[1]); + } + document.show_picture = components[2]; } } Modified: branches/trunk-reorg/projects/quickhoney/website/templates/index.xml ============================================================================== --- branches/trunk-reorg/projects/quickhoney/website/templates/index.xml (original) +++ branches/trunk-reorg/projects/quickhoney/website/templates/index.xml Fri Feb 15 11:33:56 2008 @@ -127,7 +127,7 @@