pa...@wormwood  committed e96859b

Ready for first release.

  • Participants
  • Parent commits 5fe1fb3

Comments (0)

Files changed (5)

+                    GNU GENERAL PUBLIC LICENSE
+                       Version 3, 29 June 2007
+ Copyright (C) 2007 Free Software Foundation, Inc. <>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+                            Preamble
+  The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+  The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works.  By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users.  We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors.  You can apply it to
+your programs, too.
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+  To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights.  Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received.  You must make sure that they, too, receive
+or can get the source code.  And you must show them these terms so they
+know their rights.
+  Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+  For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software.  For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+  Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so.  This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software.  The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable.  Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products.  If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+  Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary.  To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+  The precise terms and conditions for copying, distribution and
+modification follow.
+                       TERMS AND CONDITIONS
+  0. Definitions.
+  "This License" refers to version 3 of the GNU General Public License.
+  "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+  "The Program" refers to any copyrightable work licensed under this
+License.  Each licensee is addressed as "you".  "Licensees" and
+"recipients" may be individuals or organizations.
+  To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy.  The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+  A "covered work" means either the unmodified Program or a work based
+on the Program.
+  To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy.  Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+  To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies.  Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+  An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License.  If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+  1. Source Code.
+  The "source code" for a work means the preferred form of the work
+for making modifications to it.  "Object code" means any non-source
+form of a work.
+  A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+  The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form.  A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+  The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities.  However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work.  For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+  The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+  The Corresponding Source for a work in source code form is that
+same work.
+  2. Basic Permissions.
+  All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met.  This License explicitly affirms your unlimited
+permission to run the unmodified Program.  The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work.  This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+  You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force.  You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright.  Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+  Conveying under any other circumstances is permitted solely under
+the conditions stated below.  Sublicensing is not allowed; section 10
+makes it unnecessary.
+  3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+  No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+  When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+  4. Conveying Verbatim Copies.
+  You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+  You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+  5. Conveying Modified Source Versions.
+  You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+    a) The work must carry prominent notices stating that you modified
+    it, and giving a relevant date.
+    b) The work must carry prominent notices stating that it is
+    released under this License and any conditions added under section
+    7.  This requirement modifies the requirement in section 4 to
+    "keep intact all notices".
+    c) You must license the entire work, as a whole, under this
+    License to anyone who comes into possession of a copy.  This
+    License will therefore apply, along with any applicable section 7
+    additional terms, to the whole of the work, and all its parts,
+    regardless of how they are packaged.  This License gives no
+    permission to license the work in any other way, but it does not
+    invalidate such permission if you have separately received it.
+    d) If the work has interactive user interfaces, each must display
+    Appropriate Legal Notices; however, if the Program has interactive
+    interfaces that do not display Appropriate Legal Notices, your
+    work need not make them do so.
+  A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit.  Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+  6. Conveying Non-Source Forms.
+  You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+    a) Convey the object code in, or embodied in, a physical product
+    (including a physical distribution medium), accompanied by the
+    Corresponding Source fixed on a durable physical medium
+    customarily used for software interchange.
+    b) Convey the object code in, or embodied in, a physical product
+    (including a physical distribution medium), accompanied by a
+    written offer, valid for at least three years and valid for as
+    long as you offer spare parts or customer support for that product
+    model, to give anyone who possesses the object code either (1) a
+    copy of the Corresponding Source for all the software in the
+    product that is covered by this License, on a durable physical
+    medium customarily used for software interchange, for a price no
+    more than your reasonable cost of physically performing this
+    conveying of source, or (2) access to copy the
+    Corresponding Source from a network server at no charge.
+    c) Convey individual copies of the object code with a copy of the
+    written offer to provide the Corresponding Source.  This
+    alternative is allowed only occasionally and noncommercially, and
+    only if you received the object code with such an offer, in accord
+    with subsection 6b.
+    d) Convey the object code by offering access from a designated
+    place (gratis or for a charge), and offer equivalent access to the
+    Corresponding Source in the same way through the same place at no
+    further charge.  You need not require recipients to copy the
+    Corresponding Source along with the object code.  If the place to
+    copy the object code is a network server, the Corresponding Source
+    may be on a different server (operated by you or a third party)
+    that supports equivalent copying facilities, provided you maintain
+    clear directions next to the object code saying where to find the
+    Corresponding Source.  Regardless of what server hosts the
+    Corresponding Source, you remain obligated to ensure that it is
+    available for as long as needed to satisfy these requirements.
+    e) Convey the object code using peer-to-peer transmission, provided
+    you inform other peers where the object code and Corresponding
+    Source of the work are being offered to the general public at no
+    charge under subsection 6d.
+  A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+  A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling.  In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage.  For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product.  A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+  "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source.  The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+  If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information.  But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+  The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed.  Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+  Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+  7. Additional Terms.
+  "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law.  If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+  When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it.  (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.)  You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+  Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+    a) Disclaiming warranty or limiting liability differently from the
+    terms of sections 15 and 16 of this License; or
+    b) Requiring preservation of specified reasonable legal notices or
+    author attributions in that material or in the Appropriate Legal
+    Notices displayed by works containing it; or
+    c) Prohibiting misrepresentation of the origin of that material, or
+    requiring that modified versions of such material be marked in
+    reasonable ways as different from the original version; or
+    d) Limiting the use for publicity purposes of names of licensors or
+    authors of the material; or
+    e) Declining to grant rights under trademark law for use of some
+    trade names, trademarks, or service marks; or
+    f) Requiring indemnification of licensors and authors of that
+    material by anyone who conveys the material (or modified versions of
+    it) with contractual assumptions of liability to the recipient, for
+    any liability that these contractual assumptions directly impose on
+    those licensors and authors.
+  All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10.  If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term.  If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+  If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+  Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+  8. Termination.
+  You may not propagate or modify a covered work except as expressly
+provided under this License.  Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+  However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+  Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+  Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License.  If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+  9. Acceptance Not Required for Having Copies.
+  You are not required to accept this License in order to receive or
+run a copy of the Program.  Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance.  However,
+nothing other than this License grants you permission to propagate or
+modify any covered work.  These actions infringe copyright if you do
+not accept this License.  Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+  10. Automatic Licensing of Downstream Recipients.
+  Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License.  You are not responsible
+for enforcing compliance by third parties with this License.
+  An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations.  If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+  You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License.  For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+  11. Patents.
+  A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based.  The
+work thus licensed is called the contributor's "contributor version".
+  A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version.  For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+  Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+  In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement).  To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+  If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients.  "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+  If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+  A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License.  You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+  Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+  12. No Surrender of Others' Freedom.
+  If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all.  For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+  13. Use with the GNU Affero General Public License.
+  Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work.  The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+  14. Revised Versions of this License.
+  The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+  Each version is given a distinguishing version number.  If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation.  If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+  If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+  Later license versions may give you additional or different
+permissions.  However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+  15. Disclaimer of Warranty.
+  16. Limitation of Liability.
+  17. Interpretation of Sections 15 and 16.
+  If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+                     END OF TERMS AND CONDITIONS
+            How to Apply These Terms to Your New Programs
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    GNU General Public License for more details.
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <>.
+Also add information on how to contact you by electronic and paper mail.
+  If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+    <program>  Copyright (C) <year>  <name of author>
+    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+  You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+  The GNU General Public License does not permit incorporating your program
+into proprietary programs.  If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library.  If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.  But first, please read
 ;;;; -*- Mode: Lisp; Syntax: ANSI-Common-Lisp; Base: 10 -*- ;;;;;;;;;;;;;;;;;80
+;;;;    This file is part of CLOD, by Paul Sexton
+;;;;    Released under the Gnu Public License version 3
+;;;;    CLOD is free software: you can redistribute it and/or modify
+;;;;    it under the terms of the GNU General Public License as published by
+;;;;    the Free Software Foundation, either version 3 of the License, or
+;;;;    (at your option) any later version.
+;;;;    CLOD is distributed in the hope that it will be useful,
+;;;;    but WITHOUT ANY WARRANTY; without even the implied warranty of
+;;;;    GNU General Public License for more details.
+;;;;    You should have received a copy of the GNU General Public License
+;;;;    along with CLOD.  If not, see <>.
 (defpackage #:clod-asd
   (:use :cl :asdf))
 ;;;; -*- Mode: Lisp; Syntax: ANSI-Common-Lisp; Base: 10 -*- ;;;;;;;;;;;;;;;;;80
-;; still unclear how to tell if a symbol is bound to a type.
-;; eg (deftype =foo= () `(integer 0 10))
-;; todo would be nice to get CL symbols to link to hyperspec
-;;    (if (eql (symbol-package sym) (find-package :cl)) ...)
-;; Currently [[hs:sym]]  --> HyperSpecRoot/sym but this will not work as
-;; hyperspec pages are unfortunately not named according to the symbol they
-;; describe.
-;; todo table of slots at beginning of each class def
-;; todo use to document self
-;; todo need to escape org format chars in symbols: *, / etc
-;; deploy SAFE-SYMBOL
-;; todo distinguish structs more.
+;;;;    This file is part of CLOD, by Paul Sexton
+;;;;    Released under the Gnu Public License version 3
+;;;;    CLOD is free software: you can redistribute it and/or modify
+;;;;    it under the terms of the GNU General Public License as published by
+;;;;    the Free Software Foundation, either version 3 of the License, or
+;;;;    (at your option) any later version.
+;;;;    CLOD is distributed in the hope that it will be useful,
+;;;;    but WITHOUT ANY WARRANTY; without even the implied warranty of
+;;;;    GNU General Public License for more details.
+;;;;    You should have received a copy of the GNU General Public License
+;;;;    along with CLOD.  If not, see <>.
+;;;; todo:
+;;;; * would be nice to get CL symbols to link to hyperspec
+;;;;    (if (eql (symbol-package sym) (find-package :cl)) ...)
+;;;;   Currently [[hs:sym]]  --> HyperSpecRoot/sym but this will not work as
+;;;;   hyperspec pages are unfortunately not named according to the symbol they
+;;;;   describe.
+;;;; todo table of slots at beginning of each class def
 (in-package :cl-user)
+  (:export
+   #:document-package
+   #:document-packages)
    "* Description
-CLOD is a tool for creating documentation for Common Lisp programs."))
+CLOD is a tool for creating documentation for Common Lisp programs.
+CLOD examines a loaded package and writes information about all the
+symbols defined within that package, to a file.
+The output file is in org format. Org is a simple but powerful 'wiki-like'
+markup language that is understood by *Org-mode*, a powerful outliner, personal
+wiki and organiser that runs within Emacs. Org-mode can export
+org-format files to numerous other formats, including HTML, LaTeX, PDF,
+DocBook, and plain text.
+More information:
+- Emacs :: [[]] (if you program CL, you don't
+  need to be told what Emacs is)
+- Org mode :: [[]]
+* Why use CLOD?
+- You can use org markup within docstrings (easy for humans to read) to
+  create subsections, bulleted lists, hyperlinks within the document or
+  to external URLs, etc.
+- Easy export to multiple file formats: text, HTML, LaTeX -> PDF...
+- You can edit the output within Emacs, which is already the IDE of most
+  CL programmers.
+- Org has many cool tricks. Some examples of useful things you can put in
+  docstrings:
+  - Include an entire file and format as plain text:
+    : #+INCLUDE: \"filename\" quote
+  - Include an entire file with common lisp syntax highlighting
+    : #+INCLUDE: \"filename.lisp\" src lisp
+  - Timestamps and datestamps:
+    : {{{ modification-time(%r) }}}
+    {{{modification-time(%r)}}}
+    : {{{ date(%Y-%m-%d) }}}
+    {{{date(%Y-%m-%d)}}}
+  - Define text macros, use with ={{{macro(arg1,arg2)}}}=
+    : #+MACRO: foo Replacement text $1 $2
+  - Embed any LaTeX code directly (no special markup needed)
+  - Embed any HTML code (special markup needed)
+  - Automatic syntax highlighting of source code examples in exported
+    documents, eg:
+;;; (defun hello (a &key b)
+;;;    (print \"Hello, world!\"))
+* Dependencies
+- Closer-MOP:
+- Iterate:
+* How to use
+1. Install CLOD somewhere ASDF can find it.
+2. Load CLOD with =(asdf:oos 'asdf:load-op :clod)=
+3. Load the package or packages for which you wish to produce documentation,
+   eg: =(asdf:oos 'asdf:load-op :mypkg)=
+4. Run =(clod:document-package :mypkg nil)= and you will see the documentation
+   as a string, returned by [[document-package]].
+5. Run =(clod:document-package :mypkg \"\")= and the same
+   documentation will be written to ''.
+6. Load into Emacs. Export to HTML with =M-x org-export=, or press
+   C-c C-e to be presented with a menu of export options.
+* Writing the documentation
+All documentation produced by CLOD is obtained by introspection, i.e.  the
+running CL process examining itself. If a symbol has an associated docstring,
+it will be used by CLOD to produce the documentation for that symbol.
+Within documentation strings, you can use org mode markup. This is a simple,
+human-readable markup language similar to the type of markup used for wiki
+editing and forum posting. See the Org
+[[][manual]] for more information. Also see
+the docstrings in the CLOD source code, which use org markup.
+Some special points to note:
+- Outline headings are used to structure org documents. These headings
+  begin with one or more asterisks at the start of the line. Thus, if you
+  want a large docstring to be divided into subsections, the heading for
+  each subsection should be a line that starts with one or more asterisks (*),
+  then a space, then the title of the heading.
+- These headings will automatically be correctly 'indented' for their location
+  in the structure of the final document. The whole document is one outline,
+  and any given docstring will usually be appearing 2 or 3 levels deep within
+  that outline. However, CLOD finds all heading lines within docstrings and
+  increases the number of asterisks appropriately.
+- An extra blank line is also automatically inserted after headings within
+  docstrings, allowing you to save screen space in the docstring itself.
+- By default, many docstrings are inserted within a subsection titled
+  'Description'. However, if you don't want this to happen, but rather want
+  the docstring to define its own heading names, make sure that the very first
+  thing in the docstring is a heading (straight after the opening quote).
+- Some symbol names used by common lisp can conflict with the markup used
+  by org mode. For example, =*global-variable*=: asterisks are interpreted
+  by org mode as signifying bold text. CLOD catches these in headings and
+  auto-generated documentation, but not within doc strings, where you will
+  need to surround the offending symbol with =equals signs=.
+- *Hyperlinks* are created using
+  : [[double square brackets]]
+  Any text surrounded by these brackets will link to the same text (case
+  insensitive) surrounded by <<double angle brackets>>. CLOD uses this to define
+  hyperlinks for all symbols in the package. Every symbol MYSYMBOL has:
+  1. A hyperlink =<<function MYSYMBOL>>= if MYSYMBOL is a function,
+     =<<variable MYSYMBOL>>= if it is a global variable, etc.
+  2. A hyperlink =<<MYSYMBOL>>= which will either link to MYSYMBOL's documentation,
+     or to a 'disambiguation section' if the same symbol has multiple meanings
+     (eg there is both a function and a variable called MYSYMBOL).
+- Org mode has the ability to use Emacs' font-lock mode to produce source code
+  snippets that are correctly syntax highlighted for any major mode.
+  To use this normally requires surrounding the code with #+BEGIN_SRC ... #+END_SRC.
+  CLOD provides a shortcut: Any lines within docstrings that begin with three
+  semicolons ;;; are assumed to be example lisp source code. The first 3
+  semicolons are removed and the rest of the line is syntax highlighted.
+* Example
+Here is the docstring for [[document-package]].
+: * Usage
+: : (document-package PKG FILE/STREAM &key AUTO-LINKS
+: :      AUTHOR EMAIL)
+: * Arguments
+: - PKG :: A package name or package object.
+: - FILE/STREAM :: A string (filename), stream object, or =NIL=.
+: - AUTO-LINKS :: Boolean.
+: - BRIEF-METHODS :: Boolean.
+: - TITLE :: A string.
+: - AUTHOR :: A string.
+: - EMAIL :: A string.
+: * Returns
+: A string, or nil.
+: * Description
+: Produce documentation for the package =PKG=.
+: The documentation's destination depends on the value of =FILE/STREAM=:
+: - =STRING=: documentation is written to the file named by the string.
+: - =STREAM=: documentation is written to the already existing stream.
+: - =NIL=: documentation is written to a string, which is then returned by
+:   this function.
+: Explanation of optional arguments:
+: - =TITLE=, =AUTHOR= and =EMAIL= specify the document title, the name of
+:   the author, and the email address of the author.
+: - If =AUTO-LINKS= is non-nil, *all* occurrences of symbol names within the
+:   text of docstrings will be interpreted as hyperlinks, regardless of
+:   whether they are marked up as hyperlinks.
+: - If LINES-BETWEEN-SECTIONS is nil, do not output a horizontal line before
+:   each new section of documentation.
+: - If BRIEF-METHODS is nil, document individual methods with their own
+:   sections, just like functions and generic functions. Most people put
+:   'method' documentation in the docstrings of their generic functions, but
+:   if you set docstrings for individual methods then set this to nil.
+: * See also
+: - [[document-packages]]
+* Limitations
+- There is no portable way to access the lambda lists of functions. Thus, you need
+  to spell these out in function docstrings.
 (in-package :clod)
 (defvar *out* *standard-output*
-  "* Description
-Global variable that is bound to the output stream used by CLOD
-when writing documentation.")
+  "Global variable that is bound to the output stream used by CLOD
+while writing documentation.")
 (defvar *heading-level* 0
-  "* Description
-Number of levels 'deep' within the outline.")
+  "Number of levels 'deep' within the outline. Used when creating
+headings for sections and subsections.")
 (defvar *heading-char* #\*
-  "* Description
-Character used at the beginning of lines to signify headings and
+  "Character used at the beginning of lines to signify headings and
+subheadings. Should not be changed.")
 (defvar *line-width* 80
-  "* Description
-Width to which paragraphs are wrapped.")
+  "Width to which paragraphs are wrapped, in characters.")
 (defvar *left-margin* 0
-  "* Description
-Number of spaces to which text is currently being indented.")
-(defvar *ambiguities* nil)
-(defconstant +alphabet+
+  "Width of the current 'left margin', in spaces.")
+(defvar *ambiguities* nil
+  "Hash table created during package documentation. Stores all
+symbols which have multiple 'meanings' within the package.")
+(defparameter *alphabet*
   (loop for i from 1 to 26 collecting (code-char (+ 64 i)))
   "List of uppercase letters (characters) from A to Z.")
+(defvar *hyperspec-root* ""
+  "URL or directory where the Hyperspec is found. Not currently
+(defvar *auto-links* nil
+  "If true, all occurrences of package symbols anywhere in the documentation
+will be turned into hyperlinks, even if they are not marked up as such.")
+(defvar *lines-between-sections* nil
+  "If true, sections of the document will be separated by horizontal lines.")
+(defvar *brief-methods* t
+  "If true, most documentation for methods is assumed to be found in the docstring
+for their generic function. A generic function's methods are therefore described
+in a very brief format (bulleted list).
+If false, each method receives its own section, just like other functions.")
+(defvar *document-title* "Documentation"
+  "The title of the document. A string.")
+(defvar *document-author* "CLOD"
+  "The author of the document. A string.")
+(defvar *document-email* ""
+  "The email address of the document's author. A string.")
 (deftype =entity= ()
-  "* Description
-Type for entities."
+  "The type 'entity' can have any of several different symbols as its value.
+Each value is a different kind of 'meaning' which a symbol can have within
+a package. For example, =:function= is a function, =:class= is a class,
+and so on."
   `(member :slot :generic-function :function :macro
            :constant :variable :class
-           :structure :package
+           :structure :type :package
            :slot-accessor :slot-writer :slot-reader))
 (defgeneric document (sym doctype)
    "* Arguments
-- SYM: a symbol.
-- DOCTYPE: an [[=ENTITY=]].
+- SYM :: a symbol.
+- DOCTYPE :: an [[=entity=]].
 * Returns:
 * Description
-Write a section documenting the entity named SYM which is of entity type
+Writes a section documenting the [[=entity=]] named =SYM= which is of entity type
 ;;;; Utility functions ========================================================
+(defmacro do-own-symbols ((var pkg) &body body)
+  "* Usage
+: (do-own-symbols (VAR PKG)
+:    ...body...)
+* Arguments
+- VAR :: symbol naming a variable that will be bound to each symbol in turn.
+- PKG :: a package.
+* Description
+Iterate through all the non-imported symbols in the package =PKG=.
+=BODY= is executed once for each such symbol, with =VAR= bound to each
+symbol in turn."
+  `(let ((%shadow-symbols (package-shadowing-symbols ,pkg)))
+     (do-symbols (,var ,pkg)
+       (unless (find ,var %shadow-symbols)
+         ,@body))))
 (defun entity->tag (entity)
-  "* Arguments
-- ENTITY: An [[=ENTITY=]].
+  "* Usage
+: (entity->tag ENTITY)
+* Arguments
+- ENTITY :: An [[=entity=]].
 * Returns
 A string.
 * Description
-Given an entity, returns a string that can be used as a tag in org mode."
+Given an entity, returns a string that can be used as a *tag* denoting that
+entity type in org mode. See [[]] for
+information on tags."
   (case entity
     (:generic-function "generic")
     (:function "function")
     (:variable "variable")
     (:constant "constant")
     (:class "class")
+    (:type "type")
     (:slot "slot")
     (:slot-accessor "reader:writer")
     (:slot-reader "reader")
 (defun entity->string (entity)
+  "* Usage
+: (entity->string ENTITY)
+* Arguments
+- ENTITY :: An [[=entity=]].
+* Returns
+A string.
+* Description
+Given an entity, returns a string that can be used to describe that
+entity type in human-readable form, in headings, etc."
   (case entity
     (:generic-function "generic function")
     (:function "function")
     (:variable "variable")
     (:constant "constant")
     (:class "class")
+    (:type "type")
     (:slot "slot")
     (:slot-accessor "slot accessor")
     (:slot-reader "slot reader")
 (defun symbol-accessibility (sym &optional (pkg *package*))
+  "* Usage
+: (symbol-accessibility SYM [PKG])
+* Arguments
+- SYM :: A symbol.
+- PKG :: A package.
+* Returns
+One of =:inherited, :internal, :external= or =nil=.
+* Description
+Returns a symbol describing how the symbol =SYM= is accessible within
+the package =PKG=. If =SYM= is exported by =PKG= then the function
+returns =:external=, and so on."
   (unless (packagep pkg)
     (setf pkg (find-package pkg)))
   (multiple-value-bind (sym2 access) (find-symbol (string sym) pkg)
 (defun list->string-with-commas (ls)
+  "* Usage
+: (list->string-with-commas LS)
+* Arguments
+- LS :: A list of values.
+* Returns
+A string.
+* Description
+Given a list of arbitrary values, returns a string consisting of the
+printed representations of those values, separated by commas and spaces.
+* Example
+;;; (list->string-with-commas '(a b 123))
+;;; => \"A, B, 123\"
   (with-output-to-string (s)
     (if (cdr ls)
         (format s "~{~A, ~}" (butlast ls)))
 (defun make-specialised-lambda-list (terms specs)
+  "* Usage
+: (make-specialised-lambda-list TERMS SPECS)
+* Arguments
+- TERMS :: Unspecialised version of the lambda list (a list of symbols).
+- SPECS :: List of class names on which a particular method is
+  specialised.
+* Returns
+A list.
+* Description
+Given an unspecialised lambda list and a list of specialisers, reconstruct
+the specialised lambda list and return it."
     (for term in terms)
     (for spec = (pop specs))
     (if spec
-        (collect (list term (make-class-link spec)))
+        (collect (list term (make-link spec :class)))
         ;; else
         (collect term))))
 (defun list-all-direct-slots (classes)
+  "* Usage
+: (list-all-direct-slots CLASSES)
+* Arguments
+- CLASSES :: A list of class objects.
+* Return Value
+A list of SLOT-DEFINITION instances.
+* Description
+Return a list of all the direct SLOT-DEFINITION instances defined
+for all the classes in CLASSES."
   (let ((slots nil))
       (for c in classes)
 (defun list-all-indirect-slots (classes)
+  "* Usage
+: (list-all-indirect-slots CLASSES)
+* Arguments
+- CLASSES :: A list of class objects.
+* Return Value
+A list of SLOT-DEFINITION instances.
+* Description
+Return a list of all the indirect SLOT-DEFINITION instances defined
+for all the classes in CLASSES."
   (let ((indirect-slots nil))
       (for c in classes)
 (defun list-all-slot-accessors (classes)
+  "* Usage
+: (list-all-slot-accessors CLASSES)
+* Arguments
+- CLASSES :: A list of class objects.
+* Return Value
+A list of generic functions.
+* Description
+Return a list of all the reader and writer generic functions associated
+with all the slots of the classes in CLASSES."
   (let ((slots (remove-if-not
                 (lambda (slot) (typep slot (find-class 'direct-slot-definition)))
                 (list-all-direct-slots classes))))
 (defun uses-for-symbol (sym)
+  "* Usage
+: (uses-for-symbol SYM)
+* Arguments
+- SYM :: A symbol.
+* Return Value
+A list of [[=entity=]] values.
+* Description
+Given a symbol =SYM=, return a list of entity values, describing the
+different meanings/bindings of =SYM= within its home package."
   (let ((uses nil))
     (when (find-package sym)
       (push :package uses))
-    (when (find-class sym nil)
-      (push :class uses))
+    (cond
+      ((find-class sym nil)
+       (if (typep (find-class sym) 'structure-class)
+           (push :structure uses)
+           (push :class uses)))
+      ((simple-type? sym)
+       (push :type uses)))
       ((macro-function sym)
        (push :macro uses))
+(defun simple-type? (sym)
+  "* Usage
+: (simple-type? SYM)
+* Arguments
+- SYM :: A symbol.
+* Return Value
+* Description
+Returns =T= if =SYM= names a non-class type, such as can be
+defined by [[deftype]]."
+  (handler-case (typep t sym)
+    (error () (return-from simple-type? nil)))
+  t)
 (defun word-wrap (text &key (width 80) respect-newlines respect-hyphens
 		  exclude-start-char exclude-end-char)
-  "* Arguments
-- TEXT: A string.
-- WIDTH: An integer. The width that TEXT should be wrapped to fit within.
+  "* Usage
+* Arguments
+- TEXT :: A string.
+- WIDTH :: An integer. The maximum length of lines once TEXT is wrapped.
 Default is 80.
-- RESPECT-NEWLINES: Boolean. Should newline characters within the string
-be treated as unbreakable?
-- RESPECT-HYPHENS: Boolean. Should we refrain from breaking hyphenated
-- EXCLUDE-START-CHAR: A character, or nil.
-- EXCLUDE-END-CHAR: A character, or nil.
+- RESPECT-NEWLINES :: Boolean. Should newline characters within the string
+be treated as unbreakable? (=NIL=)
+- RESPECT-HYPHENS :: Boolean. Should we refrain from breaking hyphenated
+words? (=NIL=)
+- EXCLUDE-START-CHAR :: A character, or nil.
+- EXCLUDE-END-CHAR :: A character, or nil.
-* Returns
+* Return Value
 A list of strings.
 * Description
-Given a string TEXT, breaks the string into a series of
-smaller strings, none of which is longer than WIDTH. Returns the list of
+Given a string =TEXT=, breaks the string into a series of
+smaller strings, none of which is longer than =WIDTH=. Returns the list of
-If EXCLUDE-START-CHAR and EXCLUDE-END-CHAR are supplied, those characters
+If =EXCLUDE-START-CHAR= and =EXCLUDE-END-CHAR= are supplied, those characters
 will be treated as demarcating sections of the string whose length is to
-be ignored (treated as zero). This allows WORD-WRAP to correctly deal with
-strings that contain <hypertext>...</hypertext> metadata."
+be ignored (treated as zero)."
     (with counted = 0)
     (with breakpoint = nil)
     (finally (return (list text)))))
-(defparameter *unsafe-symbol-strings*
-  ;; These SEEM to only be interpreted as formatting directives when they occur
-  ;; at the beginning of words. Hence the ^ at the beginning of each regex.
-  '(("^\\*" . "\\*")  ;; bold
-    ("^/" . "\\/")    ;; italic
-    ("^\\+" . "\\+")  ;; strikethrough
-    ("^_" . "\\_")    ;; underline
-    ("^=" . "\\="))   ;; code
-  "Alist of (REGEX . REPLACEMENT). Used to ensure that symbols do not
-contain any characters which org will misinterpret as formatting directives.")
+;; (eval-when (:compile-toplevel :load-toplevel :execute)
+;;   (defparameter *unsafe-symbol-strings*
+;;     ;; These SEEM to only be interpreted as formatting directives when they occur
+;;     ;; at the beginning of words. Hence the ^ at the beginning of each regex.
+;;     '(("^\\*" . "\\*")  ;; bold
+;;       ("^/" . "\\/")    ;; italic
+;;       ("^\\+" . "\\+")  ;; strikethrough
+;;       ("^_" . "\\_")    ;; underline
+;;       ("^=" . "\\="))   ;; code
+;;     "Alist of =(REGEX . REPLACEMENT)= cons pairs. Used to ensure that symbols
+;; do not contain any characters which org will misinterpret as formatting
+;; directives.
+;; See also: [[org-safe-symbol]]."))
-(defun safe-symbol (sym)
-  (unless (stringp sym)
-    (setf sym (format nil "~A" sym)))
-  (iterate
-    (for (regex . replacement) in *unsafe-symbol-strings*)
-    (setf sym (regex-replace-all regex sym replacement)))
-  sym)
+(eval-when (:compile-toplevel :load-toplevel :execute)
+  (defun org-safe-symbol (sym)
+    "* Usage
+: (org-safe-symbol SYM)
+* Arguments
+- SYM :: A symbol.
+* Return Value
+A string.
+* Description
+Given the symbol SYM, return a string that represents SYM in a form that is
+human-readable and where org will not be confused by any characters that
+might represent markup instructions."
+    (format nil "=~A=" sym)))
+    ;; (unless (stringp sym)
+    ;;   (setf sym (format nil "~A" sym)))
+    ;; (iterate
+    ;;   (for (regex . replacement) in *unsafe-symbol-strings*)
+    ;;   (setf sym (regex-replace-all regex sym replacement)))
+    ;; sym))
+(defparameter *unsafe-html-chars*
+  '(#\< #\> #\= #\% #\? #\+ #\$ #\/ #\& #\@ #\, #\{ #\} #\^ #\~)
+  "List of characters which are unsafe within HTML links and anchors, and
+which need to be converted to a safe representation.
+See also: [[html-safe-string]].")
+(defun html-safe-string (str)
+  "Usage
+: (html-safe-string STR)
+* Arguments
+- STR :: A string.
+* Returns
+A string.
+* Description
+Given a string which is intended as a link target, return a copy in which we
+remove or alter any unsafe characters that will stop the link working properly
+when the document is exported to HTML.
+* See Also
+- [[*unsafe-html-chars*]]"
+  ;; If the link contains ':' then it represents a URL or other special
+  ;; link, and is left alone.
+  (cond
+    ((find #\: str)
+     str)
+    (t
+     (string-downcase
+      (apply #'concatenate
+             'string
+             (iterate
+               (for c in-string str)
+               (if (find c *unsafe-html-chars*)
+                   (collect (format nil "..~2X.." (char-code c)))
+                   (collect (make-string 1 :initial-element c)))))))))
 ;;;; Formatting  ==============================================================
-(defun write-preamble (&key (title "Documentation"))
-  (write-out "~&#+TITLE: ~A" title)
+(defun write-preamble ()
+  "* Usage
+: (write-preamble)
+* Arguments
+* Return Value
+* Description
+Writes some org instructions, intended to be placed at the start of the
+document. These specify the document's author, title, and set some
+export options."
+  (write-out "~&#+TITLE: ~A" *document-title*)
+  (write-out "~&#+AUTHOR: ~A" *document-author*)
+  (write-out "~&#+EMAIL: ~A" *document-email*)
   (write-out "~&#+LINK: hs ~A/%s" (if (eql 0 (search "http:" *hyperspec-root*))
                                       (format nil "file:~A" *hyperspec-root*)))
-  (write-out "~&#+OPTIONS: toc:3 H:10~%~%"))
+  (write-out "~&#+STARTUP: showall")
+  ;; H:NNN = below this many levels deep, headings become bulleted lists
+  ;; toc:NNN = go this many levels deep in table of contents
+  (write-out "~&#+OPTIONS: toc:3 H:10 @:t tags:nil~%~%"))
+(defmacro writing-section ((title) &body body)
+  `(let* ((*heading-level* (1+ *heading-level*))
+          (%title ,title))
+     (write-heading (format nil "~:(~A~)" %title))
+     ,@body
+     (terpri *out*)))
+(defmacro writing-section-for-symbol ((entity sym) &body body)
+  `(let* ((*heading-level* (1+ *heading-level*))
+          (%entity ,entity)
+          (%sym ,sym)
+          (str (format nil "~:(~A~A~): ~(~A~)"
+                       (if (symbol-accessibility %sym)
+                           (format nil "~A " (symbol-accessibility %sym))
+                           "")
+                       (entity->string %entity)
+                       (org-safe-symbol %sym))))
+     ;; Note: targets are situated *before* the heading, otherwise the heading
+     ;; is not actually visible when jumping here in HTML
+     (if (null (cdr (uses-for-symbol %sym)))   ;; only 1 use - unambiguous
+         (format *out* "# link target 2: ~A~%"
+                 (make-target %sym)))
+     (format *out* "# link target: ~A~%~%" (make-target %sym %entity))
+     (write-heading (format nil "~A~V<~A~>" str
+                            (- *line-width* (length str))
+                            (format nil ":~A:"
+                                    (entity->tag %entity))))
+     ,@body
+     (terpri *out*)))
+(defun write-chapter (symlist entity title)
+  "* Usage
+: (write-chapter SYMLIST ENTITY TITLE)
+* Arguments
+- SYMLIST :: A list of symbols.
+- ENTITY :: An [[=entity=]].
+- TITLE :: A string.
+* Return Value
+* Description
+Writes the section of the document which describes all entities of
+type =ENTITY=. =SYMLIST= should be a list of all the symbols that
+name such entities."
+  (when symlist
+    (writing-section (title)
+      (dolist (sym (sort symlist #'string< :key #'string))
+        (document sym entity)))))
 (defun write-docstring (str &key (levels *heading-level*)
                         (default "Not documented."))
+  "* Usage
+: (write-docstring STR &key LEVELS DEFAULT)
+* Arguments
+- STR :: A docstring.
+- LEVELS :: How many levels deep in the outline is
+  this docstring?
+- DEFAULT :: A string. Default text, used if =STR= is =NIL=.
+* Return Value
+* Description
+Writes the docstring STR to the document. Before doing this, processes
+the docstring to:
+- Demote headings
+- Make all hyperlinks safe for org mode and HTML export
+- Convert lines beginning with ';;;' to syntax-highlighting markup."
      (with-input-from-string (in str)
+         (with src = nil)
          (while (listen in))
          (for line = (read-line in))
          (for str =
-               (format nil "^([~A]+)([ \t]+)"
+               (format nil "^([~A]+)([ \t]+)(.*)$"
                         (format nil "~C" *heading-char*)))
-               (lambda (match match1 &rest matches)
-                 (declare (ignore match matches))
-                 (format nil "~A "
+               (lambda (match match1 match2 match3 &rest matches)
+                 (declare (ignore match match2 matches))
+                 (format nil "~A ~A~%"
                          (make-string (+ (length match1)
                                          (1- levels))
-                                      :initial-element *heading-char*)))
+                                      :initial-element *heading-char*)
+                         match3))
                :simple-calls t))
-         (format *out* "~A~%" str))))
+         (setf str (regex-replace-all "\\[\\[([^]]*)\\]\\["
+                                      str
+                                      (lambda (match match1 &rest matches)
+                                        (declare (ignore match matches))
+                                        (format nil "[[~A]["
+                                                (html-safe-string match1)))
+                                      :simple-calls t))
+         (setf str (regex-replace-all "\\[\\[([^]]*)\\]\\]"
+                                      str
+                                      (lambda (match match1 &rest matches)
+                                        (declare (ignore matches))
+                                        (let ((safe (html-safe-string match1)))
+                                          (cond
+                                            ((string= safe match1)
+                                             match)
+                                            (t
+                                             (format nil "[[~A][~A]]"
+                                                     safe match1)))))
+                                      :simple-calls t))
+         (cond
+           ((eql 0 (search ";;;" str))
+            (unless src
+              (setf src t)
+              (format *out* "#+BEGIN_SRC lisp~%"))
+            (setf str (subseq str 3)))
+           (t
+            (when src
+              (setf src nil)
+              (format *out* "#+END_SRC~%"))))
+         (format *out* "~A~%" str)
+         (finally
+          (if src
+              (format *out* "#+END_SRC~%"))))))
      (format *out* "~A~%" default))))
 (defmacro write-indented ((indent) &body body)
+  "* Usage
+: (write-indented (INDENT)
+:    ...body...)
+* Arguments
+- INDENT :: An integer.
+* Return Value
+* Description
+All text that is written within the body of the form will be indented
+a further =INDENT= spaces from the left margin."
   `(let ((*left-margin* (+ *left-margin* ,indent)))
+(defun wrap-and-write (fmt &rest args)
+  (let ((lines (word-wrap (apply #'format nil fmt args) :width *line-width*)))
+    (dolist (line lines)
+      (write-out line))
+    (terpri *out*)))
+(defun wrap-and-write-code (fmt &rest args)
+  (let ((lines (word-wrap (apply #'format nil fmt args)
+                          :width (- *line-width* 2))))
+    (dolist (line lines)
+      (format *out* ": ~A~%" line))
+    (terpri *out*)))
 (defun write-out (fmt &rest args)
   (fresh-line *out*)
   (princ (make-string *left-margin* :initial-element #\space) *out*)
 (defun write-heading (title)
-  (format *out* "~%~A ~A~%~%"
+  (format *out* "~&~%~A ~A~%~%"
            (make-string *heading-level* :initial-element *heading-char*)
-(defun make-link (str &key text linktype)
-  (when linktype
-      (unless text
-        (setf text str))
-      (setf str (concatenate 'string (string linktype) " " (string str)))
-      (unless text
-        (setf text str)))
+(defgeneric make-link (target entity &key text)
+  (:documentation
+   "* Arguments
+- TARGET :: A symbol, string, or other value that constitutes the target of the
+  link.
+- ENTITY :: An [[=entity=]].
+- TEXT :: An optional string, used for the appearance of the link. The default
+  is a direct textual representation of =TARGET=.
+* Returns
+A string.
+* Description
+Given a target and text, return a string that will be interpreted by org mode as
+a hyperlink leading to the documentation for =TARGET=."))
+(defmethod make-link ((str string) (entity null) &key text)
      (format nil "~([[~A][~A]]~)" str text))
      (format nil "~([[~A]]~)" str))))
-(defmethod make-class-link ((sym symbol))
-  (make-link sym :linktype :class))
+(defmethod make-link ((str string) (entity symbol) &key text)
+  (unless text (setf text str))
+  (let ((link (html-safe-string (concatenate 'string (string entity) " " str))))
+    (format nil "~([[~A][~A]]~)" link text)))
-(defmethod make-class-link ((str string))
-  (make-link str :linktype :class))
-(defmethod make-class-link ((c class))
-  (make-link (class-name c) :linktype :class))
+(defmethod make-link ((sym symbol) (entity t) &key text)
+  (make-link (string sym) entity
+             :text (or text
+                       (format nil "=~S="
+                               sym))))
-(defmethod make-class-link ((o standard-object))
-  (make-link (class-name (class-of o)) :linktype :class))
-(defmethod make-class-link ((c eql-specializer))
+(defmethod make-link ((c class) (entity (eql :class))  &key text)
+  (make-link (class-name c) :class :text text))
+(defmethod make-link ((o standard-object) (entity (eql :class))  &key text)
+  (make-link (class-name (class-of o)) :class :text text))
+(defmethod make-link ((c eql-specializer) (entity (eql :class))  &key text)
+  (declare (ignore text))
   (format nil "~S" `(eql ,(eql-specializer-object c))))
+(defun make-class-link (x &key text)
+  (make-link x :class :text text))
 (defun make-package-link (sym)
-  (make-link sym :linktype :package))
+  (make-link sym :package))
 (defun write-list-as-paragraph (ls)
-  (dolist (line (word-wrap 
-                 (list->string-with-commas ls)
-                 :width *line-width*))
-    (write-out line)))
+  (wrap-and-write (list->string-with-commas ls)))
-(defmacro writing-section ((entity &optional sym) &body body)
-    `(let* ((*heading-level* (1+ *heading-level*))
-            (%title ,entity)
-            (%entity %title))
-       (declare (ignorable %entity %title))
-       ,(if sym
-            `(let ((str (format nil "~:(~A~): ~(~A~)"
-                                (entity->string %entity) ,sym)))
-               (write-heading (format nil "~A~V<~A~>" str
-                                      (- *line-width* (length str))
-                                      (format nil ":~A:"
-                                              (entity->tag %entity))))
-               (write-out "# link target: ~A~%~%" (make-target ,sym %entity)))
-            `(write-heading (format nil "~:(~A~)" %title)))
-       ;; ,@(if sym
-       ;;       `((format *out* "  :PROPERTIES:~%")
-       ;;         (format *out* "  :CATEGORY: ~A~%" ,title)
-       ;;         (format *out* "  :END:~%~%")))
-       ,@body
-       (terpri *out*)))
 (defun write-docstring-section (title docstr)
   (if (and (stringp docstr)
            (eql 0 (search (format nil "~C " *heading-char*) docstr)))
-      (write-docstring docstr :levels (1+ *heading-level*))
+      (let ((*heading-level* (1+ *heading-level*)))
+        (write-docstring docstr :levels (1+ *heading-level*)))
+      ;; else
       (writing-section (title)
         (write-docstring docstr))))
 (defun make-target (sym &optional entity)
-  (if entity
-      (format nil "~(<<~A ~A>>~)" entity sym)
-      (format nil "~(<<~A>>~)" sym)))
+  (let ((target-start (if *auto-links* "<<<" "<<"))
+        (target-end (if *auto-links* ">>>" ">>"))
+        (sym (string sym)))
+    (if entity
+        (format nil "~(~A~A~A~)" target-start
+                (html-safe-string (format nil "~A ~A" entity sym))
+                target-end)
+        (format nil "~(~A~A~A~)" target-start (html-safe-string sym)
+                target-end))))
 (defmacro writing-bulleted-list (&body body)
 (defun write-bullet-point (fmt &rest args)
-  (apply #'format *out* (concatenate 'string "~&- " fmt "~&") args))
+  ;; (concatenate 'string "~&- " fmt "~&")
+  (let* ((str (apply #'format nil fmt args))
+         (lines (word-wrap str :width (- *line-width* 2))))
+    (write-out "~&- ~A~%" (car lines))
+    (write-indented (2)
+      (dolist (line (cdr lines))
+        (write-out "~A~%" line)))))
-(defun write-index (pkg &optional (accessibility :external))
+(defun write-index (pkg &optional (accessibilities (list :internal :external)))
   (let ((symbols nil)
         (index-table (make-hash-table :test 'eql)))
     (do-own-symbols (sym pkg)
-      (when (and (eql (symbol-accessibility sym pkg) accessibility)
+      (when (and (or (null accessibilities)
+                     (find (symbol-accessibility sym pkg) accessibilities))
                  (uses-for-symbol sym))
         (push sym symbols)))
     (setf symbols (sort symbols #'string>))
     (writing-section ("Index")
-      (dolist (line
-                (word-wrap
-                 (format nil
-                         "~%~{~A  ~}~%"
-                         (iterate
-                           (for (ch nil) in-hashtable index-table)
-                           (collect (format nil "[[index ~A][~A]]" ch ch))))
-                 :width *line-width*))
-        (write-out line))
+      (wrap-and-write 
+       (format nil
+               "~%~{~A  ~}~%"
+               (iterate
+                 (for (ch nil) in-hashtable index-table)
+                 (collect (format nil "[[index ~A][~A]]" ch ch)))))
-        (for ch in (cons 'nonalphabetic +alphabet+))
+        (for ch in (cons 'nonalphabetic *alphabet*))
         (for syms = (gethash ch index-table))
         (when syms
           (writing-section ((format nil "~A" ch))
                   (for use in (uses-for-symbol sym))
                    "~A, ~:(~A~)"
-                   (make-link (string sym) :linktype use)
+                   (make-link sym use)
                    (entity->string use)))))))))))
         (for use in uses)
         (write-bullet-point "~:(~A~): ~A" (entity->string use)
-                             (make-link (string sym) :linktype use)))))))
+                             (make-link sym use)))))))
 (defmethod document :after ((sym symbol) (doctype t))
   (terpri *out*))
-(defmethod document ((sym symbol) (doctype (eql 'function)))
-  (writing-section (:function sym)
+(defmethod document :before ((sym symbol) (doctype t))
+  (unless (or (not *lines-between-sections*)
+              (eql doctype :method))
+    (format *out* "~&-----~%")))
+(defmethod document ((sym symbol) (doctype (eql :function)))
+  (writing-section-for-symbol (:function sym)
     ;; We don't impose any structure (headings) on FUNCTION docstrings,
     ;; because functions are pretty opaque. It is up to the user to
     ;; write everything in the docstring.
-    (write-docstring (documentation sym 'function))))
+    (let ((*heading-level* (1+ *heading-level*)))
+      (write-docstring (documentation sym 'function)))))
-(defmethod document ((sym symbol) (doctype (eql 'macro)))
-  (writing-section (:macro sym)
+(defmethod document ((sym symbol) (doctype (eql :macro)))
+  (writing-section-for-symbol (:macro sym)
     ;; The same goes for macros.
-    (write-docstring (documentation sym 'function))))
+    (let ((*heading-level* (1+ *heading-level*)))
+      (write-docstring (documentation sym 'function)))))
-(defmethod document ((sym symbol) (doctype (eql 'var)))
-  (writing-section (:variable sym)
+(defmethod document ((sym symbol) (doctype (eql :type)))
+  (writing-section-for-symbol (:type sym)
+    ;; The same goes for macros.
+    (let ((*heading-level* (1+ *heading-level*)))
+      (write-docstring (documentation sym 'type)))))
+(defmethod document ((sym symbol) (doctype (eql :variable)))
+  (writing-section-for-symbol (:variable sym)
     (writing-section ("Value")
         ((boundp sym)
-         (format *out* "~S~%" (symbol-value sym))
-         (format *out* "Type: ~(~A~)~%" (type->string (type-of (symbol-value sym)))))
+         (wrap-and-write-code "~S" (symbol-value sym))
+         (format *out* "Type: ~(~A~)~%"
+                 (org-safe-symbol (type->string (type-of (symbol-value sym))))))
          (format *out* "Unbound.~%"))))
     (write-docstring-section "Description" (documentation sym 'variable))))
-(defmethod document ((sym symbol) (doctype (eql 'constant)))
-  (writing-section (:constant sym)
+(defmethod document ((sym symbol) (doctype (eql :constant)))
+  (writing-section-for-symbol (:constant sym)
     (writing-section ("Value")
         ((boundp sym)
-         (format *out* "~S~%" (symbol-value sym))
-         (format *out* "Type: ~(~A~)~%" (type->string (type-of (symbol-value sym)))))
+         (wrap-and-write-code "~S" (symbol-value sym))
+         (format *out* "Type: ~(~A~)~%"
+                 (org-safe-symbol (type->string (type-of (symbol-value sym))))))
          (format *out* "Unbound.~%"))))
     (write-docstring-section "Description" (documentation sym 'variable))))
-(defmethod document ((sym symbol) (doctype (eql 'generic)))
+(defmethod document ((sym symbol) (doctype (eql :generic)))
   (let ((gf (symbol-function sym)))
-    (writing-section (:generic-function sym)
+    (writing-section-for-symbol (:generic-function sym)
       (writing-section ("Usage")
         (format *out* "~((~A~{ ~A~})~)~%"
-                sym
+                (org-safe-symbol sym)
                 (generic-function-lambda-list gf)))
       (write-docstring-section "Description" (documentation gf t))
       ;; No portable way for method-combination objects to introspect.
       ;;        (generic-function-method-combination gf))
       (writing-section ("Methods")
         (dolist (m (generic-function-methods gf))
-          (document m 'method))))))
+          (document m :method))))))
-(defmethod document ((sym symbol) (doctype (eql 'slot-reader)))
+(defmethod document ((sym symbol) (doctype (eql :slot-reader)))
   (let ((gf (symbol-function sym)))
-    (writing-section (:slot-reader sym)
+    (writing-section-for-symbol (:slot-reader sym)
       (writing-section ("Usage")
         (format *out* "~((~A~{ ~A~})~)~%"
-                sym
+                (org-safe-symbol sym)
                 (generic-function-lambda-list gf)))
       (when (documentation gf t)
         (write-docstring-section "Description" (documentation gf t)))
       (writing-section ("Methods")
         (dolist (m (generic-function-methods gf))
-          (document m 'method))))))
+          (document m :method))))))
-(defmethod document ((sym symbol) (doctype (eql 'slot-writer)))
+(defmethod document ((sym symbol) (doctype (eql :slot-writer)))
   (let ((gf (symbol-function sym)))
-    (writing-section (:slot-writer sym)
+    (writing-section-for-symbol (:slot-writer sym)
       (writing-section ("Usage")
         (format *out* "~((~A~{ ~A~})~)~%"
-                sym
+                (org-safe-symbol sym)
                 (generic-function-lambda-list gf)))
       (when (documentation gf t)
         (write-docstring-section "Description" (documentation gf t)))
       (writing-section ("Methods")
         (dolist (m (generic-function-methods gf))
-          (document m 'method))))))
+          (document m :method))))))
-(defmethod document ((sym symbol) (doctype (eql 'slot-accessor)))
+(defmethod document ((sym symbol) (doctype (eql :slot-accessor)))
   (let ((gf (symbol-function sym)))
-    (writing-section (:slot-accessor sym)
+    (writing-section-for-symbol (:slot-accessor sym)
       (writing-section ("Usage")
         (format *out* "~((~A~{ ~A~})~)~%"
-                sym
+                (org-safe-symbol sym)
                 (generic-function-lambda-list gf)))
       (when (documentation gf t)
         (write-docstring-section "Description" (documentation gf t)))
       (writing-section ("Methods")
         (dolist (m (generic-function-methods gf))
-          (document m 'method))))))
+          (document m :method))))))
-(defmethod document ((m standard-method) (doctype (eql 'method)))
+(defmethod document ((m cl:standard-method) (doctype (eql :method)))
   ;; Methods are just briefly documented, 1-2 lines each.
-  (write-bullet-point
-   "(~(~A~A~{ ~A~}~))"
-   (generic-function-name (method-generic-function m))
-   (if (method-qualifiers m)
-       (format nil "~{ ~S~}" (method-qualifiers m))
-       "")
-   (make-specialised-lambda-list 
-    (method-lambda-list m)
-    (method-specializers m)))
-  (if (and (slot-exists-p m 'documentation)
-           (slot-boundp m 'documentation)
-           (documentation m t))
-      (write-indented (4)
-        (write-docstring (documentation m t)))))
+  ;; Note 'cl:standard-method' above. Avoids problems with
+  ;; assuming that all methods are closer-mop:standard-method instances.
+  (let* ((method-name (generic-function-name (method-generic-function m)))
+         (method-usage
+          (format nil
+                  "(~(~A~A~{ ~A~}~))"
+                  (org-safe-symbol method-name)
+                  (if (method-qualifiers m)
+                      (format nil "~{ ~S~}" (method-qualifiers m))
+                      "")
+                  (make-specialised-lambda-list 
+                   (method-lambda-list m)
+                   (method-specializers m)))))
+    (cond
+      (*brief-methods*
+       (write-bullet-point method-usage)
+       (if (and (slot-exists-p m 'documentation)
+                (slot-boundp m 'documentation)
+                (documentation m t))
+           (write-indented (4)
+             (write-docstring (documentation m t)))))
+      (t
+       (writing-section ((format nil "Method: ~A~A~S" method-name
+                                 (if (method-qualifiers m)
+                                     (format nil "~{ ~S~}"
+                                             (method-qualifiers m))
+                                     "")
+                                 (method-specializers m)))
+         (if (and (slot-exists-p m 'documentation)
+                  (slot-boundp m 'documentation)
+                  (documentation m t))
+             (write-docstring-section "Description"
+                                      (documentation m t))))))))
-(defmethod document ((m cl:standard-method) (doctype (eql 'method)))
-  (write-bullet-point
-   "(~(~A~A~{ ~A~}~))"
-   (generic-function-name (method-generic-function m))
-   (if (method-qualifiers m)
-       (format nil "~{ ~S~}" (method-qualifiers m))
-       "")
-   (make-specialised-lambda-list 
-    (method-lambda-list m)
-    (method-specializers m)))
-  (if (and (slot-exists-p m 'documentation)
-           (slot-boundp m 'documentation)
-           (documentation m t))
-      (write-indented (4)
-        (write-docstring (documentation m t)))))
+;; (defmethod document ((m standard-method) (doctype (eql :method)))
+;;   (write-bullet-point
+;;    "(~(~A~A~{ ~A~}~))"
+;;    (safe-symbol (generic-function-name (method-generic-function m)))
+;;    (if (method-qualifiers m)
+;;        (format nil "~{ ~S~}" (method-qualifiers m))
+;;        "")
+;;    (make-specialised-lambda-list 
+;;     (method-lambda-list m)
+;;     (method-specializers m)))
+;;   (if (and (slot-exists-p m 'documentation)
+;;            (slot-boundp m 'documentation)
+;;            (documentation m t))
+;;       (write-indented (4)
+;;         (write-docstring (documentation m t)))))
-(defmethod document ((sym symbol) (doctype (eql 'class)))
-  (let* ((c (find-class sym))
-         (struct? (typep c (find-class 'structure-class))))
-    (writing-section ((if struct? :structure :class) sym)
+(defmethod document ((sym symbol) (doctype (eql :class)))
+  (let* ((c (find-class sym)))
+    (writing-section-for-symbol (:class sym)
         (unless (class-finalized-p c)
           (error "Not finalised"))
-        (unless struct?
-          (writing-section ("Inheritance")
-            ;; todo word wrap these
-            (write-bullet-point "Parent classes:")
-            (write-indented (4)
-              (write-list-as-paragraph
-               (or
-                (mapcar #'make-class-link
-                        (mapcar
-                         #'string-downcase
-                         (mapcar
-                          #'class-name
-                          (class-direct-superclasses c))))
-                (list "None."))))
-            (write-bullet-point "Precedence list:")
-            (write-indented (4)                
-              (write-list-as-paragraph
-               (or
-                (mapcar #'make-class-link
-                        (mapcar
-                         #'string-downcase
-                         (mapcar
-                          #'class-name
-                          (class-precedence-list c))))
-                (list "None."))))
-            (write-bullet-point "Direct subclasses:")
-            (write-indented (4)                
-              (write-list-as-paragraph
-               (or 
-                (mapcar #'make-class-link
-                        (mapcar
-                         #'string-downcase
-                         (mapcar
-                          #'class-name
-                          (class-direct-subclasses c))))
-                (list "None."))))))
+        (writing-section ("Inheritance")
+          (write-bullet-point "Parent classes:")
+          (write-indented (4)
+            (write-list-as-paragraph
+             (or
+              (mapcar #'make-class-link
+                      (mapcar
+                       #'string-downcase
+                       (mapcar
+                        #'class-name
+                        (class-direct-superclasses c))))
+              (list "None."))))
+          (write-bullet-point "Precedence list:")
+          (write-indented (4)                
+            (write-list-as-paragraph
+             (or
+              (mapcar #'make-class-link
+                      (mapcar
+                       #'string-downcase
+                       (mapcar
+                        #'class-name
+                        (class-precedence-list c))))
+              (list "None."))))
+          (write-bullet-point "Direct subclasses:")
+          (write-indented (4)                
+            (write-list-as-paragraph
+             (or 
+              (mapcar #'make-class-link
+                      (mapcar
+                       #'string-downcase
+                       (mapcar
+                        #'class-name
+                        (class-direct-subclasses c))))
+              (list "None.")))))
         (write-docstring-section "Description" (documentation c t))
         (writing-section ("Direct slots")
           (dolist (slot (class-direct-slots c))
-            (document slot 'slot)))
+            (document slot :slot)))
         (when (list-all-indirect-slots (list c))
           (writing-section ("Indirect slots")
             (dolist (slot (list-all-indirect-slots (list c)))
-              (document slot 'slot))))))))
+              (document slot :slot))))))))
+(defmethod document ((sym symbol) (doctype (eql :structure)))
+  (let* ((c (find-class sym)))
+    (writing-section-for-symbol (:structure sym)
+      (progn
+        (unless (class-finalized-p c)
+          (error "Not finalised"))
+        (write-docstring-section "Description" (documentation c t))
+        (writing-section ("Slots")
+          (dolist (slot (class-direct-slots c))
+            (document slot :slot)))))))
+;; Structs have the following associated functions: (might NOT be methods)
+;;    CONCNAME-SLOTNAME readers (where CONCNAME defaults to STRUCTNAME)
+;;    make-STRUCTNAME
+;;    copy-STRUCTNAME
 (defmethod document :around ((slot slot-definition)
-                             (doctype (eql 'slot)))
-  (writing-section (:slot (slot-definition-name slot))
+                             (doctype (eql :slot)))
+  (writing-section-for-symbol (:slot (slot-definition-name slot))
      (write-bullet-point "Value type: ~(~A~)"
-                         (slot-definition-type slot))
-     (write-bullet-point "Initial value: ~(~S~)"
+                         (org-safe-symbol
+                          (type->string (slot-definition-type slot))))
+     (write-bullet-point "Initial value: =~S="
                          (slot-definition-initform slot))
      (write-bullet-point "Initargs: ~(~A~)"
                          (if (slot-definition-initargs slot)
 (defmethod document ((slot effective-slot-definition)
-                     (doctype (eql 'slot)))
+                     (doctype (eql :slot)))
   ;; These seem to be 'indirect' slots? They lack a lot of
   ;; information.
 (defmethod document ((slot direct-slot-definition)
-                     (doctype (eql 'slot)))
+                     (doctype (eql :slot)))
   (let* ((accessors (union (slot-definition-readers slot)
                            (slot-definition-writers slot)))
          (readers (set-difference (slot-definition-readers slot)
     (when (remove-if #'listp accessors)
       (writing-section ("Accessors")
         (dolist (fname (remove-if #'listp accessors))
-          (document fname 'slot-accessor))))
+          (document fname :slot-accessor))))
     (when readers
       (writing-section ("Readers")
         (dolist (fname readers)
-          (document fname 'slot-reader))))
+          (document fname :slot-reader))))
     (when writers
       (writing-section ("Writers")
         (dolist (fname writers)
-          (document fname 'slot-writer))))))
+          (document fname :slot-writer))))))
 ;;;; Toplevel =================================================================
-(defmacro do-own-symbols ((var pkg) &body body)
-  `(let ((%shadow-symbols (package-shadowing-symbols ,pkg)))
-     (do-symbols (,var ,pkg)
-       (unless (find ,var %shadow-symbols)
-         ,@body))))
-(defun document-package-contents (pkg &optional (accessibility :external))
+(defun document-package-contents (pkg &optional (accessibilities
+                                                 (list :internal :external)))
+  "* Usage