diff options
author | Brian Cully <bjc@kublai.com> | 2008-04-02 19:20:20 -0400 |
---|---|---|
committer | Brian Cully <bjc@kublai.com> | 2008-04-02 19:20:20 -0400 |
commit | ab10720260e2c184b319026da89f4dfd338500bb (patch) | |
tree | a692a27435da0296972e43b21b2f35762e720bfd /Lisp | |
download | moxie-ab10720260e2c184b319026da89f4dfd338500bb.tar.gz moxie-ab10720260e2c184b319026da89f4dfd338500bb.zip |
Initial commit
Diffstat (limited to 'Lisp')
73 files changed, 7810 insertions, 0 deletions
diff --git a/Lisp/asdf/LICENSE b/Lisp/asdf/LICENSE new file mode 100644 index 0000000..57b0a06 --- /dev/null +++ b/Lisp/asdf/LICENSE @@ -0,0 +1,24 @@ + +(This is the MIT / X Consortium license as taken from + http://www.opensource.org/licenses/mit-license.html) + +Copyright (c) 2001, 2002 Daniel Barlow and contributors + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/Lisp/asdf/README b/Lisp/asdf/README new file mode 100644 index 0000000..7243844 --- /dev/null +++ b/Lisp/asdf/README @@ -0,0 +1,752 @@ +$Id: README 20 2005-12-27 15:21:23Z bjc $ -*- Text -*- + + +asdf: another system definition facility +======================================== + +* Getting the latest version + +0) Decide which version you want. HEAD is the newest version and +usually OK, whereas RELEASE is for cautious people (e.g. who already +have systems using asdf that they don't want broken), a slightly older +version about which none of the HEAD users have complained. + +1) Check it out from sourceforge cCLan CVS: + +1a) cvs -d:pserver:anonymous@cvs.cclan.sourceforge.net:/cvsroot/cclan login + (no password: just press Enter) + +1a.1) cvs -z3 -d:pserver:anonymous@cvs.cclan.sourceforge.net:/cvsroot/cclan + co -r RELEASE asdf + +or for the bleeding edge, instead + +1a.2) cvs -z3 -d:pserver:anonymous@cvs.cclan.sourceforge.net:/cvsroot/cclan + co -A asdf + +If you are tracking the bleeding edge, you may want to subscribe to +the cclan-commits mailing list (see +<URL:http://sourceforge.net/mail/?group_id=28536>) to receive commit +messages and diffs whenever changes are made. + +For more CVS information, look at http://sourceforge.net/cvs/?group_id=28536 + + +* Getting started + +- The single file asdf.lisp is all you need to use asdf normally. For +maximum convenience you want to have it loaded whenever you start your +Lisp implementation, by loading it from the startup script, or dumping +a custom core, or something. + +- The variable asdf:*central-registry* is a list of system directory + designators. A system directory designator is a form which will be + evaluated whenever a system is to be found, and must evaluate to a + directory to look in. For example, you might have + + (*default-pathname-defaults* "/home/me/cl/systems/" + "/usr/share/common-lisp/systems/") + + (When we say "directory" here, we mean "designator for a pathname + with a supplied DIRECTORY component") + + It is possible to customize the system definition file search. + That's considered advanced use, and covered later: search forward + for *system-definition-search-functions* + +- To compile and load a system 'foo', you need to (1) ensure that + foo.asd is in one of the directories in *central-registry* (a + symlink to the real location of foo.asd is preferred), (2) execute + ``(asdf:operate 'asdf:load-op 'foo)'' + + $ cd /home/me/cl/systems/ + $ ln -s ~/src/foo/foo.asd . + $ lisp + * (asdf:operate 'asdf:load-op 'foo) + +- To write your own system definitions, look at the test systems in + test/ , and read the rest of this. Ignore systems/ which is old + and may go away when next I clean up + +- Syntax is similar to mk-defsystem 3 for straightforward systems, you + may only need to remove the :source-pathname option (and replace it + with :pathname if the asd file is not in the same place as the + system sources) + +- Join cclan-list@lists.sf.net for discussion, bug reports, questions, etc + +- cclan.asd and the source files listed therein contain useful extensions + for maintainers of systems in the cCLan. If this isn't you, you + don't need them - although you may want to look at them anyway + +- For systems that do complicated things (e.g. compiling C files to + load as foreign code), the packages in vn-cclan may provide some + guidance. db-sockets, for example, is known to do outlandish things + with preprocessors + + http://ww.telent.net/cliki/vn-cclan + + + +* Concepts + +This system definition utility talks in terms of 'components' and +'operations'. + +Components form systems: a component represents a source file, or a +collection of components. A system is therefore a component, +recursively formed of a tree of subcomponents. + +Operations are instantiated then performed on the nodes of a tree to +do things like + + - compile all its files + - load the files into a running lisp environment + - copy its source files somewhere else + +Operations can be invoked directly, or examined to see what their +effects would be without performing them. There are a bunch of +methods specialised on operation and component type which actually do +the grunt work. + +asdf is extensible to new operations and to new component types. This +allows the addition of behaviours: for example, a new component could +be added for Java JAR archives, and methods specialised on +compile-op added for it that would accomplish the relevant +actions. + +* Inspiration + +** mk-defsystem (defsystem-3.x) + +We aim to solve basically the same problems as mk-defsystem does. +However, our architecture for extensibility better exploits CL +language features (and is documented), and we intend to be portable +rather than just widely-ported. No slight on the mk-defsystem authors +and maintainers is intended here; that implementation has the +unenviable task of supporting non-ANSI implementations, which I +propose to ignore. + +The surface defsystem syntax of asdf is more-or-less compatible with +mk-defsystem + +The mk-defsystem code for topologically sorting a module's dependency +list was very useful. + +** defsystem-4 proposal + +Marco and Peter's proposal for defsystem 4 served as the driver for +many of the features in here. Notable differences are + +- we don't specify output files or output file extensions as part of + the system + + If you want to find out what files an operation would create, ask + the operation + +- we don't deal with CL packages + + If you want to compile in a particular package, use an in-package + form in that file (ilisp will like you more if you do this anyway) + +- there is no proposal here that defsystem does version control. + + A system has a given version which can be used to check + dependencies, but that's all. + +The defsystem 4 proposal tends to look more at the external features, +whereas this one centres on a protocol for system introspection. + +** kmp's "The Description of Large Systems", MIT AI Memu 801 + +Available in updated-for-CL form on the web at +http://world.std.com/~pitman/Papers/Large-Systems.html + +In our implementation we borrow kmp's overall PROCESS-OPTIONS and +concept to deal with creating component trees from defsystem surface +syntax. [ this is not true right now, though it used to be and +probably will be again soon ] + + +* The Objects + +** component + +*** Component Attributes + +**** A name (required) + +This is a string or a symbol. If a symbol, its name is taken and +lowercased. The name must be a suitable value for the :name initarg +to make-pathname in whatever filesystem the system is to be found. + +The lower-casing-symbols behaviour is unconventional, but was selected +after some consideration. Observations suggest that the type of +systems we want to support either have lowercase as customary case +(Unix, Mac, windows) or silently convert lowercase to uppercase +(lpns), so this makes more sense than attempting to use :case :common, +which is reported not to work on some implementations + +**** a version identifier (optional) + +This is used by the test-system-version operation (see later). + +**** *features* required + +Traditionally defsystem users have used reader conditionals to include +or exclude specific per-implementation files. This means that any +single implementation cannot read the entire system, which becomes a +problem if it doesn't wish to compile it, but instead for example to +create an archive file containing all the sources, as it will omit to +process the system-dependent sources for other systems. + +Each component in an asdf system may therefore specify features using +the same syntax as #+ does, and it will (somehow) be ignored for +certain operations unless the feature conditional matches + +**** dependencies on its siblings (optional but often necessary) + +There is an excitingly complicated relationship between the initarg +and the method that you use to ask about dependencies + +Dependencies are between (operation component) pairs. In your +initargs, you can say + +:in-order-to ((compile-op (load-op "a" "b") (compile-op "c")) + (load-op (load-op "foo"))) + +- before performing compile-op on this component, we must perform +load-op on "a" and "b", and compile-op on c, - before performing +load-op, we have to load "foo" + +The syntax is approximately + +(this-op {(other-op required-components)}+) + +required-components := component-name + | (required-components required-components) + +component-name := string + | (:version string minimum-version-object) + +[ This is on a par with what ACL defsystem does. mk-defsystem is less +general: it has an implied dependency + + for all x, (load x) depends on (compile x) + +and using a :depends-on argument to say that b depends on a _actually_ +means that + + (compile b) depends on (load a) + +This is insufficient for e.g. the McCLIM system, which requires that +all the files are loaded before any of them can be compiled ] + +In asdf, the dependency information for a given component and +operation can be queried using (component-depends-on operation +component), which returns a list + +((load-op "a") (load-op "b") (compile-op "c") ...) + +component-depends-on can be subclassed for more specific +component/operation types: these need to (call-next-method) and append +the answer to their dependency, unless they have a good reason for +completely overriding the default dependencies + +(If it weren't for CLISP, we'd be using a LIST method combination to +do this transparently. But, we need to support CLISP. If you have +the time for some CLISP hacking, I'm sure they'd welcome your fixes) + +**** a pathname + +This is optional and if absent will be inferred from name, type (the +subclass of source-file), and the location of parent. + +The rules for this inference are: + +(for source-files) +- the host is taken from the parent +- pathname type is (source-file-type component system) +- the pathname case option is :local +- the pathname is merged against the parent + +(for modules) +- the host is taken from the parent +- the name and type are NIL +- the directory is (:relative component-name) +- the pathname case option is :local +- the pathname is merged against the parent + +Note that the DEFSYSTEM operator (used to create a "top-level" system) +does additional processing to set the filesystem location of the +top component in that system. This is detailed elsewhere + +The answer to the frequently asked question "how do I create a system +definition where all the source files have a .cl extension" is thus + +(defmethod source-file-type ((c cl-source-file) (s (eql (find-system 'my-sys)))) + "cl") + +**** properties (optional) + +Packaging systems often require information about files or systems +additional to that specified here. Programs that create vendor +packages out of asdf systems therefore have to create "placeholder" +information to satisfy these systems. Sometimes the creator of an +asdf system may know the additional information and wish to provide it +directly. + +(component-property component property-name) and associated setf method +will allow the programmatic update of this information. Property +names are compared as if by EQL, so use symbols or keywords or something + +** Subclasses of component + +*** 'source-file' + +A source file is any file that the system does not know how to +generate from other components of the system. + +(Note that this is not necessarily the same thing as "a file +containing data that is typically fed to a compiler". If a file is +generated by some pre-processor stage (e.g. a ".h" file from ".h.in" +by autoconf) then it is not, by this definition, a source file. +Conversely, we might have a graphic file that cannot be automatically +regenerated, or a proprietary shared library that we received as a +binary: these do count as source files for our purposes. All +suggestions for better terminology gratefully received) + +Subclasses of source-file exist for various languages. + +*** 'module', a collection of sub-components + +This has extra slots for + + :components - the components contained in this module + + :default-component-class - for child components which don't specify + their class explicitly + + :if-component-dep-fails takes one of the values :fail, :try-next, :ignore + (default value is :fail). The other values can be used for implementing + conditional compilation based on implementation *features*, where + it is not necessary for all files in a module to be compiled + +The default operation knows how to traverse a module, so most +operations will not need to provide methods specialised on modules. + +The module may be subclassed to represent components such as +foreign-language linked libraries or archive files. + +*** system, subclasses module + +A system is a module with a few extra attributes for documentation +purposes. In behaviour, it's usually identical. + +Users can create new classes for their systems: the default defsystem +macro takes a :classs keyword argument. + + +** operation + +An operation is instantiated whenever the user asks that an operation +be performed, inspected, or etc. The operation object contains +whatever state is relevant to this purpose (perhaps a list of visited +nodes, for example) but primarily is a nice thing to specialise +operation methods on and easier than having them all be EQL methods. + +There are no differences between standard operations and user-defined +operations, except that the user is respectfully requested to keep his +(or more importantly, our) package namespace clean + +*** invoking operations + +(operate operation system &rest keywords-args) + +keyword-args are passed to the make-instance call when creating the +operation: valid keywords depend on the initargs that the operation is +defined to accept. Note that dependencies may cause the operation to +invoke other operations on the system or its components: the new +operation will be created with the same initargs as the original one. + +oos is accepted as a synonym for operate + +*** standard operations + +**** feature-dependent-op + +This is not intended to be instantiated directly, but other operations +may inherit from it. An instance of feature-dependent-op will ignore +any components which have a `features' attribute, unless the feature +combination it designates is satisfied by *features* + +See the earlier explanation about the component features attribute for +more information + +**** compile-op &key proclamations + +If proclamations are supplied, they will be proclaimed. This is a +good place to specify optimization settings + +When creating a new component, you should provide methods for this. + +If you invoke compile-op as a user, component dependencies often mean +you may get some parts of the system loaded. This may not necessarily +be the whole thing, though; for your own sanity it is recommended that +you use load-op if you want to load a system. + +**** load-op &key proclamations + +The default methods for load-op compile files before loading them. +For parity, your own methods on new component types should probably do +so too + +**** load-source-op + +This method will load the source for the files in a module even if the +source files have been compiled. Systems sometimes have knotty +dependencies which require that sources are loaded before they can be +compiled. This is how you do that. + +If you are creating a component type, you need to implement this +operation - at least, where meaningful. + +**** test-system-version &key minimum + +Asks the system whether it satisfies a version requirement. + +The default method accepts a string, which is expected to contain of a +number of integers separated by #\. characters. The method is not +recursive. The component satisfies the version dependency if it has +the same major number as required and each of its sub-versions is +greater than or equal to the sub-version number required. + +(defun version-satisfies (x y) + (labels ((bigger (x y) + (cond ((not y) t) + ((not x) nil) + ((> (car x) (car y)) t) + ((= (car x) (car y)) + (bigger (cdr x) (cdr y)))))) + (and (= (car x) (car y)) + (or (not (cdr y)) (bigger (cdr x) (cdr y)))))) + +If that doesn't work for your system, you can override it. I hope +yoyu have as much fun writing the new method as #lisp did +reimplementing this one. + +*** Creating new operations + +subclass operation, provide methods for source-file for + +- output-files +- perform + The perform method must call output-files to find out where to + put its files, because the user is allowed to override output-files + for local policy +- explain +- operation-done-p, if you don't like the default one + +* Writing system definitions + +** System designators + +System designators are strings or symbols and behave just like +any other component names (including case conversion) + +** find-system + +Given a system designator, find-system finds an actual system - either +in memory, or in a file on the disk. It funcalls each element in the +*system-definition-search-functions* list, expecting a pathname to be +returned. + +If a suitable file exists, it is loaded if + +- there is no system of that name in memory, +- the file's last-modified time exceeds the last-modified time of the + system in memory + +When system definitions are loaded from .asd files, a new scratch +package is created for them to load into, so that different systems do +not overwrite each others operations. The user may also wish to (and +is recommended to) include defpackage and in-package forms in his +system definition files, however, so that they can be loaded manually +if need be. + +For convenience in the normal case, and for backward compatibility +with the spirit of mk-defsystem, the default contents of +*system-definition-search-functions* is a function called +sysdef-central-registry-search. This looks in each of the directories +given by evaluating members of *central-registry*, for a file whose +name is the name of the system and whose type is "asd". The first +such file is returned, whether or not it turns out to actually define +the appropriate system + + + +** Syntax + +Systems can always be constructed programmatically by instantiating +components using make-instance. For most purposes, however, it is +likely that people will want a static defystem form. + +asdf is based around the principle that components should not have to +know defsystem syntax. That is, the initargs that a component accepts +are not necessarily related to the defsystem form which creates it. + +A defsystem parser must implement a `defsystem' macro, which can +be named for compatibility with whatever other system definition +utility is being emulated. It should instantiate components in +accordance with whatever language it accepts, and register the topmost +component using REGISTER-SYSTEM + +*** Native syntax + +The native syntax is inspired by mk-defsystem, to the extent that it +should be possible to take most straightforward mk- system definitions +and run them with only light editing. For my convenience, this turns +out to be basically the same as the initargs to the various +components, with a few extensions for convenience + +system-definition := ( defsystem system-designator {option}* ) + +option := :components component-list + | :pathname pathname + | :default-component-class + | :perform method-form + | :explain method-form + | :output-files method-form + | :operation-done-p method-form + | :depends-on ( {simple-component-name}* ) + | :serial [ t | nil ] + | :in-order-to ( {dependency}+ ) + +component-list := ( {component-def}* ) + +component-def := simple-component-name + | ( component-type name {option}* ) + +component-type := :module | :file | :system | other-component-type + +dependency := (dependent-op {requirement}+) +requirement := (required-op {required-component}+) + | (feature feature-name) +dependent-op := operation-name +required-op := operation-name | feature + +For example + +(defsystem "foo" + :version "1.0" + :components ((:module "foo" :components ((:file "bar") (:file"baz") + (:file "quux")) + :perform (compile-op :after (op c) + (do-something c)) + :explain (compile-op :after (op c) + (explain-something c))) + (:file "blah"))) + + +The method-form tokens need explaining: esentially, + + :perform (compile-op :after (op c) + (do-something c)) + :explain (compile-op :after (op c) + (explain-something c))) +has the effect of + +(defmethod perform :after ((op compile-op) (c (eql ...))) + (do-something c)) +(defmethod explain :after ((op compile-op) (c (eql ...))) + (explain-something c)) + +where ... is the component in question; note that although this also +supports :before methods, they may not do what you want them to - a +:before method on perform ((op compile-op) (c (eql ...))) will run +after all the dependencies and sub-components have been processed, but +before the component in question has been compiled. + +**** Serial dependencies + +If the `:serial t' option is specified for a module, asdf will add +dependencies for each each child component, on all the children +textually preceding it. This is done as if by :depends-on + +:components ((:file "a") (:file "b") (:file "c")) +:serial t + +is equivalent to +:components ((:file "a") + (:file "b" :depends-on ("a")) + (:file "c" :depends-on ("a" "b"))) + + + +have all the + +**** Source location + +The :pathname option is optional in all cases for native-syntax +systems, and in the usual case the user is recommended not to supply +it. If it is not supplied for the top-level form, defsystem will set +it from + +- The host/device/directory parts of *load-truename*, if it is bound +- *default-pathname-defaults*, otherwise + +If a system is being redefined, the top-level pathname will be + +- changed, if explicitly supplied or obtained from *load-truename* +- changed if it had previously been set from *default-pathname-defaults* +- left as before, if it had previously been set from *load-truename* + and *load-truename* is not now bound + +These rules are designed so that (i) find-system will load a system +from disk and have its pathname default to the right place, (ii) +this pathname information will not be overwritten with +*default-pathname-defaults* (which could be somewhere else altogether) +if the user loads up the .asd file into his editor and +interactively re-evaluates that form + +* Error handling + +It is an error to define a system incorrectly: an implementation may +detect this and signal a generalised instance of +SYSTEM-DEFINITION-ERROR + +Operations may go wrong (for example when source files contain +errors). These are signalled using generalised instances of +OPERATION-ERROR + +* Compilation error and warning handling + +ASDF checks for warnings and errors when a file is compiled. The +variables *compile-file-warnings-behaviour* and +*compile-file-errors-behavior* controls the handling of any such +events. The valid values for these variables are :error, :warn, and +:ignore. + +---------------------------------------------------------- + TODO List +---------------------------------------------------------- + +* Outstanding spec questions, things to add + +** packaging systems + +*** manual page component? + +** style guide for .asd files + +You should either use keywords or be careful with the package that you +evaluate defsystem forms in. Otherwise (defsystem partition ...) +being read in the cl-user package will intern a cl-user:partition +symbol, which will then collide with the partition:partition symbol. + +Actually there's a hairier packages problem to think about too. +in-order-to is not a keyword: if you read defsystem forms in a package +that doesn't use ASDF, odd things might happen + +** extending defsystem with new options + +You might not want to write a whole parser, but just to add options to +the existing syntax. Reinstate parse-option or something akin + +** document all the error classes + +** what to do with compile-file failure + +Should check the primary return value from compile-file and see if +that gets us any closer to a sensible error handling strategy + +** foreign files + +lift unix-dso stuff from db-sockets + +** Diagnostics + +A "dry run" of an operation can be made with the following form: + +(traverse (make-instance '<operation-name>) + (find-system <system-name>) + 'explain) + +This uses unexported symbols. What would be a nice interface for this +functionality? + +** patches + +Sometimes one wants to + + +* missing bits in implementation + +** all of the above +** reuse the same scratch package whenever a system is reloaded from disk +** rules for system pathname defaulting are not yet implemented properly +** proclamations probably aren't +** when a system is reloaded with fewer components than it previously + had, odd things happen + +we should do something inventive when processing a defsystem form, +like take the list of kids and setf the slot to nil, then transfer +children from old to new list as they're found + +** traverse may become a normal function + +If you're defining methods on traverse, speak up. + + +** a lot of load-op methods can be rewritten to use input-files + +so should be. + + +** (stuff that might happen later) + +*** david lichteblau's patch for symlink resolution? + +*** Propagation of the :force option. ``I notice that + + (oos 'compile-op :araneida :force t) + +also forces compilation of every other system the :araneida system +depends on. This is rarely useful to me; usually, when I want to force +recompilation of something more than a single source file, I want to +recompile only one system. So it would be more useful to have +make-sub-operation refuse to propagate ":force t" to other systems, and +propagate only something like ":force :recursively". '' + +Ideally what we actually want is some kind of criterion that says +to which systems (and which operations) a :force switch will propagate. + +The problem is perhaps that 'force' is a pretty meaningless concept. +How obvious is it that "load :force t" should force _compilation_? +But we don't really have the right dependency setup for the user to +compile :force t and expect it to work (files will not be loaded after +compilation, so the compile environment for subsequent files will be +emptier than it needs to be) + +What does the user actually want to do when he forces? Usually, for +me, update for use with a new version of the lisp compiler. Perhaps +for recovery when he suspects that something has gone wrong. Or else +when he's changed compilation options or configuration in some way +that's not reflected in the dependency graph. + +Other possible interface: have a 'revert' function akin to 'make clean' + + (asdf:revert 'asdf:compile-op 'araneida) + +would delete any files produced by 'compile-op 'araneida. Of course, it +wouldn't be able to do much about stuff in the image itself. + +How would this work? + +traverse + +There's a difference between a module's dependencies (peers) and its +components (children). Perhaps there's a similar difference in +operations? For example, (load "use") depends-on (load "macros") is a +peer, whereas (load "use") depends-on (compile "use") is more of a +`subservient' relationship. diff --git a/Lisp/asdf/asdf-install.lisp b/Lisp/asdf/asdf-install.lisp new file mode 100644 index 0000000..2bcd702 --- /dev/null +++ b/Lisp/asdf/asdf-install.lisp @@ -0,0 +1,299 @@ +#|| sh asdf-install.lisp will compile this file to an exe called asdf-install +sbcl <<EOF +(require 'sb-executable) +(compile-file "asdf-install.lisp") +(sb-executable:make-executable "asdf-install" *) +EOF +exit 0 +||# + +;;; Install an ASDF system or anything else that looks convincingly +;;; like one, including updating symlink for all the toplevel .asd files it +;;; contains + +;;; If the file $HOME/.asdf-install exists, it is loaded. This can be +;;; used to override the default values of exported special variables +;;; (see the defpackage form for details) - however, most of them are +;;; sensible and/or taken from the environment anyway + +#|| +TODO: +a) gpg signature checking would be better if it actually checked against +a list of "trusted to write Lisp" keys, instead of just "trusted to be +who they say they are" + +d) in sbcl 0.8.1 we'll have a run-program that knows about $PATH and so +won't need to hardcode gpgpgpgp and tar locations. + +e) nice to have: resume half-done downloads instead of starting from scratch +every time. but right now we're dealing in fairly small packages, this is not +an immediate concern + +||# +(in-package :cl-user) +(eval-when (:compile-toplevel :load-toplevel :execute) + (require 'asdf) + (require 'sb-posix) + (require 'sb-executable) + (require 'sb-bsd-sockets)) + +(defpackage :asdf-install + (:use "CL" "SB-EXT" "SB-BSD-SOCKETS") + (:export #:*proxy* #:*cclan-mirror* #:*sbcl-home* + #:*verify-gpg-signatures* #:*locations*)) + +(defpackage :asdf-install-customize + (:use "CL" "SB-EXT" "SB-BSD-SOCKETS" "ASDF-INSTALL")) + +(in-package :asdf-install) + +(defvar *proxy* (posix-getenv "http_proxy")) +(defvar *cclan-mirror* + (or (posix-getenv "CCLAN_MIRROR") + "http://ftp.linux.org.uk/pub/lisp/cclan/")) + +(defun directorify (name) + ;; input name may or may not have a training #\/, but we know we + ;; want a directory + (let ((path (pathname name))) + (if (pathname-name path) + (merge-pathnames + (make-pathname :directory `(:relative ,(pathname-name path)) + :name "") + path) + path))) + +(defvar *sbcl-home* (directorify (posix-getenv "SBCL_HOME"))) +(defvar *dot-sbcl* + (merge-pathnames (make-pathname :directory '(:relative ".sbcl")) + (user-homedir-pathname))) + +(defvar *verify-gpg-signatures* t) + +(defvar *locations* + `((,(merge-pathnames "site/" *sbcl-home*) + ,(merge-pathnames "site-systems/" *sbcl-home*) + "System-wide install") + (,(merge-pathnames "site/" *dot-sbcl*) + ,(merge-pathnames "systems/" *dot-sbcl*) + "Personal installation"))) + +(let* ((*package* (find-package :asdf-install-customize)) + (file (probe-file (merge-pathnames + (make-pathname :name ".asdf-install") + (user-homedir-pathname))))) + (when file (load file))) + +(define-condition download-error (error) + ((url :initarg :url :reader download-url) + (response :initarg :response :reader download-response)) + (:report (lambda (c s) + (format s "Server responded ~A for GET ~A" + (download-response c) (download-url c))))) + +(define-condition signature-error (error) + ((cause :initarg :cause :reader signature-error-cause)) + (:report (lambda (c s) + (format s "Cannot verify package signature: ~A" + (signature-error-cause c))))) + +(defun url-host (url) + (assert (string-equal url "http://" :end1 7)) + (let* ((port-start (position #\: url :start 7)) + (host-end (min (or (position #\/ url :start 7) (length url)) + (or port-start (length url))))) + (subseq url 7 host-end))) + +(defun url-port (url) + (assert (string-equal url "http://" :end1 7)) + (let ((port-start (position #\: url :start 7))) + (if port-start (parse-integer url :start port-start :junk-allowed t) 80))) + +(defun url-connection (url) + (let ((s (make-instance 'inet-socket :type :stream :protocol :tcp)) + (host (url-host url)) + (port (url-port url))) + (socket-connect + s (car (host-ent-addresses (get-host-by-name (url-host (or *proxy* url))))) + (url-port (or *proxy* url))) + (let ((stream (socket-make-stream s :input t :output t :buffering :full))) + ;; we are exceedingly unportable about proper line-endings here. + ;; Anyone wishing to run this under non-SBCL should take especial care + (format stream "GET ~A HTTP/1.0~%Host: ~A~%Cookie: CCLAN-SITE=~A~%~%" + url host *cclan-mirror*) + (force-output stream) + (list + (let* ((l (read-line stream)) + (space (position #\Space l))) + (parse-integer l :start (1+ space) :junk-allowed t)) + (loop for line = (read-line stream nil nil) + until (or (null line) (eql (elt line 0) (code-char 13))) + collect + (let ((colon (position #\: line))) + (cons (intern (string-upcase (subseq line 0 colon)) :keyword) + (string-trim (list #\Space (code-char 13)) + (subseq line (1+ colon)))))) + stream)))) + +(defun download (package-name-or-url file-name) + (let ((url + (if (= (mismatch package-name-or-url "http://") 7) + package-name-or-url + (format nil "http://www.cliki.net/~A?download" + package-name-or-url)))) + (destructuring-bind (response headers stream) + (block got + (loop + (destructuring-bind (response headers stream) (url-connection url) + (unless (member response '(301 302)) + (return-from got (list response headers stream))) + (close stream) + (setf url (cdr (assoc :location headers)))))) + (if (>= response 400) + (error 'download-error :url url :response response)) + (let ((length (parse-integer + (or (cdr (assoc :content-length headers)) "") + :junk-allowed t))) + (format t "Downloading ~A bytes from ~A ..." + (if length length "some unknown number of") url) + (force-output) + (with-open-file (o file-name :direction :output) + (if length + (let ((buf (make-array length + :element-type + (stream-element-type stream) ))) + (read-sequence buf stream) + (write-sequence buf o)) + (sb-executable:copy-stream stream o)))) + (close stream) + (terpri) + ;; seems to have worked. let's try for a detached gpg signature too + (when *verify-gpg-signatures* + (verify-gpg-signature url file-name))))) + +(defun verify-gpg-signature (url file-name) + (destructuring-bind (response headers stream) + (url-connection (concatenate 'string url ".asc")) + (declare (ignore headers)) + (unwind-protect + (if (= response 200) + ;; sadly, we can't pass the stream directly to run-program, + ;; because (at least in sbcl 0.8) that ignores existing buffered + ;; data and only reads new fresh data direct from the file + ;; descriptor + (let ((data (make-string (parse-integer + (cdr (assoc :content-length headers)) + :junk-allowed t)))) + (read-sequence data stream) + (let ((ret + (process-exit-code + (sb-ext:run-program "/usr/bin/gpg" + (list "--verify" "-" + (namestring file-name)) + :output t + :input (make-string-input-stream data) + :wait t)))) + (unless (zerop ret) + (error 'signature-error + :cause (make-condition + 'simple-error + :format-control "GPG returned exit status ~A" + :format-arguments (list ret)))))) + (error 'signature-error + :cause + (make-condition + 'download-error :url (concatenate 'string url ".asc") + :response response))) + (close stream)))) + + + + +(defun where () + (format t "Install where?~%") + (loop for (source system name) in *locations* + for i from 1 + do (format t "~A) ~A: ~% System in ~A~% Files in ~A ~%" + i name system source)) + (format t " --> ") (force-output) + (let ((response (read))) + (when (> response 0) + (elt *locations* (1- response))))) + +(defun install (source system packagename) + "Returns a list of asdf system names for installed asdf systems" + (ensure-directories-exist source ) + (ensure-directories-exist system ) + (let* ((tar + (with-output-to-string (o) + (or + (sb-ext:run-program "/bin/tar" + (list "-C" (namestring source) + "-xzvf" (namestring packagename)) + :output o + :wait t) + (error "can't untar")))) + (dummy (princ tar)) + (pos-slash (position #\/ tar)) + (*default-pathname-defaults* + (merge-pathnames + (make-pathname :directory + `(:relative ,(subseq tar 0 pos-slash))) + source))) + (loop for asd in (directory + (make-pathname :name :wild :type "asd")) + do (let ((target (merge-pathnames + (make-pathname :name (pathname-name asd) + :type (pathname-type asd)) + system))) + (when (probe-file target) + (sb-posix:unlink target)) + (sb-posix:symlink asd target)) + collect (pathname-name asd)))) + +(defvar *temporary-files*) +(defun temp-file-name (p) + (let* ((pos-slash (position #\/ p :from-end t)) + (pos-dot (position #\. p :start (or pos-slash 0)))) + (merge-pathnames + (make-pathname + :name (subseq p (if pos-slash (1+ pos-slash) 0) pos-dot) + :type "asdf-install-tmp")))) + + + +(defun run (&optional (packages (cdr *posix-argv*))) + (destructuring-bind (source system name) (where) + (labels ((one-iter (packages) + (dolist (asd + (loop for p in packages + unless (probe-file p) + do (let ((tmp (temp-file-name p))) + (pushnew tmp *temporary-files*) + (download p tmp) + (setf p tmp)) + end + do (format t "Installing ~A in ~A,~A~%" p source system) + append (install source system p))) + (handler-case + (asdf:operate 'asdf:load-op asd) + (asdf:missing-dependency (c) + (format t "Downloading package ~A, required by ~A~%" + (asdf::missing-requires c) + (asdf:component-name (asdf::missing-required-by c))) + (one-iter (list + (symbol-name (asdf::missing-requires c))))))))) + (one-iter packages)))) + +(handler-case + (let ((*temporary-files* nil)) + (unwind-protect + (run) + (dolist (l *temporary-files*) + (when (probe-file l) (delete-file l))))) + (error (c) + (princ "Install failed due to error:") (terpri) + (princ c) (terpri) + (quit :unix-status 1))) + +;(quit)
\ No newline at end of file diff --git a/Lisp/asdf/asdf.lisp b/Lisp/asdf/asdf.lisp new file mode 100644 index 0000000..0fd5ca7 --- /dev/null +++ b/Lisp/asdf/asdf.lisp @@ -0,0 +1,1104 @@ +;;; This is asdf: Another System Definition Facility. $Revision: 1.1.1.1 $ +;;; +;;; Feedback, bug reports, and patches are all welcome: please mail to +;;; <cclan-list@lists.sf.net>. But note first that the canonical +;;; source for asdf is presently the cCLan CVS repository at +;;; <URL:http://cvs.sourceforge.net/cgi-bin/viewcvs.cgi/cclan/asdf/> +;;; +;;; If you obtained this copy from anywhere else, and you experience +;;; trouble using it, or find bugs, you may want to check at the +;;; location above for a more recent version (and for documentation +;;; and test files, if your copy came without them) before reporting +;;; bugs. There are usually two "supported" revisions - the CVS HEAD +;;; is the latest development version, whereas the revision tagged +;;; RELEASE may be slightly older but is considered `stable' + +;;; Copyright (c) 2001-2003 Daniel Barlow and contributors +;;; +;;; Permission is hereby granted, free of charge, to any person obtaining +;;; a copy of this software and associated documentation files (the +;;; "Software"), to deal in the Software without restriction, including +;;; without limitation the rights to use, copy, modify, merge, publish, +;;; distribute, sublicense, and/or sell copies of the Software, and to +;;; permit persons to whom the Software is furnished to do so, subject to +;;; the following conditions: +;;; +;;; The above copyright notice and this permission notice shall be +;;; included in all copies or substantial portions of the Software. +;;; +;;; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +;;; EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +;;; MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +;;; NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +;;; LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +;;; OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +;;; WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +;;; the problem with writing a defsystem replacement is bootstrapping: +;;; we can't use defsystem to compile it. Hence, all in one file + +(defpackage #:asdf + (:export #:defsystem #:oos #:operate #:find-system #:run-shell-command + #:system-definition-pathname #:find-component ; miscellaneous + #:hyperdocumentation #:hyperdoc + + #:compile-op #:load-op #:load-source-op #:test-system-version + #:test-op + #:operation ; operations + #:feature ; sort-of operation + #:version ; metaphorically sort-of an operation + + #:input-files #:output-files #:perform ; operation methods + #:operation-done-p #:explain + + #:component #:source-file + #:c-source-file #:cl-source-file #:java-source-file + #:static-file + #:doc-file + #:html-file + #:text-file + #:source-file-type + #:module ; components + #:system + #:unix-dso + + #:module-components ; component accessors + #:component-pathname + #:component-relative-pathname + #:component-name + #:component-version + #:component-parent + #:component-property + #:component-system + + #:component-depends-on + + #:system-description + #:system-long-description + #:system-author + #:system-maintainer + #:system-license + + #:operation-on-warnings + #:operation-on-failure + + ;#:*component-parent-pathname* + #:*system-definition-search-functions* + #:*central-registry* ; variables + #:*compile-file-warnings-behaviour* + #:*compile-file-failure-behaviour* + #:*asdf-revision* + + #:operation-error #:compile-failed #:compile-warned #:compile-error + #:system-definition-error + #:missing-component + #:missing-dependency + #:circular-dependency ; errors + + #:retry + #:accept ; restarts + + ) + (:use :cl)) + +#+nil +(error "The author of this file habitually uses #+nil to comment out forms. But don't worry, it was unlikely to work in the New Implementation of Lisp anyway") + + +(in-package #:asdf) + +(defvar *asdf-revision* (let* ((v "$Revision: 1.1.1.1 $") + (colon (or (position #\: v) -1)) + (dot (position #\. v))) + (and v colon dot + (list (parse-integer v :start (1+ colon) + :junk-allowed t) + (parse-integer v :start (1+ dot) + :junk-allowed t))))) + +(defvar *compile-file-warnings-behaviour* :warn) +(defvar *compile-file-failure-behaviour* #+sbcl :error #-sbcl :warn) + +(defvar *verbose-out* nil) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; utility stuff + +(defmacro aif (test then &optional else) + `(let ((it ,test)) (if it ,then ,else))) + +(defun pathname-sans-name+type (pathname) + "Returns a new pathname with same HOST, DEVICE, DIRECTORY as PATHNAME, +and NIL NAME and TYPE components" + (make-pathname :name nil :type nil :defaults pathname)) + +(define-modify-macro appendf (&rest args) + append "Append onto list") + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; classes, condiitons + +(define-condition system-definition-error (error) () + ;; [this use of :report should be redundant, but unfortunately it's not. + ;; cmucl's lisp::output-instance prefers the kernel:slot-class-print-function + ;; over print-object; this is always conditions::%print-condition for + ;; condition objects, which in turn does inheritance of :report options at + ;; run-time. fortunately, inheritance means we only need this kludge here in + ;; order to fix all conditions that build on it. -- rgr, 28-Jul-02.] + #+cmu (:report print-object)) + +(define-condition formatted-system-definition-error (system-definition-error) + ((format-control :initarg :format-control :reader format-control) + (format-arguments :initarg :format-arguments :reader format-arguments)) + (:report (lambda (c s) + (apply #'format s (format-control c) (format-arguments c))))) + +(define-condition circular-dependency (system-definition-error) + ((components :initarg :components :reader circular-dependency-components))) + +(define-condition missing-component (system-definition-error) + ((requires :initform "(unnamed)" :reader missing-requires :initarg :requires) + (version :initform nil :reader missing-version :initarg :version) + (parent :initform nil :reader missing-parent :initarg :parent))) + +(define-condition missing-dependency (missing-component) + ((required-by :initarg :required-by :reader missing-required-by))) + +(define-condition operation-error (error) + ((component :reader error-component :initarg :component) + (operation :reader error-operation :initarg :operation)) + (:report (lambda (c s) + (format s (formatter "~@<erred while invoking ~A on ~A~@:>") + (error-operation c) (error-component c))))) +(define-condition compile-error (operation-error) ()) +(define-condition compile-failed (compile-error) ()) +(define-condition compile-warned (compile-error) ()) + +(defclass component () + ((name :accessor component-name :initarg :name :documentation + "Component name: designator for a string composed of portable pathname characters") + (version :accessor component-version :initarg :version) + (in-order-to :initform nil :initarg :in-order-to) + ;;; XXX crap name + (do-first :initform nil :initarg :do-first) + ;; methods defined using the "inline" style inside a defsystem form: + ;; need to store them somewhere so we can delete them when the system + ;; is re-evaluated + (inline-methods :accessor component-inline-methods :initform nil) + (parent :initarg :parent :initform nil :reader component-parent) + ;; no direct accessor for pathname, we do this as a method to allow + ;; it to default in funky ways if not supplied + (relative-pathname :initarg :pathname) + (operation-times :initform (make-hash-table ) + :accessor component-operation-times) + ;; XXX we should provide some atomic interface for updating the + ;; component properties + (properties :accessor component-properties :initarg :properties + :initform nil))) + +;;;; methods: conditions + +(defmethod print-object ((c missing-dependency) s) + (format s (formatter "~@<~A, required by ~A~@:>") + (call-next-method c nil) + (missing-required-by c))) + +(defun sysdef-error (format &rest arguments) + (error 'formatted-system-definition-error :format-control format :format-arguments arguments)) + +;;;; methods: components + +(defmethod print-object ((c missing-component) s) + (format s (formatter "~@<component ~S not found~ + ~@[ or does not match version ~A~]~ + ~@[ in ~A~]~@:>") + (missing-requires c) + (missing-version c) + (when (missing-parent c) + (component-name (missing-parent c))))) + +(defgeneric component-system (component) + (:documentation "Find the top-level system containing COMPONENT")) + +(defmethod component-system ((component component)) + (aif (component-parent component) + (component-system it) + component)) + +(defmethod print-object ((c component) stream) + (print-unreadable-object (c stream :type t :identity t) + (ignore-errors + (prin1 (component-name c) stream)))) + +(defclass module (component) + ((components :initform nil :accessor module-components :initarg :components) + ;; what to do if we can't satisfy a dependency of one of this module's + ;; components. This allows a limited form of conditional processing + (if-component-dep-fails :initform :fail + :accessor module-if-component-dep-fails + :initarg :if-component-dep-fails) + (default-component-class :accessor module-default-component-class + :initform 'cl-source-file :initarg :default-component-class))) + +(defgeneric component-pathname (component) + (:documentation "Extracts the pathname applicable for a particular component.")) + +(defun component-parent-pathname (component) + (aif (component-parent component) + (component-pathname it) + *default-pathname-defaults*)) + +(defgeneric component-relative-pathname (component) + (:documentation "Extracts the relative pathname applicable for a particular component.")) + +(defmethod component-relative-pathname ((component module)) + (or (slot-value component 'relative-pathname) + (make-pathname + :directory `(:relative ,(component-name component)) + :host (pathname-host (component-parent-pathname component))))) + +(defmethod component-pathname ((component component)) + (let ((*default-pathname-defaults* (component-parent-pathname component))) + (merge-pathnames (component-relative-pathname component)))) + +(defgeneric component-property (component property)) + +(defmethod component-property ((c component) property) + (cdr (assoc property (slot-value c 'properties) :test #'equal))) + +(defgeneric (setf component-property) (new-value component property)) + +(defmethod (setf component-property) (new-value (c component) property) + (let ((a (assoc property (slot-value c 'properties) :test #'equal))) + (if a + (setf (cdr a) new-value) + (setf (slot-value c 'properties) + (acons property new-value (slot-value c 'properties)))))) + +(defclass system (module) + ((description :accessor system-description :initarg :description) + (long-description + :accessor system-long-description :initarg :long-description) + (author :accessor system-author :initarg :author) + (maintainer :accessor system-maintainer :initarg :maintainer) + (licence :accessor system-licence :initarg :licence))) + +;;; version-satisfies + +;;; with apologies to christophe rhodes ... +(defun split (string &optional max (ws '(#\Space #\Tab))) + (flet ((is-ws (char) (find char ws))) + (nreverse + (let ((list nil) (start 0) (words 0) end) + (loop + (when (and max (>= words (1- max))) + (return (cons (subseq string start) list))) + (setf end (position-if #'is-ws string :start start)) + (push (subseq string start end) list) + (incf words) + (unless end (return list)) + (setf start (1+ end))))))) + +(defgeneric version-satisfies (component version)) + +(defmethod version-satisfies ((c component) version) + (unless (and version (slot-boundp c 'version)) + (return-from version-satisfies t)) + (let ((x (mapcar #'parse-integer + (split (component-version c) nil '(#\.)))) + (y (mapcar #'parse-integer + (split version nil '(#\.))))) + (labels ((bigger (x y) + (cond ((not y) t) + ((not x) nil) + ((> (car x) (car y)) t) + ((= (car x) (car y)) + (bigger (cdr x) (cdr y)))))) + (and (= (car x) (car y)) + (or (not (cdr y)) (bigger (cdr x) (cdr y))))))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; finding systems + +(defvar *defined-systems* (make-hash-table :test 'equal)) +(defun coerce-name (name) + (typecase name + (component (component-name name)) + (symbol (string-downcase (symbol-name name))) + (string name) + (t (sysdef-error (formatter "~@<invalid component designator ~A~@:>") + name)))) + +;;; for the sake of keeping things reasonably neat, we adopt a +;;; convention that functions in this list are prefixed SYSDEF- + +(defvar *system-definition-search-functions* + '(sysdef-central-registry-search)) + +(defun system-definition-pathname (system) + (some (lambda (x) (funcall x system)) + *system-definition-search-functions*)) + +(defvar *central-registry* + '(*default-pathname-defaults* + #+nil "/home/dan/src/sourceforge/cclan/asdf/systems/" + #+nil "telent:asdf;systems;")) + +(defun sysdef-central-registry-search (system) + (let ((name (coerce-name system))) + (block nil + (dolist (dir *central-registry*) + (let* ((defaults (eval dir)) + (file (and defaults + (make-pathname + :defaults defaults :version :newest + :name name :type "asd" :case :local)))) + (if (and file (probe-file file)) + (return file))))))) + + +(defun find-system (name &optional (error-p t)) + (let* ((name (coerce-name name)) + (in-memory (gethash name *defined-systems*)) + (on-disk (system-definition-pathname name))) + (when (and on-disk + (or (not in-memory) + (< (car in-memory) (file-write-date on-disk)))) + (let ((*package* (make-package (gensym (package-name #.*package*)) + :use '(:cl :asdf)))) + (format *verbose-out* + (formatter "~&~@<; ~@;loading system definition from ~A into ~A~@:>~%") + ;; FIXME: This wants to be (ENOUGH-NAMESTRING + ;; ON-DISK), but CMUCL barfs on that. + on-disk + *package*) + (load on-disk))) + (let ((in-memory (gethash name *defined-systems*))) + (if in-memory + (progn (if on-disk (setf (car in-memory) (file-write-date on-disk))) + (cdr in-memory)) + (if error-p (error 'missing-component :requires name)))))) + +(defun register-system (name system) + (format *verbose-out* + (formatter "~&~@<; ~@;registering ~A as ~A~@:>~%") system name) + (setf (gethash (coerce-name name) *defined-systems*) + (cons (get-universal-time) system))) + +(defun system-registered-p (name) + (gethash (coerce-name name) *defined-systems*)) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; finding components + +(defgeneric find-component (module name &optional version) + (:documentation "Finds the component with name NAME present in the +MODULE module; if MODULE is nil, then the component is assumed to be a +system.")) + +(defmethod find-component ((module module) name &optional version) + (if (slot-boundp module 'components) + (let ((m (find name (module-components module) + :test #'equal :key #'component-name))) + (if (and m (version-satisfies m version)) m)))) + + +;;; a component with no parent is a system +(defmethod find-component ((module (eql nil)) name &optional version) + (let ((m (find-system name nil))) + (if (and m (version-satisfies m version)) m))) + +;;; component subclasses + +(defclass source-file (component) ()) + +(defclass cl-source-file (source-file) ()) +(defclass c-source-file (source-file) ()) +(defclass java-source-file (source-file) ()) +(defclass static-file (source-file) ()) +(defclass doc-file (static-file) ()) +(defclass html-file (doc-file) ()) + +(defgeneric source-file-type (component system)) +(defmethod source-file-type ((c cl-source-file) (s module)) "lisp") +(defmethod source-file-type ((c c-source-file) (s module)) "c") +(defmethod source-file-type ((c java-source-file) (s module)) "java") +(defmethod source-file-type ((c html-file) (s module)) "html") +(defmethod source-file-type ((c static-file) (s module)) nil) + +(defmethod component-relative-pathname ((component source-file)) + (let* ((*default-pathname-defaults* (component-parent-pathname component)) + (name-type + (make-pathname + :name (component-name component) + :type (source-file-type component + (component-system component))))) + (if (slot-value component 'relative-pathname) + (merge-pathnames + (slot-value component 'relative-pathname) + name-type) + name-type))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; operations + +;;; one of these is instantiated whenever (operate ) is called + +(defclass operation () + ((forced :initform nil :initarg :force :accessor operation-forced) + (original-initargs :initform nil :initarg :original-initargs + :accessor operation-original-initargs) + (visited-nodes :initform nil :accessor operation-visited-nodes) + (visiting-nodes :initform nil :accessor operation-visiting-nodes) + (parent :initform nil :initarg :parent :accessor operation-parent))) + +(defmethod print-object ((o operation) stream) + (print-unreadable-object (o stream :type t :identity t) + (ignore-errors + (prin1 (operation-original-initargs o) stream)))) + +(defmethod shared-initialize :after ((operation operation) slot-names + &key force + &allow-other-keys) + (declare (ignore slot-names force)) + ;; empty method to disable initarg validity checking + ) + +(defgeneric perform (operation component)) +(defgeneric operation-done-p (operation component)) +(defgeneric explain (operation component)) +(defgeneric output-files (operation component)) +(defgeneric input-files (operation component)) + +(defun node-for (o c) + (cons (class-name (class-of o)) c)) + +(defgeneric operation-ancestor (operation) + (:documentation "Recursively chase the operation's parent pointer until we get to the head of the tree")) + +(defmethod operation-ancestor ((operation operation)) + (aif (operation-parent operation) + (operation-ancestor it) + operation)) + + +(defun make-sub-operation (c o dep-c dep-o) + (let* ((args (copy-list (operation-original-initargs o))) + (force-p (getf args :force))) + ;; note explicit comparison with T: any other non-NIL force value + ;; (e.g. :recursive) will pass through + (cond ((and (null (component-parent c)) + (null (component-parent dep-c)) + (not (eql c dep-c))) + (when (eql force-p t) + (setf (getf args :force) nil)) + (apply #'make-instance dep-o + :parent o + :original-initargs args args)) + ((subtypep (type-of o) dep-o) + o) + (t + (apply #'make-instance dep-o + :parent o :original-initargs args args))))) + + +(defgeneric visit-component (operation component data)) + +(defmethod visit-component ((o operation) (c component) data) + (unless (component-visited-p o c) + (push (cons (node-for o c) data) + (operation-visited-nodes (operation-ancestor o))))) + +(defgeneric component-visited-p (operation component)) + +(defmethod component-visited-p ((o operation) (c component)) + (assoc (node-for o c) + (operation-visited-nodes (operation-ancestor o)) + :test 'equal)) + +(defgeneric (setf visiting-component) (new-value operation component)) + +(defmethod (setf visiting-component) (new-value operation component) + ;; MCL complains about unused lexical variables + (declare (ignorable new-value operation component))) + +(defmethod (setf visiting-component) (new-value (o operation) (c component)) + (let ((node (node-for o c)) + (a (operation-ancestor o))) + (if new-value + (pushnew node (operation-visiting-nodes a) :test 'equal) + (setf (operation-visiting-nodes a) + (remove node (operation-visiting-nodes a) :test 'equal))))) + +(defgeneric component-visiting-p (operation component)) + +(defmethod component-visiting-p ((o operation) (c component)) + (let ((node (cons o c))) + (member node (operation-visiting-nodes (operation-ancestor o)) + :test 'equal))) + +(defgeneric component-depends-on (operation component)) + +(defmethod component-depends-on ((o operation) (c component)) + (cdr (assoc (class-name (class-of o)) + (slot-value c 'in-order-to)))) + +(defgeneric component-self-dependencies (operation component)) + +(defmethod component-self-dependencies ((o operation) (c component)) + (let ((all-deps (component-depends-on o c))) + (remove-if-not (lambda (x) + (member (component-name c) (cdr x) :test #'string=)) + all-deps))) + +(defmethod input-files ((operation operation) (c component)) + (let ((parent (component-parent c)) + (self-deps (component-self-dependencies operation c))) + (if self-deps + (mapcan (lambda (dep) + (destructuring-bind (op name) dep + (output-files (make-instance op) + (find-component parent name)))) + self-deps) + ;; no previous operations needed? I guess we work with the + ;; original source file, then + (list (component-pathname c))))) + +(defmethod input-files ((operation operation) (c module)) nil) + +(defmethod operation-done-p ((o operation) (c component)) + (let ((out-files (output-files o c)) + (in-files (input-files o c))) + (cond ((and (not in-files) (not out-files)) + ;; arbitrary decision: an operation that uses nothing to + ;; produce nothing probably isn't doing much + t) + ((not out-files) + (let ((op-done + (gethash (type-of o) + (component-operation-times c)))) + (and op-done + (>= op-done + (or (apply #'max + (mapcar #'file-write-date in-files)) 0))))) + ((not in-files) nil) + (t + (and + (every #'probe-file out-files) + (> (apply #'min (mapcar #'file-write-date out-files)) + (apply #'max (mapcar #'file-write-date in-files)) )))))) + +;;; So you look at this code and think "why isn't it a bunch of +;;; methods". And the answer is, because standard method combination +;;; runs :before methods most->least-specific, which is back to front +;;; for our purposes. And CLISP doesn't have non-standard method +;;; combinations, so let's keep it simple and aspire to portability + +(defgeneric traverse (operation component)) +(defmethod traverse ((operation operation) (c component)) + (let ((forced nil)) + (labels ((do-one-dep (required-op required-c required-v) + (let* ((dep-c (or (find-component + (component-parent c) + ;; XXX tacky. really we should build the + ;; in-order-to slot with canonicalized + ;; names instead of coercing this late + (coerce-name required-c) required-v) + (error 'missing-dependency :required-by c + :version required-v + :requires required-c))) + (op (make-sub-operation c operation dep-c required-op))) + (traverse op dep-c))) + (do-dep (op dep) + (cond ((eq op 'feature) + (or (member (car dep) *features*) + (error 'missing-dependency :required-by c + :requires (car dep) :version nil))) + (t + (dolist (d dep) + (cond ((consp d) + (assert (string-equal + (symbol-name (first d)) + "VERSION")) + (appendf forced + (do-one-dep op (second d) (third d)))) + (t + (appendf forced (do-one-dep op d nil))))))))) + (aif (component-visited-p operation c) + (return-from traverse + (if (cdr it) (list (cons 'pruned-op c)) nil))) + ;; dependencies + (if (component-visiting-p operation c) + (error 'circular-dependency :components (list c))) + (setf (visiting-component operation c) t) + (loop for (required-op . deps) in (component-depends-on operation c) + do (do-dep required-op deps)) + ;; constituent bits + (let ((module-ops + (when (typep c 'module) + (let ((at-least-one nil) + (forced nil) + (error nil)) + (loop for kid in (module-components c) + do (handler-case + (appendf forced (traverse operation kid )) + (missing-dependency (condition) + (if (eq (module-if-component-dep-fails c) :fail) + (error condition)) + (setf error condition)) + (:no-error (c) + (declare (ignore c)) + (setf at-least-one t)))) + (when (and (eq (module-if-component-dep-fails c) :try-next) + (not at-least-one)) + (error error)) + forced)))) + ;; now the thing itself + (when (or forced module-ops + (not (operation-done-p operation c)) + (let ((f (operation-forced (operation-ancestor operation)))) + (and f (or (not (consp f)) + (member (component-name + (operation-ancestor operation)) + (mapcar #'coerce-name f) + :test #'string=))))) + (let ((do-first (cdr (assoc (class-name (class-of operation)) + (slot-value c 'do-first))))) + (loop for (required-op . deps) in do-first + do (do-dep required-op deps))) + (setf forced (append (delete 'pruned-op forced :key #'car) + (delete 'pruned-op module-ops :key #'car) + (list (cons operation c)))))) + (setf (visiting-component operation c) nil) + (visit-component operation c (and forced t)) + forced))) + + +(defmethod perform ((operation operation) (c source-file)) + (sysdef-error + (formatter "~@<required method PERFORM not implemented~ + for operation ~A, component ~A~@:>") + (class-of operation) (class-of c))) + +(defmethod perform ((operation operation) (c module)) + nil) + +(defmethod explain ((operation operation) (component component)) + (format *verbose-out* "~&;;; ~A on ~A~%" + operation component)) + +;;; compile-op + +(defclass compile-op (operation) + ((proclamations :initarg :proclamations :accessor compile-op-proclamations :initform nil) + (on-warnings :initarg :on-warnings :accessor operation-on-warnings + :initform *compile-file-warnings-behaviour*) + (on-failure :initarg :on-failure :accessor operation-on-failure + :initform *compile-file-failure-behaviour*))) + +(defmethod perform :before ((operation compile-op) (c source-file)) + (map nil #'ensure-directories-exist (output-files operation c))) + +(defmethod perform :after ((operation operation) (c component)) + (setf (gethash (type-of operation) (component-operation-times c)) + (get-universal-time))) + +;;; perform is required to check output-files to find out where to put +;;; its answers, in case it has been overridden for site policy +(defmethod perform ((operation compile-op) (c cl-source-file)) + (let ((source-file (component-pathname c)) + (output-file (car (output-files operation c)))) + (multiple-value-bind (output warnings-p failure-p) + (compile-file source-file + :output-file output-file) + ;(declare (ignore output)) + (when warnings-p + (case (operation-on-warnings operation) + (:warn (warn + (formatter "~@<COMPILE-FILE warned while ~ + performing ~A on ~A.~@:>") + operation c)) + (:error (error 'compile-warned :component c :operation operation)) + (:ignore nil))) + (when failure-p + (case (operation-on-failure operation) + (:warn (warn + (formatter "~@<COMPILE-FILE failed while ~ + performing ~A on ~A.~@:>") + operation c)) + (:error (error 'compile-failed :component c :operation operation)) + (:ignore nil))) + (unless output + (error 'compile-error :component c :operation operation))))) + +(defmethod output-files ((operation compile-op) (c cl-source-file)) + (list (compile-file-pathname (component-pathname c)))) + +(defmethod perform ((operation compile-op) (c static-file)) + nil) + +(defmethod output-files ((operation compile-op) (c static-file)) + nil) + +;;; load-op + +(defclass load-op (operation) ()) + +(defmethod perform ((o load-op) (c cl-source-file)) + (mapcar #'load (input-files o c))) + +(defmethod perform ((operation load-op) (c static-file)) + nil) +(defmethod operation-done-p ((operation load-op) (c static-file)) + t) + +(defmethod output-files ((o operation) (c component)) + nil) + +(defmethod component-depends-on ((operation load-op) (c component)) + (cons (list 'compile-op (component-name c)) + (call-next-method))) + +;;; load-source-op + +(defclass load-source-op (operation) ()) + +(defmethod perform ((o load-source-op) (c cl-source-file)) + (let ((source (component-pathname c))) + (setf (component-property c 'last-loaded-as-source) + (and (load source) + (get-universal-time))))) + +(defmethod perform ((operation load-source-op) (c static-file)) + nil) + +(defmethod output-files ((operation load-source-op) (c component)) + nil) + +;;; FIXME: we simply copy load-op's dependencies. this is Just Not Right. +(defmethod component-depends-on ((o load-source-op) (c component)) + (let ((what-would-load-op-do (cdr (assoc 'load-op + (slot-value c 'in-order-to))))) + (mapcar (lambda (dep) + (if (eq (car dep) 'load-op) + (cons 'load-source-op (cdr dep)) + dep)) + what-would-load-op-do))) + +(defmethod operation-done-p ((o load-source-op) (c source-file)) + (if (or (not (component-property c 'last-loaded-as-source)) + (> (file-write-date (component-pathname c)) + (component-property c 'last-loaded-as-source))) + nil t)) + +(defclass test-op (operation) ()) + +(defmethod perform ((operation test-op) (c component)) + nil) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; invoking operations + +(defun operate (operation-class system &rest args) + (let* ((op (apply #'make-instance operation-class + :original-initargs args args)) + (*verbose-out* + (if (getf args :verbose t) + *trace-output* + (make-broadcast-stream))) + (system (if (typep system 'component) system (find-system system))) + (steps (traverse op system))) + (with-compilation-unit () + (loop for (op . component) in steps do + (loop + (restart-case + (progn (perform op component) + (return)) + (retry () + :report + (lambda (s) + (format s + (formatter "~@<Retry performing ~S on ~S.~@:>") + op component))) + (accept () + :report + (lambda (s) + (format s + (formatter "~@<Continue, treating ~S on ~S as ~ + having been successful.~@:>") + op component)) + (setf (gethash (type-of op) + (component-operation-times component)) + (get-universal-time)) + (return)))))))) + +(defun oos (&rest args) + "Alias of OPERATE function" + (apply #'operate args)) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; syntax + +(defun remove-keyword (key arglist) + (labels ((aux (key arglist) + (cond ((null arglist) nil) + ((eq key (car arglist)) (cddr arglist)) + (t (cons (car arglist) (cons (cadr arglist) + (remove-keyword + key (cddr arglist)))))))) + (aux key arglist))) + +(defmacro defsystem (name &body options) + (destructuring-bind (&key pathname (class 'system) &allow-other-keys) options + (let ((component-options (remove-keyword :class options))) + `(progn + ;; system must be registered before we parse the body, otherwise + ;; we recur when trying to find an existing system of the same name + ;; to reuse options (e.g. pathname) from + (let ((s (system-registered-p ',name))) + (cond ((and s (eq (type-of (cdr s)) ',class)) + (setf (car s) (get-universal-time))) + (s + #+clisp + (sysdef-error "Cannot redefine the existing system ~A with a different class" s) + #-clisp + (change-class (cdr s) ',class)) + (t + (register-system (quote ,name) + (make-instance ',class :name ',name))))) + (parse-component-form nil (apply + #'list + :module (coerce-name ',name) + :pathname + (or ,pathname + (pathname-sans-name+type + (resolve-symlinks *load-truename*)) + *default-pathname-defaults*) + ',component-options)))))) + + +(defun class-for-type (parent type) + (let ((class (find-class + (or (find-symbol (symbol-name type) *package*) + (find-symbol (symbol-name type) #.*package*)) nil))) + (or class + (and (eq type :file) + (or (module-default-component-class parent) + (find-class 'cl-source-file))) + (sysdef-error (formatter "~@<don't recognize component type ~A~@:>") + type)))) + +(defun maybe-add-tree (tree op1 op2 c) + "Add the node C at /OP1/OP2 in TREE, unless it's there already. +Returns the new tree (which probably shares structure with the old one)" + (let ((first-op-tree (assoc op1 tree))) + (if first-op-tree + (progn + (aif (assoc op2 (cdr first-op-tree)) + (if (find c (cdr it)) + nil + (setf (cdr it) (cons c (cdr it)))) + (setf (cdr first-op-tree) + (acons op2 (list c) (cdr first-op-tree)))) + tree) + (acons op1 (list (list op2 c)) tree)))) + +(defun union-of-dependencies (&rest deps) + (let ((new-tree nil)) + (dolist (dep deps) + (dolist (op-tree dep) + (dolist (op (cdr op-tree)) + (dolist (c (cdr op)) + (setf new-tree + (maybe-add-tree new-tree (car op-tree) (car op) c)))))) + new-tree)) + + +(defun remove-keys (key-names args) + (loop for ( name val ) on args by #'cddr + unless (member (symbol-name name) key-names + :key #'symbol-name :test 'equal) + append (list name val))) + +(defvar *serial-depends-on*) + +(defun parse-component-form (parent options) + (destructuring-bind + (type name &rest rest &key + ;; the following list of keywords is reproduced below in the + ;; remove-keys form. important to keep them in sync + components pathname default-component-class + perform explain output-files operation-done-p + depends-on serial in-order-to + ;; list ends + &allow-other-keys) options + (check-component-input type name depends-on components in-order-to) + (let* ((other-args (remove-keys + '(components pathname default-component-class + perform explain output-files operation-done-p + depends-on serial in-order-to) + rest)) + (ret + (or (find-component parent name) + (make-instance (class-for-type parent type))))) + (when (boundp '*serial-depends-on*) + (setf depends-on + (concatenate 'list *serial-depends-on* depends-on))) + (apply #'reinitialize-instance + ret + :name (coerce-name name) + :pathname pathname + :parent parent + other-args) + (when (typep ret 'module) + (setf (module-default-component-class ret) + (or default-component-class + (and (typep parent 'module) + (module-default-component-class parent)))) + (let ((*serial-depends-on* nil)) + (setf (module-components ret) + (loop for c-form in components + for c = (parse-component-form ret c-form) + collect c + if serial + do (push (component-name c) *serial-depends-on*))))) + + (setf (slot-value ret 'in-order-to) + (union-of-dependencies + in-order-to + `((compile-op (compile-op ,@depends-on)) + (load-op (load-op ,@depends-on)))) + (slot-value ret 'do-first) `((compile-op (load-op ,@depends-on)))) + + (loop for (n v) in `((perform ,perform) (explain ,explain) + (output-files ,output-files) + (operation-done-p ,operation-done-p)) + do (map 'nil + ;; this is inefficient as most of the stored + ;; methods will not be for this particular gf n + ;; But this is hardly performance-critical + (lambda (m) (remove-method (symbol-function n) m)) + (component-inline-methods ret)) + when v + do (destructuring-bind (op qual (o c) &body body) v + (pushnew + (eval `(defmethod ,n ,qual ((,o ,op) (,c (eql ,ret))) + ,@body)) + (component-inline-methods ret)))) + ret))) + +(defun check-component-input (type name depends-on components in-order-to) + "A partial test of the values of a component." + (unless (listp depends-on) + (sysdef-error-component ":depends-on must be a list." + type name depends-on)) + (unless (listp components) + (sysdef-error-component ":components must be NIL or a list of components." + type name components)) + (unless (and (listp in-order-to) (listp (car in-order-to))) + (sysdef-error-component ":in-order-to must be NIL or a list of components." + type name in-order-to))) + +(defun sysdef-error-component (msg type name value) + (sysdef-error (concatenate 'string msg + "~&The value specified for ~(~A~) ~A is ~W") + type name value)) + +(defun resolve-symlinks (path) + #-allegro (truename path) + #+allegro (excl:pathname-resolve-symbolic-links path) + ) + +;;; optional extras + +;;; run-shell-command functions for other lisp implementations will be +;;; gratefully accepted, if they do the same thing. If the docstring +;;; is ambiguous, send a bug report + +(defun run-shell-command (control-string &rest args) + "Interpolate ARGS into CONTROL-STRING as if by FORMAT, and +synchronously execute the result using a Bourne-compatible shell, with +output to *verbose-out*. Returns the shell's exit code." + (let ((command (apply #'format nil control-string args))) + (format *verbose-out* "; $ ~A~%" command) + #+sbcl + (sb-impl::process-exit-code + (sb-ext:run-program + "/bin/sh" + (list "-c" command) + :input nil :output *verbose-out*)) + + #+(or cmu scl) + (ext:process-exit-code + (ext:run-program + "/bin/sh" + (list "-c" command) + :input nil :output *verbose-out*)) + + #+allegro + (excl:run-shell-command command :input nil :output *verbose-out*) + + #+lispworks + (system:call-system-showing-output + command + :shell-type "/bin/sh" + :output-stream *verbose-out*) + + #+clisp ;XXX not exactly *verbose-out*, 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 *verbose-out* + :wait t))) + + #-(or openmcl clisp lispworks allegro scl cmu sbcl) + (error "RUN-SHELL-PROGRAM not implemented for this Lisp") + )) + + +(defgeneric hyperdocumentation (package name doc-type)) +(defmethod hyperdocumentation ((package symbol) name doc-type) + (hyperdocumentation (find-package package) name doc-type)) + +(defun hyperdoc (name doc-type) + (hyperdocumentation (symbol-package name) name doc-type)) + + +(pushnew :asdf *features*) + +#+sbcl +(eval-when (:compile-toplevel :load-toplevel :execute) + (when (sb-ext:posix-getenv "SBCL_BUILDING_CONTRIB") + (pushnew :sbcl-hooks-require *features*))) + +#+(and sbcl sbcl-hooks-require) +(progn + (defun module-provide-asdf (name) + (handler-bind ((style-warning #'muffle-warning)) + (let* ((*verbose-out* (make-broadcast-stream)) + (system (asdf:find-system name nil))) + (when system + (asdf:operate 'asdf:load-op name) + t)))) + + (pushnew + '(merge-pathnames "systems/" + (truename (sb-ext:posix-getenv "SBCL_HOME"))) + *central-registry*) + + (pushnew + '(merge-pathnames "site-systems/" + (truename (sb-ext:posix-getenv "SBCL_HOME"))) + *central-registry*) + + (pushnew + '(merge-pathnames ".sbcl/systems/" + (user-homedir-pathname)) + *central-registry*) + + (pushnew 'module-provide-asdf sb-ext:*module-provider-functions*)) + +(provide 'asdf) diff --git a/Lisp/asdf/asdf.texinfo b/Lisp/asdf/asdf.texinfo new file mode 100644 index 0000000..e62e2aa --- /dev/null +++ b/Lisp/asdf/asdf.texinfo @@ -0,0 +1,1220 @@ +\input texinfo @c -*- texinfo -*- +@c %**start of header +@setfilename asdf.texinfo +@settitle asdf Manual +@c %**end of header + +@copying +This manual describes asdf, a system definition facility for Common +Lisp programs and libraries. + +asdf Copyright @copyright{} 2001-2004 Daniel Barlow and contributors + +This manual Copyright @copyright{} 2001-2004 Daniel Barlow and +contributors + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +``Software''), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +@end copying + + + +@titlepage +@title asdf: another system definition facility + +@c The following two commands start the copyright page. +@page +@vskip 0pt plus 1filll +@insertcopying +@end titlepage + +@c Output the table of contents at the beginning. +@contents + +@c ------------------- + +@ifnottex + +@node Top, Using asdf to load systems, (dir), (dir) +@top asdf: another system definition facility + +@insertcopying + +@menu +* Using asdf to load systems:: +* Defining systems with defsystem:: +* The object model of asdf:: +* Error handling:: +* Compilation error and warning handling:: +* Getting the latest version:: +* TODO list:: +* missing bits in implementation:: +* Inspiration:: +* Concept Index:: +* Function and Class Index:: +* Variable Index:: + +@detailmenu + --- The Detailed Node Listing --- + +Defining systems with defsystem + +* The defsystem form:: +* A more involved example:: +* The defsystem grammar:: + +The object model of asdf + +* Operations:: +* Components:: + +Operations + +* Predefined operations of asdf:: +* Creating new operations:: + +Components + +* Common attributes of components:: +* Pre-defined subclasses of component:: +* Creating new component types:: + +properties + +* Pre-defined subclasses of component:: +* Creating new component types:: + +@end detailmenu +@end menu + +@end ifnottex + +@c ------------------- + + +@node Using asdf to load systems, Defining systems with defsystem, Top, Top +@comment node-name, next, previous, up +@chapter Using asdf to load systems +@cindex system directory designator +@vindex *central-registry* + +This chapter describes how to use asdf to compile and load ready-made +Lisp programs and libraries. + +@section Downloading asdf + +Some Lisp implementations (such as SBCL and OpenMCL) some with asdf +included already, so there is no need to download it separately. +Consult your Lisp system's documentation. If you need to download +asdf and install it by hand, the canonical source is the cCLan CVS +repository at +@url{http://cvs.sourceforge.net/cgi-bin/viewcvs.cgi/cclan/asdf/}. + +@section Setting up asdf + +The single file @file{asdf.lisp} is all you need to use asdf normally. +Once you load it in a running Lisp, you're ready to use asdf. For +maximum convenience you might want to have asdf loaded whenever you +start your Lisp implementation, for example by loading it from the +startup script or dumping a custom core -- check your Lisp +implementation's manual for details. + +The variable @code{asdf:*central-registry*} is a list of ``system +directory designators''@footnote{When we say ``directory'' here, we mean +``designator for a pathname with a supplied DIRECTORY component''.}. +A @dfn{system directory designator} is a form which will be evaluated +whenever a system is to be found, and must evaluate to a directory to +look in. You might want to set @code{*central-registry*} in your Lisp +init file, for example: + +@lisp +(setf asdf:*central-registry* + '(*default-pathname-defaults* + #p"/home/me/cl/systems/" + #p"/usr/share/common-lisp/systems/")) +@end lisp + +@section Setting up a system to be loaded + +To compile and load a system, you need to ensure that a symbolic link to its +system definition is in one of the directories in +@code{*central-registry*}@footnote{It is possible to customize the +system definition file search. That's considered advanced use, and +covered later: search forward for +@code{*system-definition-search-functions*}. @xref{Defining systems +with defsystem}.}. + +For example, if @code{#p"/home/me/cl/systems/"} (note the trailing +slash) is a member of @code{*central-registry*}, you would set up a +system @var{foo} that is stored in a directory +@file{/home/me/src/foo/} for loading with asdf with the following +commands at the shell (this has to be done only once): + +@example +$ cd /home/me/cl/systems/ +$ ln -s ~/src/foo/foo.asd . +@end example + +@section Loading a system + +The system @var{foo} is loaded (and compiled, if necessary) by +evaluating the following form in your Lisp implementation: + +@example +(asdf:operate 'asdf:load-op '@var{foo}) +@end example + +That's all you need to know to use asdf to load systems written by +others. The rest of this manual deals with writing system +definitions for Lisp software you write yourself. + +@node Defining systems with defsystem, The object model of asdf, Using asdf to load systems, Top +@comment node-name, next, previous, up +@chapter Defining systems with defsystem + +This chapter describes how to use asdf to define systems and develop +software. + + +@menu +* The defsystem form:: +* A more involved example:: +* The defsystem grammar:: +@end menu + +@node The defsystem form, A more involved example, Defining systems with defsystem, Defining systems with defsystem +@comment node-name, next, previous, up +@section The defsystem form + +Systems can be constructed programmatically by instantiating +components using make-instance. Most of the time, however, it is much +more practical to use a static @code{defsystem} form. This section +begins with an example of a system definition, then gives the full +grammar of @code{defsystem}. + +Let's look at a simple system. This is a complete file that would +usually be saved as @file{hello-lisp.asd}: + +@lisp +(defpackage hello-lisp-system + (:use :common-lisp :asdf)) + +(in-package :hello-lisp-system) + +(defsystem "hello-lisp" + :description "hello-lisp: a sample Lisp system." + :version "0.2" + :author "Joe User <joe@@example.com>" + :licence "Public Domain" + :components ((:file "packages") + (:file "macros" :depends-on ("packages")) + (:file "hello" :depends-on ("macros")))) +@end lisp + +Some notes about this example: + +@itemize + +@item +The file starts with @code{defpackage} and @code{in-package} forms to +make and use a package expressly for defining this system in. This +package is named by taking the system name and suffixing +@code{-system} - note that it is @emph{not} the same package as you +will use for the application code. + +This is not absolutely required by asdf, but helps avoid namespace +pollution and so is considered good form. + +@item +The defsystem form defines a system named "hello-lisp" that contains +three source files: @file{packages}, @file{macros} and @file{hello}. + +@item +The file @file{macros} depends on @file{packages} (presumably because +the package it's in is defined in @file{packages}), and the file +@file{hello} depends on @file{macros} (and hence, transitively on +@file{packages}). This means that asdf will compile and load +@file{packages} and @file{macros} before starting the compilation of +file @file{hello}. + + +@item +The files are located in the same directory as the file with the +system definition. asdf resolves symbolic links before loading the system +definition file and stores its location in the resulting +system@footnote{It is possible, though almost never necessary, to +override this behaviour.}. This is a good thing because the user can +move the system sources without having to edit the system definition. + +@end itemize + +@node A more involved example, The defsystem grammar, The defsystem form, Defining systems with defsystem +@comment node-name, next, previous, up +@section A more involved example + +Let's illustrate some more involved uses of @code{defsystem} via a +slightly convoluted example: + +@lisp +(defsystem "foo" + :version "1.0" + :components ((:module "foo" :components ((:file "bar") (:file"baz") + (:file "quux")) + :perform (compile-op :after (op c) + (do-something c)) + :explain (compile-op :after (op c) + (explain-something c))) + (:file "blah"))) +@end lisp + +The method-form tokens need explaining: essentially, this part: + +@lisp + :perform (compile-op :after (op c) + (do-something c)) + :explain (compile-op :after (op c) + (explain-something c)) +@end lisp + +has the effect of + +@lisp +(defmethod perform :after ((op compile-op) (c (eql ...))) + (do-something c)) +(defmethod explain :after ((op compile-op) (c (eql ...))) + (explain-something c)) +@end lisp + +where @code{...} is the component in question; note that although this +also supports @code{:before} methods, they may not do what you want +them to -- a @code{:before} method on perform @code{((op compile-op) (c +(eql ...)))} will run after all the dependencies and sub-components +have been processed, but before the component in question has been +compiled. + +@node The defsystem grammar, , A more involved example, Defining systems with defsystem +@comment node-name, next, previous, up +@section The defsystem grammar + +@verbatim +system-definition := ( defsystem system-designator {option}* ) + +option := :components component-list + | :pathname pathname + | :default-component-class + | :perform method-form + | :explain method-form + | :output-files method-form + | :operation-done-p method-form + | :depends-on ( {simple-component-name}* ) + | :serial [ t | nil ] + | :in-order-to ( {dependency}+ ) + +component-list := ( {component-def}* ) + +component-def := simple-component-name + | ( component-type name {option}* ) + +component-type := :module | :file | :system | other-component-type + +dependency := (dependent-op {requirement}+) +requirement := (required-op {required-component}+) + | (feature feature-name) +dependent-op := operation-name +required-op := operation-name | feature +@end verbatim + +@subsection Serial dependencies + +If the @code{:serial t} option is specified for a module, asdf will add +dependencies for each each child component, on all the children +textually preceding it. This is done as if by @code{:depends-on}. + +@lisp +:components ((:file "a") (:file "b") (:file "c")) +:serial t +@end lisp + +is equivalent to + +@lisp +:components ((:file "a") + (:file "b" :depends-on ("a")) + (:file "c" :depends-on ("a" "b"))) +@end lisp + + +@subsection Source location + +The @code{:pathname} option is optional in all cases for systems +defined via @code{defsystem}, and in the usual case the user is +recommended not to supply it. + +Instead, asdf follows a hairy set of rules that are designed so that +@enumerate +@item @code{find-system} will load a system from disk and have its pathname +default to the right place +@item this pathname information will not be +overwritten with @code{*default-pathname-defaults*} (which could be +somewhere else altogether) if the user loads up the @file{.asd} file +into his editor and interactively re-evaluates that form. +@end enumerate + +If a system is being loaded for the first time, its top-level pathname +will be set to: + +@itemize +@item The host/device/directory parts of @code{*load-truename*}, if it is bound +@item @code{*default-pathname-defaults*}, otherwise +@end itemize + +If a system is being redefined, the top-level pathname will be + +@itemize +@item +changed, if explicitly supplied or obtained from +@code{*load-truename*} (so that an updated source location is +reflected in the system definition) +@item +changed if it had previously been set from +@code{*default-pathname-defaults*} +@item +left as before, if it had previously been set from +@code{*load-truename*} and @code{*load-truename*} is currently +unbound (so that a developer can evaluate a @code{defsystem} form from +within an editor without clobbering its source location) +@end itemize + + + +@node The object model of asdf, Error handling, Defining systems with defsystem, Top +@comment node-name, next, previous, up +@chapter The object model of asdf + +asdf is designed in an object-oriented way from the ground up. Both a +system's structure and the operations that can be performed on systems +follow a protocol. asdf is extensible to new operations and to new +component types. This allows the addition of behaviours: for example, +a new component could be added for Java JAR archives, and methods +specialised on @code{compile-op} added for it that would accomplish the +relevant actions. + +This chapter deals with @emph{components}, the building blocks of a +system, and @emph{operations}, the actions that can be performed on a +system. + + + +@menu +* Operations:: +* Components:: +@end menu + +@node Operations, Components, The object model of asdf, The object model of asdf +@comment node-name, next, previous, up +@section Operations +@cindex operation + +An @dfn{operation} object of the appropriate type is instantiated +whenever the user wants to do something with a system like + +@itemize +@item compile all its files +@item load the files into a running lisp environment +@item copy its source files somewhere else +@end itemize + +Operations can be invoked directly, or examined to see what their +effects would be without performing them. @emph{FIXME: document how!} There +are a bunch of methods specialised on operation and component type +that actually do the grunt work. + +The operation object contains whatever state is relevant for this +purpose (perhaps a list of visited nodes, for example) but primarily +is a nice thing to specialise operation methods on and easier than +having them all be EQL methods. + +Operations are invoked on systems via @code{operate}. + +@deffn {Generic function} operate operation system &rest initargs +@deffnx {Generic function} oos operation system &rest initargs +@code{operate} invokes @var{operation} on @var{system}. @code{oos} +is a synonym for @code{operate}. + +@var{operation} is a symbol that is passed, along with the supplied +@var{initargs}, to @code{make-instance} to create the operation object. +@var{system} is a system designator. + +The initargs are passed to the @code{make-instance} call when creating +the operation object. Note that dependencies may cause the operation +to invoke other operations on the system or its components: the new +operations will be created with the same initargs as the original one. + +@end deffn + +@menu +* Predefined operations of asdf:: +* Creating new operations:: +@end menu + +@node Predefined operations of asdf, Creating new operations, Operations, Operations +@comment node-name, next, previous, up +@subsection Predefined operations of asdf + +All the operations described in this section are in the @code{asdf} +package. They are invoked via the @code{operate} generic function. + +@lisp +(asdf:operate 'asdf:@var{operation-name} '@var{system-name} @{@var{operation-options ...}@}) +@end lisp + +@deffn Operation compile-op &key proclamations + +This operation compiles the specified component. If proclamations are +supplied, they will be proclaimed. This is a good place to specify +optimization settings. + +When creating a new component type, you should provide methods for +@code{compile-op}. + +When @code{compile-op} is invoked, component dependencies often cause +some parts of the system to be loaded as well as compiled. Invoking +@code{compile-op} does not necessarily load all the parts of the +system, though; use @code{load-op} to load a system. +@end deffn + +@deffn Operation load-op &key proclamations + +This operation loads a system. + +The default methods for @code{load-op} compile files before loading them. +For parity, your own methods on new component types should probably do +so too. +@end deffn + +@deffn Operation load-source-op + +This operation will load the source for the files in a module even if +the source files have been compiled. Systems sometimes have knotty +dependencies which require that sources are loaded before they can be +compiled. This is how you do that. + +If you are creating a component type, you need to implement this +operation - at least, where meaningful. +@end deffn + +@deffn Operation test-system-version &key minimum + +Asks the system whether it satisfies a version requirement. + +The default method accepts a string, which is expected to contain of a +number of integers separated by #\. characters. The method is not +recursive. The component satisfies the version dependency if it has +the same major number as required and each of its sub-versions is +greater than or equal to the sub-version number required. + +@lisp +(defun version-satisfies (x y) + (labels ((bigger (x y) + (cond ((not y) t) + ((not x) nil) + ((> (car x) (car y)) t) + ((= (car x) (car y)) + (bigger (cdr x) (cdr y)))))) + (and (= (car x) (car y)) + (or (not (cdr y)) (bigger (cdr x) (cdr y)))))) +@end lisp + +If that doesn't work for your system, you can override it. I hope +you have as much fun writing the new method as @verb{|#lisp|} did +reimplementing this one. +@end deffn + +@deffn Operation feature-dependent-op + +An instance of @code{feature-dependent-op} will ignore any components +which have a @code{features} attribute, unless the feature combination +it designates is satisfied by @code{*features*}. This operation is +not intended to be instantiated directly, but other operations may +inherit from it. + +@end deffn + +@node Creating new operations, , Predefined operations of asdf, Operations +@comment node-name, next, previous, up +@subsection Creating new operations + +asdf was designed to be extensible in an object-oriented fashion. To +teach asdf new tricks, a programmer can implement the behaviour he +wants by creating a subclass of @code{operation}. + + +asdf's pre-defined operations are in no way ``privileged'', but it is +requested that developers never use the @code{asdf} package for +operations they develop themselves. The rationale for this rule is +that we don't want to establish a ``global asdf operation name +registry'', but also want to avoid name clashes. + +An operation must provide methods for the following generic functions +when invoked with an object of type @code{source-file}: @emph{FIXME describe +this better} + +@itemize + +@item @code{output-files} +@item @code{perform} +The @code{perform} method must call @code{output-files} to find out +where to put its files, because the user is allowed to override +@item @code{output-files} for local policy @code{explain} +@item @code{operation-done-p}, if you don't like the default one + +@end itemize + +@node Components, , Operations, The object model of asdf +@comment node-name, next, previous, up +@section Components +@cindex component +@cindex system +@cindex system designator +@vindex *system-definition-search-functions* + +A @dfn{component} represents a source file or (recursively) a +collection of components. A @dfn{system} is (roughly speaking) a +top-level component that can be found via @code{find-system}. + +A @dfn{system designator} is a string or symbol and behaves just like +any other component name (including with regard to the case conversion +rules for component names). + + +@defun find-system system-designator &optional (error-p t) + +Given a system designator, @code{find-system} finds and returns a +system. If no system is found, an error of type +@code{missing-component} is thrown, or @code{nil} is returned if +@code{error-p} is false. + +To find and update systems, @code{find-system} funcalls each element +in the @code{*system-definition-search-functions*} list, expecting a +pathname to be returned. The resulting pathname is loaded if either +of the following conditions is true: + +@itemize +@item there is no system of that name in memory +@item the file's last-modified time exceeds the last-modified time of the + system in memory +@end itemize + +When system definitions are loaded from @file{.asd} files, a new +scratch package is created for them to load into, so that different +systems do not overwrite each others operations. The user may also +wish to (and is recommended to) include @code{defpackage} and +@code{in-package} forms in his system definition files, however, so +that they can be loaded manually if need be. + +The default value of @code{*system-definition-search-functions*} is a +function that looks in each of the directories given by evaluating +members of @code{*central-registry*} for a file whose name is the +name of the system and whose type is @file{asd}. The first such file +is returned, whether or not it turns out to actually define the +appropriate system. Hence, it is strongly advised to define a system +@var{foo} in the corresponding file @var{foo.asd}. +@end defun + + +@menu +* Common attributes of components:: +* Pre-defined subclasses of component:: +* Creating new component types:: +@end menu + +@node Common attributes of components, Pre-defined subclasses of component, Components, Components +@comment node-name, next, previous, up +@subsection Common attributes of components + +All components, regardless of type, have the following attributes. +All attributes except @code{name} are optional. + +@subsubsection Name + +A component name is a string or a symbol. If a symbol, its name is +taken and lowercased. The name must be a suitable value for the +@code{:name} initarg to @code{make-pathname} in whatever filesystem +the system is to be found. + +The lower-casing-symbols behaviour is unconventional, but was selected +after some consideration. Observations suggest that the type of +systems we want to support either have lowercase as customary case +(Unix, Mac, windows) or silently convert lowercase to uppercase +(lpns), so this makes more sense than attempting to use @code{:case +:common} as argument to @code{make-pathname}, which is reported not to +work on some implementations + +@subsubsection Version identifier + +This optional attribute is used by the test-system-version +operation. @xref{Predefined operations of asdf}. For the default method of +test-system-version, the version should be a string of intergers +separated by dots, for example @samp{1.0.11}. + +@subsubsection Required features + +Traditionally defsystem users have used reader conditionals to include +or exclude specific per-implementation files. This means that any +single implementation cannot read the entire system, which becomes a +problem if it doesn't wish to compile it, but instead for example to +create an archive file containing all the sources, as it will omit to +process the system-dependent sources for other systems. + +Each component in an asdf system may therefore specify features using +the same syntax as #+ does, and it will (somehow) be ignored for +certain operations unless the feature conditional is a member of +@code{*features*}. + + +@subsubsection Dependencies + +This attribute specifies dependencies of the component on its +siblings. It is optional but often necessary. + +There is an excitingly complicated relationship between the initarg +and the method that you use to ask about dependencies + +Dependencies are between (operation component) pairs. In your +initargs for the component, you can say + +@lisp +:in-order-to ((compile-op (load-op "a" "b") (compile-op "c")) + (load-op (load-op "foo"))) +@end lisp + +This means the following things: +@itemize +@item +before performing compile-op on this component, we must perform +load-op on @var{a} and @var{b}, and compile-op on @var{c}, +@item +before performing @code{load-op}, we have to load @var{foo} +@end itemize + +The syntax is approximately + +@verbatim +(this-op {(other-op required-components)}+) + +required-components := component-name + | (required-components required-components) + +component-name := string + | (:version string minimum-version-object) +@end verbatim + +Side note: + +This is on a par with what ACL defsystem does. mk-defsystem is less +general: it has an implied dependency + +@verbatim + for all x, (load x) depends on (compile x) +@end verbatim + +and using a @code{:depends-on} argument to say that @var{b} depends on +@var{a} @emph{actually} means that + +@verbatim + (compile b) depends on (load a) +@end verbatim + +This is insufficient for e.g. the McCLIM system, which requires that +all the files are loaded before any of them can be compiled ] + +End side note + +In asdf, the dependency information for a given component and +operation can be queried using @code{(component-depends-on operation +component)}, which returns a list + +@lisp +((load-op "a") (load-op "b") (compile-op "c") ...) +@end lisp + +@code{component-depends-on} can be subclassed for more specific +component/operation types: these need to @code{(call-next-method)} and +append the answer to their dependency, unless they have a good reason +for completely overriding the default dependencies + +(If it weren't for CLISP, we'd be using a @code{LIST} method +combination to do this transparently. But, we need to support CLISP. +If you have the time for some CLISP hacking, I'm sure they'd welcome +your fixes) + +@subsubsection pathname + +This attribute is optional and if absent will be inferred from the +component's name, type (the subclass of source-file), and the location +of its parent. + +The rules for this inference are: + +(for source-files) +@itemize +@item the host is taken from the parent +@item pathname type is @code{(source-file-type component system)} +@item the pathname case option is @code{:local} +@item the pathname is merged against the parent +@end itemize + +(for modules) +@itemize +@item the host is taken from the parent +@item the name and type are @code{NIL} +@item the directory is @code{(:relative component-name)} +@item the pathname case option is @code{:local} +@item the pathname is merged against the parent +@end itemize + +Note that the DEFSYSTEM operator (used to create a ``top-level'' +system) does additional processing to set the filesystem location of +the top component in that system. This is detailed +elsewhere, @xref{Defining systems with defsystem}. + +The answer to the frequently asked question "how do I create a system +definition where all the source files have a .cl extension" is thus + +@lisp +(defmethod source-file-type ((c cl-source-file) (s (eql (find-system 'my-sys)))) + "cl") +@end lisp + +@subsubsection properties + +This attribute is optional. + +Packaging systems often require information about files or systems in +addition to that specified by asdf's pre-defined component attributes. +Programs that create vendor packages out of asdf systems therefore +have to create ``placeholder'' information to satisfy these systems. +Sometimes the creator of an asdf system may know the additional +information and wish to provide it directly. + +(component-property component property-name) and associated setf +method will allow the programmatic update of this information. +Property names are compared as if by @code{EQL}, so use symbols or +keywords or something. + +@menu +* Pre-defined subclasses of component:: +* Creating new component types:: +@end menu + +@node Pre-defined subclasses of component, Creating new component types, Common attributes of components, Components +@comment node-name, next, previous, up +@subsection Pre-defined subclasses of component + +@deffn Component source-file + +A source file is any file that the system does not know how to +generate from other components of the system. + +Note that this is not necessarily the same thing as ``a file +containing data that is typically fed to a compiler''. If a file is +generated by some pre-processor stage (e.g. a @file{.h} file from +@file{.h.in} by autoconf) then it is not, by this definition, a source +file. Conversely, we might have a graphic file that cannot be +automatically regenerated, or a proprietary shared library that we +received as a binary: these do count as source files for our purposes. + +Subclasses of source-file exist for various languages. @emph{FIXME: +describe these.} +@end deffn + +@deffn Component module + +A module is a collection of sub-components. + +A module component has the following extra initargs: + +@itemize +@item +@code{:components} the components contained in this module + +@item +@code{:default-component-class} All child components which don't +specify their class explicitly are inferred to be of this type. + +@item +@code{:if-component-dep-fails} This attribute takes one of the values +@code{:fail}, @code{:try-next}, @code{:ignore}, its default value is +@code{:fail}. The other values can be used for implementing +conditional compilation based on implementation @code{*features*}, for +the case where it is not necessary for all files in a module to be +compiled. + +@item +@code{:serial} When this attribute is set, each subcomponent of this +component is assumed to depend on all subcomponents before it in the +list given to @code{:components}, i.e. all of them are loaded before +a compile or load operation is performed on it. + +@end itemize + +The default operation knows how to traverse a module, so most +operations will not need to provide methods specialised on modules. + +@code{module} may be subclassed to represent components such as +foreign-language linked libraries or archive files. +@end deffn + +@deffn Component system + +@code{system} is a subclass of @code{module}. + +A system is a module with a few extra attributes for documentation +purposes; these are given elsewhere. @xref{The defsystem grammar}. + +Users can create new classes for their systems: the default +@code{defsystem} macro takes a @code{:classs} keyword +argument. +@end deffn + +@node Creating new component types, , Pre-defined subclasses of component, Components +@comment node-name, next, previous, up +@subsection Creating new component types + +New component types are defined by subclassing one of the existing +component classes and specializing methods on the new component class. + +@emph{FIXME: this should perhaps be explained more throughly, not only by +example ...} + +As an example, suppose we have some implementation-dependent +functionality that we want to isolate in one subdirectory per Lisp +implementation our system supports. We create a subclass of +@code{cl-source-file}: + +@lisp +(defclass unportable-cl-source-file (cl-source-file) + ()) +@end lisp + +A hypothetical function @code{system-dependent-dirname} gives us the +name of the subdirectory. All that's left is to define how to +calculate the pathname of an @code{unportable-cl-source-file}. + +@lisp +(defmethod component-pathname ((component unportable-cl-source-file)) + (let ((pathname (call-next-method)) + (name (string-downcase (system-dependent-dirname)))) + (merge-pathnames + (make-pathname :directory (list :relative name)) + pathname))) +@end lisp + +The new component type is used in a @code{defsystem} form in this way: + +@lisp +(defsystem :foo + :components + ((:file "packages") + ... + (:unportable-cl-source-file "threads" + :depends-on ("packages" ...)) + ... + ) +@end lisp + +@node Error handling, Compilation error and warning handling, The object model of asdf, Top +@comment node-name, next, previous, up +@chapter Error handling +@findex SYSTEM-DEFINITION-ERROR +@findex OPERATION-ERROR + +It is an error to define a system incorrectly: an implementation may +detect this and signal a generalised instance of +@code{SYSTEM-DEFINITION-ERROR}. + +Operations may go wrong (for example when source files contain +errors). These are signalled using generalised instances of +@code{OPERATION-ERROR}. + +@node Compilation error and warning handling, Getting the latest version, Error handling, Top +@comment node-name, next, previous, up +@chapter Compilation error and warning handling +@vindex *compile-file-warnings-behaviour* +@vindex *compile-file-errors-behavior* + +ASDF checks for warnings and errors when a file is compiled. The +variables @code{*compile-file-warnings-behaviour*} and +@code{*compile-file-errors-behavior*} controls the handling of any +such events. The valid values for these variables are @code{:error}, +@code{:warn}, and @code{:ignore}. + +@node Getting the latest version, TODO list, Compilation error and warning handling, Top +@comment node-name, next, previous, up +@chapter Getting the latest version + +@enumerate +@item +Decide which version you want. HEAD is the newest version and +usually OK, whereas RELEASE is for cautious people (e.g. who already +have systems using asdf that they don't want broken), a slightly older +version about which none of the HEAD users have complained. + +@item +Check it out from sourceforge cCLan CVS: + +@kbd{cvs -d:pserver:anonymous@@cvs.cclan.sourceforge.net:/cvsroot/cclan login} + +(no password: just press @key{Enter}) + +@kbd{cvs -z3 -d:pserver:anonymous@@cvs.cclan.sourceforge.net:/cvsroot/cclan co -r RELEASE asdf} + +or for the bleeding edge, instead + +@kbd{cvs -z3 -d:pserver:anonymous@@cvs.cclan.sourceforge.net:/cvsroot/cclan co -A asdf} + +@end enumerate + +If you are tracking the bleeding edge, you may want to subscribe to +the cclan-commits mailing list (see +@url{http://sourceforge.net/mail/?group_id=28536}) to receive commit +messages and diffs whenever changes are made. + +For more CVS information, look at +@url{http://sourceforge.net/cvs/?group_id=28536}. + + + + +@node TODO list, missing bits in implementation, Getting the latest version, Top +@comment node-name, next, previous, up +@chapter TODO list + +* Outstanding spec questions, things to add + +** packaging systems + +*** manual page component? + +** style guide for .asd files + +You should either use keywords or be careful with the package that you +evaluate defsystem forms in. Otherwise (defsystem partition ...) +being read in the cl-user package will intern a cl-user:partition +symbol, which will then collide with the partition:partition symbol. + +Actually there's a hairier packages problem to think about too. +in-order-to is not a keyword: if you read defsystem forms in a package +that doesn't use ASDF, odd things might happen + +** extending defsystem with new options + +You might not want to write a whole parser, but just to add options to +the existing syntax. Reinstate parse-option or something akin + +** document all the error classes + +** what to do with compile-file failure + +Should check the primary return value from compile-file and see if +that gets us any closer to a sensible error handling strategy + +** foreign files + +lift unix-dso stuff from db-sockets + +** Diagnostics + +A ``dry run'' of an operation can be made with the following form: + +@lisp +(traverse (make-instance '<operation-name>) + (find-system <system-name>) + 'explain) +@end lisp + +This uses unexported symbols. What would be a nice interface for this +functionality? + +@node missing bits in implementation, Inspiration, TODO list, Top +@comment node-name, next, previous, up +@chapter missing bits in implementation + +** all of the above + +** reuse the same scratch package whenever a system is reloaded from disk + +** rules for system pathname defaulting are not yet implemented properly + +** proclamations probably aren't + +** when a system is reloaded with fewer components than it previously + had, odd things happen + +we should do something inventive when processing a defsystem form, +like take the list of kids and setf the slot to nil, then transfer +children from old to new list as they're found + +** traverse may become a normal function + +If you're defining methods on traverse, speak up. + + +** a lot of load-op methods can be rewritten to use input-files + +so should be. + + +** (stuff that might happen later) + +*** david lichteblau's patch for symlink resolution? + +*** Propagation of the :force option. ``I notice that + + (oos 'compile-op :araneida :force t) + +also forces compilation of every other system the :araneida system +depends on. This is rarely useful to me; usually, when I want to force +recompilation of something more than a single source file, I want to +recompile only one system. So it would be more useful to have +make-sub-operation refuse to propagate @code{:force t} to other systems, and +propagate only something like @code{:force :recursively}. + +Ideally what we actually want is some kind of criterion that says to +which systems (and which operations) a @code{:force} switch will +propagate. + +The problem is perhaps that `force' is a pretty meaningless concept. +How obvious is it that @code{load :force t} should force +@emph{compilation}? But we don't really have the right dependency +setup for the user to compile @code{:force t} and expect it to work +(files will not be loaded after compilation, so the compile +environment for subsequent files will be emptier than it needs to be) + +What does the user actually want to do when he forces? Usually, for +me, update for use with a new version of the lisp compiler. Perhaps +for recovery when he suspects that something has gone wrong. Or else +when he's changed compilation options or configuration in some way +that's not reflected in the dependency graph. + +Other possible interface: have a 'revert' function akin to 'make clean' + +@lisp +(asdf:revert 'asdf:compile-op 'araneida) +@end lisp + +would delete any files produced by 'compile-op 'araneida. Of course, it +wouldn't be able to do much about stuff in the image itself. + +How would this work? + +traverse + +There's a difference between a module's dependencies (peers) and its +components (children). Perhaps there's a similar difference in +operations? For example, @code{(load "use") depends-on (load "macros")} is a +peer, whereas @code{(load "use") depends-on (compile "use")} is more of a +`subservient' relationship. + +@node Inspiration, Concept Index, missing bits in implementation, Top +@comment node-name, next, previous, up +@chapter Inspiration + +@section mk-defsystem (defsystem-3.x) + +We aim to solve basically the same problems as mk-defsystem does. +However, our architecture for extensibility better exploits CL +language features (and is documented), and we intend to be portable +rather than just widely-ported. No slight on the mk-defsystem authors +and maintainers is intended here; that implementation has the +unenviable task of supporting pre-ANSI implementations, which is +no longer necessary. + +The surface defsystem syntax of asdf is more-or-less compatible with +mk-defsystem, except that we do not support the @code{source-foo} and +@code{binary-foo} prefixes for separating source and binary files, and +we advise the removal of all options to specify pathnames. + +The mk-defsystem code for topologically sorting a module's dependency +list was very useful. + +@section defsystem-4 proposal + +Marco and Peter's proposal for defsystem 4 served as the driver for +many of the features in here. Notable differences are: + +@itemize +@item +We don't specify output files or output file extensions as part of the +system. + +If you want to find out what files an operation would create, ask the +operation. + +@item +We don't deal with CL packages + +If you want to compile in a particular package, use an in-package form +in that file (ilisp / SLIME will like you more if you do this anyway) + +@item +There is no proposal here that defsystem does version control. + +A system has a given version which can be used to check dependencies, +but that's all. +@end itemize + +The defsystem 4 proposal tends to look more at the external features, +whereas this one centres on a protocol for system introspection. + +@section kmp's ``The Description of Large Systems'', MIT AI Memu 801 + +Available in updated-for-CL form on the web at +@url{http://world.std.com/~pitman/Papers/Large-Systems.html} + +In our implementation we borrow kmp's overall PROCESS-OPTIONS and +concept to deal with creating component trees from defsystem surface +syntax. [ this is not true right now, though it used to be and +probably will be again soon ] + + +@c ------------------- + + +@node Concept Index, Function and Class Index, Inspiration, Top +@unnumbered Concept Index + +@printindex cp + +@node Function and Class Index, Variable Index, Concept Index, Top +@unnumbered Function and Class Index + +@printindex fn + +@node Variable Index, , Function and Class Index, Top +@unnumbered Variable Index + +@printindex vr + + + + +@bye + diff --git a/Lisp/asdf/cclan-package.lisp b/Lisp/asdf/cclan-package.lisp new file mode 100644 index 0000000..d993e94 --- /dev/null +++ b/Lisp/asdf/cclan-package.lisp @@ -0,0 +1,5 @@ +(in-package :cl-user) + +(defpackage :cclan (:use #:cl #:asdf) + (:export #:all-components #:write-package)) + diff --git a/Lisp/asdf/cclan.asd b/Lisp/asdf/cclan.asd new file mode 100644 index 0000000..07dbebb --- /dev/null +++ b/Lisp/asdf/cclan.asd @@ -0,0 +1,8 @@ +;;; -*- Lisp -*- +(defpackage :cclan-system (:use #:cl #:asdf)) +(in-package :cclan-system) + +(defsystem cclan + :version "0.1" + :components ((:file "cclan-package") + (:file "cclan" :depends-on ("cclan-package")))) diff --git a/Lisp/asdf/cclan.lisp b/Lisp/asdf/cclan.lisp new file mode 100644 index 0000000..7d08307 --- /dev/null +++ b/Lisp/asdf/cclan.lisp @@ -0,0 +1,99 @@ +(in-package :cclan) + +;;;; This file contains functions, classes etc that are not part of +;;;; asdf itself, but extend it in various ways useful for maintainers +;;;; of new-style cCLan packages + +;;;; The public interface consists of the functions whose symbols are +;;;; exported from the package + +;;;; This file does not contain references to asdf internals - or +;;;; shouldn't, anyway. Send bug reports + + +(defun mapappend (function list) + (let ((f (coerce function 'function))) + (loop for i in list append (funcall f i)))) + +(defgeneric all-components (component)) +(defmethod all-components ((source-file source-file)) + (list source-file)) + +(defmethod all-components ((module module)) + (cons module (mapappend #'all-components (module-components module)))) + +(defmethod all-components ((module symbol)) + (all-components (find-system module))) + +(defun cvs-tag-name (system) + (let* ((system (find-system system)) + (version (component-version system))) + (format nil "release_~A" (substitute #\_ #\. version)))) + +(defun cvs-tag (system) + (let* ((system (find-system system)) + (directory (component-pathname system))) + (run-shell-command "cd ~A && cvs tag -F ~A" + (namestring directory) (cvs-tag-name system)))) + + +(defun write-readme-file (stream suggested-registry system-name) + "Write a README.install file detailing a possible sequence of commands to use the newly-untarred system." + (format stream "~ +1. Make a symlink in ~W[*] pointing to the .asd file +2. Start your asdf-enabled lisp +2a. Ensure that ~W[*] is in asdf:*central-registry* +3. At the lisp prompt, type '(asdf:operate 'asdf:load-op ~W)'. This + will compile and load the system into your running lisp. + +[*] This path (~W) is only a suggestion; the important +thing is that asdf know where to find the .asd file. asdf uses the +contents of the variable ASDF:*CENTRAL-REGISTRY* to find its system +definitions. + +These instructions were automatically generated by cCLan software. Use +at your own peril.~%" suggested-registry suggested-registry system-name suggested-registry)) + +(defun write-package (system) + (let* ((parent-dir + (parse-namestring + (format nil "/tmp/~A.~A/" + #+sbcl (sb-unix:unix-getpid) + #-sbcl (random 1000000) + (get-internal-run-time)))) + (system (find-system system)) + (sub-dir-name + (format nil "~A_~A" + (component-name system) (component-version system))) + (cvsroot-file + (merge-pathnames "CVS/Root" (component-pathname system))) + (old-pwd *default-pathname-defaults*) + (*default-pathname-defaults* parent-dir)) + (ensure-directories-exist parent-dir) + (cvs-tag system) + (and + (zerop (asdf:run-shell-command + "cd ~A && cvs -d `cat ~A` checkout -d ~A -r ~A -kv ~A" + (namestring parent-dir) + (namestring cvsroot-file) + sub-dir-name + (cvs-tag-name system) + (component-name system))) + (with-open-file (o (format nil "~A/INSTALL.asdf" sub-dir-name) + :direction :output) + (write-readme-file o "$HOME/lisp/systems/" (component-name system)) + t) + (zerop (asdf:run-shell-command "cd ~A && tar cf ~A~A.tar ~A" + (namestring parent-dir) + (namestring old-pwd) sub-dir-name + sub-dir-name)) + (zerop (asdf:run-shell-command + "gzip -f9 ~A~A.tar" + (namestring old-pwd) sub-dir-name)) + (format t "Now run~% gpg -b -a ~A~A.tar.gz~%in a shell with a tty" + (namestring old-pwd) sub-dir-name)))) + +(defun class-name-of (x) + (class-name (class-of x))) + + diff --git a/Lisp/asdf/debian/README.Debian b/Lisp/asdf/debian/README.Debian new file mode 100644 index 0000000..b38202d --- /dev/null +++ b/Lisp/asdf/debian/README.Debian @@ -0,0 +1,14 @@ +Debian Package cl-asdf +---------------------- + +This package was created for Debian by Kevin M. Rosenberg +<kmr@debian.org> in Aug 2002. The URL for asdf is +http://www.telent.net/cliki/asdf. The README file has details +about the use of asdf. + +To load asdf into your Lisp system, give the command +(load "/usr/share/common-lisp/source/asdf/asdf.lisp") + +Additionally, there is an optional module that you can load +with the command +(load "/usr/share/common-lisp/source/asdf/wild-modules.lisp") diff --git a/Lisp/asdf/debian/changelog b/Lisp/asdf/debian/changelog new file mode 100644 index 0000000..fbac8d8 --- /dev/null +++ b/Lisp/asdf/debian/changelog @@ -0,0 +1,304 @@ +cl-asdf (1.81-1) unstable; urgency=low + + * New upstream + + -- Kevin M. Rosenberg <kmr@debian.org> Tue, 30 Dec 2003 12:12:38 -0700 + +cl-asdf (1.80-1) unstable; urgency=low + + * New upstream + + -- Kevin M. Rosenberg <kmr@debian.org> Fri, 5 Dec 2003 14:55:43 -0700 + +cl-asdf (1.79-1) unstable; urgency=low + + * New upstream + + -- Kevin M. Rosenberg <kmr@debian.org> Tue, 11 Nov 2003 16:12:07 -0700 + +cl-asdf (1.78-1) unstable; urgency=low + + * New upstream + + -- Kevin M. Rosenberg <kmr@debian.org> Thu, 9 Oct 2003 16:46:38 -0600 + +cl-asdf (1.77.2-1) unstable; urgency=low + + * Don't export asdf:wild-module as can cause a full warning when + reloading asdf + + -- Kevin M. Rosenberg <kmr@debian.org> Mon, 11 Aug 2003 21:55:16 -0600 + +cl-asdf (1.77.1-1) unstable; urgency=low + + * cclan.lisp: conditionalize for sbcl (closes: 201822) + + -- Kevin M. Rosenberg <kmr@debian.org> Thu, 17 Jul 2003 23:30:57 -0600 + +cl-asdf (1.77-1) unstable; urgency=low + + * New upstream + * Add automated [cvs2cl] ChangeLog + + -- Kevin M. Rosenberg <kmr@debian.org> Thu, 17 Jul 2003 10:27:27 -0600 + +cl-asdf (1.76) unstable; urgency=low + + * New upstream + + -- Kevin M. Rosenberg <kmr@debian.org> Thu, 10 Jul 2003 16:42:48 -0600 + +cl-asdf (1.75) unstable; urgency=low + + * New upstream + * Use compat rather than DH_COMPAT + + -- Kevin M. Rosenberg <kmr@debian.org> Thu, 5 Jun 2003 00:15:11 -0600 + +cl-asdf (1.73b) unstable; urgency=low + + * Update README + * export two variables + + -- Kevin M. Rosenberg <kmr@debian.org> Wed, 28 May 2003 11:19:40 -0600 + +cl-asdf (1.73) unstable; urgency=low + + * Update README to mention asdf::*compile-file-warnings-behaviour* + (closes:194957) + + -- Kevin M. Rosenberg <kmr@debian.org> Tue, 27 May 2003 16:00:36 -0600 + +cl-asdf (1.72) unstable; urgency=low + + * New upstream + + -- Kevin M. Rosenberg <kmr@debian.org> Tue, 20 May 2003 14:07:10 -0600 + +cl-asdf (1.71) unstable; urgency=low + + * New upstream + + -- Kevin M. Rosenberg <kmr@debian.org> Tue, 13 May 2003 09:33:51 -0600 + +cl-asdf (1.70) unstable; urgency=low + + * Add another check in check-component-values. + * Signal a generalized instance of SYSTEM-DEFINITION-ERROR + from check-component-values + + -- Kevin M. Rosenberg <kmr@debian.org> Tue, 6 May 2003 09:32:16 -0600 + +cl-asdf (1.69) unstable; urgency=low + + * Add check-component-values function with partial checking of components + + -- Kevin M. Rosenberg <kmr@debian.org> Tue, 6 May 2003 08:26:11 -0600 + +cl-asdf (1.68) unstable; urgency=low + + * New upstream with 'asdf:test-op + + -- Kevin M. Rosenberg <kmr@debian.org> Wed, 19 Mar 2003 10:16:01 -0700 + +cl-asdf (1.66) unstable; urgency=low + + * New upstream version, added changes to dependent system + compilations with :force option. + + -- Kevin M. Rosenberg <kmr@debian.org> Mon, 17 Mar 2003 12:50:00 -0700 + +cl-asdf (1.62) unstable; urgency=low + + * New upstream, fixes a sbcl-specific directory name + + -- Kevin M. Rosenberg <kmr@debian.org> Fri, 7 Mar 2003 09:23:11 -0700 + +cl-asdf (1.61-1) unstable; urgency=low + + * New upstream, fixes 'load-source-op + + -- Kevin M. Rosenberg <kmr@debian.org> Tue, 4 Mar 2003 09:48:40 -0700 + +cl-asdf (1.60-1) unstable; urgency=low + + * New upstream + + -- Kevin M. Rosenberg <kmr@debian.org> Mon, 3 Mar 2003 12:40:27 -0700 + +cl-asdf (1.59-1) unstable; urgency=low + + * New upstream + + -- Kevin M. Rosenberg <kmr@debian.org> Fri, 14 Feb 2003 09:24:59 -0700 + +cl-asdf (1.58-1) unstable; urgency=low + + * New upstream + + -- Kevin M. Rosenberg <kmr@debian.org> Sun, 9 Feb 2003 11:55:03 -0700 + +cl-asdf (1.57-1) unstable; urgency=low + + * New upstream + + -- Kevin M. Rosenberg <kmr@debian.org> Tue, 4 Feb 2003 10:23:03 -0700 + +cl-asdf (1.55-1) unstable; urgency=low + + * New upstream.version (closes: 172074) + + -- Kevin M. Rosenberg <kmr@debian.org> Mon, 9 Dec 2002 10:23:21 -0700 + +cl-asdf (1.54-1) unstable; urgency=low + + * New upstream. + + -- Kevin M. Rosenberg <kmr@debian.org> Fri, 8 Nov 2002 07:30:41 -0700 + +cl-asdf (1.49-1) unstable; urgency=low + + * Remove clc-reregister-all-impl from postinst + + -- Kevin M. Rosenberg <kmr@debian.org> Sat, 5 Oct 2002 09:38:18 -0600 + +cl-asdf (1.49) unstable; urgency=low + + * New upstream release, fixes run-shell-command for allegro. Code + refactoring for run-shell-code. + * Support new CLC reregister command + + -- Kevin M. Rosenberg <kmr@debian.org> Wed, 25 Sep 2002 23:57:23 -0600 + +cl-asdf (1.47) unstable; urgency=low + + * Return numeric exit status for openmcl's run-shell-command + + -- Kevin M. Rosenberg <kmr@debian.org> Fri, 20 Sep 2002 10:22:36 -0600 + +cl-asdf (1.46) unstable; urgency=low + + * New upstream version, adds run-shell-command for openmcl + + -- Kevin M. Rosenberg <kmr@debian.org> Fri, 20 Sep 2002 10:11:48 -0600 + +cl-asdf (1.45) unstable; urgency=low + + * Changes to improve clisp support + + -- Kevin M. Rosenberg <kmr@debian.org> Fri, 20 Sep 2002 07:12:21 -0600 + +cl-asdf (1.44.1-1) unstable; urgency=low + + * Make cclan.asd a symlink, remove :pathname keyword + + -- Kevin M. Rosenberg <kmr@debian.org> Wed, 18 Sep 2002 00:19:26 -0600 + +cl-asdf (1.44-1) unstable; urgency=low + + * New upstream version + + -- Kevin M. Rosenberg <kmr@debian.org> Tue, 17 Sep 2002 12:24:27 -0600 + +cl-asdf (1.43-1) unstable; urgency=low + + * New upstream version + + -- Kevin M. Rosenberg <kmr@debian.org> Tue, 17 Sep 2002 10:34:57 -0600 + +cl-asdf (1.42-2) unstable; urgency=low + + * Add reregister-common-lisp-implementations call when installing cl-asdf. + + -- Kevin M. Rosenberg <kmr@debian.org> Mon, 16 Sep 2002 08:31:13 -0600 + +cl-asdf (1.42-1) unstable; urgency=low + + * Remove Depends on lisp-compiler for cl-asdf (fixes problem with + circular dependencies) + + -- Kevin M. Rosenberg <kmr@debian.org> Sat, 14 Sep 2002 11:59:58 -0600 + +cl-asdf (1.42) unstable; urgency=low + + * New upstream. + + -- Kevin M. Rosenberg <kmr@debian.org> Fri, 13 Sep 2002 08:40:58 -0600 + +cl-asdf (1.41) unstable; urgency=low + + * Same release as 1.40, but with proper version number. + + -- Kevin M. Rosenberg <kmr@debian.org> Fri, 13 Sep 2002 08:38:30 -0600 + +cl-asdf (1.40) unstable; urgency=low + + * New upstream version. + + -- Kevin M. Rosenberg <kmr@debian.org> Fri, 13 Sep 2002 07:31:27 -0600 + +cl-asdf (1.39) unstable; urgency=low + + * New upstream version. + + -- Kevin M. Rosenberg <kmr@debian.org> Wed, 11 Sep 2002 19:21:32 -0600 + +cl-asdf (1.38) unstable; urgency=low + + * New upstream version + * Re-add register and unregister clc-source for cclan + + -- Kevin M. Rosenberg <kmr@debian.org> Wed, 11 Sep 2002 13:39:51 -0600 + +cl-asdf (1.35-1) unstable; urgency=low + + * Comment call to register and unregister clc-source until new + version of clc is released. (closes: 158697) + + -- Kevin M. Rosenberg <kmr@debian.org> Wed, 28 Aug 2002 18:58:59 -0600 + +cl-asdf (1.35) unstable; urgency=high + + * New upstream version, fixes important bugs. + + -- Kevin M. Rosenberg <kmr@debian.org> Wed, 28 Aug 2002 09:36:58 -0600 + +cl-asdf (1.34) unstable; urgency=low + + * New upstream version. + + -- Kevin M. Rosenberg <kmr@debian.org> Wed, 28 Aug 2002 07:18:57 -0600 + +cl-asdf (0.0+cvs.2002.08.26-1) unstable; urgency=low + + * Add Common Lisp Controller registration functions for cl-cclan + + -- Kevin M. Rosenberg <kmr@debian.org> Mon, 26 Aug 2002 04:21:32 -0600 + +cl-asdf (0.0+cvs.2002.08.26) unstable; urgency=low + + * New upstream version + + -- Kevin M. Rosenberg <kmr@debian.org> Mon, 26 Aug 2002 01:23:48 -0600 + +cl-asdf (0.0+cvs.2002.08.22) unstable; urgency=low + + * Add new binary package: cl-cclan + + -- Kevin M. Rosenberg <kmr@debian.org> Thu, 22 Aug 2002 12:43:21 -0600 + +cl-asdf (0.0+cvs.2002.08.18) unstable; urgency=low + + * New upstream version + * Expand description in control file. + * Change version numbering scheme since upstream has native debian + directory + + -- Kevin M. Rosenberg <kmr@debian.org> Sat, 17 Aug 2002 14:25:33 -0600 + +cl-asdf (0.0+cvs.2002.08.15-1) unstable; urgency=low + + * Initial Release (closes: 157009) + + -- Kevin M. Rosenberg <kmr@debian.org> Fri, 16 Aug 2002 23:14:49 -0600 + diff --git a/Lisp/asdf/debian/cl-asdf.postinst b/Lisp/asdf/debian/cl-asdf.postinst new file mode 100644 index 0000000..6a6e3cf --- /dev/null +++ b/Lisp/asdf/debian/cl-asdf.postinst @@ -0,0 +1,45 @@ +#! /bin/sh +# postinst script for asdf + +set -e + +# summary of how this script can be called: +# * <postinst> `configure' <most-recently-configured-version> +# * <old-postinst> `abort-upgrade' <new version> +# * <conflictor's-postinst> `abort-remove' `in-favour' <package> +# <new-version> +# * <deconfigured's-postinst> `abort-deconfigure' `in-favour' +# <failed-install-package> <version> `removing' +# <conflicting-package> <version> +# for details, see http://www.debian.org/doc/debian-policy/ or +# the debian-policy package +# +# quoting from the policy: +# Any necessary prompting should almost always be confined to the +# post-installation script, and should be protected with a conditional +# so that unnecessary prompting doesn't happen if a package's +# installation fails and the `postinst' is called with `abort-upgrade', +# `abort-remove' or `abort-deconfigure'. + +case "$1" in + configure) + if [ -x /usr/sbin/clc-reregister-all-impl ]; then + /usr/sbin/clc-reregister-all-impl + fi + ;; + abort-upgrade|abort-remove|abort-deconfigure) + ;; + *) + echo "postinst called with unknown argument \`$1'" >&2 + exit 1 + ;; +esac + +# dh_installdeb will replace this with shell code automatically +# generated by other debhelper scripts. + +#DEBHELPER# + +exit 0 + + diff --git a/Lisp/asdf/debian/cl-cclan.postinst b/Lisp/asdf/debian/cl-cclan.postinst new file mode 100644 index 0000000..3276e88 --- /dev/null +++ b/Lisp/asdf/debian/cl-cclan.postinst @@ -0,0 +1,41 @@ +#!/bin/sh + +set -e + +pkg=cclan + +# summary of how this script can be called: +# * <postinst> `configure' <most-recently-configured-version> +# * <old-postinst> `abort-upgrade' <new version> +# * <conflictor's-postinst> `abort-remove' `in-favour' <package> +# <new-version> +# * <deconfigured's-postinst> `abort-deconfigure' `in-favour' +# <failed-install-package> <version> `removing' +# <conflicting-package> <version> +# for details, see http://www.debian.org/doc/debian-policy/ or +# the debian-policy package +# +# quoting from the policy: +# Any necessary prompting should almost always be confined to the +# post-installation script, and should be protected with a conditional +# so that unnecessary prompting doesn't happen if a package's +# installation fails and the `postinst' is called with `abort-upgrade', +# `abort-remove' or `abort-deconfigure'. + +case "$1" in + configure) + /usr/sbin/register-common-lisp-source $pkg + ;; + abort-upgrade|abort-remove|abort-deconfigure) + ;; + *) + echo "postinst called with unknown argument \`$1'" >&2 + exit 1 + ;; +esac + +#DEBHELPER# + +exit 0 + + diff --git a/Lisp/asdf/debian/cl-cclan.prerm b/Lisp/asdf/debian/cl-cclan.prerm new file mode 100644 index 0000000..d8cda90 --- /dev/null +++ b/Lisp/asdf/debian/cl-cclan.prerm @@ -0,0 +1,36 @@ +#!/bin/sh + +set -e + +pkg=cclan + +# summary of how this script can be called: +# * <prerm> `remove' +# * <old-prerm> `upgrade' <new-version> +# * <new-prerm> `failed-upgrade' <old-version> +# * <conflictor's-prerm> `remove' `in-favour' <package> <new-version> +# * <deconfigured's-prerm> `deconfigure' `in-favour' +# <package-being-installed> <version> `removing' +# <conflicting-package> <version> +# for details, see http://www.debian.org/doc/debian-policy/ or +# the debian-policy package + + +case "$1" in + remove|upgrade|deconfigure) + /usr/sbin/unregister-common-lisp-source $pkg + ;; + failed-upgrade) + ;; + *) + echo "prerm called with unknown argument \`$1'" >&2 + exit 1 + ;; +esac + + +#DEBHELPER# + +exit 0 + + diff --git a/Lisp/asdf/debian/compat b/Lisp/asdf/debian/compat new file mode 100644 index 0000000..7290ba8 --- /dev/null +++ b/Lisp/asdf/debian/compat @@ -0,0 +1,2 @@ +4 +4 diff --git a/Lisp/asdf/debian/control b/Lisp/asdf/debian/control new file mode 100644 index 0000000..850b435 --- /dev/null +++ b/Lisp/asdf/debian/control @@ -0,0 +1,26 @@ +Source: cl-asdf +Section: devel +Priority: optional +Maintainer: Kevin M. Rosenberg <kmr@debian.org> +Build-Depends-Indep: debhelper (>> 4.0.0) +Standards-Version: 3.6.1.0 + +Package: cl-asdf +Architecture: all +Depends: ${shlibs:Depends} +Recommends: common-lisp-controller, sbcl | lisp-compiler +Description: Another System Definition Facility + asdf provides a "make" type functions for Common Lisp packages. It + provides compilation and loading features for complex Lisp systems + with multiple modules and files. It is similar in concept to, but + with features different from, "defsystem" which is included in the + common-lisp-controller package. Unlike defsystem3 in CLC, asdf is + object-oriented and extensible. + +Package: cl-cclan +Architecture: all +Depends: ${shlibs:Depends}, cl-asdf +Description: Comprehensive Common Lisp Archive Network + cclan is a tool for creating a repository of Common Lisp packages. + cclan utilizes asdf to automatically create installable packages for various + operating systems. diff --git a/Lisp/asdf/debian/copyright b/Lisp/asdf/debian/copyright new file mode 100644 index 0000000..db3d7e5 --- /dev/null +++ b/Lisp/asdf/debian/copyright @@ -0,0 +1,37 @@ +This package was debianized by Kevin M. Rosenberg <kmr@debian.org> on +Fri, 16 Aug 2002 23:14:49 -0600. + +It was downloaded from SourceForge CVS server with the below commands: + cvs -d:pserver:anonymous@cvs.cclan.sourceforge.net:/cvsroot/cclan login + (no password: just press Enter) + cvs -z3 -d:pserver:anonymous@cvs.cclan.sourceforge.net:/cvsroot/cclan \ + co asdf + +Upstream Authors: Dan Barlow <dan@telent.net> & Contributors + +Copyright: + +(This is the MIT / X Consortium license as taken from + http://www.opensource.org/licenses/mit-license.html) + +Copyright (c) 2001, 2002 Daniel Barlow and contributors + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + diff --git a/Lisp/asdf/debian/docs b/Lisp/asdf/debian/docs new file mode 100644 index 0000000..e845566 --- /dev/null +++ b/Lisp/asdf/debian/docs @@ -0,0 +1 @@ +README diff --git a/Lisp/asdf/debian/rules b/Lisp/asdf/debian/rules new file mode 100644 index 0000000..38630bb --- /dev/null +++ b/Lisp/asdf/debian/rules @@ -0,0 +1,84 @@ +#!/usr/bin/make -f +# GNU copyright 1997 to 1999 by Joey Hess. + +pkg=cl-asdf +pkg-cclan=cl-cclan +clc-base=usr/share/common-lisp +clc-src=$(clc-base)/source +clc-systems=$(clc-base)/systems +asdf-files=$(clc-src)/asdf +cclan-files=$(clc-src)/cclan +doc-dir=usr/share/doc/$(pkg) + +configure: configure-stamp +configure-stamp: + dh_testdir + # Add here commands to configure the package. + touch configure-stamp + + +build: build-stamp + +build-stamp: configure-stamp + dh_testdir + # Add here commands to compile the package. + touch build-stamp + +clean: + dh_testdir + dh_testroot + rm -f build-stamp configure-stamp + # Add here commands to clean up after the build process. + dh_clean + +install: build + dh_testdir + dh_testroot + dh_clean -k + dh_installdirs + + # Add here commands to install the package into debian/asdf. + dh_installdirs -p $(pkg) $(asdf-files) $(doc-dir)/examples + dh_install -p $(pkg) asdf.lisp wild-modules.lisp asdf-install.lisp $(asdf-files) + chmod +x test/run-tests.sh + dh_install -p $(pkg) test/* $(doc-dir)/examples + dh_installdirs -p $(pkg-cclan) $(clc-systems) $(cclan-files) + dh_install -p $(pkg-cclan) cclan-package.lisp cclan.lisp cclan.asd $(cclan-files) + dh_link -p $(pkg-cclan) $(cclan-files)/cclan.asd $(clc-systems)/cclan.asd + +# Build architecture-independent files here. +binary-indep: build install +# We have nothing to do by default. + +# Build architecture-dependent files here. +binary-arch: build install + dh_testdir + dh_testroot +# dh_installdebconf + dh_installdocs +# dh_installexamples + dh_installmenu +# dh_installlogrotate +# dh_installemacsen +# dh_installpam +# dh_installmime +# dh_installinit + dh_installcron + dh_installman + dh_installinfo +# dh_undocumented + dh_installchangelogs ChangeLog + dh_link + dh_strip + dh_compress + dh_fixperms +# dh_makeshlibs + dh_installdeb +# dh_perl + dh_shlibdeps + dh_gencontrol + dh_md5sums + dh_builddeb + +binary: binary-indep binary-arch +.PHONY: build clean binary-indep binary-arch binary install configure diff --git a/Lisp/asdf/test-mail b/Lisp/asdf/test-mail new file mode 100644 index 0000000..0aa66d7 --- /dev/null +++ b/Lisp/asdf/test-mail @@ -0,0 +1 @@ +Wed Aug 28 21:18:48 BST 2002 diff --git a/Lisp/asdf/test/file1.lisp b/Lisp/asdf/test/file1.lisp new file mode 100644 index 0000000..3612a2b --- /dev/null +++ b/Lisp/asdf/test/file1.lisp @@ -0,0 +1,4 @@ +(defpackage :test-package (:use :cl)) +(in-package :test-package) +(defvar *file1* t) + diff --git a/Lisp/asdf/test/file2.lisp b/Lisp/asdf/test/file2.lisp new file mode 100644 index 0000000..a8192bb --- /dev/null +++ b/Lisp/asdf/test/file2.lisp @@ -0,0 +1,2 @@ +(in-package :test-package) +(assert *file1*) diff --git a/Lisp/asdf/test/file3.lisp b/Lisp/asdf/test/file3.lisp new file mode 100644 index 0000000..0ed2df7 --- /dev/null +++ b/Lisp/asdf/test/file3.lisp @@ -0,0 +1,4 @@ +(defpackage :test-package (:use :cl)) +(in-package :test-package) +(defvar *file3* t) + diff --git a/Lisp/asdf/test/file4.lisp b/Lisp/asdf/test/file4.lisp new file mode 100644 index 0000000..45a709a --- /dev/null +++ b/Lisp/asdf/test/file4.lisp @@ -0,0 +1,2 @@ +(in-package :test-package) +(assert *file3*) diff --git a/Lisp/asdf/test/run-tests.sh b/Lisp/asdf/test/run-tests.sh new file mode 100644 index 0000000..0c4f87e --- /dev/null +++ b/Lisp/asdf/test/run-tests.sh @@ -0,0 +1,39 @@ +#!/bin/sh + +do_tests() { +rm *.$2 || true +( cd .. && echo '(compile-file "asdf")' |$1 ) +for i in *.script; +do + rm *.$2 || true + if $1 < $i ;then + echo "Using $1, $i passed" >&2 + else + echo "Using $1, $i failed" >&2 + exit 1 + fi +done +echo "Using $1, all tests apparently successful" >&2 +} + +# do_tests {lisp invocation} {fasl extension} +# - read lisp forms one at a time from standard input +# - quit with exit status 0 on getting eof +# - quit with exit status >0 if an unhandled error occurs + +set -e + +if type sbcl +then + do_tests "sbcl --userinit /dev/null --sysinit /dev/null --noprogrammer" fasl +fi + +if [ -x /usr/bin/lisp ] +then + do_tests "/usr/bin/lisp -batch -noinit" x86f +fi + +if [ -x /usr/bin/clisp ] +then + do_tests "/usr/bin/clisp -norc -ansi -I " fas +fi diff --git a/Lisp/asdf/test/test1.asd b/Lisp/asdf/test/test1.asd new file mode 100644 index 0000000..423d796 --- /dev/null +++ b/Lisp/asdf/test/test1.asd @@ -0,0 +1,12 @@ +;;; -*- Lisp -*- +(asdf:defsystem test1 + :components ((:file "file2" :in-order-to ((compile-op (load-op "file1")))) + (:file "file1"))) + +#| +1) from clean, check that all fasl files build and that some function + defined in the second file is present + +2) delete the second fasl file, and build again. do test 1 again and + also check the date on file1.fasl +|# diff --git a/Lisp/asdf/test/test1.script b/Lisp/asdf/test/test1.script new file mode 100644 index 0000000..f39882c --- /dev/null +++ b/Lisp/asdf/test/test1.script @@ -0,0 +1,32 @@ +;;; -*- Lisp -*- +(load "../asdf") +(setf asdf:*central-registry* '(*default-pathname-defaults*)) +(asdf:operate 'asdf:load-op 'test1) + +;; test that it compiled +(defvar file1-date (file-write-date (compile-file-pathname "file1"))) +(assert (and file1-date (file-write-date (compile-file-pathname "file2")))) + +;; and loaded +(assert test-package::*file1*) + +;; now remove one output file and check that the other is _not_ +;; recompiled +(sleep 1) ; mtime has 1-second granularity, so pause here for fast machines + +(asdf::run-shell-command "rm ~A" + (namestring (compile-file-pathname "file2"))) +(asdf:operate 'asdf:load-op 'test1) +(assert (= file1-date (file-write-date (compile-file-pathname "file1")))) +(assert (file-write-date (compile-file-pathname "file2"))) + +;; now touch file1 and check that file2 _is_ also recompiled + +;; XXX run-shell-command loses if *default-pathname-defaults* is not the +;; unix cwd. this is not a problem for run-tests.sh, but can be in general + +(let ((before (file-write-date (compile-file-pathname "file2")))) + (asdf::run-shell-command "touch file1.lisp") + (sleep 1) + (asdf:operate 'asdf:load-op 'test1) + (assert (> (file-write-date (compile-file-pathname "file2")) before))) diff --git a/Lisp/asdf/test/test2.asd b/Lisp/asdf/test/test2.asd new file mode 100644 index 0000000..344d17f --- /dev/null +++ b/Lisp/asdf/test/test2.asd @@ -0,0 +1,8 @@ +;;; -*- Lisp -*- +(asdf:defsystem test2b + :version "1.0" + :components ((:file "file2" :in-order-to ((compile-op (load-op "file1")))) + (:file "file1")) + :depends-on (version 'test2a "1.1")) + + diff --git a/Lisp/asdf/test/test2.script b/Lisp/asdf/test/test2.script new file mode 100644 index 0000000..bca6012 --- /dev/null +++ b/Lisp/asdf/test/test2.script @@ -0,0 +1,19 @@ +;;; -*- Lisp -*- +(load "../asdf") +(setf asdf:*central-registry* '(*default-pathname-defaults*)) +;(trace asdf::perform) +;(trace asdf::find-component) +;(trace asdf::traverse) +(asdf:oos 'asdf:load-op 'test2b1) +(assert (and (probe-file (compile-file-pathname "file3")) + (probe-file (compile-file-pathname "file4")))) +(handler-case + (asdf:oos 'asdf:load-op 'test2b2) + (asdf:missing-dependency (c) + (format t "load failed as expected: - ~%~A~%" c)) + (:no-error (c) (error "should have failed, oops"))) +(handler-case + (asdf:oos 'asdf:load-op 'test2b3) + (asdf:missing-dependency (c) + (format t "load failed as expected: - ~%~A~%" c)) + (:no-error (c) (error "should have failed, oops"))) diff --git a/Lisp/asdf/test/test2a.asd b/Lisp/asdf/test/test2a.asd new file mode 100644 index 0000000..0e031db --- /dev/null +++ b/Lisp/asdf/test/test2a.asd @@ -0,0 +1,12 @@ +;;; -*- Lisp -*- +(asdf:defsystem test2a + :version "1.1" + :components ((:file "file4" :in-order-to ((compile-op (load-op "file3")))) + (:file "file3"))) +#| +this system is referenced by test2b[12] +|# + + + + diff --git a/Lisp/asdf/test/test2b1.asd b/Lisp/asdf/test/test2b1.asd new file mode 100644 index 0000000..985b352 --- /dev/null +++ b/Lisp/asdf/test/test2b1.asd @@ -0,0 +1,8 @@ +;;; -*- Lisp -*- +(asdf:defsystem test2b1 + :version "1.0" + :components ((:file "file2" :in-order-to ((compile-op (load-op "file1")))) + (:file "file1")) + :in-order-to ((load-op (load-op (version test2a "1.1"))))) + + diff --git a/Lisp/asdf/test/test2b2.asd b/Lisp/asdf/test/test2b2.asd new file mode 100644 index 0000000..3344fcd --- /dev/null +++ b/Lisp/asdf/test/test2b2.asd @@ -0,0 +1,8 @@ +;;; -*- Lisp -*- +(asdf:defsystem test2b2 + :version "1.0" + :components ((:file "file2" :in-order-to ((compile-op (load-op "file1")))) + (:file "file1")) + :in-order-to ((load-op (load-op (version test2a "1.2"))))) + + diff --git a/Lisp/asdf/test/test2b3.asd b/Lisp/asdf/test/test2b3.asd new file mode 100644 index 0000000..36771cc --- /dev/null +++ b/Lisp/asdf/test/test2b3.asd @@ -0,0 +1,8 @@ +;;; -*- Lisp -*- +(asdf:defsystem test2b3 + :version "1.0" + :components ((:file "file2" :in-order-to ((compile-op (load-op "file1")))) + (:file "file1")) + :depends-on (bet-you-cant-find-this)) + + diff --git a/Lisp/asdf/test/test3.asd b/Lisp/asdf/test/test3.asd new file mode 100644 index 0000000..10f82c9 --- /dev/null +++ b/Lisp/asdf/test/test3.asd @@ -0,0 +1,11 @@ +;;; -*- Lisp -*- +(asdf:defsystem test3 + :properties ((:prop1 . "value")) + :components + ((:module "deps" + :if-component-dep-fails :try-next + :pathname "." + :components + ((:file "file1" :in-order-to ((compile-op (feature :f1)))) + (:file "file2" :in-order-to ((compile-op (feature :f2)))))))) + diff --git a/Lisp/asdf/test/test3.script b/Lisp/asdf/test/test3.script new file mode 100644 index 0000000..170d4c5 --- /dev/null +++ b/Lisp/asdf/test/test3.script @@ -0,0 +1,23 @@ +;;; -*- Lisp -*- +#+(or f1 f2) + (error "This test cannot run if :f1 or :f2 are on *features*") +(load "../asdf") +(asdf:run-shell-command "rm ~A ~A" + (namestring (compile-file-pathname "file1")) + (namestring (compile-file-pathname "file2"))) +(setf asdf:*central-registry* '(*default-pathname-defaults*)) +(in-package :asdf) +(handler-case + (asdf:oos 'asdf:load-op 'test3) + (asdf:missing-dependency (c) + (format t "first test failed as expected: - ~%~A~%" c)) + (:no-error (c) (error "should have failed, oops"))) +(pushnew :f1 *features*) +(asdf:oos 'asdf:load-op 'test3) +(assert (probe-file (compile-file-pathname "file1"))) +(assert (not (probe-file (compile-file-pathname "file2")))) +(run-shell-command "rm ~A" (namestring (compile-file-pathname "file1"))) +(setf *features* (cons :f2 (cdr *features*))) +(asdf:oos 'asdf:load-op 'test3) +(assert (probe-file (compile-file-pathname "file2"))) +(assert (not (probe-file (compile-file-pathname "file1")))) diff --git a/Lisp/asdf/test/test4.script b/Lisp/asdf/test/test4.script new file mode 100644 index 0000000..e0ca859 --- /dev/null +++ b/Lisp/asdf/test/test4.script @@ -0,0 +1,8 @@ +;;; -*- Lisp -*- +(load "../asdf") +(setf asdf:*central-registry* '(*default-pathname-defaults*)) +(in-package :asdf) +(assert (not (component-property (find-system 'test3) :foo))) +(assert (equal (component-property (find-system 'test3) :prop1) "value")) +(setf (component-property (find-system 'test3) :foo) "bar") +(assert (equal (component-property (find-system 'test3) :foo) "bar")) diff --git a/Lisp/asdf/test/wild-module.asd b/Lisp/asdf/test/wild-module.asd new file mode 100644 index 0000000..8c09008 --- /dev/null +++ b/Lisp/asdf/test/wild-module.asd @@ -0,0 +1,6 @@ +;;; -*- Lisp -*- + +(asdf:defsystem wild-module + :version "0.0" + :components ((:wild-module "systems" + :pathname "*.asd"))) diff --git a/Lisp/asdf/test/wild-module.script b/Lisp/asdf/test/wild-module.script new file mode 100644 index 0000000..c514693 --- /dev/null +++ b/Lisp/asdf/test/wild-module.script @@ -0,0 +1,7 @@ +;;; -*- Lisp -*- + +(load "../asdf") +(load "../wild-modules") + +(setf asdf:*central-registry* '(*default-pathname-defaults*)) +(asdf:operate 'asdf:load-op 'wild-module) diff --git a/Lisp/asdf/wild-modules.lisp b/Lisp/asdf/wild-modules.lisp new file mode 100644 index 0000000..2649d7e --- /dev/null +++ b/Lisp/asdf/wild-modules.lisp @@ -0,0 +1,38 @@ +(in-package :asdf) + +(defclass wild-module (module) + ((component-class :accessor wild-module-component-class + :initform 'static-file :initarg :component-class) + (component-options :accessor wild-module-component-options + :initform nil :initarg :component-options))) + +(defmethod (setf module-components) (new-value (module wild-module)) + (when new-value + (sysdef-error "Cannot explicitly set wild-module ~A's components. Please ~ +use a wild pathname instead." module))) + +(defmethod reinitialize-instance :after ((self wild-module) &key) + (let ((pathname (slot-value self 'relative-pathname))) + (and pathname + (not (wild-pathname-p pathname)) + (sysdef-error "Wild-module ~A specified with non-wild pathname ~A." + self pathname)) + (setf (slot-value self 'components) + (let* ((*default-pathname-defaults* (component-parent-pathname self)) + (files (directory (merge-pathnames (component-relative-pathname self)))) + (class (wild-module-component-class self)) + (options (wild-module-component-options self))) + (mapcar (lambda (file) + (apply #'make-instance class + :name (file-namestring file) + ;; XXX fails when wildcards are in + ;; the directory or higher parts. + :pathname file + :parent self + options)) + files))))) + +;; Don't export wild-module or else will get a full warning +;; when (require 'asdf) if asdf is already loaded + +;;(export '(wild-module)) diff --git a/Lisp/build-lisp-image.sh b/Lisp/build-lisp-image.sh new file mode 100755 index 0000000..f741457 --- /dev/null +++ b/Lisp/build-lisp-image.sh @@ -0,0 +1,30 @@ +#!/bin/sh + +PATH="$HOME/bin:$PATH" +export PATH + +build_clisp() +{ + mkdir $topdir/clisp/base + clisp -i save-moxie-image.lisp + gzip -c /tmp/lispinit.mem > base/lispinit.mem + rm -f /tmp/lispinit.mem +} + +build_openmcl() +{ + openmcl -e '(load "save-moxie-image.lisp")' + mv /tmp/dppccl.image . +} + +build_sbcl() +{ + sbcl --load "save-moxie-image.lisp" + mv /tmp/sbcl.core . +} + +topdir=`dirname $0` + +#(cd "$topdir/clisp" && build_clisp) +#(cd "$topdir/openmcl" && build_openmcl) +(cd "$topdir/sbcl" && build_sbcl) diff --git a/Lisp/clisp/clisp b/Lisp/clisp/clisp Binary files differnew file mode 100755 index 0000000..dbf5ae4 --- /dev/null +++ b/Lisp/clisp/clisp diff --git a/Lisp/clisp/save-moxie-image.lisp b/Lisp/clisp/save-moxie-image.lisp new file mode 100644 index 0000000..7548ffa --- /dev/null +++ b/Lisp/clisp/save-moxie-image.lisp @@ -0,0 +1,5 @@ +(load "../asdf/asdf") +(pushnew (merge-pathnames ".lisp/systems/" (user-homedir-pathname)) + asdf:*central-registry*) +(asdf:operate 'asdf:load-op :moxie) +(moxie::save-lisp-and-die "/tmp/lispinit.mem") diff --git a/Lisp/init-template.lisp b/Lisp/init-template.lisp new file mode 100644 index 0000000..7f348c8 --- /dev/null +++ b/Lisp/init-template.lisp @@ -0,0 +1,3 @@ +#-asdf (require 'asdf) +#-moxie (asdf:operate 'asdf:load-op :moxie) +(moxie::start-repl)
\ No newline at end of file diff --git a/Lisp/moxie/Map_Sym.txt b/Lisp/moxie/Map_Sym.txt new file mode 100644 index 0000000..eb1a000 --- /dev/null +++ b/Lisp/moxie/Map_Sym.txt @@ -0,0 +1,1956 @@ +&ALLOW-OTHER-KEYS +../Body/03_da.htm +&AUX +../Body/03_da.htm +&BODY +../Body/03_dd.htm +&ENVIRONMENT +../Body/03_dd.htm +&KEY +../Body/03_da.htm +&OPTIONAL +../Body/03_da.htm +&REST +../Body/03_da.htm +&WHOLE +../Body/03_dd.htm +* +../Body/a_st.htm +** +../Body/v__stst_.htm +*** +../Body/v__stst_.htm +*BREAK-ON-SIGNALS* +../Body/v_break_.htm +*COMPILE-FILE-PATHNAME* +../Body/v_cmp_fi.htm +*COMPILE-FILE-TRUENAME* +../Body/v_cmp_fi.htm +*COMPILE-PRINT* +../Body/v_cmp_pr.htm +*COMPILE-VERBOSE* +../Body/v_cmp_pr.htm +*DEBUG-IO* +../Body/v_debug_.htm +*DEBUGGER-HOOK* +../Body/v_debugg.htm +*DEFAULT-PATHNAME-DEFAULTS* +../Body/v_defaul.htm +*ERROR-OUTPUT* +../Body/v_debug_.htm +*FEATURES* +../Body/v_featur.htm +*GENSYM-COUNTER* +../Body/v_gensym.htm +*LOAD-PATHNAME* +../Body/v_ld_pns.htm +*LOAD-PRINT* +../Body/v_ld_prs.htm +*LOAD-TRUENAME* +../Body/v_ld_pns.htm +*LOAD-VERBOSE* +../Body/v_ld_prs.htm +*MACROEXPAND-HOOK* +../Body/v_mexp_h.htm +*MODULES* +../Body/v_module.htm +*PACKAGE* +../Body/v_pkg.htm +*PRINT-ARRAY* +../Body/v_pr_ar.htm +*PRINT-BASE* +../Body/v_pr_bas.htm +*PRINT-CASE* +../Body/v_pr_cas.htm +*PRINT-CIRCLE* +../Body/v_pr_cir.htm +*PRINT-ESCAPE* +../Body/v_pr_esc.htm +*PRINT-GENSYM* +../Body/v_pr_gen.htm +*PRINT-LENGTH* +../Body/v_pr_lev.htm +*PRINT-LEVEL* +../Body/v_pr_lev.htm +*PRINT-LINES* +../Body/v_pr_lin.htm +*PRINT-MISER-WIDTH* +../Body/v_pr_mis.htm +*PRINT-PPRINT-DISPATCH* +../Body/v_pr_ppr.htm +*PRINT-PRETTY* +../Body/v_pr_pre.htm +*PRINT-RADIX* +../Body/v_pr_bas.htm +*PRINT-READABLY* +../Body/v_pr_rda.htm +*PRINT-RIGHT-MARGIN* +../Body/v_pr_rig.htm +*QUERY-IO* +../Body/v_debug_.htm +*RANDOM-STATE* +../Body/v_rnd_st.htm +*READ-BASE* +../Body/v_rd_bas.htm +*READ-DEFAULT-FLOAT-FORMAT* +../Body/v_rd_def.htm +*READ-EVAL* +../Body/v_rd_eva.htm +*READ-SUPPRESS* +../Body/v_rd_sup.htm +*READTABLE* +../Body/v_rdtabl.htm +*STANDARD-INPUT* +../Body/v_debug_.htm +*STANDARD-OUTPUT* +../Body/v_debug_.htm +*TERMINAL-IO* +../Body/v_termin.htm +*TRACE-OUTPUT* +../Body/v_debug_.htm ++ +../Body/a_pl.htm +++ +../Body/v_pl_plp.htm ++++ +../Body/v_pl_plp.htm +- +../Body/a__.htm +/ +../Body/a_sl.htm +// +../Body/v_sl_sls.htm +/// +../Body/v_sl_sls.htm +/= +../Body/f_eq_sle.htm +1+ +../Body/f_1pl_1_.htm +1- +../Body/f_1pl_1_.htm +< +../Body/f_eq_sle.htm +<= +../Body/f_eq_sle.htm += +../Body/f_eq_sle.htm +> +../Body/f_eq_sle.htm +>= +../Body/f_eq_sle.htm +ABORT +../Body/a_abort.htm +ABS +../Body/f_abs.htm +ACONS +../Body/f_acons.htm +ACOS +../Body/f_asin_.htm +ACOSH +../Body/f_sinh_.htm +ADD-METHOD +../Body/f_add_me.htm +ADJOIN +../Body/f_adjoin.htm +ADJUST-ARRAY +../Body/f_adjust.htm +ADJUSTABLE-ARRAY-P +../Body/f_adju_1.htm +ALLOCATE-INSTANCE +../Body/f_alloca.htm +ALPHA-CHAR-P +../Body/f_alpha_.htm +ALPHANUMERICP +../Body/f_alphan.htm +AND +../Body/a_and.htm +APPEND +../Body/f_append.htm +APPLY +../Body/f_apply.htm +APROPOS +../Body/f_apropo.htm +APROPOS-LIST +../Body/f_apropo.htm +AREF +../Body/f_aref.htm +ARITHMETIC-ERROR +../Body/e_arithm.htm +ARITHMETIC-ERROR-OPERANDS +../Body/f_arithm.htm +ARITHMETIC-ERROR-OPERATION +../Body/f_arithm.htm +ARRAY +../Body/t_array.htm +ARRAY-DIMENSION +../Body/f_ar_dim.htm +ARRAY-DIMENSION-LIMIT +../Body/v_ar_dim.htm +ARRAY-DIMENSIONS +../Body/f_ar_d_1.htm +ARRAY-DISPLACEMENT +../Body/f_ar_dis.htm +ARRAY-ELEMENT-TYPE +../Body/f_ar_ele.htm +ARRAY-HAS-FILL-POINTER-P +../Body/f_ar_has.htm +ARRAY-IN-BOUNDS-P +../Body/f_ar_in_.htm +ARRAY-RANK +../Body/f_ar_ran.htm +ARRAY-RANK-LIMIT +../Body/v_ar_ran.htm +ARRAY-ROW-MAJOR-INDEX +../Body/f_ar_row.htm +ARRAY-TOTAL-SIZE +../Body/f_ar_tot.htm +ARRAY-TOTAL-SIZE-LIMIT +../Body/v_ar_tot.htm +ARRAYP +../Body/f_arrayp.htm +ASH +../Body/f_ash.htm +ASIN +../Body/f_asin_.htm +ASINH +../Body/f_sinh_.htm +ASSERT +../Body/m_assert.htm +ASSOC +../Body/f_assocc.htm +ASSOC-IF +../Body/f_assocc.htm +ASSOC-IF-NOT +../Body/f_assocc.htm +ATAN +../Body/f_asin_.htm +ATANH +../Body/f_sinh_.htm +ATOM +../Body/a_atom.htm +BASE-CHAR +../Body/t_base_c.htm +BASE-STRING +../Body/t_base_s.htm +BIGNUM +../Body/t_bignum.htm +BIT +../Body/a_bit.htm +BIT-AND +../Body/f_bt_and.htm +BIT-ANDC1 +../Body/f_bt_and.htm +BIT-ANDC2 +../Body/f_bt_and.htm +BIT-EQV +../Body/f_bt_and.htm +BIT-IOR +../Body/f_bt_and.htm +BIT-NAND +../Body/f_bt_and.htm +BIT-NOR +../Body/f_bt_and.htm +BIT-NOT +../Body/f_bt_and.htm +BIT-ORC1 +../Body/f_bt_and.htm +BIT-ORC2 +../Body/f_bt_and.htm +BIT-VECTOR +../Body/t_bt_vec.htm +BIT-VECTOR-P +../Body/f_bt_vec.htm +BIT-XOR +../Body/f_bt_and.htm +BLOCK +../Body/s_block.htm +BOOLE +../Body/f_boole.htm +BOOLE-1 +../Body/v_b_1_b.htm +BOOLE-2 +../Body/v_b_1_b.htm +BOOLE-AND +../Body/v_b_1_b.htm +BOOLE-ANDC1 +../Body/v_b_1_b.htm +BOOLE-ANDC2 +../Body/v_b_1_b.htm +BOOLE-C1 +../Body/v_b_1_b.htm +BOOLE-C2 +../Body/v_b_1_b.htm +BOOLE-CLR +../Body/v_b_1_b.htm +BOOLE-EQV +../Body/v_b_1_b.htm +BOOLE-IOR +../Body/v_b_1_b.htm +BOOLE-NAND +../Body/v_b_1_b.htm +BOOLE-NOR +../Body/v_b_1_b.htm +BOOLE-ORC1 +../Body/v_b_1_b.htm +BOOLE-ORC2 +../Body/v_b_1_b.htm +BOOLE-SET +../Body/v_b_1_b.htm +BOOLE-XOR +../Body/v_b_1_b.htm +BOOLEAN +../Body/t_ban.htm +BOTH-CASE-P +../Body/f_upper_.htm +BOUNDP +../Body/f_boundp.htm +BREAK +../Body/f_break.htm +BROADCAST-STREAM +../Body/t_broadc.htm +BROADCAST-STREAM-STREAMS +../Body/f_broadc.htm +BUILT-IN-CLASS +../Body/t_built_.htm +BUTLAST +../Body/f_butlas.htm +BYTE +../Body/f_by_by.htm +BYTE-POSITION +../Body/f_by_by.htm +BYTE-SIZE +../Body/f_by_by.htm +CAAAAR +../Body/f_car_c.htm +CAAADR +../Body/f_car_c.htm +CAAAR +../Body/f_car_c.htm +CAADAR +../Body/f_car_c.htm +CAADDR +../Body/f_car_c.htm +CAADR +../Body/f_car_c.htm +CAAR +../Body/f_car_c.htm +CADAAR +../Body/f_car_c.htm +CADADR +../Body/f_car_c.htm +CADAR +../Body/f_car_c.htm +CADDAR +../Body/f_car_c.htm +CADDDR +../Body/f_car_c.htm +CADDR +../Body/f_car_c.htm +CADR +../Body/f_car_c.htm +CALL-ARGUMENTS-LIMIT +../Body/v_call_a.htm +CALL-METHOD +../Body/m_call_m.htm +CALL-NEXT-METHOD +../Body/f_call_n.htm +CAR +../Body/f_car_c.htm +CASE +../Body/m_case_.htm +CATCH +../Body/s_catch.htm +CCASE +../Body/m_case_.htm +CDAAAR +../Body/f_car_c.htm +CDAADR +../Body/f_car_c.htm +CDAAR +../Body/f_car_c.htm +CDADAR +../Body/f_car_c.htm +CDADDR +../Body/f_car_c.htm +CDADR +../Body/f_car_c.htm +CDAR +../Body/f_car_c.htm +CDDAAR +../Body/f_car_c.htm +CDDADR +../Body/f_car_c.htm +CDDAR +../Body/f_car_c.htm +CDDDAR +../Body/f_car_c.htm +CDDDDR +../Body/f_car_c.htm +CDDDR +../Body/f_car_c.htm +CDDR +../Body/f_car_c.htm +CDR +../Body/f_car_c.htm +CEILING +../Body/f_floorc.htm +CELL-ERROR +../Body/e_cell_e.htm +CELL-ERROR-NAME +../Body/f_cell_e.htm +CERROR +../Body/f_cerror.htm +CHANGE-CLASS +../Body/f_chg_cl.htm +CHAR +../Body/f_char_.htm +CHAR-CODE +../Body/f_char_c.htm +CHAR-CODE-LIMIT +../Body/v_char_c.htm +CHAR-DOWNCASE +../Body/f_char_u.htm +CHAR-EQUAL +../Body/f_chareq.htm +CHAR-GREATERP +../Body/f_chareq.htm +CHAR-INT +../Body/f_char_i.htm +CHAR-LESSP +../Body/f_chareq.htm +CHAR-NAME +../Body/f_char_n.htm +CHAR-NOT-EQUAL +../Body/f_chareq.htm +CHAR-NOT-GREATERP +../Body/f_chareq.htm +CHAR-NOT-LESSP +../Body/f_chareq.htm +CHAR-UPCASE +../Body/f_char_u.htm +CHAR/= +../Body/f_chareq.htm +CHAR< +../Body/f_chareq.htm +CHAR<= +../Body/f_chareq.htm +CHAR= +../Body/f_chareq.htm +CHAR> +../Body/f_chareq.htm +CHAR>= +../Body/f_chareq.htm +CHARACTER +../Body/a_ch.htm +CHARACTERP +../Body/f_chp.htm +CHECK-TYPE +../Body/m_check_.htm +CIS +../Body/f_cis.htm +CLASS +../Body/t_class.htm +CLASS-NAME +../Body/f_class_.htm +CLASS-OF +../Body/f_clas_1.htm +CLEAR-INPUT +../Body/f_clear_.htm +CLEAR-OUTPUT +../Body/f_finish.htm +CLOSE +../Body/f_close.htm +CLRHASH +../Body/f_clrhas.htm +CODE-CHAR +../Body/f_code_c.htm +COERCE +../Body/f_coerce.htm +COMPILATION-SPEED +../Body/d_optimi.htm +COMPILE +../Body/f_cmp.htm +COMPILE-FILE +../Body/f_cmp_fi.htm +COMPILE-FILE-PATHNAME +../Body/f_cmp__1.htm +COMPILED-FUNCTION +../Body/t_cmpd_f.htm +COMPILED-FUNCTION-P +../Body/f_cmpd_f.htm +COMPILER-MACRO +../Body/f_docume.htm +COMPILER-MACRO-FUNCTION +../Body/f_cmp_ma.htm +COMPLEMENT +../Body/f_comple.htm +COMPLEX +../Body/a_comple.htm +COMPLEXP +../Body/f_comp_3.htm +COMPUTE-APPLICABLE-METHODS +../Body/f_comput.htm +COMPUTE-RESTARTS +../Body/f_comp_1.htm +CONCATENATE +../Body/f_concat.htm +CONCATENATED-STREAM +../Body/t_concat.htm +CONCATENATED-STREAM-STREAMS +../Body/f_conc_1.htm +COND +../Body/m_cond.htm +CONDITION +../Body/e_cnd.htm +CONJUGATE +../Body/f_conjug.htm +CONS +../Body/a_cons.htm +CONSP +../Body/f_consp.htm +CONSTANTLY +../Body/f_cons_1.htm +CONSTANTP +../Body/f_consta.htm +CONTINUE +../Body/a_contin.htm +CONTROL-ERROR +../Body/e_contro.htm +COPY-ALIST +../Body/f_cp_ali.htm +COPY-LIST +../Body/f_cp_lis.htm +COPY-PPRINT-DISPATCH +../Body/f_cp_ppr.htm +COPY-READTABLE +../Body/f_cp_rdt.htm +COPY-SEQ +../Body/f_cp_seq.htm +COPY-STRUCTURE +../Body/f_cp_stu.htm +COPY-SYMBOL +../Body/f_cp_sym.htm +COPY-TREE +../Body/f_cp_tre.htm +COS +../Body/f_sin_c.htm +COSH +../Body/f_sinh_.htm +COUNT +../Body/f_countc.htm +COUNT-IF +../Body/f_countc.htm +COUNT-IF-NOT +../Body/f_countc.htm +CTYPECASE +../Body/m_tpcase.htm +DEBUG +../Body/d_optimi.htm +DECF +../Body/m_incf_.htm +DECLAIM +../Body/m_declai.htm +DECLARATION +../Body/d_declar.htm +DECLARE +../Body/s_declar.htm +DECODE-FLOAT +../Body/f_dec_fl.htm +DECODE-UNIVERSAL-TIME +../Body/f_dec_un.htm +DEFCLASS +../Body/m_defcla.htm +DEFCONSTANT +../Body/m_defcon.htm +DEFGENERIC +../Body/m_defgen.htm +DEFINE-COMPILER-MACRO +../Body/m_define.htm +DEFINE-CONDITION +../Body/m_defi_5.htm +DEFINE-METHOD-COMBINATION +../Body/m_defi_4.htm +DEFINE-MODIFY-MACRO +../Body/m_defi_2.htm +DEFINE-SETF-EXPANDER +../Body/m_defi_3.htm +DEFINE-SYMBOL-MACRO +../Body/m_defi_1.htm +DEFMACRO +../Body/m_defmac.htm +DEFMETHOD +../Body/m_defmet.htm +DEFPACKAGE +../Body/m_defpkg.htm +DEFPARAMETER +../Body/m_defpar.htm +DEFSETF +../Body/m_defset.htm +DEFSTRUCT +../Body/m_defstr.htm +DEFTYPE +../Body/m_deftp.htm +DEFUN +../Body/m_defun.htm +DEFVAR +../Body/m_defpar.htm +DELETE +../Body/f_rm_rm.htm +DELETE-DUPLICATES +../Body/f_rm_dup.htm +DELETE-FILE +../Body/f_del_fi.htm +DELETE-IF +../Body/f_rm_rm.htm +DELETE-IF-NOT +../Body/f_rm_rm.htm +DELETE-PACKAGE +../Body/f_del_pk.htm +DENOMINATOR +../Body/f_numera.htm +DEPOSIT-FIELD +../Body/f_deposi.htm +DESCRIBE +../Body/f_descri.htm +DESCRIBE-OBJECT +../Body/f_desc_1.htm +DESTRUCTURING-BIND +../Body/m_destru.htm +DIGIT-CHAR +../Body/f_digit_.htm +DIGIT-CHAR-P +../Body/f_digi_1.htm +DIRECTORY +../Body/f_dir.htm +DIRECTORY-NAMESTRING +../Body/f_namest.htm +DISASSEMBLE +../Body/f_disass.htm +DIVISION-BY-ZERO +../Body/e_divisi.htm +DO +../Body/m_do_do.htm +DO* +../Body/m_do_do.htm +DO-ALL-SYMBOLS +../Body/m_do_sym.htm +DO-EXTERNAL-SYMBOLS +../Body/m_do_sym.htm +DO-SYMBOLS +../Body/m_do_sym.htm +DOCUMENTATION +../Body/f_docume.htm +DOLIST +../Body/m_dolist.htm +DOTIMES +../Body/m_dotime.htm +DOUBLE-FLOAT +../Body/t_short_.htm +DOUBLE-FLOAT-EPSILON +../Body/v_short_.htm +DOUBLE-FLOAT-NEGATIVE-EPSILON +../Body/v_short_.htm +DPB +../Body/f_dpb.htm +DRIBBLE +../Body/f_dribbl.htm +DYNAMIC-EXTENT +../Body/d_dynami.htm +ECASE +../Body/m_case_.htm +ECHO-STREAM +../Body/t_echo_s.htm +ECHO-STREAM-INPUT-STREAM +../Body/f_echo_s.htm +ECHO-STREAM-OUTPUT-STREAM +../Body/f_echo_s.htm +ED +../Body/f_ed.htm +EIGHTH +../Body/f_firstc.htm +ELT +../Body/f_elt.htm +ENCODE-UNIVERSAL-TIME +../Body/f_encode.htm +END-OF-FILE +../Body/e_end_of.htm +ENDP +../Body/f_endp.htm +ENOUGH-NAMESTRING +../Body/f_namest.htm +ENSURE-DIRECTORIES-EXIST +../Body/f_ensu_1.htm +ENSURE-GENERIC-FUNCTION +../Body/f_ensure.htm +EQ +../Body/f_eq.htm +EQL +../Body/a_eql.htm +EQUAL +../Body/f_equal.htm +EQUALP +../Body/f_equalp.htm +ERROR +../Body/a_error.htm +ETYPECASE +../Body/m_tpcase.htm +EVAL +../Body/f_eval.htm +EVAL-WHEN +../Body/s_eval_w.htm +EVENP +../Body/f_evenpc.htm +EVERY +../Body/f_everyc.htm +EXP +../Body/f_exp_e.htm +EXPORT +../Body/f_export.htm +EXPT +../Body/f_exp_e.htm +EXTENDED-CHAR +../Body/t_extend.htm +FBOUNDP +../Body/f_fbound.htm +FCEILING +../Body/f_floorc.htm +FDEFINITION +../Body/f_fdefin.htm +FFLOOR +../Body/f_floorc.htm +FIFTH +../Body/f_firstc.htm +FILE-AUTHOR +../Body/f_file_a.htm +FILE-ERROR +../Body/e_file_e.htm +FILE-ERROR-PATHNAME +../Body/f_file_e.htm +FILE-LENGTH +../Body/f_file_l.htm +FILE-NAMESTRING +../Body/f_namest.htm +FILE-POSITION +../Body/f_file_p.htm +FILE-STREAM +../Body/t_file_s.htm +FILE-STRING-LENGTH +../Body/f_file_s.htm +FILE-WRITE-DATE +../Body/f_file_w.htm +FILL +../Body/f_fill.htm +FILL-POINTER +../Body/f_fill_p.htm +FIND +../Body/f_find_.htm +FIND-ALL-SYMBOLS +../Body/f_find_a.htm +FIND-CLASS +../Body/f_find_c.htm +FIND-IF +../Body/f_find_.htm +FIND-IF-NOT +../Body/f_find_.htm +FIND-METHOD +../Body/f_find_m.htm +FIND-PACKAGE +../Body/f_find_p.htm +FIND-RESTART +../Body/f_find_r.htm +FIND-SYMBOL +../Body/f_find_s.htm +FINISH-OUTPUT +../Body/f_finish.htm +FIRST +../Body/f_firstc.htm +FIXNUM +../Body/t_fixnum.htm +FLET +../Body/s_flet_.htm +FLOAT +../Body/a_float.htm +FLOAT-DIGITS +../Body/f_dec_fl.htm +FLOAT-PRECISION +../Body/f_dec_fl.htm +FLOAT-RADIX +../Body/f_dec_fl.htm +FLOAT-SIGN +../Body/f_dec_fl.htm +FLOATING-POINT-INEXACT +../Body/e_floa_1.htm +FLOATING-POINT-INVALID-OPERATION +../Body/e_floati.htm +FLOATING-POINT-OVERFLOW +../Body/e_floa_2.htm +FLOATING-POINT-UNDERFLOW +../Body/e_floa_3.htm +FLOATP +../Body/f_floatp.htm +FLOOR +../Body/f_floorc.htm +FMAKUNBOUND +../Body/f_fmakun.htm +FORCE-OUTPUT +../Body/f_finish.htm +FORMAT +../Body/f_format.htm +FORMATTER +../Body/m_format.htm +FOURTH +../Body/f_firstc.htm +FRESH-LINE +../Body/f_terpri.htm +FROUND +../Body/f_floorc.htm +FTRUNCATE +../Body/f_floorc.htm +FTYPE +../Body/d_ftype.htm +FUNCALL +../Body/f_funcal.htm +FUNCTION +../Body/a_fn.htm +FUNCTION-KEYWORDS +../Body/f_fn_kwd.htm +FUNCTION-LAMBDA-EXPRESSION +../Body/f_fn_lam.htm +FUNCTIONP +../Body/f_fnp.htm +GCD +../Body/f_gcd.htm +GENERIC-FUNCTION +../Body/t_generi.htm +GENSYM +../Body/f_gensym.htm +GENTEMP +../Body/f_gentem.htm +GET +../Body/f_get.htm +GET-DECODED-TIME +../Body/f_get_un.htm +GET-DISPATCH-MACRO-CHARACTER +../Body/f_set__1.htm +GET-INTERNAL-REAL-TIME +../Body/f_get_in.htm +GET-INTERNAL-RUN-TIME +../Body/f_get__1.htm +GET-MACRO-CHARACTER +../Body/f_set_ma.htm +GET-OUTPUT-STREAM-STRING +../Body/f_get_ou.htm +GET-PROPERTIES +../Body/f_get_pr.htm +GET-SETF-EXPANSION +../Body/f_get_se.htm +GET-UNIVERSAL-TIME +../Body/f_get_un.htm +GETF +../Body/f_getf.htm +GETHASH +../Body/f_gethas.htm +GO +../Body/s_go.htm +GRAPHIC-CHAR-P +../Body/f_graphi.htm +HANDLER-BIND +../Body/m_handle.htm +HANDLER-CASE +../Body/m_hand_1.htm +HASH-TABLE +../Body/t_hash_t.htm +HASH-TABLE-COUNT +../Body/f_hash_1.htm +HASH-TABLE-P +../Body/f_hash_t.htm +HASH-TABLE-REHASH-SIZE +../Body/f_hash_2.htm +HASH-TABLE-REHASH-THRESHOLD +../Body/f_hash_3.htm +HASH-TABLE-SIZE +../Body/f_hash_4.htm +HASH-TABLE-TEST +../Body/f_hash_5.htm +HOST-NAMESTRING +../Body/f_namest.htm +IDENTITY +../Body/f_identi.htm +IF +../Body/s_if.htm +IGNORABLE +../Body/d_ignore.htm +IGNORE +../Body/d_ignore.htm +IGNORE-ERRORS +../Body/m_ignore.htm +IMAGPART +../Body/f_realpa.htm +IMPORT +../Body/f_import.htm +IN-PACKAGE +../Body/m_in_pkg.htm +INCF +../Body/m_incf_.htm +INITIALIZE-INSTANCE +../Body/f_init_i.htm +INLINE +../Body/d_inline.htm +INPUT-STREAM-P +../Body/f_in_stm.htm +INSPECT +../Body/f_inspec.htm +INTEGER +../Body/t_intege.htm +INTEGER-DECODE-FLOAT +../Body/f_dec_fl.htm +INTEGER-LENGTH +../Body/f_intege.htm +INTEGERP +../Body/f_inte_1.htm +INTERACTIVE-STREAM-P +../Body/f_intera.htm +INTERN +../Body/f_intern.htm +INTERNAL-TIME-UNITS-PER-SECOND +../Body/v_intern.htm +INTERSECTION +../Body/f_isec_.htm +INVALID-METHOD-ERROR +../Body/f_invali.htm +INVOKE-DEBUGGER +../Body/f_invoke.htm +INVOKE-RESTART +../Body/f_invo_1.htm +INVOKE-RESTART-INTERACTIVELY +../Body/f_invo_2.htm +ISQRT +../Body/f_sqrt_.htm +KEYWORD +../Body/t_kwd.htm +KEYWORDP +../Body/f_kwdp.htm +LABELS +../Body/s_flet_.htm +LAMBDA +../Body/a_lambda.htm +LAMBDA-LIST-KEYWORDS +../Body/v_lambda.htm +LAMBDA-PARAMETERS-LIMIT +../Body/v_lamb_1.htm +LAST +../Body/f_last.htm +LCM +../Body/f_lcm.htm +LDB +../Body/f_ldb.htm +LDB-TEST +../Body/f_ldb_te.htm +LDIFF +../Body/f_ldiffc.htm +LEAST-NEGATIVE-DOUBLE-FLOAT +../Body/v_most_1.htm +LEAST-NEGATIVE-LONG-FLOAT +../Body/v_most_1.htm +LEAST-NEGATIVE-NORMALIZED-DOUBLE-FLOAT +../Body/v_most_1.htm +LEAST-NEGATIVE-NORMALIZED-LONG-FLOAT +../Body/v_most_1.htm +LEAST-NEGATIVE-NORMALIZED-SHORT-FLOAT +../Body/v_most_1.htm +LEAST-NEGATIVE-NORMALIZED-SINGLE-FLOAT +../Body/v_most_1.htm +LEAST-NEGATIVE-SHORT-FLOAT +../Body/v_most_1.htm +LEAST-NEGATIVE-SINGLE-FLOAT +../Body/v_most_1.htm +LEAST-POSITIVE-DOUBLE-FLOAT +../Body/v_most_1.htm +LEAST-POSITIVE-LONG-FLOAT +../Body/v_most_1.htm +LEAST-POSITIVE-NORMALIZED-DOUBLE-FLOAT +../Body/v_most_1.htm +LEAST-POSITIVE-NORMALIZED-LONG-FLOAT +../Body/v_most_1.htm +LEAST-POSITIVE-NORMALIZED-SHORT-FLOAT +../Body/v_most_1.htm +LEAST-POSITIVE-NORMALIZED-SINGLE-FLOAT +../Body/v_most_1.htm +LEAST-POSITIVE-SHORT-FLOAT +../Body/v_most_1.htm +LEAST-POSITIVE-SINGLE-FLOAT +../Body/v_most_1.htm +LENGTH +../Body/f_length.htm +LET +../Body/s_let_l.htm +LET* +../Body/s_let_l.htm +LISP-IMPLEMENTATION-TYPE +../Body/f_lisp_i.htm +LISP-IMPLEMENTATION-VERSION +../Body/f_lisp_i.htm +LIST +../Body/a_list.htm +LIST* +../Body/f_list_.htm +LIST-ALL-PACKAGES +../Body/f_list_a.htm +LIST-LENGTH +../Body/f_list_l.htm +LISTEN +../Body/f_listen.htm +LISTP +../Body/f_listp.htm +LOAD +../Body/f_load.htm +LOAD-LOGICAL-PATHNAME-TRANSLATIONS +../Body/f_ld_log.htm +LOAD-TIME-VALUE +../Body/s_ld_tim.htm +LOCALLY +../Body/s_locall.htm +LOG +../Body/f_log.htm +LOGAND +../Body/f_logand.htm +LOGANDC1 +../Body/f_logand.htm +LOGANDC2 +../Body/f_logand.htm +LOGBITP +../Body/f_logbtp.htm +LOGCOUNT +../Body/f_logcou.htm +LOGEQV +../Body/f_logand.htm +LOGICAL-PATHNAME +../Body/a_logica.htm +LOGICAL-PATHNAME-TRANSLATIONS +../Body/f_logica.htm +LOGIOR +../Body/f_logand.htm +LOGNAND +../Body/f_logand.htm +LOGNOR +../Body/f_logand.htm +LOGNOT +../Body/f_logand.htm +LOGORC1 +../Body/f_logand.htm +LOGORC2 +../Body/f_logand.htm +LOGTEST +../Body/f_logtes.htm +LOGXOR +../Body/f_logand.htm +LONG-FLOAT +../Body/t_short_.htm +LONG-FLOAT-EPSILON +../Body/v_short_.htm +LONG-FLOAT-NEGATIVE-EPSILON +../Body/v_short_.htm +LONG-SITE-NAME +../Body/f_short_.htm +LOOP +../Body/m_loop.htm +LOOP-FINISH +../Body/m_loop_f.htm +LOWER-CASE-P +../Body/f_upper_.htm +MACHINE-INSTANCE +../Body/f_mach_i.htm +MACHINE-TYPE +../Body/f_mach_t.htm +MACHINE-VERSION +../Body/f_mach_v.htm +MACRO-FUNCTION +../Body/f_macro_.htm +MACROEXPAND +../Body/f_mexp_.htm +MACROEXPAND-1 +../Body/f_mexp_.htm +MACROLET +../Body/s_flet_.htm +MAKE-ARRAY +../Body/f_mk_ar.htm +MAKE-BROADCAST-STREAM +../Body/f_mk_bro.htm +MAKE-CONCATENATED-STREAM +../Body/f_mk_con.htm +MAKE-CONDITION +../Body/f_mk_cnd.htm +MAKE-DISPATCH-MACRO-CHARACTER +../Body/f_mk_dis.htm +MAKE-ECHO-STREAM +../Body/f_mk_ech.htm +MAKE-HASH-TABLE +../Body/f_mk_has.htm +MAKE-INSTANCE +../Body/f_mk_ins.htm +MAKE-INSTANCES-OBSOLETE +../Body/f_mk_i_1.htm +MAKE-LIST +../Body/f_mk_lis.htm +MAKE-LOAD-FORM +../Body/f_mk_ld_.htm +MAKE-LOAD-FORM-SAVING-SLOTS +../Body/f_mk_l_1.htm +MAKE-METHOD +../Body/m_call_m.htm +MAKE-PACKAGE +../Body/f_mk_pkg.htm +MAKE-PATHNAME +../Body/f_mk_pn.htm +MAKE-RANDOM-STATE +../Body/f_mk_rnd.htm +MAKE-SEQUENCE +../Body/f_mk_seq.htm +MAKE-STRING +../Body/f_mk_stg.htm +MAKE-STRING-INPUT-STREAM +../Body/f_mk_s_1.htm +MAKE-STRING-OUTPUT-STREAM +../Body/f_mk_s_2.htm +MAKE-SYMBOL +../Body/f_mk_sym.htm +MAKE-SYNONYM-STREAM +../Body/f_mk_syn.htm +MAKE-TWO-WAY-STREAM +../Body/f_mk_two.htm +MAKUNBOUND +../Body/f_makunb.htm +MAP +../Body/f_map.htm +MAP-INTO +../Body/f_map_in.htm +MAPC +../Body/f_mapc_.htm +MAPCAN +../Body/f_mapc_.htm +MAPCAR +../Body/f_mapc_.htm +MAPCON +../Body/f_mapc_.htm +MAPHASH +../Body/f_maphas.htm +MAPL +../Body/f_mapc_.htm +MAPLIST +../Body/f_mapc_.htm +MASK-FIELD +../Body/f_mask_f.htm +MAX +../Body/f_max_m.htm +MEMBER +../Body/a_member.htm +MEMBER-IF +../Body/f_mem_m.htm +MEMBER-IF-NOT +../Body/f_mem_m.htm +MERGE +../Body/f_merge.htm +MERGE-PATHNAMES +../Body/f_merge_.htm +METHOD +../Body/t_method.htm +METHOD-COMBINATION +../Body/a_method.htm +METHOD-COMBINATION-ERROR +../Body/f_meth_1.htm +METHOD-QUALIFIERS +../Body/f_method.htm +MIN +../Body/f_max_m.htm +MINUSP +../Body/f_minusp.htm +MISMATCH +../Body/f_mismat.htm +MOD +../Body/a_mod.htm +MOST-NEGATIVE-DOUBLE-FLOAT +../Body/v_most_1.htm +MOST-NEGATIVE-FIXNUM +../Body/v_most_p.htm +MOST-NEGATIVE-LONG-FLOAT +../Body/v_most_1.htm +MOST-NEGATIVE-SHORT-FLOAT +../Body/v_most_1.htm +MOST-NEGATIVE-SINGLE-FLOAT +../Body/v_most_1.htm +MOST-POSITIVE-DOUBLE-FLOAT +../Body/v_most_1.htm +MOST-POSITIVE-FIXNUM +../Body/v_most_p.htm +MOST-POSITIVE-LONG-FLOAT +../Body/v_most_1.htm +MOST-POSITIVE-SHORT-FLOAT +../Body/v_most_1.htm +MOST-POSITIVE-SINGLE-FLOAT +../Body/v_most_1.htm +MUFFLE-WARNING +../Body/a_muffle.htm +MULTIPLE-VALUE-BIND +../Body/m_multip.htm +MULTIPLE-VALUE-CALL +../Body/s_multip.htm +MULTIPLE-VALUE-LIST +../Body/m_mult_1.htm +MULTIPLE-VALUE-PROG1 +../Body/s_mult_1.htm +MULTIPLE-VALUE-SETQ +../Body/m_mult_2.htm +MULTIPLE-VALUES-LIMIT +../Body/v_multip.htm +NAME-CHAR +../Body/f_name_c.htm +NAMESTRING +../Body/f_namest.htm +NBUTLAST +../Body/f_butlas.htm +NCONC +../Body/f_nconc.htm +NEXT-METHOD-P +../Body/f_next_m.htm +NIL +../Body/a_nil.htm +NINTERSECTION +../Body/f_isec_.htm +NINTH +../Body/f_firstc.htm +NO-APPLICABLE-METHOD +../Body/f_no_app.htm +NO-NEXT-METHOD +../Body/f_no_nex.htm +NOT +../Body/a_not.htm +NOTANY +../Body/f_everyc.htm +NOTEVERY +../Body/f_everyc.htm +NOTINLINE +../Body/d_inline.htm +NRECONC +../Body/f_revapp.htm +NREVERSE +../Body/f_revers.htm +NSET-DIFFERENCE +../Body/f_set_di.htm +NSET-EXCLUSIVE-OR +../Body/f_set_ex.htm +NSTRING-CAPITALIZE +../Body/f_stg_up.htm +NSTRING-DOWNCASE +../Body/f_stg_up.htm +NSTRING-UPCASE +../Body/f_stg_up.htm +NSUBLIS +../Body/f_sublis.htm +NSUBST +../Body/f_substc.htm +NSUBST-IF +../Body/f_substc.htm +NSUBST-IF-NOT +../Body/f_substc.htm +NSUBSTITUTE +../Body/f_sbs_s.htm +NSUBSTITUTE-IF +../Body/f_sbs_s.htm +NSUBSTITUTE-IF-NOT +../Body/f_sbs_s.htm +NTH +../Body/f_nth.htm +NTH-VALUE +../Body/m_nth_va.htm +NTHCDR +../Body/f_nthcdr.htm +NULL +../Body/a_null.htm +NUMBER +../Body/t_number.htm +NUMBERP +../Body/f_nump.htm +NUMERATOR +../Body/f_numera.htm +NUNION +../Body/f_unionc.htm +ODDP +../Body/f_evenpc.htm +OPEN +../Body/f_open.htm +OPEN-STREAM-P +../Body/f_open_s.htm +OPTIMIZE +../Body/d_optimi.htm +OR +../Body/a_or.htm +OTHERWISE +../Body/m_case_.htm +OUTPUT-STREAM-P +../Body/f_in_stm.htm +PACKAGE +../Body/t_pkg.htm +PACKAGE-ERROR +../Body/e_pkg_er.htm +PACKAGE-ERROR-PACKAGE +../Body/f_pkg_er.htm +PACKAGE-NAME +../Body/f_pkg_na.htm +PACKAGE-NICKNAMES +../Body/f_pkg_ni.htm +PACKAGE-SHADOWING-SYMBOLS +../Body/f_pkg_sh.htm +PACKAGE-USE-LIST +../Body/f_pkg_us.htm +PACKAGE-USED-BY-LIST +../Body/f_pkg__1.htm +PACKAGEP +../Body/f_pkgp.htm +PAIRLIS +../Body/f_pairli.htm +PARSE-ERROR +../Body/e_parse_.htm +PARSE-INTEGER +../Body/f_parse_.htm +PARSE-NAMESTRING +../Body/f_pars_1.htm +PATHNAME +../Body/a_pn.htm +PATHNAME-DEVICE +../Body/f_pn_hos.htm +PATHNAME-DIRECTORY +../Body/f_pn_hos.htm +PATHNAME-HOST +../Body/f_pn_hos.htm +PATHNAME-MATCH-P +../Body/f_pn_mat.htm +PATHNAME-NAME +../Body/f_pn_hos.htm +PATHNAME-TYPE +../Body/f_pn_hos.htm +PATHNAME-VERSION +../Body/f_pn_hos.htm +PATHNAMEP +../Body/f_pnp.htm +PEEK-CHAR +../Body/f_peek_c.htm +PHASE +../Body/f_phase.htm +PI +../Body/v_pi.htm +PLUSP +../Body/f_minusp.htm +POP +../Body/m_pop.htm +POSITION +../Body/f_pos_p.htm +POSITION-IF +../Body/f_pos_p.htm +POSITION-IF-NOT +../Body/f_pos_p.htm +PPRINT +../Body/f_wr_pr.htm +PPRINT-DISPATCH +../Body/f_ppr_di.htm +PPRINT-EXIT-IF-LIST-EXHAUSTED +../Body/m_ppr_ex.htm +PPRINT-FILL +../Body/f_ppr_fi.htm +PPRINT-INDENT +../Body/f_ppr_in.htm +PPRINT-LINEAR +../Body/f_ppr_fi.htm +PPRINT-LOGICAL-BLOCK +../Body/m_ppr_lo.htm +PPRINT-NEWLINE +../Body/f_ppr_nl.htm +PPRINT-POP +../Body/m_ppr_po.htm +PPRINT-TAB +../Body/f_ppr_ta.htm +PPRINT-TABULAR +../Body/f_ppr_fi.htm +PRIN1 +../Body/f_wr_pr.htm +PRIN1-TO-STRING +../Body/f_wr_to_.htm +PRINC +../Body/f_wr_pr.htm +PRINC-TO-STRING +../Body/f_wr_to_.htm +PRINT +../Body/f_wr_pr.htm +PRINT-NOT-READABLE +../Body/e_pr_not.htm +PRINT-NOT-READABLE-OBJECT +../Body/f_pr_not.htm +PRINT-OBJECT +../Body/f_pr_obj.htm +PRINT-UNREADABLE-OBJECT +../Body/m_pr_unr.htm +PROBE-FILE +../Body/f_probe_.htm +PROCLAIM +../Body/f_procla.htm +PROG +../Body/m_prog_.htm +PROG* +../Body/m_prog_.htm +PROG1 +../Body/m_prog1c.htm +PROG2 +../Body/m_prog1c.htm +PROGN +../Body/s_progn.htm +PROGRAM-ERROR +../Body/e_progra.htm +PROGV +../Body/s_progv.htm +PROVIDE +../Body/f_provid.htm +PSETF +../Body/m_setf_.htm +PSETQ +../Body/m_psetq.htm +PUSH +../Body/m_push.htm +PUSHNEW +../Body/m_pshnew.htm +QUOTE +../Body/s_quote.htm +RANDOM +../Body/f_random.htm +RANDOM-STATE +../Body/t_rnd_st.htm +RANDOM-STATE-P +../Body/f_rnd_st.htm +RASSOC +../Body/f_rassoc.htm +RASSOC-IF +../Body/f_rassoc.htm +RASSOC-IF-NOT +../Body/f_rassoc.htm +RATIO +../Body/t_ratio.htm +RATIONAL +../Body/a_ration.htm +RATIONALIZE +../Body/f_ration.htm +RATIONALP +../Body/f_rati_1.htm +READ +../Body/f_rd_rd.htm +READ-BYTE +../Body/f_rd_by.htm +READ-CHAR +../Body/f_rd_cha.htm +READ-CHAR-NO-HANG +../Body/f_rd_c_1.htm +READ-DELIMITED-LIST +../Body/f_rd_del.htm +READ-FROM-STRING +../Body/f_rd_fro.htm +READ-LINE +../Body/f_rd_lin.htm +READ-PRESERVING-WHITESPACE +../Body/f_rd_rd.htm +READ-SEQUENCE +../Body/f_rd_seq.htm +READER-ERROR +../Body/e_rder_e.htm +READTABLE +../Body/t_rdtabl.htm +READTABLE-CASE +../Body/f_rdtabl.htm +READTABLEP +../Body/f_rdta_1.htm +REAL +../Body/t_real.htm +REALP +../Body/f_realp.htm +REALPART +../Body/f_realpa.htm +REDUCE +../Body/f_reduce.htm +REINITIALIZE-INSTANCE +../Body/f_reinit.htm +REM +../Body/f_mod_r.htm +REMF +../Body/m_remf.htm +REMHASH +../Body/f_remhas.htm +REMOVE +../Body/f_rm_rm.htm +REMOVE-DUPLICATES +../Body/f_rm_dup.htm +REMOVE-IF +../Body/f_rm_rm.htm +REMOVE-IF-NOT +../Body/f_rm_rm.htm +REMOVE-METHOD +../Body/f_rm_met.htm +REMPROP +../Body/f_rempro.htm +RENAME-FILE +../Body/f_rn_fil.htm +RENAME-PACKAGE +../Body/f_rn_pkg.htm +REPLACE +../Body/f_replac.htm +REQUIRE +../Body/f_provid.htm +REST +../Body/f_rest.htm +RESTART +../Body/t_rst.htm +RESTART-BIND +../Body/m_rst_bi.htm +RESTART-CASE +../Body/m_rst_ca.htm +RESTART-NAME +../Body/f_rst_na.htm +RETURN +../Body/m_return.htm +RETURN-FROM +../Body/s_ret_fr.htm +REVAPPEND +../Body/f_revapp.htm +REVERSE +../Body/f_revers.htm +ROOM +../Body/f_room.htm +ROTATEF +../Body/m_rotate.htm +ROUND +../Body/f_floorc.htm +ROW-MAJOR-AREF +../Body/f_row_ma.htm +RPLACA +../Body/f_rplaca.htm +RPLACD +../Body/f_rplaca.htm +SAFETY +../Body/d_optimi.htm +SATISFIES +../Body/t_satisf.htm +SBIT +../Body/f_bt_sb.htm +SCALE-FLOAT +../Body/f_dec_fl.htm +SCHAR +../Body/f_char_.htm +SEARCH +../Body/f_search.htm +SECOND +../Body/f_firstc.htm +SEQUENCE +../Body/t_seq.htm +SERIOUS-CONDITION +../Body/e_seriou.htm +SET +../Body/f_set.htm +SET-DIFFERENCE +../Body/f_set_di.htm +SET-DISPATCH-MACRO-CHARACTER +../Body/f_set__1.htm +SET-EXCLUSIVE-OR +../Body/f_set_ex.htm +SET-MACRO-CHARACTER +../Body/f_set_ma.htm +SET-PPRINT-DISPATCH +../Body/f_set_pp.htm +SET-SYNTAX-FROM-CHAR +../Body/f_set_sy.htm +SETF +../Body/a_setf.htm +SETQ +../Body/s_setq.htm +SEVENTH +../Body/f_firstc.htm +SHADOW +../Body/f_shadow.htm +SHADOWING-IMPORT +../Body/f_shdw_i.htm +SHARED-INITIALIZE +../Body/f_shared.htm +SHIFTF +../Body/m_shiftf.htm +SHORT-FLOAT +../Body/t_short_.htm +SHORT-FLOAT-EPSILON +../Body/v_short_.htm +SHORT-FLOAT-NEGATIVE-EPSILON +../Body/v_short_.htm +SHORT-SITE-NAME +../Body/f_short_.htm +SIGNAL +../Body/f_signal.htm +SIGNED-BYTE +../Body/t_sgn_by.htm +SIGNUM +../Body/f_signum.htm +SIMPLE-ARRAY +../Body/t_smp_ar.htm +SIMPLE-BASE-STRING +../Body/t_smp_ba.htm +SIMPLE-BIT-VECTOR +../Body/t_smp_bt.htm +SIMPLE-BIT-VECTOR-P +../Body/f_smp_bt.htm +SIMPLE-CONDITION +../Body/e_smp_cn.htm +SIMPLE-CONDITION-FORMAT-ARGUMENTS +../Body/f_smp_cn.htm +SIMPLE-CONDITION-FORMAT-CONTROL +../Body/f_smp_cn.htm +SIMPLE-ERROR +../Body/e_smp_er.htm +SIMPLE-STRING +../Body/t_smp_st.htm +SIMPLE-STRING-P +../Body/f_smp_st.htm +SIMPLE-TYPE-ERROR +../Body/e_smp_tp.htm +SIMPLE-VECTOR +../Body/t_smp_ve.htm +SIMPLE-VECTOR-P +../Body/f_smp_ve.htm +SIMPLE-WARNING +../Body/e_smp_wa.htm +SIN +../Body/f_sin_c.htm +SINGLE-FLOAT +../Body/t_short_.htm +SINGLE-FLOAT-EPSILON +../Body/v_short_.htm +SINGLE-FLOAT-NEGATIVE-EPSILON +../Body/v_short_.htm +SINH +../Body/f_sinh_.htm +SIXTH +../Body/f_firstc.htm +SLEEP +../Body/f_sleep.htm +SLOT-BOUNDP +../Body/f_slt_bo.htm +SLOT-EXISTS-P +../Body/f_slt_ex.htm +SLOT-MAKUNBOUND +../Body/f_slt_ma.htm +SLOT-MISSING +../Body/f_slt_mi.htm +SLOT-UNBOUND +../Body/f_slt_un.htm +SLOT-VALUE +../Body/f_slt_va.htm +SOFTWARE-TYPE +../Body/f_sw_tpc.htm +SOFTWARE-VERSION +../Body/f_sw_tpc.htm +SOME +../Body/f_everyc.htm +SORT +../Body/f_sort_.htm +SPACE +../Body/d_optimi.htm +SPECIAL +../Body/d_specia.htm +SPECIAL-OPERATOR-P +../Body/f_specia.htm +SPEED +../Body/d_optimi.htm +SQRT +../Body/f_sqrt_.htm +STABLE-SORT +../Body/f_sort_.htm +STANDARD +../Body/07_ffb.htm +STANDARD-CHAR +../Body/t_std_ch.htm +STANDARD-CHAR-P +../Body/f_std_ch.htm +STANDARD-CLASS +../Body/t_std_cl.htm +STANDARD-GENERIC-FUNCTION +../Body/t_std_ge.htm +STANDARD-METHOD +../Body/t_std_me.htm +STANDARD-OBJECT +../Body/t_std_ob.htm +STEP +../Body/m_step.htm +STORAGE-CONDITION +../Body/e_storag.htm +STORE-VALUE +../Body/a_store_.htm +STREAM +../Body/t_stream.htm +STREAM-ELEMENT-TYPE +../Body/f_stm_el.htm +STREAM-ERROR +../Body/e_stm_er.htm +STREAM-ERROR-STREAM +../Body/f_stm_er.htm +STREAM-EXTERNAL-FORMAT +../Body/f_stm_ex.htm +STREAMP +../Body/f_stmp.htm +STRING +../Body/a_string.htm +STRING-CAPITALIZE +../Body/f_stg_up.htm +STRING-DOWNCASE +../Body/f_stg_up.htm +STRING-EQUAL +../Body/f_stgeq_.htm +STRING-GREATERP +../Body/f_stgeq_.htm +STRING-LEFT-TRIM +../Body/f_stg_tr.htm +STRING-LESSP +../Body/f_stgeq_.htm +STRING-NOT-EQUAL +../Body/f_stgeq_.htm +STRING-NOT-GREATERP +../Body/f_stgeq_.htm +STRING-NOT-LESSP +../Body/f_stgeq_.htm +STRING-RIGHT-TRIM +../Body/f_stg_tr.htm +STRING-STREAM +../Body/t_stg_st.htm +STRING-TRIM +../Body/f_stg_tr.htm +STRING-UPCASE +../Body/f_stg_up.htm +STRING/= +../Body/f_stgeq_.htm +STRING< +../Body/f_stgeq_.htm +STRING<= +../Body/f_stgeq_.htm +STRING= +../Body/f_stgeq_.htm +STRING> +../Body/f_stgeq_.htm +STRING>= +../Body/f_stgeq_.htm +STRINGP +../Body/f_stgp.htm +STRUCTURE +../Body/f_docume.htm +STRUCTURE-CLASS +../Body/t_stu_cl.htm +STRUCTURE-OBJECT +../Body/t_stu_ob.htm +STYLE-WARNING +../Body/e_style_.htm +SUBLIS +../Body/f_sublis.htm +SUBSEQ +../Body/f_subseq.htm +SUBSETP +../Body/f_subset.htm +SUBST +../Body/f_substc.htm +SUBST-IF +../Body/f_substc.htm +SUBST-IF-NOT +../Body/f_substc.htm +SUBSTITUTE +../Body/f_sbs_s.htm +SUBSTITUTE-IF +../Body/f_sbs_s.htm +SUBSTITUTE-IF-NOT +../Body/f_sbs_s.htm +SUBTYPEP +../Body/f_subtpp.htm +SVREF +../Body/f_svref.htm +SXHASH +../Body/f_sxhash.htm +SYMBOL +../Body/t_symbol.htm +SYMBOL-FUNCTION +../Body/f_symb_1.htm +SYMBOL-MACROLET +../Body/s_symbol.htm +SYMBOL-NAME +../Body/f_symb_2.htm +SYMBOL-PACKAGE +../Body/f_symb_3.htm +SYMBOL-PLIST +../Body/f_symb_4.htm +SYMBOL-VALUE +../Body/f_symb_5.htm +SYMBOLP +../Body/f_symbol.htm +SYNONYM-STREAM +../Body/t_syn_st.htm +SYNONYM-STREAM-SYMBOL +../Body/f_syn_st.htm +T +../Body/a_t.htm +TAGBODY +../Body/s_tagbod.htm +TAILP +../Body/f_ldiffc.htm +TAN +../Body/f_sin_c.htm +TANH +../Body/f_sinh_.htm +TENTH +../Body/f_firstc.htm +TERPRI +../Body/f_terpri.htm +THE +../Body/s_the.htm +THIRD +../Body/f_firstc.htm +THROW +../Body/s_throw.htm +TIME +../Body/m_time.htm +TRACE +../Body/m_tracec.htm +TRANSLATE-LOGICAL-PATHNAME +../Body/f_tr_log.htm +TRANSLATE-PATHNAME +../Body/f_tr_pn.htm +TREE-EQUAL +../Body/f_tree_e.htm +TRUENAME +../Body/f_tn.htm +TRUNCATE +../Body/f_floorc.htm +TWO-WAY-STREAM +../Body/t_two_wa.htm +TWO-WAY-STREAM-INPUT-STREAM +../Body/f_two_wa.htm +TWO-WAY-STREAM-OUTPUT-STREAM +../Body/f_two_wa.htm +TYPE +../Body/a_type.htm +TYPE-ERROR +../Body/e_tp_err.htm +TYPE-ERROR-DATUM +../Body/f_tp_err.htm +TYPE-ERROR-EXPECTED-TYPE +../Body/f_tp_err.htm +TYPE-OF +../Body/f_tp_of.htm +TYPECASE +../Body/m_tpcase.htm +TYPEP +../Body/f_typep.htm +UNBOUND-SLOT +../Body/e_unboun.htm +UNBOUND-SLOT-INSTANCE +../Body/f_unboun.htm +UNBOUND-VARIABLE +../Body/e_unbo_1.htm +UNDEFINED-FUNCTION +../Body/e_undefi.htm +UNEXPORT +../Body/f_unexpo.htm +UNINTERN +../Body/f_uninte.htm +UNION +../Body/f_unionc.htm +UNLESS +../Body/m_when_.htm +UNREAD-CHAR +../Body/f_unrd_c.htm +UNSIGNED-BYTE +../Body/t_unsgn_.htm +UNTRACE +../Body/m_tracec.htm +UNUSE-PACKAGE +../Body/f_unuse_.htm +UNWIND-PROTECT +../Body/s_unwind.htm +UPDATE-INSTANCE-FOR-DIFFERENT-CLASS +../Body/f_update.htm +UPDATE-INSTANCE-FOR-REDEFINED-CLASS +../Body/f_upda_1.htm +UPGRADED-ARRAY-ELEMENT-TYPE +../Body/f_upgr_1.htm +UPGRADED-COMPLEX-PART-TYPE +../Body/f_upgrad.htm +UPPER-CASE-P +../Body/f_upper_.htm +USE-PACKAGE +../Body/f_use_pk.htm +USE-VALUE +../Body/a_use_va.htm +USER-HOMEDIR-PATHNAME +../Body/f_user_h.htm +VALUES +../Body/a_values.htm +VALUES-LIST +../Body/f_vals_l.htm +VARIABLE +../Body/f_docume.htm +VECTOR +../Body/a_vector.htm +VECTOR-POP +../Body/f_vec_po.htm +VECTOR-PUSH +../Body/f_vec_ps.htm +VECTOR-PUSH-EXTEND +../Body/f_vec_ps.htm +VECTORP +../Body/f_vecp.htm +WARN +../Body/f_warn.htm +WARNING +../Body/e_warnin.htm +WHEN +../Body/m_when_.htm +WILD-PATHNAME-P +../Body/f_wild_p.htm +WITH-ACCESSORS +../Body/m_w_acce.htm +WITH-COMPILATION-UNIT +../Body/m_w_comp.htm +WITH-CONDITION-RESTARTS +../Body/m_w_cnd_.htm +WITH-HASH-TABLE-ITERATOR +../Body/m_w_hash.htm +WITH-INPUT-FROM-STRING +../Body/m_w_in_f.htm +WITH-OPEN-FILE +../Body/m_w_open.htm +WITH-OPEN-STREAM +../Body/m_w_op_1.htm +WITH-OUTPUT-TO-STRING +../Body/m_w_out_.htm +WITH-PACKAGE-ITERATOR +../Body/m_w_pkg_.htm +WITH-SIMPLE-RESTART +../Body/m_w_smp_.htm +WITH-SLOTS +../Body/m_w_slts.htm +WITH-STANDARD-IO-SYNTAX +../Body/m_w_std_.htm +WRITE +../Body/f_wr_pr.htm +WRITE-BYTE +../Body/f_wr_by.htm +WRITE-CHAR +../Body/f_wr_cha.htm +WRITE-LINE +../Body/f_wr_stg.htm +WRITE-SEQUENCE +../Body/f_wr_seq.htm +WRITE-STRING +../Body/f_wr_stg.htm +WRITE-TO-STRING +../Body/f_wr_to_.htm +Y-OR-N-P +../Body/f_y_or_n.htm +YES-OR-NO-P +../Body/f_y_or_n.htm +ZEROP +../Body/f_zerop.htm diff --git a/Lisp/moxie/Mop_Sym.txt b/Lisp/moxie/Mop_Sym.txt new file mode 100644 index 0000000..1647166 --- /dev/null +++ b/Lisp/moxie/Mop_Sym.txt @@ -0,0 +1,128 @@ +SPEC2 +dictionary.html#spec2 +ADD-DEPENDENT +dictionary.html#add-dependent +ADD-DIRECT-METHOD +dictionary.html#add-direct-method +ADD-DIRECT-SUBCLASS +dictionary.html#add-direct-subclass +ADD-METHOD +dictionary.html#add-method +ALLOCATE-INSTANCE +dictionary.html#allocate-instance +CLASS- +dictionary.html#class- +COMPUTE-APPLICABLE-METHODS +dictionary.html#compute-applicable-methods +COMPUTE-APPLICABLE-METHODS-USING-CLASSES +dictionary.html#compute-applicable-methods-using-classes +COMPUTE-CLASS-PRECEDENCE-LIST +dictionary.html#compute-class-precedence-list +COMPUTE-DEFAULT-INITARGS +dictionary.html#compute-default-initargs +COMPUTE-DISCRIMINATING-FUNCTION +dictionary.html#compute-discriminating-function +COMPUTE-EFFECTIVE-METHOD +dictionary.html#compute-effective-method +COMPUTE-EFFECTIVE-SLOT-DEFINITION +dictionary.html#compute-effective-slot-definition +COMPUTE-SLOTS +dictionary.html#compute-slots +DIRECT-SLOT-DEFINITION-CLASS +dictionary.html#direct-slot-definition-class +EFFECTIVE-SLOT-DEFINITION-CLASS +dictionary.html#effective-slot-definition-class +ENSURE-CLASS +dictionary.html#ensure-class +ENSURE-CLASS-USING-CLASS +dictionary.html#ensure-class-using-class +ENSURE-GENERIC-FUNCTION +dictionary.html#ensure-generic-function +ENSURE-GENERIC-FUNCTION-USING-CLASS +dictionary.html#ensure-generic-function-using-class +EQL-SPECIALIZER-OBJECT +dictionary.html#eql-specializer-object +EXTRACT-LAMBDA-LIST +dictionary.html#extract-lambda-list +EXTRACT-SPECIALIZER-NAMES +dictionary.html#extract-specializer-names +FINALIZE-INHERITANCE +dictionary.html#finalize-inheritance +FIND-METHOD-COMBINATION +dictionary.html#find-method-combination +FUNCALLABLE-STANDARD-INSTANCE-ACCESS +dictionary.html#funcallable-standard-instance-access +GENERIC-FUNCTION- +dictionary.html#generic-function- +</A> +dictionary.html#</a> +CLASS-MO-INITARGS +dictionary.html#class-mo-initargs +</A> +dictionary.html#</a> +GF-MO-INITARGS +dictionary.html#gf-mo-initargs +INITIALIZATION +dictionary.html#Initialization +METHOD-MO-INITARGS +dictionary.html#method-mo-initargs +INITIALIZATION +dictionary.html#Initialization +SLOTD-MO-INITARGS +dictionary.html#slotd-mo-initargs +INTERN-EQL-SPECIALIZER +dictionary.html#intern-eql-specializer +MAKE-INSTANCE +dictionary.html#make-instance +MAKE-METHOD-LAMBDA +dictionary.html#make-method-lambda +MAP-DEPENDENTS +dictionary.html#map-dependents +METHOD- +dictionary.html#method- +CLASS-MO-READERS +dictionary.html#class-mo-readers +GF-MO-READERS +dictionary.html#gf-mo-readers +METHOD-MO-READERS +dictionary.html#method-mo-readers +SLOTD-MO-READERS +dictionary.html#slotd-mo-readers +READER-METHOD-CLASS +dictionary.html#reader-method-class +REMOVE-DEPENDENT +dictionary.html#remove-dependent +REMOVE-DIRECT-METHOD +dictionary.html#remove-direct-method +REMOVE-DIRECT-SUBCLASS +dictionary.html#remove-direct-subclass +REMOVE-METHOD +dictionary.html#remove-method +SET-FUNCALLABLE-INSTANCE-FUNCTION +dictionary.html#set-funcallable-instance-function +(SETF CLASS-NAME) +dictionary.html#(setf class-name) +(SETF GENERIC-FUNCTION-NAME) +dictionary.html#(setf generic-function-name) +(SETF SLOT-VALUE-USING-CLASS) +dictionary.html#(setf slot-value-using-class) +SLOT-BOUNDP-USING-CLASS +dictionary.html#slot-boundp-using-class +SLOT-DEFINITION- +dictionary.html#slot-definition- +SLOT-MAKUNBOUND-USING-CLASS +dictionary.html#slot-makunbound-using-class +SLOT-VALUE-USING-CLASS +dictionary.html#slot-value-using-class +SPECIALIZER-DIRECT-GENERIC-FUNCTIONS +dictionary.html#specializer-direct-generic-functions +SPECIALIZER-DIRECT-METHODS +dictionary.html#specializer-direct-methods +STANDARD-INSTANCE-ACCESS +dictionary.html#standard-instance-access +UPDATE-DEPENDENT +dictionary.html#update-dependent +VALIDATE-SUPERCLASS +dictionary.html#validate-superclass +WRITER-METHOD-CLASS +dictionary.html#writer-method-class diff --git a/Lisp/moxie/clhs-lookup.lisp b/Lisp/moxie/clhs-lookup.lisp new file mode 100644 index 0000000..02a3a32 --- /dev/null +++ b/Lisp/moxie/clhs-lookup.lisp @@ -0,0 +1,148 @@ +(defpackage clhs-lookup + (:use :common-lisp) + (:export :symbol-lookup + :populate-table + :spec-lookup)) +(in-package :clhs-lookup) + +(defparameter *hyperspec-pathname* (translate-logical-pathname "MOXIE:RES;")) + +(defparameter *hyperspec-map-file* (merge-pathnames "Map_Sym.txt" *hyperspec-pathname*)) + +(defparameter *hyperspec-root* "http://www.lispworks.com/reference/HyperSpec/") + +;;; AMOP. +(defparameter *mop-map-file* (merge-pathnames "Mop_Sym.txt" *hyperspec-pathname*)) + +(defparameter *mop-root* "http://www.alu.org/mop/") + +(defvar *symbol-table* (make-hash-table :test 'equal)) + +(defvar *section-table* (make-hash-table :test 'equal)) + +(defvar *format-table* (make-hash-table :test 'equal)) + +(defvar *populated-p* nil) + +(defun add-clhs-section-to-table (&rest numbers) + (let ((key (format nil "~{~d~^.~}" numbers)) + (target (concatenate 'string *hyperspec-root* (format nil "Body/~2,'0d_~(~{~36r~}~).htm" (car numbers) (mapcar #'(lambda (x) (+ x 9)) (cdr numbers)))))) + (setf (gethash key *section-table*) target))) + +(defun valid-target (&rest numbers) + (probe-file (format nil "Body/~2,'0d_~(~{~36r~}~).htm" (car numbers) (mapcar #'(lambda (x) (+ x 9)) (cdr numbers))))) + +(defvar *last-warn-time* 0) + +(defun populate-table () + (unless *populated-p* + ;; Hyperspec + (with-open-file (s *hyperspec-map-file* :if-does-not-exist nil) + ;; populate the table with the symbols from the Map file + ;; this bit is easy and portable. + (unless s + (when (> (- (get-universal-time) *last-warn-time*) 10) + (format *trace-output* "Warning: could not find hyperspec map file. Adjust the path at the top of clhs-lookup.lisp to get links to the HyperSpec.~%") + (setf *last-warn-time* (get-universal-time))) + (return-from populate-table nil)) + (do ((symbol-name (read-line s nil s) (read-line s nil s)) + (url (read-line s nil s) (read-line s nil s))) + ((eq url s) 'done) + (setf (gethash symbol-name *symbol-table*) (concatenate 'string *hyperspec-root* (subseq url 3)))) + ;; add in section references. + (let ((*default-pathname-defaults* *hyperspec-pathname*)) + ;; Yuk. I know. Fixes welcome. + (loop for section from 0 to 27 + do (add-clhs-section-to-table section) + do (loop named s for s1 from 1 to 26 + unless (valid-target section s1) + do (return-from s nil) + do (add-clhs-section-to-table section s1) + do (loop named ss for s2 from 1 to 26 + unless (valid-target section s1 s2) + do (return-from ss nil) + do (add-clhs-section-to-table section s1 s2) + do (loop named sss for s3 from 1 to 26 + unless (valid-target section s1 s2 s3) + do (return-from sss nil) + do (add-clhs-section-to-table section s1 s2 s3) + do (loop named ssss for s4 from 1 to 26 + unless (valid-target section s1 s2 s3 s4) + do (return-from ssss nil) + do (add-clhs-section-to-table section s1 s2 s3 s4) + do (loop named sssss for s5 from 1 to 26 + unless (valid-target section s1 s2 s3 s4 s5) + do (return-from sssss nil) + do (add-clhs-section-to-table section s1 s2 s3 s4 s5)))))))) + ;; format directives + (loop for code from 32 to 127 + do (setf (gethash (format nil "~~~A" (code-char code)) *format-table*) + (concatenate 'string + *hyperspec-root* + (case (code-char code) + ((#\c #\C) "Body/22_caa.htm") + ((#\%) "Body/22_cab.htm") + ((#\&) "Body/22_cac.htm") + ((#\|) "Body/22_cad.htm") + ((#\~) "Body/22_cae.htm") + ((#\r #\R) "Body/22_cba.htm") + ((#\d #\D) "Body/22_cbb.htm") + ((#\b #\B) "Body/22_cbc.htm") + ((#\o #\O) "Body/22_cbd.htm") + ((#\x #\X) "Body/22_cbe.htm") + ((#\f #\F) "Body/22_cca.htm") + ((#\e #\E) "Body/22_ccb.htm") + ((#\g #\G) "Body/22_ccc.htm") + ((#\$) "Body/22_ccd.htm") + ((#\a #\A) "Body/22_cda.htm") + ((#\s #\S) "Body/22_cdb.htm") + ((#\w #\W) "Body/22_cdc.htm") + ((#\_) "Body/22_cea.htm") + ;((#\<) "Body/22_ceb.htm") + ((#\i #\I) "Body/22_cec.htm") + ((#\/) "Body/22_ced.htm") + ((#\t #\T) "Body/22_cfa.htm") + ;; FIXME + ((#\<) "Body/22_cfb.htm") + ((#\>) "Body/22_cfc.htm") + ((#\*) "Body/22_cga.htm") + ((#\[) "Body/22_cgb.htm") + ((#\]) "Body/22_cgc.htm") + ((#\{) "Body/22_cgd.htm") + ((#\}) "Body/22_cge.htm") + ((#\?) "Body/22_cgf.htm") + ((#\() "Body/22_cha.htm") + ((#\)) "Body/22_chb.htm") + ((#\p #\P) "Body/22_chc.htm") + ((#\;) "Body/22_cia.htm") + ((#\^) "Body/22_cib.htm") + ((#\Newline) "Body/22_cic.htm") + (t "Body/22_c.htm"))))) + ;; glossary. + ) + ;; MOP + (with-open-file (s *mop-map-file* :if-does-not-exist nil) + (when s + (do ((symbol-name (read-line s nil s) (read-line s nil s)) + (url (read-line s nil s) (read-line s nil s))) + ((eq url s) 'done) + (setf (gethash (concatenate 'string "MOP:" symbol-name) *symbol-table*) (concatenate 'string *mop-root* url))))) + (setf *populated-p* t))) + +(defun spec-lookup (term &key (type :all)) + (unless *populated-p* + (populate-table)) + (ecase type + (:all + (or (gethash term *symbol-table*) + (gethash term *section-table*) + (gethash term *format-table*))) + (:symbol + (gethash term *symbol-table*)) + (:section + (gethash term *section-table*)) + (:format + (gethash term *format-table*)))) + +(defun symbol-lookup (term) + (spec-lookup term :type :symbol)) diff --git a/Lisp/moxie/compat/compat-clisp.lib b/Lisp/moxie/compat/compat-clisp.lib new file mode 100644 index 0000000..6d4ac37 --- /dev/null +++ b/Lisp/moxie/compat/compat-clisp.lib @@ -0,0 +1,17 @@ +#0Y UTF-8 +(COMMON-LISP::SETQ COMMON-LISP::*PACKAGE* (SYSTEM::%FIND-PACKAGE "MOXIE")) +(SYSTEM::C-DEFUN 'MOXIE::MAKE-RESULT-STREAM + (SYSTEM::LAMBDA-LIST-TO-SIGNATURE 'COMMON-LISP::NIL)) +(SYSTEM::C-DEFUN 'MOXIE::COERCE-INET-ADDRESS-DESIGNATOR + (SYSTEM::LAMBDA-LIST-TO-SIGNATURE '(MOXIE::HOST))) +(SYSTEM::C-DEFUN 'MOXIE::OPEN-CONNECTION + (SYSTEM::LAMBDA-LIST-TO-SIGNATURE + '(MOXIE::HOST MOXIE::PORT COMMON-LISP::&KEY (MOXIE::BUFFERING :FULL)))) +(SYSTEM::C-DEFUN 'MOXIE::CLOSE-CONNECTION + (SYSTEM::LAMBDA-LIST-TO-SIGNATURE '(COMMON-LISP::STREAM))) +(SYSTEM::C-DEFUN 'MOXIE::ADD-INPUT-HANDLER + (SYSTEM::LAMBDA-LIST-TO-SIGNATURE '(COMMON-LISP::STREAM MOXIE::HANDLER))) +(SYSTEM::C-DEFUN 'MOXIE::REMOVE-INPUT-HANDLER + (SYSTEM::LAMBDA-LIST-TO-SIGNATURE '(MOXIE::HANDLER))) +(SYSTEM::C-DEFUN 'MOXIE::SAVE-LISP-AND-DIE + (SYSTEM::LAMBDA-LIST-TO-SIGNATURE '(MOXIE::PATH))) diff --git a/Lisp/moxie/compat/compat-clisp.lisp b/Lisp/moxie/compat/compat-clisp.lisp new file mode 100644 index 0000000..160d193 --- /dev/null +++ b/Lisp/moxie/compat/compat-clisp.lisp @@ -0,0 +1,24 @@ +;;; -*- Lisp -*- +;; $Id: compat-clisp.lisp 40 2006-01-02 03:35:07Z bjc $ +(in-package :moxie) + +(defun make-result-stream () + (ext:make-stream 3 :direction :output)) + +(defun coerce-inet-address-designator (host) + "Coerce HOST into an addess vector.") + +(defun open-connection (host port &key (buffering :full)) + "Opens a connection to HOST:PORT, returning a STREAM if successful, NIL otherwise.") + +(defun close-connection (stream) + "Closes STREAM.") + +(defun add-input-handler (stream handler) + "Adds HANDLER to the input handler list on SOCKET.") + +(defun remove-input-handler (handler)) + +(defun save-lisp-and-die (path) + (ext:saveinitmem path) + (ext:quit)) diff --git a/Lisp/moxie/compat/compat-openmcl.lisp b/Lisp/moxie/compat/compat-openmcl.lisp new file mode 100644 index 0000000..6bafbd7 --- /dev/null +++ b/Lisp/moxie/compat/compat-openmcl.lisp @@ -0,0 +1,59 @@ +;;; -*- Lisp -*- +;; $Id: compat-openmcl.lisp 36 2006-01-01 20:47:40Z bjc $ +(in-package :moxie) + +(defvar *stream-to-process* (make-hash-table)) +(defvar *stream-to-handler* (make-hash-table)) + +(defmacro with-thread (thread &body body) + `(ccl:process-interrupt ,thread + (lambda () + ,@body))) + +(defun make-result-stream () + (ccl::make-fd-stream 3 :direction :output)) + +(defun coerce-inet-address-designator (host) + "Coerce HOST into an addess vector." + (or (and (integerp host) host) + (ccl:dotted-to-ipaddr host :errorp nil) + (ignore-errors (ccl:lookup-hostname host)))) + +(defun open-connection-thread (parent stream) + (ccl:socket-connect stream) + (loop + (ccl:process-input-wait (ccl:stream-device stream :input)) + (let ((handler (gethash stream *stream-to-handler*))) + (with-thread parent + (funcall handler stream))))) + +(defun open-connection (host port &rest args) + "Opens a connection to HOST:PORT, returning a STREAM if successful, NIL otherwise." + (declare (ignore args)) + (let ((s (ccl:make-socket :address-family :internet :type :stream :connect :active + :remote-host (coerce-inet-address-designator host) + :remote-port port))) + (setf (gethash s *stream-to-process*) + (ccl:process-run-function (format nil "Connection to ~A:~A" host port) + #'open-connection-thread + ccl:*current-process* s)) + s)) + +(defun close-connection (stream) + "Closes STREAM." + (ignore-errors + (close stream) + (ccl:process-kill (gethash stream *stream-to-process*)) + (remove-input-handler stream) + (remhash stream *stream-to-process*))) + +(defun add-input-handler (stream handler) + "Adds HANDLER to the input handler list on STREAM." + (setf (gethash stream *stream-to-handler*) handler)) + +(defun remove-input-handler (stream) + "Removes all handlers from STREAM." + (remhash stream *stream-to-handler*)) + +(defun save-lisp-and-die (path) + (ccl:save-application path))
\ No newline at end of file diff --git a/Lisp/moxie/compat/compat-sbcl.fasl b/Lisp/moxie/compat/compat-sbcl.fasl Binary files differnew file mode 100644 index 0000000..d1e2b41 --- /dev/null +++ b/Lisp/moxie/compat/compat-sbcl.fasl diff --git a/Lisp/moxie/compat/compat-sbcl.lisp b/Lisp/moxie/compat/compat-sbcl.lisp new file mode 100644 index 0000000..bb43bc8 --- /dev/null +++ b/Lisp/moxie/compat/compat-sbcl.lisp @@ -0,0 +1,49 @@ +;;; -*- Lisp -*- +;; $Id: compat-sbcl.lisp 36 2006-01-01 20:47:40Z bjc $ +(in-package :moxie) + +(defvar *stream-to-handler* (make-hash-table)) +(defvar *stream-to-socket* (make-hash-table)) + +(defun make-result-stream () + (sb-sys:make-fd-stream 3 :output t)) + +(defun coerce-inet-address-designator (host) + "Coerce HOST into an addess vector." + (cond ((typep host '(vector (unsigned-byte 8) 4)) host) + ((some #'alpha-char-p host) (sb-bsd-sockets:host-ent-address + (sb-bsd-sockets:get-host-by-name host))) + (t (sb-bsd-sockets:make-inet-address host)))) + +(defun open-connection (host port &key (buffering :full)) + "Opens a connection to HOST:PORT, returning a STREAM if successful, NIL otherwise." + (let ((socket (make-instance 'sb-bsd-sockets:inet-socket :type :stream + :protocol :tcp))) + (sb-bsd-sockets:socket-connect socket (coerce-inet-address-designator host) port) + (let ((stream (sb-bsd-sockets:socket-make-stream socket + :input t :output t :buffering buffering))) + (setf (gethash stream *stream-to-socket*) socket) + stream))) + +(defun close-connection (stream) + "Closes STREAM." + (ignore-errors + (remove-input-handler stream) + (remhash stream *stream-to-socket*) + (close stream))) + +(defun add-input-handler (stream handler) + "Adds HANDLER to the input handler list on SOCKET." + (setf (gethash stream *stream-to-handler*) + (sb-sys:add-fd-handler (sb-bsd-sockets:socket-file-descriptor (gethash stream *stream-to-socket*)) + :input + (lambda (fd) + (declare (ignore fd)) + (funcall handler stream))))) + +(defun remove-input-handler (stream) + (awhen (gethash stream *stream-to-handler*) + (sb-sys:remove-fd-handler it))) + +(defun save-lisp-and-die (path) + (sb-ext:save-lisp-and-die path))
\ No newline at end of file diff --git a/Lisp/moxie/default.fasl b/Lisp/moxie/default.fasl Binary files differnew file mode 100644 index 0000000..3f88e09 --- /dev/null +++ b/Lisp/moxie/default.fasl diff --git a/Lisp/moxie/default.lisp b/Lisp/moxie/default.lisp new file mode 100644 index 0000000..a408d68 --- /dev/null +++ b/Lisp/moxie/default.lisp @@ -0,0 +1,63 @@ +;;; -*- Lisp -*- +;; $Id: world.lisp 20 2005-12-27 15:21:23Z bjc $ +;; +;; Functions that should eventually be moved to the real plug in +;; support methodology (i.e., with nib files). +;; +(in-package :moxie) + +(defun notify-front-end-load (&rest args) + (declare (ignore args)) + (send-event-to-world *world* :change-settings (world-vars *world*))) + +(defun notify-front-end-close (&rest args) + (declare (ignore args)) + (send-event-to-world *world* :world-closed)) + +(defun notify-front-end-connect (&rest args) + (declare (ignore args)) + (set-status-buffer "Connected") + (send-event-to-world *world* :world-connected)) + +(defun notify-front-end-disconnect (&rest args) + (declare (ignore args)) + (set-status-buffer "Disconnected") + (send-event-to-world *world* :world-disconnected)) + +(defun notify-front-end-data (line) + (print-to-world *world* line)) + +(defun notify-back-end-data (line) + (print-to-world *world* (format nil "-> ~A~%" line))) + +(defun notify-back-end-settings (alist) + (when (world-save-path *world*) + (format t "DEBUG: saving new settings: ~S~%" alist) + (save-world-state *world*))) + +(add-hook 'notify-front-end-load :world-loaded-hook) +(add-hook 'notify-front-end-close :world-closed-hook) +(add-hook 'notify-front-end-connect :world-connected-hook) +(add-hook 'notify-front-end-disconnect :world-disconnected-hook) +(add-hook 'notify-front-end-data :output-from-server-hook) +(add-hook 'notify-back-end-data :input-from-client-hook) +(add-hook 'notify-back-end-settings :setting-changed-hook) + +(defun show-by-filter (key val &optional (test #'eql)) + (map-by-filter (lambda (world) + (format t "Matches ~S = ~S: ~S~%" key val world)) + key val test)) + +(defun map-by-filter (fn key val &optional (test #'eql)) + (map-worlds (lambda (world) + (when (funcall test (world-var key world) val) + (funcall fn world))))) + +(defun do-auto-connect (&rest args) + (declare (ignore args)) + (setf *tmp* *world*) + (when (and (not (world-connected *world*)) (world-var :connect-on-open)) + (format t "DEBUG: auto-connecting to ~A:~A~%" (world-var :hostname) (world-var :port)) + (world-connect))) + +(add-hook 'do-auto-connect :world-loaded-hook)
\ No newline at end of file diff --git a/Lisp/moxie/events.fasl b/Lisp/moxie/events.fasl Binary files differnew file mode 100644 index 0000000..385f796 --- /dev/null +++ b/Lisp/moxie/events.fasl diff --git a/Lisp/moxie/events.lisp b/Lisp/moxie/events.lisp new file mode 100644 index 0000000..88afb71 --- /dev/null +++ b/Lisp/moxie/events.lisp @@ -0,0 +1,100 @@ +(in-package :moxie) + +(defgeneric moxie-event-handler (event &rest args) + (:documentation "Handle EVENT (w/ ARGS).")) + +(defmethod moxie-event-handler ((event (eql :world-event)) &rest args) + (apply #'world-event args)) + +(defmethod moxie-event-handler ((event (eql :eval)) &rest args) + (do* ((f args (cdr f)) + (form (car f) (car f))) + ((null f)) + (case form + (:r (let ((restarts (compute-restarts)) + (num (cadr f))) + (if (and (integerp num) + (> num 0) (<= num (length restarts))) + (progn + (setf f (cdr f)) + (invoke-restart (elt restarts (1- num)))) + (print-restarts restarts)))) + ((:? :h :help) (format t "~A~%" *repl-help*)) + (t (let (values) + (setq - form) + (setq values (multiple-value-list (eval -))) + (setq /// // // / / values *** ** ** * * (car /)) + (send-command :repl-result `(:values ,@values)))))) + (send-command :repl-result `(:prompt ,(repl-prompt)))) + +(defmethod world-event-handler ((event (eql :close-world)) &rest args) + (declare (ignore args)) + (close-world)) + +(defmethod world-event-handler ((event (eql :connect-world)) &rest args) + (declare (ignore args)) + (world-connect)) + +(defmethod world-event-handler ((event (eql :disconnect-world)) &rest args) + (declare (ignore args)) + (world-disconnect)) + +(defmethod world-event-handler ((event (eql :load-world)) &rest args) + (format t "world-event-handler :load-world ~S~%" args) + (apply #'load-world-state *world* args)) + +(defmethod world-event-handler ((event (eql :save-world)) &rest args) + (apply #'save-world-state *world* args)) + +(defmethod world-event-handler ((event (eql :setting-changed)) &rest args) + (let* ((form (car args)) + (key (car form)) + (val (cadr form)) + (old-val (world-var key))) + (unless (eql old-val val) + (format t "DEBUG: changing setting ~S: ~S -> ~S.~%" key old-val val) + (setf (world-var key) val) + (format t "DEBUG: running hook.~%") + (run-hook :setting-changed-hook (list key val old-val)) + (format t "DEBUG: hook finished.~%")))) + +(defmethod world-event-handler ((event (eql :input-from-client-hook)) &rest args) + (send-to-mux *world* (or (run-hook event (car args)) (car args)))) + +(defmethod load-world-state ((world world) &key path &allow-other-keys) + (format t "load-world-state ~S ~S~%" world path) + (with-open-file (s (or path (world-save-path world))) + (awhen (aand (read s) (parse-world-version-1 it)) + (setf (world-vars world) it) + (setf (world-save-path world) path) + (let ((*world* world)) + (run-hook :world-loaded-hook))))) + +(defmethod save-world-state ((world world) &key path as-copy &allow-other-keys) + (with-open-file (s (or path (world-save-path world)) + :direction :output :if-exists :supersede + :if-does-not-exist :create) + (prin1 (write-world-version-1) s)) + (unless as-copy + (setf (world-save-path world) path)) + (let ((*world* world)) + (run-hook :world-saved-hook))) + +(defun parse-world-version-1 (form) + "Parses a world definition in the form '(:KEY value), returning an ALIST." + (when (evenp (length form)) + (labels ((keyvalue-to-alist (form &optional (accumulator nil)) + (if (null form) + accumulator + (keyvalue-to-alist (cddr form) + (cons (cons (car form) (cadr form)) accumulator))))) + (keyvalue-to-alist form)))) + +(defun write-world-version-1 (&optional (world *world*)) + "Writes out a FORM of '(:KEY1 value1 :KEY2 value2) from WORLD." + (labels ((alist-to-keyvalue (form &optional (accumulator nil)) + (if (null form) + accumulator + (alist-to-keyvalue (cdr form) + (cons (caar form) (cons (cdar form) accumulator)))))) + (alist-to-keyvalue (world-vars world))))
\ No newline at end of file diff --git a/Lisp/moxie/hooks.lisp b/Lisp/moxie/hooks.lisp new file mode 100644 index 0000000..49714f6 --- /dev/null +++ b/Lisp/moxie/hooks.lisp @@ -0,0 +1,21 @@ +;;; -*- Lisp -*- +;; $Id: moxie.asd,v 1.1.1.1 2005/02/15 06:06:59 shmit Exp $ +#| +Hooks: + +;; Sent from world handlers +:world-opened-hook *world* +:world-closed-hook *world* +:input-from-client-hook line +:output-from-server-hook line + +;; This can probably just be a plugin, off :output-from-server-hook +:telnet-option-hook telnetCodes + +;; Controlled by the front end, ultimately. +:start-logging-hook +:stop-logging-hook + +;; XXX: IDK +:timer-hook +|#
\ No newline at end of file diff --git a/Lisp/moxie/moxie.asd b/Lisp/moxie/moxie.asd new file mode 100644 index 0000000..bda1706 --- /dev/null +++ b/Lisp/moxie/moxie.asd @@ -0,0 +1,34 @@ +;;; -*- Lisp -*- +;; $Id: moxie.asd 33 2006-01-01 06:41:36Z bjc $ +(defpackage moxie-system + (:use :cl :asdf)) +(in-package :moxie-system) + +(defsystem :moxie + :name "Moxie REPL Components." + :version "0.2" + :author "Brian Cully <shmit@kublai.com>" + :maintainer "Brian Cully <shmit@kublai.com>" + :licence "Public Domain" + :description "Moxie's Lisp programming interface." + + :depends-on (#+sbcl sb-bsd-sockets) + :components ((:file "package") + (:module "utils" + :components ((:file "bjc-utils")) + :depends-on ("package")) + (:module "compat" + :components ((:file #+sbcl "compat-sbcl" + #+clisp "compat-clisp" + #+openmcl "compat-openmcl" + #-(or sbcl clisp openmcl) (error "Compiler not supported."))) + :depends-on ("package")) + (:module "main" + :pathname "" + :components ((:file "moxie") + (:file "world" :depends-on ("moxie")) + (:file "events" :depends-on ("world")) + (:file "repl" :depends-on ("world")) + (:file "default" :depends-on ("moxie"))) + :depends-on ("package" "compat" "utils")))) +(pushnew :moxie *features*) diff --git a/Lisp/moxie/moxie.fasl b/Lisp/moxie/moxie.fasl Binary files differnew file mode 100644 index 0000000..70ee196 --- /dev/null +++ b/Lisp/moxie/moxie.fasl diff --git a/Lisp/moxie/moxie.lisp b/Lisp/moxie/moxie.lisp new file mode 100644 index 0000000..c18e630 --- /dev/null +++ b/Lisp/moxie/moxie.lisp @@ -0,0 +1,218 @@ +;;; The lisp bootstrapping code. +;; $Id: moxie.lisp 29 2005-12-31 22:59:17Z bjc $ + +(in-package :moxie) + +(defvar *hooks* (make-hash-table) + "The hooks. +See the functions add-hook and remove-hook.") + +(defun add-hook (sym mode) + "Adds the function SYM to the list MODE." + (setf (gethash mode *hooks*) + (let ((hooks (reverse (gethash mode *hooks*)))) + (pushnew sym hooks) + (nreverse hooks)))) + +(defun remove-hook (sym mode) + "Removes the function HOOK from the list MODE." + (setf (gethash mode *hooks*) (remove sym (gethash mode *hooks*)))) + +;; We should see how many args there are, and pass that amount in. Not just the return +;; value. But for now, this means hooks need at least one arg. +(defun run-hook (mode &optional arg) + "Runs all the hooks for MODE, in order of how they were attached." + (let ((result nil)) + (do ((hooks (gethash mode *hooks*) (cdr hooks))) + ((or (null hooks) (null (car hooks))) result) + (awhen (funcall (car hooks) (or result arg)) + (setf result it))))) + +(defvar *keywords* (make-hash-table :test #'equal)) + +(defun add-keyword (sym key) + "Adds /KEY as a keyword, calling SYM with the rest of the input string." + (setf (gethash (string-upcase key) *keywords*) sym)) + +(defun remove-keyword (key) + "Removes /KEY as a keyword." + (remhash (string-upcase key) *keywords*)) + +(defun get-keyword (string) + "Finds the keyword in STRING, if any." + (when (and (> (length string) 0) (eql #\/ (elt string 0))) + (let ((pos (or (position-if (lambda (c) + (or (eql #\Space c) + (eql #\Newline c) + (eql #\Tab c))) + string) + (length string)))) + (values + (string-upcase (subseq string 1 pos)) + (aif (and (< pos (length string)) + (position-if-not (lambda (c) + (or (eql #\Space c) + (eql #\Newline c) + (eql #\Tab c))) + string + :start pos)) + (subseq string it (length string)) + ""))))) + +(defun run-keyword-hook (string &rest keywords) + "Runs through the keyword database for the word at the beginning of STRING." + (multiple-value-bind (key rem) (get-keyword string) + (when key + (or (aand (gethash key *keywords*) (apply it rem keywords)) "")))) + +(add-hook 'run-keyword-hook :input-from-client-hook) + +;; Keystrokes are keywords that look like this: +;; keystroke := :[<modifier>-]*<keycode> +;; modifier := cmd|opt|ctrl|shift|numpad +;; keycode := <fkey>|character +;; fkey := f1 .. fn .. f35 +;; +;; So, CMD-NUMPAD-8 is: +;; :cmd-numpad-8 +;; +;; Okay, that won't work for the long term, because :cmd-shift-numpad-8 will be +;; evaluated differently than :shift-cmd-numpad-8. +(defvar *keystroke-macros* (make-hash-table) + "The keystroke macro to symbol dispatch table.") + +(defun add-keystroke-macro (sym keystroke) + "Adds KEYSTROKE as a keystroke-macro, calling SYM on dispatch." + (setf (gethash keystroke *keystroke-macros*) sym) + (register-keystroke-macro keystroke)) + +(defun remove-keystroke-macro (keystroke) + "Removes any hint of KEYSTROKE being invoked as a keystroke-macro." + (remhash keystroke *keystroke-macros*) + (unregister-keystroke-macro keystroke)) + +(defun run-keystroke-macro-hook (keystroke) + "Dispatches KEYSTROKE to the appropriate hook function." + (awhen (gethash keystroke *keystroke-macros*) + (funcall it keystroke))) + +(add-hook 'run-keystroke-macro-hook :keystroke-macro-hook) + +;; +;; Utility functions +;; +(defun map-variables (string vars) + "Returns a string made of of substituting $[0-9]+$ in STRING variables with those positions in VARS." + (with-output-to-string (result) + (let ((strlen (1- (length string)))) + (loop for i from 0 to strlen + as char = (elt string i) + do (aif (aand (< (1+ i) strlen) (eql char #\$) + (position #\$ string :start (1+ i))) + (let ((var (parse-integer (subseq string (1+ i) it)))) + (when var + (princ (elt vars (1- var)) result)) + (setq i it)) + (princ char result)))) + result)) + +(defun escape-mux-string (string) + "Returns a string made from STRING with substitutions for white space." + (with-output-to-string (result) + (let ((strlen (length string))) + (loop for i from 0 to (1- strlen) + as char = (elt string i) + do (case char + ((#\Space) + (princ "%b" result)) + ((#\Tab) + (princ "%t" result)) + ((#\Newline #\Return) + (princ "%r" result)) + (t (princ char result))))) + result)) + +(defun make-attributed-string (string &rest attribute-ranges) + (list string attribute-ranges)) + +(defun make-attributes (&rest attributes) + attributes) + +(defun make-range (location length) + (list :range location length)) + +(defun make-color (r g b) + (list :color r g b)) + +(defun make-font (name size) + (list :font name size)) + +(defun make-super (n) + (cons :super n)) + +(defun make-underline (n) + (cons :underline n)) + +(defun make-link (url) + (cons :link url)) + +;; +;; Low level commands which interface directly to Moxie. +;; +;; Useful stuff to add: +;; say, for speaking text +;; playsound/music, for sound effects +;; + +(defmacro with-response (cmd-and-args &body body) + `(progn + (apply #'send-command ,@cmd-and-args) + (let ((response (read))) + ,@body))) + +(defun write-array-to-mux (world &rest args) + "Send ARGS to the output window associated with WORLD." + (format (world-stream world) "~S~%" args) + (finish-output (world-stream world))) + +(defun send-to-mux (world &rest args) + "Send ARGS to the MUX associated with WORLD." + (format (world-stream world) "~A~%" (car args)) + (finish-output (world-stream world))) + +(defun print-to-world (world &rest args) + "Send ARGS to the output window associated with WORLD." + (apply #'send-event-to-world world :output-from-server-hook args)) + +(defun register-keystroke-macro (keystroke) + "Register KEYSTROKE as a macro with Moxie." + (send-command :register-keystroke keystroke)) + +(defun unregister-keystroke-macro (keystroke) + "Unregisters KEYSTROKE as a macro with Moxie." + (send-command :unregister-keystroke keystroke)) + +(defun set-status-buffer (string &optional (world *world*)) + "Set the status buffer of the window associated with WORLD to STRING." + (send-event-to-world world :set-status-buffer string)) + +(defun clear-screen (world) + (send-event-to-world world :clear-screen)) + +(defun enable-logging (world) + "Enable logging for WORLD." + (send-event-to-world world :enable-logging)) + +(defun disable-logging (world) + "Disable logging for WORLD." + (send-event-to-world world :disable-logging)) + +(defun send-event-to-world (world event &rest args) + "Send EVENT and ARGS to WORLD's result handler." + (apply #'send-command (world-id world) event args)) + +(defun send-command (cmd &rest args) + "Send CMD and ARGS to Moxie's generic result handler." + (let ((*print-pretty* nil)) + (prin1 `(,cmd ,@args) *moxie-result-stream*)) + #-clisp (finish-output *moxie-result-stream*))
\ No newline at end of file diff --git a/Lisp/moxie/package.fasl b/Lisp/moxie/package.fasl Binary files differnew file mode 100644 index 0000000..0eaf469 --- /dev/null +++ b/Lisp/moxie/package.fasl diff --git a/Lisp/moxie/package.lisp b/Lisp/moxie/package.lisp new file mode 100644 index 0000000..12514b0 --- /dev/null +++ b/Lisp/moxie/package.lisp @@ -0,0 +1,21 @@ +(defpackage moxie + (:use :cl :cl-user) + (:export *moxie-repl-stream* + add-hook remove-hook run-hook + add-keyword remove-keyword + add-keystroke-macro remove-keystroke-macro + map-variables escape-mux-string + + *world* world-var + + make-attributed-string make-attributes make-range make-font + make-color make-super make-underline make-link + send-to-mux write-array-to-mux print-to-world set-status-buffer clear-screen + enable-logging disable-logging)) +(in-package :moxie) + +(defvar *moxie-result-stream* nil + "Where output from the TPL goes.") + +(defvar *world* nil + "The world currently calling into a plug in function.")
\ No newline at end of file diff --git a/Lisp/moxie/repl.fasl b/Lisp/moxie/repl.fasl Binary files differnew file mode 100644 index 0000000..afb126a --- /dev/null +++ b/Lisp/moxie/repl.fasl diff --git a/Lisp/moxie/repl.lisp b/Lisp/moxie/repl.lisp new file mode 100644 index 0000000..b5b7bb3 --- /dev/null +++ b/Lisp/moxie/repl.lisp @@ -0,0 +1,95 @@ +(in-package :moxie) + +(defvar *repl-motd* + "Welcome to Moxie! + +To get help, enter :HELP at the prompt.") + +(defvar *repl-help* + "Top level commands: + :R [num] Invoke restart NUM, or list restarts. + :HELP :H :? Display this message.") + +(defvar *repl-level* 0) + +(defun start-repl (&optional (use-result-stream t)) + (let ((*moxie-result-stream* (or (and use-result-stream (make-result-stream)) + *error-output*))) + (format t "~%~A~%" *repl-motd*) + (send-command :repl-result `(:prompt ,(repl-prompt))) + (repl))) + +(defun repl () + "This is Moxie's top level loop. At this point, it's only here +because we don't want the host lisp to print results or its prompt." + (let* ((*debugger-hook* #'repl-dbg) + (*repl-level* (1+ *repl-level*)) + (lex-level *repl-level*)) + (loop + (force-output) + (let ((form (read))) + (restart-case (eval form) + (abort () + :report (lambda (stream) + ;; I know this looks weird, but because the + ;; formatter is called from the condition + ;; handler's environment, and because + ;; *repl-level* is special, at the time of + ;; evaluation, *repl-level* may be higher than + ;; lex-level. + (if (eql lex-level *repl-level*) + (format stream "Abort handling of current request.") + (format stream "Return to REPL level ~A." + lex-level))) + (send-command :repl-result `(:prompt ,(repl-prompt))))))))) + +(defun repl-dbg (condition debugger-hook) + "This debugger hook just sends a message to Moxie when the debugger +has been entered, so Moxie can keep track of the prompt." + (declare (ignore debugger-hook)) + (send-command :repl-dbg `(:condition ,condition))) + +(defmacro eval-hook (&rest forms) + "Ensure all FORMS are valid for evaluation before calling +EVAL-HOOK-HELPER." + (let ((helped-forms (mapcar (lambda (x) `(quote ,x)) forms))) + `(eval-hook-helper ,@helped-forms))) + +(defun eval-hook-helper (&rest forms) + "Evaluate all FORMS, sending the results to the Moxie output +stream. When finished processing, send the prompt." + (do* ((f forms (cdr f)) + (form (car f) (car f))) + ((null f)) + (case form + (:r (let ((restarts (compute-restarts)) + (num (cadr f))) + (if (and (integerp num) + (> num 0) (<= num (length restarts))) + (progn + (setf f (cdr f)) + (invoke-restart (elt restarts (1- num)))) + (print-restarts restarts)))) + ((:? :h :help) (format t "~A~%" *repl-help*)) + (t (let (values) + (setq - form) + (setq values (multiple-value-list (eval -))) + (setq /// // // / / values *** ** ** * * (car /)) + (send-command :repl-result `(:values ,@values)))))) + (send-command :repl-result `(:prompt ,(repl-prompt)))) + +(defun print-restarts (restarts) + (format t "Available restarts: ~%") + (do ((c restarts (cdr c)) + (i 1 (1+ i))) + ((null c)) + (format t " ~A ~A~%" i (car c))) + (format t "Invoke restarts with :R [num]~%")) + +(defun repl-prompt () + "Compute the prompt for Moxie's REPL." + (format nil "~A~@[[~A]~]> " + (if (eql *package* (find-package :cl-user)) + "CL-USER" + (package-name *package*)) + (when (> *repl-level* 1) *repl-level*)))
\ No newline at end of file diff --git a/Lisp/moxie/repl.lisp.old b/Lisp/moxie/repl.lisp.old new file mode 100644 index 0000000..8ae7408 --- /dev/null +++ b/Lisp/moxie/repl.lisp.old @@ -0,0 +1,87 @@ +(in-package :moxie) + +(defvar *repl-motd* + "Welcome to Moxie! + +To get help, enter :HELP at the prompt.") + +(defvar *repl-help* + "Top level commands: + :R [num] Invoke restart NUM, or list restarts. + :HELP :H :? Display this message.") + +(defvar *repl-level* 0) + +(defun start-repl (&optional (use-result-stream t)) + (let ((*moxie-result-stream* (or (and use-result-stream (make-result-stream)) + *error-output*))) + (format t "~%~A~%" *repl-motd*) + (send-command :repl-result `(:prompt ,(repl-prompt))))) + +(defmethod moxie-event-handler ((event (eql :eval)) &rest args) + (let* ((*debugger-hook* #'repl-dbg) + (*repl-level* (1+ *repl-level*)) + (lex-level *repl-level*)) + (dolist (form args) + (force-output) + (restart-case (eval form) + (abort () + :report (lambda (stream) + ;; I know this looks weird, but because the formatter is called + ;; from the condition handler's environment, and because + ;; *repl-level* is special, at the time of evaluation, + ;; *repl-level* may be higher than lex-level. + (if (eql lex-level *repl-level*) + (format stream "Abort handling of current request.") + (format stream "Return to REPL level ~A." lex-level))) + (send-command :repl-result `(:prompt ,(repl-prompt)))))))) + +(defun repl-dbg (condition debugger-hook) + "This debugger hook just sends a message to Moxie when the debugger has +been entered, so Moxie can keep track of the prompt." + (declare (ignore debugger-hook)) + (send-command :repl-dbg `(:condition ,condition))) + +(defmacro eval-hook (&rest forms) + "Ensure all FORMS are valid for evaluation before calling EVAL-HOOK-HELPER." + (let ((helped-forms (mapcar (lambda (x) `(quote ,x)) forms))) + `(eval-hook-helper ,@helped-forms))) + +(defun eval-hook-helper (&rest forms) + "Evaluate all FORMS, sending the results to the Moxie output stream. When finished +processing, send the prompt." + (do* ((f forms (cdr f)) + (form (car f) (car f))) + ((null f)) + (case form + (:r (let ((restarts (compute-restarts)) + (num (cadr f))) + (if (and (integerp num) + (> num 0) (<= num (length restarts))) + (progn + (setf f (cdr f)) + (invoke-restart (elt restarts (1- num)))) + (print-restarts restarts)))) + ((:? :h :help) (format t "~A~%" *repl-help*)) + (t (let (values) + (setq - form) + (setq values (multiple-value-list (eval -))) + (setq /// // // / / values *** ** ** * * (car /)) + (send-command :repl-result `(:values ,@values)))))) + (send-command :repl-result `(:prompt ,(repl-prompt)))) + +(defun print-restarts (restarts) + (format t "Available restarts: ~%") + (do ((c restarts (cdr c)) + (i 1 (1+ i))) + ((null c)) + (format t " ~A ~A~%" i (car c))) + (format t "Invoke restarts with :R [num]~%")) + +(defun repl-prompt () + "Compute the prompt for Moxie's REPL." + (format nil "~A~@[[~A]~]> " + (if (eql *package* (find-package :cl-user)) + "CL-USER" + (package-name *package*)) + (when (> *repl-level* 1) *repl-level*)))
\ No newline at end of file diff --git a/Lisp/moxie/utils/bjc-utils.fasl b/Lisp/moxie/utils/bjc-utils.fasl Binary files differnew file mode 100644 index 0000000..9d6cb67 --- /dev/null +++ b/Lisp/moxie/utils/bjc-utils.fasl diff --git a/Lisp/moxie/utils/bjc-utils.lisp b/Lisp/moxie/utils/bjc-utils.lisp new file mode 100644 index 0000000..f24774b --- /dev/null +++ b/Lisp/moxie/utils/bjc-utils.lisp @@ -0,0 +1,185 @@ +;;; -*- Lisp -*- +;; $Id: bjc-utils.lisp 19 2005-12-27 01:40:27Z bjc $ +(in-package :moxie) + +(defmacro while (expr &body body) + "Evaluate BODY continously until EXPR evaluates to FALSE." + `(do () + ((not ,expr)) + ,@body)) + +(defmacro acond (&rest clauses) + (if (null clauses) + nil + (let ((cl1 (car clauses)) + (sym (gensym))) + `(let ((,sym ,(car cl1))) + (if ,sym + (let ((it ,sym)) + ,@(cdr cl1) + (acond ,@(cdr clauses)))))))) + +(defmacro aif (expr then &optional else) + "Anaphoric if: if EXPR is true, set IT to the result of EXPR and evaluate THEN, otherwise evaluate ELSE." + `(let ((it ,expr)) + (if it + ,then + ,else))) + +(defmacro awhen (expr &body body) + "Anaphoric when: when EXPR is true, set IT to the result of EXPR and evaluate BODY." + `(let ((it ,expr)) + (when it + ,@body))) + +(defmacro awhile (expr &body body) + "Anaphoric while: while EXPR is true, set IT to the result of EXPR and evaluate BODY." + `(do ((it ,expr ,expr)) + ((not it)) + ,@body)) + +(defmacro aand (&rest args) + (cond ((null args) t) + ((null (cdr args)) (car args)) + (t `(aif ,(car args) (aand ,@(cdr args)))))) + +(defmacro aif2 (expr &optional then else) + "Two-value version of aif: aif EXPR's second value is TRUE, evaluate THEN, otherwise, evaluate ELSE." + (let ((win (gensym))) + `(multiple-value-bind (it ,win) ,expr + (if (or it ,win) ,then ,else)))) + +(defmacro awhile2 (expr &body body) + "Two-value version of awhile: awhile EXPR's second value is TRUE, evaluate BODY." + (let ((flag (gensym))) + `(let ((,flag t)) + (while ,flag + (aif2 ,expr + (progn ,@body) + (setq ,flag nil)))))) + +(defmacro with-gensyms (syms &body body) + `(let ,(mapcar (lambda (s) `(,s (gensym))) syms) + ,@body)) + +(declaim (ftype (function (function) function) memoize)) +(defun memoize (f) + "Return memoized version of FN." + (let ((cache (make-hash-table :test #'equal))) + (lambda (&rest args) + (multiple-value-bind (val win) (gethash args cache) + (if win + val + (setf (gethash args cache) (apply f args))))))) + +(declaim (ftype (function (function integer) function) memoize-with-timeout)) +(defun memoize-with-timeout (fn len) + "Memoize FN for LEN seconds after initial call." + (let ((cache (make-hash-table :test #'equal))) + (lambda (&rest args) + (multiple-value-bind (val win) (gethash args cache) + (if (and win (< (get-universal-time) (car val))) + (cdr val) + (cdr (setf (gethash args cache) + (cons (+ len (get-universal-time)) + (apply fn args))))))))) + +(defmacro enumerator (list) + "Returns an enumerator for LIST." + (let ((index (gensym))) + `(let ((,index 0)) + (lambda () + (progn + (incf ,index) + (nth (1- ,index) ,list)))))) + +(defun mkstr (&rest args) + "Creates a str from ARGS." + (with-output-to-string (s) + (dolist (a args) + (princ a s)))) + +;; +;; This macro can save and load the state of simple variables. +;; +;; Use: +;; > (setq *foo* '(1 2 3)) => (1 2 3) +;; > (def-i/o foo-w foo-r (*foo*)) => T +;; > (foo-w #p"/tmp/foo-vars") => NIL +;; > (makunbound '*foo*) => *FOO* +;; > (foo-r #p"/tmp/foo-vars") => NIL +;; > *foo* => (1 2 3) +(defmacro def-i/o (writer-name reader-name (&rest vars)) + (let ((file-name (gensym)) + (var (gensym)) + (stream (gensym))) + `(progn + (defun ,writer-name (,file-name) + (with-open-file (,stream ,file-name + :direction :output :if-exists :supersede) + (dolist (,var (list ,@vars)) + (declare (special ,@vars)) + (print ,var ,stream)))) + (defun ,reader-name (,file-name) + (with-open-file (,stream ,file-name + :direction :input :if-does-not-exist :error) + (dolist (,var ',vars) + (set ,var (read ,stream))))) + t))) + +(defun string-has-prefix (string prefix) + "Returns T if STRING begins with PREFIX, NIL otherwise." + (let ((strlen (length string)) + (prefixlen (length prefix))) + (when (<= prefixlen strlen) + (do ((i 0 (1+ i))) + ((<= prefixlen i) t) + (let ((s (elt string i)) (p (elt prefix i))) + (when (not (eql s p)) + (return-from string-has-prefix nil))))))) + +(defmacro llambda (simple-lambda-list &body body) + (let ((num-args (gensym)) + (args (gensym)) + (accumulated-args (gensym)) + (call-lambda (gensym))) + (labels ((lambda-length (simple-lambda-list &optional (count 0)) + (if (or (null simple-lambda-list) + (member (car simple-lambda-list) + '(&allow-other-keys &key &rest &aux &optional))) + count + (lambda-length (cdr simple-lambda-list) (1+ count))))) + `(labels ((,call-lambda (,num-args ,accumulated-args) + (lambda (&rest ,args) + (if (< (length ,args) ,num-args) + (,call-lambda (- ,num-args (length ,args)) + (append ,accumulated-args ,args)) + (apply (lambda ,simple-lambda-list ,@body) + (append ,accumulated-args ,args)))))) + (,call-lambda ,(lambda-length simple-lambda-list) nil))))) + +(defmacro $c (f &rest args) + (let ((a (gensym))) + `(lambda ($_) + (flet ((my-apply (sym args) + (cond ((functionp sym) (apply (the function sym) args)) + ((macro-function sym) + (eval (funcall (macro-function sym) + `(,sym ,args) + nil))) + ((symbol-function sym) (apply (symbol-function sym) args)) + (t (error "Can't curry ~A" (type-of sym)))))) + (let ((,a (subs-var '$_ $_ + (list ,@(if (member '$_ args) + args + (append args '($_))))))) + (my-apply ,f ,a)))))) + +(defun subs-var (sym val expr &optional accum) + (if (null expr) + (nreverse accum) + (subs-var sym val (cdr expr) + (if (and (atom (car expr)) + (eq (car expr) sym)) + (cons val accum) + (cons (car expr) accum)))))
\ No newline at end of file diff --git a/Lisp/moxie/world.fasl b/Lisp/moxie/world.fasl Binary files differnew file mode 100644 index 0000000..a903e04 --- /dev/null +++ b/Lisp/moxie/world.fasl diff --git a/Lisp/moxie/world.lisp b/Lisp/moxie/world.lisp new file mode 100644 index 0000000..af6ee65 --- /dev/null +++ b/Lisp/moxie/world.lisp @@ -0,0 +1,120 @@ +;;; -*- Lisp -*- +;; $Id: world.lisp 48 2006-01-09 00:27:16Z bjc $ +(in-package :moxie) + +(defvar *worlds* (make-hash-table) + "The world environments, keyed on world id.") + +(let ((next-world-id 0)) + (defclass world () + ((id :initarg :id :initform (incf next-world-id) + :accessor world-id + :documentation "The world id.") + (vars :initarg :vars :initform nil + :accessor world-vars + :documentation "Savable settings.") + (save-path :initarg :save-path :initform nil + :accessor world-save-path + :documentation "File path.") + (stream :initarg :stream :initform nil + :accessor world-stream + :documentation "Connection to server.") + (connected :initarg :connected :initform nil + :accessor world-connected + :documentation "Are we currently connected?")) + (:documentation "All associated world information."))) + +(defgeneric load-world-state (world &key path &allow-other-keys) + (:documentation "Returns an ALIST from WORLD's disk location, or PATH (if set).")) + +(defgeneric save-world-state (world &key path as-copy &allow-other-keys) + (:documentation "Saves WORLD's state to its disk location or PATH (if set).")) + +(defgeneric world-event-handler (event &rest args) + (:documentation "Handle EVENT (w/ ARGS) for *WORLD*.")) + +(defmethod initialize-instance ((instance world) &rest initargs) + (declare (ignore initargs)) + (format t "initialize-instance world~%") + (add-world (call-next-method))) + +(defmethod world-event-handler (event &rest args) + "Default handler doesn't know about anything, so it logs, instead." + (format t "Don't know how to handle event ~S ~S from world ~S.~%" + event args (world-id *world*))) + +(defun add-world (world) + (setf (gethash (world-id world) *worlds*) world)) + +(defun remove-world (world) + (remhash (world-id world) *worlds*)) + +(defun map-worlds (fn) + (let ((result nil)) + (maphash (lambda (k v) + (declare (ignore k)) + (setf result (cons (funcall fn v) result))) + *worlds*) + (nreverse result))) + +(defun map-world-vars (fn &optional (world *world*)) + (mapcar (lambda (list) + (funcall fn (car list) (cdr list))) + (world-vars world))) + +(defun world-var (name &optional (world *world*)) + "Returns the value for NAME in WORLD's environment." + (cdr (assoc name (world-vars world)))) + +(defun set-world-var (name value &optional (world *world*)) + "Sets the value of NAME to VALUE in WORLD's environment." + (setf (world-vars world) + (cons (cons name value) + (remove-if (lambda (x) + (eql (car x) name)) + (world-vars world))))) + +(defsetf world-var (name &optional (world '*world*)) (value) + `(set-world-var ,name ,value ,world)) + +(defun close-world (&optional (world *world*)) + "Closes WORLD." + (world-disconnect world) + (remove-world world) + (let ((*world* world)) + (run-hook :world-closed-hook))) + +(defun world-connect (&optional (world *world*)) + "Connects WORLD to the host and port specified." + (awhen (aand (world-var :hostname world) (world-var :port world) + (open-connection (world-var :hostname world) (world-var :port world))) + (add-input-handler it + (lambda (stream) + (let ((*world* world)) + (handler-case + (while (listen stream) + (multiple-value-bind (line missing-newline-p) (read-line stream) + (run-hook :output-from-server-hook line) + (when missing-newline-p + (signal 'end-of-file)))) + (end-of-file () + (world-disconnect world)))))) + (setf (world-stream world) it) + (setf (world-connected world) t) + (let ((*world* world)) + (run-hook :world-connected-hook)))) + +(defun world-disconnect (&optional (world *world*)) + "Closes the connection, if opened, for WORLD." + (let ((*world* world)) + (when (world-connected *world*) + (close-connection (world-stream *world*)) + (setf (world-stream *world*) nil) + (setf (world-connected *world*) nil) + (run-hook :world-disconnected-hook)))) + +(defun world-event (world-id &rest args) + (format t "DEBUG: world-event ~S ~S~%" world-id args) + (let ((*world* (or (gethash world-id *worlds*) + (make-instance 'world :id world-id)))) + (apply #'world-event-handler args)))
\ No newline at end of file diff --git a/Lisp/openmcl/dppccl b/Lisp/openmcl/dppccl Binary files differnew file mode 100755 index 0000000..49761db --- /dev/null +++ b/Lisp/openmcl/dppccl diff --git a/Lisp/openmcl/openmcl b/Lisp/openmcl/openmcl new file mode 100755 index 0000000..1f457fa --- /dev/null +++ b/Lisp/openmcl/openmcl @@ -0,0 +1,42 @@ +#!/bin/sh +# +# Change the definition of CCL_DEFAULT_DIRECTORY below to refer to +# your OpenMCL installation directory. +# Any definition of CCL_DEFAULT_DIRECTORY already present in the environment +# takes precedence over definitions made below. + +if [ -z "$CCL_DEFAULT_DIRECTORY" ]; then + CCL_DEFAULT_DIRECTORY="$1" +fi + +# This is shorter (& easier to type), making the invocation below +# a little easier to read. + +DD=${CCL_DEFAULT_DIRECTORY} + +# If you don't want to guess the name of the OpenMCL kernel on +# every invocation (or if you want to use a kernel with a +# non-default name), you might want to uncomment and change +# the following line: +#OPENMCL_KERNEL=some_name + +# Set the CCL_DEFAULT_DIRECTORY environment variable; +# the lisp will use this to setup translations for the CCL: logical host. + +if [ -z "$OPENMCL_KERNEL" ]; then + case `uname -s` in + Darwin) + OPENMCL_KERNEL=dppccl + ;; + Linux) + OPENMCL_KERNEL=ppccl + ;; + *) + echo "Can't determine host OS. Fix this." + exit 1 + ;; + esac +fi + +CCL_DEFAULT_DIRECTORY=${DD} exec ${DD}/${OPENMCL_KERNEL} "$@" + diff --git a/Lisp/openmcl/save-moxie-image.lisp b/Lisp/openmcl/save-moxie-image.lisp new file mode 100644 index 0000000..1fda5fd --- /dev/null +++ b/Lisp/openmcl/save-moxie-image.lisp @@ -0,0 +1,3 @@ +(require 'asdf) +(asdf:operate 'asdf:load-op :moxie) +(moxie::save-lisp-and-die "/tmp/dppccl.image") diff --git a/Lisp/sbcl/save-moxie-image.lisp b/Lisp/sbcl/save-moxie-image.lisp new file mode 100644 index 0000000..fed8216 --- /dev/null +++ b/Lisp/sbcl/save-moxie-image.lisp @@ -0,0 +1,3 @@ +(require 'asdf) +(asdf:operate 'asdf:load-op :moxie) +(moxie::save-lisp-and-die "/tmp/sbcl.core") diff --git a/Lisp/sbcl/sbcl b/Lisp/sbcl/sbcl Binary files differnew file mode 100755 index 0000000..76bd663 --- /dev/null +++ b/Lisp/sbcl/sbcl diff --git a/Lisp/startlisp b/Lisp/startlisp new file mode 100755 index 0000000..a7005cf --- /dev/null +++ b/Lisp/startlisp @@ -0,0 +1,46 @@ +#!/bin/sh +# +# Args are Resources, Plugins, and Framework paths. +# + +topdir=`dirname $0` +cd "$1" + +template="init-template.lisp" +initfile="/tmp/moxie-init.$$.lisp" + +start_clisp() +{ + if [ ! -f "$1/base" ]; then + ln -s . "$1/base" + fi + "$topdir/clisp" -B "$1" -E UTF-8 -i "$initfile" +} + +start_openmcl() +{ + CCL_DEFAULT_DIRECTORY="$1" + export CCL_DEFAULT_DIRECTORY + "$topdir/openmcl" -l "$initfile" +} + +start_sbcl() +{ + "$topdir/sbcl" --core "$1/sbcl.core" --load "$initfile" +} + +# +# Create the init file by substituting our args for variables in +# the template. +# +sed -e "s,@resources@,$1,g;s,@plugins@,$2,g;s,@framework@,$3,g" < $template > $initfile + +# +# Start up a lisp with the initialization file we just created. +# +#start_clisp "$1" +start_sbcl "$1" +#start_openmcl "$1" + +# Remove the initfile when the lisp quits. +#rm -f $initfile
\ No newline at end of file |