Thx! The changes were actually very very minor, its just finding them thats really annoying. Which reminds me, i should probably relate what i did to get it to work, for others.
Locate the package.lisp file.
At the top should be something like #-(...bunch of lisp implementations) (error "...")
Include clisp in the bunch of lisp implementations.
Then, go to the :use statement. Add #+clisp :clos to the list
Now, we need to add a new file-position function. In sbcl, if we try to position
the file beyond the eof, it will add #\Null characters or 0s for padding depending on
stream type.
Add following statement to defpackage statement
(:shadow :file-position)
Then, after the (in-package :rucksack) at the end of the file, add the following.
Code: Select all
(defun file-position (stream &optional position)
#-clisp (cl:file-position stream position)
#+clisp (if (not position)
(cl:file-position stream)
(let ((eof-position (file-length stream)))
(if (>= position eof-position)
(progn
(cl:file-position stream eof-position)
(loop repeat (1+ (- position eof-position))
do(write-byte 0 stream))
(cl:file-position stream position))
(cl:file-position stream position)))))
Locate the rucksack.lisp file
Rucksack uses locks. Since clisp doesn't contain these, you need to add dummy
lock macros. Should end up looking like this
Code: Select all
(defun make-lock (&key (name "lock"))
#+allegro
(mp:make-process-lock :name name)
#+lispworks
(mp:make-lock :name name)
#+sbcl
(sb-thread:make-mutex :name name)
#+openmcl
(ccl:make-lock name)
#-(or allegro lispworks sbcl openmcl)
nil)
(defmacro with-lock ((lock) &body body)
#+allegro
`(mp:with-process-lock (,lock) ,@body)
#+lispworks
`(mp:with-lock (,lock) ,@body)
#+sbcl
`(sb-thread:with-mutex (,lock) ,@body)
#+openmcl
`(ccl:with-lock-grabbed (,lock) ,@body)
#-(or allegro lispworks sbcl openmcl) `(progn ,@body))
(defun process-lock (lock)
#+lispworks
(mp:process-lock lock)
#+sbcl
(sb-thread:get-mutex lock)
#-(or sbcl lispworks)
nil)
(defun process-unlock (lock)
#+lispworks
(mp:process-unlock lock)
#+sbcl
(sb-thread:release-mutex lock)
#-(or sbcl lispworks)
nil)
Locate the serialize.lisp file. Change the max-character-code function to the following.
The problem here is that in sbcl, it will return 0 if the string is empty, but clisp will return nil.
(defun max-character-code (string)
"Returns the highest character code in string."
#+clisp (if (string-equal string "") (return-from max-character-code 0))
(loop for char across string
maximize (char-code char)))
Finally, and this is a hack, we need to suppress clisp warnings. The thing is, when we have nested (with-rucksacks) for the same database, it tries to have more than one open stream to a file. If we don't suppress it, it will crash our program. I guess you could also try try catch blocks, but whatever.
In windows:create a shortcut to clisp by right clicking on clisp.exe and clicking create shortcut. Rename it as "click-appease" or something. Right click shortcut and click on properties. Under shortcut tab, rename target to something like following, replacing thing between parantheses by the pathname of your shortcut.
"C:\Program Files\clisp-2.45\clisp.exe" -on-error appease
Click OK, and your done. Use this shortcut when you use clisp and rucksack together.
No clue how to do it on other systems.
A much better way would probably be to create a global hashtable which has
the pathname as a key and an open stream or nil if there is none as the item. Something like that, anyways. Actually, you shouldn't have nested with-rucksacks for the same database in the first place, but you can figure out why the example signals a warning.