TIVI-153: add as dependency for iputils 92/1592/1 accepted/trunk/20120904.191431 submit/trunk/20120831.192937
authorGraydon, Tracy <tracy.graydon@intel.com>
Fri, 31 Aug 2012 19:29:30 +0000 (12:29 -0700)
committerGraydon, Tracy <tracy.graydon@intel.com>
Fri, 31 Aug 2012 19:29:30 +0000 (12:29 -0700)
70 files changed:
BUGS [new file with mode: 0644]
COPYING [new file with mode: 0644]
ChangeLog [new file with mode: 0644]
DOC/ChangeLog [new file with mode: 0644]
DOC/Extras/README [new file with mode: 0644]
DOC/Extras/docbook.dcl [new file with mode: 0644]
DOC/Extras/docbook.dtd [new file with mode: 0644]
DOC/Extras/isonum.ent [new file with mode: 0644]
DOC/Extras/isopub.ent [new file with mode: 0644]
DOC/HTML/SGMLSpm/bugs.html [new file with mode: 0644]
DOC/HTML/SGMLSpm/definition.html [new file with mode: 0644]
DOC/HTML/SGMLSpm/events.html [new file with mode: 0644]
DOC/HTML/SGMLSpm/example.html [new file with mode: 0644]
DOC/HTML/SGMLSpm/extend.html [new file with mode: 0644]
DOC/HTML/SGMLSpm/perl5.html [new file with mode: 0644]
DOC/HTML/SGMLSpm/sample.pl [new symlink]
DOC/HTML/SGMLSpm/sgml.html [new file with mode: 0644]
DOC/HTML/SGMLSpm/sgmls.html [new file with mode: 0644]
DOC/HTML/SGMLSpm/sgmlsattribute.html [new file with mode: 0644]
DOC/HTML/SGMLSpm/sgmlselement.html [new file with mode: 0644]
DOC/HTML/SGMLSpm/sgmlsentity.html [new file with mode: 0644]
DOC/HTML/SGMLSpm/sgmlsevent.html [new file with mode: 0644]
DOC/HTML/SGMLSpm/sgmlsnotation.html [new file with mode: 0644]
DOC/HTML/SGMLSpm/sgmlspm.html [new file with mode: 0644]
DOC/HTML/SGMLSpm/sgmlspm.refs [new file with mode: 0644]
DOC/HTML/SGMLSpm/terms.html [new file with mode: 0644]
DOC/HTML/SGMLSpm/xtrainfo.html [new file with mode: 0644]
DOC/HTML/sgmlspl/bugs.html [new file with mode: 0644]
DOC/HTML/sgmlspl/definition.html [new file with mode: 0644]
DOC/HTML/sgmlspl/dsssl.html [new file with mode: 0644]
DOC/HTML/sgmlspl/forward.html [new file with mode: 0644]
DOC/HTML/sgmlspl/generic.html [new file with mode: 0644]
DOC/HTML/sgmlspl/handlers.html [new file with mode: 0644]
DOC/HTML/sgmlspl/installation.html [new file with mode: 0644]
DOC/HTML/sgmlspl/output.html [new file with mode: 0644]
DOC/HTML/sgmlspl/outputex.html [new file with mode: 0644]
DOC/HTML/sgmlspl/popoutput.html [new file with mode: 0644]
DOC/HTML/sgmlspl/pushoutput.html [new file with mode: 0644]
DOC/HTML/sgmlspl/sgmlspl.html [new file with mode: 0644]
DOC/HTML/sgmlspl/sgmlspl.refs [new file with mode: 0644]
DOC/HTML/sgmlspl/skel.html [new file with mode: 0644]
DOC/HTML/sgmlspl/specific.html [new file with mode: 0644]
DOC/HTML/sgmlspl/specs.html [new file with mode: 0644]
DOC/HTML/sgmlspl/terms.html [new file with mode: 0644]
DOC/LaTeX/sample.pl [new symlink]
DOC/LaTeX/sgmlspl.refs [new file with mode: 0644]
DOC/LaTeX/sgmlspl.tex [new file with mode: 0644]
DOC/LaTeX/sgmlspm.refs [new file with mode: 0644]
DOC/LaTeX/sgmlspm.tex [new file with mode: 0644]
DOC/Makefile [new file with mode: 0644]
DOC/README [new file with mode: 0644]
DOC/TODO [new file with mode: 0644]
DOC/sample.pl [new file with mode: 0644]
DOC/sgmlspl.sgml [new file with mode: 0644]
DOC/sgmlspm.sgml [new file with mode: 0644]
DOC/tohtml.pl [new file with mode: 0644]
DOC/tolatex.pl [new file with mode: 0644]
Makefile [new file with mode: 0644]
Output.pm [new file with mode: 0644]
README [new file with mode: 0644]
Refs.pm [new file with mode: 0644]
SGMLS.pm [new file with mode: 0644]
TODO [new file with mode: 0644]
elisp/README [new file with mode: 0644]
elisp/sgmls.el [new file with mode: 0644]
packaging/perl-SGMLSpm.changes [new file with mode: 0644]
packaging/perl-SGMLSpm.spec [new file with mode: 0644]
sgmlspl.pl [new file with mode: 0755]
skel.pl [new file with mode: 0644]
test-SGMLS.pl [new file with mode: 0644]

diff --git a/BUGS b/BUGS
new file mode 100644 (file)
index 0000000..77c688c
--- /dev/null
+++ b/BUGS
@@ -0,0 +1,7 @@
+SGMLS.pm: Known bugs.
+
+- currently, escaped sequences for SDATA, record-ends, and octal
+characters are _not_ processed in attribute values.  I will add this
+capability in the future, but it is not obvious how I should do it.
+
+- link attributes are currently ignored.
\ No newline at end of file
diff --git a/COPYING b/COPYING
new file mode 100644 (file)
index 0000000..e77696a
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,339 @@
+                   GNU GENERAL PUBLIC LICENSE
+                      Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+                          675 Mass Ave, Cambridge, MA 02139, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+                           Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  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
+this service 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 make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  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.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+\f
+                   GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute 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 and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+\f
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+\f
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+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
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+\f
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the 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 a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+                           NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+                    END OF TERMS AND CONDITIONS
+\f
+           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
+convey 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) 19yy  <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 2 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
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    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, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) 19yy name of author
+    Gnomovision 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, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This 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 Library General
+Public License instead of this License.
diff --git a/ChangeLog b/ChangeLog
new file mode 100644 (file)
index 0000000..ec9a51c
--- /dev/null
+++ b/ChangeLog
@@ -0,0 +1,119 @@
+Tue Dec  5 07:18:09 1995  David Megginson <david@baeda.english.uottawa.ca>
+
+* VERSION 1.03ii
+
+       * elisp/sgmls.el: Added my Gnu Emacs 19 mode for running (n)sgmls
+       with a postprocessor.
+
+       * Output.pm (push_output): For a 'handle' argument, force
+       unqualified filehandles into the caller's package (reported by
+       Rick Wong).
+
+* VERSION 1.03
+
+Sun Dec  3 11:37:08 1995  David Megginson  <david@baeda.english.uottawa.ca>
+
+       * sgmlspl.pl (main::sgml): Stopped using SGMLS_Event::key method
+       (why keep it around?).
+
+       * SGMLS.pm: Added POD documentation to the module; changed the
+       SGMLS_Event class constructor so that it does not take an explicit
+       key argument (the key will be generated automatically if needed),
+       and propagated the change throughout the module.
+
+Sat Dec  2 21:24:05 1995  David Megginson  <david@baeda.english.uottawa.ca>
+
+       * Refs.pm: Added POD documentation to the module.
+
+       * Output.pm: Added POD documentation to the module.
+
+Thu Nov 16 06:52:46 1995  David Megginson  <david@baeda.english.uottawa.ca>
+
+       * Refs.pm: Refs::warn now returns 1 if a warning was printed, or 0
+       if it was not.
+
+Wed Nov 15 13:43:10 1995  David Megginson  <david@baeda.english.uottawa.ca>
+
+       * Refs.pm: Added a new, simple package for managing references and
+       reporting any changes.
+
+       * SGMLS.pm: SGMLS::new now forces its filehandle argument into the
+       caller's package, unless it is already qualified with a package
+       name; reported by Rick Wong.
+
+       * Makefile: Install modules in ${MODULEDIR} instead of ${PERL5DIR}
+       -- that way, all add-ons can be qualified with SGMLS::.
+
+       * Output.pm: Now uses Carp.pm and Exporter.pm to be a
+       better-behavied module.  The symbols "output", "push_output", and
+       "pop_output" will be exported into the caller's package rather
+       than main::, and the caller will have some control over them.
+
+       Changed the package from Output to SGMLS::Output.pm.
+
+       * skel.pl: Use SGMLS::Output instead of Output.
+
+       * sgmlspl.pl: Altered to create the SGMLS object with main::STDIN
+       as the filehandle.  Have Output.pm export its symbols into main::
+       rather than into SGMLS_PL::.
+
+       Use SGMLS::Output instead of Output.
+
+* VERSION 1.02
+
+Thu Aug 24 10:00:52 1995  David Megginson  <david@baeda.english.uottawa.ca>
+
+       * SGMLS.pm: Added SGMLS_Event::parse to retrieve the SGMLS parent
+       class, SGMLS_Event::entity to look up an arbitrary entity, and
+       SGMLS_Event::notation to look up an arbitrary notation.
+
+       * Makefile (HTML_SOURCES): fixed faulty path, reported by Rick
+       Wong (rwong@jessica.stanford.edu).
+
+       * skel.pl: fixed bug in commented out 're' handler, reported by
+       Rick Wong (rwong@jessica.stanford.edu).
+
+       * SGMLS.pm: fixed bug in SGMLS_Attribute::set_value, reported by
+        Rick Wong (rwong@jessica.stanford.edu).
+
+       Loosened up checking of types in main loop, in case new types are
+       added in the future.
+
+       Added support for new output from NSGMLS with -h option: 'T' for
+       external text entities, new entity types 'PI', 'TEXT', and 'ID'.
+
+       Added support (not yet tested) for data entities.
+       
+
+* VERSION 1.01
+
+Sat Aug 12 09:34:40 1995  David Megginson  <david@baeda.english.uottawa.ca>
+
+       * Makefile: changed the order of the operations for make all, so
+       that the necessary files are installed _before_ trying to make the
+       documentation.  Also, introduced the target "dist" to make the
+       most current version of all the documentation.
+
+       * skel.pl: fixed the header comment for 'subdoc' handlers, and
+       added default handlers for 'end_element', 'cdata', 're',
+       'end_subdoc', and 'conforming' (reported by Rick Wong
+       <rwong@jessica.stanford.edu>).
+
+       * SGMLS.pm: fixed bugs in SGMLS_Attribute::set_value, cleaned up
+       the recognition and processing of octal escape sequences in the
+       (N)SGMLS output, and fixed a minor bug with generated-filenames in
+       the external entities (reported by Rick Wong
+       <rwong@jessica.stanford.edu>).
+
+       * sgmls.pl: changed handler patterns to allow dashes and other
+       characters in element, subdoc, and entity names, and fixed error
+       in generic start_subdoc_handler (reported by Rick Wong
+       <rwong@jessica.stanford.edu> and Alan Karben
+       <karben@nrs.dowjones.com>).
+
+       * Makefile: Corrected several typos in the "install_html" target
+       (reported by Rick Wong <rwong@jessica.stanford.edu>).  Changed the
+       perl binary location from /usr/bin/perl to /usr/local/bin/perl (I
+       am working on a slightly different system now).
+
+* VERSION 1.00 (initial release)
\ No newline at end of file
diff --git a/DOC/ChangeLog b/DOC/ChangeLog
new file mode 100644 (file)
index 0000000..92511e7
--- /dev/null
@@ -0,0 +1,55 @@
+Tue Dec  5 07:20:09 1995  David Megginson <david@baeda.english.uottawa.ca>
+
+* VERSION 1.03ii       
+
+       * Fixed typo in sgmlspl.sgml -- changed "references.hash" to
+       "references.refs" for consistency (reported by Rick Wong).
+
+* VERSION 1.03
+
+Sun Dec  3 17:03:32 1995  David Megginson  <david@baeda.english.uottawa.ca>
+
+        * tolatex.pl: Changed to use the SGMLS::Refs package.
+       
+       * tohtml.pl: Changed to use the SGMLS::Refs package.
+
+       * sgmlspl.sgml: Added documentation for the SGMLS::Refs package,
+       and fixed up references to SGMLS::Output.  List the version
+       explicitly in the title.
+
+       * sgmlspm.sgml: List the version explicitly in the title.
+
+* VERSION 1.02
+
+Thu Aug 24 10:14:09 1995  David Megginson <david@baeda.english.uottawa.ca>
+
+       * tolatex.pl and tohtml.pl: added support for wacky SYSID
+        modifications to NSGMLS.
+
+       * Makefile (clean): added $(SGMLSPL) variable, so that users can
+       specify a location for sgmlspl not in their paths (suggested by
+       Rick Wong, rwong@jessica.stanford.edu).
+
+* VERSION 1.01
+
+Sat Aug 12 09:58:17 1995  David Megginson  <david@baeda.english.uottawa.ca>
+
+       * tohtml.pl: changed entity handler to deal with funky sysids
+       from NSGMLS (this needs more work).
+
+       * Makefile (SGMLDECL): changed to
+       /usr/local/lib/sgml/sgmldecl/docbook.dcl to reflect changes in my
+       local system (your mileage may vary).
+       (clean): now _really_ cleans up.
+       (html): if the refs.pl file does not exist in the relevant
+       directory, make the HTML files _twice_.
+
+       * sgmlspl.sgml: fixed some typos with the function name sgmls()
+       instead of sgml() (reported by Rick Wong
+       <rwong@jessica.stanford.edu>).
+
+       * sgmlspm.sgml: fixed the captions on tables 1 and 2 (reported by
+        Rick Wong <rwong@jessica.stanford.edu>).
+
+
+* VERSION 1.00 (initial release)
\ No newline at end of file
diff --git a/DOC/Extras/README b/DOC/Extras/README
new file mode 100644 (file)
index 0000000..3716381
--- /dev/null
@@ -0,0 +1,4 @@
+This directory contains the Docbook 2.2.1 DTD, the ISO
+character-entity files for "Publishing" and "Numeric and Special
+Graphic", and the SGML declaration distributed with Docbook.  You will
+require these only if they are not already installed on your system.
diff --git a/DOC/Extras/docbook.dcl b/DOC/Extras/docbook.dcl
new file mode 100644 (file)
index 0000000..e78c1d7
--- /dev/null
@@ -0,0 +1,105 @@
+                      <!SGML  "ISO 8879:1986"
+
+                              CHARSET
+
+         BASESET  "ISO 646:1983//CHARSET
+                   International Reference Version (IRV)//ESC 2/5 4/0"
+         DESCSET
+                    0   9   UNUSED
+                    9   2     9
+                   11   2   UNUSED
+                   13   1    13
+                   14  18   UNUSED
+                   32  95    32
+                  127   1   UNUSED
+
+         BASESET  "ISO Registration Number 100//CHARSET
+                   ECMA-94 Right Part of Latin Alphabet Nr. 1//ESC 2/13 4/1"
+         DESCSET  
+                  128  32   UNUSED
+                  160  96   32
+
+
+                          CAPACITY SGMLREF
+
+       TOTALCAP         99000000
+       ATTCAP            1000000
+       ATTCHCAP          1000000
+       AVGRPCAP          1000000
+       ELEMCAP           1000000
+       ENTCAP            1000000
+       ENTCHCAP          1000000
+       GRPCAP            1000000
+       IDCAP            32000000
+       IDREFCAP         32000000
+  
+                           SCOPE DOCUMENT
+
+                               SYNTAX
+
+         SHUNCHAR CONTROLS   0   1   2   3   4   5   6   7   8   9
+                            10  11  12  13  14  15  16  17  18  19
+                            20  21  22  23  24  25  26  27  28  29
+                            30  31                     127 128 129
+                           130 131 132 133 134 135 136 137 138 139
+                           140 141 142 143 144 145 146 147 148 149
+                           150 151 152 153 154 155 156 157 158 159
+
+         BASESET  "ISO 646:1983//CHARSET
+                   International Reference Version (IRV)//ESC 2/5 4/0"
+         DESCSET
+                  0 128 0
+
+
+         FUNCTION
+                  RE          13
+                  RS          10
+                  SPACE       32
+                  TAB SEPCHAR  9
+
+         NAMING
+                  LCNMSTRT ""
+                  UCNMSTRT ""
+                  LCNMCHAR ".-"
+                  UCNMCHAR ".-"
+                  NAMECASE GENERAL YES
+                           ENTITY  NO
+
+         DELIM    GENERAL  SGMLREF
+                  SHORTREF SGMLREF
+
+         NAMES    SGMLREF
+
+         QUANTITY SGMLREF
+                 ATTCNT    256
+                  GRPCNT    253
+                  GRPGTCNT  253
+                  LITLEN   8092
+                  NAMELEN    44
+                  TAGLVL    100
+
+                              FEATURES
+         MINIMIZE
+                  DATATAG  NO
+                  OMITTAG  NO
+                  RANK     NO
+                  SHORTTAG YES 
+
+         LINK
+                  SIMPLE   NO
+                  IMPLICIT NO
+                  EXPLICIT NO
+
+         OTHER
+                  CONCUR   NO
+                  SUBDOC   NO
+                  FORMAL   YES
+
+                               APPINFO
+         NONE
+>
+
+<!--
+     Reference Concrete Syntax modifications for the DocBook DTD,
+                           Revision: 2.2.1
+  -->
diff --git a/DOC/Extras/docbook.dtd b/DOC/Extras/docbook.dtd
new file mode 100644 (file)
index 0000000..72eeb43
--- /dev/null
@@ -0,0 +1,2023 @@
+<!-- ===================================================================== -->
+
+<!-- 
+
+                    DocBook DTD  Revision: 2.2.1
+
+                    $Date: 1995/01/23 17:00:40 $
+
+   Copyright 1992, 1993, 1994  HaL Computer Systems, Inc., and
+     O'Reilly & Associates, Inc.
+
+   Permission to use, copy, modify and distribute the DocBook DTD and
+     its accompanying documentation for any purpose and without fee is
+     hereby granted, provided that this copyright notice appears in
+     all copies.  If you modify the DocBook DTD, rename your modified
+     version.  HaL Computer Systems, Inc., and O'Reilly & Associates,
+     Inc., make no representation about the suitability of the DTD for
+     any purpose.  It is provided "as is" without expressed or implied
+     warranty.
+
+   The DocBook DTD is maintained by HaL Computer Systems, Inc., and
+     O'Reilly & Associates, Inc.  Please direct all questions, bug
+     reports, or suggestions for changes to: davenport@ora.com or by
+     postal mail to either: Terry Allen, O'Reilly & Associates, Inc.,
+     103A Morris Street, Sebastopol, California, 95472; or Conleth
+     O'Connell, HaL Computer Systems, 3006-A Longhorn Blvd., Austin,
+     Texas, 78758.
+
+   Please note that an SGML declaration is provided for this DTD.
+     
+   Public Identifier:
+       "-//HaL and O'Reilly//DTD DocBook//EN"
+
+  -->
+
+<!-- ===================================================================== -->
+<!-- ##################################################################### -->
+<!-- ===================================================================== -->
+
+<!--
+
+       PARAMETER ENTITIES to allow inclusion of local modifications.  
+       To include your local terms, table content model, graphics 
+       format, or other local item,
+       
+       At the head of your instance, after the DOCTYPE line, include
+       a reference to an external entity file that that includes all
+       the local terms, table content models, and (or) graphics
+       formats you are using:
+
+       <!DOCTYPE Chapter SYSTEM "/yourpath/docbook.dtd" [
+       <!ENTITY % localmods SYSTEM "/yourpath/localmodfile" >
+               %localmods;
+       ]>
+
+       You may need to set up attributes for your local elements.
+       
+  -->
+
+<!-- CONTENT MODEL LOCALIZATIONS -->
+
+<!ENTITY % local.admonitions   "" >
+<!ENTITY % local.appendix      "" >
+<!ENTITY % local.book          "" >
+<!ENTITY % local.chapter       "" >
+<!ENTITY % local.cptrterms     "" >
+<!ENTITY % local.equations     "" >
+<!ENTITY % local.examples      "" >
+<!ENTITY % local.index         "" >
+<!ENTITY % local.links         "" >
+<!ENTITY % local.lists         "" >
+<!ENTITY % local.notations     "" >
+<!ENTITY % local.refclasses    "" >
+<!ENTITY % local.nav           "" >
+<!ENTITY % local.ndxterms      "" >
+<!ENTITY % local.synopsis      "" >
+<!ENTITY % local.tables                "" >
+<!ENTITY % local.terms         "" >
+
+<!-- ===================================================================== -->
+<!-- ##################################################################### -->
+<!-- ===================================================================== -->
+
+<!-- NOTATIONS -->
+
+<!NOTATION CGM-CHAR    PUBLIC "ISO 8632/2//NOTATION Character encoding//EN" >
+<!NOTATION CGM-BINARY  PUBLIC "ISO 8632/3//NOTATION Binary encoding//EN" >
+<!NOTATION CGM-CLEAR   PUBLIC "ISO 8632/4//NOTATION Clear text encoding//EN" >
+<!NOTATION DITROFF     SYSTEM "DITROFF" >
+<!NOTATION DVI         SYSTEM "DVI" >
+<!NOTATION EPS         PUBLIC "+//ISBN 0-201-18127-4::Adobe//NOTATION 
+                                PostScript Language Ref. Manual//EN" >
+<!NOTATION EQN         SYSTEM "-//AT&T//NOTATION EQN-1//EN" >
+<!NOTATION FAX         PUBLIC "-//USA-DOD//NOTATION CCITT Group 4 Facsimile
+                                Type 1 Untiled Raster//EN" >
+<!NOTATION GIF         SYSTEM "GIF" >
+<!NOTATION IGES                PUBLIC "-//USA-DOD//NOTATION (ASME/ANSI Y14.26M-1987)
+                                Initial Graphics Exchange Specification//EN" >
+<!NOTATION PIC         SYSTEM "-//AT&T//NOTATION PIC-1//EN" >
+<!NOTATION PS          SYSTEM "PS" >
+<!NOTATION TBL         SYSTEM "-//AT&T//NOTATION TBL-1//EN" >
+<!NOTATION TEX         PUBLIC "+//ISBN 0-201-13448-9::Knuth//NOTATION
+                                The TeXbook//EN" >
+<!NOTATION TIFF                SYSTEM "TIFF" >
+<!NOTATION linespecific        SYSTEM 
+     "line ends and leading white space must be preserved in output" >
+
+<!ENTITY % notationtypes "CGM-CHAR | CGM-BINARY | CGM-CLEAR | DITROFF | DVI |
+               EPS | EQN | FAX | FAXTILE | GIF | IGES | PIC | PS | TBL | TEX
+               | TIFF | linespecific %local.notations;" >
+
+<!-- ===================================================================== -->
+<!-- ##################################################################### -->
+<!-- ===================================================================== -->
+
+<!-- 
+
+       ATTRIBUTE LIST for a set of common attributes.
+
+  -->
+
+<!ENTITY % commonatts
+               "Id             ID              #IMPLIED
+               Lang            CDATA           #IMPLIED
+               Remap           CDATA           #IMPLIED
+               Role            CDATA           #IMPLIED
+               XRefLabel       CDATA           #IMPLIED" 
+>
+
+<!-- ===================================================================== -->
+<!--
+
+       Many attributes have a Boolean value.  They are given the declared
+       value of "%yesorno;" rather then NUMBER to indicate this intent.  0
+       is interpreted as false; all other numbers as true.  This concept
+       is borrowed from the CALS MIL DTD.
+
+  -->
+
+<!ENTITY % yesorno "NUMBER" >
+<!ENTITY % yes     "1" >
+<!ENTITY % no      "0" >
+
+<!-- ===================================================================== -->
+<!-- ##################################################################### -->
+<!-- ===================================================================== -->
+<!--                           PARAMETER ENTITIES                          -->
+<!-- ===================================================================== -->
+
+<!-- Book Contents -->
+
+<!ENTITY % appendix.gp "Appendix %local.appendix;" >
+
+<!ENTITY % book.gp     "Book %local.book;" >
+
+<!ENTITY % chapter.gp  "Chapter %local.chapter;" >
+
+<!ENTITY % index.gp    "Index | SetIndex %local.index;" >
+
+<!ENTITY % bookcontent.gp "%appendix.gp; | Bibliography | %chapter.gp; |
+               Glossary | %index.gp; | LoT | Preface | RefEntry | Reference |
+               ToC " >
+
+<!-- ===================================================================== -->
+
+<!--    Contents that can appear almost anywhere  -->
+
+<!ENTITY % ndxterm.gp "IndexTerm %local.ndxterms;" >
+
+<!ENTITY % xref.gp "FootnoteRef | XRef" >
+
+<!ENTITY % links.gp "Link | OLink | ULink %local.links;" >
+
+<!ENTITY % basechar.gp "#PCDATA | Anchor" >
+
+<!ENTITY % phrase.gp "%basechar.gp; | Comment | Subscript | Superscript |
+               %links.gp;" >
+
+<!-- ===================================================================== -->
+
+<!ENTITY % bookinfo.content.gp "Author | AuthorInitials | Title | Copyright |
+               CorpAuthor | CorpName | Date | Editor | Edition |
+               InvPartNumber | ISBN | LegalNotice | OrgName | OtherCredit |
+               PrintHistory | ProductName | ProductNumber | Publisher |
+               PubsNumber | ReleaseInfo | RevHistory | Subtitle |
+               VolumeNum" >
+
+<!-- ===================================================================== -->
+
+<!ENTITY % docinfo.content.gp "Author | AuthorInitials | CorpAuthor | ModeSpec
+               | OtherCredit | ProductName | ProductNumber | RevHistory" >
+
+<!-- ===================================================================== -->
+
+<!ENTITY % words.gp "Abbrev | Acronym | Citation | CiteTitle | CiteRefEntry |
+               Emphasis | FirstTerm | ForeignPhrase | GlossTerm | Footnote |
+               Markup | Quote | SGMLTag | Trademark | WordAsWord" >
+
+<!-- ===================================================================== -->
+
+<!ENTITY % computerterms.gp "Action | Application | Classname | Command |
+               ComputerOutput | Database | ErrorName | ErrorType | Filename |
+               Function | Hardware | Interface | InterfaceDefinition | KeyCap
+               | KeyCode | KeySym | Literal | MediaLabel | MsgText | Option |
+               Optional | Parameter | Property | Replaceable | ReturnValue |
+               StructField | StructName | Symbol | SystemItem | Token | Type
+               | UserInput %local.cptrterms;" >
+
+<!-- ===================================================================== -->
+
+<!ENTITY % cptrphrase.gp "%phrase.gp; | %computerterms.gp;" >
+
+<!ENTITY % inlinechar.gp "%phrase.gp; | %computerterms.gp; |
+               %docinfo.content.gp; | %words.gp; | %xref.gp; %local.terms;" >
+
+<!-- ===================================================================== -->
+<!-- ##################################################################### -->
+<!-- ===================================================================== -->
+
+<!-- ===================================================================== -->
+
+<!-- Contents of Equation -->
+
+<!ENTITY % eqncontent.gp "Graphic %local.equations;" >
+
+<!-- ===================================================================== -->
+
+<!-- Contents of Table -->
+
+<!ENTITY % tblcontent.gp "Graphic+ | TGroup+ %local.tables;" >
+
+<!-- All the varieties of lists -->
+
+<!ENTITY % list.gp "GlossList | ItemizedList | OrderedList | SegmentedList |
+               SimpleList | VariableList %local.lists; " >
+
+<!-- ===================================================================== -->
+
+<!-- All of the varieties of admonitions -->
+
+<!ENTITY % admonition.gp "Caution | Important | Note | Tip | Warning
+               %local.admonitions;" >
+
+<!-- ===================================================================== -->
+
+<!-- All of the varieties of code and whitespace-sensitive examples -->
+
+<!ENTITY % code.example.gp "LiteralLayout | ProgramListing | Screen |
+               ScreenShot %local.examples;" >
+
+<!ENTITY % synop.gp "Synopsis | CmdSynopsis | FuncSynopsis %local.synopsis;" >
+
+<!-- ===================================================================== -->
+
+<!-- Informal elements used within other paragraph elements -->
+
+<!ENTITY % object.gp "BlockQuote | InformalEquation | InformalExample |
+               InformalTable | %code.example.gp; | Graphic | %synop.gp;" >
+
+<!-- ===================================================================== -->
+
+<!-- Para elements -->
+
+<!ENTITY % para.gp "FormalPara | Para | SimPara" >
+
+<!-- ===================================================================== -->
+
+<!-- Formal elements used within other paragraph elements -->
+
+<!ENTITY % formalobject.gp "Equation | Example | Figure | Table" >
+
+<!-- ===================================================================== -->
+
+<!ENTITY % component.gp "Abstract | Anchor | AuthorBlurb | %admonition.gp; |
+               BridgeHead | Comment | Epigraph | %formalobject.gp; |
+               Highlights | %list.gp; | %object.gp; |
+               %para.gp; | MsgSet | Procedure | Sidebar" >
+
+<!-- ===================================================================== -->
+
+<!ENTITY % refclass.gp "#PCDATA | Application %local.refclasses;" >
+
+<!ENTITY % nav.gp "ToC | LoT | Index | Glossary | Bibliography %local.nav;" >
+
+<!ENTITY % inlineobj.gp "%inlinechar.gp; | InlineGraphic | InlineEquation |
+               %synop.gp;" >
+
+<!-- ===================================================================== -->
+
+<!-- The sect1.gp parameter entity is used in Chapter, Preface, and
+               Appendix -->
+
+<!ENTITY % sect1.gp "((%component.gp;)+, (Sect1* | RefEntry*)) | Sect1+ |
+               RefEntry+" >
+
+<!-- ===================================================================== -->
+
+<!ENTITY % ubiq.gp "%ndxterm.gp; | BeginPage" >
+
+<!-- ===================================================================== -->
+
+<!ENTITY % primsee "PrimaryIE, (SeeIE | SeeAlsoIE)*" >
+
+<!ENTITY % secsee "SecondaryIE, (SeeIE | SeeAlsoIE | TertiaryIE)*" >
+
+<!-- Common attributes for command synopses: -->
+
+<!ENTITY % argchcatt   "Choice ( opt | req | plain )   'opt'">
+<!ENTITY % grpchcatt   "Choice ( opt | req | plain | optmult | reqmult )
+                                                       'opt'">
+<!ENTITY % repatt      "Rep    ( norepeat | repeat )   'norepeat'">
+
+<!-- ===================================================================== -->
+<!-- ##################################################################### -->
+<!-- ===================================================================== -->
+<!--                               ELEMENTS                                -->
+<!-- ===================================================================== -->
+
+<!-- ===================================================================== -->
+<!--                         GENERAL BOOK STRUCTURES                       -->
+<!-- ===================================================================== -->
+
+<!--
+
+       A Set contains at least two books.  A Book, which could be a
+       journal or an anthology, must have a Chapter or Reference or
+       Part, and may contain other contents as required.  We believe
+       this model accommodates the order of contents for English,
+       French, German, and Japanese books.
+
+       A Part contains at least one book content element.  A
+       Preface, ToC, LoT, Bibliography, Glossary, or Index can be a
+       chapter-level component, while ToC, LoT, Bibliography,
+       Glossary, RefEntry, and Index may also appear within
+       chapter-level components.
+
+  -->
+
+<!--    A model for a Set of Books  -->
+
+<!ELEMENT Set - - ((Title, TitleAbbrev?)?, SetInfo?, ToC?, (%book.gp;),
+               (%book.gp;)+, SetIndex?) +(%ubiq.gp;) >
+<!ATTLIST Set
+               %commonatts;
+               FPI             CDATA           #IMPLIED 
+>
+
+<!ELEMENT SetInfo - - ((%bookinfo.content.gp;)+) -(%ubiq.gp;) >
+<!ATTLIST SetInfo
+               %commonatts;
+       -- Contents points to the IDs of the book pieces (from
+               book.gp) in the order of their appearance --
+               Contents        IDREFS          #IMPLIED 
+>
+
+<!--    A prescriptive model for a Book  -->
+
+<!ELEMENT Book - - ((Title, TitleAbbrev?)?, BookInfo?, ToC?, LoT*, Preface*,
+               (((%chapter.gp;)+, Reference*) | Part+ | Reference+ |
+               Article+), (%appendix.gp;)*, Glossary?, Bibliography?,
+               (%index.gp;)*, LoT*, ToC? ) +(%ubiq.gp;) >
+<!ATTLIST Book 
+               %commonatts;
+               FPI             CDATA           #IMPLIED 
+               Label           CDATA           #IMPLIED 
+>
+
+<!ELEMENT BookInfo - - (BookBiblio, LegalNotice*, ModeSpec*) -(%ubiq.gp;) >
+<!ATTLIST BookInfo
+               %commonatts;
+       -- Contents points to the IDs of the book pieces (from
+               book.gp) in the order of their appearance --
+               Contents        IDREFS          #IMPLIED 
+>
+
+<!--
+
+       PageNums is the pages contained in a given issue or volume. 
+
+  -->
+
+<!ELEMENT BookBiblio - - ((Title, TitleAbbrev?)?, Subtitle?, Edition?,
+               AuthorGroup+, ((ISBN, VolumeNum?)  | (ISSN, VolumeNum?,
+               IssueNum?, PageNums?))?, InvPartNumber?, ProductNumber?,
+               ProductName?, PubsNumber?, ReleaseInfo?, PubDate*, Publisher*,
+               Copyright?, SeriesInfo?, Abstract*, ConfGroup*, (ContractNum |
+               ContractSponsor)*, PrintHistory?, RevHistory?) -(%ubiq.gp;) >
+<!ATTLIST BookBiblio
+               %commonatts;
+>
+
+<!--   Most of the book component elements  -->
+
+<!ELEMENT Appendix - - (DocInfo?, Title, TitleAbbrev?, (%sect1.gp;))
+               +(%ubiq.gp;) >
+<!ATTLIST Appendix
+               %commonatts;
+               Label           CDATA           #IMPLIED 
+>
+
+<!ELEMENT Chapter - - (DocInfo?, Title, TitleAbbrev?, (%sect1.gp;), (Index |
+               Glossary | Bibliography)*) +(%ubiq.gp;) >
+<!ATTLIST Chapter
+               %commonatts;
+               Label           CDATA           #IMPLIED 
+>
+
+<!ELEMENT DocInfo - - (Title, TitleAbbrev?, Subtitle?, AuthorGroup+,
+               Abstract*, RevHistory?, LegalNotice*) -(%ubiq.gp;) >
+<!ATTLIST DocInfo 
+               %commonatts; 
+>
+               
+<!ELEMENT Part - - (DocInfo?, Title, TitleAbbrev?, PartIntro?,
+               (%bookcontent.gp;)+) +(%ubiq.gp;) >
+<!ATTLIST Part
+               %commonatts;
+               Label           CDATA           #IMPLIED
+>
+
+<!ELEMENT PartIntro - - ((Title, TitleAbbrev?)?, (%sect1.gp;)) +(%ubiq.gp;) >
+<!ATTLIST PartIntro    
+               %commonatts;
+               Label           CDATA           #IMPLIED 
+>
+
+<!ELEMENT Preface - - (DocInfo?, Title, TitleAbbrev?, (%sect1.gp;))
+               +(%ubiq.gp;) >
+<!ATTLIST Preface
+               %commonatts; 
+>
+
+<!ELEMENT Reference - - (DocInfo?, Title, TitleAbbrev?, PartIntro?, RefEntry+)
+               +(%ubiq.gp;) >
+<!ATTLIST Reference
+               %commonatts; 
+               Label           CDATA           #IMPLIED 
+>
+
+<!ELEMENT SeriesInfo - - (Title, TitleAbbrev?, Subtitle?, AuthorGroup*, ISBN?,
+               VolumeNum?, IssueNum?, SeriesVolNums, PubDate*, Publisher*,
+               Copyright?) -(%ubiq.gp;) >
+<!ATTLIST SeriesInfo
+               %commonatts;
+>
+
+<!ELEMENT Title - - ((%inlinechar.gp;)+) >
+<!ATTLIST Title
+               %commonatts; 
+               Pagenum         CDATA           #IMPLIED 
+>
+
+<!ELEMENT TitleAbbrev - - ((%inlinechar.gp;)+) >
+<!ATTLIST TitleAbbrev
+               %commonatts; 
+>
+
+<!ELEMENT Subtitle - - ((%inlinechar.gp;)+) >
+<!ATTLIST Subtitle
+               %commonatts; 
+>
+
+<!-- ===================================================================== -->
+<!-- ##################################################################### -->
+<!-- ===================================================================== -->
+<!--                                SECTIONS                               -->
+<!-- ===================================================================== -->
+
+<!ELEMENT Sect1 - - (Title, TitleAbbrev?, (%nav.gp;)*, (((%component.gp;)+,
+               (RefEntry* | Sect2*)) | RefEntry+ | Sect2+), (%nav.gp;)*)
+               +(%ubiq.gp;) >
+<!ATTLIST Sect1
+               %commonatts;
+               Label           CDATA           #IMPLIED 
+               Renderas        (Sect2 | Sect3 | Sect4 | Sect5)
+                                               #IMPLIED
+>
+
+<!ELEMENT Sect2 - - (Title, TitleAbbrev?, (%nav.gp;)*, (((%component.gp;)+,
+               (RefEntry* | Sect3*)) | RefEntry+ | Sect3+), (%nav.gp;)*) >
+<!ATTLIST Sect2
+               %commonatts;
+               Label           CDATA           #IMPLIED 
+               Renderas        (Sect1 | Sect3 | Sect4 | Sect5)
+                                               #IMPLIED
+>
+
+<!ELEMENT Sect3 - - (Title, TitleAbbrev?, (%nav.gp;)*, (((%component.gp;)+,
+               (RefEntry* | Sect4*)) | RefEntry+ | Sect4+), (%nav.gp;)*) >
+<!ATTLIST Sect3
+               %commonatts;
+               Label           CDATA           #IMPLIED 
+               Renderas        (Sect1 | Sect2 | Sect4 | Sect5)
+                                               #IMPLIED
+>
+
+<!ELEMENT Sect4 - - (Title, TitleAbbrev?, (%nav.gp;)*, (((%component.gp;)+,
+               (RefEntry* | Sect5*)) | RefEntry+ | Sect5+), (%nav.gp;)*) >
+<!ATTLIST Sect4
+               %commonatts;
+               Label           CDATA           #IMPLIED 
+               Renderas        (Sect1 | Sect2 | Sect3 | Sect5)
+                                               #IMPLIED
+>
+
+<!ELEMENT Sect5 - - (Title, TitleAbbrev?, (%nav.gp;)*, (((%component.gp;)+,
+               RefEntry*) | RefEntry+), (%nav.gp;)*) >
+<!ATTLIST Sect5
+               %commonatts;
+               Label           CDATA           #IMPLIED 
+               Renderas        (Sect1 | Sect2 | Sect3 | Sect4)
+                                               #IMPLIED
+>
+
+<!-- ===================================================================== -->
+<!-- ##################################################################### -->
+<!-- ===================================================================== -->
+<!--                       OTHER SECTION-ISH ELEMENTS                      -->
+<!-- ===================================================================== -->
+
+<!ELEMENT MsgSet - - (MsgEntry+) >
+<!ATTLIST MsgSet
+               %commonatts; 
+>
+
+<!ELEMENT MsgEntry - - (Msg+, MsgInfo?, MsgExplan*) >
+<!ATTLIST MsgEntry
+               %commonatts; 
+>
+
+<!ELEMENT Msg - - (Title?, MsgMain, (MsgSub | MsgRel)*) >
+<!ATTLIST Msg
+               %commonatts; 
+>
+
+<!ELEMENT MsgMain - - (Title?, MsgText) >
+<!ATTLIST MsgMain
+               %commonatts; 
+>
+
+<!ELEMENT MsgSub - - (Title?, MsgText) >
+<!ATTLIST MsgSub
+               %commonatts; 
+>
+
+<!ELEMENT MsgRel - - (Title?, MsgText) >
+<!ATTLIST MsgRel
+               %commonatts; 
+>
+
+<!ELEMENT MsgText - - ((%component.gp;)+) >
+<!ATTLIST MsgText
+               %commonatts; 
+>
+
+<!ELEMENT MsgInfo - - ((MsgLevel | MsgOrig | MsgAud)*) >
+<!ATTLIST MsgInfo
+               %commonatts; 
+>
+
+<!ELEMENT MsgLevel - - (#PCDATA) >
+<!ATTLIST MsgLevel
+               %commonatts; 
+>
+
+<!ELEMENT MsgOrig - - (#PCDATA) >
+<!ATTLIST MsgOrig
+               %commonatts; 
+>
+
+<!ELEMENT MsgAud - - (#PCDATA) >
+<!ATTLIST MsgAud
+               %commonatts; 
+>
+
+<!ELEMENT MsgExplan - - (Title?, (%component.gp;)+) >
+<!ATTLIST MsgExplan
+               %commonatts; 
+>
+
+<!-- ===================================================================== -->
+<!-- ##################################################################### -->
+<!-- ===================================================================== -->
+
+<!ELEMENT Procedure - - ((Title, TitleAbbrev?)?, (%component.gp;)*, Step+) >
+<!ATTLIST Procedure
+               %commonatts; 
+>
+
+<!ELEMENT Step - - (Title?, (((%component.gp;)+, (SubSteps,
+               (%component.gp;)*)?) | (SubSteps, (%component.gp;)*))) >
+<!ATTLIST Step
+               %commonatts; 
+               Performance     (Optional|Required)
+                                               Required
+>
+
+<!ELEMENT SubSteps - - (Step+) >
+<!ATTLIST SubSteps
+               %commonatts; 
+               Performance     (Optional|Required)
+                                               Required
+>
+
+<!--
+
+       Components not included in Sidebar are: Abstract, AuthorBlurb,
+               Epigraph, Highlights, and Sidebar.
+
+  -->
+
+<!ELEMENT Sidebar - - ((Title, TitleAbbrev?)?, (%para.gp; | %list.gp; |
+               %object.gp; | %admonition.gp; | %formalobject.gp; | Highlights
+               | BridgeHead | Procedure | Comment | Anchor)+) >
+<!ATTLIST Sidebar
+               %commonatts; 
+>
+
+<!-- ===================================================================== -->
+<!-- ##################################################################### -->
+<!-- ===================================================================== -->
+<!--                       PARAGRAPH-RELATED ELEMENTS                      -->
+<!-- ===================================================================== -->
+
+<!ELEMENT (Abstract | AuthorBlurb) - - (Title?, (%para.gp;)+) >
+<!ATTLIST (Abstract | AuthorBlurb)
+               %commonatts; 
+>
+
+<!ELEMENT BlockQuote - - (Title?, (%component.gp;)+) >
+<!ATTLIST BlockQuote
+               %commonatts; 
+>
+
+<!ELEMENT BridgeHead - - ((%inlinechar.gp;)+) >
+<!ATTLIST BridgeHead
+               %commonatts; 
+               Renderas        (Other | Sect1 | Sect2 | Sect3 | Sect4 |
+                                Sect5)         #IMPLIED
+>
+
+<!ELEMENT Comment - - ((%inlinechar.gp;)+) -(%ubiq.gp;) >
+<!ATTLIST Comment
+               %commonatts;
+>
+
+<!ELEMENT Epigraph - - ((%para.gp;)+) >
+<!ATTLIST Epigraph 
+               %commonatts; 
+>
+
+<!ELEMENT Footnote - - ((%para.gp; | %list.gp; | %object.gp;)+) -(Footnote) >
+<!ATTLIST Footnote
+               %commonatts; 
+               Label           CDATA           #IMPLIED
+>
+
+<!ELEMENT Highlights - - ((%para.gp; | %list.gp; | %admonition.gp;)+) >
+<!ATTLIST Highlights
+               %commonatts; 
+>
+
+<!ELEMENT FormalPara - - (Title, Para) >
+<!ATTLIST FormalPara
+               %commonatts; 
+>
+
+<!ELEMENT Para - - ((%inlinechar.gp; | InlineGraphic | InlineEquation |
+               %list.gp; | %object.gp;)+) >
+<!ATTLIST Para
+               %commonatts; 
+>
+
+<!ELEMENT SimPara - - ((%inlineobj.gp;)+) >
+<!ATTLIST SimPara
+               %commonatts; 
+>
+
+<!--
+
+       Components not included are: Abstract, AuthorBlurb, other admonitions,
+               Epigraph, and Highlights.
+
+  -->
+
+<!ELEMENT (%admonition.gp;) - - (Title?, (Anchor | BridgeHead | Comment |
+               %formalobject.gp; | %list.gp; | %object.gp; |
+               %para.gp; | Procedure | Sidebar)+) -(%admonition.gp;) >
+<!ATTLIST (%admonition.gp;)
+               %commonatts; 
+>
+
+<!-- ===================================================================== -->
+<!-- ##################################################################### -->
+<!-- ===================================================================== -->
+<!--                                   LISTS                               -->
+<!-- ===================================================================== -->
+
+<!ELEMENT GlossList - - (GlossEntry+) >
+<!ATTLIST GlossList
+               %commonatts; 
+>
+
+<!--
+       The Mark attribute specifies the mark that should appear
+       before each ListItem, such as Bullet, Dash, Box, Check.
+  -->
+
+<!ELEMENT ItemizedList - - (ListItem+) >
+<!ATTLIST ItemizedList   
+               %commonatts;
+               Mark            CDATA           #IMPLIED
+>
+
+<!ELEMENT ListItem - - ((%component.gp;)+) >
+<!ATTLIST ListItem
+               %commonatts; 
+               Override        CDATA           #IMPLIED
+>
+
+<!ELEMENT OrderedList - - (ListItem+) >
+<!ATTLIST OrderedList  
+               %commonatts;
+               Numeration      (Arabic | Upperalpha | Loweralpha
+                               | Upperroman | Lowerroman)
+                                               #IMPLIED
+               InheritNum      (Inherit | Ignore)
+                                               Ignore
+               Continuation    (Continues | Restarts)
+                                               Restarts
+>
+
+<!ELEMENT SegmentedList - - ((Title, TitleAbbrev?)?, SegTitle*, SegListItem+)
+               >
+<!ATTLIST SegmentedList
+               %commonatts; 
+>
+
+<!ELEMENT SegTitle - - ((%inlinechar.gp;)+) >
+<!ATTLIST SegTitle
+               %commonatts; 
+>
+
+<!ELEMENT SegListItem - - (Seg, Seg+) >
+<!ATTLIST SegListItem
+               %commonatts; 
+>
+
+<!ELEMENT Seg - - ((%inlinechar.gp;)+) >
+<!ATTLIST Seg
+               %commonatts; 
+>
+
+<!ELEMENT VariableList - - ((Title, TitleAbbrev?)?, VarListEntry+) >
+<!ATTLIST VariableList
+               %commonatts; 
+>
+
+<!ELEMENT VarListEntry - - (Term+, ListItem) >
+<!ATTLIST VarListEntry
+               %commonatts; 
+>
+
+<!ELEMENT Term - - ((%inlinechar.gp;)+) >
+<!ATTLIST Term
+               %commonatts; 
+>
+
+<!-- ===================================================================== -->
+<!--
+
+       SimpleList allows you to list short strings (Members) in an array or
+       in a normal sentence.  The "inline" value of the Type attribute
+       presents the Members inline (you have to generate commas
+       and the "and" if need be).  "Horiz" means set up as many columns 
+       as are specified by the value of the Columns attribute, of equal 
+       width, indented as for a BlockQuote, and enter the Members in 
+       these slots from L to R, top to bottom, left justified.  "Vert" means
+       calculate the columns the same way and determine the number of rows
+       as if you were using Horiz; then just fill in the positions from
+       top to bottom, L to R left-justified.  In other words, you
+       don't set the number of rows, only the number of columns.
+       (This way, when on-line and the window resizes, you don't have to
+       readjust the text unless the window gets so narrow you can't
+       display the specified number of columns, then a renderer might
+       reduce the number of columns.)  When Column = 1, Vert and Horiz
+       provide the same rendition.  
+
+  -->
+
+<!ELEMENT SimpleList - - (Member+) >
+<!ATTLIST SimpleList
+               %commonatts;
+               Columns         NUMBER          #IMPLIED
+               Type            (Inline | Vert | Horiz)
+                                               Vert
+>
+
+<!ELEMENT Member  - - ((%inlinechar.gp;)+) >
+<!ATTLIST Member
+               %commonatts; 
+>
+
+<!-- ===================================================================== -->
+<!-- ##################################################################### -->
+<!-- ===================================================================== -->
+<!--                                OBJECTS                                -->
+<!-- ===================================================================== -->
+
+<!-- ===================================================================== -->
+<!--                                EXAMPLE                                -->
+<!-- ===================================================================== -->
+
+<!ELEMENT Example - - (Title, TitleAbbrev?, (%para.gp; | %list.gp; |
+               %object.gp;)+) >
+<!ATTLIST Example
+               %commonatts; 
+               Label           CDATA           #IMPLIED
+>
+
+<!ELEMENT InformalExample - - ((%para.gp; | %list.gp; | %object.gp;)+) >
+<!ATTLIST InformalExample
+               %commonatts; 
+>
+
+<!ELEMENT ProgramListing - - ((LineAnnotation | %inlinechar.gp;)+) >
+<!ATTLIST ProgramListing
+               %commonatts; 
+               Format          NOTATION
+                               (linespecific)  linespecific
+               Width           NUMBER          #IMPLIED
+>
+
+<!ELEMENT LiteralLayout - - ((LineAnnotation | %inlinechar.gp;)+) >
+<!ATTLIST LiteralLayout
+               %commonatts; 
+               Format          NOTATION
+                               (linespecific)  linespecific
+               Width           NUMBER          #IMPLIED
+>
+
+<!ELEMENT Screen - - ((LineAnnotation | %inlinechar.gp;)+) >
+<!ATTLIST Screen
+               %commonatts; 
+               Format          NOTATION
+                               (linespecific)  linespecific
+               Width           NUMBER          #IMPLIED
+>
+
+<!ELEMENT ScreenShot - - (ScreenInfo?, Graphic) >
+<!ATTLIST ScreenShot
+               %commonatts; 
+>
+
+<!ELEMENT ScreenInfo - - (#PCDATA) -(%ubiq.gp;) >
+<!ATTLIST ScreenInfo
+               %commonatts; 
+>
+
+<!-- ===================================================================== -->
+<!-- ##################################################################### -->
+<!-- ===================================================================== -->
+<!--                                FIGURE                                 -->
+<!-- ===================================================================== -->
+<!--
+
+       N.B.: Graphic occurs in object.gp, so does not appear
+       explicitly in Figure.
+
+  -->
+
+<!ELEMENT Figure - - (Title, TitleAbbrev?, (%object.gp; | %links.gp;)+) >
+<!ATTLIST Figure
+               %commonatts;
+               Float           %yesorno;       %no;
+               Label           CDATA           #IMPLIED
+>
+
+<!--
+
+       Graphical data can be the content of Graphic, or you can
+       reference an external file through the Fileref attribute,
+       either as an entity or a filename.
+
+  -->
+
+<!ELEMENT Graphic - - CDATA >
+<!ATTLIST Graphic 
+               %commonatts;
+               Entityref       ENTITY          #IMPLIED        
+               Fileref         CDATA           #IMPLIED 
+               Format          NOTATION
+                               (%notationtypes;)
+                                               #IMPLIED
+               SrcCredit       CDATA           #IMPLIED 
+>
+
+<!ELEMENT InlineGraphic - - CDATA >
+<!ATTLIST InlineGraphic 
+               %commonatts;
+               Entityref       ENTITY          #IMPLIED        
+               Fileref         CDATA           #IMPLIED 
+               Format          NOTATION
+                               (%notationtypes;)
+                                               #IMPLIED
+               SrcCredit       CDATA           #IMPLIED 
+>
+
+
+<!-- ===================================================================== -->
+<!-- ##################################################################### -->
+<!-- ===================================================================== -->
+<!--                               EQUATION                                -->
+<!-- ===================================================================== -->
+
+<!ELEMENT Equation - - ((Title, TitleAbbrev?)?, (InformalEquation |
+               %eqncontent.gp;)+) >
+<!ATTLIST Equation
+               %commonatts; 
+               Label           CDATA           #IMPLIED
+>
+
+<!ELEMENT InformalEquation - - ((%eqncontent.gp;)+) >
+<!ATTLIST InformalEquation
+               %commonatts; 
+>
+
+<!ELEMENT InlineEquation - - ((%eqncontent.gp;)+) >
+<!ATTLIST InlineEquation
+               %commonatts; 
+>
+
+<!-- ===================================================================== -->
+<!-- ##################################################################### -->
+<!-- ===================================================================== -->
+<!--                                 TABLE                                 -->
+<!-- ===================================================================== -->
+
+<!--
+
+       The CALS table specification derived from MIL-M-28001B.  The only
+               difference is the content of Entry.  InformalTable was derived
+               from Table by removing titling and the attributes: Label,
+               ShortEntry, and ToCentry.
+
+  -->
+
+<!ELEMENT Table - - (Title, TitleAbbrev?, (%tblcontent.gp;))
+               -(Table|InformalTable)>
+<!ATTLIST Table
+               %commonatts;
+               Colsep          %yesorno;       #IMPLIED
+               Frame           (Top|Bottom|Topbot|All|Sides|None)
+                                               #IMPLIED
+               Label           CDATA           #IMPLIED 
+               Orient          (Port | Land)   #IMPLIED
+               Pgwide          %yesorno;       #IMPLIED
+               Rowsep          %yesorno;       #IMPLIED
+               Shortentry      %yesorno;       #IMPLIED
+               Tabstyle        NMTOKEN         #IMPLIED
+               Tocentry        %yesorno;       %yes;
+>
+
+<!ELEMENT InformalTable - - ((%tblcontent.gp;)) -(Table|InformalTable)>
+<!ATTLIST InformalTable
+               %commonatts;
+               Colsep          %yesorno;       #IMPLIED
+               Frame           (Top|Bottom|Topbot|All|Sides|None)
+                                               #IMPLIED
+               Orient          (Port | Land)   #IMPLIED
+               Pgwide          %yesorno;       #IMPLIED
+               Rowsep          %yesorno;       #IMPLIED
+               Tabstyle        NMTOKEN         #IMPLIED
+>
+
+<!ELEMENT TGroup - O (ColSpec*, SpanSpec*, THead?, TFoot?, TBody) >
+<!ATTLIST TGroup
+               %commonatts;
+               Align           (Left|Right|Center|Justify|Char)
+                                               Left
+               Char            CDATA           ""
+               Charoff         NUTOKEN         "50"
+               Cols            NUMBER          #REQUIRED
+               Colsep          %yesorno;       #IMPLIED
+               Rowsep          %yesorno;       #IMPLIED
+               TGroupStyle     NMTOKEN         #IMPLIED
+>
+
+<!ELEMENT ColSpec - O  EMPTY >
+<!ATTLIST ColSpec
+               %commonatts; 
+               Align           (Left|Right|Center|Justify|Char)
+                                               #IMPLIED
+               Char            CDATA           #IMPLIED
+               Charoff         NUTOKEN         #IMPLIED
+               Colname         NMTOKEN         #IMPLIED
+               Colnum          NUMBER          #IMPLIED
+               Colsep          %yesorno;       #IMPLIED
+               Colwidth        CDATA           #IMPLIED
+               Rowsep          %yesorno;       #IMPLIED
+>
+
+<!ELEMENT SpanSpec - O  EMPTY >
+<!ATTLIST SpanSpec
+               %commonatts; 
+               Align           (Left|Right|Center|Justify|Char)
+                                               "Center"
+               Char            CDATA           #IMPLIED
+               Charoff         NUTOKEN         #IMPLIED
+               Colsep          %yesorno;       #IMPLIED
+               Nameend         NMTOKEN         #REQUIRED
+               Namest          NMTOKEN         #REQUIRED
+               Rowsep          %yesorno;       #IMPLIED
+               Spanname        NMTOKEN         #REQUIRED
+>
+
+<!ELEMENT THead - O (ColSpec*, Row+)                   -(EntryTbl) >
+<!ATTLIST THead
+               %commonatts; 
+               VAlign          (Top | Middle | Bottom)
+                                               "Bottom"
+>
+
+<!ELEMENT TFoot - O (ColSpec*, Row+)                   -(EntryTbl) >
+<!ATTLIST TFoot
+               %commonatts; 
+               VAlign          (Top | Middle | Bottom)
+                                               "Top"
+>
+
+<!ELEMENT TBody - O (Row+) >
+<!ATTLIST TBody
+               %commonatts; 
+               VAlign          (Top | Middle | Bottom)
+                                               "Top"
+>
+
+<!ELEMENT Row - O ((Entry | EntryTbl)+) >
+<!ATTLIST Row
+               %commonatts; 
+               Rowsep          %yesorno;       #IMPLIED
+               VAlign          (Top | Middle | Bottom)
+                                               #IMPLIED
+>
+
+<!-- 
+
+       The content model of Entry is broken into two possibilities:
+       paragraph-like elements (Para, Note, LiteralLayout, lists,
+       etc., and inline text elements (PCDATA, Command, Link, etc.).
+       Because of the possibility that PCDATA can occur without
+       being contained, you can not allow for spurious record ends
+       to occur between the paragraph-like elements.  If the inline
+       text elements were contained in another element, e.g., Cell,
+       (it could be a sibling of Entry or part of the content model
+       for Entry), this issue would disappear.
+
+  -->
+<!ELEMENT Entry - O ((%para.gp; | %admonition.gp; | %code.example.gp; |
+               %list.gp; | Graphic)+ | (%inlineobj.gp;)+) >
+<!ATTLIST Entry
+               %commonatts;
+               Align           (Left|Right|Center|Justify|Char)
+                                               #IMPLIED
+               Char            CDATA           #IMPLIED
+               Charoff         NUTOKEN         #IMPLIED
+               Colname         NMTOKEN         #IMPLIED
+               Colsep          %yesorno;       #IMPLIED
+               Morerows        NUMBER          "0"
+               Nameend         NMTOKEN         #IMPLIED
+               Namest          NMTOKEN         #IMPLIED
+               Rotate          %yesorno;       %no;
+               Rowsep          %yesorno;       #IMPLIED
+               Spanname        NMTOKEN         #IMPLIED
+               VAlign          (Top | Middle | Bottom)
+                                               #IMPLIED
+>
+
+<!ELEMENT EntryTbl - - ((ColSpec*, SpanSpec*, THead?, TBody)+)
+               -(EntryTbl) >
+<!ATTLIST EntryTbl
+               %commonatts;
+               Align           (Left|Right|Center|Justify|Char)
+                                               #IMPLIED
+               Char            CDATA           #IMPLIED
+               Charoff         NUTOKEN         #IMPLIED
+               Colname         NMTOKEN         #IMPLIED
+               Cols            NUMBER          #REQUIRED
+               Colsep          %yesorno;       #IMPLIED
+               Nameend         NMTOKEN         #IMPLIED
+               Namest          NMTOKEN         #IMPLIED
+               Rowsep          %yesorno;       #IMPLIED
+               Spanname        NMTOKEN         #IMPLIED
+               TGroupStyle     NMTOKEN         #IMPLIED
+>
+
+<!-- ===================================================================== -->
+<!-- ##################################################################### -->
+<!-- ===================================================================== -->
+<!--                                  LINKS                                -->
+<!-- ===================================================================== -->
+
+<!ELEMENT Anchor - O  EMPTY >
+<!ATTLIST Anchor
+       -- commonatts, but Id is required, and Pagenum replaces Lang --
+               Id              ID              #REQUIRED
+               Pagenum         CDATA           #IMPLIED 
+               Remap           CDATA           #IMPLIED
+               Role            CDATA           #IMPLIED
+               XRefLabel       CDATA           #IMPLIED
+>
+
+<!--
+
+       The PageNum attribute of BeginPage, if given, specifies
+       the number of the page that begins at that point.
+
+  -->
+
+<!ELEMENT BeginPage - O  EMPTY >
+<!ATTLIST BeginPage
+               %commonatts;
+               Pagenum         CDATA           #IMPLIED 
+>
+
+<!--
+
+       IndexTerms occur in the text flow for generating or linking an
+               Index.
+
+  -->
+
+<!ELEMENT IndexTerm - O (Primary, ((Secondary, ((Tertiary, (See | SeeAlso+)?)
+               | See | SeeAlso+)?) | See | SeeAlso+)?) -(%ubiq.gp;) >
+<!ATTLIST IndexTerm
+               %commonatts;
+               Pagenum         CDATA           #IMPLIED
+       -- local implementations of Scope define what the default should be --
+               Scope           (All | Global | Local)
+                                               #IMPLIED
+               Significance    (Preferred | Normal)
+                                               Normal
+-- FUTURE use: SpanEnd attribute will be renamed to indicate that it
+               points to the content of the indexterm being spanned.
+               Another attribute will be added to "flag" that the
+               indexterm is the other end of a spanned indexterm and
+               not just a point in the flow.
+--
+               SpanEnd         IDREF           #CONREF
+       -- if Zone is used, they point to elements where they originated -- 
+               Zone            IDREFS          #IMPLIED
+>
+
+<!ELEMENT (Primary | Secondary | Tertiary ) - - ((%inlinechar.gp;)+) >
+<!ATTLIST (Primary | Secondary | Tertiary )
+               %commonatts;
+               SortAs          CDATA           #IMPLIED
+>
+
+<!ELEMENT (See | SeeAlso) - - ((%inlinechar.gp;)+) >
+<!ATTLIST (See | SeeAlso)
+               %commonatts;
+>
+
+<!-- ===================================================================== -->
+<!--
+
+       Use of the HyTime terms Linkend and Endterm does not indicate
+       that HyTime processing is required.  Link has both Endterm and
+       Linkend attributes: Linkend is the spot linked to, Endterm
+       identifies information that may be used by the Link.  You
+       might, for example, make the Linkend a Sect2 and make the
+       Endterm its Title.
+
+  -->
+
+
+<!ELEMENT Link - - ((%inlineobj.gp;)+) >
+<!ATTLIST Link
+               %commonatts;
+                Endterm                IDREF           #IMPLIED
+                Linkend         IDREF           #REQUIRED
+                Type            CDATA           #IMPLIED 
+>
+
+<!-- ===================================================================== -->
+<!-- 
+
+       Hytimeish link, after Eliot Kimber.  TargetDocEnt points
+       to an entity in the manner of HyTime's Docorsub; this could
+       be an FPI inside a text entity or could be a data entity.
+       LinkMode points to a ModeSpec, which may contain
+       application-specific information and may appear only in
+       DocInfo and BookInfo.
+
+  -->
+
+<!ELEMENT OLink - - ((%inlineobj.gp;)+) >
+<!ATTLIST OLink
+               %commonatts;
+               TargetDocEnt    ENTITY          #IMPLIED
+               LinkMode        IDREF           #IMPLIED
+               LocalInfo       CDATA           #IMPLIED
+               Type            CDATA           #IMPLIED 
+>
+
+<!ELEMENT ModeSpec - - (#PCDATA) -(%ubiq.gp;) >
+<!ATTLIST ModeSpec
+               %commonatts;
+               Application     NOTATION
+                               (%notationtypes;)
+                                               #IMPLIED 
+>
+
+<!--
+       URL link.  To point to a filename, use "file://pathname/filename" as
+       the value of the URL attribute
+  -->
+
+<!ELEMENT ULink  - - ((%inlineobj.gp;)+) >
+<!ATTLIST ULink
+               %commonatts;
+                URL            CDATA           #REQUIRED
+                Type            CDATA           #IMPLIED 
+>
+
+<!-- FUTURE Use
+<!ELEMENT FootnoteRef - O EMPTY >
+  -->
+<!ELEMENT FootnoteRef - O (#PCDATA) -(%ubiq.gp;) >
+<!ATTLIST FootnoteRef   
+               %commonatts;
+               Linkend         IDREF           #REQUIRED
+-- FUTURE Use
+               Label           CDATA           #IMPLIED
+--
+               Mark            CDATA           #IMPLIED
+>
+
+<!ELEMENT XRef - O  EMPTY >
+<!ATTLIST XRef   
+               %commonatts;
+               Endterm         IDREF           #IMPLIED
+               Linkend         IDREF           #REQUIRED
+>
+
+<!-- ===================================================================== -->
+<!-- ##################################################################### -->
+<!-- ===================================================================== -->
+<!--                                DOCINFO                                -->
+<!-- ===================================================================== -->
+
+<!--  
+
+       DOCINFO elements; some appear in BiblioEntry, too
+
+  -->
+
+<!ELEMENT (Author | Editor | OtherCredit) - - ((Honorific | Firstname |
+               Surname | Lineage | OtherName | Affiliation | AuthorBlurb |
+               Contrib)+) >
+
+<!ELEMENT (AuthorInitials | Contrib | CorpAuthor | CorpName | Date | Edition |
+               Firstname | Holder | Honorific | ISBN | InvPartNumber |
+               Lineage | OtherName | ProductNumber | ReleaseInfo | RevNumber
+               | RevRemark | Surname | Year ) - - (#PCDATA) >
+
+<!ELEMENT Affiliation - - (ShortAffil?, JobTitle*, OrgName?, OrgDiv*,
+               Address*) >
+
+<!ELEMENT JobTitle - - (#PCDATA) >
+
+<!-- ShortAffil is for places like ToCs -->
+<!ELEMENT ShortAffil - - (#PCDATA) >
+
+<!ELEMENT Copyright - - (Year+, Holder*) >
+
+<!ELEMENT LegalNotice - - (Title?, ( %admonition.gp; | BlockQuote |
+               %code.example.gp; | %list.gp; | %para.gp;)+) >
+
+<!ELEMENT PrintHistory - - ((%para.gp;)+) >
+
+<!ELEMENT ProductName - - ((%inlinechar.gp;)+) >
+<!ATTLIST ProductName
+               %commonatts;
+               Class   (Service|Trade|Registered|Copyright)
+                                               Trade
+>
+
+<!-- FUTURE Use
+<!ELEMENT RevHistory - - (Revision+) >
+  -->
+<!ELEMENT RevHistory - - (Revision*) >
+
+<!ELEMENT Revision - - (RevNumber, Date, AuthorInitials*, RevRemark?) >
+
+<!ATTLIST (Affiliation | Author | AuthorInitials | Contrib | Copyright |
+               CorpAuthor | CorpName | Date | Edition | Editor | Firstname |
+               Holder | Honorific | ISBN | InvPartNumber | JobTitle |
+               LegalNotice | Lineage | OtherCredit | OtherName | PrintHistory
+               | ProductNumber | ReleaseInfo | Revision | RevHistory |
+               RevNumber | RevRemark | ShortAffil | Surname | Year)
+
+               %commonatts;
+>
+
+<!-- ===================================================================== -->
+<!-- ##################################################################### -->
+<!-- ===================================================================== -->
+<!--                      COMPUTER TERM INLINES                            -->
+<!-- ===================================================================== -->
+
+<!ELEMENT Application - - ((%inlinechar.gp;)+) >
+<!ATTLIST Application
+               %commonatts;
+               Class           (Hardware|Software)
+                                               #IMPLIED
+               MoreInfo        (RefEntry|None) None
+>
+
+<!ELEMENT Database - - ((%cptrphrase.gp;)+) >
+<!ATTLIST Database
+               %commonatts;
+               Class           (Name|Table|Field|Key1|Key2|Record)
+                                               #IMPLIED
+               MoreInfo        (RefEntry|None) None
+>
+
+<!ELEMENT Interface - - ((%cptrphrase.gp;)+) >
+<!ATTLIST Interface
+               %commonatts;
+               Class           (Button|Icon|Menu|MenuItem)
+                                               #IMPLIED
+               MoreInfo        (RefEntry|None) None
+>
+
+<!ELEMENT MediaLabel - - (#PCDATA) >
+<!ATTLIST MediaLabel
+               %commonatts;
+               Class           (Cartridge|CDRom|Disk|Tape)
+                                               #IMPLIED
+>
+
+<!ELEMENT Parameter - - ((%cptrphrase.gp;)+) >
+<!ATTLIST Parameter
+               %commonatts;
+               Class           (Command|Function|Option)
+                                               #IMPLIED
+               MoreInfo        (RefEntry|None) None
+>
+
+<!ELEMENT Replaceable - - ((%phrase.gp;)+) >
+<!ATTLIST Replaceable
+               %commonatts; 
+               Class           (Command | Function | Option | Parameter)
+                                               #IMPLIED
+>
+
+<!ELEMENT SystemItem - - ((%cptrphrase.gp;)+) >
+<!ATTLIST SystemItem
+               %commonatts;
+               Class
+               (Constant|EnvironVar|Macro|OSname|Prompt|Resource|SystemName)
+                                               #IMPLIED
+               MoreInfo        (RefEntry|None) None
+>
+
+<!ELEMENT (Command | Literal) - - ((%cptrphrase.gp;)+) >
+<!ATTLIST (Command | Literal)
+               %commonatts;
+               MoreInfo        (RefEntry|None) None
+>
+
+<!ELEMENT (Action | Filename | Function | Hardware | KeyCap |
+               InterfaceDefinition | Property) - - ((%cptrphrase.gp;)+) >
+<!ATTLIST (Action | Filename | Function | Hardware | KeyCap |
+               InterfaceDefinition | Property)
+
+               %commonatts;
+               MoreInfo        (RefEntry|None) None
+>
+
+<!ELEMENT ComputerOutput - - ((%cptrphrase.gp;)+) >
+<!ATTLIST ComputerOutput
+               %commonatts;
+               MoreInfo        (RefEntry|None) None
+>
+
+<!ELEMENT UserInput - - ((%cptrphrase.gp;)+) >
+<!ATTLIST UserInput
+               %commonatts;
+               MoreInfo        (RefEntry|None) None
+>
+
+<!-- ===================================================================== -->
+<!-- ##################################################################### -->
+<!-- ===================================================================== -->
+
+<!ELEMENT CiteTitle - - ((%inlinechar.gp;)+) >
+<!ATTLIST CiteTitle
+               %commonatts;
+       -- The kind of title in a published work being cited. --
+               Pubwork         (Article|Book|Chapter|Part|RefEntry|Section)
+                                               #IMPLIED
+>
+
+<!ELEMENT CiteRefEntry - - (RefEntryTitle, ManVolNum?) >
+<!ATTLIST CiteRefEntry
+               %commonatts;
+>
+
+<!ELEMENT Option - - ((%cptrphrase.gp;)+) >
+<!ATTLIST Option
+               %commonatts;
+>
+
+<!ELEMENT Quote - - ((%inlinechar.gp;)+) >
+<!ATTLIST Quote
+               %commonatts;
+>
+
+<!ELEMENT Trademark - - ((%cptrphrase.gp;)+) >
+<!ATTLIST Trademark
+               %commonatts;
+               Class   (Service|Trade|Registered|Copyright)
+                                               Trade
+>
+
+<!ELEMENT (Subscript | Superscript) - - ((%phrase.gp; | Emphasis |
+               Replaceable)+) >
+<!ATTLIST (Subscript | Superscript)
+               %commonatts;
+>
+
+<!ELEMENT SGMLTag - - (#PCDATA) >
+<!ATTLIST SGMLTag
+               %commonatts;
+               Class           (Attribute|Element|GenEntity|ParamEntity)
+                                               #IMPLIED
+>
+
+<!ELEMENT (Abbrev | Acronym | Citation | Classname | Emphasis | ErrorName |
+               ErrorType | FirstTerm | ForeignPhrase | KeySym | KeyCode |
+               LineAnnotation | Markup | PubsNumber | ReturnValue |
+               StructField | StructName | Symbol | Token | Type | VolumeNum |
+               WordAsWord) - - (#PCDATA) >
+<!ATTLIST (Abbrev | Acronym | Citation | Classname | Emphasis | ErrorName |
+               ErrorType | FirstTerm | ForeignPhrase | KeySym | KeyCode |
+               LineAnnotation | Markup | PubsNumber | ReturnValue |
+               StructField | StructName | Symbol | Token | Type | VolumeNum |
+               WordAsWord)
+
+               %commonatts;
+>
+
+<!--
+
+       The element named Optional is for use in syntax lines, as in a
+       RefEntry, where optional parameters are shown in square
+       brackets.  Optional should replace those brackets.
+
+  -->
+
+<!ELEMENT Optional - - ((%cptrphrase.gp;)+) >
+<!ATTLIST Optional
+               %commonatts; 
+>
+
+
+<!-- ===================================================================== -->
+<!-- ##################################################################### -->
+<!-- ===================================================================== -->
+<!--                               NAVIGATION                              -->
+<!-- ===================================================================== -->
+
+<!ELEMENT ToC - - (DocInfo?, (Title, TitleAbbrev?)?, ToCfront*, (ToCpart+ |
+               ToCchap+), ToCback*) >
+<!ATTLIST ToC
+               %commonatts; 
+>
+
+<!ELEMENT ToCfront - - ((%inlinechar.gp;)+) >
+<!ATTLIST ToCfront
+               %commonatts; 
+               Label           CDATA           #IMPLIED 
+               Pagenum         CDATA           #IMPLIED 
+>
+
+<!ELEMENT ToCentry - - ((%inlinechar.gp;)+) >
+<!ATTLIST ToCentry
+               %commonatts; 
+               Linkend         IDREF           #IMPLIED 
+               Pagenum         CDATA           #IMPLIED 
+>
+
+<!ELEMENT ToCpart - - (ToCentry+, ToCchap*) >
+<!ATTLIST ToCpart
+               %commonatts; 
+>
+
+<!ELEMENT ToCchap - - (ToCentry+, ToClevel1*) >
+<!ATTLIST ToCchap
+               %commonatts; 
+               Label           CDATA           #IMPLIED
+>
+
+<!ELEMENT ToClevel1 - - (ToCentry+, ToClevel2*) >
+<!ATTLIST ToClevel1
+               %commonatts; 
+>
+
+<!ELEMENT ToClevel2 - - (ToCentry+, ToClevel3*) >
+<!ATTLIST ToClevel2
+               %commonatts; 
+>
+
+<!ELEMENT ToClevel3 - - (ToCentry+, ToClevel4*) >
+<!ATTLIST ToClevel3
+               %commonatts; 
+>
+
+<!ELEMENT ToClevel4 - - (ToCentry+, ToClevel5*) >
+<!ATTLIST ToClevel4
+               %commonatts; 
+>
+
+<!ELEMENT ToClevel5 - - (ToCentry+) > 
+<!ATTLIST ToClevel5
+               %commonatts; 
+>
+
+<!ELEMENT ToCback - - ((%inlinechar.gp;)+) >
+<!ATTLIST ToCback
+               %commonatts; 
+               Label           CDATA           #IMPLIED 
+               Pagenum         CDATA           #IMPLIED 
+>
+
+<!-- ===================================================================== -->
+<!-- ##################################################################### -->
+<!-- ===================================================================== -->
+
+<!ELEMENT LoT - - (DocInfo?, (Title, TitleAbbrev?)?, LoTentry+) >
+<!ATTLIST LoT
+               %commonatts; 
+               Label           CDATA           #IMPLIED 
+>
+
+<!ELEMENT LoTentry - - ((%inlinechar.gp;)+ ) >
+<!ATTLIST LoTentry
+               %commonatts;
+               Pagenum         CDATA           #IMPLIED 
+               SrcCredit       CDATA           #IMPLIED 
+>
+
+<!-- ===================================================================== -->
+<!-- ##################################################################### -->
+<!-- ===================================================================== -->
+
+<!ELEMENT Bibliography - - (DocInfo?, (Title, TitleAbbrev?)?,
+               (%component.gp;)*, (BiblioDiv+ | BiblioEntry+)) >
+<!ATTLIST Bibliography
+               %commonatts; 
+>
+
+<!ELEMENT BiblioDiv - - ((Title, TitleAbbrev?)?, (%component.gp;)*,
+               BiblioEntry+) >
+<!ATTLIST BiblioDiv
+               %commonatts;
+>
+
+<!--
+       N.B. this model of BiblioEntry produces info in the order
+       "title, author"; TEI prefers "author, title".
+  -->
+<!ELEMENT BiblioEntry - - (BiblioMisc?, (ArtHeader | BookBiblio | SeriesInfo),
+               BiblioMisc?) >
+<!ATTLIST BiblioEntry
+               %commonatts; 
+>
+
+<!ELEMENT BiblioMisc - - (#PCDATA) >
+<!ATTLIST BiblioMisc
+               %commonatts; 
+>
+
+
+<!-- ===================================================================== -->
+<!-- ##################################################################### -->
+<!-- ===================================================================== -->
+
+<!ELEMENT Glossary - - (DocInfo?, (Title, TitleAbbrev?)?, (%component.gp;)*,
+               (GlossDiv+ | GlossEntry+), Bibliography?) >
+<!ATTLIST Glossary
+               %commonatts; 
+>
+
+<!ELEMENT GlossDiv - - (Title, TitleAbbrev?, (%component.gp;)*,
+               GlossEntry+) >
+<!ATTLIST GlossDiv
+               %commonatts;
+>
+
+<!ELEMENT GlossEntry - - (GlossTerm, Acronym?, Abbrev?, (GlossSee |
+               GlossDef+)) >
+<!ATTLIST GlossEntry
+               %commonatts; 
+               SortAs          CDATA           #IMPLIED
+>
+
+<!ELEMENT GlossTerm - - ((%inlineobj.gp;)+) >
+<!ATTLIST GlossTerm
+               %commonatts;
+>
+
+<!ELEMENT GlossDef - - ((Comment | %para.gp; | %list.gp; | %object.gp;)+,
+               GlossSeeAlso*) >
+<!ATTLIST GlossDef
+               %commonatts; 
+               Subject         CDATA           #IMPLIED
+>
+
+<!ELEMENT GlossSee - O ((%inlineobj.gp;)+) >
+<!ATTLIST GlossSee
+               %commonatts;
+               OtherTerm       IDREF           #CONREF
+>
+
+<!ELEMENT GlossSeeAlso - O ((%inlineobj.gp;)+) >
+<!ATTLIST GlossSeeAlso
+               %commonatts;
+               OtherTerm       IDREF           #CONREF
+>
+
+<!-- ===================================================================== -->
+<!-- ##################################################################### -->
+<!-- ===================================================================== -->
+
+<!ELEMENT (SetIndex | Index) - - (DocInfo?, (Title, TitleAbbrev?)?,
+               (%component.gp;)*, (IndexDiv+ | IndexEntry+)) -(%ndxterm.gp;) >
+<!ATTLIST (SetIndex | Index)
+               %commonatts; 
+>
+
+<!--
+
+       The IndexDiv model allows a SegmentedList as the content of
+       IndexDiv so SegmentedList can be used for permuted indices.
+
+  -->
+
+<!ELEMENT IndexDiv - - ((Title, TitleAbbrev?)?, ((Anchor | Comment |
+               %links.gp; | ItemizedList | OrderedList | VariableList |
+               %object.gp; | %para.gp;)*, (IndexEntry+ | SegmentedList))) >
+<!ATTLIST IndexDiv
+               %commonatts; 
+>
+
+<!--  
+
+       IndexEntries appear in the Index, not the text.
+
+  -->
+
+<!ELEMENT IndexEntry - - (%primsee;, (%secsee;)*) >
+<!ATTLIST IndexEntry  
+               %commonatts; 
+>
+
+<!ELEMENT PrimaryIE - - ((%inlinechar.gp;)+) >
+<!ATTLIST PrimaryIE
+               %commonatts;
+               Linkends        IDREFS          #IMPLIED
+>
+       
+<!ELEMENT SecondaryIE - - ((%inlinechar.gp;)+) >
+<!ATTLIST SecondaryIE
+               %commonatts;
+               Linkends        IDREFS          #IMPLIED
+>
+
+<!ELEMENT TertiaryIE - - ((%inlinechar.gp;)+) >
+<!ATTLIST TertiaryIE
+               %commonatts;
+               Linkends        IDREFS          #IMPLIED
+>
+
+<!ELEMENT SeeIE - - ((%inlinechar.gp;)+) >
+<!ATTLIST SeeIE
+               %commonatts;
+               Linkend         IDREF           #IMPLIED
+>
+
+<!ELEMENT SeeAlsoIE - - ((%inlinechar.gp;)+) >
+<!ATTLIST SeeAlsoIE
+               %commonatts;
+               Linkends        IDREFS          #IMPLIED
+>
+
+<!-- ===================================================================== -->
+<!-- ##################################################################### -->
+<!-- ===================================================================== -->
+<!--                            REFERENCE ENTRIES                          -->
+<!-- ===================================================================== -->
+
+<!ELEMENT RefEntry - - (DocInfo?, RefMeta?, (Comment | %links.gp;)*,
+               RefNameDiv, RefSynopsisDiv?, RefSect1+) +(%ubiq.gp;) >
+<!ATTLIST RefEntry
+               %commonatts; 
+>
+
+<!ELEMENT RefMeta - - (RefEntryTitle, ManVolNum?, RefMiscInfo*) -(BeginPage) >
+<!ATTLIST RefMeta
+               %commonatts; 
+>
+
+<!ELEMENT RefEntryTitle - - ((%inlinechar.gp;)+) >
+<!ATTLIST RefEntryTitle
+               %commonatts; 
+>
+
+<!ELEMENT ManVolNum - - (#PCDATA) >
+<!ATTLIST ManVolNum
+               %commonatts; 
+>
+
+<!ELEMENT RefMiscInfo - - (#PCDATA) >
+<!ATTLIST RefMiscInfo
+               %commonatts; 
+               Class           CDATA           #IMPLIED
+>
+
+<!ELEMENT RefNameDiv - - (RefDescriptor?, RefName+, RefPurpose, RefClass*,
+               (Comment | %links.gp;)*) >
+<!ATTLIST RefNameDiv
+               %commonatts; 
+>
+       
+<!ELEMENT RefDescriptor - - (#PCDATA) >
+<!ATTLIST RefDescriptor
+               %commonatts; 
+>
+
+<!ELEMENT RefName - - ((#PCDATA | %computerterms.gp;)+) >
+<!ATTLIST RefName
+               %commonatts; 
+>
+
+<!ELEMENT RefPurpose - - ((%inlinechar.gp;)+) >
+<!ATTLIST RefPurpose
+               %commonatts; 
+>
+
+<!ELEMENT RefClass - - ((%refclass.gp;)+) >
+<!ATTLIST RefClass
+               %commonatts;
+>
+
+<!ELEMENT RefSynopsisDiv - - ((Title, TitleAbbrev?)?, (((%synop.gp;)+,
+               RefSect2*) | (RefSect2+))) >
+<!ATTLIST RefSynopsisDiv
+               %commonatts;
+>
+
+<!ELEMENT RefSect1 - - (Title, TitleAbbrev?, (((%component.gp;)+, RefSect2*) |
+               RefSect2+)) >
+<!ATTLIST RefSect1
+               %commonatts; 
+>
+
+<!ELEMENT RefSect2 - - (Title, TitleAbbrev?, (((%component.gp;)+, RefSect3*) |
+               RefSect3+)) >
+<!ATTLIST RefSect2
+               %commonatts; 
+>
+
+<!ELEMENT RefSect3 - - (Title, TitleAbbrev?, (%component.gp;)+) >
+<!ATTLIST RefSect3
+               %commonatts; 
+>
+
+<!ELEMENT Synopsis - - ((LineAnnotation | %inlinechar.gp; | Graphic)+) >
+<!ATTLIST Synopsis
+               %commonatts;
+               Format          NOTATION
+                               (linespecific)  linespecific 
+               Label           CDATA           #IMPLIED
+>
+
+<!-- ===================================================================== -->
+<!-- ##################################################################### -->
+<!-- ===================================================================== -->
+
+<!-- Example command synopsis in typical UNIX(tm) format:
+
+     rm [-f] [-r] [-i] [-] {filename|dirname}...
+     ^    ^    ^    ^   ^  ^   ^       ^     ^
+     |    |    |    |   |  |   |       |     |
+     |    optional args    |   |       |     repeat indicator
+     |    (contain options)|   |       |
+     |                     |   |       second child of group
+     command name          |   |
+                           |   first child of group
+                           |
+                           required repeatable group
+
+     SGML source for this example:
+
+     <CMDSYNOPSIS>
+     <COMMAND>rm</COMMAND>
+     <ARG Choice="opt">-f</ARG>                (<OPTION> not required for arg
+                                       contents unless doing extra-special
+                                       processing)
+     <ARG Choice="opt">-r</ARG>
+     <ARG Choice="opt">-i</ARG>
+     <ARG Choice="opt">-</ARG>         (UNIX(tm) synopsis format or other
+                                       format can be generated)
+     <GROUP Choice="req" Rep="repeat">
+       <REPLACEABLE>filename</REPLACEABLE>
+       <REPLACEABLE>dirname</REPLACEABLE>
+     </GROUP>
+     </CMDSYNOPSIS>
+-->
+
+<!ELEMENT CmdSynopsis - - ((Arg | Group)*, Command, (Arg | Group)*,
+               SynopFragment*) >
+<!ATTLIST CmdSynopsis
+               %commonatts; 
+               Label           CDATA           #IMPLIED
+               Sepchar         CDATA           " "
+>
+
+<!ELEMENT Arg - - ((#PCDATA | Arg | Group | Option | SynopFragmentRef |
+               Replaceable)+) >
+<!ATTLIST Arg
+               %commonatts;
+               %argchcatt;
+               %repatt;
+>
+
+<!ELEMENT Group - - ((Arg | Group | SynopFragmentRef | Replaceable)+) >
+<!ATTLIST Group
+               %commonatts;
+               %grpchcatt;
+               %repatt;
+>
+
+<!ELEMENT SynopFragmentRef - - RCDATA >
+<!ATTLIST SynopFragmentRef
+               %commonatts;
+               Linkend         IDREF           #REQUIRED -- to Fragment --
+>
+
+<!ELEMENT SynopFragment - - ((Arg | Group)+) >
+<!ATTLIST SynopFragment
+               -- commonatts, but Id is required --
+               Id              ID              #REQUIRED
+               Lang            CDATA           #IMPLIED
+               Remap           CDATA           #IMPLIED
+               Role            CDATA           #IMPLIED
+               XRefLabel       CDATA           #IMPLIED
+>
+
+<!-- ===================================================================== -->
+<!-- ##################################################################### -->
+<!-- ===================================================================== -->
+
+<!ELEMENT FuncSynopsis - - (FuncSynopsisInfo?, ((FuncDef, (void | varargs |
+               ParamDef+)))+ ) >
+<!ATTLIST FuncSynopsis
+               %commonatts; 
+               Label           CDATA           #IMPLIED
+>
+
+<!ELEMENT FuncSynopsisInfo - - ((LineAnnotation | %cptrphrase.gp;)* ) >
+<!ATTLIST FuncSynopsisInfo
+               %commonatts;
+               Format          NOTATION
+                               (linespecific)  linespecific 
+>
+
+<!ELEMENT FuncDef - - ((#PCDATA | Replaceable | Function)*) >
+<!ATTLIST FuncDef
+               %commonatts;
+>
+
+<!ELEMENT void - O EMPTY >
+<!ATTLIST void
+               %commonatts;
+>
+
+<!ELEMENT varargs - O EMPTY >
+<!ATTLIST varargs
+               %commonatts;
+>
+
+<!--
+
+       Processing assumes that only one Parameter will appear in a 
+       ParamDef, and that funcparams will be used at most once, for 
+       providing information on the "inner parameters" for parameters
+       that are pointers to functions.
+
+  -->
+
+<!ELEMENT ParamDef - - ((#PCDATA | Replaceable | Parameter | FuncParams)*) >
+<!ATTLIST ParamDef
+               %commonatts;
+>
+
+<!ELEMENT FuncParams - - ((%cptrphrase.gp;)*) >
+<!ATTLIST FuncParams
+               %commonatts;
+>
+
+<!-- ===================================================================== -->
+<!-- ##################################################################### -->
+<!-- ===================================================================== -->
+<!--                               ARTICLE                                 -->
+<!-- ===================================================================== -->
+
+<!--  This Article model is derived from the MAJOUR header DTD.
+                       CHANGES from MAJOUR:
+  - Gnomic element names (oad, onm, odv, oid, kwdg, cgn, cgs, cnm . . .)
+       have been replaced by understandable ones.
+  - Quite a few elements have been dropped; others that already exist
+       in Docbook have been substituted for the Majour ones.
+  - Some of the modularity has been suppressed, empty elements
+       containing pointers have been eliminated, and occurrence
+       indicators have been changed ad lib.
+  - Affiliation has been nested inside Author, instead of inside
+       AuthorGroup.  
+  - JournalInfo info has been folded into BookBiblio inside BookInfo,
+       cf. also BiblioEntry.  Some of this info lies elsewhere in 
+       the Majour model.
+
+       A journal or anthology is a Book in Docbook, and the meta for
+       a journal is permitted in BookInfo.  Articles (Chapters)
+       within a journal or anthology have ArtHeaders, which may 
+       contain the same info.
+-->
+
+<!ELEMENT Article - - (ArtHeader, (%sect1.gp;), ((%nav.gp;) | (%appendix.gp;)
+               | Ackno)*) +(%ubiq.gp;) >
+<!ATTLIST Article
+               %commonatts;
+               ParentBook      IDREF           #IMPLIED 
+>
+
+<!--
+
+       ArtPageNums are the page numbers of the article as published.
+  -->
+
+<!ELEMENT ArtHeader - - (Title, TitleAbbrev?, Subtitle?, AuthorGroup+,
+               BookBiblio?, ArtPageNums, Abstract*, ConfGroup*, (ContractNum
+               | ContractSponsor)*) >
+<!ATTLIST ArtHeader
+               %commonatts;
+>
+
+<!ELEMENT ArtPageNums - - (#PCDATA) >
+
+<!ELEMENT Ackno - - (#PCDATA) >
+
+<!ELEMENT Address - - (Street | POB | Postcode | City | State | Country |
+               Phone | Fax | Email | OtherAddr)*>
+
+<!ELEMENT (Street | POB | Postcode | City | State | Country | Phone | Fax |
+               Email | OtherAddr) - - (#PCDATA) >
+
+<!ELEMENT (OrgName | OrgDiv) - - (#PCDATA) >
+
+<!ELEMENT AuthorGroup - - ((Author | Editor | Collab | CorpAuthor |
+               OtherCredit)+) >
+
+<!ELEMENT Collab  - - (CollabName, Affiliation*) >
+
+<!ELEMENT CollabName  - - (#PCDATA) >
+
+<!ELEMENT ConfDates - - (#PCDATA) >
+
+<!ELEMENT ConfGroup - - ((ConfDates | ConfTitle | ConfNum | Address |
+               ConfSponsor)*) >
+
+<!ELEMENT ConfNum - - (#PCDATA) >
+
+<!ELEMENT ConfSponsor - - (#PCDATA) >
+
+<!ELEMENT ConfTitle - - (#PCDATA) >
+
+<!ELEMENT ContractNum - - (#PCDATA) >
+
+<!ELEMENT ContractSponsor - - (#PCDATA) >
+
+<!ELEMENT ISSN - - (#PCDATA) >
+
+<!ELEMENT IssueNum - - (#PCDATA) >
+
+<!ELEMENT PageNums - - (#PCDATA) >
+
+<!ELEMENT PubDate - - (#PCDATA) >
+
+<!ELEMENT Publisher - - (PublisherName, Address*) >
+
+<!ELEMENT PublisherName - - (#PCDATA) >
+
+<!ELEMENT SeriesVolNums - - (#PCDATA) >
+
+<!ATTLIST (Ackno | Address | ArtPageNums | AuthorGroup | City | Collab |
+               CollabName | ConfDates | ConfGroup | ConfNum | ConfSponsor |
+               ConfTitle | ContractNum | ContractSponsor | Country | Email |
+               Fax | ISSN | IssueNum | OrgDiv | OrgName | OtherAddr | POB |
+               PageNums | Phone | Postcode | PubDate | Publisher |
+               PublisherName | SeriesVolNums | State | Street)
+
+               %commonatts;
+>
+
+<!-- ===================================================================== -->
+<!--                        End of the DocBook DTD                         -->
+<!-- ===================================================================== -->
diff --git a/DOC/Extras/isonum.ent b/DOC/Extras/isonum.ent
new file mode 100644 (file)
index 0000000..7ee1414
--- /dev/null
@@ -0,0 +1,88 @@
+     <!--  (C)  International   Organization   for   Standardization   1986
+     Permission to copy in any form is granted for use with conforming SGML
+     systems and applications as defined in ISO 8879, provided this  notice
+     is included in all copies.  -->
+
+     <!-- Character entity set. Typical invocation:
+
+     <!ENTITY % ISOnum PUBLIC "ISO 8879-1986//ENTITIES Numeric and  Special
+     Graphic//EN">
+     %ISOnum;
+     -->
+
+     <!ENTITY half   SDATA "[half  ]"--=fraction one-half-->
+     <!ENTITY frac12 SDATA "[frac12]"--=fraction one-half-->
+     <!ENTITY frac14 SDATA "[frac14]"--=fraction one-quarter-->
+     <!ENTITY frac34 SDATA "[frac34]"--=fraction three-quarters-->
+     <!ENTITY frac18 SDATA "[frac18]"--=fraction one-eighth-->
+     <!ENTITY frac38 SDATA "[frac38]"--=fraction three-eighths-->
+     <!ENTITY frac58 SDATA "[frac58]"--=fraction five-eighths-->
+     <!ENTITY frac78 SDATA "[frac78]"--=fraction seven-eighths-->
+     <!ENTITY sup1   SDATA "[sup1  ]"--=superscript one-->
+     <!ENTITY sup2   SDATA "[sup2  ]"--=superscript two-->
+     <!ENTITY sup3   SDATA "[sup3  ]"--=superscript three-->
+     <!ENTITY plus   SDATA "[plus  ]"--=plus sign B:-- >
+     <!ENTITY plusmn SDATA "[plusmn]"--/pm B: =plus-or-minus sign-->
+     <!ENTITY lt     SDATA "[lt    ]"--=less-than sign R:-->
+     <!ENTITY equals SDATA "[equals]"--=equals sign R:-->
+     <!ENTITY gt     SDATA "[gt    ]"--=greater-than sign R:-->
+     <!ENTITY divide SDATA "[divide]"--/div B: =divide sign-->
+     <!ENTITY times  SDATA "[times ]"--/times B: =multiply sign-->
+     <!ENTITY curren SDATA "[curren]"--=general currency sign-->
+     <!ENTITY pound  SDATA "[pound ]"--=pound sign-->
+     <!ENTITY dollar SDATA "[dollar]"--=dollar sign-->
+     <!ENTITY cent   SDATA "[cent  ]"--=cent sign-->
+     <!ENTITY yen    SDATA "[yen   ]"--/yen =yen sign-->
+     <!ENTITY num    SDATA "[num   ]"--=number sign-->
+     <!ENTITY percnt SDATA "[percnt]"--=percent sign-->
+     <!ENTITY amp    SDATA "[amp   ]"--=ampersand-->
+     <!ENTITY ast    SDATA "[ast   ]"--/ast B: =asterisk-->
+     <!ENTITY commat SDATA "[commat]"--=commercial at-->
+     <!ENTITY lsqb   SDATA "[lsqb  ]"--/lbrack O: =left square bracket-->
+     <!ENTITY bsol   SDATA "[bsol  ]"--/backslash =reverse solidus-->
+     <!ENTITY rsqb   SDATA "[rsqb  ]"--/rbrack C: =right square bracket-->
+     <!ENTITY lcub   SDATA "[lcub  ]"--/lbrace O: =left curly bracket-->
+     <!ENTITY horbar SDATA "[horbar]"--=horizontal bar-->
+     <!ENTITY verbar SDATA "[verbar]"--/vert =vertical bar-->
+     <!ENTITY rcub   SDATA "[rcub  ]"--/rbrace C: =right curly bracket-->
+     <!ENTITY micro  SDATA "[micro ]"--=micro sign-->
+     <!ENTITY ohm    SDATA "[ohm   ]"--=ohm sign-->
+     <!ENTITY deg    SDATA "[deg   ]"--=degree sign-->
+     <!ENTITY ordm   SDATA "[ordm  ]"--=ordinal indicator, masculine-->
+     <!ENTITY ordf   SDATA "[ordf  ]"--=ordinal indicator, feminine-->
+     <!ENTITY sect   SDATA "[sect  ]"--=section sign-->
+     <!ENTITY para   SDATA "[para  ]"--=pilcrow (paragraph sign)-->
+     <!ENTITY middot SDATA "[middot]"--/centerdot B: =middle dot-->
+     <!ENTITY larr   SDATA "[larr  ]"--/leftarrow /gets A: =leftward arrow-->
+     <!ENTITY rarr   SDATA "[rarr  ]"--/rightarrow /to A: =rightward arrow-->
+     <!ENTITY uarr   SDATA "[uarr  ]"--/uparrow A: =upward arrow-->
+     <!ENTITY darr   SDATA "[darr  ]"--/downarrow A: =downward arrow-->
+     <!ENTITY copy   SDATA "[copy  ]"--=copyright sign-->
+     <!ENTITY reg    SDATA "[reg   ]"--/circledR =registered sign-->
+     <!ENTITY trade  SDATA "[trade ]"--=trade mark sign-->
+     <!ENTITY brvbar SDATA "[brvbar]"--=broken (vertical) bar-->
+     <!ENTITY not    SDATA "[not   ]"--/neg /lnot =not sign-->
+     <!ENTITY sung   SDATA "[sung  ]"--=music note (sung text sign)-->
+     <!ENTITY excl   SDATA "[excl  ]"--=exclamation mark-->
+     <!ENTITY iexcl  SDATA "[iexcl ]"--=inverted exclamation mark-->
+     <!ENTITY quot   SDATA "[quot  ]"--=quotation mark-->
+     <!ENTITY apos   SDATA "[apos  ]"--=apostrophe-->
+     <!ENTITY lpar   SDATA "[lpar  ]"--O: =left parenthesis-->
+     <!ENTITY rpar   SDATA "[rpar  ]"--C: =right parenthesis-->
+     <!ENTITY comma  SDATA "[comma ]"--P: =comma-->
+     <!ENTITY lowbar SDATA "[lowbar]"--=low line-->
+     <!ENTITY hyphen SDATA "[hyphen]"--=hyphen-->
+     <!ENTITY period SDATA "[period]"--=full stop, period-->
+     <!ENTITY sol    SDATA "[sol   ]"--=solidus-->
+     <!ENTITY colon  SDATA "[colon ]"--/colon P:-->
+     <!ENTITY semi   SDATA "[semi  ]"--=semicolon P:-->
+     <!ENTITY quest  SDATA "[quest ]"--=question mark-->
+     <!ENTITY iquest SDATA "[iquest]"--=inverted question mark-->
+     <!ENTITY laquo  SDATA "[laquo ]"--=angle quotation mark, left-->
+     <!ENTITY raquo  SDATA "[raquo ]"--=angle quotation mark, right-->
+     <!ENTITY lsquo  SDATA "[lsquo ]"--=single quotation mark, left-->
+     <!ENTITY rsquo  SDATA "[rsquo ]"--=single quotation mark, right-->
+     <!ENTITY ldquo  SDATA "[ldquo ]"--=double quotation mark, left-->
+     <!ENTITY rdquo  SDATA "[rdquo ]"--=double quotation mark, right-->
+     <!ENTITY nbsp   SDATA "[nbsp  ]"--=no break (required) space-->
+     <!ENTITY shy    SDATA "[shy   ]"--=soft hyphen-->
diff --git a/DOC/Extras/isopub.ent b/DOC/Extras/isopub.ent
new file mode 100644 (file)
index 0000000..33d1252
--- /dev/null
@@ -0,0 +1,96 @@
+     <!--  (C)  International   Organization   for   Standardization   1986
+     Permission to copy in any form is granted for use with conforming SGML
+     systems and applications as defined in ISO 8879, provided this  notice
+     is included in all copies.  -->
+
+     <!-- Character entity set. Typical invocation:
+
+     <!ENTITY % ISOpub PUBLIC "ISO 8879-1986//ENTITIES Publishing//EN">
+     %ISOpub;
+     -->
+
+     <!ENTITY emsp   SDATA "[emsp  ]"--=em space-->
+     <!ENTITY ensp   SDATA "[ensp  ]"--=en space (1/2-em)-->
+     <!ENTITY emsp13 SDATA "[emsp3 ]"--=1/3-em space-->
+     <!ENTITY emsp14 SDATA "[emsp4 ]"--=1/4-em space-->
+     <!ENTITY numsp  SDATA "[numsp ]"--=digit space (width of a number)-->
+     <!ENTITY puncsp SDATA "[puncsp]"--=punctuation space (width of comma)-->
+     <!ENTITY thinsp SDATA "[thinsp]"--=thin space (1/6-em)-->
+     <!ENTITY hairsp SDATA "[hairsp]"--=hair space-->
+     <!ENTITY mdash  SDATA "[mdash ]"--=em dash-->
+     <!ENTITY ndash  SDATA "[ndash ]"--=en dash-->
+     <!ENTITY dash   SDATA "[dash  ]"--=hyphen (true graphic)-->
+     <!ENTITY blank  SDATA "[blank ]"--=significant blank symbol-->
+     <!ENTITY hellip SDATA "[hellip]"--=ellipsis (horizontal)-->
+     <!ENTITY nldr   SDATA "[nldr  ]"--=double baseline dot (en leader)-->
+     <!ENTITY frac13 SDATA "[frac13]"--=fraction one-third-->
+     <!ENTITY frac23 SDATA "[frac23]"--=fraction two-thirds-->
+     <!ENTITY frac15 SDATA "[frac15]"--=fraction one-fifth-->
+     <!ENTITY frac25 SDATA "[frac25]"--=fraction two-fifths-->
+     <!ENTITY frac35 SDATA "[frac35]"--=fraction three-fifths-->
+     <!ENTITY frac45 SDATA "[frac45]"--=fraction four-fifths-->
+     <!ENTITY frac16 SDATA "[frac16]"--=fraction one-sixth-->
+     <!ENTITY frac56 SDATA "[frac56]"--=fraction five-sixths-->
+     <!ENTITY incare SDATA "[incare]"--=in-care-of symbol-->
+     <!ENTITY block  SDATA "[block ]"--=full block-->
+     <!ENTITY uhblk  SDATA "[uhblk ]"--=upper half block-->
+     <!ENTITY lhblk  SDATA "[lhblk ]"--=lower half block-->
+     <!ENTITY blk14  SDATA "[blk14 ]"--=25% shaded block-->
+     <!ENTITY blk12  SDATA "[blk12 ]"--=50% shaded block-->
+     <!ENTITY blk34  SDATA "[blk34 ]"--=75% shaded block-->
+     <!ENTITY marker SDATA "[marker]"--=histogram marker-->
+     <!ENTITY cir    SDATA "[cir   ]"--/circ B: =circle, open-->
+     <!ENTITY squ    SDATA "[squ   ]"--=square, open-->
+     <!ENTITY rect   SDATA "[rect  ]"--=rectangle, open-->
+     <!ENTITY utri   SDATA "[utri  ]"--/triangle =up triangle, open-->
+     <!ENTITY dtri   SDATA "[dtri  ]"--/triangledown =down triangle, open-->
+     <!ENTITY star   SDATA "[star  ]"--=star, open-->
+     <!ENTITY bull   SDATA "[bull  ]"--/bullet B: =round bullet, filled-->
+     <!ENTITY squf   SDATA "[squf  ]"--/blacksquare =sq bullet, filled-->
+     <!ENTITY utrif  SDATA "[utrif ]"--/blacktriangle =up tri, filled-->
+     <!ENTITY dtrif  SDATA "[dtrif ]"--/blacktriangledown =dn tri, filled-->
+     <!ENTITY ltrif  SDATA "[ltrif ]"--/blacktriangleleft R: =l tri, filled-->
+     <!ENTITY rtrif  SDATA "[rtrif ]"--/blacktriangleright R: =r tri, filled-->
+     <!ENTITY clubs  SDATA "[clubs ]"--/clubsuit =club suit symbol-->
+     <!ENTITY diams  SDATA "[diams ]"--/diamondsuit =diamond suit symbol-->
+     <!ENTITY hearts SDATA "[hearts]"--/heartsuit =heart suit symbol-->
+     <!ENTITY spades SDATA "[spades]"--/spadesuit =spades suit symbol-->
+     <!ENTITY malt   SDATA "[malt  ]"--/maltese =maltese cross-->
+     <!ENTITY dagger SDATA "[dagger]"--/dagger B: =dagger-->
+     <!ENTITY Dagger SDATA "[Dagger]"--/ddagger B: =double dagger-->
+     <!ENTITY check  SDATA "[check ]"--/checkmark =tick, check mark-->
+     <!ENTITY cross  SDATA "[ballot]"--=ballot cross-->
+     <!ENTITY sharp  SDATA "[sharp ]"--/sharp =musical sharp-->
+     <!ENTITY flat   SDATA "[flat  ]"--/flat =musical flat-->
+     <!ENTITY male   SDATA "[male  ]"--=male symbol-->
+     <!ENTITY female SDATA "[female]"--=female symbol-->
+     <!ENTITY phone  SDATA "[phone ]"--=telephone symbol-->
+     <!ENTITY telrec SDATA "[telrec]"--=telephone recorder symbol-->
+     <!ENTITY copysr SDATA "[copysr]"--=sound recording copyright sign-->
+     <!ENTITY caret  SDATA "[caret ]"--=caret (insertion mark)-->
+     <!ENTITY lsquor SDATA "[lsquor]"--=rising single quote, left (low)-->
+     <!ENTITY ldquor SDATA "[ldquor]"--=rising dbl quote, left (low)-->
+     <!ENTITY fflig  SDATA "[fflig ]"--small ff ligature-->
+     <!ENTITY filig  SDATA "[filig ]"--small fi ligature-->
+     <!ENTITY fjlig  SDATA "[fjlig ]"--small fj ligature-->
+     <!ENTITY ffilig SDATA "[ffilig]"--small ffi ligature-->
+     <!ENTITY ffllig SDATA "[ffllig]"--small ffl ligature-->
+     <!ENTITY fllig  SDATA "[fllig ]"--small fl ligature-->
+     <!ENTITY mldr   SDATA "[mldr  ]"--em leader-->
+     <!ENTITY rdquor SDATA "[rdquor]"--rising dbl quote, right (high)-->
+     <!ENTITY rsquor SDATA "[rsquor]"--rising single quote, right (high)-->
+     <!ENTITY vellip SDATA "[vellip]"--vertical ellipsis-->
+     <!ENTITY hybull SDATA "[hybull]"--rectangle, filled (hyphen bullet)-->
+     <!ENTITY loz    SDATA "[loz   ]"--/lozenge - lozenge or total mark-->
+     <!ENTITY lozf   SDATA "[lozf  ]"--/blacklozenge - lozenge, filled-->
+     <!ENTITY ltri   SDATA "[ltri  ]"--/triangleleft B: l triangle, open-->
+     <!ENTITY rtri   SDATA "[rtri  ]"--/triangleright B: r triangle, open-->
+     <!ENTITY starf  SDATA "[starf ]"--/bigstar - star, filled-->
+     <!ENTITY natur  SDATA "[natur ]"--/natural - music natural-->
+     <!ENTITY rx     SDATA "[rx    ]"--pharmaceutical prescription (Rx)-->
+     <!ENTITY sext   SDATA "[sext  ]"--sextile (6-pointed star)-->
+     <!ENTITY target SDATA "[target]"--register mark or target-->
+     <!ENTITY dlcrop SDATA "[dlcrop]"--downward left crop mark -->
+     <!ENTITY drcrop SDATA "[drcrop]"--downward right crop mark -->
+     <!ENTITY ulcrop SDATA "[ulcrop]"--upward left crop mark -->
+     <!ENTITY urcrop SDATA "[urcrop]"--upward right crop mark -->
diff --git a/DOC/HTML/SGMLSpm/bugs.html b/DOC/HTML/SGMLSpm/bugs.html
new file mode 100644 (file)
index 0000000..0056f67
--- /dev/null
@@ -0,0 +1,21 @@
+<HTML>
+<HEAD>
+<TITLE>Are there any bugs?</TITLE>
+</HEAD>
+<BODY>
+
+<P><B>Links</B>: <A HREF=extend.html>Previous</A> <A HREF=sgmlspm.html>Up</A> <A HREF=sgmlspm.html>Top</A></P>
+
+<H1>Are there any bugs?</H1>
+
+<P>Of course!  Right now, <A HREF=sgmlspm.html><TT>SGMLS.pm</TT></A> silently ignores link attributes
+(<A HREF="http://www.jclark.com/sp.html"><TT>nsgmls</TT></A> only) and data attributes, and there may be many other bugs
+which I have not yet found.</P>
+
+
+<P><B>Links</B>: <A HREF=extend.html>Previous</A> <A HREF=sgmlspm.html>Up</A> <A HREF=sgmlspm.html>Top</A></P>
+
+
+<ADDRESS>David Megginson <A HREF="mailto:dmeggins@aix1.uottawa.ca">&lt;dmeggins@aix1.uottawa.ca&gt;</A></ADDRESS>
+</BODY>
+</HTML>
diff --git a/DOC/HTML/SGMLSpm/definition.html b/DOC/HTML/SGMLSpm/definition.html
new file mode 100644 (file)
index 0000000..6570997
--- /dev/null
@@ -0,0 +1,34 @@
+<HTML>
+<HEAD>
+<TITLE>What is SGMLS.pm?</TITLE>
+</HEAD>
+<BODY>
+
+<P><B>Links</B>: <A HREF=sgml.html>Next</A> <A HREF=terms.html>Previous</A> <A HREF=sgmlspm.html>Up</A> <A HREF=sgmlspm.html>Top</A></P>
+
+<H1>What is <A HREF=sgmlspm.html><TT>SGMLS.pm</TT></A>?</H1>
+
+<P><A HREF=sgmlspm.html><TT>SGMLS.pm</TT></A> is an <A HREF=extend.html>extensible</A> <A HREF="http://www.metronet.com/0/perlinfo/perl5/manual/perl.html"><TT>perl5</TT></A>
+class library for parsing the output from James Clark's popular
+<TT>sgmls</TT> and <A HREF="http://www.jclark.com/sp.html"><TT>nsgmls</TT></A> parsers, available on the Internet at <A HREF="ftp://jclark.com/"><TT>ftp://jclark.com</TT></A>.
+This is <EM>not</EM> a complete system for translating
+documents written the the <I>Standard Generalised Markup
+Language</I> (<A HREF="http://www.sil.org/sgml/sgml.html"><B>SGML</B></A>) into other formats, but it can easily
+form the basis of such a system (for a simple example, see the <A HREF="../sgmlspl/sgmlspl.html"><TT>sgmlspl</TT></A>
+program included in this package).</P>
+
+<P>The library recognises four basic types of <A HREF="http://www.sil.org/sgml/sgml.html"><B>SGML</B></A> objects: the
+<A HREF=sgmlselement.html><I>element</I></A>, the
+<A HREF=sgmlsattribute.html><I>attribute</I></A>,
+the <A HREF=sgmlsnotation.html><I>notation</I></A>, and the
+<A HREF=sgmlsentity.html><I>entity</I></A>; each
+of these is a fully-developed class with methods for accessing
+important information.</P>
+
+
+<P><B>Links</B>: <A HREF=sgml.html>Next</A> <A HREF=terms.html>Previous</A> <A HREF=sgmlspm.html>Up</A> <A HREF=sgmlspm.html>Top</A></P>
+
+
+<ADDRESS>David Megginson <A HREF="mailto:dmeggins@aix1.uottawa.ca">&lt;dmeggins@aix1.uottawa.ca&gt;</A></ADDRESS>
+</BODY>
+</HTML>
diff --git a/DOC/HTML/SGMLSpm/events.html b/DOC/HTML/SGMLSpm/events.html
new file mode 100644 (file)
index 0000000..372ccee
--- /dev/null
@@ -0,0 +1,161 @@
+<HTML>
+<HEAD>
+<TITLE>What are the different event types and data?</TITLE>
+</HEAD>
+<BODY>
+
+<P><B>Links</B>: <A HREF=sgmlselement.html>Next</A> <A HREF=sgmlsevent.html>Previous</A> <A HREF=sgmlspm.html>Up</A> <A HREF=sgmlspm.html>Top</A></P>
+
+<H1>What are the different event types and data?</H1>
+
+<P>Table 2 lists the ten
+different event types returned by the <TT>next_event</TT>
+method of an <A HREF=sgmls.html><TT>SGMLS</TT></A>
+object and the different types of data associated with each of these
+(note that these do <EM>not</EM> correspond to the
+standard <B>ESIS</B> events).</P>
+
+
+<H3>Table 2: The <TT>SGMLS_Event</TT> types</H3>
+
+<HR>
+<DL>
+<DT><B>Event Type</B></DT>
+<DD><TT>'start_element'</TT></DD>
+<DT><B>Event Data</B></DT>
+<DD><TT>SGMLS_Element</TT></DD>
+<DT><B>Description</B></DT>
+<DD>The beginning of an element.</DD>
+
+</DL>
+<HR>
+
+
+<DL>
+<DT><B>Event Type</B></DT>
+<DD><TT>'end_element'</TT></DD>
+<DT><B>Event Data</B></DT>
+<DD><TT>SGMLS_Element</TT></DD>
+<DT><B>Description</B></DT>
+<DD>The end of an element.</DD>
+
+</DL>
+<HR>
+
+
+<DL>
+<DT><B>Event Type</B></DT>
+<DD><TT>'cdata'</TT></DD>
+<DT><B>Event Data</B></DT>
+<DD>string</DD>
+<DT><B>Description</B></DT>
+<DD>Regular character data.</DD>
+
+</DL>
+<HR>
+
+
+<DL>
+<DT><B>Event Type</B></DT>
+<DD><TT>'sdata'</TT></DD>
+<DT><B>Event Data</B></DT>
+<DD>string</DD>
+<DT><B>Description</B></DT>
+<DD>Special system data.</DD>
+
+</DL>
+<HR>
+
+
+<DL>
+<DT><B>Event Type</B></DT>
+<DD><TT>'re'</TT></DD>
+<DT><B>Event Data</B></DT>
+<DD>[none]</DD>
+<DT><B>Description</B></DT>
+<DD>A record-end (i.e., a newline).</DD>
+
+</DL>
+<HR>
+
+
+<DL>
+<DT><B>Event Type</B></DT>
+<DD><TT>'pi'</TT></DD>
+<DT><B>Event Data</B></DT>
+<DD>string</DD>
+<DT><B>Description</B></DT>
+<DD>A processing instruction</DD>
+
+</DL>
+<HR>
+
+
+<DL>
+<DT><B>Event Type</B></DT>
+<DD><TT>'entity'</TT></DD>
+<DT><B>Event Data</B></DT>
+<DD><TT>SGMLS_Entity</TT></DD>
+<DT><B>Description</B></DT>
+<DD>A non-SGML external entity.</DD>
+
+</DL>
+<HR>
+
+
+<DL>
+<DT><B>Event Type</B></DT>
+<DD><TT>'start_subdoc'</TT></DD>
+<DT><B>Event Data</B></DT>
+<DD><TT>SGMLS_Entity</TT></DD>
+<DT><B>Description</B></DT>
+<DD>The beginning of an SGML subdocument.</DD>
+
+</DL>
+<HR>
+
+
+<DL>
+<DT><B>Event Type</B></DT>
+<DD><TT>'end_subdoc'</TT></DD>
+<DT><B>Event Data</B></DT>
+<DD><TT>SGMLS_Entity</TT></DD>
+<DT><B>Description</B></DT>
+<DD>The end of an SGML subdocument.</DD>
+
+</DL>
+<HR>
+
+
+<DL>
+<DT><B>Event Type</B></DT>
+<DD><TT>'conforming'</TT></DD>
+<DT><B>Event Data</B></DT>
+<DD>[none]</DD>
+<DT><B>Description</B></DT>
+<DD>The document was valid.</DD>
+
+</DL>
+<HR>
+
+
+<P>For example, if <TT>$event->type</TT> returns
+<TT>'start_element'</TT>, then
+<TT>$event->data</TT> will return an object belonging to the
+<A HREF=sgmlselement.html><TT>SGMLS_Element</TT></A>
+class (which will contain a list of attributes, etc. -- see
+below), <TT>$event->file</TT> and
+<TT>$event->line</TT> will return the file and line-number
+in which the element appeared (if you called <TT>sgmls</TT> or <A HREF="http://www.jclark.com/sp.html"><TT>nsgmls</TT></A> with
+the <IT>-l</IT> flag), and
+<TT>$event->element</TT> will return the element currently
+in force (in this case, the same as
+<TT>$event->data</TT>).</P>
+
+
+<P><B>Links</B>: <A HREF=sgmlselement.html>Next</A> <A HREF=sgmlsevent.html>Previous</A> <A HREF=sgmlspm.html>Up</A> <A HREF=sgmlspm.html>Top</A></P>
+
+
+<ADDRESS>David Megginson <A HREF="mailto:dmeggins@aix1.uottawa.ca">&lt;dmeggins@aix1.uottawa.ca&gt;</A></ADDRESS>
+</BODY>
+</HTML>
diff --git a/DOC/HTML/SGMLSpm/example.html b/DOC/HTML/SGMLSpm/example.html
new file mode 100644 (file)
index 0000000..a263f30
--- /dev/null
@@ -0,0 +1,82 @@
+<HTML>
+<HEAD>
+<TITLE>How about a simple example?</TITLE>
+</HEAD>
+<BODY>
+
+<P><B>Links</B>: <A HREF=extend.html>Next</A> <A HREF=xtrainfo.html>Previous</A> <A HREF=sgmlspm.html>Up</A> <A HREF=sgmlspm.html>Top</A></P>
+
+<H1>How about a simple example?</H1>
+
+<P>OK.  The following script simply reports its events:</P>
+
+<P>
+<PRE>#!/usr/bin/perl
+
+use SGMLS;
+
+$this_parse = new SGMLS(STDIN); # Read from standard input.
+
+while ($this_event = $this_parse-&gt;next_event) {
+    my $type = $this_event-&gt;type;
+    my $data = $this_event-&gt;data;
+  SWITCH: {
+      $type eq 'start_element' &amp;&amp; do {
+          print "Beginning element: " . $data-&gt;name . "\n";
+          last SWITCH;
+      };
+      $type eq 'end_element' &amp;&amp; do {
+          print "Ending element: " . $data-&gt;name . "\n";
+          last SWITCH;
+      };
+      $type eq 'cdata' &amp;&amp; do {
+          print "Character data: " . $data . "\n";
+          last SWITCH;
+      };
+      $type eq 'sdata' &amp;&amp; do {
+          print "Special data: " . $data . "\n";
+          last SWITCH;
+      };
+      $type eq 're' &amp;&amp; do {
+          print "Record End\n";
+          last SWITCH;
+      };
+      $type eq 'pi' &amp;&amp; do {
+          print "Processing Instruction: " . $data . "\n";
+          last SWITCH;
+      };
+      $type eq 'entity' &amp;&amp; do {
+          print "External Data Entity: " . $data-&gt;name .
+              " with notation " . $data-&gt;notation-&gt;name . "\n";
+          last SWITCH;
+      };
+      $type eq 'start_subdoc' &amp;&amp; do {
+          print "Beginning Subdocument Entity: " . $data-&gt;name . "\n";
+          last SWITCH;
+      };
+      $type eq 'end_subdoc' &amp;&amp; do {
+          print "Ending Subdocument Entity: " . $data-&gt;name . "\n";
+          last SWITCH;
+      };
+      $type eq 'conforming' &amp;&amp; do {
+          print "This is a conforming SGML document\n";
+          last SWITCH;
+      };
+  }
+}
+</PRE>
+</P>
+<P>To use it under Unix, try something like</P>
+
+<P>
+<PRE>sgmls document.sgml | perl sample.pl</PRE>
+</P>
+<P>and watch the output scroll down.</P>
+
+
+<P><B>Links</B>: <A HREF=extend.html>Next</A> <A HREF=xtrainfo.html>Previous</A> <A HREF=sgmlspm.html>Up</A> <A HREF=sgmlspm.html>Top</A></P>
+
+
+<ADDRESS>David Megginson <A HREF="mailto:dmeggins@aix1.uottawa.ca">&lt;dmeggins@aix1.uottawa.ca&gt;</A></ADDRESS>
+</BODY>
+</HTML>
diff --git a/DOC/HTML/SGMLSpm/extend.html b/DOC/HTML/SGMLSpm/extend.html
new file mode 100644 (file)
index 0000000..a40bd8c
--- /dev/null
@@ -0,0 +1,59 @@
+<HTML>
+<HEAD>
+<TITLE>How do I design my own classes?</TITLE>
+</HEAD>
+<BODY>
+
+<P><B>Links</B>: <A HREF=bugs.html>Next</A> <A HREF=example.html>Previous</A> <A HREF=sgmlspm.html>Up</A> <A HREF=sgmlspm.html>Top</A></P>
+
+<H1>How do I design my <EM>own</EM> classes?</H1>
+
+<P>In addition to the methods listed above, all of the classes used
+in <A HREF=sgmlspm.html><TT>SGMLS.pm</TT></A> have an <TT>ext</TT> method which returns a
+reference to an initially-empty hash table.  You are free to use this
+hash table to store <EM>anything</EM> you want -- it
+should be especially useful if you are building your own, derived
+classes from the ones provided here.  The following example builds a
+derived class <TT>My_Element</TT> from the <A HREF=sgmlselement.html><TT>SGMLS_Element</TT></A>
+class, adding methods to set and get the current font:</P>
+
+<P>
+<PRE>use SGMLS;
+
+package My_Element;
+@ISA = qw(SGMLS_Element);
+
+sub new {
+  my ($class,$element,$font) = @_;
+  $element->ext->{'font'} = $font;
+  return bless $element;
+}
+
+sub get_font {
+  my ($self) = @_;
+  return $self->ext->{'font'};
+}
+
+sub set_font {
+  my ($self,$font) = @_;
+  $self->ext->{'font'} = $font;
+}</PRE>
+</P>
+<P>Note that the derived class does not need to have any knowledge
+about the underlying structure of the <A HREF=sgmlselement.html><TT>SGMLS_Element</TT></A>
+class, and need only avoid shadowing any of the methods currently
+existing there.</P>
+
+<P>If you decide to create a derived class from the <A HREF=sgmls.html><TT>SGMLS</TT></A>, please note that in
+addition to the methods listed above, that class uses internal methods
+named <TT>element</TT>, <TT>line</TT>, and
+<TT>file</TT>, similar to the same methods in <A HREF=sgmlsevent.html><TT>SGMLS_Event</TT></A> --
+it is essential that you not shadow these method names.</P>
+
+
+<P><B>Links</B>: <A HREF=bugs.html>Next</A> <A HREF=example.html>Previous</A> <A HREF=sgmlspm.html>Up</A> <A HREF=sgmlspm.html>Top</A></P>
+
+
+<ADDRESS>David Megginson <A HREF="mailto:dmeggins@aix1.uottawa.ca">&lt;dmeggins@aix1.uottawa.ca&gt;</A></ADDRESS>
+</BODY>
+</HTML>
diff --git a/DOC/HTML/SGMLSpm/perl5.html b/DOC/HTML/SGMLSpm/perl5.html
new file mode 100644 (file)
index 0000000..4a68f91
--- /dev/null
@@ -0,0 +1,26 @@
+<HTML>
+<HEAD>
+<TITLE>How do I program in perl5?</TITLE>
+</HEAD>
+<BODY>
+
+<P><B>Links</B>: <A HREF=sgmls.html>Next</A> <A HREF=sgml.html>Previous</A> <A HREF=sgmlspm.html>Up</A> <A HREF=sgmlspm.html>Top</A></P>
+
+<H1>How do I program in <A HREF="http://www.metronet.com/0/perlinfo/perl5/manual/perl.html"><TT>perl5</TT></A>?</H1>
+
+<P>If you have to ask this question, you probably should not be
+trying to use this library right now, since it is intended only for
+experienced <A HREF="http://www.metronet.com/0/perlinfo/perl5/manual/perl.html"><TT>perl5</TT></A> programmers.  That said, however, you can find the
+<A HREF="http://www.metronet.com/0/perlinfo/perl5/manual/perl.html"><TT>perl5</TT></A> documentation with the <A HREF="http://www.metronet.com/0/perlinfo/perl5/manual/perl.html"><TT>perl5</TT></A> source distribution or on the
+World-Wide Web at <A HREF="http://www.metronet.com/0/perlinfo/perl5/manual/perl.html"><TT>http://www.metronet.com/0/perlinfo/perl5/manual/perl.html</TT></A>.</P>
+
+<P><EM>Please</EM> do not write to me for help on using
+<A HREF="http://www.metronet.com/0/perlinfo/perl5/manual/perl.html"><TT>perl5</TT></A>.</P>
+
+
+<P><B>Links</B>: <A HREF=sgmls.html>Next</A> <A HREF=sgml.html>Previous</A> <A HREF=sgmlspm.html>Up</A> <A HREF=sgmlspm.html>Top</A></P>
+
+
+<ADDRESS>David Megginson <A HREF="mailto:dmeggins@aix1.uottawa.ca">&lt;dmeggins@aix1.uottawa.ca&gt;</A></ADDRESS>
+</BODY>
+</HTML>
diff --git a/DOC/HTML/SGMLSpm/sample.pl b/DOC/HTML/SGMLSpm/sample.pl
new file mode 120000 (symlink)
index 0000000..36d789d
--- /dev/null
@@ -0,0 +1 @@
+../../sample.pl
\ No newline at end of file
diff --git a/DOC/HTML/SGMLSpm/sgml.html b/DOC/HTML/SGMLSpm/sgml.html
new file mode 100644 (file)
index 0000000..193f8a0
--- /dev/null
@@ -0,0 +1,23 @@
+<HTML>
+<HEAD>
+<TITLE>How do I produce SGML documents?</TITLE>
+</HEAD>
+<BODY>
+
+<P><B>Links</B>: <A HREF=perl5.html>Next</A> <A HREF=definition.html>Previous</A> <A HREF=sgmlspm.html>Up</A> <A HREF=sgmlspm.html>Top</A></P>
+
+<H1>How do I produce <A HREF="http://www.sil.org/sgml/sgml.html"><B>SGML</B></A> documents?</H1>
+
+<P>I am presuming here that you are already experienced with <A HREF="http://www.sil.org/sgml/sgml.html"><B>SGML</B></A>
+and the <TT>sgmls</TT> or <A HREF="http://www.jclark.com/sp.html"><TT>nsgmls</TT></A> parser.  For help with the parsers see the
+manual pages accompanying each one; for help with <A HREF="http://www.sil.org/sgml/sgml.html"><B>SGML</B></A> see Robin
+Cover's SGML Web Page at <A HREF="http://www.sil.org/sgml/sgml.html"><TT>http://www.sil.org/sgml/sgml.html</TT></A>
+on the Internet.</P>
+
+
+<P><B>Links</B>: <A HREF=perl5.html>Next</A> <A HREF=definition.html>Previous</A> <A HREF=sgmlspm.html>Up</A> <A HREF=sgmlspm.html>Top</A></P>
+
+
+<ADDRESS>David Megginson <A HREF="mailto:dmeggins@aix1.uottawa.ca">&lt;dmeggins@aix1.uottawa.ca&gt;</A></ADDRESS>
+</BODY>
+</HTML>
diff --git a/DOC/HTML/SGMLSpm/sgmls.html b/DOC/HTML/SGMLSpm/sgmls.html
new file mode 100644 (file)
index 0000000..6d0bb29
--- /dev/null
@@ -0,0 +1,64 @@
+<HTML>
+<HEAD>
+<TITLE>How do I use SGMLS.pm?</TITLE>
+</HEAD>
+<BODY>
+
+<P><B>Links</B>: <A HREF=sgmlsevent.html>Next</A> <A HREF=perl5.html>Previous</A> <A HREF=sgmlspm.html>Up</A> <A HREF=sgmlspm.html>Top</A></P>
+
+<H1>How do I use <A HREF=sgmlspm.html><TT>SGMLS.pm</TT></A>?</H1>
+
+<P>First, you need to copy the file <A HREF=sgmlspm.html><TT>SGMLS.pm</TT></A> to a directory where
+perl can find it (on a Unix system, it might be
+<TT>/usr/lib/perl5</TT> or
+<TT>/usr/local/lib/perl5</TT>, or whatever the environment
+variable <TT>PERL5LIB</TT> is set to) and make certain that it
+is world-readable.</P>
+
+<P>Next, near the top of your <A HREF="http://www.metronet.com/0/perlinfo/perl5/manual/perl.html"><TT>perl5</TT></A> program, type the following
+line:</P>
+
+<P>
+<PRE>use SGMLS;</PRE>
+</P>
+<P>You must then open up a file handle from which <A HREF=sgmlspm.html><TT>SGMLS.pm</TT></A> can read the
+data from an <TT>sgmls</TT> or <A HREF="http://www.jclark.com/sp.html"><TT>nsgmls</TT></A> process, unless you are reading from
+a standard handle like <TT>STDIN</TT> -- for example,
+if you are piping the output from <TT>sgmls</TT> to a <A HREF="http://www.metronet.com/0/perlinfo/perl5/manual/perl.html"><TT>perl5</TT></A> script, using
+something like</P>
+
+<P>
+<PRE>sgmls foo.sgml | perl myscript.pl</PRE>
+</P>
+<P>then the predefined filehandle <TT>STDIN</TT> will be
+sufficient.  In DOS, you might want to dump the sgmls output to a file
+and use it as standard input (or open it explicitly in perl), and in
+Unix, you might actually want to open a pipe or socket for the input.
+<A HREF=sgmlspm.html><TT>SGMLS.pm</TT></A> doesn't need to seek, so any input stream should
+work.</P>
+
+<P>To parse the <TT>sgmls</TT> or <A HREF="http://www.jclark.com/sp.html"><TT>nsgmls</TT></A> output from the handle, create
+a new object instance of the <TT>SGMLS</TT> class with
+the handle as an argument, i.e.</P>
+
+<P>
+<PRE>$parse = new SGMLS(STDIN);</PRE>
+</P>
+<P>(You may create more than one <TT>SGMLS</TT>
+object at once, but each object <EM>must</EM> have a
+unique handle pointing to a unique stream, or
+<EM>chaos</EM> will result.)  Now, you can retrieve and
+process events using the <TT>next_event</TT> method:</P>
+
+<P>
+<PRE>while ($event = $parse->next_event) {
+    #do something with each event
+}</PRE>
+</P>
+
+<P><B>Links</B>: <A HREF=sgmlsevent.html>Next</A> <A HREF=perl5.html>Previous</A> <A HREF=sgmlspm.html>Up</A> <A HREF=sgmlspm.html>Top</A></P>
+
+
+<ADDRESS>David Megginson <A HREF="mailto:dmeggins@aix1.uottawa.ca">&lt;dmeggins@aix1.uottawa.ca&gt;</A></ADDRESS>
+</BODY>
+</HTML>
diff --git a/DOC/HTML/SGMLSpm/sgmlsattribute.html b/DOC/HTML/SGMLSpm/sgmlsattribute.html
new file mode 100644 (file)
index 0000000..c5a7857
--- /dev/null
@@ -0,0 +1,121 @@
+<HTML>
+<HEAD>
+<TITLE>What do I do with an
+SGMLS_Attribute?</TITLE>
+</HEAD>
+<BODY>
+
+<P><B>Links</B>: <A HREF=sgmlsentity.html>Next</A> <A HREF=sgmlselement.html>Previous</A> <A HREF=sgmlspm.html>Up</A> <A HREF=sgmlspm.html>Top</A></P>
+
+<H1>What do I do with an
+<TT>SGMLS_Attribute</TT>?</H1>
+
+<P>Note that objects of the <TT>SGMLS_Attribute</TT>
+class do not have events in their own right, and are available only
+through the <TT>attributes</TT> or
+<TT>attribute(<IT>aname</IT>)</TT> methods for
+<A HREF=sgmlselement.html><TT>SGMLS_Element</TT></A>
+objects.  An object belonging to the
+<TT>SGMLS_Attribute</TT> class will recognise the
+methods listed in table 4.</P>
+
+
+<H3>Table 4: The <TT>SGMLS_Attribute</TT> class</H3>
+
+<HR>
+<DL>
+<DT><B>Method</B></DT>
+<DD><TT>name</TT></DD>
+<DT><B>Return Type</B></DT>
+<DD>string</DD>
+<DT><B>Description</B></DT>
+<DD>The name of the attribute (in upper-case).</DD>
+
+</DL>
+<HR>
+
+
+<DL>
+<DT><B>Method</B></DT>
+<DD><TT>type</TT></DD>
+<DT><B>Return Type</B></DT>
+<DD>string</DD>
+<DT><B>Description</B></DT>
+<DD>The type of the attribute: <TT>'IMPLIED'</TT>,
+<TT>'CDATA'</TT>, <TT>'NOTATION'</TT>,
+<TT>'ENTITY'</TT>, or <TT>'TOKEN'</TT>.</DD>
+
+</DL>
+<HR>
+
+
+<DL>
+<DT><B>Method</B></DT>
+<DD><TT>value</TT></DD>
+<DT><B>Return Type</B></DT>
+<DD>string, <TT>SGMLS_Entity</TT>, or
+<TT>SGMLS_Notation</TT>.</DD>
+<DT><B>Description</B></DT>
+<DD>The value of the attribute.  If the type is
+<TT>'CDATA'</TT> or <TT>'TOKEN'</TT>, it will be a
+simple string; if it is <TT>'NOTATION'</TT> it will be an
+object belonging to the <TT>SGMLS_Notation</TT> class,
+and if it is <TT>'Entity'</TT> it will be an object
+belonging to the <TT>SGMLS_Entity</TT> class.</DD>
+
+</DL>
+<HR>
+
+
+<DL>
+<DT><B>Method</B></DT>
+<DD><TT>is_implied</TT></DD>
+<DT><B>Return Type</B></DT>
+<DD>boolean</DD>
+<DT><B>Description</B></DT>
+<DD>Return true if the value of the attribute is implied, or false if
+it has an explicit value.</DD>
+
+</DL>
+<HR>
+
+
+<DL>
+<DT><B>Method</B></DT>
+<DD><TT>set_type(<IT>type</IT>)</TT></DD>
+<DT><B>Return Type</B></DT>
+<DD>[none]</DD>
+<DT><B>Description</B></DT>
+<DD>Provide a new type for the current attribute -- no sanity
+checking will be performed, so be careful.</DD>
+
+</DL>
+<HR>
+
+
+<DL>
+<DT><B>Method</B></DT>
+<DD><TT>set_value(<IT>value</IT>)</TT></DD>
+<DT><B>Return Type</B></DT>
+<DD>[none]</DD>
+<DT><B>Description</B></DT>
+<DD>Provide a new value for the current attribute -- no sanity
+checking will be performed, so be careful.</DD>
+
+</DL>
+<HR>
+
+
+<P>Note that the type <TT>'TOKEN'</TT> includes both
+individual tokens and lists of tokens (ie <TT>'TOKENS'</TT>,
+<TT>'IDS'</TT>, or <TT>'IDREFS'</TT> in the
+original <A HREF="http://www.sil.org/sgml/sgml.html"><B>SGML</B></A> document), so you might need to use the perl function
+'split' to break the value string into a list.</P>
+
+
+<P><B>Links</B>: <A HREF=sgmlsentity.html>Next</A> <A HREF=sgmlselement.html>Previous</A> <A HREF=sgmlspm.html>Up</A> <A HREF=sgmlspm.html>Top</A></P>
+
+
+<ADDRESS>David Megginson <A HREF="mailto:dmeggins@aix1.uottawa.ca">&lt;dmeggins@aix1.uottawa.ca&gt;</A></ADDRESS>
+</BODY>
+</HTML>
diff --git a/DOC/HTML/SGMLSpm/sgmlselement.html b/DOC/HTML/SGMLSpm/sgmlselement.html
new file mode 100644 (file)
index 0000000..5a12466
--- /dev/null
@@ -0,0 +1,147 @@
+<HTML>
+<HEAD>
+<TITLE>What do I do with an SGMLS_Element?</TITLE>
+</HEAD>
+<BODY>
+
+<P><B>Links</B>: <A HREF=sgmlsattribute.html>Next</A> <A HREF=events.html>Previous</A> <A HREF=sgmlspm.html>Up</A> <A HREF=sgmlspm.html>Top</A></P>
+
+<H1>What do I do with an <TT>SGMLS_Element</TT>?</H1>
+
+<P>Altogether, there are six classes in <A HREF=sgmlspm.html><TT>SGMLS.pm</TT></A>, each with its
+own methods: in addition to <A HREF=sgmls.html><TT>SGMLS</TT></A> (for the parse) and
+<A HREF=sgmlsevent.html><TT>SGMLS_Event</TT></A>
+(for a specific event), the classes are
+<TT>SGMLS_Element</TT>, <A HREF=sgmlsattribute.html><TT>SGMLS_Attribute</TT></A>,
+<A HREF=sgmlsentity.html><TT>SGMLS_Entity</TT></A>,
+and <A HREF=sgmlsnotation.html><TT>SGMLS_Notation</TT></A>.
+Like all of these, <TT>SGMLS_Element</TT> has a number
+of methods available for obtaining different types of information.
+For example, if you were to use</P>
+
+<P>
+<PRE>my $element = $event->data</PRE>
+</P>
+<P>to retrieve the data for a <TT>'start_element'</TT> or
+<TT>'end_element'</TT> event, then you could use the methods
+listed in table 3 to find more
+information about the element.</P>
+
+
+<H3>Table 3: The <TT>SGMLS_Element</TT> class</H3>
+
+<HR>
+<DL>
+<DT><B>Method</B></DT>
+<DD><TT>name</TT></DD>
+<DT><B>Return Type</B></DT>
+<DD>string</DD>
+<DT><B>Description</B></DT>
+<DD>The name (or GI), in upper-case.</DD>
+
+</DL>
+<HR>
+
+
+<DL>
+<DT><B>Method</B></DT>
+<DD><TT>parent</TT></DD>
+<DT><B>Return Type</B></DT>
+<DD><TT>SGMLS_Element</TT></DD>
+<DT><B>Description</B></DT>
+<DD>The parent element, or <TT>''</TT> if this is the top
+element.</DD>
+
+</DL>
+<HR>
+
+
+<DL>
+<DT><B>Method</B></DT>
+<DD><TT>attributes</TT></DD>
+<DT><B>Return Type</B></DT>
+<DD>HASH</DD>
+<DT><B>Description</B></DT>
+<DD>Return a reference to a hash table of
+<TT>SGMLS_Attribute</TT> objects, keyed by the attribute
+names (in upper-case).</DD>
+
+</DL>
+<HR>
+
+
+<DL>
+<DT><B>Method</B></DT>
+<DD><TT>attribute_names</TT></DD>
+<DT><B>Return Type</B></DT>
+<DD>ARRAY</DD>
+<DT><B>Description</B></DT>
+<DD>A list of all attribute names for the current element (in
+upper-case).</DD>
+
+</DL>
+<HR>
+
+
+<DL>
+<DT><B>Method</B></DT>
+<DD><TT>attribute(<IT>aname</IT>)</TT></DD>
+<DT><B>Return Type</B></DT>
+<DD><TT>SGMLS_Attribute</TT></DD>
+<DT><B>Description</B></DT>
+<DD>Return the attribute named ANAME.</DD>
+
+</DL>
+<HR>
+
+
+<DL>
+<DT><B>Method</B></DT>
+<DD><TT>set_attribute(<IT>attribute</IT>)</TT></DD>
+<DT><B>Return Type</B></DT>
+<DD>[none]</DD>
+<DT><B>Description</B></DT>
+<DD>The <IT>attribute</IT> argument should be an
+object belonging to the <A HREF="sgmlsattribute.html"><TT>SGMLS_Attribute</TT></A>
+class.  Add it to the element, replacing any previous attribute with
+the same name.</DD>
+
+</DL>
+<HR>
+
+
+<DL>
+<DT><B>Method</B></DT>
+<DD><TT>in(<IT>name</IT>)</TT></DD>
+<DT><B>Return Type</B></DT>
+<DD><TT>SGMLS_Element</TT></DD>
+<DT><B>Description</B></DT>
+<DD>If the current element's parent is named
+<IT>name</IT>, return the parent; otherwise, return
+<TT>''</TT>.</DD>
+
+</DL>
+<HR>
+
+
+<DL>
+<DT><B>Method</B></DT>
+<DD><TT>within(<IT>name</IT>)</TT></DD>
+<DT><B>Return Type</B></DT>
+<DD><TT>SGMLS_Element</TT></DD>
+<DT><B>Description</B></DT>
+<DD>If any ancestor of the current element is named
+<IT>name</IT>, return it; otherwise, return
+<TT>''</TT>.</DD>
+
+</DL>
+<HR>
+
+
+
+<P><B>Links</B>: <A HREF=sgmlsattribute.html>Next</A> <A HREF=events.html>Previous</A> <A HREF=sgmlspm.html>Up</A> <A HREF=sgmlspm.html>Top</A></P>
+
+
+<ADDRESS>David Megginson <A HREF="mailto:dmeggins@aix1.uottawa.ca">&lt;dmeggins@aix1.uottawa.ca&gt;</A></ADDRESS>
+</BODY>
+</HTML>
diff --git a/DOC/HTML/SGMLSpm/sgmlsentity.html b/DOC/HTML/SGMLSpm/sgmlsentity.html
new file mode 100644 (file)
index 0000000..ce61c58
--- /dev/null
@@ -0,0 +1,124 @@
+<HTML>
+<HEAD>
+<TITLE>What do I do with an SGMLS_Entity?</TITLE>
+</HEAD>
+<BODY>
+
+<P><B>Links</B>: <A HREF=sgmlsnotation.html>Next</A> <A HREF=sgmlsattribute.html>Previous</A> <A HREF=sgmlspm.html>Up</A> <A HREF=sgmlspm.html>Top</A></P>
+
+<H1>What do I do with an <TT>SGMLS_Entity</TT>?</H1>
+
+<P>An <TT>SGMLS_Entity</TT> object can come in an
+<TT>'entity'</TT> <A HREF=events.html>event</A> (in
+which case it is always external), in a
+<TT>'start_subdoc'</TT> or <TT>'end_subdoc'</TT>
+event (in which case it always has the type
+<TT>'SUBDOC'</TT>), or as the value of an attribute (in
+which case it may be internal or external).  An object belonging to
+the <TT>SGMLS_Entity</TT> class may use the methods
+listed in table 5.</P>
+
+
+<H3>Table 5: The <TT>SGMLS_Entity</TT> class</H3>
+
+<HR>
+<DL>
+<DT><B>Method</B></DT>
+<DD><TT>name</TT></DD>
+<DT><B>Return Type</B></DT>
+<DD>string</DD>
+<DT><B>Description</B></DT>
+<DD>The entity name.</DD>
+
+</DL>
+<HR>
+
+
+<DL>
+<DT><B>Method</B></DT>
+<DD><TT>type</TT></DD>
+<DT><B>Return Type</B></DT>
+<DD>string</DD>
+<DT><B>Description</B></DT>
+<DD>The entity type: <TT>'CDATA'</TT>,
+<TT>'SDATA'</TT>, <TT>'NDATA'</TT>, or
+<TT>'SUBDOC'</TT>.</DD>
+
+</DL>
+<HR>
+
+
+<DL>
+<DT><B>Method</B></DT>
+<DD><TT>value</TT></DD>
+<DT><B>Return Type</B></DT>
+<DD>string</DD>
+<DT><B>Description</B></DT>
+<DD>The entity replacement text (internal entities
+only).</DD>
+
+</DL>
+<HR>
+
+
+<DL>
+<DT><B>Method</B></DT>
+<DD><TT>sysid</TT></DD>
+<DT><B>Return Type</B></DT>
+<DD>string</DD>
+<DT><B>Description</B></DT>
+<DD>The system identifier (external entities only).</DD>
+
+</DL>
+<HR>
+
+
+<DL>
+<DT><B>Method</B></DT>
+<DD><TT>pubid</TT></DD>
+<DT><B>Return Type</B></DT>
+<DD>string</DD>
+<DT><B>Description</B></DT>
+<DD>The public identifier (external entities only).</DD>
+
+</DL>
+<HR>
+
+
+<DL>
+<DT><B>Method</B></DT>
+<DD><TT>filenames</TT></DD>
+<DT><B>Return Type</B></DT>
+<DD>ARRAY</DD>
+<DT><B>Description</B></DT>
+<DD>A list of file names generated from the sysid and pubid
+(external entities only).</DD>
+
+</DL>
+<HR>
+
+
+<DL>
+<DT><B>Method</B></DT>
+<DD><TT>notation</TT></DD>
+<DT><B>Return Type</B></DT>
+<DD><TT>SGMLS_Notation</TT></DD>
+<DT><B>Description</B></DT>
+<DD>The associated notation (external data entities only).</DD>
+
+</DL>
+<HR>
+
+
+<P>An entity of type <TT>'SUBDOC'</TT> will have a sysid
+and pubid, and external data entity will have a sysid, pubid,
+filenames, and a notation, and an internal data entity will have a
+value.</P>
+
+
+<P><B>Links</B>: <A HREF=sgmlsnotation.html>Next</A> <A HREF=sgmlsattribute.html>Previous</A> <A HREF=sgmlspm.html>Up</A> <A HREF=sgmlspm.html>Top</A></P>
+
+
+<ADDRESS>David Megginson <A HREF="mailto:dmeggins@aix1.uottawa.ca">&lt;dmeggins@aix1.uottawa.ca&gt;</A></ADDRESS>
+</BODY>
+</HTML>
diff --git a/DOC/HTML/SGMLSpm/sgmlsevent.html b/DOC/HTML/SGMLSpm/sgmlsevent.html
new file mode 100644 (file)
index 0000000..85a070d
--- /dev/null
@@ -0,0 +1,127 @@
+<HTML>
+<HEAD>
+<TITLE>So what do I do with an event?</TITLE>
+</HEAD>
+<BODY>
+
+<P><B>Links</B>: <A HREF=events.html>Next</A> <A HREF=sgmls.html>Previous</A> <A HREF=sgmlspm.html>Up</A> <A HREF=sgmlspm.html>Top</A></P>
+
+<H1>So what do I do with an event?</H1>
+
+<P>The <TT>next_event</TT> method for the <A HREF=sgmls.html><TT>SGMLS</TT></A> class returns an
+object belonging to the class <TT>SGMLS_Event</TT>.
+This class has several methods available, as listed in table 1.</P>
+
+
+<H3>Table 1: The <TT>SGMLS_Event</TT> class</H3>
+
+<HR>
+<DL>
+<DT><B>Method</B></DT>
+<DD><TT>type</TT></DD>
+<DT><B>Return Type</B></DT>
+<DD>string</DD>
+<DT><B>Description</B></DT>
+<DD>Return the type of the event.</DD>
+
+</DL>
+<HR>
+
+
+<DL>
+<DT><B>Method</B></DT>
+<DD><TT>data</TT></DD>
+<DT><B>Return Type</B></DT>
+<DD>string, <TT>SGMLS_Element</TT>, or
+<TT>SGMLS_Entity</TT></DD>
+<DT><B>Description</B></DT>
+<DD>Return any data associated with the event.</DD>
+
+</DL>
+<HR>
+
+
+<DL>
+<DT><B>Method</B></DT>
+<DD><TT>file</TT></DD>
+<DT><B>Return Type</B></DT>
+<DD>string</DD>
+<DT><B>Description</B></DT>
+<DD>Return the name of the <A HREF="http://www.sil.org/sgml/sgml.html"><B>SGML</B></A> source file which generated the
+event, if available.</DD>
+
+</DL>
+<HR>
+
+
+<DL>
+<DT><B>Method</B></DT>
+<DD><TT>line</TT></DD>
+<DT><B>Return Type</B></DT>
+<DD>string</DD>
+<DT><B>Description</B></DT>
+<DD>Return the line number of the <A HREF="http://www.sil.org/sgml/sgml.html"><B>SGML</B></A> source file which
+generated the event, if available.</DD>
+
+</DL>
+<HR>
+
+
+<DL>
+<DT><B>Method</B></DT>
+<DD><TT>element</TT></DD>
+<DT><B>Return Type</B></DT>
+<DD><TT>SGMLS_Element</TT></DD>
+<DT><B>Description</B></DT>
+<DD>Return the element in force when the  event was
+generated.</DD>
+
+</DL>
+<HR>
+
+
+<DL>
+<DT><B>Method</B></DT>
+<DD><TT>parse</TT></DD>
+<DT><B>Return Type</B></DT>
+<DD>Return the <TT>SGMLS</TT> object for the current
+parse.</DD>
+
+</DL>
+<HR>
+
+
+<DL>
+<DT><B>Method</B></DT>
+<DD><TT>entity(<IT>ename</IT>)</TT></DD>
+<DT><B>Return Type</B></DT>
+<DD>Look up an entity from those currently known to the parse.  An
+alias for <TT>->parse->entity($ename)</TT></DD>
+
+</DL>
+<HR>
+
+
+<DL>
+<DT><B>Method</B></DT>
+<DD><TT>notation(<IT>nname</IT>)</TT></DD>
+<DT><B>Return Type</B></DT>
+<DD>Look up the notation from those currently known to the parse:
+an alias for <TT>->parse->notation($nname)</TT>.</DD>
+
+</DL>
+<HR>
+
+
+<P>The <TT>file</TT> and <TT>line</TT> methods
+will return useful information only if you called <TT>sgmls</TT> or <A HREF="http://www.jclark.com/sp.html"><TT>nsgmls</TT></A>
+with the <IT>-l</IT> flag to include file and
+line-number information.</P>
+
+
+<P><B>Links</B>: <A HREF=events.html>Next</A> <A HREF=sgmls.html>Previous</A> <A HREF=sgmlspm.html>Up</A> <A HREF=sgmlspm.html>Top</A></P>
+
+
+<ADDRESS>David Megginson <A HREF="mailto:dmeggins@aix1.uottawa.ca">&lt;dmeggins@aix1.uottawa.ca&gt;</A></ADDRESS>
+</BODY>
+</HTML>
diff --git a/DOC/HTML/SGMLSpm/sgmlsnotation.html b/DOC/HTML/SGMLSpm/sgmlsnotation.html
new file mode 100644 (file)
index 0000000..3271f01
--- /dev/null
@@ -0,0 +1,69 @@
+<HTML>
+<HEAD>
+<TITLE>What do I do with an SGMLS_Notation?</TITLE>
+</HEAD>
+<BODY>
+
+<P><B>Links</B>: <A HREF=xtrainfo.html>Next</A> <A HREF=sgmlsentity.html>Previous</A> <A HREF=sgmlspm.html>Up</A> <A HREF=sgmlspm.html>Top</A></P>
+
+<H1>What do I do with an <TT>SGMLS_Notation</TT>?</H1>
+
+<P>The fourth data class is the notation, which is available only
+as a return value from the <TT>notation</TT> method of an
+<A HREF=sgmlsentity.html><TT>SGMLS_Entity</TT></A>
+or the <TT>value</TT> method of an <A HREF=sgmlsattribute.html><TT>SGMLS_Attribute</TT></A>
+with type <TT>'NOTATION'</TT>.  You can use the notation to
+decide how to treat non-SGML data (such as graphics).  An object
+belonging to the <TT>SGMLS_Notation</TT> class will have
+access to the methods listed in table 6.</P>
+
+
+<H3>Table 6: The <TT>SGMLS_Notation class</TT></H3>
+
+<HR>
+<DL>
+<DT><B>Method</B></DT>
+<DD><TT>name</TT></DD>
+<DT><B>Return Type</B></DT>
+<DD>string</DD>
+<DT><B>Description</B></DT>
+<DD>The notation's name.</DD>
+
+</DL>
+<HR>
+
+
+<DL>
+<DT><B>Method</B></DT>
+<DD><TT>sysid</TT></DD>
+<DT><B>Return Type</B></DT>
+<DD>string</DD>
+<DT><B>Description</B></DT>
+<DD>The notation's system identifier.</DD>
+
+</DL>
+<HR>
+
+
+<DL>
+<DT><B>Method</B></DT>
+<DD><TT>pubid</TT></DD>
+<DT><B>Return Type</B></DT>
+<DD>string</DD>
+<DT><B>Description</B></DT>
+<DD>The notation's public identifier.</DD>
+
+</DL>
+<HR>
+
+
+<P>What you do with this information is
+<EM>entirely</EM> up to you.</P>
+
+
+<P><B>Links</B>: <A HREF=xtrainfo.html>Next</A> <A HREF=sgmlsentity.html>Previous</A> <A HREF=sgmlspm.html>Up</A> <A HREF=sgmlspm.html>Top</A></P>
+
+
+<ADDRESS>David Megginson <A HREF="mailto:dmeggins@aix1.uottawa.ca">&lt;dmeggins@aix1.uottawa.ca&gt;</A></ADDRESS>
+</BODY>
+</HTML>
diff --git a/DOC/HTML/SGMLSpm/sgmlspm.html b/DOC/HTML/SGMLSpm/sgmlspm.html
new file mode 100644 (file)
index 0000000..fd81bd2
--- /dev/null
@@ -0,0 +1,38 @@
+<HTML>
+<HEAD>
+<TITLE>SGMLS.pm: a perl5 class library for handling output from the
+SGMLS and NSGMLS parsers (version 1.03)</TITLE>
+</HEAD>
+<BODY>
+<H1>SGMLS.pm: a perl5 class library for handling output from the
+SGMLS and NSGMLS parsers (version 1.03)</H1>
+
+<P>Welcome to <A HREF=sgmlspm.html><TT>SGMLS.pm</TT></A>, an extensible <A HREF="http://www.metronet.com/0/perlinfo/perl5/manual/perl.html"><TT>perl5</TT></A> class library for
+processing the output from the <TT>sgmls</TT> and <A HREF="http://www.jclark.com/sp.html"><TT>nsgmls</TT></A> parsers.
+<A HREF=sgmlspm.html><TT>SGMLS.pm</TT></A> is free, copyrighted software available by anonymous ftp in
+the directory <A HREF="ftp://aix1.uottawa.ca/pub/dmeggins/">ftp://aix1.uottawa.ca/pub/dmeggins/</A>.
+You might also want to look at the documentation for <A HREF="../sgmlspl/sgmlspl.html"><TT>sgmlspl</TT></A>,
+a simple sample script which uses <A HREF=sgmlspm.html><TT>SGMLS.pm</TT></A> to convert documents from
+<A HREF="http://www.sil.org/sgml/sgml.html"><B>SGML</B></A> to other formats.</P>
+
+<LI><A HREF="terms.html">Terms</A></LI>
+<LI><A HREF="definition.html">What is SGMLS.pm?</A></LI>
+<LI><A HREF="sgml.html">How do I produce SGML documents?</A></LI>
+<LI><A HREF="perl5.html">How do I program in perl5?</A></LI>
+<LI><A HREF="sgmls.html">How do I use SGMLS.pm?</A></LI>
+<LI><A HREF="sgmlsevent.html">So what do I do with an event?</A></LI>
+<LI><A HREF="events.html">What are the different event types and data?</A></LI>
+<LI><A HREF="sgmlselement.html">What do I do with an SGMLS_Element?</A></LI>
+<LI><A HREF="sgmlsattribute.html">What do I do with an
+SGMLS_Attribute?</A></LI>
+<LI><A HREF="sgmlsentity.html">What do I do with an SGMLS_Entity?</A></LI>
+<LI><A HREF="sgmlsnotation.html">What do I do with an SGMLS_Notation?</A></LI>
+<LI><A HREF="xtrainfo.html">Is there any extra information available from the SGML
+document?</A></LI>
+<LI><A HREF="example.html">How about a simple example?</A></LI>
+<LI><A HREF="extend.html">How do I design my own classes?</A></LI>
+<LI><A HREF="bugs.html">Are there any bugs?</A></LI>
+
+<ADDRESS>David Megginson <A HREF="mailto:dmeggins@aix1.uottawa.ca">&lt;dmeggins@aix1.uottawa.ca&gt;</A></ADDRESS>
+</BODY>
+</HTML>
diff --git a/DOC/HTML/SGMLSpm/sgmlspm.refs b/DOC/HTML/SGMLSpm/sgmlspm.refs
new file mode 100644 (file)
index 0000000..16a9330
--- /dev/null
@@ -0,0 +1,86 @@
+{
+  '' => '',
+  'title:sgmls' => 'How do I use <A HREF=sgmlspm.html><TT>SGMLS.pm</TT></A>?',
+  'previous:sgmlsevent.html' => 'sgmls.html',
+  'previous:extend.html' => 'example.html',
+  'previous:definition.html' => 'terms.html',
+  'title:definition' => 'What is <A HREF=sgmlspm.html><TT>SGMLS.pm</TT></A>?',
+  'firstname:sgmlspm' => 'David',
+  'xref:table.class.sgmls.element' => '3',
+  'orgdiv:sgmlspm' => 'Department of English',
+  'title:example' => 'How about a simple example?',
+  'title:bugs' => 'Are there any bugs?',
+  'title:sgmlsnotation' => 'What do I do with an <TT>SGMLS_Notation</TT>?',
+  'next:sgml.html' => 'perl5.html',
+  'xref:table.class.sgmls' => '1',
+  'previous:events.html' => 'sgmlsevent.html',
+  'title:events' => 'What are the different event types and data?',
+  'up:sgmlselement.html' => 'sgmlspm.html',
+  'up:sgmlsattribute.html' => 'sgmlspm.html',
+  'previous:sgmlsentity.html' => 'sgmlsattribute.html',
+  'xref:table.class.sgmls.event' => '2',
+  'xref:table.class.sgmls.extra' => '7',
+  'title:extend' => 'How do I design my <EM>own</EM> classes?',
+  'title:sgmlsevent' => 'So what do I do with an event?',
+  'email:sgmlspm' => 'dmeggins@aix1.uottawa.ca',
+  'next:xtrainfo.html' => 'example.html',
+  'title:table.class.sgmls.entity' => 'The <TT>SGMLS_Entity</TT> class',
+  'title:terms' => 'Terms',
+  'next:terms.html' => 'definition.html',
+  'xref:table.class.sgmls.notation' => '6',
+  'up:extend.html' => 'sgmlspm.html',
+  'up:sgmlsevent.html' => 'sgmlspm.html',
+  'up:definition.html' => 'sgmlspm.html',
+  'up:terms.html' => 'sgmlspm.html',
+  'previous:sgml.html' => 'definition.html',
+  'title:sgml' => 'How do I produce <A HREF="http://www.sil.org/sgml/sgml.html"><B>SGML</B></A> documents?',
+  'title:table.class.sgmls.notation' => 'The <TT>SGMLS_Notation class</TT>',
+  'up:events.html' => 'sgmlspm.html',
+  'next:sgmlsentity.html' => 'sgmlsnotation.html',
+  'previous:sgmls.html' => 'perl5.html',
+  'previous:perl5.html' => 'sgml.html',
+  'title:perl5' => 'How do I program in <A HREF="http://www.metronet.com/0/perlinfo/perl5/manual/perl.html"><TT>perl5</TT></A>?',
+  'up:sgmlsentity.html' => 'sgmlspm.html',
+  'previous:xtrainfo.html' => 'sgmlsnotation.html',
+  'previous:example.html' => 'xtrainfo.html',
+  'title:xtrainfo' => 'Is there any extra information available from the <A HREF="http://www.sil.org/sgml/sgml.html"><B>SGML</B></A>
+document?',
+  'previous:bugs.html' => 'extend.html',
+  'title:table.class.sgmls.event' => 'The <TT>SGMLS_Event</TT> types',
+  'title:sgmlselement' => 'What do I do with an <TT>SGMLS_Element</TT>?',
+  'next:sgmlselement.html' => 'sgmlsattribute.html',
+  'previous:sgmlsnotation.html' => 'sgmlsentity.html',
+  'title:table.class.sgmls.extra' => 'Additional methods for the <TT>SGMLS</TT>
+class',
+  'xref:table.class.sgmls.attribute' => '4',
+  'up:sgml.html' => 'sgmlspm.html',
+  'title:sgmlsattribute' => 'What do I do with an
+<TT>SGMLS_Attribute</TT>?',
+  'next:sgmlsattribute.html' => 'sgmlsentity.html',
+  'surname:sgmlspm' => 'Megginson',
+  'xref:table.class.sgmls.entity' => '5',
+  'title:sgmlspm' => 'SGMLS.pm: a perl5 class library for handling output from the
+SGMLS and NSGMLS parsers (version 1.03)',
+  'next:sgmls.html' => 'sgmlsevent.html',
+  'next:extend.html' => 'bugs.html',
+  'next:sgmlsevent.html' => 'events.html',
+  'next:perl5.html' => 'sgmls.html',
+  'next:definition.html' => 'sgml.html',
+  'orgname:sgmlspm' => 'University of Ottawa',
+  'up:sgmls.html' => 'sgmlspm.html',
+  'next:example.html' => 'extend.html',
+  'previous:sgmlselement.html' => 'events.html',
+  'up:perl5.html' => 'sgmlspm.html',
+  'up:xtrainfo.html' => 'sgmlspm.html',
+  'next:sgmlsnotation.html' => 'xtrainfo.html',
+  'up:example.html' => 'sgmlspm.html',
+  'next:events.html' => 'sgmlselement.html',
+  'up:bugs.html' => 'sgmlspm.html',
+  'up:sgmlsnotation.html' => 'sgmlspm.html',
+  'previous:sgmlsattribute.html' => 'sgmlselement.html',
+  'title:table.class.sgmls.element' => 'The <TT>SGMLS_Element</TT> class',
+  'title:table.class.sgmls' => 'The <TT>SGMLS_Event</TT> class',
+  'title:table.class.sgmls.attribute' => 'The <TT>SGMLS_Attribute</TT> class',
+  'title:sgmlsentity' => 'What do I do with an <TT>SGMLS_Entity</TT>?',
+  '' => ''
+}
diff --git a/DOC/HTML/SGMLSpm/terms.html b/DOC/HTML/SGMLSpm/terms.html
new file mode 100644 (file)
index 0000000..36f816a
--- /dev/null
@@ -0,0 +1,32 @@
+<HTML>
+<HEAD>
+<TITLE>Terms</TITLE>
+</HEAD>
+<BODY>
+
+<P><B>Links</B>: <A HREF=definition.html>Next</A> <A HREF=sgmlspm.html>Up</A> <A HREF=sgmlspm.html>Top</A></P>
+
+<H1>Terms</H1>
+
+<P>This program, along with its documentation, 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 2 of the License, or (at your option) any later
+version.</P>
+
+<P>This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.</P>
+
+<P>You should have received a copy of the GNU General Public
+License along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.</P>
+
+
+<P><B>Links</B>: <A HREF=definition.html>Next</A> <A HREF=sgmlspm.html>Up</A> <A HREF=sgmlspm.html>Top</A></P>
+
+
+<ADDRESS>David Megginson <A HREF="mailto:dmeggins@aix1.uottawa.ca">&lt;dmeggins@aix1.uottawa.ca&gt;</A></ADDRESS>
+</BODY>
+</HTML>
diff --git a/DOC/HTML/SGMLSpm/xtrainfo.html b/DOC/HTML/SGMLSpm/xtrainfo.html
new file mode 100644 (file)
index 0000000..a2abd04
--- /dev/null
@@ -0,0 +1,81 @@
+<HTML>
+<HEAD>
+<TITLE>Is there any extra information available from the SGML
+document?</TITLE>
+</HEAD>
+<BODY>
+
+<P><B>Links</B>: <A HREF=example.html>Next</A> <A HREF=sgmlsnotation.html>Previous</A> <A HREF=sgmlspm.html>Up</A> <A HREF=sgmlspm.html>Top</A></P>
+
+<H1>Is there any extra information available from the <A HREF="http://www.sil.org/sgml/sgml.html"><B>SGML</B></A>
+document?</H1>
+
+<P>The <A HREF=sgmls.html><TT>SGMLS</TT></A>
+object which you created at the beginning of the parse has several
+methods available in addition to <TT>next_event</TT> --
+you will find them all listed in table 7.  There should normally be no need to
+use the <TT>notation</TT> and <TT>entity</TT>
+methods, since <A HREF=sgmlspm.html><TT>SGMLS.pm</TT></A> will look up entities and notations for you
+automatically as needed.</P>
+
+
+<H3>Table 7: Additional methods for the <TT>SGMLS</TT>
+class</H3>
+
+<HR>
+<DL>
+<DT><B>Method</B></DT>
+<DD><TT>next_event</TT></DD>
+<DT><B>Return Type</B></DT>
+<DD><TT>SGMLS_Event</TT></DD>
+<DT><B>Description</B></DT>
+<DD>Return the next event.</DD>
+
+</DL>
+<HR>
+
+
+<DL>
+<DT><B>Method</B></DT>
+<DD><TT>appinfo</TT></DD>
+<DT><B>Return Type</B></DT>
+<DD>string</DD>
+<DT><B>Description</B></DT>
+<DD>Return the APPINFO parameter from the <A HREF="http://www.sil.org/sgml/sgml.html"><B>SGML</B></A> declaration, if
+any.</DD>
+
+</DL>
+<HR>
+
+
+<DL>
+<DT><B>Method</B></DT>
+<DD><TT>notation(<IT>nname</IT>)</TT></DD>
+<DT><B>Return Type</B></DT>
+<DD><TT>SGMLS_Notation</TT></DD>
+<DT><B>Description</B></DT>
+<DD>Look up a notation by name.</DD>
+
+</DL>
+<HR>
+
+
+<DL>
+<DT><B>Method</B></DT>
+<DD><TT>entity(<IT>ename</IT>)</TT></DD>
+<DT><B>Return Type</B></DT>
+<DD><TT>SGMLS_Entity</TT></DD>
+<DT><B>Description</B></DT>
+<DD>Look up an entity by name.</DD>
+
+</DL>
+<HR>
+
+
+
+<P><B>Links</B>: <A HREF=example.html>Next</A> <A HREF=sgmlsnotation.html>Previous</A> <A HREF=sgmlspm.html>Up</A> <A HREF=sgmlspm.html>Top</A></P>
+
+
+<ADDRESS>David Megginson <A HREF="mailto:dmeggins@aix1.uottawa.ca">&lt;dmeggins@aix1.uottawa.ca&gt;</A></ADDRESS>
+</BODY>
+</HTML>
diff --git a/DOC/HTML/sgmlspl/bugs.html b/DOC/HTML/sgmlspl/bugs.html
new file mode 100644 (file)
index 0000000..b4b62b4
--- /dev/null
@@ -0,0 +1,20 @@
+<HTML>
+<HEAD>
+<TITLE>Are there any bugs?</TITLE>
+</HEAD>
+<BODY>
+
+<P><B>Links</B>: <A HREF=forward.html>Previous</A> <A HREF=sgmlspl.html>Up</A> <A HREF=sgmlspl.html>Top</A></P>
+
+<H1>Are there any bugs?</H1>
+
+<P>Any bugs in <A HREF="../SGMLSpm/sgmlspm.html"><TT>SGMLS.pm</TT></A> will be here too, since <A HREF=sgmlspl.html><TT>sgmlspl</TT></A> relies
+heavily on that <A HREF="http://www.metronet.com/0/perlinfo/perl5/manual/perl.html"><TT>perl5</TT></A> library.</P>
+
+
+<P><B>Links</B>: <A HREF=forward.html>Previous</A> <A HREF=sgmlspl.html>Up</A> <A HREF=sgmlspl.html>Top</A></P>
+
+
+<ADDRESS>David Megginson <A HREF="mailto:dmeggins@aix1.uottawa.ca">&lt;dmeggins@aix1.uottawa.ca&gt;</A></ADDRESS>
+</BODY>
+</HTML>
diff --git a/DOC/HTML/sgmlspl/definition.html b/DOC/HTML/sgmlspl/definition.html
new file mode 100644 (file)
index 0000000..eaf5ac9
--- /dev/null
@@ -0,0 +1,42 @@
+<HTML>
+<HEAD>
+<TITLE>What is sgmlspl?</TITLE>
+</HEAD>
+<BODY>
+
+<P><B>Links</B>: <A HREF=installation.html>Next</A> <A HREF=terms.html>Previous</A> <A HREF=sgmlspl.html>Up</A> <A HREF=sgmlspl.html>Top</A></P>
+
+<H1>What is <A HREF=sgmlspl.html><TT>sgmlspl</TT></A>?</H1>
+
+<P><A HREF=sgmlspl.html><TT>sgmlspl</TT></A> is a sample application distributed with the
+<A HREF="../SGMLSpm/sgmlspm.html"><TT>SGMLS.pm</TT></A> <A HREF="http://www.metronet.com/0/perlinfo/perl5/manual/perl.html"><TT>perl5</TT></A> class library -- you can use it to convert
+<A HREF="http://www.sil.org/sgml/sgml.html"><B>SGML</B></A> documents to other formats by providing a <A HREF=specs.html><I>specification file</I></A>
+detailing exactly how you want to handle each element, external data
+entity, subdocument entity, CDATA string, record end, SDATA string,
+and processing instruction.  <A HREF=sgmlspl.html><TT>sgmlspl</TT></A> also uses the <A HREF=output.html><TT>SGMLS::Output</TT></A>
+library (included in this distribution) to allow you to redirect or
+capture output.</P>
+
+<P>To use <A HREF=sgmlspl.html><TT>sgmlspl</TT></A>, you simply prepare a specification file
+containing regular <A HREF="http://www.metronet.com/0/perlinfo/perl5/manual/perl.html"><TT>perl5</TT></A> code.  If your <A HREF="http://www.sil.org/sgml/sgml.html"><B>SGML</B></A> document were named
+<TT>doc.sgml</TT>, your <A HREF=sgmlspl.html><TT>sgmlspl</TT></A> specification file
+were named, <TT>spec.pl</TT>, and the name of your new
+file were <TT>doc.latex</TT>, then you could use the
+following command in a Unix shell to convert your <A HREF="http://www.sil.org/sgml/sgml.html"><B>SGML</B></A> document:</P>
+
+<P>
+<PRE>sgmls doc.sgml | sgmlspl spec.pl > doc.latex</PRE>
+</P>
+<P><A HREF=sgmlspl.html><TT>sgmlspl</TT></A> will pass any additional arguments on to the specification
+file, which can process them in the regular <A HREF="http://www.metronet.com/0/perlinfo/perl5/manual/perl.html"><TT>perl5</TT></A> fashion.  The
+specification files used to convert this manual --
+<TT>tolatex.pl</TT> and <TT>tohtml.pl</TT>
+-- are available with the <A HREF="../SGMLSpm/sgmlspm.html"><TT>SGMLS.pm</TT></A> distribution.</P>
+
+
+<P><B>Links</B>: <A HREF=installation.html>Next</A> <A HREF=terms.html>Previous</A> <A HREF=sgmlspl.html>Up</A> <A HREF=sgmlspl.html>Top</A></P>
+
+
+<ADDRESS>David Megginson <A HREF="mailto:dmeggins@aix1.uottawa.ca">&lt;dmeggins@aix1.uottawa.ca&gt;</A></ADDRESS>
+</BODY>
+</HTML>
diff --git a/DOC/HTML/sgmlspl/dsssl.html b/DOC/HTML/sgmlspl/dsssl.html
new file mode 100644 (file)
index 0000000..2e92610
--- /dev/null
@@ -0,0 +1,34 @@
+<HTML>
+<HEAD>
+<TITLE>Is sgmlspl the best way to convert SGML documents?</TITLE>
+</HEAD>
+<BODY>
+
+<P><B>Links</B>: <A HREF=specs.html>Next</A> <A HREF=installation.html>Previous</A> <A HREF=sgmlspl.html>Up</A> <A HREF=sgmlspl.html>Top</A></P>
+
+<H1>Is <A HREF=sgmlspl.html><TT>sgmlspl</TT></A> the best way to convert <A HREF="http://www.sil.org/sgml/sgml.html"><B>SGML</B></A> documents?</H1>
+
+<P>Not necessarily.  While <A HREF=sgmlspl.html><TT>sgmlspl</TT></A> is fully functional, it is not
+always particularly intuitive or pleasant to use.  There is a new
+proposed standard, <I>Document Style Semantics and
+Specification Language</I> (<B>DSSSL</B>), based
+on the <TT>Scheme</TT> programming language, and
+implementations should soon be available.  To read more about the
+<TT>DSSSL</TT> standard, see <A HREF="http://www.jclark.com/dsssl"><TT>http://www.jclark.com/dsssl/</TT></A>
+on the Internet.</P>
+
+<P>That said, <B>DSSSL</B> is a declarative,
+side-effect-free programming language, while <A HREF=sgmlspl.html><TT>sgmlspl</TT></A> allows you to
+use any programming constructions available in <A HREF="http://www.metronet.com/0/perlinfo/perl5/manual/perl.html"><TT>perl5</TT></A>, including
+those with side-effects.  This means that if you want to do more than
+simply format the document or convert it from one <I>Document
+Type Definition</I> (<B>DTD</B>) to another,
+<A HREF=sgmlspl.html><TT>sgmlspl</TT></A> might be a good choice.</P>
+
+
+<P><B>Links</B>: <A HREF=specs.html>Next</A> <A HREF=installation.html>Previous</A> <A HREF=sgmlspl.html>Up</A> <A HREF=sgmlspl.html>Top</A></P>
+
+
+<ADDRESS>David Megginson <A HREF="mailto:dmeggins@aix1.uottawa.ca">&lt;dmeggins@aix1.uottawa.ca&gt;</A></ADDRESS>
+</BODY>
+</HTML>
diff --git a/DOC/HTML/sgmlspl/forward.html b/DOC/HTML/sgmlspl/forward.html
new file mode 100644 (file)
index 0000000..afb09b4
--- /dev/null
@@ -0,0 +1,130 @@
+<HTML>
+<HEAD>
+<TITLE>How should I handle forward references?</TITLE>
+</HEAD>
+<BODY>
+
+<P><B>Links</B>: <A HREF=bugs.html>Next</A> <A HREF=skel.html>Previous</A> <A HREF=sgmlspl.html>Up</A> <A HREF=sgmlspl.html>Top</A></P>
+
+<H1>How should I handle forward references?</H1>
+
+<P>Because <A HREF=sgmlspl.html><TT>sgmlspl</TT></A> processes the document as a linear data
+stream, from beginning to end, it is easy to refer
+<EM>back</EM> to information, but relatively difficult to
+refer <EM>forward</EM>, since you do not know what will be
+coming later in the parse.  Here are a few suggestions.</P>
+
+<P>First, you could use <A HREF=pushoutput.html><TT>push_output</TT></A> and
+<A HREF=popoutput.html><TT>pop_output</TT></A> to
+save up output in a large string.  When you have found the information
+which you need, you can make any necessary modifications to the string
+and print it then. This will work for relatively small chunks of a
+document, but you would not want to try it for anything larger.</P>
+
+<P>Next, you could use the <A HREF="../SGMLSpm/extend.html"><TT>ext</TT></A> method to
+add extra pointers, and build a parse tree of the whole document
+before processing any of it.  This method will work well for small
+documents, but large documents will place some serious stress on your
+system's memory and/or swapping.</P>
+
+<P>A more sophisticated solution, however, involves the
+<TT>Refs.pm</TT> module, included in this
+distribution.  In your <A HREF=sgmlspl.html><TT>sgmlspl</TT></A> script, include the line</P>
+
+<P>
+<PRE>use SGMLS::Refs.pm;</PRE>
+</P>
+<P>to activate the library.  The library will create a database
+file to keep track of references between passes, and to tell you if
+any references have changed.  For example, you might want to try
+something like this:</P>
+
+<P>
+<PRE>sgml('start', sub {
+  my $Refs = new SGMLS::Refs('references.refs');
+});
+sgml('end', sub {
+  $Refs->warn;
+  destroy $Refs;
+});</PRE>
+</P>
+<P>This code will create an object, $Refs, linked to a file of
+references called <TT>references.refs</TT>.  The
+<TT>SGMLS::Refs</TT> class understands the methods
+listed in table 4</P>
+
+
+<H3>Table 4: The SGMLS::Refs class</H3>
+
+<HR>
+<DL>
+<DT><B>Method</B></DT>
+<DD><TT>new</TT>(<IT>filename</IT>,[<IT>logfile_handle</IT>])</DD>
+<DT><B>Return Type</B></DT>
+<DD><TT>SGMLS::Refs</TT></DD>
+<DT><B>Description</B></DT>
+<DD>Create a new <TT>SGMLS::Refs</TT> object.
+Arguments are the name of the hashfile and (optionally) a writable
+filehandle for logging changes.</DD>
+
+</DL>
+<HR>
+
+
+<DL>
+<DT><B>Method</B></DT>
+<DD><TT>get</TT>(<IT>key</IT>)</DD>
+<DT><B>Return Type</B></DT>
+<DD>string</DD>
+<DT><B>Description</B></DT>
+<DD>Look up a reference key in the hash file and return its value.</DD>
+
+</DL>
+<HR>
+
+
+<DL>
+<DT><B>Method</B></DT>
+<DD><TT>put</TT>(<IT>key</IT>,<IT>value</IT>)</DD>
+<DT><B>Return Type</B></DT>
+<DD>[none]</DD>
+<DT><B>Description</B></DT>
+<DD>Set a new value for the key in the hashfile.</DD>
+
+</DL>
+<HR>
+
+
+<DL>
+<DT><B>Method</B></DT>
+<DD><TT>count</TT></DD>
+<DT><B>Return Type</B></DT>
+<DD>number</DD>
+<DT><B>Description</B></DT>
+<DD>Return the number of references whose values have changed (thus
+far).</DD>
+
+</DL>
+<HR>
+
+
+<DL>
+<DT><B>Method</B></DT>
+<DD><TT>warn</TT></DD>
+<DT><B>Return Type</B></DT>
+<DD>1 or 0</DD>
+<DT><B>Description</B></DT>
+<DD>Print a warning mentioning the number of references which have
+changed, and return 1 if a warning was printed.</DD>
+
+</DL>
+<HR>
+
+
+
+<P><B>Links</B>: <A HREF=bugs.html>Next</A> <A HREF=skel.html>Previous</A> <A HREF=sgmlspl.html>Up</A> <A HREF=sgmlspl.html>Top</A></P>
+
+
+<ADDRESS>David Megginson <A HREF="mailto:dmeggins@aix1.uottawa.ca">&lt;dmeggins@aix1.uottawa.ca&gt;</A></ADDRESS>
+</BODY>
+</HTML>
diff --git a/DOC/HTML/sgmlspl/generic.html b/DOC/HTML/sgmlspl/generic.html
new file mode 100644 (file)
index 0000000..425ccdd
--- /dev/null
@@ -0,0 +1,185 @@
+<HTML>
+<HEAD>
+<TITLE>What are the generic events?</TITLE>
+</HEAD>
+<BODY>
+
+<P><B>Links</B>: <A HREF=specific.html>Next</A> <A HREF=handlers.html>Previous</A> <A HREF=sgmlspl.html>Up</A> <A HREF=sgmlspl.html>Top</A></P>
+
+<H1>What are the generic events?</H1>
+
+<P><A HREF=sgmlspl.html><TT>sgmlspl</TT></A> recognises the twelve generic events listed in table
+1.  You may provide any one of these
+as the first argument to <TT>sgml</TT> to declare a handler
+(string or subroutine) for that event.</P>
+
+
+<H3>Table 1: <A HREF=sgmlspl.html><TT>sgmlspl</TT></A> generic events</H3>
+
+<HR>
+<DL>
+<DT><B>Event</B></DT>
+<DD><TT>'start'</TT></DD>
+<DT><B>Description</B></DT>
+<DD>Execute <IT>handler</IT> (with no arguments) at
+the beginning of the parse.</DD>
+
+</DL>
+<HR>
+
+
+<DL>
+<DT><B>Event</B></DT>
+<DD><TT>'end'</TT></DD>
+<DT><B>Description</B></DT>
+<DD>Execute <IT>handler</IT> (with no arguments) at
+the end of the parse.</DD>
+
+</DL>
+<HR>
+
+
+<DL>
+<DT><B>Event</B></DT>
+<DD><TT>'start_element'</TT></DD>
+<DT><B>Description</B></DT>
+<DD>Execute <IT>handler</IT> at the beginning of every
+element without a specific start handler.</DD>
+
+</DL>
+<HR>
+
+
+<DL>
+<DT><B>Event</B></DT>
+<DD><TT>'end_element'</TT></DD>
+<DT><B>Description</B></DT>
+<DD>Execute <IT>handler</IT> at the end of every
+element without a specific end handler.</DD>
+
+</DL>
+<HR>
+
+
+<DL>
+<DT><B>Event</B></DT>
+<DD><TT>'cdata'</TT></DD>
+<DT><B>Description</B></DT>
+<DD>Execute <IT>handler</IT> for every character-data
+string.</DD>
+
+</DL>
+<HR>
+
+
+<DL>
+<DT><B>Event</B></DT>
+<DD><TT>'sdata'</TT></DD>
+<DT><B>Description</B></DT>
+<DD>Execute <IT>handler</IT> for every special-data
+string without a specific handler.</DD>
+
+</DL>
+<HR>
+
+
+<DL>
+<DT><B>Event</B></DT>
+<DD><TT>'re'</TT></DD>
+<DT><B>Description</B></DT>
+<DD>Execute <IT>handler</IT> for every
+record end.</DD>
+
+</DL>
+<HR>
+
+
+<DL>
+<DT><B>Event</B></DT>
+<DD><TT>'pi'</TT></DD>
+<DT><B>Description</B></DT>
+<DD>Execute <IT>handler</IT> for every processing
+instruction.</DD>
+
+</DL>
+<HR>
+
+
+<DL>
+<DT><B>Event</B></DT>
+<DD><TT>'entity'</TT></DD>
+<DT><B>Description</B></DT>
+<DD>Execute <IT>handler</IT> for every external data
+entity without a specific handler.</DD>
+
+</DL>
+<HR>
+
+
+<DL>
+<DT><B>Event</B></DT>
+<DD><TT>'start_subdoc'</TT></DD>
+<DT><B>Description</B></DT>
+<DD>Execute <IT>handler</IT> at the beginning of every
+subdocument entity without a specific handler.</DD>
+
+</DL>
+<HR>
+
+
+<DL>
+<DT><B>Event</B></DT>
+<DD><TT>'end_subdoc'</TT></DD>
+<DT><B>Description</B></DT>
+<DD>Execute <IT>handler</IT> at the end of every
+subdocument entity without a specific handler.</DD>
+
+</DL>
+<HR>
+
+
+<DL>
+<DT><B>Event</B></DT>
+<DD><TT>'conforming'</TT></DD>
+<DT><B>Description</B></DT>
+<DD>Execute <IT>handler</IT> once, at the end of the
+document parse, if and only if the document was conforming.</DD>
+
+</DL>
+<HR>
+
+
+<P>The handlers for all of these except the document events
+<TT>'start'</TT> and <TT>'end'</TT> will receive
+two arguments whenever they are called: the first will be the data
+associated with the event (if any), and the second will be the
+<TT>SGMLS_Event</TT> object itself (see the document for
+<A HREF="../SGMLSpm/sgmlspm.html"><TT>SGMLS.pm</TT></A>).  Note the following example, which allows processing
+instructions for including the date or the hostname in the document at
+parse time:</P>
+
+<P>
+<PRE>sgml('pi', sub {
+    my ($instruction) = @_;
+    if ($instruction eq 'date') {
+      output `date`;
+    } elsif ($instruction eq 'hostname') {
+      output `hostname`;
+    } else {
+      print STDERR "Warning: unknown processing instruction: $instruction\n";
+    }
+});</PRE>
+</P>
+<P>With this <A HREF=handlers.html>handler</A>, any occurance
+of <TT>&lt;?date&gt;</TT> in the original <A HREF="http://www.sil.org/sgml/sgml.html"><B>SGML</B></A> document
+would be replaced by the current date and time, and any occurance of
+<TT>&lt;?hostname&gt;</TT> would be replaced by the name of
+the host.</P>
+
+
+<P><B>Links</B>: <A HREF=specific.html>Next</A> <A HREF=handlers.html>Previous</A> <A HREF=sgmlspl.html>Up</A> <A HREF=sgmlspl.html>Top</A></P>
+
+
+<ADDRESS>David Megginson <A HREF="mailto:dmeggins@aix1.uottawa.ca">&lt;dmeggins@aix1.uottawa.ca&gt;</A></ADDRESS>
+</BODY>
+</HTML>
diff --git a/DOC/HTML/sgmlspl/handlers.html b/DOC/HTML/sgmlspl/handlers.html
new file mode 100644 (file)
index 0000000..1e5fa9f
--- /dev/null
@@ -0,0 +1,77 @@
+<HTML>
+<HEAD>
+<TITLE>What about the handler argument?</TITLE>
+</HEAD>
+<BODY>
+
+<P><B>Links</B>: <A HREF=generic.html>Next</A> <A HREF=specs.html>Previous</A> <A HREF=sgmlspl.html>Up</A> <A HREF=sgmlspl.html>Top</A></P>
+
+<H1>What about the <IT>handler</IT> argument?</H1>
+
+<P>The second argument to the <TT>sgml</TT> subroutine is
+the actual code or data associated with each event.  If it is a
+string, it will be printed literally using the
+<TT>output</TT> subroutine from the <A HREF=output.html><TT>SGMLS::Output</TT></A> library; if
+it is a reference to a <A HREF="http://www.metronet.com/0/perlinfo/perl5/manual/perl.html"><TT>perl5</TT></A> subroutine, the subroutine will be
+called whenever the event occurs.  The following three
+<TT>sgml</TT> commands will have identical results:</P>
+
+<P>
+<PRE># Example 1
+sgml('&lt;DOC&gt;', "\\begin{document}\n");
+
+# Example 2
+sgml('&lt;DOC&gt;', sub {
+  output "\\begin{document}\n";
+});
+
+# Example 3
+sub do_begin_document { output "\\begin{document}\n"; }
+sgml('&lt;DOC&gt;', \&amp;do_begin_document);</PRE>
+</P>
+<P>For simply printing a string, of course, it does not make sense
+to use a subroutine; however, the subroutines can be useful when you
+need to check the value of an attribute, perform different actions in
+different contexts, or perform other types of relatively more
+complicated post-processing.</P>
+
+<P>If your handler is a subroutine, then it will receive two
+arguments: the <A HREF="../SGMLSpm/sgmlspm.html"><TT>SGMLS.pm</TT></A> event's data, and the <A HREF="../SGMLSpm/sgmlspm.html"><TT>SGMLS.pm</TT></A> event
+itself (see the <A HREF="../SGMLSpm/sgmlspm.html"><TT>SGMLS.pm</TT></A> <A HREF="../SGMLSpm/events.html">documentation</A> for a description
+of event and data types).  The following example will print
+<TT>'\begin{enumerate}'</TT> if the value of the attribute
+<TT>TYPE</TT> is <TT>'ORDERED'</TT>, and
+<TT>'\begin{itemize}'</TT> if the value of the attribute
+<TT>TYPE</TT> is <TT>'UNORDERED'</TT>:</P>
+
+<P>
+<PRE>sgml('&lt;LIST&gt;', sub {
+  my ($element,$event) = @_;
+  my $type = $element->attribute('TYPE')->value;
+
+  if ($type eq 'ORDERED') {
+    output "\\begin{enumerate}\n";
+  } elsif ($type eq 'UNORDERED') {
+    output "\\begin{itemize}\n";
+  } else {
+    die "Bad TYPE '$type' for element LIST at line " .
+      $event->line . " in " . $event->file . "\n";
+  }
+});</PRE>
+</P>
+<P>You will not always need to use the <IT>event</IT>
+argument, but it can be useful if you want to report line numbers or
+file names for errors (presuming that you called <TT>sgmls</TT> or <A HREF="http://www.jclark.com/sp.html"><TT>nsgmls</TT></A>
+with the <IT>-l</IT> option).  If you have a new version
+of <A HREF="http://www.jclark.com/sp.html"><TT>nsgmls</TT></A> which accepts the <IT>-h</IT> option, you
+can also use the <IT>event</IT> argument to look up
+arbitrary entities declared by the program. See the <A HREF="../SGMLSpm/sgmlsevent.html">SGMLS_Event</A> documentation for
+more information.</P>
+
+
+<P><B>Links</B>: <A HREF=generic.html>Next</A> <A HREF=specs.html>Previous</A> <A HREF=sgmlspl.html>Up</A> <A HREF=sgmlspl.html>Top</A></P>
+
+
+<ADDRESS>David Megginson <A HREF="mailto:dmeggins@aix1.uottawa.ca">&lt;dmeggins@aix1.uottawa.ca&gt;</A></ADDRESS>
+</BODY>
+</HTML>
diff --git a/DOC/HTML/sgmlspl/installation.html b/DOC/HTML/sgmlspl/installation.html
new file mode 100644 (file)
index 0000000..3c4e46b
--- /dev/null
@@ -0,0 +1,29 @@
+<HTML>
+<HEAD>
+<TITLE>How do I install sgmlspl on my system?</TITLE>
+</HEAD>
+<BODY>
+
+<P><B>Links</B>: <A HREF=dsssl.html>Next</A> <A HREF=definition.html>Previous</A> <A HREF=sgmlspl.html>Up</A> <A HREF=sgmlspl.html>Top</A></P>
+
+<H1>How do I install <A HREF=sgmlspl.html><TT>sgmlspl</TT></A> on my system?</H1>
+
+<P>To use <A HREF=sgmlspl.html><TT>sgmlspl</TT></A>, you need to install <A HREF="../SGMLSpm/sgmlspm.html"><TT>SGMLS.pm</TT></A> on your system,
+by copying the <A HREF="../SGMLSpm/sgmlspm.html"><TT>SGMLS.pm</TT></A> file to a directory searched by <A HREF="http://www.metronet.com/0/perlinfo/perl5/manual/perl.html"><TT>perl5</TT></A>.
+You also need to install <A HREF=output.html><TT>SGMLS::Output</TT></A> in the same directory, and
+<A HREF=sgmlspl.html><TT>sgmlspl</TT></A> (with execute permission) somewhere on your
+<TT>PATH</TT>.  The easiest way to do all of this on a Unix
+system is to change to the root directory of this distribution
+(<TT>SGMLSpm</TT>), edit the <TT>Makefile</TT>
+appropriately, and type</P>
+
+<P>
+<PRE>make install</PRE>
+</P>
+
+<P><B>Links</B>: <A HREF=dsssl.html>Next</A> <A HREF=definition.html>Previous</A> <A HREF=sgmlspl.html>Up</A> <A HREF=sgmlspl.html>Top</A></P>
+
+
+<ADDRESS>David Megginson <A HREF="mailto:dmeggins@aix1.uottawa.ca">&lt;dmeggins@aix1.uottawa.ca&gt;</A></ADDRESS>
+</BODY>
+</HTML>
diff --git a/DOC/HTML/sgmlspl/output.html b/DOC/HTML/sgmlspl/output.html
new file mode 100644 (file)
index 0000000..e96dc91
--- /dev/null
@@ -0,0 +1,40 @@
+<HTML>
+<HEAD>
+<TITLE>Why does sgmlspl use output instead of
+print?</TITLE>
+</HEAD>
+<BODY>
+
+<P><B>Links</B>: <A HREF=pushoutput.html>Next</A> <A HREF=specific.html>Previous</A> <A HREF=sgmlspl.html>Up</A> <A HREF=sgmlspl.html>Top</A></P>
+
+<H1>Why does <A HREF=sgmlspl.html><TT>sgmlspl</TT></A> use <TT>output</TT> instead of
+<TT>print</TT>?</H1>
+
+<P><A HREF=sgmlspl.html><TT>sgmlspl</TT></A> uses a special <A HREF="http://www.metronet.com/0/perlinfo/perl5/manual/perl.html"><TT>perl5</TT></A> library <A HREF=output.html><TT>SGMLS::Output</TT></A> for
+printing text.  <A HREF=output.html><TT>SGMLS::Output</TT></A> exports the subroutines
+<TT>output(<IT>string</IT>...)</TT>,
+<TT>push_output(<IT>type</IT>[,<IT>data</IT>])</TT>,
+and <TT>pop_output</TT>.  The subroutine
+<TT>output</TT> works much like the regular <A HREF="http://www.metronet.com/0/perlinfo/perl5/manual/perl.html"><TT>perl5</TT></A> function
+<TT>print</TT>, except that you are not able to specify a
+file handle, and you may include multiple strings as arguments.</P>
+
+<P>When you want to write data to somewhere other than
+<TT>STDOUT</TT> (the default), then you use the subroutines
+<A HREF=pushoutput.html><TT>push_output</TT></A> and
+<A HREF=popoutput.html><TT>pop_output</TT></A> to set
+a new destination or to restore an old one.</P>
+
+<P>You can use the <A HREF=output.html><TT>SGMLS::Output</TT></A> package in other programs by adding
+the following line:</P>
+
+<P>
+<PRE>use SGMLS::Output;</PRE>
+</P>
+
+<P><B>Links</B>: <A HREF=pushoutput.html>Next</A> <A HREF=specific.html>Previous</A> <A HREF=sgmlspl.html>Up</A> <A HREF=sgmlspl.html>Top</A></P>
+
+
+<ADDRESS>David Megginson <A HREF="mailto:dmeggins@aix1.uottawa.ca">&lt;dmeggins@aix1.uottawa.ca&gt;</A></ADDRESS>
+</BODY>
+</HTML>
diff --git a/DOC/HTML/sgmlspl/outputex.html b/DOC/HTML/sgmlspl/outputex.html
new file mode 100644 (file)
index 0000000..55f81c0
--- /dev/null
@@ -0,0 +1,37 @@
+<HTML>
+<HEAD>
+<TITLE>How about an example for output?</TITLE>
+</HEAD>
+<BODY>
+
+<P><B>Links</B>: <A HREF=skel.html>Next</A> <A HREF=popoutput.html>Previous</A> <A HREF=sgmlspl.html>Up</A> <A HREF=sgmlspl.html>Top</A></P>
+
+<H1>How about an example for <TT>output</TT>?</H1>
+
+<P>Here is a simple example to demonstrate how <A HREF=output.html><TT>output</TT></A>, <A HREF=pushoutput.html><TT>push_output</TT></A>, and
+<A HREF=popoutput.html><TT>pop_output</TT></A> work:</P>
+
+<P>
+<PRE>output "Hello, world!\n";               # (Written to STDOUT by default)
+push_output('nul');                     # Push 'nul' ahead of STDOUT
+output "Hello, again!\n";               # (Discarded)
+push_output('file','foo.out');          # Push file 'foo.out' ahead of 'nul'
+output "Hello, again!\n";               # (Written to the file 'foo.out')
+pop_output;                             # Pop 'foo.out' and revert to 'nul'
+output "Hello, again!\n";               # (Discarded)
+push_output('string');                  # Push 'string' ahead of 'nul'
+output "Hello, ";                       # (Written to the string)
+output "again!\n";                      # (Also written to the string)
+                                        # Pop the string "Hello, again!\n"
+$foo = pop_output;                      # and revert to 'nul'
+output "Hello, again!\n";               # (Discarded)
+pop_output;                             # Pop 'nul' and revert to STDOUT
+output "Hello, at last!\n";             # (Written to STDOUT)</PRE>
+</P>
+
+<P><B>Links</B>: <A HREF=skel.html>Next</A> <A HREF=popoutput.html>Previous</A> <A HREF=sgmlspl.html>Up</A> <A HREF=sgmlspl.html>Top</A></P>
+
+
+<ADDRESS>David Megginson <A HREF="mailto:dmeggins@aix1.uottawa.ca">&lt;dmeggins@aix1.uottawa.ca&gt;</A></ADDRESS>
+</BODY>
+</HTML>
diff --git a/DOC/HTML/sgmlspl/popoutput.html b/DOC/HTML/sgmlspl/popoutput.html
new file mode 100644 (file)
index 0000000..8e05bd9
--- /dev/null
@@ -0,0 +1,27 @@
+<HTML>
+<HEAD>
+<TITLE>How do I use pop_output?</TITLE>
+</HEAD>
+<BODY>
+
+<P><B>Links</B>: <A HREF=outputex.html>Next</A> <A HREF=pushoutput.html>Previous</A> <A HREF=sgmlspl.html>Up</A> <A HREF=sgmlspl.html>Top</A></P>
+
+<H1>How do I use <TT>pop_output</TT>?</H1>
+
+<P>When you want to restore the previous output after using <A HREF=pushoutput.html><TT>push_output</TT></A>, simply
+call the subroutine <TT>pop_output</TT>.  If the output type
+was a string, <TT>pop_output</TT> will return the string
+(containing all of the output); otherwise, the return value is not
+useful.</P>
+
+<P>Usually, you will want to use <TT>push_output</TT> in
+the start handler for an element or subdocument entity, and
+<TT>pop_output</TT> in the end handler.</P>
+
+
+<P><B>Links</B>: <A HREF=outputex.html>Next</A> <A HREF=pushoutput.html>Previous</A> <A HREF=sgmlspl.html>Up</A> <A HREF=sgmlspl.html>Top</A></P>
+
+
+<ADDRESS>David Megginson <A HREF="mailto:dmeggins@aix1.uottawa.ca">&lt;dmeggins@aix1.uottawa.ca&gt;</A></ADDRESS>
+</BODY>
+</HTML>
diff --git a/DOC/HTML/sgmlspl/pushoutput.html b/DOC/HTML/sgmlspl/pushoutput.html
new file mode 100644 (file)
index 0000000..8a7aad8
--- /dev/null
@@ -0,0 +1,116 @@
+<HTML>
+<HEAD>
+<TITLE>How do I use push_output?</TITLE>
+</HEAD>
+<BODY>
+
+<P><B>Links</B>: <A HREF=popoutput.html>Next</A> <A HREF=output.html>Previous</A> <A HREF=sgmlspl.html>Up</A> <A HREF=sgmlspl.html>Top</A></P>
+
+<H1>How do I use <TT>push_output</TT>?</H1>
+
+<P>The subroutine
+<TT>push_output(<IT>type</IT>[,<IT>data</IT>])</TT>
+takes two arguments: the <IT>type</IT>, which is always
+required, and the <IT>data</IT>, which is needed for
+certain types of output.  Table 3 lists the different types which you
+can push onto the output stack.</P>
+
+
+<H3>Table 3: Types for <TT>push_output</TT></H3>
+
+<HR>
+<DL>
+<DT><B>Type</B></DT>
+<DD><TT>'handle'</TT></DD>
+<DT><B>Data</B></DT>
+<DD>a filehandle</DD>
+<DT><B>Description</B></DT>
+<DD>Send all output to the supplied filehandle.</DD>
+
+</DL>
+<HR>
+
+
+<DL>
+<DT><B>Type</B></DT>
+<DD><TT>'file'</TT></DD>
+<DT><B>Data</B></DT>
+<DD>a filename</DD>
+<DT><B>Description</B></DT>
+<DD>Open the supplied file for writing, erasing its current
+contents (if any), and send all output to it.</DD>
+
+</DL>
+<HR>
+
+
+<DL>
+<DT><B>Type</B></DT>
+<DD><TT>'append'</TT></DD>
+<DT><B>Data</B></DT>
+<DD>a filename</DD>
+<DT><B>Description</B></DT>
+<DD>Open the supplied file for writing and append all output to its
+current contents.</DD>
+
+</DL>
+<HR>
+
+
+<DL>
+<DT><B>Type</B></DT>
+<DD><TT>'pipe'</TT></DD>
+<DT><B>Data</B></DT>
+<DD>a shell command</DD>
+<DT><B>Description</B></DT>
+<DD>Pipe all output to the supplied shell command.</DD>
+
+</DL>
+<HR>
+
+
+<DL>
+<DT><B>Type</B></DT>
+<DD><TT>'string'</TT></DD>
+<DT><B>Data</B></DT>
+<DD>a string [optional]</DD>
+<DT><B>Description</B></DT>
+<DD>Append all output to the supplied string, which will be
+returned by <TT>pop_output</TT>.</DD>
+
+</DL>
+<HR>
+
+
+<DL>
+<DT><B>Type</B></DT>
+<DD><TT>'nul'</TT></DD>
+<DT><B>Data</B></DT>
+<DD>[none]</DD>
+<DT><B>Description</B></DT>
+<DD>Ignore all output.</DD>
+
+</DL>
+<HR>
+
+
+<P>Because the output is stack-based, you do not lose the previous
+output destination when you push a new one.  This is especially
+convenient for dealing with data in tree-structures, like <A HREF="http://www.sil.org/sgml/sgml.html"><B>SGML</B></A> data
+-- for example, you can capture the contents of sub-elements as
+strings, ignore certain types of elements, and split the output from
+one <A HREF="http://www.sil.org/sgml/sgml.html"><B>SGML</B></A> parse into a series of sub-files.  Here are some examples:</P>
+
+<P>
+<PRE>push_output('string');                  # append output to an empty string
+push_output('file','/tmp/foo');         # send output to this file
+push_output('pipe','mail webmaster');   # mail output to 'webmaster' (!!)
+push_output('nul');                     # just ignore all output</PRE>
+</P>
+
+<P><B>Links</B>: <A HREF=popoutput.html>Next</A> <A HREF=output.html>Previous</A> <A HREF=sgmlspl.html>Up</A> <A HREF=sgmlspl.html>Top</A></P>
+
+
+<ADDRESS>David Megginson <A HREF="mailto:dmeggins@aix1.uottawa.ca">&lt;dmeggins@aix1.uottawa.ca&gt;</A></ADDRESS>
+</BODY>
+</HTML>
diff --git a/DOC/HTML/sgmlspl/sgmlspl.html b/DOC/HTML/sgmlspl/sgmlspl.html
new file mode 100644 (file)
index 0000000..ac8c3bf
--- /dev/null
@@ -0,0 +1,32 @@
+<HTML>
+<HEAD>
+<TITLE>sgmlspl: a simple post-processor for SGMLS and NSGMLS (for use
+with SGMLS.pm version 1.03)</TITLE>
+</HEAD>
+<BODY>
+<H1>sgmlspl: a simple post-processor for SGMLS and NSGMLS (for use
+with <A HREF="../SGMLSpm/sgmlspm.html"><TT>SGMLS.pm</TT></A> version 1.03)</H1>
+
+<P>Welcome to <A HREF=sgmlspl.html><TT>sgmlspl</TT></A>, a simple sample <A HREF="http://www.metronet.com/0/perlinfo/perl5/manual/perl.html"><TT>perl5</TT></A> application which
+uses the <A HREF="../SGMLSpm/sgmlspm.html"><TT>SGMLS.pm</TT></A> class library.</P>
+
+<LI><A HREF="terms.html">Terms</A></LI>
+<LI><A HREF="definition.html">What is sgmlspl?</A></LI>
+<LI><A HREF="installation.html">How do I install sgmlspl on my system?</A></LI>
+<LI><A HREF="dsssl.html">Is sgmlspl the best way to convert SGML documents?</A></LI>
+<LI><A HREF="specs.html">How does the specification file tell sgmlspl what to do?</A></LI>
+<LI><A HREF="handlers.html">What about the handler argument?</A></LI>
+<LI><A HREF="generic.html">What are the generic events?</A></LI>
+<LI><A HREF="specific.html">What are the specific events?</A></LI>
+<LI><A HREF="output.html">Why does sgmlspl use output instead of
+print?</A></LI>
+<LI><A HREF="pushoutput.html">How do I use push_output?</A></LI>
+<LI><A HREF="popoutput.html">How do I use pop_output?</A></LI>
+<LI><A HREF="outputex.html">How about an example for output?</A></LI>
+<LI><A HREF="skel.html">Is there an easier way to make specification files?</A></LI>
+<LI><A HREF="forward.html">How should I handle forward references?</A></LI>
+<LI><A HREF="bugs.html">Are there any bugs?</A></LI>
+
+<ADDRESS>David Megginson <A HREF="mailto:dmeggins@aix1.uottawa.ca">&lt;dmeggins@aix1.uottawa.ca&gt;</A></ADDRESS>
+</BODY>
+</HTML>
diff --git a/DOC/HTML/sgmlspl/sgmlspl.refs b/DOC/HTML/sgmlspl/sgmlspl.refs
new file mode 100644 (file)
index 0000000..2f8f5b9
--- /dev/null
@@ -0,0 +1,78 @@
+{
+  '' => '',
+  'title:specific' => 'What are the specific events?',
+  'previous:definition.html' => 'terms.html',
+  'previous:dsssl.html' => 'installation.html',
+  'firstname:sgmlspl' => 'David',
+  'title:definition' => 'What is <A HREF=sgmlspl.html><TT>sgmlspl</TT></A>?',
+  'xref:table.events.generic' => '1',
+  'orgdiv:sgmlspl' => 'Department of English',
+  'up:specific.html' => 'sgmlspl.html',
+  'previous:handlers.html' => 'specs.html',
+  'previous:pushoutput.html' => 'output.html',
+  'next:skel.html' => 'forward.html',
+  'next:output.html' => 'pushoutput.html',
+  'title:pushoutput' => 'How do I use <TT>push_output</TT>?',
+  'title:bugs' => 'Are there any bugs?',
+  'next:installation.html' => 'dsssl.html',
+  'previous:generic.html' => 'handlers.html',
+  'next:specs.html' => 'handlers.html',
+  'previous:popoutput.html' => 'pushoutput.html',
+  'title:popoutput' => 'How do I use <TT>pop_output</TT>?',
+  'up:specs.html' => 'sgmlspl.html',
+  'xref:table.output.push.output' => '3',
+  'email:sgmlspl' => 'dmeggins@aix1.uottawa.ca',
+  'next:dsssl.html' => 'specs.html',
+  'title:table.class.refs' => 'The SGMLS::Refs class',
+  'title:terms' => 'Terms',
+  'next:terms.html' => 'definition.html',
+  'previous:skel.html' => 'outputex.html',
+  'next:outputex.html' => 'skel.html',
+  'title:skel' => 'Is there an easier way to make specification files?',
+  'previous:output.html' => 'specific.html',
+  'up:definition.html' => 'sgmlspl.html',
+  'up:dsssl.html' => 'sgmlspl.html',
+  'previous:installation.html' => 'definition.html',
+  'up:terms.html' => 'sgmlspl.html',
+  'title:output' => 'Why does <A HREF=sgmlspl.html><TT>sgmlspl</TT></A> use <TT>output</TT> instead of
+<TT>print</TT>?',
+  'up:handlers.html' => 'sgmlspl.html',
+  'up:pushoutput.html' => 'sgmlspl.html',
+  'title:generic' => 'What are the generic events?',
+  'next:generic.html' => 'specific.html',
+  'title:specs' => 'How does the specification file tell <A HREF=sgmlspl.html><TT>sgmlspl</TT></A> what to do?',
+  'title:table.events.specific' => 'Specific event types',
+  'next:popoutput.html' => 'outputex.html',
+  'up:generic.html' => 'sgmlspl.html',
+  'next:specific.html' => 'output.html',
+  'up:popoutput.html' => 'sgmlspl.html',
+  'previous:outputex.html' => 'popoutput.html',
+  'previous:bugs.html' => 'forward.html',
+  'title:handlers' => 'What about the <IT>handler</IT> argument?',
+  'title:installation' => 'How do I install <A HREF=sgmlspl.html><TT>sgmlspl</TT></A> on my system?',
+  'xref:table.events.specific' => '2',
+  'previous:forward.html' => 'skel.html',
+  'up:skel.html' => 'sgmlspl.html',
+  'title:table.events.generic' => '<A HREF=sgmlspl.html><TT>sgmlspl</TT></A> generic events',
+  'up:output.html' => 'sgmlspl.html',
+  'up:installation.html' => 'sgmlspl.html',
+  'surname:sgmlspl' => 'Megginson',
+  'xref:table.class.refs' => '4',
+  'title:sgmlspl' => 'sgmlspl: a simple post-processor for SGMLS and NSGMLS (for use
+with <A HREF="../SGMLSpm/sgmlspm.html"><TT>SGMLS.pm</TT></A> version 1.03)',
+  'previous:specific.html' => 'generic.html',
+  'title:dsssl' => 'Is <A HREF=sgmlspl.html><TT>sgmlspl</TT></A> the best way to convert <A HREF="http://www.sil.org/sgml/sgml.html"><B>SGML</B></A> documents?',
+  'next:definition.html' => 'installation.html',
+  'orgname:sgmlspl' => 'University of Ottawa',
+  'title:outputex' => 'How about an example for <TT>output</TT>?',
+  'next:handlers.html' => 'generic.html',
+  'next:pushoutput.html' => 'popoutput.html',
+  'up:outputex.html' => 'sgmlspl.html',
+  'title:table.output.push.output' => 'Types for <TT>push_output</TT>',
+  'title:forward' => 'How should I handle forward references?',
+  'next:forward.html' => 'bugs.html',
+  'up:bugs.html' => 'sgmlspl.html',
+  'up:forward.html' => 'sgmlspl.html',
+  'previous:specs.html' => 'dsssl.html',
+  '' => ''
+}
diff --git a/DOC/HTML/sgmlspl/skel.html b/DOC/HTML/sgmlspl/skel.html
new file mode 100644 (file)
index 0000000..5c2a798
--- /dev/null
@@ -0,0 +1,29 @@
+<HTML>
+<HEAD>
+<TITLE>Is there an easier way to make specification files?</TITLE>
+</HEAD>
+<BODY>
+
+<P><B>Links</B>: <A HREF=forward.html>Next</A> <A HREF=outputex.html>Previous</A> <A HREF=sgmlspl.html>Up</A> <A HREF=sgmlspl.html>Top</A></P>
+
+<H1>Is there an easier way to make specification files?</H1>
+
+<P>Yes.  The script <TT>skel.pl</TT>, included in this
+package, is an <A HREF=sgmlspl.html><TT>sgmlspl</TT></A> specification which writes a specification
+(!!!).  To use it under Unix, try something like</P>
+
+<P>
+<PRE>sgmls foo.sgml | sgmlspl skel.pl > foo-spec.pl</PRE>
+</P>
+<P>(presuming that there is a copy of <TT>skel.pl</TT>
+in the current directory or in a directory searched by <A HREF="http://www.metronet.com/0/perlinfo/perl5/manual/perl.html"><TT>perl5</TT></A>) to
+generate a new, blank template named
+<TT>foo-spec.pl</TT>.</P>
+
+
+<P><B>Links</B>: <A HREF=forward.html>Next</A> <A HREF=outputex.html>Previous</A> <A HREF=sgmlspl.html>Up</A> <A HREF=sgmlspl.html>Top</A></P>
+
+
+<ADDRESS>David Megginson <A HREF="mailto:dmeggins@aix1.uottawa.ca">&lt;dmeggins@aix1.uottawa.ca&gt;</A></ADDRESS>
+</BODY>
+</HTML>
diff --git a/DOC/HTML/sgmlspl/specific.html b/DOC/HTML/sgmlspl/specific.html
new file mode 100644 (file)
index 0000000..b62b412
--- /dev/null
@@ -0,0 +1,118 @@
+<HTML>
+<HEAD>
+<TITLE>What are the specific events?</TITLE>
+</HEAD>
+<BODY>
+
+<P><B>Links</B>: <A HREF=output.html>Next</A> <A HREF=generic.html>Previous</A> <A HREF=sgmlspl.html>Up</A> <A HREF=sgmlspl.html>Top</A></P>
+
+<H1>What are the specific events?</H1>
+
+<P>In addition to the <A HREF=generic.html>generic
+events</A> listed in the previous section, <A HREF=sgmlspl.html><TT>sgmlspl</TT></A> allows
+special, specific handlers for the beginning and end of elements and
+subdocument entities, for SDATA strings, and for external data
+entities.  Table 2 lists the
+different specific event types available.</P>
+
+
+<H3>Table 2: Specific event types</H3>
+
+<HR>
+<DL>
+<DT><B>Event</B></DT>
+<DD><TT>'&lt;GI&gt;'</TT></DD>
+<DT><B>Description</B></DT>
+<DD>Execute <IT>handler</IT> at the beginning of
+every element named <TT>'GI'</TT>.</DD>
+
+</DL>
+<HR>
+
+
+<DL>
+<DT><B>Event</B></DT>
+<DD><TT>'&lt;/GI&gt;'</TT></DD>
+<DT><B>Description</B></DT>
+<DD>Execute <IT>handler</IT> at the end of every
+element named <TT>'GI'</TT>.</DD>
+
+</DL>
+<HR>
+
+
+<DL>
+<DT><B>Event</B></DT>
+<DD><TT>'|SDATA|'</TT></DD>
+<DT><B>Description</B></DT>
+<DD>Execute <IT>handler</IT> for every special-data
+string <TT>'SDATA'</TT>.</DD>
+
+</DL>
+<HR>
+
+
+<DL>
+<DT><B>Event</B></DT>
+<DD><TT>'&amp;ENTITY;'</TT></DD>
+<DT><B>Description</B></DT>
+<DD>Execute <IT>handler</IT> for every external data
+entity named <TT>'ENTITY'</TT>.</DD>
+
+</DL>
+<HR>
+
+
+<DL>
+<DT><B>Event</B></DT>
+<DD><TT>'{ENTITY}'</TT></DD>
+<DT><B>Description</B></DT>
+<DD>Execute <IT>handler</IT> at the beginning of
+every subdocument entity named <TT>'ENTITY'</TT>.</DD>
+
+</DL>
+<HR>
+
+
+<DL>
+<DT><B>Event</B></DT>
+<DD><TT>'{/ENTITY}'</TT></DD>
+<DT><B>Description</B></DT>
+<DD>Execute <IT>handler</IT> at the end of every
+subdocument entity named <TT>'ENTITY'</TT>.</DD>
+
+</DL>
+<HR>
+
+
+<P>Note that these override the <A HREF=generic.html>generic-event</A> handlers.  For example, if you
+were to type</P>
+
+<P>
+<PRE>sgml('&amp;FOO;', sub {
+    output "Found a \"foo\" entity!\n";
+});
+
+sgml('entity', sub {
+    output "Found an entity!\n";
+});</PRE>
+</P>
+<P>And the external data entity <TT>&amp;FOO;</TT>
+appeared in your <A HREF="http://www.sil.org/sgml/sgml.html"><B>SGML</B></A> document, <A HREF=sgmlspl.html><TT>sgmlspl</TT></A> would call the first
+handler rather than the second.</P>
+
+<P>Note also that start and end handlers are entirely separate
+things: if an element has a specific start handler but no specific end
+handler, the generic end handler will still be called at the end of
+the element.  To prevent this, declare a handler with an empty string:</P>
+
+<P>
+<PRE>sgml('&lt;/HACK&gt;', '');</PRE>
+</P>
+
+<P><B>Links</B>: <A HREF=output.html>Next</A> <A HREF=generic.html>Previous</A> <A HREF=sgmlspl.html>Up</A> <A HREF=sgmlspl.html>Top</A></P>
+
+
+<ADDRESS>David Megginson <A HREF="mailto:dmeggins@aix1.uottawa.ca">&lt;dmeggins@aix1.uottawa.ca&gt;</A></ADDRESS>
+</BODY>
+</HTML>
diff --git a/DOC/HTML/sgmlspl/specs.html b/DOC/HTML/sgmlspl/specs.html
new file mode 100644 (file)
index 0000000..114ea15
--- /dev/null
@@ -0,0 +1,41 @@
+<HTML>
+<HEAD>
+<TITLE>How does the specification file tell sgmlspl what to do?</TITLE>
+</HEAD>
+<BODY>
+
+<P><B>Links</B>: <A HREF=handlers.html>Next</A> <A HREF=dsssl.html>Previous</A> <A HREF=sgmlspl.html>Up</A> <A HREF=sgmlspl.html>Top</A></P>
+
+<H1>How does the specification file tell <A HREF=sgmlspl.html><TT>sgmlspl</TT></A> what to do?</H1>
+
+<P><A HREF=sgmlspl.html><TT>sgmlspl</TT></A> uses an <I>event model</I> rather than
+a <I>procedural model</I> -- instead of
+saying "do A then B then C" you say "whenever X
+happens, do A; whenever Y happens, do B; whenever Z happens, do
+C".  In other words, while you design the code, <A HREF=sgmlspl.html><TT>sgmlspl</TT></A>
+decides when and how often to run it.</P>
+
+<P>The specification file, which contains your instructions, is
+regular <A HREF="http://www.metronet.com/0/perlinfo/perl5/manual/perl.html"><TT>perl5</TT></A> code, and you can define packages and subroutines,
+display information, read files, create variables, etc.  For
+processing the <A HREF="http://www.sil.org/sgml/sgml.html"><B>SGML</B></A> document, however, <A HREF=sgmlspl.html><TT>sgmlspl</TT></A> exports a single
+subroutine, <TT>sgml(<IT>event</IT>,
+<IT>handler</IT>)</TT>, into the 'main' package
+-- each time you call <TT>sgml</TT>, you declare a
+handler for a specific type of <TT>sgmls</TT> <A HREF="../SGMLSpm/events.html">event</A>, and <A HREF=sgmlspl.html><TT>sgmlspl</TT></A> will then
+execute that handler every time the event occurs.  You may use
+<TT>sgml</TT> to declare a <A HREF=handlers.html>handler</A> for a <A HREF=generic.html><I>generic event</I></A>, like
+<TT>'start_element'</TT>, or a <A HREF=specific.html><I>specific event</I></A>,
+like <TT>'&lt;DOC&gt;'</TT> -- a specific event will
+always take precedence over a generic event, so when the
+<TT>DOC</TT> element begins, <A HREF=sgmlspl.html><TT>sgmlspl</TT></A> will execute the
+<TT>'&lt;DOC&gt;'</TT> handler rather than the
+<TT>'start_element'</TT> handler.</P>
+
+
+<P><B>Links</B>: <A HREF=handlers.html>Next</A> <A HREF=dsssl.html>Previous</A> <A HREF=sgmlspl.html>Up</A> <A HREF=sgmlspl.html>Top</A></P>
+
+
+<ADDRESS>David Megginson <A HREF="mailto:dmeggins@aix1.uottawa.ca">&lt;dmeggins@aix1.uottawa.ca&gt;</A></ADDRESS>
+</BODY>
+</HTML>
diff --git a/DOC/HTML/sgmlspl/terms.html b/DOC/HTML/sgmlspl/terms.html
new file mode 100644 (file)
index 0000000..d6991bc
--- /dev/null
@@ -0,0 +1,32 @@
+<HTML>
+<HEAD>
+<TITLE>Terms</TITLE>
+</HEAD>
+<BODY>
+
+<P><B>Links</B>: <A HREF=definition.html>Next</A> <A HREF=sgmlspl.html>Up</A> <A HREF=sgmlspl.html>Top</A></P>
+
+<H1>Terms</H1>
+
+<P>This program, along with its documentation, 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 2 of the License, or (at your option) any later
+version.</P>
+
+<P>This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.</P>
+
+<P>You should have received a copy of the GNU General Public
+License along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.</P>
+
+
+<P><B>Links</B>: <A HREF=definition.html>Next</A> <A HREF=sgmlspl.html>Up</A> <A HREF=sgmlspl.html>Top</A></P>
+
+
+<ADDRESS>David Megginson <A HREF="mailto:dmeggins@aix1.uottawa.ca">&lt;dmeggins@aix1.uottawa.ca&gt;</A></ADDRESS>
+</BODY>
+</HTML>
diff --git a/DOC/LaTeX/sample.pl b/DOC/LaTeX/sample.pl
new file mode 120000 (symlink)
index 0000000..9efacbd
--- /dev/null
@@ -0,0 +1 @@
+../sample.pl
\ No newline at end of file
diff --git a/DOC/LaTeX/sgmlspl.refs b/DOC/LaTeX/sgmlspl.refs
new file mode 100644 (file)
index 0000000..cb42f50
--- /dev/null
@@ -0,0 +1,24 @@
+{
+  '' => '',
+  'title:SPECIFIC' => 'What are the specific events?',
+  'title:DEFINITION' => 'What is {\\sc sgmlspl}?',
+  'title:DSSSL' => 'Is {\\sc sgmlspl} the best way to convert {\\sc SGML} documents?',
+  'title:TABLE.CLASS.REFS' => 'The SGMLS::Refs class',
+  'title:TERMS' => 'Terms',
+  'title:OUTPUTEX' => 'How about an example for {\\tt output}?',
+  'title:SKEL' => 'Is there an easier way to make specification files?',
+  'title:BUGS' => 'Are there any bugs?',
+  'title:PUSHOUTPUT' => 'How do I use {\\tt push\\_output}?',
+  'title:OUTPUT' => 'Why does {\\sc sgmlspl} use {\\tt output} instead of
+{\\tt print}?',
+  'title:HANDLERS' => 'What about the {\\tt\\sl handler\\/} argument?',
+  'title:INSTALLATION' => 'How do I install {\\sc sgmlspl} on my system?',
+  'title:TABLE.OUTPUT.PUSH.OUTPUT' => 'Types for {\\tt push\\_output}',
+  'title:FORWARD' => 'How should I handle forward references?',
+  'title:TABLE.EVENTS.GENERIC' => '{\\sc sgmlspl} generic events',
+  'title:GENERIC' => 'What are the generic events?',
+  'title:SPECS' => 'How does the specification file tell {\\sc sgmlspl} what to do?',
+  'title:TABLE.EVENTS.SPECIFIC' => 'Specific event types',
+  'title:POPOUTPUT' => 'How do I use {\\tt pop\\_output}?',
+  '' => ''
+}
diff --git a/DOC/LaTeX/sgmlspl.tex b/DOC/LaTeX/sgmlspl.tex
new file mode 100644 (file)
index 0000000..e2560f8
--- /dev/null
@@ -0,0 +1,575 @@
+\documentstyle[11pt]{article}
+
+\setlength{\parskip}{3ex}
+\raggedright
+
+\title{sgmlspl: a simple post-processor for SGMLS and NSGMLS (for use
+with {\sc SGMLS.pm} version 1.03)}
+\author{David Megginson \\
+  Department of English, \\
+  University of Ottawa, \\
+  Email: {\tt dmeggins@aix1.uottawa.ca} \\
+}
+
+
+\begin{document}
+\maketitle
+
+
+Welcome to {\sc sgmlspl}, a simple sample {\sc perl5} application which
+uses the {\sc SGMLS.pm} class library.
+
+
+{\em\section{Terms}
+\label{TERMS}
+
+
+This program, along with its documentation, 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 2 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
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 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, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+
+}
+
+
+
+\section{What is {\sc sgmlspl}?}
+\label{DEFINITION}
+
+
+{\sc sgmlspl} is a sample application distributed with the
+{\sc SGMLS.pm} {\sc perl5} class library {---} you can use it to convert
+{\sc SGML} documents to other formats by providing a {\em specification file\/}
+detailing exactly how you want to handle each element, external data
+entity, subdocument entity, CDATA string, record end, SDATA string,
+and processing instruction.  {\sc sgmlspl} also uses the {\sc SGMLS::Output}
+library (included in this distribution) to allow you to redirect or
+capture output.
+
+To use {\sc sgmlspl}, you simply prepare a specification file
+containing regular {\sc perl5} code.  If your {\sc SGML} document were named
+{\tt doc.sgml}, your {\sc sgmlspl} specification file
+were named, {\tt spec.pl}, and the name of your new
+file were {\tt doc.latex}, then you could use the
+following command in a Unix shell to convert your {\sc SGML} document:
+
+{\footnotesize\begin{verbatim}
+sgmls doc.sgml | sgmlspl spec.pl > doc.latex
+\end{verbatim}}
+
+{\sc sgmlspl} will pass any additional arguments on to the specification
+file, which can process them in the regular {\sc perl5} fashion.  The
+specification files used to convert this manual {---}
+{\tt tolatex.pl} and {\tt tohtml.pl}
+{---} are available with the {\sc SGMLS.pm} distribution.
+
+
+
+
+\section{How do I install {\sc sgmlspl} on my system?}
+\label{INSTALLATION}
+
+
+To use {\sc sgmlspl}, you need to install {\sc SGMLS.pm} on your system,
+by copying the {\sc SGMLS.pm} file to a directory searched by {\sc perl5}.
+You also need to install {\sc SGMLS::Output} in the same directory, and
+{\sc sgmlspl} (with execute permission) somewhere on your
+{\tt PATH}.  The easiest way to do all of this on a Unix
+system is to change to the root directory of this distribution
+({\tt SGMLSpm}), edit the {\tt Makefile}
+appropriately, and type
+
+{\footnotesize\begin{verbatim}
+make install
+\end{verbatim}}
+
+
+
+
+\section{Is {\sc sgmlspl} the best way to convert {\sc SGML} documents?}
+\label{DSSSL}
+
+
+Not necessarily.  While {\sc sgmlspl} is fully functional, it is not
+always particularly intuitive or pleasant to use.  There is a new
+proposed standard, {\em Document Style Semantics and
+Specification Language\/} ({\sc DSSSL}), based
+on the {\sc Scheme} programming language, and
+implementations should soon be available.  To read more about the
+{\sc DSSSL} standard, see {\tt http://www.jclark.com/dsssl/}
+on the Internet.
+
+That said, {\sc DSSSL} is a declarative,
+side-effect-free programming language, while {\sc sgmlspl} allows you to
+use any programming constructions available in {\sc perl5}, including
+those with side-effects.  This means that if you want to do more than
+simply format the document or convert it from one {\em Document
+Type Definition\/} ({\sc DTD}) to another,
+{\sc sgmlspl} might be a good choice.
+
+
+
+
+\section{How does the specification file tell {\sc sgmlspl} what to do?}
+\label{SPECS}
+
+
+{\sc sgmlspl} uses an {\em event model\/} rather than
+a {\em procedural model\/} {---} instead of
+saying {``}do A then B then C{''} you say {``}whenever X
+happens, do A; whenever Y happens, do B; whenever Z happens, do
+C{''}.  In other words, while you design the code, {\sc sgmlspl}
+decides when and how often to run it.
+
+The specification file, which contains your instructions, is
+regular {\sc perl5} code, and you can define packages and subroutines,
+display information, read files, create variables, etc.  For
+processing the {\sc SGML} document, however, {\sc sgmlspl} exports a single
+subroutine, {\tt sgml({\tt\sl event\/},
+{\tt\sl handler\/})}, into the 'main' package
+{---} each time you call {\tt sgml}, you declare a
+handler for a specific type of {\sc sgmls} event, and {\sc sgmlspl} will then
+execute that handler every time the event occurs.  You may use
+{\tt sgml} to declare a handler for a {\em generic event\/}, like
+{\tt 'start\_element'}, or a {\em specific event\/},
+like {\tt '$<$DOC$>$'} {---} a specific event will
+always take precedence over a generic event, so when the
+{\tt DOC} element begins, {\sc sgmlspl} will execute the
+{\tt '$<$DOC$>$'} handler rather than the
+{\tt 'start\_element'} handler.
+
+
+
+
+\section{What about the {\tt\sl handler\/} argument?}
+\label{HANDLERS}
+
+
+The second argument to the {\tt sgml} subroutine is
+the actual code or data associated with each event.  If it is a
+string, it will be printed literally using the
+{\tt output} subroutine from the {\sc SGMLS::Output} library; if
+it is a reference to a {\sc perl5} subroutine, the subroutine will be
+called whenever the event occurs.  The following three
+{\tt sgml} commands will have identical results:
+
+{\footnotesize\begin{verbatim}
+# Example 1
+sgml('<DOC>', "\\begin{document}\n");
+
+# Example 2
+sgml('<DOC>', sub {
+  output "\\begin{document}\n";
+});
+
+# Example 3
+sub do_begin_document { output "\\begin{document}\n"; }
+sgml('<DOC>', \&do_begin_document);
+\end{verbatim}}
+
+For simply printing a string, of course, it does not make sense
+to use a subroutine; however, the subroutines can be useful when you
+need to check the value of an attribute, perform different actions in
+different contexts, or perform other types of relatively more
+complicated post-processing.
+
+If your handler is a subroutine, then it will receive two
+arguments: the {\sc SGMLS.pm} event's data, and the {\sc SGMLS.pm} event
+itself (see the {\sc SGMLS.pm} documentation for a description
+of event and data types).  The following example will print
+{\tt '\verb|\|begin\{enumerate\}'} if the value of the attribute
+{\tt TYPE} is {\tt 'ORDERED'}, and
+{\tt '\verb|\|begin\{itemize\}'} if the value of the attribute
+{\tt TYPE} is {\tt 'UNORDERED'}:
+
+{\footnotesize\begin{verbatim}
+sgml('<LIST>', sub {
+  my ($element,$event) = @_;
+  my $type = $element->attribute('TYPE')->value;
+
+  if ($type eq 'ORDERED') {
+    output "\\begin{enumerate}\n";
+  } elsif ($type eq 'UNORDERED') {
+    output "\\begin{itemize}\n";
+  } else {
+    die "Bad TYPE '$type' for element LIST at line " .
+      $event->line . " in " . $event->file . "\n";
+  }
+});
+\end{verbatim}}
+
+You will not always need to use the {\tt\sl event\/}
+argument, but it can be useful if you want to report line numbers or
+file names for errors (presuming that you called {\sc sgmls} or {\sc nsgmls}
+with the {\tt\sl -l\/} option).  If you have a new version
+of {\sc nsgmls} which accepts the {\tt\sl -h\/} option, you
+can also use the {\tt\sl event\/} argument to look up
+arbitrary entities declared by the program. See the SGMLS\_Event documentation for
+more information.
+
+
+
+
+\section{What are the generic events?}
+\label{GENERIC}
+
+
+{\sc sgmlspl} recognises the twelve generic events listed in table
+\ref{TABLE.EVENTS.GENERIC}.  You may provide any one of these
+as the first argument to {\tt sgml} to declare a handler
+(string or subroutine) for that event.
+
+\begin{table}[htbp]
+\footnotesize
+\caption{{\sc sgmlspl} generic events}
+\label{TABLE.EVENTS.GENERIC}
+\vspace{2ex}\begin{tabular}{l|l}
+\parbox[c]{2.225in}{\raggedright\vspace{4pt} Event\vspace{4pt}}         & \parbox[c]{2.225in}{\raggedright\vspace{4pt} Description\vspace{4pt}}        \\ \hline\hline
+\parbox[c]{2.225in}{\raggedright\vspace{4pt} {\tt 'start'}\vspace{4pt}}         & \parbox[c]{2.225in}{\raggedright\vspace{4pt} Execute {\tt\sl handler\/} (with no arguments) at
+the beginning of the parse.\vspace{4pt}}       \\ \hline
+\parbox[c]{2.225in}{\raggedright\vspace{4pt} {\tt 'end'}\vspace{4pt}}   & \parbox[c]{2.225in}{\raggedright\vspace{4pt} Execute {\tt\sl handler\/} (with no arguments) at
+the end of the parse.\vspace{4pt}}     \\ \hline
+\parbox[c]{2.225in}{\raggedright\vspace{4pt} {\tt 'start\_element'}\vspace{4pt}}        & \parbox[c]{2.225in}{\raggedright\vspace{4pt} Execute {\tt\sl handler\/} at the beginning of every
+element without a specific start handler.\vspace{4pt}} \\ \hline
+\parbox[c]{2.225in}{\raggedright\vspace{4pt} {\tt 'end\_element'}\vspace{4pt}}  & \parbox[c]{2.225in}{\raggedright\vspace{4pt} Execute {\tt\sl handler\/} at the end of every
+element without a specific end handler.\vspace{4pt}}   \\ \hline
+\parbox[c]{2.225in}{\raggedright\vspace{4pt} {\tt 'cdata'}\vspace{4pt}}         & \parbox[c]{2.225in}{\raggedright\vspace{4pt} Execute {\tt\sl handler\/} for every character-data
+string.\vspace{4pt}}   \\ \hline
+\parbox[c]{2.225in}{\raggedright\vspace{4pt} {\tt 'sdata'}\vspace{4pt}}         & \parbox[c]{2.225in}{\raggedright\vspace{4pt} Execute {\tt\sl handler\/} for every special-data
+string without a specific handler.\vspace{4pt}}        \\ \hline
+\parbox[c]{2.225in}{\raggedright\vspace{4pt} {\tt 're'}\vspace{4pt}}    & \parbox[c]{2.225in}{\raggedright\vspace{4pt} Execute {\tt\sl handler\/} for every
+record end.\vspace{4pt}}       \\ \hline
+\parbox[c]{2.225in}{\raggedright\vspace{4pt} {\tt 'pi'}\vspace{4pt}}    & \parbox[c]{2.225in}{\raggedright\vspace{4pt} Execute {\tt\sl handler\/} for every processing
+instruction.\vspace{4pt}}      \\ \hline
+\parbox[c]{2.225in}{\raggedright\vspace{4pt} {\tt 'entity'}\vspace{4pt}}        & \parbox[c]{2.225in}{\raggedright\vspace{4pt} Execute {\tt\sl handler\/} for every external data
+entity without a specific handler.\vspace{4pt}}        \\ \hline
+\parbox[c]{2.225in}{\raggedright\vspace{4pt} {\tt 'start\_subdoc'}\vspace{4pt}}         & \parbox[c]{2.225in}{\raggedright\vspace{4pt} Execute {\tt\sl handler\/} at the beginning of every
+subdocument entity without a specific handler.\vspace{4pt}}    \\ \hline
+\parbox[c]{2.225in}{\raggedright\vspace{4pt} {\tt 'end\_subdoc'}\vspace{4pt}}   & \parbox[c]{2.225in}{\raggedright\vspace{4pt} Execute {\tt\sl handler\/} at the end of every
+subdocument entity without a specific handler.\vspace{4pt}}    \\ \hline
+\parbox[c]{2.225in}{\raggedright\vspace{4pt} {\tt 'conforming'}\vspace{4pt}}    & \parbox[c]{2.225in}{\raggedright\vspace{4pt} Execute {\tt\sl handler\/} once, at the end of the
+document parse, if and only if the document was conforming.\vspace{4pt}}       \\ \hline
+\end{tabular}\end{table}
+
+The handlers for all of these except the document events
+{\tt 'start'} and {\tt 'end'} will receive
+two arguments whenever they are called: the first will be the data
+associated with the event (if any), and the second will be the
+{\tt SGMLS\_Event} object itself (see the document for
+{\sc SGMLS.pm}).  Note the following example, which allows processing
+instructions for including the date or the hostname in the document at
+parse time:
+
+{\footnotesize\begin{verbatim}
+sgml('pi', sub {
+    my ($instruction) = @_;
+    if ($instruction eq 'date') {
+      output `date`;
+    } elsif ($instruction eq 'hostname') {
+      output `hostname`;
+    } else {
+      print STDERR "Warning: unknown processing instruction: $instruction\n";
+    }
+});
+\end{verbatim}}
+
+With this handler, any occurance
+of {\tt $<$?date$>$} in the original {\sc SGML} document
+would be replaced by the current date and time, and any occurance of
+{\tt $<$?hostname$>$} would be replaced by the name of
+the host.
+
+
+
+
+\section{What are the specific events?}
+\label{SPECIFIC}
+
+
+In addition to the generic
+events listed in the previous section, {\sc sgmlspl} allows
+special, specific handlers for the beginning and end of elements and
+subdocument entities, for SDATA strings, and for external data
+entities.  Table \ref{TABLE.EVENTS.SPECIFIC} lists the
+different specific event types available.
+
+\begin{table}[htbp]
+\footnotesize
+\caption{Specific event types}
+\label{TABLE.EVENTS.SPECIFIC}
+\vspace{2ex}\begin{tabular}{l|l}
+\parbox[c]{2.225in}{\raggedright\vspace{4pt} Event\vspace{4pt}}         & \parbox[c]{2.225in}{\raggedright\vspace{4pt} Description\vspace{4pt}}        \\ \hline\hline
+\parbox[c]{2.225in}{\raggedright\vspace{4pt} {\tt '$<$GI$>$'}\vspace{4pt}}      & \parbox[c]{2.225in}{\raggedright\vspace{4pt} Execute {\tt\sl handler\/} at the beginning of
+every element named {\tt 'GI'}.\vspace{4pt}}   \\ \hline
+\parbox[c]{2.225in}{\raggedright\vspace{4pt} {\tt '$<$/GI$>$'}\vspace{4pt}}     & \parbox[c]{2.225in}{\raggedright\vspace{4pt} Execute {\tt\sl handler\/} at the end of every
+element named {\tt 'GI'}.\vspace{4pt}} \\ \hline
+\parbox[c]{2.225in}{\raggedright\vspace{4pt} {\tt '|SDATA|'}\vspace{4pt}}       & \parbox[c]{2.225in}{\raggedright\vspace{4pt} Execute {\tt\sl handler\/} for every special-data
+string {\tt 'SDATA'}.\vspace{4pt}}     \\ \hline
+\parbox[c]{2.225in}{\raggedright\vspace{4pt} {\tt '\&ENTITY;'}\vspace{4pt}}     & \parbox[c]{2.225in}{\raggedright\vspace{4pt} Execute {\tt\sl handler\/} for every external data
+entity named {\tt 'ENTITY'}.\vspace{4pt}}      \\ \hline
+\parbox[c]{2.225in}{\raggedright\vspace{4pt} {\tt '\{ENTITY\}'}\vspace{4pt}}    & \parbox[c]{2.225in}{\raggedright\vspace{4pt} Execute {\tt\sl handler\/} at the beginning of
+every subdocument entity named {\tt 'ENTITY'}.\vspace{4pt}}    \\ \hline
+\parbox[c]{2.225in}{\raggedright\vspace{4pt} {\tt '\{/ENTITY\}'}\vspace{4pt}}   & \parbox[c]{2.225in}{\raggedright\vspace{4pt} Execute {\tt\sl handler\/} at the end of every
+subdocument entity named {\tt 'ENTITY'}.\vspace{4pt}}  \\ \hline
+\end{tabular}\end{table}
+
+Note that these override the generic-event handlers.  For example, if you
+were to type
+
+{\footnotesize\begin{verbatim}
+sgml('&FOO;', sub {
+    output "Found a \"foo\" entity!\n";
+});
+
+sgml('entity', sub {
+    output "Found an entity!\n";
+});
+\end{verbatim}}
+
+And the external data entity {\tt \&FOO;}
+appeared in your {\sc SGML} document, {\sc sgmlspl} would call the first
+handler rather than the second.
+
+Note also that start and end handlers are entirely separate
+things: if an element has a specific start handler but no specific end
+handler, the generic end handler will still be called at the end of
+the element.  To prevent this, declare a handler with an empty string:
+
+{\footnotesize\begin{verbatim}
+sgml('</HACK>', '');
+\end{verbatim}}
+
+
+
+
+\section{Why does {\sc sgmlspl} use {\tt output} instead of
+{\tt print}?}
+\label{OUTPUT}
+
+
+{\sc sgmlspl} uses a special {\sc perl5} library {\sc SGMLS::Output} for
+printing text.  {\sc SGMLS::Output} exports the subroutines
+{\tt output({\tt\sl string\/}{\ldots})},
+{\tt push\_output({\tt\sl type\/}[,{\tt\sl data\/}])},
+and {\tt pop\_output}.  The subroutine
+{\tt output} works much like the regular {\sc perl5} function
+{\tt print}, except that you are not able to specify a
+file handle, and you may include multiple strings as arguments.
+
+When you want to write data to somewhere other than
+{\tt STDOUT} (the default), then you use the subroutines
+{\tt push\_output} and
+{\tt pop\_output} to set
+a new destination or to restore an old one.
+
+You can use the {\sc SGMLS::Output} package in other programs by adding
+the following line:
+
+{\footnotesize\begin{verbatim}
+use SGMLS::Output;
+\end{verbatim}}
+
+
+
+
+\section{How do I use {\tt push\_output}?}
+\label{PUSHOUTPUT}
+
+
+The subroutine
+{\tt push\_output({\tt\sl type\/}[,{\tt\sl data\/}])}
+takes two arguments: the {\tt\sl type\/}, which is always
+required, and the {\tt\sl data\/}, which is needed for
+certain types of output.  Table \ref{TABLE.OUTPUT.PUSH.OUTPUT} lists the different types which you
+can push onto the output stack.
+
+\begin{table}[htbp]
+\footnotesize
+\caption{Types for {\tt push\_output}}
+\label{TABLE.OUTPUT.PUSH.OUTPUT}
+\vspace{2ex}\begin{tabular}{l|l|l}
+\parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} Type\vspace{4pt}}       & \parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} Data\vspace{4pt}}     & \parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} Description\vspace{4pt}}     \\ \hline\hline
+\parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} {\tt 'handle'}\vspace{4pt}}     & \parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} a filehandle\vspace{4pt}}     & \parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} Send all output to the supplied filehandle.\vspace{4pt}}     \\ \hline
+\parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} {\tt 'file'}\vspace{4pt}}       & \parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} a filename\vspace{4pt}}       & \parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} Open the supplied file for writing, erasing its current
+contents (if any), and send all output to it.\vspace{4pt}}     \\ \hline
+\parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} {\tt 'append'}\vspace{4pt}}     & \parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} a filename\vspace{4pt}}       & \parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} Open the supplied file for writing and append all output to its
+current contents.\vspace{4pt}} \\ \hline
+\parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} {\tt 'pipe'}\vspace{4pt}}       & \parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} a shell command\vspace{4pt}}  & \parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} Pipe all output to the supplied shell command.\vspace{4pt}}  \\ \hline
+\parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} {\tt 'string'}\vspace{4pt}}     & \parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} a string [optional]\vspace{4pt}}      & \parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} Append all output to the supplied string, which will be
+returned by {\tt pop\_output}.\vspace{4pt}}    \\ \hline
+\parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} {\tt 'nul'}\vspace{4pt}}        & \parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} [none]\vspace{4pt}}   & \parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} Ignore all output.\vspace{4pt}}      \\ \hline
+\end{tabular}\end{table}
+
+Because the output is stack-based, you do not lose the previous
+output destination when you push a new one.  This is especially
+convenient for dealing with data in tree-structures, like {\sc SGML} data
+{---} for example, you can capture the contents of sub-elements as
+strings, ignore certain types of elements, and split the output from
+one {\sc SGML} parse into a series of sub-files.  Here are some examples:
+
+{\footnotesize\begin{verbatim}
+push_output('string');                  # append output to an empty string
+push_output('file','/tmp/foo');         # send output to this file
+push_output('pipe','mail webmaster');   # mail output to 'webmaster' (!!)
+push_output('nul');                     # just ignore all output
+\end{verbatim}}
+
+
+
+
+\section{How do I use {\tt pop\_output}?}
+\label{POPOUTPUT}
+
+
+When you want to restore the previous output after using {\tt push\_output}, simply
+call the subroutine {\tt pop\_output}.  If the output type
+was a string, {\tt pop\_output} will return the string
+(containing all of the output); otherwise, the return value is not
+useful.
+
+Usually, you will want to use {\tt push\_output} in
+the start handler for an element or subdocument entity, and
+{\tt pop\_output} in the end handler.
+
+
+
+
+\section{How about an example for {\tt output}?}
+\label{OUTPUTEX}
+
+
+Here is a simple example to demonstrate how {\tt output}, {\tt push\_output}, and
+{\tt pop\_output} work:
+
+{\footnotesize\begin{verbatim}
+output "Hello, world!\n";               # (Written to STDOUT by default)
+push_output('nul');                     # Push 'nul' ahead of STDOUT
+output "Hello, again!\n";               # (Discarded)
+push_output('file','foo.out');          # Push file 'foo.out' ahead of 'nul'
+output "Hello, again!\n";               # (Written to the file 'foo.out')
+pop_output;                             # Pop 'foo.out' and revert to 'nul'
+output "Hello, again!\n";               # (Discarded)
+push_output('string');                  # Push 'string' ahead of 'nul'
+output "Hello, ";                       # (Written to the string)
+output "again!\n";                      # (Also written to the string)
+                                        # Pop the string "Hello, again!\n"
+$foo = pop_output;                      # and revert to 'nul'
+output "Hello, again!\n";               # (Discarded)
+pop_output;                             # Pop 'nul' and revert to STDOUT
+output "Hello, at last!\n";             # (Written to STDOUT)
+\end{verbatim}}
+
+
+
+
+\section{Is there an easier way to make specification files?}
+\label{SKEL}
+
+
+Yes.  The script {\tt skel.pl}, included in this
+package, is an {\sc sgmlspl} specification which writes a specification
+(!!!).  To use it under Unix, try something like
+
+{\footnotesize\begin{verbatim}
+sgmls foo.sgml | sgmlspl skel.pl > foo-spec.pl
+\end{verbatim}}
+
+(presuming that there is a copy of {\tt skel.pl}
+in the current directory or in a directory searched by {\sc perl5}) to
+generate a new, blank template named
+{\tt foo-spec.pl}.
+
+
+
+
+\section{How should I handle forward references?}
+\label{FORWARD}
+
+
+Because {\sc sgmlspl} processes the document as a linear data
+stream, from beginning to end, it is easy to refer
+{\em back\/} to information, but relatively difficult to
+refer {\em forward\/}, since you do not know what will be
+coming later in the parse.  Here are a few suggestions.
+
+First, you could use {\tt push\_output} and
+{\tt pop\_output} to
+save up output in a large string.  When you have found the information
+which you need, you can make any necessary modifications to the string
+and print it then. This will work for relatively small chunks of a
+document, but you would not want to try it for anything larger.
+
+Next, you could use the {\tt ext} method to
+add extra pointers, and build a parse tree of the whole document
+before processing any of it.  This method will work well for small
+documents, but large documents will place some serious stress on your
+system's memory and/or swapping.
+
+A more sophisticated solution, however, involves the
+{\sc Refs.pm} module, included in this
+distribution.  In your {\sc sgmlspl} script, include the line
+
+{\footnotesize\begin{verbatim}
+use SGMLS::Refs.pm;
+\end{verbatim}}
+
+to activate the library.  The library will create a database
+file to keep track of references between passes, and to tell you if
+any references have changed.  For example, you might want to try
+something like this:
+
+{\footnotesize\begin{verbatim}
+sgml('start', sub {
+  my $Refs = new SGMLS::Refs('references.refs');
+});
+sgml('end', sub {
+  $Refs->warn;
+  destroy $Refs;
+});
+\end{verbatim}}
+
+This code will create an object, \$Refs, linked to a file of
+references called {\tt references.refs}.  The
+{\tt SGMLS::Refs} class understands the methods
+listed in table \ref{TABLE.CLASS.REFS}
+
+\begin{table}[htbp]
+\footnotesize
+\caption{The SGMLS::Refs class}
+\label{TABLE.CLASS.REFS}
+\vspace{2ex}\begin{tabular}{l|l|l}
+\parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} Method\vspace{4pt}}     & \parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} Return Type\vspace{4pt}}      & \parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} Description\vspace{4pt}}     \\ \hline\hline
+\parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} {\tt new}({\tt\sl filename\/},[{\tt\sl logfile\_handle\/}])\vspace{4pt}}        & \parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} {\tt SGMLS::Refs}\vspace{4pt}}        & \parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} Create a new {\tt SGMLS::Refs} object.
+Arguments are the name of the hashfile and (optionally) a writable
+filehandle for logging changes.\vspace{4pt}}   \\ \hline
+\parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} {\tt get}({\tt\sl key\/})\vspace{4pt}}  & \parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} string\vspace{4pt}}   & \parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} Look up a reference key in the hash file and return its value.\vspace{4pt}}  \\ \hline
+\parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} {\tt put}({\tt\sl key\/},{\tt\sl value\/})\vspace{4pt}}         & \parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} [none]\vspace{4pt}}   & \parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} Set a new value for the key in the hashfile.\vspace{4pt}}    \\ \hline
+\parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} {\tt count}\vspace{4pt}}        & \parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} number\vspace{4pt}}   & \parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} Return the number of references whose values have changed (thus
+far).\vspace{4pt}}     \\ \hline
+\parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} {\tt warn}\vspace{4pt}}         & \parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} 1 or 0\vspace{4pt}}   & \parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} Print a warning mentioning the number of references which have
+changed, and return 1 if a warning was printed.\vspace{4pt}}   \\ \hline
+\end{tabular}\end{table}
+
+
+
+
+\section{Are there any bugs?}
+\label{BUGS}
+
+
+Any bugs in {\sc SGMLS.pm} will be here too, since {\sc sgmlspl} relies
+heavily on that {\sc perl5} library.
+
+
+\end{document}
diff --git a/DOC/LaTeX/sgmlspm.refs b/DOC/LaTeX/sgmlspm.refs
new file mode 100644 (file)
index 0000000..6462b67
--- /dev/null
@@ -0,0 +1,29 @@
+{
+  '' => '',
+  'title:SGMLS' => 'How do I use {\\sc SGMLS.pm}?',
+  'title:PERL5' => 'How do I program in {\\sc perl5}?',
+  'title:SGMLSEVENT' => 'So what do I do with an event?',
+  'title:EXTEND' => 'How do I design my {\\em own\\/} classes?',
+  'title:DEFINITION' => 'What is {\\sc SGMLS.pm}?',
+  'title:TERMS' => 'Terms',
+  'title:TABLE.CLASS.SGMLS.ENTITY' => 'The {\\tt SGMLS\\_Entity} class',
+  'title:XTRAINFO' => 'Is there any extra information available from the {\\sc SGML}
+document?',
+  'title:EXAMPLE' => 'How about a simple example?',
+  'title:TABLE.CLASS.SGMLS.EVENT' => 'The {\\tt SGMLS\\_Event} types',
+  'title:SGMLSELEMENT' => 'What do I do with an {\\tt SGMLS\\_Element}?',
+  'title:BUGS' => 'Are there any bugs?',
+  'title:SGMLSNOTATION' => 'What do I do with an {\\tt SGMLS\\_Notation}?',
+  'title:TABLE.CLASS.SGMLS.EXTRA' => 'Additional methods for the {\\tt SGMLS}
+class',
+  'title:SGML' => 'How do I produce {\\sc SGML} documents?',
+  'title:EVENTS' => 'What are the different event types and data?',
+  'title:TABLE.CLASS.SGMLS.ELEMENT' => 'The {\\tt SGMLS\\_Element} class',
+  'title:TABLE.CLASS.SGMLS.NOTATION' => 'The {\\tt SGMLS\\_Notation class}',
+  'title:SGMLSATTRIBUTE' => 'What do I do with an
+{\\tt SGMLS\\_Attribute}?',
+  'title:TABLE.CLASS.SGMLS' => 'The {\\tt SGMLS\\_Event} class',
+  'title:TABLE.CLASS.SGMLS.ATTRIBUTE' => 'The {\\tt SGMLS\\_Attribute} class',
+  'title:SGMLSENTITY' => 'What do I do with an {\\tt SGMLS\\_Entity}?',
+  '' => ''
+}
diff --git a/DOC/LaTeX/sgmlspm.tex b/DOC/LaTeX/sgmlspm.tex
new file mode 100644 (file)
index 0000000..11c42bb
--- /dev/null
@@ -0,0 +1,583 @@
+\documentstyle[11pt]{article}
+
+\setlength{\parskip}{3ex}
+\raggedright
+
+\title{SGMLS.pm: a perl5 class library for handling output from the
+SGMLS and NSGMLS parsers (version 1.03)}
+\author{David Megginson \\
+  Department of English, \\
+  University of Ottawa, \\
+  Email: {\tt dmeggins@aix1.uottawa.ca} \\
+}
+
+
+\begin{document}
+\maketitle
+
+
+Welcome to {\sc SGMLS.pm}, an extensible {\sc perl5} class library for
+processing the output from the {\sc sgmls} and {\sc nsgmls} parsers.
+{\sc SGMLS.pm} is free, copyrighted software available by anonymous ftp in
+the directory ftp://aix1.uottawa.ca/pub/dmeggins/.
+You might also want to look at the documentation for {\sc sgmlspl},
+a simple sample script which uses {\sc SGMLS.pm} to convert documents from
+{\sc SGML} to other formats.
+
+
+{\em\section{Terms}
+\label{TERMS}
+
+
+This program, along with its documentation, 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 2 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
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 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, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+
+}
+
+
+
+\section{What is {\sc SGMLS.pm}?}
+\label{DEFINITION}
+
+
+{\sc SGMLS.pm} is an extensible {\sc perl5}
+class library for parsing the output from James Clark's popular
+{\sc sgmls} and {\sc nsgmls} parsers, available on the Internet at {\tt ftp://jclark.com}.
+This is {\em not\/} a complete system for translating
+documents written the the {\em Standard Generalised Markup
+Language\/} ({\sc SGML}) into other formats, but it can easily
+form the basis of such a system (for a simple example, see the {\sc sgmlspl}
+program included in this package).
+
+The library recognises four basic types of {\sc SGML} objects: the
+{\em element\/}, the
+{\em attribute\/},
+the {\em notation\/}, and the
+{\em entity\/}; each
+of these is a fully-developed class with methods for accessing
+important information.
+
+
+
+
+\section{How do I produce {\sc SGML} documents?}
+\label{SGML}
+
+
+I am presuming here that you are already experienced with {\sc SGML}
+and the {\sc sgmls} or {\sc nsgmls} parser.  For help with the parsers see the
+manual pages accompanying each one; for help with {\sc SGML} see Robin
+Cover's SGML Web Page at {\tt http://www.sil.org/sgml/sgml.html}
+on the Internet.
+
+
+
+
+\section{How do I program in {\sc perl5}?}
+\label{PERL5}
+
+
+If you have to ask this question, you probably should not be
+trying to use this library right now, since it is intended only for
+experienced {\sc perl5} programmers.  That said, however, you can find the
+{\sc perl5} documentation with the {\sc perl5} source distribution or on the
+World-Wide Web at {\tt http://www.metronet.com/0/perlinfo/perl5/manual/perl.html}.
+
+{\em Please\/} do not write to me for help on using
+{\sc perl5}.
+
+
+
+
+\section{How do I use {\sc SGMLS.pm}?}
+\label{SGMLS}
+
+
+First, you need to copy the file {\sc SGMLS.pm} to a directory where
+perl can find it (on a Unix system, it might be
+{\tt /usr/lib/perl5} or
+{\tt /usr/local/lib/perl5}, or whatever the environment
+variable {\tt PERL5LIB} is set to) and make certain that it
+is world-readable.
+
+Next, near the top of your {\sc perl5} program, type the following
+line:
+
+{\footnotesize\begin{verbatim}
+use SGMLS;
+\end{verbatim}}
+
+You must then open up a file handle from which {\sc SGMLS.pm} can read the
+data from an {\sc sgmls} or {\sc nsgmls} process, unless you are reading from
+a standard handle like {\tt STDIN} {---} for example,
+if you are piping the output from {\sc sgmls} to a {\sc perl5} script, using
+something like
+
+{\footnotesize\begin{verbatim}
+sgmls foo.sgml | perl myscript.pl
+\end{verbatim}}
+
+then the predefined filehandle {\tt STDIN} will be
+sufficient.  In DOS, you might want to dump the sgmls output to a file
+and use it as standard input (or open it explicitly in perl), and in
+Unix, you might actually want to open a pipe or socket for the input.
+{\sc SGMLS.pm} doesn't need to seek, so any input stream should
+work.
+
+To parse the {\sc sgmls} or {\sc nsgmls} output from the handle, create
+a new object instance of the {\tt SGMLS} class with
+the handle as an argument, i.e.
+
+{\footnotesize\begin{verbatim}
+$parse = new SGMLS(STDIN);
+\end{verbatim}}
+
+(You may create more than one {\tt SGMLS}
+object at once, but each object {\em must\/} have a
+unique handle pointing to a unique stream, or
+{\em chaos\/} will result.)  Now, you can retrieve and
+process events using the {\tt next\_event} method:
+
+{\footnotesize\begin{verbatim}
+while ($event = $parse->next_event) {
+    #do something with each event
+}
+\end{verbatim}}
+
+
+
+
+\section{So what do I do with an event?}
+\label{SGMLSEVENT}
+
+
+The {\tt next\_event} method for the {\tt SGMLS} class returns an
+object belonging to the class {\tt SGMLS\_Event}.
+This class has several methods available, as listed in table \ref{TABLE.CLASS.SGMLS}.
+
+\begin{table}[htbp]
+\footnotesize
+\caption{The {\tt SGMLS\_Event} class}
+\label{TABLE.CLASS.SGMLS}
+\vspace{2ex}\begin{tabular}{l|l|l}
+\parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} Method\vspace{4pt}}     & \parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} Return Type\vspace{4pt}}      & \parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} Description\vspace{4pt}}     \\ \hline\hline
+\parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} {\tt type}\vspace{4pt}}         & \parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} string\vspace{4pt}}   & \parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} Return the type of the event.\vspace{4pt}}   \\ \hline
+\parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} {\tt data}\vspace{4pt}}         & \parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} string, {\tt SGMLS\_Element}, or
+{\tt SGMLS\_Entity}\vspace{4pt}}        & \parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} Return any data associated with the event.\vspace{4pt}}      \\ \hline
+\parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} {\tt file}\vspace{4pt}}         & \parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} string\vspace{4pt}}   & \parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} Return the name of the {\sc SGML} source file which generated the
+event, if available.\vspace{4pt}}      \\ \hline
+\parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} {\tt line}\vspace{4pt}}         & \parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} string\vspace{4pt}}   & \parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} Return the line number of the {\sc SGML} source file which
+generated the event, if available.\vspace{4pt}}        \\ \hline
+\parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} {\tt element}\vspace{4pt}}      & \parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} {\tt SGMLS\_Element}\vspace{4pt}}     & \parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} Return the element in force when the  event was
+generated.\vspace{4pt}}        \\ \hline
+\parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} {\tt parse}\vspace{4pt}}        & \parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} Return the {\tt SGMLS} object for the current
+parse.\vspace{4pt}}    \\ \hline
+\parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} {\tt entity({\tt\sl ename\/})}\vspace{4pt}}     & \parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} Look up an entity from those currently known to the parse.  An
+alias for {\tt ->parse->entity(\$ename)}\vspace{4pt}}  \\ \hline
+\parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} {\tt notation({\tt\sl nname\/})}\vspace{4pt}}   & \parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} Look up the notation from those currently known to the parse:
+an alias for {\tt ->parse->notation(\$nname)}.\vspace{4pt}}    \\ \hline
+\end{tabular}\end{table}
+
+The {\tt file} and {\tt line} methods
+will return useful information only if you called {\sc sgmls} or {\sc nsgmls}
+with the {\tt\sl -l\/} flag to include file and
+line-number information.
+
+
+
+
+\section{What are the different event types and data?}
+\label{EVENTS}
+
+
+Table \ref{TABLE.CLASS.SGMLS.EVENT} lists the ten
+different event types returned by the {\tt next\_event}
+method of an {\tt SGMLS}
+object and the different types of data associated with each of these
+(note that these do {\em not\/} correspond to the
+standard {\sc ESIS} events).
+
+\begin{table}[htbp]
+\footnotesize
+\caption{The {\tt SGMLS\_Event} types}
+\label{TABLE.CLASS.SGMLS.EVENT}
+\vspace{2ex}\begin{tabular}{l|l|l}
+\parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} Event Type\vspace{4pt}}         & \parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} Event Data\vspace{4pt}}       & \parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} Description\vspace{4pt}}     \\ \hline\hline
+\parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} {\tt 'start\_element'}\vspace{4pt}}     & \parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} {\tt SGMLS\_Element}\vspace{4pt}}     & \parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} The beginning of an element.\vspace{4pt}}    \\ \hline
+\parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} {\tt 'end\_element'}\vspace{4pt}}       & \parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} {\tt SGMLS\_Element}\vspace{4pt}}     & \parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} The end of an element.\vspace{4pt}}  \\ \hline
+\parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} {\tt 'cdata'}\vspace{4pt}}      & \parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} string\vspace{4pt}}   & \parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} Regular character data.\vspace{4pt}} \\ \hline
+\parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} {\tt 'sdata'}\vspace{4pt}}      & \parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} string\vspace{4pt}}   & \parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} Special system data.\vspace{4pt}}    \\ \hline
+\parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} {\tt 're'}\vspace{4pt}}         & \parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} [none]\vspace{4pt}}   & \parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} A record-end (i.e., a newline).\vspace{4pt}} \\ \hline
+\parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} {\tt 'pi'}\vspace{4pt}}         & \parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} string\vspace{4pt}}   & \parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} A processing instruction\vspace{4pt}}        \\ \hline
+\parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} {\tt 'entity'}\vspace{4pt}}     & \parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} {\tt SGMLS\_Entity}\vspace{4pt}}      & \parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} A non-SGML external entity.\vspace{4pt}}     \\ \hline
+\parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} {\tt 'start\_subdoc'}\vspace{4pt}}      & \parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} {\tt SGMLS\_Entity}\vspace{4pt}}      & \parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} The beginning of an SGML subdocument.\vspace{4pt}}   \\ \hline
+\parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} {\tt 'end\_subdoc'}\vspace{4pt}}        & \parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} {\tt SGMLS\_Entity}\vspace{4pt}}      & \parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} The end of an SGML subdocument.\vspace{4pt}} \\ \hline
+\parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} {\tt 'conforming'}\vspace{4pt}}         & \parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} [none]\vspace{4pt}}   & \parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} The document was valid.\vspace{4pt}} \\ \hline
+\end{tabular}\end{table}
+
+For example, if {\tt \$event->type} returns
+{\tt 'start\_element'}, then
+{\tt \$event->data} will return an object belonging to the
+{\tt SGMLS\_Element}
+class (which will contain a list of attributes, etc. {---} see
+below), {\tt \$event->file} and
+{\tt \$event->line} will return the file and line-number
+in which the element appeared (if you called {\sc sgmls} or {\sc nsgmls} with
+the {\tt\sl -l\/} flag), and
+{\tt \$event->element} will return the element currently
+in force (in this case, the same as
+{\tt \$event->data}).
+
+
+
+
+\section{What do I do with an {\tt SGMLS\_Element}?}
+\label{SGMLSELEMENT}
+
+
+Altogether, there are six classes in {\sc SGMLS.pm}, each with its
+own methods: in addition to {\tt SGMLS} (for the parse) and
+{\tt SGMLS\_Event}
+(for a specific event), the classes are
+{\tt SGMLS\_Element}, {\tt SGMLS\_Attribute},
+{\tt SGMLS\_Entity},
+and {\tt SGMLS\_Notation}.
+Like all of these, {\tt SGMLS\_Element} has a number
+of methods available for obtaining different types of information.
+For example, if you were to use
+
+{\footnotesize\begin{verbatim}
+my $element = $event->data
+\end{verbatim}}
+
+to retrieve the data for a {\tt 'start\_element'} or
+{\tt 'end\_element'} event, then you could use the methods
+listed in table \ref{TABLE.CLASS.SGMLS.ELEMENT} to find more
+information about the element.
+
+\begin{table}[htbp]
+\footnotesize
+\caption{The {\tt SGMLS\_Element} class}
+\label{TABLE.CLASS.SGMLS.ELEMENT}
+\vspace{2ex}\begin{tabular}{l|l|l}
+\parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} Method\vspace{4pt}}     & \parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} Return Type\vspace{4pt}}      & \parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} Description\vspace{4pt}}     \\ \hline\hline
+\parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} {\tt name}\vspace{4pt}}         & \parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} string\vspace{4pt}}   & \parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} The name (or GI), in upper-case.\vspace{4pt}}        \\ \hline
+\parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} {\tt parent}\vspace{4pt}}       & \parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} {\tt SGMLS\_Element}\vspace{4pt}}     & \parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} The parent element, or {\tt ''} if this is the top
+element.\vspace{4pt}}  \\ \hline
+\parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} {\tt attributes}\vspace{4pt}}   & \parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} HASH\vspace{4pt}}     & \parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} Return a reference to a hash table of
+{\tt SGMLS\_Attribute} objects, keyed by the attribute
+names (in upper-case).\vspace{4pt}}    \\ \hline
+\parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} {\tt attribute\_names}\vspace{4pt}}     & \parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} ARRAY\vspace{4pt}}    & \parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} A list of all attribute names for the current element (in
+upper-case).\vspace{4pt}}      \\ \hline
+\parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} {\tt attribute({\tt\sl aname\/})}\vspace{4pt}}  & \parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} {\tt SGMLS\_Attribute}\vspace{4pt}}   & \parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} Return the attribute named ANAME.\vspace{4pt}}       \\ \hline
+\parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} {\tt set\_attribute({\tt\sl attribute\/})}\vspace{4pt}}         & \parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} [none]\vspace{4pt}}   & \parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} The {\tt\sl attribute\/} argument should be an
+object belonging to the {\tt SGMLS\_Attribute}
+class.  Add it to the element, replacing any previous attribute with
+the same name.\vspace{4pt}}    \\ \hline
+\parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} {\tt in({\tt\sl name\/})}\vspace{4pt}}  & \parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} {\tt SGMLS\_Element}\vspace{4pt}}     & \parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} If the current element's parent is named
+{\tt\sl name\/}, return the parent; otherwise, return
+{\tt ''}.\vspace{4pt}} \\ \hline
+\parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} {\tt within({\tt\sl name\/})}\vspace{4pt}}      & \parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} {\tt SGMLS\_Element}\vspace{4pt}}     & \parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} If any ancestor of the current element is named
+{\tt\sl name\/}, return it; otherwise, return
+{\tt ''}.\vspace{4pt}} \\ \hline
+\end{tabular}\end{table}
+
+
+
+
+\section{What do I do with an
+{\tt SGMLS\_Attribute}?}
+\label{SGMLSATTRIBUTE}
+
+
+Note that objects of the {\tt SGMLS\_Attribute}
+class do not have events in their own right, and are available only
+through the {\tt attributes} or
+{\tt attribute({\tt\sl aname\/})} methods for
+{\tt SGMLS\_Element}
+objects.  An object belonging to the
+{\tt SGMLS\_Attribute} class will recognise the
+methods listed in table \ref{TABLE.CLASS.SGMLS.ATTRIBUTE}.
+
+\begin{table}[htbp]
+\footnotesize
+\caption{The {\tt SGMLS\_Attribute} class}
+\label{TABLE.CLASS.SGMLS.ATTRIBUTE}
+\vspace{2ex}\begin{tabular}{l|l|l}
+\parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} Method\vspace{4pt}}     & \parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} Return Type\vspace{4pt}}      & \parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} Description\vspace{4pt}}     \\ \hline\hline
+\parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} {\tt name}\vspace{4pt}}         & \parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} string\vspace{4pt}}   & \parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} The name of the attribute (in upper-case).\vspace{4pt}}      \\ \hline
+\parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} {\tt type}\vspace{4pt}}         & \parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} string\vspace{4pt}}   & \parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} The type of the attribute: {\tt 'IMPLIED'},
+{\tt 'CDATA'}, {\tt 'NOTATION'},
+{\tt 'ENTITY'}, or {\tt 'TOKEN'}.\vspace{4pt}} \\ \hline
+\parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} {\tt value}\vspace{4pt}}        & \parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} string, {\tt SGMLS\_Entity}, or
+{\tt SGMLS\_Notation}.\vspace{4pt}}     & \parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} The value of the attribute.  If the type is
+{\tt 'CDATA'} or {\tt 'TOKEN'}, it will be a
+simple string; if it is {\tt 'NOTATION'} it will be an
+object belonging to the {\tt SGMLS\_Notation} class,
+and if it is {\tt 'Entity'} it will be an object
+belonging to the {\tt SGMLS\_Entity} class.\vspace{4pt}}       \\ \hline
+\parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} {\tt is\_implied}\vspace{4pt}}  & \parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} boolean\vspace{4pt}}  & \parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} Return true if the value of the attribute is implied, or false if
+it has an explicit value.\vspace{4pt}} \\ \hline
+\parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} {\tt set\_type({\tt\sl type\/})}\vspace{4pt}}   & \parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} [none]\vspace{4pt}}   & \parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} Provide a new type for the current attribute -- no sanity
+checking will be performed, so be careful.\vspace{4pt}}        \\ \hline
+\parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} {\tt set\_value({\tt\sl value\/})}\vspace{4pt}}         & \parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} [none]\vspace{4pt}}   & \parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} Provide a new value for the current attribute -- no sanity
+checking will be performed, so be careful.\vspace{4pt}}        \\ \hline
+\end{tabular}\end{table}
+
+Note that the type {\tt 'TOKEN'} includes both
+individual tokens and lists of tokens (ie {\tt 'TOKENS'},
+{\tt 'IDS'}, or {\tt 'IDREFS'} in the
+original {\sc SGML} document), so you might need to use the perl function
+'split' to break the value string into a list.
+
+
+
+
+\section{What do I do with an {\tt SGMLS\_Entity}?}
+\label{SGMLSENTITY}
+
+
+An {\tt SGMLS\_Entity} object can come in an
+{\tt 'entity'} event (in
+which case it is always external), in a
+{\tt 'start\_subdoc'} or {\tt 'end\_subdoc'}
+event (in which case it always has the type
+{\tt 'SUBDOC'}), or as the value of an attribute (in
+which case it may be internal or external).  An object belonging to
+the {\tt SGMLS\_Entity} class may use the methods
+listed in table \ref{TABLE.CLASS.SGMLS.ENTITY}.
+
+\begin{table}[htbp]
+\footnotesize
+\caption{The {\tt SGMLS\_Entity} class}
+\label{TABLE.CLASS.SGMLS.ENTITY}
+\vspace{2ex}\begin{tabular}{l|l|l}
+\parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} Method\vspace{4pt}}     & \parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} Return Type\vspace{4pt}}      & \parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} Description\vspace{4pt}}     \\ \hline\hline
+\parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} {\tt name}\vspace{4pt}}         & \parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} string\vspace{4pt}}   & \parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} The entity name.\vspace{4pt}}        \\ \hline
+\parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} {\tt type}\vspace{4pt}}         & \parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} string\vspace{4pt}}   & \parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} The entity type: {\tt 'CDATA'},
+{\tt 'SDATA'}, {\tt 'NDATA'}, or
+{\tt 'SUBDOC'}.\vspace{4pt}}   \\ \hline
+\parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} {\tt value}\vspace{4pt}}        & \parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} string\vspace{4pt}}   & \parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} The entity replacement text (internal entities
+only).\vspace{4pt}}    \\ \hline
+\parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} {\tt sysid}\vspace{4pt}}        & \parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} string\vspace{4pt}}   & \parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} The system identifier (external entities only).\vspace{4pt}} \\ \hline
+\parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} {\tt pubid}\vspace{4pt}}        & \parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} string\vspace{4pt}}   & \parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} The public identifier (external entities only).\vspace{4pt}} \\ \hline
+\parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} {\tt filenames}\vspace{4pt}}    & \parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} ARRAY\vspace{4pt}}    & \parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} A list of file names generated from the sysid and pubid
+(external entities only).\vspace{4pt}} \\ \hline
+\parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} {\tt notation}\vspace{4pt}}     & \parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} {\tt SGMLS\_Notation}\vspace{4pt}}    & \parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} The associated notation (external data entities only).\vspace{4pt}}  \\ \hline
+\end{tabular}\end{table}
+
+An entity of type {\tt 'SUBDOC'} will have a sysid
+and pubid, and external data entity will have a sysid, pubid,
+filenames, and a notation, and an internal data entity will have a
+value.
+
+
+
+
+\section{What do I do with an {\tt SGMLS\_Notation}?}
+\label{SGMLSNOTATION}
+
+
+The fourth data class is the notation, which is available only
+as a return value from the {\tt notation} method of an
+{\tt SGMLS\_Entity}
+or the {\tt value} method of an {\tt SGMLS\_Attribute}
+with type {\tt 'NOTATION'}.  You can use the notation to
+decide how to treat non-SGML data (such as graphics).  An object
+belonging to the {\tt SGMLS\_Notation} class will have
+access to the methods listed in table \ref{TABLE.CLASS.SGMLS.NOTATION}.
+
+\begin{table}[htbp]
+\footnotesize
+\caption{The {\tt SGMLS\_Notation class}}
+\label{TABLE.CLASS.SGMLS.NOTATION}
+\vspace{2ex}\begin{tabular}{l|l|l}
+\parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} Method\vspace{4pt}}     & \parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} Return Type\vspace{4pt}}      & \parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} Description\vspace{4pt}}     \\ \hline\hline
+\parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} {\tt name}\vspace{4pt}}         & \parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} string\vspace{4pt}}   & \parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} The notation's name.\vspace{4pt}}    \\ \hline
+\parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} {\tt sysid}\vspace{4pt}}        & \parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} string\vspace{4pt}}   & \parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} The notation's system identifier.\vspace{4pt}}       \\ \hline
+\parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} {\tt pubid}\vspace{4pt}}        & \parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} string\vspace{4pt}}   & \parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} The notation's public identifier.\vspace{4pt}}       \\ \hline
+\end{tabular}\end{table}
+
+What you do with this information is
+{\em entirely\/} up to you.
+
+
+
+
+\section{Is there any extra information available from the {\sc SGML}
+document?}
+\label{XTRAINFO}
+
+
+The {\tt SGMLS}
+object which you created at the beginning of the parse has several
+methods available in addition to {\tt next\_event} {---}
+you will find them all listed in table \ref{TABLE.CLASS.SGMLS.EXTRA}.  There should normally be no need to
+use the {\tt notation} and {\tt entity}
+methods, since {\sc SGMLS.pm} will look up entities and notations for you
+automatically as needed.
+
+\begin{table}[htbp]
+\footnotesize
+\caption{Additional methods for the {\tt SGMLS}
+class}
+\label{TABLE.CLASS.SGMLS.EXTRA}
+\vspace{2ex}\begin{tabular}{l|l|l}
+\parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} Method\vspace{4pt}}     & \parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} Return Type\vspace{4pt}}      & \parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} Description\vspace{4pt}}     \\ \hline\hline
+\parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} {\tt next\_event}\vspace{4pt}}  & \parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} {\tt SGMLS\_Event}\vspace{4pt}}       & \parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} Return the next event.\vspace{4pt}}  \\ \hline
+\parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} {\tt appinfo}\vspace{4pt}}      & \parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} string\vspace{4pt}}   & \parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} Return the APPINFO parameter from the {\sc SGML} declaration, if
+any.\vspace{4pt}}      \\ \hline
+\parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} {\tt notation({\tt\sl nname\/})}\vspace{4pt}}   & \parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} {\tt SGMLS\_Notation}\vspace{4pt}}    & \parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} Look up a notation by name.\vspace{4pt}}     \\ \hline
+\parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} {\tt entity({\tt\sl ename\/})}\vspace{4pt}}     & \parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} {\tt SGMLS\_Entity}\vspace{4pt}}      & \parbox[c]{1.48333333333333in}{\raggedright\vspace{4pt} Look up an entity by name.\vspace{4pt}}      \\ \hline
+\end{tabular}\end{table}
+
+
+
+
+\section{How about a simple example?}
+\label{EXAMPLE}
+
+
+OK.  The following script simply reports its events:
+
+{\footnotesize\begin{verbatim}
+#!/usr/bin/perl
+
+use SGMLS;
+
+$this_parse = new SGMLS(STDIN); # Read from standard input.
+
+while ($this_event = $this_parse->next_event) {
+    my $type = $this_event->type;
+    my $data = $this_event->data;
+  SWITCH: {
+      $type eq 'start_element' && do {
+          print "Beginning element: " . $data->name . "\n";
+          last SWITCH;
+      };
+      $type eq 'end_element' && do {
+          print "Ending element: " . $data->name . "\n";
+          last SWITCH;
+      };
+      $type eq 'cdata' && do {
+          print "Character data: " . $data . "\n";
+          last SWITCH;
+      };
+      $type eq 'sdata' && do {
+          print "Special data: " . $data . "\n";
+          last SWITCH;
+      };
+      $type eq 're' && do {
+          print "Record End\n";
+          last SWITCH;
+      };
+      $type eq 'pi' && do {
+          print "Processing Instruction: " . $data . "\n";
+          last SWITCH;
+      };
+      $type eq 'entity' && do {
+          print "External Data Entity: " . $data->name .
+              " with notation " . $data->notation->name . "\n";
+          last SWITCH;
+      };
+      $type eq 'start_subdoc' && do {
+          print "Beginning Subdocument Entity: " . $data->name . "\n";
+          last SWITCH;
+      };
+      $type eq 'end_subdoc' && do {
+          print "Ending Subdocument Entity: " . $data->name . "\n";
+          last SWITCH;
+      };
+      $type eq 'conforming' && do {
+          print "This is a conforming SGML document\n";
+          last SWITCH;
+      };
+  }
+}
+
+\end{verbatim}}
+
+To use it under Unix, try something like
+
+{\footnotesize\begin{verbatim}
+sgmls document.sgml | perl sample.pl
+\end{verbatim}}
+
+and watch the output scroll down.
+
+
+
+
+\section{How do I design my {\em own\/} classes?}
+\label{EXTEND}
+
+
+In addition to the methods listed above, all of the classes used
+in {\sc SGMLS.pm} have an {\tt ext} method which returns a
+reference to an initially-empty hash table.  You are free to use this
+hash table to store {\em anything\/} you want {---} it
+should be especially useful if you are building your own, derived
+classes from the ones provided here.  The following example builds a
+derived class {\tt My\_Element} from the {\tt SGMLS\_Element}
+class, adding methods to set and get the current font:
+
+{\footnotesize\begin{verbatim}
+use SGMLS;
+
+package My_Element;
+@ISA = qw(SGMLS_Element);
+
+sub new {
+  my ($class,$element,$font) = @_;
+  $element->ext->{'font'} = $font;
+  return bless $element;
+}
+
+sub get_font {
+  my ($self) = @_;
+  return $self->ext->{'font'};
+}
+
+sub set_font {
+  my ($self,$font) = @_;
+  $self->ext->{'font'} = $font;
+}
+\end{verbatim}}
+
+Note that the derived class does not need to have any knowledge
+about the underlying structure of the {\tt SGMLS\_Element}
+class, and need only avoid shadowing any of the methods currently
+existing there.
+
+If you decide to create a derived class from the {\tt SGMLS}, please note that in
+addition to the methods listed above, that class uses internal methods
+named {\tt element}, {\tt line}, and
+{\tt file}, similar to the same methods in {\tt SGMLS\_Event} {---}
+it is essential that you not shadow these method names.
+
+
+
+
+\section{Are there any bugs?}
+\label{BUGS}
+
+
+Of course!  Right now, {\sc SGMLS.pm} silently ignores link attributes
+({\sc nsgmls} only) and data attributes, and there may be many other bugs
+which I have not yet found.
+
+
+\end{document}
diff --git a/DOC/Makefile b/DOC/Makefile
new file mode 100644 (file)
index 0000000..96c0831
--- /dev/null
@@ -0,0 +1,124 @@
+########################################################################
+# Makefile for producing HTML and LaTeX (and thence, DVI and
+# Postscript) versions of the SGML documentation.
+#
+# version 1.03
+#
+# *** NOTE ***
+#
+# This will _not_ work unless you have the Docbook 2.2.1 DTD properly
+# installed on your system, and sgmls or nsgmls can find it using the
+# public identifier "-//HaL and O'Reilly//DTD DocBook//EN".  You will
+# also need the character-entity files with the public identifiers
+#
+# "ISO 8879:1986//ENTITIES Publishing//EN"
+#    and
+# "ISO 8879:1986//ENTITIES Numeric and Special Graphic//EN"
+#
+# installed.  Copies of the source files for these are included in
+# the Extras/ subdirectory.
+########################################################################
+
+#
+# Beginning of user configuration options.
+#
+
+# Which program do you use: sgmls or nsgmls?
+SGMLS = nsgmls
+
+# What is the command for running LaTeX on a file?
+LATEX = latex
+
+# Do you want to supply a full path for sgmlspl?
+SGMLSPL = sgmlspl
+
+# If you want Postscript, what is the command for converting DVI to Postscript?
+DVIPS = dvips
+
+# What SGML declaration do you use with the Docbook 2.2.1 DTD?
+SGMLDECL = /usr/local/lib/sgml/sgmldecl/docbook.dcl
+
+#
+# End of user configuration options.
+#
+
+SHELL = /bin/sh
+LATEXSPEC = tolatex.pl
+HTMLSPEC = tohtml.pl
+
+all: latex html
+
+latex: LaTeX/sgmlspm.tex LaTeX/sgmlspl.tex
+dvi: LaTeX/sgmlspm.dvi LaTeX/sgmlspl.dvi
+ps: PS/sgmlspm.ps PS/sgmlspl.ps
+html:  HTML/SGMLSpm/sgmlspm.html HTML/sgmlspl/sgmlspl.html
+
+
+LaTeX/sgmlspm.tex: sgmlspm.sgml ${LATEXSPEC}
+       @echo Converting sgmlspm.sgml to LaTeX...; \
+       cd LaTeX; ln -sf ../sample.pl .; \
+       if [ \! -r sgmlspm.refs -o -r .redo_sgmlspm ]; then \
+         echo \(Preliminary LaTeX pass for sgmlspm.sgml...\); \
+         ${SGMLS} ${SGMLDECL} ../sgmlspm.sgml \
+           | $(SGMLSPL) ../${LATEXSPEC} sgmlspm > sgmlspm.tex; \
+       fi; \
+       echo \(Main LaTeX pass for sgmlspm.sgml...\); \
+       ${SGMLS} ${SGMLDECL} ../sgmlspm.sgml \
+         | $(SGMLSPL) ../${LATEXSPEC} sgmlspm >sgmlspm.tex
+
+LaTeX/sgmlspm.dvi: LaTeX/sgmlspm.tex
+       @echo Converting sgmlspm.tex to DVI...; \
+       cd LaTeX; ${LATEX} sgmlspm.tex; ${LATEX} sgmlspm.tex
+
+PS/sgmlspm.ps: LaTeX/sgmlspm.dvi
+       @echo Converting sgmlspm.dvi to Postscript...; \
+       ${DVIPS} -o PS/sgmlspm.ps LaTeX/sgmlspm.dvi
+
+HTML/SGMLSpm/sgmlspm.html: sgmlspm.sgml ${HTMLSPEC}
+       @cd HTML/SGMLSpm; ln -sf ../../sample.pl .; \
+       echo Converting sgmlspm.sgml to HTML...; \
+       if [ \! -r sgmlspm.refs -o -r .redo_sgmlspm ]; then \
+         echo \(Preliminary HTML pass for sgmlspm.sgml...\); \
+         ${SGMLS} ${SGMLDECL} ../../sgmlspm.sgml \
+           | $(SGMLSPL) ../../${HTMLSPEC} sgmlspm; \
+       fi; \
+       echo \(Main HTML pass for sgmlspm.sgml...\); \
+       ${SGMLS} ${SGMLDECL} ../../sgmlspm.sgml \
+         | $(SGMLSPL) ../../${HTMLSPEC} sgmlspm;
+
+LaTeX/sgmlspl.tex: sgmlspl.sgml ${LATEXSPEC}
+       @echo Converting sgmlspl.sgml to LaTeX...; \
+       cd LaTeX; \
+       if [ \! -r sgmlspl.refs -o -r .redo_sgmlspl ]; then \
+         echo \(Preliminary LaTeX pass for sgmlspl.sgml...\); \
+         ${SGMLS} ${SGMLDECL} ../sgmlspl.sgml \
+           | $(SGMLSPL) ../${LATEXSPEC} sgmlspl > sgmlspl.tex; \
+       fi; \
+       echo \(Main LaTeX pass for sgmlspl.sgml...\); \
+       ${SGMLS} ${SGMLDECL} ../sgmlspl.sgml \
+         | $(SGMLSPL) ../${LATEXSPEC} sgmlspl > sgmlspl.tex
+
+LaTeX/sgmlspl.dvi: LaTeX/sgmlspl.tex
+       @echo Converting sgmlspl.tex to DVI...; \
+       cd LaTeX; \
+       ${LATEX} sgmlspl.tex; ${LATEX} sgmlspl.tex
+
+PS/sgmlspl.ps: LaTeX/sgmlspl.dvi
+       @echo Converting sgmlspl.dvi to Postscript...; \
+       ${DVIPS} -o PS/sgmlspl.ps LaTeX/sgmlspl.dvi
+
+HTML/sgmlspl/sgmlspl.html: sgmlspl.sgml ${HTMLSPEC}
+       @cd HTML/sgmlspl; \
+       echo Converting sgmlspl.sgml to HTML...; \
+       if [ ! -r sgmlspl.refs -o -r .redo_sgmlspl ]; then \
+         echo \(Preliminary HTML pass for sgmlspl.sgml...\); \
+         ${SGMLS} ${SGMLDECL} ../../sgmlspl.sgml \
+           | $(SGMLSPL) ../../${HTMLSPEC} sgmlspl; \
+       fi; \
+       echo \(Main HTML pass for sgmlspl.sgml...\); \
+       ${SGMLS} ${SGMLDECL} ../../sgmlspl.sgml \
+         | $(SGMLSPL) ../../${HTMLSPEC} sgmlspl;
+
+clean:
+       rm -f *~ core LaTeX/* HTML/SGMLSpm/* HTML/sgmlspl/* PS/*
+
diff --git a/DOC/README b/DOC/README
new file mode 100644 (file)
index 0000000..a9df29a
--- /dev/null
@@ -0,0 +1,11 @@
+This directory contains the SGML source files documention SGMLS.pm and
+sgmlspl.  If you are working in Unix or a Unix-like environment, make
+any necessary changes in the Makefile then type one of the following:
+
+  make latex   Generate LaTeX source files of the documentation.
+  make dvi     Generate a printable DVI version of the documentation.
+  make ps      Generate a printable Postscript version of the docs.
+  make html    Generate an HTML version of the documentation.
+  make all     Generate _all_ of the above.
+  make clean    Remove all generated files.
+
diff --git a/DOC/TODO b/DOC/TODO
new file mode 100644 (file)
index 0000000..78ccbc6
--- /dev/null
+++ b/DOC/TODO
@@ -0,0 +1,4 @@
+SGMLS.pm documentation: things to do
+
+- move to the new HTML table standard instead of breaking the tables
+up into lists.
\ No newline at end of file
diff --git a/DOC/sample.pl b/DOC/sample.pl
new file mode 100644 (file)
index 0000000..27bf221
--- /dev/null
@@ -0,0 +1,53 @@
+#!/usr/bin/perl
+
+use SGMLS;
+
+$this_parse = new SGMLS(STDIN); # Read from standard input.
+
+while ($this_event = $this_parse->next_event) {
+    my $type = $this_event->type;
+    my $data = $this_event->data;
+  SWITCH: {
+      $type eq 'start_element' && do {
+          print "Beginning element: " . $data->name . "\n";
+          last SWITCH;
+      };
+      $type eq 'end_element' && do {
+          print "Ending element: " . $data->name . "\n";
+          last SWITCH;
+      };
+      $type eq 'cdata' && do {
+          print "Character data: " . $data . "\n";
+          last SWITCH;
+      };
+      $type eq 'sdata' && do {
+          print "Special data: " . $data . "\n";
+          last SWITCH;
+      };
+      $type eq 're' && do {
+          print "Record End\n";
+          last SWITCH;
+      };
+      $type eq 'pi' && do {
+          print "Processing Instruction: " . $data . "\n";
+          last SWITCH;
+      };
+      $type eq 'entity' && do {
+          print "External Data Entity: " . $data->name .
+              " with notation " . $data->notation->name . "\n";
+          last SWITCH;
+      };
+      $type eq 'start_subdoc' && do {
+          print "Beginning Subdocument Entity: " . $data->name . "\n";
+          last SWITCH;
+      };
+      $type eq 'end_subdoc' && do {
+          print "Ending Subdocument Entity: " . $data->name . "\n";
+          last SWITCH;
+      };
+      $type eq 'conforming' && do {
+          print "This is a conforming SGML document\n";
+          last SWITCH;
+      };
+  }
+}
diff --git a/DOC/sgmlspl.sgml b/DOC/sgmlspl.sgml
new file mode 100644 (file)
index 0000000..8d7ce88
--- /dev/null
@@ -0,0 +1,780 @@
+<!DOCTYPE article PUBLIC "-//HaL and O'Reilly//DTD DocBook//EN" [
+  <!ENTITY % ISOpub PUBLIC "ISO 8879:1986//ENTITIES Publishing//EN">
+  %ISOpub;
+  <!ENTITY % ISOnum PUBLIC
+    "ISO 8879:1986//ENTITIES Numeric and Special Graphic//EN">
+  %ISOnum;
+
+  <!ENTITY sgml "<ulink url='http://www.sil.org/sgml/sgml.html'><acronym>SGML</acronym></ulink>">
+  <!ENTITY esis "<acronym>ESIS</acronym>">
+  <!ENTITY sgmls.pm "<ulink url='../SGMLSpm/sgmlspm.html'><application>SGMLS.pm</application></ulink>">
+  <!ENTITY output.pm "<link linkend='output'><application>SGMLS::Output</application></link>">
+  <!ENTITY sgmlspl "<link linkend='sgmlspl'><application>sgmlspl</application></link>">
+  <!ENTITY perl5 "<ulink url='http://www.metronet.com/0/perlinfo/perl5/manual/perl.html'><application>perl5</application></ulink>">
+  <!ENTITY sgmls "<application>sgmls</application>">
+  <!ENTITY nsgmls "<ulink url='http://www.jclark.com/sp.html'><application>nsgmls</application></ulink>">
+  <!ENTITY LaTeX SDATA "[LaTeX]">
+]>
+
+<article id=sgmlspl>
+
+<artheader>
+
+<title>sgmlspl: a simple post-processor for SGMLS and NSGMLS (for use
+with &sgmls.pm; version 1.03)</title>
+
+<authorgroup>
+<author>
+<firstname>David</firstname>
+<surname>Megginson</surname>
+<affiliation>
+<orgname>University of Ottawa</orgname>
+<orgdiv>Department of English</orgdiv>
+<address><email>dmeggins@aix1.uottawa.ca</email></address>
+</affiliation>
+</author>
+</authorgroup>
+
+<artpagenums>[unpublished]</artpagenums>
+
+</artheader>
+
+<para>Welcome to &sgmlspl;, a simple sample &perl5; application which
+uses the &sgmls.pm; class library.</para>
+
+<important id=terms>
+<title>Terms</title>
+
+<para>This program, along with its documentation, 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 2 of the License, or (at your option) any later
+version.</para>
+
+<para>This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.</para>
+
+<para>You should have received a copy of the GNU General Public
+License along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.</para>
+
+</important>
+
+<sect1 id=definition>
+<title>What is &sgmlspl;?</title>
+
+<para>&sgmlspl; is a sample application distributed with the
+&sgmls.pm; &perl5; class library &mdash; you can use it to convert
+&sgml; documents to other formats by providing a <link
+linkend='specs'><glossterm>specification file</glossterm></link>
+detailing exactly how you want to handle each element, external data
+entity, subdocument entity, CDATA string, record end, SDATA string,
+and processing instruction.  &sgmlspl; also uses the &output.pm;
+library (included in this distribution) to allow you to redirect or
+capture output.</para>
+
+<para>To use &sgmlspl;, you simply prepare a specification file
+containing regular &perl5; code.  If your &sgml; document were named
+<filename>doc.sgml</filename>, your &sgmlspl; specification file
+were named, <filename>spec.pl</filename>, and the name of your new
+file were <filename>doc.latex</filename>, then you could use the
+following command in a Unix shell to convert your &sgml; document:</para>
+
+<programlisting>
+sgmls doc.sgml | sgmlspl spec.pl > doc.latex
+</programlisting>
+
+<para>&sgmlspl will pass any additional arguments on to the specification
+file, which can process them in the regular &perl5; fashion.  The
+specification files used to convert this manual &mdash;
+<filename>tolatex.pl</filename> and <filename>tohtml.pl</filename>
+&mdash; are available with the &sgmls.pm; distribution.</para>
+
+</sect1>
+
+
+<sect1 id=installation>
+<title>How do I install &sgmlspl; on my system?</title>
+
+<para>To use &sgmlspl;, you need to install &sgmls.pm; on your system,
+by copying the &sgmls.pm; file to a directory searched by &perl5;.
+You also need to install &output.pm; in the same directory, and
+&sgmlspl; (with execute permission) somewhere on your
+<symbol>PATH</symbol>.  The easiest way to do all of this on a Unix
+system is to change to the root directory of this distribution
+(<filename>SGMLSpm</filename>), edit the <filename>Makefile</filename>
+appropriately, and type</para>
+
+<programlisting>
+make install
+</programlisting>
+
+</sect1>
+
+
+<sect1 id=dsssl>
+<title>Is &sgmlspl; the best way to convert &sgml; documents?</title>
+
+<para>Not necessarily.  While &sgmlspl; is fully functional, it is not
+always particularly intuitive or pleasant to use.  There is a new
+proposed standard, <glossterm>Document Style Semantics and
+Specification Language</glossterm> (<acronym>DSSSL</acronym>), based
+on the <application>Scheme</application> programming language, and
+implementations should soon be available.  To read more about the
+<application>DSSSL</application> standard, see <ulink
+url="http://www.jclark.com/dsssl"><filename>http://www.jclark.com/dsssl/</filename></ulink>
+on the Internet.</para>
+
+<para>That said, <acronym>DSSSL</acronym> is a declarative,
+side-effect-free programming language, while &sgmlspl; allows you to
+use any programming constructions available in &perl5;, including
+those with side-effects.  This means that if you want to do more than
+simply format the document or convert it from one <glossterm>Document
+Type Definition</glossterm> (<acronym>DTD</acronym>) to another,
+&sgmlspl; might be a good choice.</para>
+
+</sect1>
+
+
+<sect1 id=specs>
+<title>How does the specification file tell &sgmlspl; what to do?</title>
+
+<para>&sgmlspl; uses an <glossterm>event model</glossterm> rather than
+a <glossterm>procedural model</glossterm> &mdash; instead of
+saying <quote>do A then B then C</quote> you say <quote>whenever X
+happens, do A; whenever Y happens, do B; whenever Z happens, do
+C</quote>.  In other words, while you design the code, &sgmlspl;
+decides when and how often to run it.</para>
+
+<para>The specification file, which contains your instructions, is
+regular &perl5; code, and you can define packages and subroutines,
+display information, read files, create variables, etc.  For
+processing the &sgml; document, however, &sgmlspl; exports a single
+subroutine, <command>sgml(<parameter>event</parameter>,
+<parameter>handler</parameter>)</command>, into the 'main' package
+&mdash; each time you call <command>sgml</command>, you declare a
+handler for a specific type of &sgmls; <ulink
+url='../SGMLSpm/events.html'>event</ulink>, and &sgmlspl; will then
+execute that handler every time the event occurs.  You may use
+<command>sgml</command> to declare a <link
+linkend='handlers'>handler</link> for a <link
+linkend='generic'><glossterm>generic event</glossterm></link>, like
+<literal>'start_element'</literal>, or a <link
+linkend='specific'><glossterm>specific event</glossterm></link>,
+like <literal>'&lt;DOC&gt;'</literal> &mdash; a specific event will
+always take precedence over a generic event, so when the
+<symbol>DOC</symbol> element begins, &sgmlspl; will execute the
+<literal>'&lt;DOC&gt;'</literal> handler rather than the
+<literal>'start_element'</literal> handler.</para>
+
+</sect1>
+
+
+<sect1 id=handlers>
+<title>What about the <parameter>handler</parameter> argument?</title>
+
+<para>The second argument to the <command>sgml</command> subroutine is
+the actual code or data associated with each event.  If it is a
+string, it will be printed literally using the
+<command>output</command> subroutine from the &output.pm; library; if
+it is a reference to a &perl5; subroutine, the subroutine will be
+called whenever the event occurs.  The following three
+<command>sgml</command> commands will have identical results:</para>
+
+<programlisting>
+# Example 1
+sgml('&lt;DOC&gt;', "\\begin{document}\n");
+
+# Example 2
+sgml('&lt;DOC&gt;', sub {
+  output "\\begin{document}\n";
+});
+
+# Example 3
+sub do_begin_document { output "\\begin{document}\n"; }
+sgml('&lt;DOC&gt;', \&amp;do_begin_document);
+</programlisting>
+
+<para>For simply printing a string, of course, it does not make sense
+to use a subroutine; however, the subroutines can be useful when you
+need to check the value of an attribute, perform different actions in
+different contexts, or perform other types of relatively more
+complicated post-processing.</para>
+
+<para>If your handler is a subroutine, then it will receive two
+arguments: the &sgmls.pm; event's data, and the &sgmls.pm; event
+itself (see the &sgmls.pm; <ulink
+url='../SGMLSpm/events.html'>documentation</ulink> for a description
+of event and data types).  The following example will print
+<literal>'\begin{enumerate}'</literal> if the value of the attribute
+<symbol>TYPE</symbol> is <literal>'ORDERED'</literal>, and
+<literal>'\begin{itemize}'</literal> if the value of the attribute
+<symbol>TYPE</symbol> is <literal>'UNORDERED'</literal>:</para>
+
+<programlisting>
+sgml('&lt;LIST&gt;', sub {
+  my ($element,$event) = @_;
+  my $type = $element->attribute('TYPE')->value;
+
+  if ($type eq 'ORDERED') {
+    output "\\begin{enumerate}\n";
+  } elsif ($type eq 'UNORDERED') {
+    output "\\begin{itemize}\n";
+  } else {
+    die "Bad TYPE '$type' for element LIST at line " .
+      $event->line . " in " . $event->file . "\n";
+  }
+});
+</programlisting>
+
+<para>You will not always need to use the <parameter>event</parameter>
+argument, but it can be useful if you want to report line numbers or
+file names for errors (presuming that you called &sgmls; or &nsgmls;
+with the <parameter>-l</parameter> option).  If you have a new version
+of &nsgmls; which accepts the <parameter>-h</parameter> option, you
+can also use the <parameter>event</parameter> argument to look up
+arbitrary entities declared by the program. See the <ulink
+url="../SGMLSpm/sgmlsevent.html">SGMLS_Event</ulink> documentation for
+more information.</para>
+
+</sect1>
+
+
+<sect1 id=generic>
+<title>What are the generic events?</title>
+
+<para>&sgmlspl; recognises the twelve generic events listed in table
+<xref linkend=table.events.generic>.  You may provide any one of these
+as the first argument to <command>sgml</command> to declare a handler
+(string or subroutine) for that event.</para>
+
+<table id=table.events.generic>
+<title>&sgmlspl; generic events</title>
+
+<tgroup cols=2>
+
+<thead>
+
+<row>
+<entry>Event</entry>
+<entry>Description</entry>
+</row>
+
+</thead>
+
+<tbody>
+
+<row>
+<entry><literal>'start'</literal></entry>
+<entry>Execute <parameter>handler</parameter> (with no arguments) at
+the beginning of the parse.</entry>
+</row>
+
+<row>
+<entry><literal>'end'</literal></entry>
+<entry>Execute <parameter>handler</parameter> (with no arguments) at
+the end of the parse.</entry>
+</row>
+
+<row>
+<entry><literal>'start_element'</literal></entry>
+<entry>Execute <parameter>handler</parameter> at the beginning of every
+element without a specific start handler.</entry>
+</row>
+
+<row>
+<entry><literal>'end_element'</literal></entry>
+<entry>Execute <parameter>handler</parameter> at the end of every
+element without a specific end handler.</entry>
+</row>
+
+<row>
+<entry><literal>'cdata'</literal></entry>
+<entry>Execute <parameter>handler</parameter> for every character-data
+string.</entry>
+</row>
+
+<row>
+<entry><literal>'sdata'</literal></entry>
+<entry>Execute <parameter>handler</parameter> for every special-data
+string without a specific handler.</entry>
+</row>
+
+<row>
+<entry><literal>'re'</literal></entry>
+<entry>Execute <parameter>handler</parameter> for every
+record end.</entry>
+</row>
+
+<row>
+<entry><literal>'pi'</literal></entry>
+<entry>Execute <parameter>handler</parameter> for every processing
+instruction.</entry>
+</row>
+
+<row>
+<entry><literal>'entity'</literal></entry>
+<entry>Execute <parameter>handler</parameter> for every external data
+entity without a specific handler.</entry>
+</row>
+
+<row>
+<entry><literal>'start_subdoc'</literal></entry>
+<entry>Execute <parameter>handler</parameter> at the beginning of every
+subdocument entity without a specific handler.</entry>
+</row>
+
+<row>
+<entry><literal>'end_subdoc'</literal></entry>
+<entry>Execute <parameter>handler</parameter> at the end of every
+subdocument entity without a specific handler.</entry>
+</row>
+
+<row>
+<entry><literal>'conforming'</literal></entry>
+<entry>Execute <parameter>handler</parameter> once, at the end of the
+document parse, if and only if the document was conforming.</entry>
+</row>
+
+</tbody>
+</tgroup>
+</table>
+
+<para>The handlers for all of these except the document events
+<literal>'start'</literal> and <literal>'end'</literal> will receive
+two arguments whenever they are called: the first will be the data
+associated with the event (if any), and the second will be the
+<classname>SGMLS_Event</classname> object itself (see the document for
+&sgmls.pm;).  Note the following example, which allows processing
+instructions for including the date or the hostname in the document at
+parse time:</para>
+
+<programlisting>
+sgml('pi', sub {
+    my ($instruction) = @_;
+    if ($instruction eq 'date') {
+      output `date`;
+    } elsif ($instruction eq 'hostname') {
+      output `hostname`;
+    } else {
+      print STDERR "Warning: unknown processing instruction: $instruction\n";
+    }
+});
+</programlisting>
+
+<para>With this <link linkend='handlers'>handler</link>, any occurance
+of <literal>&lt;?date&gt;</literal> in the original &sgml; document
+would be replaced by the current date and time, and any occurance of
+<literal>&lt;?hostname&gt;</literal> would be replaced by the name of
+the host.</para>
+
+</sect1>
+
+
+<sect1 id=specific>
+<title>What are the specific events?</title>
+
+<para>In addition to the <link linkend=generic>generic
+events</link> listed in the previous section, &sgmlspl; allows
+special, specific handlers for the beginning and end of elements and
+subdocument entities, for SDATA strings, and for external data
+entities.  Table <xref linkend=table.events.specific> lists the
+different specific event types available.</para>
+
+<table id=table.events.specific>
+<title>Specific event types</title>
+
+<tgroup cols=2>
+
+<thead>
+
+<row>
+<entry>Event</entry>
+<entry>Description</entry>
+</row>
+
+</thead>
+
+<tbody>
+
+<row>
+<entry><literal>'&lt;GI&gt;'</literal></entry>
+<entry>Execute <parameter>handler</parameter> at the beginning of
+every element named <literal>'GI'</literal>.</entry>
+</row>
+
+<row>
+<entry><literal>'&lt;/GI&gt;'</literal></entry>
+<entry>Execute <parameter>handler</parameter> at the end of every
+element named <literal>'GI'</literal>.</entry>
+</row>
+
+<row>
+<entry><literal>'|SDATA|'</literal></entry>
+<entry>Execute <parameter>handler</parameter> for every special-data
+string <literal>'SDATA'</literal>.</entry>
+</row>
+
+<row>
+<entry><literal>'&amp;ENTITY;'</literal></entry>
+<entry>Execute <parameter>handler</parameter> for every external data
+entity named <literal>'ENTITY'</literal>.</entry>
+</row>
+
+<row>
+<entry><literal>'{ENTITY}'</literal></entry>
+<entry>Execute <parameter>handler</parameter> at the beginning of
+every subdocument entity named <literal>'ENTITY'</literal>.</entry>
+</row>
+
+<row>
+<entry><literal>'{/ENTITY}'</literal></entry>
+<entry>Execute <parameter>handler</parameter> at the end of every
+subdocument entity named <literal>'ENTITY'</literal>.</entry>
+</row>
+
+</tbody>
+</tgroup>
+
+</table>
+
+<para>Note that these override the <link
+linkend=generic>generic-event</link> handlers.  For example, if you
+were to type</para>
+
+<programlisting>
+sgml('&amp;FOO;', sub {
+    output "Found a \"foo\" entity!\n";
+});
+
+sgml('entity', sub {
+    output "Found an entity!\n";
+});
+</programlisting>
+
+<para>And the external data entity <literal>&amp;FOO;</literal>
+appeared in your &sgml; document, &sgmlspl; would call the first
+handler rather than the second.</para>
+
+<para>Note also that start and end handlers are entirely separate
+things: if an element has a specific start handler but no specific end
+handler, the generic end handler will still be called at the end of
+the element.  To prevent this, declare a handler with an empty string:</para>
+
+<programlisting>
+sgml('&lt;/HACK&gt;', '');
+</programlisting>
+
+</sect1>
+
+
+<sect1 id=output>
+<title>Why does &sgmlspl; use <command>output</command> instead of
+<command>print</command>?</title>
+
+<para>&sgmlspl; uses a special &perl5; library &output.pm; for
+printing text.  &output.pm; exports the subroutines
+<command>output(<parameter>string</parameter>&hellip;)</command>,
+<command>push_output(<parameter>type</parameter>[,<parameter>data</parameter>])</command>,
+and <command>pop_output</command>.  The subroutine
+<command>output</command> works much like the regular &perl5; function
+<command>print</command>, except that you are not able to specify a
+file handle, and you may include multiple strings as arguments.</para>
+
+<para>When you want to write data to somewhere other than
+<symbol>STDOUT</symbol> (the default), then you use the subroutines
+<link linkend=pushoutput><command>push_output</command></link> and
+<link linkend=popoutput><command>pop_output</command></link> to set
+a new destination or to restore an old one.</para>
+
+<para>You can use the &output.pm; package in other programs by adding
+the following line:</para>
+
+<programlisting>
+use SGMLS::Output;
+</programlisting>
+
+</sect1>
+
+
+<sect1 id=pushoutput>
+<title>How do I use <command>push_output</command>?</title>
+
+<para>The subroutine
+<command>push_output(<parameter>type</parameter>[,<parameter>data</parameter>])</command>
+takes two arguments: the <parameter>type</parameter>, which is always
+required, and the <parameter>data</parameter>, which is needed for
+certain types of output.  Table <xref
+linkend=table.output.push.output> lists the different types which you
+can push onto the output stack.</para>
+
+<table id=table.output.push.output>
+<title>Types for <command>push_output</command></title>
+
+<tgroup cols=3>
+
+<thead>
+
+<row>
+<entry>Type</entry>
+<entry>Data</entry>
+<entry>Description</entry>
+</row>
+
+</thead>
+
+<tbody>
+
+<row>
+<entry><literal>'handle'</literal></entry>
+<entry>a filehandle</entry>
+<entry>Send all output to the supplied filehandle.</entry>
+</row>
+
+<row>
+<entry><literal>'file'</literal></entry>
+<entry>a filename</entry>
+<entry>Open the supplied file for writing, erasing its current
+contents (if any), and send all output to it.</entry>
+</row>
+
+<row>
+<entry><literal>'append'</literal></entry>
+<entry>a filename</entry>
+<entry>Open the supplied file for writing and append all output to its
+current contents.</entry>
+</row>
+
+<row>
+<entry><literal>'pipe'</literal></entry>
+<entry>a shell command</entry>
+<entry>Pipe all output to the supplied shell command.</entry>
+</row>
+
+<row>
+<entry><literal>'string'</literal></entry>
+<entry>a string [optional]</entry>
+<entry>Append all output to the supplied string, which will be
+returned by <command>pop_output</command>.</entry>
+</row>
+
+<row>
+<entry><literal>'nul'</literal></entry>
+<entry>[none]</entry>
+<entry>Ignore all output.</entry>
+</row>
+
+</tbody>
+</tgroup>
+</table>
+
+<para>Because the output is stack-based, you do not lose the previous
+output destination when you push a new one.  This is especially
+convenient for dealing with data in tree-structures, like &sgml; data
+&mdash; for example, you can capture the contents of sub-elements as
+strings, ignore certain types of elements, and split the output from
+one &sgml; parse into a series of sub-files.  Here are some examples:</para>
+
+<programlisting>
+push_output('string');                  # append output to an empty string
+push_output('file','/tmp/foo');         # send output to this file
+push_output('pipe','mail webmaster');   # mail output to 'webmaster' (!!)
+push_output('nul');                     # just ignore all output
+</programlisting>
+
+</sect1>
+
+
+<sect1 id=popoutput>
+<title>How do I use <command>pop_output</command>?</title>
+
+<para>When you want to restore the previous output after using <link
+linkend=pushoutput><command>push_output</command></link>, simply
+call the subroutine <command>pop_output</command>.  If the output type
+was a string, <command>pop_output</command> will return the string
+(containing all of the output); otherwise, the return value is not
+useful.</para>
+
+<para>Usually, you will want to use <command>push_output</command> in
+the start handler for an element or subdocument entity, and
+<command>pop_output</command> in the end handler.</para>
+
+</sect1>
+
+
+<sect1 id=outputex>
+<title>How about an example for <command>output</command>?</title>
+
+<para>Here is a simple example to demonstrate how <link
+linkend=output><command>output</command></link>, <link
+linkend="pushoutput"><command>push_output</command></link>, and
+<link linkend=popoutput><command>pop_output</command></link> work:</para>
+
+<programlisting>
+output "Hello, world!\n";               # (Written to STDOUT by default)
+push_output('nul');                     # Push 'nul' ahead of STDOUT
+output "Hello, again!\n";               # (Discarded)
+push_output('file','foo.out');          # Push file 'foo.out' ahead of 'nul'
+output "Hello, again!\n";               # (Written to the file 'foo.out')
+pop_output;                             # Pop 'foo.out' and revert to 'nul'
+output "Hello, again!\n";               # (Discarded)
+push_output('string');                  # Push 'string' ahead of 'nul'
+output "Hello, ";                       # (Written to the string)
+output "again!\n";                      # (Also written to the string)
+                                        # Pop the string "Hello, again!\n"
+$foo = pop_output;                      # and revert to 'nul'
+output "Hello, again!\n";               # (Discarded)
+pop_output;                             # Pop 'nul' and revert to STDOUT
+output "Hello, at last!\n";             # (Written to STDOUT)
+</programlisting>
+
+</sect1>
+
+
+<sect1 id=skel>
+<title>Is there an easier way to make specification files?</title>
+
+<para>Yes.  The script <filename>skel.pl</filename>, included in this
+package, is an &sgmlspl; specification which writes a specification
+(!!!).  To use it under Unix, try something like</para>
+
+<programlisting>
+sgmls foo.sgml | sgmlspl skel.pl > foo-spec.pl
+</programlisting>
+
+<para>(presuming that there is a copy of <filename>skel.pl</filename>
+in the current directory or in a directory searched by &perl5;) to
+generate a new, blank template named
+<filename>foo-spec.pl</filename>.</para>
+
+</sect1>
+
+
+<sect1 id=forward>
+<title>How should I handle forward references?</title>
+
+<para>Because &sgmlspl; processes the document as a linear data
+stream, from beginning to end, it is easy to refer
+<emphasis>back</emphasis> to information, but relatively difficult to
+refer <emphasis>forward</emphasis>, since you do not know what will be
+coming later in the parse.  Here are a few suggestions.</para>
+
+<para>First, you could use <link
+linkend=pushoutput><command>push_output</command></link> and
+<link linkend=popoutput><command>pop_output</command></link> to
+save up output in a large string.  When you have found the information
+which you need, you can make any necessary modifications to the string
+and print it then. This will work for relatively small chunks of a
+document, but you would not want to try it for anything larger.</para>
+
+<para>Next, you could use the <ulink
+url="../SGMLSpm/extend.html"><command>ext</command></ulink> method to
+add extra pointers, and build a parse tree of the whole document
+before processing any of it.  This method will work well for small
+documents, but large documents will place some serious stress on your
+system's memory and/or swapping.</para>
+
+<para>A more sophisticated solution, however, involves the
+<application>Refs.pm</application> module, included in this
+distribution.  In your &sgmlspl; script, include the line</para>
+
+<programlisting>
+use SGMLS::Refs.pm;
+</programlisting>
+
+<para>to activate the library.  The library will create a database
+file to keep track of references between passes, and to tell you if
+any references have changed.  For example, you might want to try
+something like this:</para>
+
+<programlisting>
+sgml('start', sub {
+  my $Refs = new SGMLS::Refs('references.refs');
+});
+sgml('end', sub {
+  $Refs->warn;
+  destroy $Refs;
+});
+</programlisting>
+
+<para>This code will create an object, $Refs, linked to a file of
+references called <filename>references.refs</filename>.  The
+<classname>SGMLS::Refs</classname> class understands the methods
+listed in table <xref linkend=table.class.refs></para>
+
+<table id=table.class.refs>
+<title>The SGMLS::Refs class</title>
+
+<tgroup cols=3>
+
+<thead>
+
+<row>
+<entry>Method</entry>
+<entry>Return Type</entry>
+<entry>Description</entry>
+</row>
+
+</thead>
+
+<tbody>
+
+<row>
+<entry><command>new</command>(<parameter>filename</parameter>,[<parameter>logfile_handle</parameter>])</entry>
+<entry><classname>SGMLS::Refs</classname></entry>
+<entry>Create a new <classname>SGMLS::Refs</classname> object.
+Arguments are the name of the hashfile and (optionally) a writable
+filehandle for logging changes.</entry>
+</row>
+
+<row>
+<entry><command>get</command>(<parameter>key</parameter>)</entry>
+<entry>string</entry>
+<entry>Look up a reference key in the hash file and return its value.</entry>
+</row>
+
+<row>
+<entry><command>put</command>(<parameter>key</parameter>,<parameter>value</parameter>)</entry>
+<entry>[none]</entry>
+<entry>Set a new value for the key in the hashfile.</entry>
+</row>
+
+<row>
+<entry><command>count</command></entry>
+<entry>number</entry>
+<entry>Return the number of references whose values have changed (thus
+far).</entry>
+</row>
+
+<row>
+<entry><command>warn</command></entry>
+<entry>1 or 0</entry>
+<entry>Print a warning mentioning the number of references which have
+changed, and return 1 if a warning was printed.</entry>
+</row>
+
+</tbody>
+</tgroup>
+</table>
+
+</sect1>
+
+
+<sect1 id=bugs>
+<title>Are there any bugs?</title>
+
+<para>Any bugs in &sgmls.pm; will be here too, since &sgmlspl; relies
+heavily on that &perl5; library.</para>
+
+</sect1>
+
+</article>
+
+<!-- Keep this comment at the end of the file
+Local variables:
+mode: sgml
+sgml-declaration:"/usr/local/lib/sgml/sgmldecl/docbook.dcl"
+End:
+-->
diff --git a/DOC/sgmlspm.sgml b/DOC/sgmlspm.sgml
new file mode 100644 (file)
index 0000000..cc61533
--- /dev/null
@@ -0,0 +1,883 @@
+<!DOCTYPE article PUBLIC "-//HaL and O'Reilly//DTD DocBook//EN" [
+  <!ENTITY % ISOpub PUBLIC "ISO 8879:1986//ENTITIES Publishing//EN">
+  %ISOpub;
+  <!ENTITY % ISOnum PUBLIC 
+    "ISO 8879:1986//ENTITIES Numeric and Special Graphic//EN">
+  %ISOnum;
+
+  <!ENTITY sample.program SYSTEM "sample.pl" CDATA linespecific>
+
+  <!ENTITY sgml "<ulink url='http://www.sil.org/sgml/sgml.html'><acronym>SGML</acronym></ulink>">
+  <!ENTITY esis "<acronym>ESIS</acronym>">
+  <!ENTITY sgmls.pm "<link linkend=SGMLSpm><application>SGMLS.pm</application></link>">
+  <!ENTITY perl5 "<ulink url='http://www.metronet.com/0/perlinfo/perl5/manual/perl.html'><application>perl5</application></ulink>">
+  <!ENTITY perl5 "<application>perl5</application>">
+  <!ENTITY sgmls "<application>sgmls</application>">
+  <!ENTITY nsgmls "<ulink url='http://www.jclark.com/sp.html'><application>nsgmls</application></ulink>">
+]>
+
+<article id=SGMLSpm>
+
+<artheader>
+
+<title>SGMLS.pm: a perl5 class library for handling output from the
+SGMLS and NSGMLS parsers (version 1.03)</title>
+
+<authorgroup>
+<author>
+<firstname>David</firstname>
+<surname>Megginson</surname>
+<affiliation>
+<orgname>University of Ottawa</orgname>
+<orgdiv>Department of English</orgdiv>
+<address><email>dmeggins@aix1.uottawa.ca</email></address>
+</affiliation>
+</author>
+</authorgroup>
+
+<artpagenums>[unpublished]</artpagenums>
+
+</artheader>
+
+<para>Welcome to &sgmls.pm;, an extensible &perl5; class library for
+processing the output from the &sgmls; and &nsgmls; parsers.
+&sgmls.pm; is free, copyrighted software available by anonymous ftp in
+the directory <ulink
+url="ftp://aix1.uottawa.ca/pub/dmeggins/">ftp://aix1.uottawa.ca/pub/dmeggins/</ulink>.
+You might also want to look at the documentation for <ulink
+url="../sgmlspl/sgmlspl.html"><application>sgmlspl</application></ulink>,
+a simple sample script which uses &sgmls.pm; to convert documents from
+&sgml; to other formats.</para>
+
+<important id=terms>
+<title>Terms</title>
+
+<para>This program, along with its documentation, 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 2 of the License, or (at your option) any later
+version.</para>
+
+<para>This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.</para>
+
+<para>You should have received a copy of the GNU General Public
+License along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.</para>
+
+</important>
+
+
+<sect1 id=definition>
+<title>What is &sgmls.pm;?</title>
+
+<para>&sgmls.pm; is an <link linkend=extend>extensible</link> &perl5;
+class library for parsing the output from James Clark's popular
+&sgmls; and &nsgmls; parsers, available on the Internet at <ulink
+url="ftp://jclark.com/"><filename>ftp://jclark.com</filename></ulink>.
+This is <emphasis>not</emphasis> a complete system for translating
+documents written the the <glossterm>Standard Generalised Markup
+Language</glossterm> (&sgml;) into other formats, but it can easily
+form the basis of such a system (for a simple example, see the <ulink
+url="../sgmlspl/sgmlspl.html"><application>sgmlspl</application></ulink>
+program included in this package).</para>
+
+<para>The library recognises four basic types of &sgml; objects: the
+<link linkend=sgmlselement><glossterm>element</glossterm></link>, the
+<link linkend=sgmlsattribute><glossterm>attribute</glossterm></link>,
+the <link
+linkend=sgmlsnotation><glossterm>notation</glossterm></link>, and the
+<link linkend=sgmlsentity><glossterm>entity</glossterm></link>; each
+of these is a fully-developed class with methods for accessing
+important information.</para>
+
+</sect1>
+
+
+<sect1 id=sgml>
+<title>How do I produce &sgml; documents?</title>
+
+<para>I am presuming here that you are already experienced with &sgml;
+and the &sgmls; or &nsgmls; parser.  For help with the parsers see the
+manual pages accompanying each one; for help with &sgml; see Robin
+Cover's SGML Web Page at <ulink
+url="http://www.sil.org/sgml/sgml.html"><filename>http://www.sil.org/sgml/sgml.html</filename></ulink>
+on the Internet.</para>
+
+</sect1>
+
+
+<sect1 id=perl5>
+<title>How do I program in &perl5;?</title>
+
+<para>If you have to ask this question, you probably should not be
+trying to use this library right now, since it is intended only for
+experienced &perl5; programmers.  That said, however, you can find the
+&perl5; documentation with the &perl5; source distribution or on the
+World-Wide Web at <ulink
+url="http://www.metronet.com/0/perlinfo/perl5/manual/perl.html"><filename>http://www.metronet.com/0/perlinfo/perl5/manual/perl.html</filename></ulink>.</para>
+
+<para><emphasis>Please</emphasis> do not write to me for help on using
+&perl5;.</para>
+
+</sect1>
+
+<sect1 id=sgmls>
+<title>How do I use &sgmls.pm;?</title>
+
+<para>First, you need to copy the file &sgmls.pm; to a directory where
+perl can find it (on a Unix system, it might be
+<filename>/usr/lib/perl5</filename> or
+<filename>/usr/local/lib/perl5</filename>, or whatever the environment
+variable <symbol>PERL5LIB</symbol> is set to) and make certain that it
+is world-readable.</para>
+
+<para>Next, near the top of your &perl5; program, type the following
+line:</para>
+
+<programlisting>
+use SGMLS;
+</programlisting>
+
+<para>You must then open up a file handle from which &sgmls.pm; can read the
+data from an &sgmls; or &nsgmls; process, unless you are reading from
+a standard handle like <symbol>STDIN</symbol> &mdash; for example,
+if you are piping the output from &sgmls; to a &perl5; script, using
+something like</para>
+
+<programlisting>
+sgmls foo.sgml | perl myscript.pl
+</programlisting>
+
+<para>then the predefined filehandle <symbol>STDIN</symbol> will be
+sufficient.  In DOS, you might want to dump the sgmls output to a file
+and use it as standard input (or open it explicitly in perl), and in
+Unix, you might actually want to open a pipe or socket for the input.
+&sgmls.pm; doesn't need to seek, so any input stream should
+work.</para>
+
+<para>To parse the &sgmls; or &nsgmls; output from the handle, create
+a new object instance of the <classname>SGMLS</classname> class with
+the handle as an argument, i.e.</para>
+
+<programlisting>
+$parse = new SGMLS(STDIN);
+</programlisting>
+
+<para>(You may create more than one <classname>SGMLS</classname>
+object at once, but each object <emphasis>must</emphasis> have a
+unique handle pointing to a unique stream, or
+<emphasis>chaos</emphasis> will result.)  Now, you can retrieve and
+process events using the <command>next_event</command> method:</para>
+
+<programlisting>
+while ($event = $parse->next_event) {
+    #do something with each event
+}
+</programlisting>
+
+</sect1>
+
+
+<sect1 id=sgmlsevent>
+<title>So what do I do with an event?</title>
+
+<para>The <command>next_event</command> method for the <link
+linkend=sgmls><classname>SGMLS</classname></link> class returns an
+object belonging to the class <classname>SGMLS_Event</classname>.
+This class has several methods available, as listed in table <xref
+linkend=table.class.sgmls>.</para>
+
+<table id=table.class.sgmls>
+<title>The <classname>SGMLS_Event</classname> class</title>
+
+<tgroup cols=3>
+
+<thead>
+
+<row>
+<entry>Method</entry>
+<entry>Return Type</entry>
+<entry>Description</entry>
+</row>
+
+</thead>
+
+<tbody>
+
+<row>
+<entry><command>type</command></entry>
+<entry>string</entry>
+<entry>Return the type of the event.</entry>
+</row>
+
+<row>
+<entry><command>data</command></entry>
+<entry>string, <classname>SGMLS_Element</classname>, or
+<classname>SGMLS_Entity</classname></entry>
+<entry>Return any data associated with the event.</entry>
+</row>
+
+<row>
+<entry><command>file</command></entry>
+<entry>string</entry>
+<entry>Return the name of the &sgml; source file which generated the
+event, if available.</entry>
+</row>
+
+<row>
+<entry><command>line</command></entry>
+<entry>string</entry>
+<entry>Return the line number of the &sgml; source file which
+generated the event, if available.</entry>
+</row>
+
+<row>
+<entry><command>element</command></entry>
+<entry><classname>SGMLS_Element</classname></entry>
+<entry>Return the element in force when the  event was
+generated.</entry>
+</row>
+
+<row>
+<entry><command>parse</command></entry>
+<entry>Return the <classname>SGMLS</classname> object for the current
+parse.</entry>
+</row>
+
+<row>
+<entry><command>entity(<parameter>ename</parameter>)</command></entry>
+<entry>Look up an entity from those currently known to the parse.  An
+alias for <literal>->parse->entity($ename)</literal></entry>
+</row>
+
+<row>
+<entry><command>notation(<parameter>nname</parameter>)</command></entry>
+<entry>Look up the notation from those currently known to the parse:
+an alias for <literal>->parse->notation($nname)</literal>.</entry>
+</row>
+
+</tbody>
+</tgroup>
+</table>
+
+<para>The <command>file</command> and <command>line</command> methods
+will return useful information only if you called &sgmls; or &nsgmls;
+with the <parameter>-l</parameter> flag to include file and
+line-number information.</para>
+
+</sect1>
+
+
+<sect1 id=events>
+<title>What are the different event types and data?</title>
+
+<para>Table <xref linkend=table.class.sgmls.event> lists the ten
+different event types returned by the <command>next_event</command>
+method of an <link linkend=sgmls><classname>SGMLS</classname></link>
+object and the different types of data associated with each of these
+(note that these do <emphasis>not</emphasis> correspond to the
+standard &esis; events).</para>
+
+
+<table id=table.class.sgmls.event>
+<title>The <classname>SGMLS_Event</classname> types</title>
+
+<tgroup cols=3>
+
+<thead>
+
+<row>
+<entry>Event Type</entry>
+<entry>Event Data</entry>
+<entry>Description</entry>
+</row>
+
+</thead>
+
+
+<tbody>
+
+<row>
+<entry><returnvalue>'start_element'</returnvalue></entry>
+<entry><classname>SGMLS_Element</classname></entry>
+<entry>The beginning of an element.</entry>
+</row>
+
+<row>
+<entry><returnvalue>'end_element'</returnvalue></entry>
+<entry><classname>SGMLS_Element</classname></entry>
+<entry>The end of an element.</entry>
+</row>
+
+<row>
+<entry><returnvalue>'cdata'</returnvalue></entry>
+<entry>string</entry>
+<entry>Regular character data.</entry>
+</row>
+
+<row>
+<entry><returnvalue>'sdata'</returnvalue></entry>
+<entry>string</entry>
+<entry>Special system data.</entry>
+</row>
+
+<row>
+<entry><returnvalue>'re'</returnvalue></entry>
+<entry>[none]</entry>
+<entry>A record-end (i.e., a newline).</entry>
+</row>
+
+<row>
+<entry><returnvalue>'pi'</returnvalue></entry>
+<entry>string</entry>
+<entry>A processing instruction</entry>
+</row>
+
+<row>
+<entry><returnvalue>'entity'</returnvalue></entry>
+<entry><classname>SGMLS_Entity</classname></entry>
+<entry>A non-SGML external entity.</entry>
+</row>
+
+<row>
+<entry><returnvalue>'start_subdoc'</returnvalue></entry>
+<entry><classname>SGMLS_Entity</classname></entry>
+<entry>The beginning of an SGML subdocument.</entry>
+</row>
+
+<row>
+<entry><returnvalue>'end_subdoc'</returnvalue></entry>
+<entry><classname>SGMLS_Entity</classname></entry>
+<entry>The end of an SGML subdocument.</entry>
+</row>
+
+<row>
+<entry><returnvalue>'conforming'</returnvalue></entry>
+<entry>[none]</entry>
+<entry>The document was valid.</entry>
+</row>
+
+</tbody>
+</tgroup>
+</table>
+
+<para>For example, if <literal>$event->type</literal> returns
+<returnvalue>'start_element'</returnvalue>, then
+<literal>$event->data</literal> will return an object belonging to the
+<link linkend=sgmlselement><classname>SGMLS_Element</classname></link>
+class (which will contain a list of attributes, etc. &mdash; see
+below), <literal>$event->file</literal> and
+<literal>$event->line</literal> will return the file and line-number
+in which the element appeared (if you called &sgmls; or &nsgmls; with
+the <parameter>-l</parameter> flag), and
+<literal>$event->element</literal> will return the element currently
+in force (in this case, the same as
+<literal>$event->data</literal>).</para>
+
+</sect1>
+
+
+<sect1 id=sgmlselement>
+<title>What do I do with an <classname>SGMLS_Element</classname>?</title>
+
+<para>Altogether, there are six classes in &sgmls.pm;, each with its
+own methods: in addition to <link
+linkend=sgmls><classname>SGMLS</classname></link> (for the parse) and
+<link linkend=sgmlsevent><classname>SGMLS_Event</classname></link>
+(for a specific event), the classes are
+<classname>SGMLS_Element</classname>, <link
+linkend=sgmlsattribute><classname>SGMLS_Attribute</classname></link>,
+<link linkend=sgmlsentity><classname>SGMLS_Entity</classname></link>,
+and <link
+linkend=sgmlsnotation><classname>SGMLS_Notation</classname></link>.
+Like all of these, <classname>SGMLS_Element</classname> has a number
+of methods available for obtaining different types of information.
+For example, if you were to use</para>
+
+<programlisting>
+my $element = $event->data
+</programlisting>
+
+<para>to retrieve the data for a <literal>'start_element'</literal> or
+<literal>'end_element'</literal> event, then you could use the methods
+listed in table <xref linkend=table.class.sgmls.element> to find more
+information about the element.</para>
+
+<table id=table.class.sgmls.element>
+<title>The <classname>SGMLS_Element</classname> class</title>
+
+<tgroup cols=3>
+
+<thead>
+
+<row>
+<entry>Method</entry>
+<entry>Return Type</entry>
+<entry>Description</entry>
+</row>
+
+</thead>
+
+<tbody>
+
+<row>
+<entry><command>name</command></entry>
+<entry>string</entry>
+<entry>The name (or GI), in upper-case.</entry>
+</row>
+
+<row>
+<entry><command>parent</command></entry>
+<entry><classname>SGMLS_Element</classname></entry>
+<entry>The parent element, or <literal>''</literal> if this is the top
+element.</entry>
+</row>
+
+<row>
+<entry><command>attributes</command></entry>
+<entry>HASH</entry>
+<entry>Return a reference to a hash table of
+<classname>SGMLS_Attribute</classname> objects, keyed by the attribute
+names (in upper-case).</entry>
+</row>
+
+<row>
+<entry><command>attribute_names</command></entry>
+<entry>ARRAY</entry>
+<entry>A list of all attribute names for the current element (in
+upper-case).</entry>
+</row>
+
+<row>
+<entry><command>attribute(<parameter>aname</parameter>)</command></entry>
+<entry><classname>SGMLS_Attribute</classname></entry>
+<entry>Return the attribute named ANAME.</entry>
+</row>
+
+<row>
+<entry><command>set_attribute(<parameter>attribute</parameter>)</command></entry>
+<entry>[none]</entry>
+<entry>The <parameter>attribute</parameter> argument should be an
+object belonging to the <ulink
+url=sgmlsattribute.html><classname>SGMLS_Attribute</classname></ulink>
+class.  Add it to the element, replacing any previous attribute with
+the same name.</entry>
+</row>
+
+<row>
+<entry><command>in(<parameter>name</parameter>)</command></entry>
+<entry><classname>SGMLS_Element</classname></entry>
+<entry>If the current element's parent is named
+<parameter>name</parameter>, return the parent; otherwise, return
+<literal>''</literal>.</entry>
+</row>
+
+<row>
+<entry><command>within(<parameter>name</parameter>)</command></entry>
+<entry><classname>SGMLS_Element</classname></entry>
+<entry>If any ancestor of the current element is named
+<parameter>name</parameter>, return it; otherwise, return
+<literal>''</literal>.</entry>
+</row>
+
+</tbody>
+</tgroup>
+</table>
+
+</sect1>
+
+
+<sect1 id=sgmlsattribute>
+<title>What do I do with an
+<classname>SGMLS_Attribute</classname>?</title>
+
+<para>Note that objects of the <classname>SGMLS_Attribute</classname>
+class do not have events in their own right, and are available only
+through the <command>attributes</command> or
+<command>attribute(<parameter>aname</parameter>)</command> methods for
+<link linkend=sgmlselement><classname>SGMLS_Element</classname></link>
+objects.  An object belonging to the
+<classname>SGMLS_Attribute</classname> class will recognise the
+methods listed in table <xref
+linkend=table.class.sgmls.attribute>.</para>
+
+<table id=table.class.sgmls.attribute>
+<title>The <classname>SGMLS_Attribute</classname> class</title>
+
+<tgroup cols=3>
+
+<thead>
+
+<row>
+<entry>Method</entry>
+<entry>Return Type</entry>
+<entry>Description</entry>
+</row>
+
+</thead>
+
+<tbody>
+
+<row>
+<entry><command>name</command></entry>
+<entry>string</entry>
+<entry>The name of the attribute (in upper-case).</entry>
+</row>
+
+<row>
+<entry><command>type</command></entry>
+<entry>string</entry>
+<entry>The type of the attribute: <literal>'IMPLIED'</literal>,
+<literal>'CDATA'</literal>, <literal>'NOTATION'</literal>,
+<literal>'ENTITY'</literal>, or <literal>'TOKEN'</literal>.</entry>
+</row>
+
+<row>
+<entry><command>value</command></entry>
+<entry>string, <classname>SGMLS_Entity</classname>, or
+<classname>SGMLS_Notation</classname>.</entry>
+<entry>The value of the attribute.  If the type is
+<literal>'CDATA'</literal> or <literal>'TOKEN'</literal>, it will be a
+simple string; if it is <literal>'NOTATION'</literal> it will be an
+object belonging to the <classname>SGMLS_Notation</classname> class,
+and if it is <literal>'Entity'</literal> it will be an object
+belonging to the <classname>SGMLS_Entity</classname> class.</entry>
+</row>
+
+<row>
+<entry><command>is_implied</command></entry>
+<entry>boolean</entry>
+<entry>Return true if the value of the attribute is implied, or false if
+it has an explicit value.</entry>
+</row>
+
+<row>
+<entry><command>set_type(<parameter>type</parameter>)</command></entry>
+<entry>[none]</entry>
+<entry>Provide a new type for the current attribute -- no sanity
+checking will be performed, so be careful.</entry>
+</row>
+
+<row>
+<entry><command>set_value(<parameter>value</parameter>)</command></entry>
+<entry>[none]</entry>
+<entry>Provide a new value for the current attribute -- no sanity
+checking will be performed, so be careful.</entry>
+</row>
+
+</tbody>
+</tgroup>
+</table>
+
+<para>Note that the type <literal>'TOKEN'</literal> includes both
+individual tokens and lists of tokens (ie <literal>'TOKENS'</literal>,
+<literal>'IDS'</literal>, or <literal>'IDREFS'</literal> in the
+original &sgml; document), so you might need to use the perl function
+'split' to break the value string into a list.</para>
+
+</sect1>
+
+
+<sect1 id=sgmlsentity>
+<title>What do I do with an <classname>SGMLS_Entity</classname>?</title>
+
+<para>An <classname>SGMLS_Entity</classname> object can come in an
+<literal>'entity'</literal> <link linkend=events>event</link> (in
+which case it is always external), in a
+<literal>'start_subdoc'</literal> or <literal>'end_subdoc'</literal>
+event (in which case it always has the type
+<literal>'SUBDOC'</literal>), or as the value of an attribute (in
+which case it may be internal or external).  An object belonging to
+the <classname>SGMLS_Entity</classname> class may use the methods
+listed in table <xref linkend=table.class.sgmls.entity>.</para>
+
+<table id=table.class.sgmls.entity>
+<title>The <classname>SGMLS_Entity</classname> class</title>
+
+<tgroup cols=3>
+
+<thead>
+
+<row>
+<entry>Method</entry>
+<entry>Return Type</entry>
+<entry>Description</entry>
+</row>
+
+</thead>
+
+<tbody>
+
+<row>
+<entry><command>name</command></entry>
+<entry>string</entry>
+<entry>The entity name.</entry>
+</row>
+
+<row>
+<entry><command>type</command></entry>
+<entry>string</entry>
+<entry>The entity type: <literal>'CDATA'</literal>,
+<literal>'SDATA'</literal>, <literal>'NDATA'</literal>, or
+<literal>'SUBDOC'</literal>.</entry>
+</row>
+
+<row>
+<entry><command>value</command></entry>
+<entry>string</entry>
+<entry>The entity replacement text (internal entities
+only).</entry>
+</row>
+
+<row>
+<entry><command>sysid</command></entry>
+<entry>string</entry>
+<entry>The system identifier (external entities only).</entry>
+</row>
+
+<row>
+<entry><command>pubid</command></entry>
+<entry>string</entry>
+<entry>The public identifier (external entities only).</entry>
+</row>
+
+<row>
+<entry><command>filenames</command></entry>
+<entry>ARRAY</entry>
+<entry>A list of file names generated from the sysid and pubid
+(external entities only).</entry>
+</row>
+
+<row>
+<entry><command>notation</command></entry>
+<entry><classname>SGMLS_Notation</classname></entry>
+<entry>The associated notation (external data entities only).</entry>
+</row>
+
+</tbody>
+</tgroup>
+</table>
+
+<para>An entity of type <literal>'SUBDOC'</literal> will have a sysid
+and pubid, and external data entity will have a sysid, pubid,
+filenames, and a notation, and an internal data entity will have a
+value.</para>
+
+</sect1>
+
+
+<sect1 id=sgmlsnotation>
+<title>What do I do with an <classname>SGMLS_Notation</classname>?</title>
+
+<para>The fourth data class is the notation, which is available only
+as a return value from the <command>notation</command> method of an
+<link linkend=sgmlsentity><classname>SGMLS_Entity</classname></link>
+or the <command>value</command> method of an <link
+linkend=sgmlsattribute><classname>SGMLS_Attribute</classname></link>
+with type <literal>'NOTATION'</literal>.  You can use the notation to
+decide how to treat non-SGML data (such as graphics).  An object
+belonging to the <classname>SGMLS_Notation</classname> class will have
+access to the methods listed in table <xref
+linkend=table.class.sgmls.notation>.</para>
+
+<table id=table.class.sgmls.notation>
+<title>The <classname>SGMLS_Notation class</classname></title>
+
+<tgroup cols=3>
+
+<thead>
+
+<row>
+<entry>Method</entry>
+<entry>Return Type</entry>
+<entry>Description</entry>
+</row>
+
+</thead>
+
+<tbody>
+
+<row>
+<entry><command>name</command></entry>
+<entry>string</entry>
+<entry>The notation's name.</entry>
+</row>
+
+<row>
+<entry><command>sysid</command></entry>
+<entry>string</entry>
+<entry>The notation's system identifier.</entry>
+</row>
+
+<row>
+<entry><command>pubid</command></entry>
+<entry>string</entry>
+<entry>The notation's public identifier.</entry>
+</row>
+
+</tbody>
+</tgroup>
+</table>
+
+<para>What you do with this information is
+<emphasis>entirely</emphasis> up to you.</para>
+
+</sect1>
+
+
+<sect1 id=xtrainfo>
+<title>Is there any extra information available from the &sgml;
+document?</title>
+
+<para>The <link linkend=sgmls><classname>SGMLS</classname></link>
+object which you created at the beginning of the parse has several
+methods available in addition to <command>next_event</command> &mdash;
+you will find them all listed in table <xref
+linkend=table.class.sgmls.extra>.  There should normally be no need to
+use the <command>notation</command> and <command>entity</command>
+methods, since &sgmls.pm; will look up entities and notations for you
+automatically as needed.</para>
+
+<table id=table.class.sgmls.extra>
+<title>Additional methods for the <classname>SGMLS</classname>
+class</title>
+<tgroup cols=3>
+
+<thead>
+
+<row role=label>
+<entry>Method</entry>
+<entry>Return Type</entry>
+<entry>Description</entry>
+</row>
+
+</thead>
+
+<tbody>
+
+<row>
+<entry><command>next_event</command></entry>
+<entry><classname>SGMLS_Event</classname></entry>
+<entry>Return the next event.</entry>
+</row>
+
+<row>
+<entry><command>appinfo</command></entry>
+<entry>string</entry>
+<entry>Return the APPINFO parameter from the &sgml; declaration, if
+any.</entry>
+</row>
+
+<row>
+<entry><command>notation(<parameter>nname</parameter>)</command></entry>
+<entry><classname>SGMLS_Notation</classname></entry>
+<entry>Look up a notation by name.</entry>
+</row>
+
+<row>
+<entry><command>entity(<parameter>ename</parameter>)</command></entry>
+<entry><classname>SGMLS_Entity</classname></entry>
+<entry>Look up an entity by name.</entry>
+</row>
+
+</tbody>
+</tgroup>
+</table>
+
+</sect1>
+
+
+<sect1 id=example>
+<title>How about a simple example?</title>
+
+<para>OK.  The following script simply reports its events:</para>
+
+<programlisting>
+&sample.program;
+</programlisting>
+
+<para>To use it under Unix, try something like</para>
+
+<programlisting>
+sgmls document.sgml | perl sample.pl
+</programlisting>
+
+<para>and watch the output scroll down.</para>
+
+</sect1>
+
+
+<sect1 id=extend>
+<title>How do I design my <emphasis>own</emphasis> classes?</title>
+
+<para>In addition to the methods listed above, all of the classes used
+in &sgmls.pm; have an <command>ext</command> method which returns a
+reference to an initially-empty hash table.  You are free to use this
+hash table to store <emphasis>anything</emphasis> you want &mdash; it
+should be especially useful if you are building your own, derived
+classes from the ones provided here.  The following example builds a
+derived class <classname>My_Element</classname> from the <link
+linkend=sgmlselement><classname>SGMLS_Element</classname></link>
+class, adding methods to set and get the current font:</para>
+
+<programlisting>
+use SGMLS;
+
+package My_Element;
+@ISA = qw(SGMLS_Element);
+
+sub new {
+  my ($class,$element,$font) = @_;
+  $element->ext->{'font'} = $font;
+  return bless $element;
+}
+
+sub get_font {
+  my ($self) = @_;
+  return $self->ext->{'font'};
+}
+
+sub set_font {
+  my ($self,$font) = @_;
+  $self->ext->{'font'} = $font;
+}
+</programlisting>
+
+<para>Note that the derived class does not need to have any knowledge
+about the underlying structure of the <link
+linkend=sgmlselement><classname>SGMLS_Element</classname></link>
+class, and need only avoid shadowing any of the methods currently
+existing there.</para>
+
+<para>If you decide to create a derived class from the <link
+linkend=sgmls><classname>SGMLS</classname></link>, please note that in
+addition to the methods listed above, that class uses internal methods
+named <command>element</command>, <command>line</command>, and
+<command>file</command>, similar to the same methods in <link
+linkend=sgmlsevent><classname>SGMLS_Event</classname></link> &mdash;
+it is essential that you not shadow these method names.</para>
+
+</sect1>
+
+
+<sect1 id=bugs>
+<title>Are there any bugs?</title>
+
+<para>Of course!  Right now, &sgmls.pm; silently ignores link attributes
+(&nsgmls; only) and data attributes, and there may be many other bugs
+which I have not yet found.</para>
+
+</sect1>
+
+</article>
+
+<!-- Keep this comment at the end of the file
+Local variables:
+mode: sgml
+sgml-declaration:"/usr/local/lib/sgml/sgmldecl/docbook.dcl"
+End:
+-->
diff --git a/DOC/tohtml.pl b/DOC/tohtml.pl
new file mode 100644 (file)
index 0000000..399167b
--- /dev/null
@@ -0,0 +1,569 @@
+########################################################################
+# SGMLSPL script to convert from the DocBook DTD to HTML pages.
+#
+# by David Megginson <dmeggins@aix1.uottawa.ca>
+#
+# This is a slightly more complicated script than tolatex.pl, since it
+# uses forward references and an external reference file.  Note that
+# this script is customised for the SGMLS.pm and sgmlspl documentation
+# in this directory, and is not meant as a general-purpose
+# DocBook->HTML translator (though it could form the basis of one).
+# Because each parse uses information saved from the last parse,
+# you might need two passes to make certain that all references are
+# up to date.
+#
+# $Log: tohtml.pl,v $
+# Revision 1.4  1995/12/03  22:07:21  david
+# Changed to use SGMLS::Output instead of Output, and to take advantage
+# of the SGMLS::Refs package for forward references.
+#
+# Revision 1.3  1995/08/12  16:25:53  david
+# Oops! Fixed comment leader in RCS file.
+#
+# Revision 1.2  1995/08/12  16:21:06  david
+# Changes for release 1.01: fixed handling of prefixed sysid's from
+# NSGMLS.
+#
+########################################################################
+
+use SGMLS;                     # Use the SGMLS package.
+use SGMLS::Output;             # Use stack-based output.
+use SGMLS::Refs;
+
+$version = '$Id: tohtml.pl,v 1.4 1995/12/03 22:07:21 david Exp $';
+
+$basename = shift;             # Extra argument to script is basename.
+
+#
+# This conversion script keeps the idea of a current ID and a current
+# file.  Since the SGML document will be broken up into a series of
+# smaller HTML documents, it is necessary to keep track of the current
+# file name.  The current ID is the ID (explicit or implied) of the
+# most recent element which wants to capture titles, etc.
+#
+$current_id = '';              # The ID of the current container element.
+@current_id_stack = ();                # The IDs of any parent container elements.
+$current_file = '';            # The name of the current output file.
+@current_file_stack = ();      # The names of the parent output files.
+
+$top_id = '';                  # The ID of the top element.
+$top_file = '';                        # The ID of the top file.
+
+$previous_file = '';           # The previous file on the same level.
+
+$table_counter = 0;            # The number of the current table.
+
+
+
+\f
+########################################################################
+# Handler declarations for sgmlspl.
+########################################################################
+
+#
+# Use the 'start' and 'end' handlers of the document to begin and
+# terminate reference handling.
+#
+sgml('start', sub { 
+    system("touch .redo_$basename");
+                                # Start up the reference manager.
+    $Refs = new SGMLS::Refs("$basename.refs");
+});
+sgml('end', sub {
+    unlink(".redo_$basename") unless $Refs->warn;
+});
+
+
+# 
+# The <ARTICLE> is the top-level element.
+#
+sgml('<ARTICLE>', sub {
+    start_html(shift);
+    $top_id = $current_id;
+    $top_file = $current_file;
+});
+sgml('</ARTICLE>', sub { end_html(); });
+
+#
+# Ignore all of the header except for the bits which we actually want,
+# by pushing output to 'nul'.
+#
+sgml('<ARTHEADER>', sub { push_output 'nul'; });
+sgml('</ARTHEADER>', sub { pop_output(); });
+
+#
+# Save the title of something for future reference.
+#
+sgml('<TITLE>', sub { push_output 'string'; });
+sgml('</TITLE>', sub { $Refs->put("title:$current_id",pop_output()); });
+
+#
+# These are just containers in the <ARTHEADER>.
+#
+sgml('<AUTHORGROUP>', "");
+sgml('</AUTHORGROUP>', "");
+sgml('<AUTHOR>', "");
+sgml('</AUTHOR>', "");
+sgml('<AFFILIATION>', "");
+sgml('</AFFILIATION>', "");
+sgml('<ADDRESS>', "");
+sgml('</ADDRESS>', "");
+sgml('<ARTPAGENUMS>', "");
+sgml('</ARTPAGENUMS>', "");
+
+#
+# Save the author's first name for future reference.
+#
+sgml('<FIRSTNAME>', sub { push_output 'string'; });
+sgml('</FIRSTNAME>', sub { $Refs->put("firstname:$current_id",pop_output()); });
+
+#
+# Save the author's surname for future reference.
+#
+sgml('<SURNAME>', sub { push_output 'string'; });
+sgml('</SURNAME>', sub { $Refs->put("surname:$current_id",pop_output()); });
+
+#
+# Save the organisation name for future reference.
+#
+sgml('<ORGNAME>', sub { push_output 'string'; });
+sgml('</ORGNAME>', sub { $Refs->put("orgname:$current_id",pop_output()); });
+
+#
+# Save the organisation division for future reference.
+#
+sgml('<ORGDIV>', sub { push_output 'string'; });
+sgml('</ORGDIV>', sub { $Refs->put("orgdiv:$current_id",pop_output()); });
+
+#
+# Save the email address for future reference.
+#
+sgml('<EMAIL>', sub { push_output('string'); });
+sgml('</EMAIL>', sub { $Refs->put("email:$current_id",pop_output()); });
+
+
+
+#
+# Sectioning elements -- all of these simply call the &start_html
+# and &end_html subroutines, which do all of the real work.
+#
+sgml('<IMPORTANT>', sub { start_html(shift); });
+sgml('</IMPORTANT>', sub { end_html(); });
+sgml('<SECT1>', sub { start_html(shift); });
+sgml('</SECT1>', sub { end_html(); });
+sgml('<SECT2>', sub { start_html(shift); });
+sgml('</SECT2>', sub { end_html(); });
+sgml('<SECT3>', sub { start_html(shift); });
+sgml('</SECT3>', sub { end_html(); });
+sgml('<SECT4>', sub { start_html(shift); });
+sgml('</SECT4>', sub { end_html(); });
+sgml('<SECT5>', sub { start_html(shift); });
+sgml('</SECT5>', sub { end_html(); });
+
+
+#
+# Paragraphs must be marked explicitly in HTML -- use the HTML 3
+# practice (actually just _real_ SGML, for a change) of marking both
+# the beginning and the end.
+#
+sgml('<PARA>', "<P>");
+sgml('</PARA>', "</P>\n\n");
+
+
+
+
+#
+# Cross-references.
+#
+
+#
+# This is an internal cross reference -- get the URL by
+# simply adding ".html" to the IDREF (note that this would not work
+# for tables!!!).
+#
+sgml('<LINK>', sub {
+    my $element = shift;
+    output "<A HREF=";
+    output lc($element->attribute(LINKEND)->value) . ".html";
+    output ">";
+});
+sgml('</LINK>', "</A>");
+
+#
+# This is an external cross-reference, with a supplied URL.
+#
+sgml('<ULINK>', sub {
+    my $element = shift;
+    output "<A HREF=\"";
+    output $element->attribute(URL)->value;
+    output "\">";
+});
+sgml('</ULINK>', "</A>");
+
+
+#
+# This is a pointer to something (in this case, always a table).
+#
+sgml('<XREF>', sub {
+    my $element = shift;
+    output $Refs->get('xref:' . lc($element->attribute(LINKEND)->value));
+});
+sgml('</XREF>', "");
+
+
+
+#
+# Inline elements.
+#
+
+#
+# Print application names in typewriter.
+#
+sgml('<APPLICATION>', "<TT>");
+sgml('</APPLICATION>', "</TT>");
+
+#
+# Print acronyms in bold.
+#
+sgml('<ACRONYM>', "<B>");
+sgml('</ACRONYM>', "</B>");
+
+#
+# Print terms in italics.
+#
+sgml('<GLOSSTERM>', "<I>");
+sgml('</GLOSSTERM>', "</I>");
+
+#
+# Print file names in typewriter.
+#
+sgml('<FILENAME>', "<TT>");
+sgml('</FILENAME>', "</TT>");
+
+#
+# Print symbols in typewriter.
+#
+sgml('<SYMBOL>', "<TT>");
+sgml('</SYMBOL>', "</TT>");
+
+#
+# Print return values in typewriter.
+#
+sgml('<RETURNVALUE>', "<TT>");
+sgml('</RETURNVALUE>', "</TT>");
+
+#
+# Print quotations in quotation marks.
+#
+sgml('<QUOTE>', '"');
+sgml('</QUOTE>', '"');
+
+#
+# Print commands in typewriter.
+#
+sgml('<COMMAND>', "<TT>");
+sgml('</COMMAND>', "</TT>");
+
+#
+# Print parameters in typewriter.
+#
+sgml('<PARAMETER>', "<IT>");
+sgml('</PARAMETER>', "</IT>");
+
+#
+# Print literal elements in typewriter.
+#
+sgml('<LITERAL>', "<TT>");
+sgml('</LITERAL>', "</TT>");
+
+#
+# Print class names in typewriter.
+#
+sgml('<CLASSNAME>', "<TT>");
+sgml('</CLASSNAME>', "</TT>");
+
+#
+# Emphasise emphasis.
+#
+sgml('<EMPHASIS>', "<EM>");
+sgml('</EMPHASIS>', "</EM>");
+
+
+
+#
+# Block elements.
+#
+
+#
+# Program listings are preformatted.
+#
+sgml('<PROGRAMLISTING>', "<P>\n<PRE>");
+sgml('</PROGRAMLISTING>', "</PRE>\n</P>\n");
+
+#
+# Keep a counter for table numbers, note the ID, and look up the
+# title (caption) for the table.
+#
+sgml('<TABLE>', sub {
+    my $element = shift;
+    push @current_id_stack, $current_id;
+    $current_id = lc($element->attribute(ID)->value || gen_id());
+    $table_counter++;
+    $Refs->put("xref:$current_id",$table_counter);
+    output "\n<H3>Table $table_counter: " 
+       . $Refs->get("title:$current_id") . "</H3>\n\n";
+});
+sgml('</TABLE>', sub {
+    output "\n";
+    $current_id = pop @current_id_stack;
+});
+
+#
+# Nothing needs to be done here -- we don't care how many cells there are.
+#
+sgml('<TGROUP>', "");
+sgml('</TGROUP>', "");
+
+#
+# We will keep track of all of the entries in the head, for later use.
+#
+sgml('<THEAD>', sub { @cell_headings = (); push_output('nul'); });
+sgml('</THEAD>', sub { pop_output(); });
+
+#
+# Print a single horizontal rule before the beginning of the body.
+#
+sgml('<TBODY>', "<HR>");
+sgml('</TBODY>', "");
+
+#
+# Make each row into a labelled list (!!) -- HTML 3 does have tables,
+# but they might not be able to handle the paragraph-length entries
+# which I used in my documentation (these will not print if we are
+# in the <THEAD>, since output will be 'nul').
+#
+sgml('<ROW>', sub { 
+    output "\n<DL>\n";
+    $cell_counter = 0;
+});
+sgml('</ROW>', "\n</DL>\n<HR>\n\n");
+
+#
+# If an entry is in the <THEAD>, save it for later use; otherwise,
+# print the entry as a list item with its corresponding <THEAD> entry
+# as a label.
+#
+sgml('<ENTRY>', sub {
+    my $element = shift;
+    if ($element->within(THEAD)) {
+       push_output 'string';
+    } else {
+       output "<DT><B>";
+       output $cell_headings[$cell_counter];
+       output "</B></DT>\n<DD>";
+    }
+});
+sgml('</ENTRY>', sub {
+    my $element = shift;
+    if ($element->within(THEAD)) {
+       $cell_headings[$cell_counter] = pop_output();
+    } else {
+       output "</DD>\n";
+    }
+    $cell_counter++;
+});
+
+
+
+########################################################################
+# SDATA Handlers -- use HTML entities wherever possible.
+########################################################################
+
+sgml('|[lt    ]|', "&lt;");
+sgml('|[gt    ]|', "&gt;");
+sgml('|[mdash ]|', "--");
+sgml('|[LaTeX]|', "LaTeX");
+sgml('|[hellip]|', "...");
+sgml('|[amp   ]|', "&amp;");
+
+
+
+########################################################################
+# The generic external data entity handler.  Handle only entities
+# with type CDATA, and simply dump their files into the current
+# document with minimal conversion.
+########################################################################
+
+sgml('entity',sub {
+    my $entity = shift;
+                               # Use the first generated filename
+                               # or the system identifier.
+    my $filename = $entity->filenames->[0] || $entity->sysid;
+                               # A strange, NSGMLS-thing.
+    if ($filename =~ /^FILE:/ || $filename =~ /^\<FILE[^>]+\>/) {
+      $filename = $';
+    }
+
+                               # Handle only CDATA.
+    if ($entity->type eq 'CDATA') {
+
+       if (-r $filename) {
+           unless (open INPUT, "<$filename") {
+               die "Cannot open external file $filename\n";
+           }
+                               # Convert special SGML characters.
+           while (<INPUT>) {
+               s/\&/\&amp;/g;
+               s/\</\&lt;/g;
+               s/\>/\&gt;/g;
+               output $_;
+           }
+           close INPUT;
+       } else {
+           die "Cannot read file $filename\n";
+       }
+    } else {
+       die "Cannot handle external entity with type " . $entity->type . "\n";
+    }
+});
+
+
+
+########################################################################
+# Default handlers -- these will pick up any unrecognised elements,
+# SDATA strings, processing instructions, or subdocument entities,
+# and report an error to the user.
+#########################################################################
+
+
+sgml('start_element',sub { die "Unknown element: " . $_[0]->name; });
+sgml('sdata',sub { die "Unknown SDATA: " . $_[0]; });
+sgml('pi',sub { die "Unknown processing instruction: " . $_[0]; });
+sgml('start_subdoc',sub { die "Unknown subdoc entity: " . $_[0]->name; });
+
+
+#
+# End of sgmlspl handler declarations.
+#
+
+\f
+########################################################################
+# Utility procedures.
+########################################################################
+
+
+#
+# Given an element, start a new HTML document for it.
+#
+sub start_html {
+    my $element = shift;
+    my $old_file = $current_file;
+
+                               # Save the old values on the stack.
+    push @current_id_stack, $current_id;
+    push @current_file_stack, $current_file;
+
+                               # Get the new ID and file.
+    $current_id = lc($element->attribute(ID)->value || gen_id());
+    $current_file = $current_id . '.html';
+
+                               # Note the previous child, if any.
+    if ($previous_file) {
+       $Refs->put("previous:$current_file",$previous_file);
+       $Refs->put("next:$previous_file",$current_file);
+    }
+    $previous_file = '';
+
+                               # Put a reference up to the parent.
+    if ($old_file) {
+       $Refs->put("up:$current_file",$old_file);
+    }
+
+                               # Look up the title reference.
+    my $plaintitle = my $title = $Refs->get("title:$current_id");
+
+                               # Strip the title.
+    $plaintitle =~ s/\<[^\>]+\>//g;
+
+                               # If this is not the top-level
+                               # file, send out a link
+                               # before beginning the new file.
+    if ($old_file) {
+       output "<LI><A HREF=\"$current_file\">$plaintitle</A></LI>\n";
+    }
+
+                               # Send output to the new file.
+    push_output('file',$current_file);
+
+                               # Print the front matter.
+    output "<HTML>\n<HEAD>\n<TITLE>$plaintitle</TITLE>\n</HEAD>\n<BODY>\n";
+
+                               # Navigational aids, if this is not
+                               # the top-level file.
+    if ($old_file) {
+       output "\n<P><B>Links</B>: ";
+       my $up = $Refs->get("up:$current_file");
+       my $previous = $Refs->get("previous:$current_file");
+       my $next = $Refs->get("next:$current_file");
+       output "<A HREF=$next>Next</A> " if $next;
+       output "<A HREF=$previous>Previous</A> " if $previous;
+       output "<A HREF=$up>Up</A> " if $up;
+       output "<A HREF=$top_file>Top</A>";
+       output "</P>\n\n";
+    }
+
+    
+    output "<H1>$title</H1>\n\n";
+}
+
+#
+# End the HTML document.
+#
+sub end_html {
+                               # Look up the name and email info.
+    my $firstname = $Refs->get("firstname:$current_id") ||
+       $Refs->get("firstname:$top_id");
+    my $surname = $Refs->get("surname:$current_id") ||
+       $Refs->get("surname:$top_id");
+    my $email = $Refs->get("email:$current_id") ||
+       $Refs->get("email:$top_id");
+
+                               # Restore the previous ID and file,
+                               # and note this as the previous
+                               # child.
+    $previous_file = $current_file;
+    $current_id = pop @current_id_stack;
+    $current_file = pop @current_file_stack;
+
+                               # If this is not the top-level file,
+                               # add some navigational information.
+    if ($current_file) {
+       output "\n<P><B>Links</B>: ";
+       my $up = $Refs->get("up:$previous_file");
+       my $previous = $Refs->get("previous:$previous_file");
+       my $next = $Refs->get("next:$previous_file");
+       output "<A HREF=$next>Next</A> " if $next;
+       output "<A HREF=$previous>Previous</A> " if $previous;
+       output "<A HREF=$up>Up</A> " if $up;
+       output "<A HREF=$top_file>Top</A>";
+       output "</P>\n\n";
+    }
+
+                               # Add an address, if available,
+                               # including a MAILTO URL.
+    output "\n<ADDRESS>";
+    output "$firstname $surname " if $firstname || $surname;
+    output "<A HREF=\"mailto:$email\">&lt;$email&gt;</A>" if $email;
+    output "</ADDRESS>\n</BODY>\n</HTML>\n";
+    pop_output();
+}
+
+#
+# Generate a new ID for anything which does not already have one.
+#
+sub gen_id {
+    $id_counter++;
+    return "node$id_counter";
+}
+
+1;
diff --git a/DOC/tolatex.pl b/DOC/tolatex.pl
new file mode 100644 (file)
index 0000000..fb25443
--- /dev/null
@@ -0,0 +1,508 @@
+########################################################################
+# SGMLSPL script to convert from the DocBook DTD to LaTeX.
+#
+# by David Megginson <dmeggins@aix1.uottawa.ca>
+#
+# This is a simple translation sample script.  Note that this
+# script is customised for the SGMLS.pm and sgmlspl documentation in
+# this directory, and is not meant as a general-purpose DocBook->LaTeX
+# translator (though it could form the basis of one).
+#
+# $Log: tolatex.pl,v $
+# Revision 1.4  1995/12/03  22:08:03  david
+# Changed to use SGMLS::Output instead of Output, and to take advantage
+# of the SGMLS::Refs package for forward references.
+#
+# Revision 1.3  1995/08/12  16:25:07  david
+# Oops! Fixed comment leader in RCS file.
+#
+# Revision 1.2  1995/08/12  16:22:17  david
+# Revised for release 1.01: fixed handling of prefixed sysid's from
+# NSGMLS.
+#
+########################################################################
+
+use SGMLS;                     # Use the SGMLS package.
+use SGMLS::Output;             # Use stack-based output.
+use SGMLS::Refs;               # Use forward-reference manager.
+
+$version = '$Id: tolatex.pl,v 1.4 1995/12/03 22:08:03 david Exp $';
+
+$basename = shift;             # We need an explicit basename to
+                               # produce different reference
+                               # files for the two documents.
+
+########################################################################
+# Document handlers, called at the beginning and end of the entire parse.
+########################################################################
+
+sgml('start', sub {
+    system("touch .redo_$basename");
+                                # Start up the reference manager.
+    $Refs = new SGMLS::Refs("$basename.refs");
+});
+sgml('end', sub {
+    unlink(".redo_$basename") unless $Refs->warn;
+});
+
+
+########################################################################
+# Specific element handlers, called at the beginning and end of each
+# corresponding element.
+########################################################################
+
+#
+# The <ARTICLE> is the top-level argument: when it starts, print the
+# beginning of the LaTeX preamble; when it ends, print the LaTeX
+# close.
+#
+sgml('<ARTICLE>', "\\documentstyle[11pt]{article}\n\n" .
+     "\\setlength{\\parskip}{3ex}\n" .
+     "\\raggedright\n\n");
+sgml('</ARTICLE>', "\\end{document}\n");
+
+#
+# The <ARTHEADER> contains bibliographical information about the
+# article.  Push output to nul so that nothing prints by default,
+# grab any relevant information into variables using the sub-elements,
+# then end the preamble and begin the actual document once the
+# header is finished.
+#
+sgml('<ARTHEADER>', sub { push_output('nul'); });
+sgml('</ARTHEADER>', sub {
+    pop_output;
+    output "\\title{$title}\n";
+    output "\\author{$firstname $surname \\\\\n";
+    output "  $orgdiv, \\\\\n" if $orgdiv;
+    output "  $orgname, \\\\\n" if $orgname;
+    output "  Email: {\\tt $email} \\\\\n" if $email;
+    output "}\n\n";
+    output "\\date{$date}\n" if $date;
+    output "\n\\begin{document}\n\\maketitle\n\n";
+});
+
+#
+# Use push_output and pop_output to save the contents of the <TITLE>
+# element.  The element's treatment is context-sensitive: inside
+# an <ARTHEADER>, save the title in the $title variable; inside <SECT1>,
+# or <IMPORTANT>, begin the new section now; inside a <TABLE>, print 
+# the caption.
+#
+sgml('<TITLE>', sub { push_output 'string'; });
+sgml('</TITLE>', sub {
+    my $element = shift;
+    my $data = pop_output;
+    if ($element->in(ARTHEADER)) {
+       $title = $data;
+    } elsif ($element->in(SECT1) || $element->in(IMPORTANT)) {
+       $Refs->put("title:$current_section",$data);
+    } elsif ($element->in(TABLE)) {
+       $Refs->put("title:$current_table",$data);
+    } else {
+       die "Do not know what to do with TITLE in "
+           . $element->parent->name . "\n";
+    }
+});
+
+# Element: AUTHORGROUP
+sgml('<AUTHORGROUP>', "");
+sgml('</AUTHORGROUP>', "");
+
+# Element: AUTHOR
+sgml('<AUTHOR>', "");
+sgml('</AUTHOR>', "");
+
+#
+# Save the contents of <FIRSTNAME> into the variable $firstname,
+# presuming that this appears only within the <ARTHEADER>.
+#
+sgml('<FIRSTNAME>', sub { push_output('string'); });
+sgml('</FIRSTNAME>', sub { $firstname = pop_output; });
+
+#
+# Save the contents of <SURNAME> into the variable $surname,
+# presuming that this appears only within the <ARTHEADER>.
+#
+sgml('<SURNAME>', sub { push_output('string'); });
+sgml('</SURNAME>', sub{ $surname = pop_output; });
+
+# Element: AFFILIATION
+sgml('<AFFILIATION>', "");
+sgml('</AFFILIATION>', "");
+
+#
+# Save the contents of <ORGNAME> into the variable $orgname,
+# presuming that this appears only within the <ARTHEADER>.
+#
+sgml('<ORGNAME>', sub { push_output('string'); });
+sgml('</ORGNAME>', sub { $orgname = pop_output; });
+
+#
+# Save the contents of <ORGDIV> into the variable $orgdiv,
+# presuming that this appears only within the <ARTHEADER>.
+#
+sgml('<ORGDIV>', sub { push_output('string'); });
+sgml('</ORGDIV>', sub { $orgdiv = pop_output; });
+
+# Element: ADDRESS
+sgml('<ADDRESS>', "");
+sgml('</ADDRESS>', "");
+
+#
+# Save the contents of <EMAIL> into the variable $email,
+# presuming that this appears only within the <ARTHEADER>.
+#
+sgml('<EMAIL>', sub { push_output('string'); });
+sgml('</EMAIL>', sub { $email = pop_output; });
+
+# Element: ARTPAGENUMS
+sgml('<ARTPAGENUMS>', "");
+sgml('</ARTPAGENUMS>', "");
+
+#
+# Print an <IMPORTANT> section in italics.
+#
+sgml('<IMPORTANT>', sub {
+    my $element = shift;
+
+    push @current_section_stack,$current_section;
+    $current_section = $element->attribute(ID)->value || generate_id();
+    my $title = $Refs->get("title:$current_section") || '[Untitled]';
+    output "\n\n\{\\em\\section{$title}\n\\label{$current_section}\n\n";
+});
+sgml('</IMPORTANT>', "\n\n\}\n\n");
+
+#
+# Blank lines delimit paragraphs in LaTeX.
+#
+sgml('<PARA>', "\n");
+sgml('</PARA>', "\n");
+
+#
+# The actual section will begin with the <TITLE> element, but note
+# the section's ID now.
+#
+sgml('<SECT1>', sub {
+    my $element = shift;
+
+    push @current_section_stack,$current_section;
+    $current_section = $element->attribute(ID)->value || generate_id();
+    my $title = $Refs->get("title:$current_section") || '[Untitled]';
+    output "\n\n\\section{$title}\n\\label{$current_section}\n\n";
+});
+sgml('</SECT1>', sub {
+    $current_section = pop @current_section_stack;
+    output "\n\n";
+});
+
+# Element: LINK (used only for HTML version)
+sgml('<LINK>', "");
+sgml('</LINK>', "");
+
+# Element: ULINK (used only for HTML version)
+sgml('<ULINK>', "");
+sgml('</ULINK>', "");
+
+#
+# An XREF may print the section number (or table number, etc.) or the actual
+# page number, depending upon the value of the ROLE= attribute.
+#
+sgml('<XREF>', sub {
+    my $element = shift;
+    my $idref = $element->attribute('LINKEND')->value;
+    my $type = $element->attribute('ROLE')->value;
+    if ($type eq 'page') {
+      output "\\pageref{$idref}";
+    } else {
+      output "\\ref{$idref}";
+    }
+});
+sgml('</XREF>', "");
+
+#
+# The name of an application will appear in small caps.
+#
+sgml('<APPLICATION>', "{\\sc ");
+sgml('</APPLICATION>', "}");
+
+#
+# Use LaTeX emphasis for emphasis.
+#
+sgml('<EMPHASIS>', "{\\em ");
+sgml('</EMPHASIS>', "\\/}");
+
+#
+# Technical terms are simply emphasised.
+#
+sgml('<GLOSSTERM>', "{\\em ");
+sgml('</GLOSSTERM>', "\\/}");
+
+#
+# Use proper quotation marks for quotes, with braces to get the ligaturing
+# right.
+#
+sgml('<QUOTE>', "{``}");
+sgml('</QUOTE>', "{''}");
+
+#
+# Acronyms appear in small caps.
+#
+sgml('<ACRONYM>', "{\\sc ");
+sgml('</ACRONYM>', "}");
+
+#
+# Filenames appear in typewriter.
+#
+sgml('<FILENAME>', "{\\tt ");
+sgml('</FILENAME>', "}");
+
+#
+# Symbols appear in typewriter.
+#
+sgml('<SYMBOL>', "{\\tt ");
+sgml('</SYMBOL>', "}");
+
+#
+# Program listings appear in the verbatim environment, which
+# preserves whitespace but also prints control characters as-is
+# (see the CDATA and SDATA handlers below for the special
+# treatment required).
+#
+sgml('<PROGRAMLISTING>', "\n{\\footnotesize\\begin{verbatim}\n");
+sgml('</PROGRAMLISTING>', "\n\\end{verbatim}}\n");
+
+#
+# Class names appear in typewriter.
+#
+sgml('<CLASSNAME>', "{\\tt ");
+sgml('</CLASSNAME>', "}");
+
+#
+# Commands (ie. methods, etc.) appear in typewriter.
+#
+sgml('<COMMAND>', "{\\tt ");
+sgml('</COMMAND>', "}");
+
+#
+# Begin a formal table.  The actual tabular environment will come
+# later, but for now, note the table's ID (so that it can follow
+# the caption -- see <TITLE>, above), and begin a floating environment
+# with the following placement preference: here, top, bottom, page.
+# Print tables in a small font to save space.
+#
+sgml('<TABLE>', sub {
+  my $element = shift;
+  push @current_table_stack,$current_table;
+  $current_table = $element->attribute('ID')->value || generate_id();
+  my $title = $Refs->get("title:$current_table");
+  output "\n\\begin{table}[htbp]\n\\footnotesize\n";
+  output "\\caption{$title}\n\\label{$current_table}\n";
+});
+sgml('</TABLE>', "\\end{table}\n");
+
+#
+# Here is where the tables get tricky: the <TGROUP> element specifies
+# the table's width in columns: instead of letting LaTeX sort out the
+# width of each column, presume that we want the table 4.45 inches wide
+# (!?!) and divide that width by the number of columns.  This is
+# a cheezy solution, but it allows the use of parboxes in the tables
+# for continuous text.
+#
+sgml('<TGROUP>', sub {
+    my $element = shift;
+    $table_columns = $element->attribute('COLS')->value;
+    $width = 4.45 / $table_columns;
+});
+sgml('</TGROUP>', "");
+
+#
+# Presume only one <THEAD> for each table, at its beginning.  Begin
+# the tabular element here, presuming left justification.
+#
+sgml('<THEAD>', sub {
+    output "\\vspace{2ex}\\begin{tabular}{l" .
+       "|l" x ($table_columns - 1) . "}\n";
+});
+sgml('</THEAD>', "");
+
+#
+# For end the tabular environment at the end of the table body.
+#
+sgml('<TBODY>', "");
+sgml('</TBODY>', "\\end{tabular}");
+
+#
+# Print a single line under each row in <TBODY>, but a double line under
+# the row in <THEAD>.  Reset the variable $row to 0 each time we begin
+# a new row.
+#
+sgml('<ROW>', sub { $row = 0; });
+sgml('</ROW>', sub {
+    my $element = shift;
+    if ($element->in('THEAD')) {
+       output "\\\\ \\hline\\hline\n";
+    } else {
+       output "\\\\ \\hline\n";
+    }
+});
+
+#
+# Here is the tricky part: use the $row variable to determine whether this
+# is the _first_ entry of the row (and thus, does not require a leading "&"),
+# and use parboxes for the actual entries' contents, so that they can
+# take up multiple lines.  Also add 4 points to the top and bottom of each
+# parbox, just to make it purtier.
+#
+sgml('<ENTRY>', sub {
+    if ($row == 0) {
+       $row = 1;
+    } else {
+       print " & ";
+    }
+    print "\\parbox[c]{" . $width . "in}{\\raggedright\\vspace{4pt} ";
+});
+sgml('</ENTRY>', "\\vspace{4pt}}\t");
+
+#
+# Parameters appear in slanted typewriter.
+#
+sgml('<PARAMETER>', "{\\tt\\sl ");
+sgml('</PARAMETER>', "\\/}");
+
+#
+# Return values appear in typewriter.
+#
+sgml('<RETURNVALUE>', "{\\tt ");
+sgml('</RETURNVALUE>', "}");
+
+#
+# Literal elements appear in typewriter.
+#
+sgml('<LITERAL>', "{\\tt ");
+sgml('</LITERAL>', "}");
+
+
+########################################################################
+# Declare handlers for SDATA strings.
+########################################################################
+
+#
+# These three will appear only in regular body text, so use simple
+# replacement strings for their LaTeX equivalents.
+#
+sgml('|[mdash ]|', "{---}");
+sgml('|[hellip]|', "{\\ldots}");
+sgml('|[LaTeX]|', "{\\LaTeX}");
+
+#
+# &lt;, &gt;, and &amp; could appear in the <PROGRAMLISTING> element,
+# where they should appear as literal '<', '>', and '&'; otherwise,
+# they need special treatment in LaTeX.  Note how these handlers use
+# the second argument to the handler, $event, to get the element
+# currently in force.
+#
+sgml('|[lt    ]|', sub {
+    my ($data,$event) = @_;
+    if ($event->element->name eq 'PROGRAMLISTING') {
+      output "\<";             # simple less-than in verbatim
+    } else {
+      output "\$\<\$";         # math less-than in regular text
+    }
+});
+sgml('|[gt    ]|', sub {
+    my ($data,$event) = @_;
+    if ($event->element->name eq 'PROGRAMLISTING') {
+      output "\>";             # simple greater-than in verbatim
+    } else {
+      output "\$\>\$";         # math greater-than in regular text
+    }
+});
+sgml('|[amp   ]|', sub {
+    my ($data,$event) = @_;
+    if ($event->element->name eq 'PROGRAMLISTING') {
+      output "\&";             # simple ampersand in verbatim
+    } else {
+      output "\\\&";           # escaped ampersand in regular text
+    }
+});
+
+
+########################################################################
+# CDATA handler: escape characters which can appear as-is in SGML
+# data but will cause problems in LaTeX.
+########################################################################
+
+sgml('cdata',sub {
+    my ($data,$event) = @_;
+    unless ($event->element->name eq 'PROGRAMLISTING') {
+       $data =~ s/\\/\\verb\|\\\|/g; # backslash
+       $data =~ s/\{/\\\{/g;   # opening brace
+       $data =~ s/\}/\\\}/g;   # closing brace
+       $data =~ s/\#/\\\#/g;   # hash
+       $data =~ s/\$/\\\$/g;   # dollar
+       $data =~ s/\%/\\\%/g;   # percent
+       $data =~ s/\&/\\\&/g;   # ampersand
+       $data =~ s/\~/\\\~/g;   # tilde
+       $data =~ s/\_/\\\_/g;   # underscore
+       $data =~ s/\^/\\\^/g;   # caret
+    }
+    output $data;
+});
+
+
+########################################################################
+# External data entity handler: deal with CDATA entities only,
+# including them verbatim.  For now, I use the SYSID for the
+# entity's file name, though I should probably
+########################################################################
+
+
+
+sgml('entity',sub {
+    my $entity = shift;
+    my $filename = $entity->filenames->[0] || $entity->sysid;
+                               # A strange NSGMLS-thing.
+    if ($filename =~ /^FILE:/ || $filename =~ /^\<FILE[^>]+\>/) {
+      $filename = $';
+    }
+    if ($entity->type eq 'CDATA') {
+       if (-r $filename) {
+           unless (open INPUT, "<$filename") {
+               die "Cannot open external file $filename\n";
+           }
+           while (<INPUT>) {
+               output $_;
+           }
+           close INPUT;
+       } else {
+           die "Cannot read file $filename\n";
+       }
+    } else {
+       die "Cannot handle external entity with type " . $entity->type . "\n";
+    }
+});
+
+
+########################################################################
+# The following default handlers will catch any new elements, SDATA,
+# processing instructions, or subdocument entities which I might add
+# to the document later, and will report an error if they are not
+# handled properly above.
+########################################################################
+
+sgml('start_element',sub { die "Unknown element: " . $_[0]->name; });
+sgml('sdata',sub { die "Unknown SDATA: " . $_[0]; });
+sgml('pi',sub { die "Unknown processing instruction: " . $_[0]->name; });
+sgml('start_subdoc',sub { die "Unknown subdoc entity: " . $_[0]->name; });
+
+\f
+########################################################################
+# Utility functions.
+########################################################################
+
+$id_counter = 1;
+sub generate_id {
+    return "ID" . $id_counter++;
+}
+
+1;
diff --git a/Makefile b/Makefile
new file mode 100644 (file)
index 0000000..db522e1
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,98 @@
+########################################################################
+# Makefile for installing SGMLS.pm and associated files in Unix
+# or Unix-like environments.  You should check the values of the
+# variables at the beginning and change them as appropriate.
+#
+# Version: 1.03ii
+########################################################################
+
+DIST = SGMLSpm-1.03ii.tar.gz
+
+#
+# Beginning of user options.
+#
+
+# Where is the binary for perl5 located on your system?
+PERL = /usr/bin/perl
+
+# Where do you want the sgmlspl executable script to be installed?
+BINDIR = /usr/local/bin
+
+# Where do you put local perl5 libaries?
+PERL5DIR = /usr/local/lib/perl5
+MODULEDIR = ${PERL5DIR}/SGMLS
+
+# Where do you want to put sgmlspl specifications?
+SPECDIR = ${PERL5DIR}
+
+# If you plan to install the HTML version of the documentation, where
+# do you intend to put it?  'make html' will create two
+# subdirectories, ${HTMLDIR}/SGMLSpm and ${HTMLDIR}/sgmlspl, and place
+# its files there.
+HTMLDIR = /usr/local/lib/www/docs
+
+
+#
+# End of user options.
+#
+
+HTML_SOURCES = DOC/HTML/SGMLSpm/ DOC/HTML/sgmlspl/
+
+FILES =        ${BINDIR}/sgmlspl \
+       ${PERL5DIR}/SGMLS.pm \
+       ${MODULEDIR}/Output.pm \
+       ${MODULEDIR}/Refs.pm \
+       ${SPECDIR}/skel.pl
+
+all: install docs
+
+install: install_system # install_html
+
+install_system: ${MODULEDIR} ${FILES}
+
+dist: ${DIST}
+
+${BINDIR}/sgmlspl: sgmlspl.pl
+       sed -e 's!/usr/bin/perl!${PERL}!' sgmlspl.pl > ${BINDIR}/sgmlspl
+       chmod a+x,a+r ${BINDIR}/sgmlspl
+
+${PERL5DIR}/SGMLS.pm: SGMLS.pm
+       cp SGMLS.pm ${PERL5DIR}/SGMLS.pm
+       chmod a+r ${PERL5DIR}/SGMLS.pm
+
+${MODULEDIR}:
+       if [ ! -d ${MODULEDIR} ]; then\
+         mkdir ${MODULEDIR}; \
+         chmod a+x ${MODULEDIR}; \
+       fi
+
+${MODULEDIR}/Output.pm: Output.pm
+       cp Output.pm ${MODULEDIR}/Output.pm
+       chmod a+r ${MODULEDIR}/Output.pm
+
+${MODULEDIR}/Refs.pm: Refs.pm
+       cp Refs.pm ${MODULEDIR}/Refs.pm
+       chmod a+r ${MODULEDIR}/Refs.pm
+
+${SPECDIR}/skel.pl: skel.pl
+       cp skel.pl ${SPECDIR}/skel.pl
+       chmod a+r ${SPECDIR}/skel.pl
+
+install_html: ${HTML_SOURCES}
+       cd DOC; make html
+       rm -rf ${HTMLDIR}/SGMLSpm ${HTMLDIR}/sgmlspl
+       cp -r ${HTML_SOURCES} ${HTMLDIR}
+       chmod a+x,a+r ${HTMLDIR}/SGMLSpm ${HTMLDIR}/sgmlspl
+       chmod a+r ${HTMLDIR}/SGMLSpm/* ${HTMLDIR}/sgmlspl/*
+
+docs:
+       cd DOC; make all
+
+${DIST}: clean docs
+       cd ..; \
+       tar -c -v -z --exclude RCS -f /tmp/${DIST} SGMLSpm; \
+       mv /tmp/${DIST} SGMLSpm
+
+clean:
+       cd DOC; make clean
+       rm -f *~ core *.tar *.tar.gz
diff --git a/Output.pm b/Output.pm
new file mode 100644 (file)
index 0000000..4758bfa
--- /dev/null
+++ b/Output.pm
@@ -0,0 +1,225 @@
+package SGMLS::Output;
+use Carp;
+
+use Exporter;
+@ISA = Exporter;
+@EXPORT = qw(output push_output pop_output);
+
+$version = '$Id: Output.pm,v 1.6 1995/12/05 12:21:51 david Exp $';
+
+=head1 NAME
+
+SGMLS::Output - Stack-based Output Procedures
+
+=head1 SYNOPSIS
+
+  use SGMLS::Output;
+
+To print a string to the current output destination:
+
+  output($data);
+
+To push a new output level to the filehandle DATA:
+
+  push_output('handle',DATA);
+
+To push a new output level to the file "foo.data" (which will be
+opened and closed automatically):
+
+  push_output('file','foo.data');
+
+To push a new output level to a pipe to the shell command "sort":
+
+  push_output('pipe','sort');
+
+To push a new output level I<appending> to the file "foo.data":
+
+  push_output('append','foo.data');
+
+To push a new output level to an empty string:
+
+  push_output('string');
+
+To push a new output level appending to the string "David is ":
+
+  push_output('string',"David is ");
+
+To push a new output level to The Great Beyond:
+
+  push_output('nul');
+
+To revert to the previous output level:
+
+  pop_output();
+
+To revert to the previous output level, returning the contents of an
+output string:
+
+  $data = pop_output();
+
+=head1 DESCRIPTION
+
+This library allows redirectable, stack-based output to files, pipes,
+handles, strings, or nul.  It is especially useful for packages like
+L<SGMLS>, since handlers for individual B<SGML> elements can
+temporarily change and restore the default output destination.  It is
+also particularly useful for capturing the contents of an element (and
+its sub-elements) in a string.
+
+Example:
+
+  sgmls('<title>', sub{ push_output('string'); });
+  sgmls('</title>', sub{ $title = pop_output(); });
+
+In between, anything sent to B<output> (such as CDATA) will be
+accumulated in the string returned from B<pop_output()>.
+
+Example:
+
+  sgmls('<tei.header>', sub { push_output('nul'); });
+  sgmls('</tei.header>', sub { pop_output(); });
+
+All output will be ignored until the header has finished.
+
+
+=head1 AUTHOR AND COPYRIGHT
+
+Copyright 1994 and 1995 by David Megginson,
+C<dmeggins@aix1.uottawa.ca>.  Distributed under the terms of the Gnu
+General Public License (version 2, 1991) -- see the file C<COPYING>
+which is included in the B<SGMLS.pm> distribution.
+
+
+=head1 SEE ALSO:
+
+L<SGMLS>.
+
+=cut
+
+#
+# Anonymous subroutines for handling different types of references.
+#
+$output_handle_sub = sub {
+    print $current_output_data @_;
+};
+
+$output_file_sub = sub {
+    print $current_output_data @_;
+};
+
+$output_string_sub = sub {
+    $current_output_data .= shift;
+    foreach (@_) {
+       $current_output_data .= $, . $_;
+    }
+    $current_output_data .= $\;
+};
+
+$output_nul_sub = sub {};
+
+#
+# Status variables
+#
+$current_output_type = 'handle';
+$current_output_data = STDOUT;
+$current_output_sub = $output_handle_sub;
+@output_stack = qw();
+
+#
+# Externally-visible functions
+#
+
+                               # Send data to the output.
+sub output {
+    &{$current_output_sub}(@_);
+}
+
+                               # Push a new output destination.
+sub push_output {
+    my ($type,$data) = @_;
+    push @output_stack, [$current_output_type,$current_output_data,
+                        $current_output_sub];
+  SWITCH: {
+      $type eq 'handle' && do {
+          # Force unqualified filehandles into caller's package
+          my ($package) = caller;
+          $data =~ s/^[^':]+$/$package\:\:$&/;
+
+         $current_output_sub = $output_handle_sub;
+         $current_output_type = 'handle';
+         $current_output_data = $data;
+         last SWITCH;
+      };
+      $type eq 'file' && do {
+         $current_output_sub = $output_file_sub;
+         my $handle = new_handle();
+         open($handle,">$data") || croak "Cannot create file $data.\n";
+         $current_output_type = 'file';
+         $current_output_data = $handle;
+         last SWITCH;
+      };
+      $type eq 'pipe' && do {
+         $current_output_sub = $output_file_sub;
+         my $handle = new_handle();
+         open($handle,"|$data") || croak "Cannot open pipe to $data.\n";
+         $current_output_type = 'file';
+         $current_output_data = $handle;
+         last SWITCH;
+      };
+      $type eq 'append' && do {
+         $current_output_sub = $output_file_sub;
+         my $handle = new_handle();
+         open($handle,">>$data") || croak "Cannot append to file $data.\n";
+         $current_output_type = 'file';
+         $current_output_data = $handle;
+         last SWITCH;
+      };
+      $type eq 'string' && do {
+         $current_output_sub = $output_string_sub;
+         $current_output_type = 'string';
+         $current_output_data = $data;
+         last SWITCH;
+      };
+      $type eq 'nul' && do {
+         $current_output_sub = $output_nul_sub;
+         $current_output_type = 'nul';
+         $current_output_data = '';
+         last SWITCH;
+      };
+      croak "Unknown output type: $type.\n";
+  }
+}
+
+                               # Pop the current output destination.
+sub pop_output {
+    my ($old_type,$old_data) = ($current_output_type,$current_output_data);
+    ($current_output_type,$current_output_data,$current_output_sub) =
+       @{pop @output_stack};
+  SWITCH: {
+      $old_type eq 'handle' && do {
+         return $old_data;
+      };
+      $old_type eq 'file' && do {
+         close($old_data);
+         return '';
+      };
+      $old_type eq 'string' && do {
+         return $old_data;
+      };
+      $old_type eq 'nul' && do {
+         return '';
+      };
+      croak "Unknown output type: $type.\n";
+  }
+}
+
+#
+# Local Utility functions.
+#
+$new_handle_counter = 1;
+
+sub new_handle {
+    return "IOHandle" . $new_handle_counter++;
+}
+
+1;
diff --git a/README b/README
new file mode 100644 (file)
index 0000000..7a9cec3
--- /dev/null
+++ b/README
@@ -0,0 +1,105 @@
+          SGMLS.PM: A PERL5 CLASS LIBRARY FOR USE WITH THE
+                      SGMLS AND NSGMLS PARSERS
+
+                            Version 1.03ii
+
+
+                          David Megginson,
+                        University of Ottawa
+
+
+[This is the fourth public release.  See "CHANGES", below, for a
+summary of the most important changes since version 1.02.  For
+detailed changes, see ChangeLog and DOC/ChangeLog; for known bugs, see
+BUGS.]
+
+
+This distribution contains SGMLS.pm, a perl5 class library for parsing
+the output from James Clark's SGMLS and NSGMLS parsers.  This is a
+free package, but it is _not_ Public-Domain software -- please see the
+file COPYING in this directory for the terms of use.
+
+Full documentation is available in SGML format the DOC directory, and
+in Postscript, LaTeX, and HTML format in the various subdirectories of
+the DOC directory.  Documentation in POD format is also included
+within each of the modules, and once they are installed, you can view
+them with perldoc (SGMLS, SGMLS::Ouptut, or SGMLS::Refs) -- there is
+no POD documentation in sgmlspl yet.
+
+Take a look in the elisp/ subdirectory for a special package for Gnu
+Emacs -- it will allow you to run (n)sgmls and sgmlspl from within an
+Emacs buffer containing an SGML file, displaying the output (LaTeX,
+for example) in another Emacs buffer.
+
+I have included a Unix Makefile for installing the package on Unix and
+Unix-like systems.  Make any necessary changes at the top of the
+Makefile, then type
+
+  make install
+
+to install the perl5 scripts on your system.  If you want to test the
+installation, change to the DOC subdirectory, read the comments at the
+top of the make file there, then type
+
+  make clean; make all
+
+to regenerate the LaTeX and HTML documentation using the scripts which
+you have just installed (you will have to have the SGMLS or NSGMLS
+parser, the Docbook 2.2.1 DTD and SGML declaration, and the ISOpub and
+ISOnum entity sets available on your system -- copies are included in
+the DOC/Extras subdirectory).  You may also type
+
+  make dvi
+
+or
+
+  make ps
+
+to produce DVI or Postscript versions of the documentation for
+printing.
+
+
+** nb: Effective with v.1.02, SGMLS.pm supports the new output from
+NSGMLS 0.4.13 with the -h option.
+
+
+CHANGES
+
+There have been some major changes since version 1.02.  File handles
+passed as arguments to SGMLS::new should be qualified in the correct
+package now.  The Output.pm module has been moved, so you should now
+type
+
+  use SGMLS::Output;
+
+instead of
+
+  use Output;
+
+in all of your scripts.  There is also a new package, SGMLS::Refs, to
+maintain a database of forward references from one processing pass to
+another, like the LaTeX .aux files.  Once you have installed SGMLS.pm,
+you can type
+
+  perldoc SGMLS::Refs
+
+at the shell prompt for more information, or you can read the new
+section in the SGML documentation for sgmlspl.  All of the
+documentation for this package is available online through my home
+page, listed below.
+
+As mentioned above, there is also a convenient package for Gnu Emacs
+19 in the elisp/ directory.
+
+
+Enjoy!
+
+David Megginson
+
+
+EMAIL: dmeggins@aix1.uottawa.ca
+WWW: http://www.uottawa.ca/~dmeggins
+Canada Post: Department of English,
+             University of Ottawa,
+             Ottawa, CANADA
+
diff --git a/Refs.pm b/Refs.pm
new file mode 100644 (file)
index 0000000..3e3f563
--- /dev/null
+++ b/Refs.pm
@@ -0,0 +1,216 @@
+package SGMLS::Refs;
+
+use Carp;
+
+$version = '$Id: Refs.pm,v 1.5 1995/12/03 21:28:36 david Exp $';
+
+=head1 NAME
+
+SGMLS::Refs
+
+=head1 SYNOPSIS
+
+  use SGMLS::Refs;
+
+To create a new reference-manager object using the file "foo.refs":
+
+  my $refs = new SGMLS::Refs("foo.refs");
+
+To create a new reference-manager object using the file "foo.refs" and
+logging changes to the file "foo.log":
+
+  my $refs = new SGMLS::Refs("foo.refs","foo.log");
+
+To record a reference:
+
+  $refs->put("document title",$title);
+
+To retrieve a reference:
+
+  $title = $refs->get("document title");
+
+To return the number of references changed since the last run:
+
+  $num = $refs->changed;
+
+To print a LaTeX-like warning if any references have changed:
+
+  $refs->warn;
+
+=head1 DESCRIPTION
+
+This library can be used together with the B<SGMLS> package to keep
+track of forward references from one run to another, like the B<LaTeX>
+C<.aux> files.  Each reference manager is an object which reads and
+then rewrites a file of perl source, with the file name provided by
+the caller.
+
+Example:
+
+  # Start up the reference manager before the parse.
+  sgml('start', sub { $refs = new SGMLS::Refs("foo.refs"); });
+
+  # Warn about any changed references at the end.
+  sgml('end', sub { $refs->warn; });
+
+  # Look up the title from the last parse, if available.
+  sgml('<div>', sub { 
+    my $element = shift;
+    my $id = $element->attribute(ID)->value;
+    my $title = $refs->get("title:$id") || "[no title available]";
+
+    $current_div_id = $id;
+
+    output "\\section{$title}\n\n";
+  });
+
+
+  # Save the title for the next parse.
+  sgml('<head>', sub { push_output('string'); });
+  sgml('</head>', sub {
+    my $title = pop_output();
+    my $id = $current_div_id;
+
+    $refs->put("title:$id",$title);
+  });
+  
+
+=head1 AUTHOR AND COPYRIGHT
+
+Copyright 1994 and 1995 by David Megginson,
+C<dmeggins@aix1.uottawa.ca>.  Distributed under the terms of the Gnu
+General Public License (version 2, 1991) -- see the file C<COPYING>
+which is included in the B<SGMLS.pm> distribution.
+
+
+=head1 SEE ALSO:
+
+L<SGMLS>, L<SGMLS::Output>.
+
+=cut
+
+#
+# Create a new instance of a reference manager.  The first argument is
+# the filename for the database, and the second (if present) is a
+# filename for logging changes.
+#
+sub new {
+    my ($class,$filename,$logname) = (@_);
+    my $self = {};
+    my $handle = generate_handle();
+    my $loghandle = generate_handle() if $logname;
+    my $oldRS = $/;            # Save old record separator.
+
+    # Read the current contents of the reference file (if any).
+    if (open($handle,"<$filename")) {
+       $/ = 0777;
+       $self->{'refs'} = eval <$handle> || {};
+       close $handle;
+    } else {
+       $self->{'refs'} = {};
+    }
+
+    # Open the reference file.
+    open($handle,">$filename") || croak $@;
+
+    # Open the log file, if any.
+    if ($logname) {
+       open($loghandle,">$logname") || croak $@;
+    }
+
+    # Note pertinent information.
+    $self->{'change_count'} = 0;
+    $self->{'handle'} = $handle;
+    $self->{'loghandle'} = $loghandle;
+    $self->{'filename'} = $filename;
+    $self->{'logname'} = $logname;
+
+    $/ = $oldRS;               # Restore old record separator.
+    return bless $self;
+}
+
+#
+# Set a reference's value.  If the value is unchanged, don't do anything;
+# otherwise, note the change by counting it and (optionally) logging it
+# to the file handle provided when the object was created.
+#
+sub put {
+    my ($self,$key,$value) = (@_);
+    my $loghandle = $self->{'loghandle'};
+    my $oldvalue = $self->{'refs'}->{$key};
+    
+    if ($oldvalue ne $value) {
+       $self->{'change_count'}++;
+       if ($loghandle) {
+           print $loghandle "\"$key\" changed from " .
+             
+             "\"$oldvalue\" to \"$value\".\n";
+       }
+       $self->{'refs'}->{$key} = $value;
+    }
+
+    return $oldvalue;
+}
+
+#
+# Grab the value of a reference.
+#
+sub get {
+    my ($self,$key) = (@_);
+
+    return $self->{'refs'}->{$key};
+}
+
+#
+# Return the number of changed references.
+#
+sub changed {
+    my $self = shift;
+    return $self->{'changed_count'};
+}
+
+#
+# Print a warning if any references have
+# changed (a la LaTeX -- so that the user knows that another pass is
+# necessary).  Return 1 if a warning has been printed, or 0 if it
+# was unnecessary.
+#
+sub warn {
+    my $self = shift;
+    my $count = $self->{'change_count'};
+    my $filename = $self->{'filename'};
+    my $plural = "references have";
+
+    $plural = "reference has" if $count == 1;
+    if ($count > 0) {
+       warn "SGMLS::Refs ($filename): $count $plural changed.\n";
+       return 1;
+    }
+    return 0;
+}
+
+sub DESTROY {
+    my $self = shift;
+    my $handle = $self->{'handle'};
+
+    close $self->{'loghandle'};
+
+    print $handle "{\n";
+    foreach $key (keys %{$self->{'refs'}}) {
+       my $value = $self->{'refs'}->{$key};
+       $key =~ s/\\/\\\\/g;
+       $key =~ s/'/\\'/g;
+       $value =~ s/\\/\\\\/g;
+       $value =~ s/'/\\'/g;
+       print $handle "  '$key' => '$value',\n";
+    }
+    print $handle "  '' => ''\n}\n";
+}
+
+$handle_counter = 1;
+sub generate_handle {
+    return "Handle" . $handle_counter++;
+}
+
+1;
+
diff --git a/SGMLS.pm b/SGMLS.pm
new file mode 100644 (file)
index 0000000..b29395e
--- /dev/null
+++ b/SGMLS.pm
@@ -0,0 +1,893 @@
+package SGMLS;
+use Carp;
+
+$version = '$Revision: 1.14 $';
+
+=head1 NAME
+
+SGMLS - class for postprocessing the output from the B<sgmls> and
+B<nsgmls> parsers.
+
+=head1 SYNOPSIS
+
+  use SGMLS;
+
+  my $parse = new SGMLS(STDIN);
+
+  my $event = $parse->next_event;
+  while ($event) {
+
+    SWITCH: {
+
+      ($event->type eq 'start_element') && do {
+        my $element = $event->data;    # An object of class SGMLS_Element
+        [[your code for the beginning of an element]]
+        last SWITCH;
+      };
+
+      ($event->type eq 'end_element') && do {
+        my $element = $event->data;    # An object of class SGMLS_Element
+        [[your code for the end of an element]]
+        last SWITCH;
+      };
+
+      ($event->type eq 'cdata') && do {
+        my $cdata = $event->data;      # A string
+        [[your code for character data]]
+        last SWITCH;
+      };
+
+      ($event->type eq 'sdata') && do {
+        my $sdata = $event->data;      # A string
+        [[your code for system data]]
+        last SWITCH;
+      };
+
+      ($event->type eq 're') && do {
+        [[your code for a record end]]
+        last SWITCH;
+      };
+
+      ($event->type eq 'pi') && do {
+        my $pi = $event->data;         # A string
+        [[your code for a processing instruction]]
+        last SWITCH;
+      };
+
+      ($event->type eq 'entity') && do {
+        my $entity = $event->data;     # An object of class SGMLS_Entity
+        [[your code for an external entity]]
+        last SWITCH;
+      };
+
+      ($event->type eq 'start_subdoc') && do {
+        my $entity = $event->data;     # An object of class SGMLS_Entity
+        [[your code for the beginning of a subdoc entity]]
+        last SWITCH;
+      };
+
+      ($event->type eq 'end_subdoc') && do {
+        my $entity = $event->data;     # An object of class SGMLS_Entity
+        [[your code for the end of a subdoc entity]]
+        last SWITCH;
+      };
+
+      ($event->type eq 'conforming') && do {
+        [[your code for a conforming document]]
+        last SWITCH;
+      };
+
+      die "Internal error: unknown event type " . $event->type . "\n";
+    }
+
+    $event = $parse->next_event;
+  }
+
+=head1 DESCRIPTION
+
+The B<SGMLS> package consists of several related classes: see
+L<"SGMLS">, L<"SGMLS_Event">, L<"SGMLS_Element">,
+L<"SGMLS_Attribute">, L<"SGMLS_Notation">, and L<"SGMLS_Entity">.  All
+of these classes are available when you specify
+
+  use SGMLS;
+
+Generally, the only object which you will create explicitly will
+belong to the C<SGMLS> class; all of the others will then be created
+automatically for you over the course of the parse.  Much fuller
+documentation is available in the C<.sgml> files in the C<DOC/>
+directory of the C<SGMLS.pm> distribution.
+
+=head2 The C<SGMLS> class
+
+This class holds a single parse.  When you create an instance of it,
+you specify a file handle as an argument (if you are reading the
+output of B<sgmls> or B<nsgmls> from a pipe, the file handle will
+ordinarily be C<STDIN>):
+
+  my $parse = new SGMLS(STDIN);
+
+The most important method for this class is C<next_event>, which reads
+and returns the next major event from the input stream.  It is
+important to note that the C<SGMLS> class deals with most B<ESIS>
+events itself: attributes and entity definitions, for example, are
+collected and stored automatically and invisibly to the user.  The
+following list contains all of the methods for the C<SGMLS> class:
+
+=item C<next_event()>: Return an C<SGMLS_Event> object containing the
+next major event from the SGML parse.
+
+=item C<element()>: Return an C<SGMLS_Element> object containing the
+current element in the document.
+
+=item C<file()>: Return a string containing the name of the current
+SGML source file (this will work only if the C<-l> option was given to
+B<sgmls> or B<nsgmls>).
+
+=item C<line()>: Return a string containing the current line number
+from the source file (this will work only if the C<-l> option was
+given to B<sgmls> or B<nsgmls>).
+
+=item C<appinfo()>: Return a string containing the C<APPINFO>
+parameter (if any) from the SGML declaration.
+
+=item C<notation(NNAME)>: Return an C<SGMLS_Notation> object
+representing the notation named C<NNAME>.  With newer versions of
+B<nsgmls>, all notations are available; otherwise, only the notations
+which are actually used will be available.
+
+=item C<entity(ENAME)>: Return an C<SGMLS_Entity> object representing
+the entity named C<ENAME>.  With newer versions of B<nsgmls>, all
+entities are available; otherwise, only external data entities and
+internal entities used as attribute values will be available.
+
+=item C<ext()>: Return a reference to an associative array for
+user-defined extensions.
+
+
+=head2 The C<SGMLS_Event> class
+
+This class holds a single major event, as generated by the
+C<next_event> method in the C<SGMLS> class.  It uses the following
+methods:
+
+=item C<type()>: Return a string describing the type of event:
+"start_element", "end_element", "cdata", "sdata", "re", "pi",
+"entity", "start_subdoc", "end_subdoc", and "conforming".  See
+L<"SYNOPSIS">, above, for the values associated with each of these.
+
+=item C<data()>: Return the data associated with the current event (if
+any).  For "start_element" and "end_element", returns an
+C<SGMLS_ELement> object; for "entity", "start_subdoc", and
+"end_subdoc", returns an C<SGMLS_Entity> object; for "cdata", "sdata",
+and "pi", returns a string; and for "re" and "conforming", returns the
+empty string.  See L<"SYNOPSIS">, above, for an example of this
+method's use.
+
+=item C<key()>: Return a string key to the event, such as an element
+or entity name (otherwise, the same as C<data()>).
+
+=item C<file()>: Return the current file name, as in the C<SGMLS>
+class.
+
+=item C<line()>: Return the current line number, as in the C<SGMLS>
+class.
+
+=item C<element()>: Return the current element, as in the C<SGMLS>
+class.
+
+=item C<parse()>: Return the C<SGMLS> object which generated the
+event.
+
+=item C<entity(ENAME)>: Look up an entity, as in the C<SGMLS> class.
+
+=item C<notation(ENAME)>: Look up a notation, as in the C<SGMLS>
+class.
+
+=item C<ext()>: Return a reference to an associative array for
+user-defined extensions.
+
+
+=head2 The C<SGMLS_Element> class
+
+This class is used for elements, and contains all associated
+information (such as the element's attributes).  It recognises the
+following methods:
+
+=item C<name()>: Return a string containing the name, or Generic
+Identifier, of the element, in upper case.
+
+=item C<parent()>: Return the C<SGMLS_Element> object for the
+element's parent (if any).
+
+=item C<parse()>: Return the C<SGMLS> object for the current parse.
+
+=item C<attributes()>: Return a reference to an associative array of
+attribute names and C<SGMLS_Attribute> structures.  Attribute names
+will be all in upper case.
+
+=item C<attribute_names()>: Return an array of strings containing the
+names of all attributes defined for the current element, in upper
+case.
+
+=item C<attribute(ANAME)>: Return the C<SGMLS_Attribute> structure for
+the attribute C<ANAME>.
+
+=item C<set_attribute(ATTRIB)>: Add the C<SGMLS_Attribute> object
+C<ATTRIB> to the current element, replacing any other attribute
+structure with the same name.
+
+=item C<in(GI)>: Return C<true> (ie. 1) if the string C<GI> is the
+name of the current element's parent, or C<false> (ie. 0) if it is
+not.
+
+=item C<within(GI)>: Return C<true> (ie. 1) if the string C<GI> is the
+name of any of the ancestors of the current element, or C<false>
+(ie. 0) if it is not.
+
+=item C<ext()>: Return a reference to an associative array for
+user-defined extensions.
+
+
+=head2 The C<SGMLS_Attribute> class
+
+Each instance of an attribute for each C<SGMLS_Element> is an object
+belonging to this class, which recognises the following methods:
+
+=item C<name()>: Return a string containing the name of the current
+attribute, all in upper case.
+
+=item C<type()>: Return a string containing the type of the current
+attribute, all in upper case.  Available types are "IMPLIED", "CDATA",
+"NOTATION", "ENTITY", and "TOKEN".
+
+=item C<value()>: Return the value of the current attribute, if any.
+This will be an empty string if the type is "IMPLIED", a string of
+some sort if the type is "CDATA" or "TOKEN" (if it is "TOKEN", you may
+want to split the string into a series of separate tokens), an
+C<SGMLS_Notation> object if the type is "NOTATION", or an
+C<SGMLS_Entity> object if the type is "ENTITY".  Note that if the
+value is "CDATA", it will I<not> have escape sequences for 8-bit
+characters, record ends, or SDATA processed -- that will be your
+responsibility.
+
+=item C<is_implied()>: Return C<true> (ie. 1) if the value of the
+attribute is implied, or C<false> (ie. 0) if it is specified in the
+document.
+
+=item C<set_type(TYPE)>: Change the type of the attribute to the
+string C<TYPE> (which should be all in upper case).  Available types
+are "IMPLIED", "CDATA", "NOTATION", "ENTITY", and "TOKEN".
+
+=item C<set_value(VALUE)>: Change the value of the attribute to
+C<VALUE>, which may be a string, an C<SGMLS_Entity> object, or an
+C<SGMLS_Notation> subject, depending on the attribute's type.
+
+=item C<ext()>: Return a reference to an associative array available
+for user-defined extensions.
+
+
+=head2 The C<SGMLS_Notation> class
+
+All declared notations appear as objects belonging to this class,
+which recognises the following methods:
+
+=item C<name()>: Return a string containing the name of the notation.
+
+=item C<sysid()>: Return a string containing the system identifier of
+the notation, if any.
+
+=item C<pubid()>: Return a string containing the public identifier of
+the notation, if any.
+
+=item C<ext()>: Return a reference to an associative array available
+for user-defined extensions.
+
+
+=head2 The C<SGMLS_Entity> class
+
+All declared entities appear as objects belonging to this class, which
+recognises the following methods:
+
+=item C<name()>: Return a string containing the name of the entity, in
+mixed case.
+
+=item C<type()>: Return a string containing the type of the entity, in
+upper case.  Available types are "CDATA", "SDATA", "NDATA" (external
+entities only), "SUBDOC", "PI" (newer versions of B<nsgmls> only), or
+"TEXT" (newer versions of B<nsgmls> only).
+
+=item C<value()>: Return a string containing the value of the entity,
+if it is internal.
+
+=item C<sysid()>: Return a string containing the system identifier of
+the entity (if any), if it is external.
+
+=item C<pubid()>: Return a string containing the public identifier of
+the entity (if any), if it is external.
+
+=item C<filenames()>: Return an array of strings containing any file
+names generated from the identifiers, if the entity is external.
+
+=item C<notation()>: Return the C<SGMLS_Notation> object associated
+with the entity, if it is external.
+
+=item C<data_attributes()>: Return a reference to an associative array
+of data attribute names (in upper case) and the associated
+C<SGMLS_Attribute> objects for the current entity.
+
+=item C<data_attribute_names()>: Return an array of data attribute
+names (in upper case) for the current entity.
+
+=item C<data_attribute(ANAME)>: Return the C<SGMLS_Attribute> object
+for the data attribute named C<ANAME> for the current entity.
+
+=item C<set_data_attribute(ATTRIB)>: Add the C<SGMLS_Attribute> object
+C<ATTRIB> to the current entity, replacing any other data attribute
+with the same name.
+
+=item C<ext()>: Return a reference to an associative array for
+user-defined extensions.
+
+
+=head1 AUTHOR AND COPYRIGHT
+
+Copyright 1994 and 1995 by David Megginson,
+C<dmeggins@aix1.uottawa.ca>.  Distributed under the terms of the Gnu
+General Public License (version 2, 1991) -- see the file C<COPYING>
+which is included in the B<SGMLS.pm> distribution.
+
+
+=head1 SEE ALSO:
+
+L<SGMLS::Output> and L<SGMLS::Refs>.
+
+=cut
+
+#
+# Data class for a single SGMLS ESIS output event.  The object will
+# keep information about its own current element and, if available,
+# the source file and line where the event appeared.
+#
+# Event types are as follow:
+#        Event                 Data
+# -------------------------------------------------------
+#     'start_element'        SGMLS_Element
+#     'end_element'          SGMLS_Element
+#     'cdata'                string
+#     'sdata'                string
+#     're'                   [none]
+#     'pi'                   string
+#     'entity'               SGMLS_Entity
+#     'start_subdoc'         SGMLS_Entity
+#     'end_subdoc'           SGMLS_Entity
+#     'conforming'           [none]
+#
+package SGMLS_Event;
+use Carp;
+                               # Constructor.
+sub new {
+    my ($class,$type,$data,$parse) = @_;
+    return bless [$type,
+                 $data,
+                 $parse->file,
+                 $parse->line,
+                 $parse->element,
+                 $parse,
+                 {}
+                 ];
+}
+                               # Accessors.
+sub type { return $_[0]->[0]; }
+sub data { return $_[0]->[1]; }
+sub file { return $_[0]->[2]; }
+sub line { return $_[0]->[3]; }
+sub element { return $_[0]->[4]; }
+sub parse { return $_[0]->[5]; }
+sub ext { return $_[0]->[6]; }
+                               # Generate a key for the event.
+sub key {
+    my $self = shift;
+    if (ref($self->data) eq SGMLS_Element ||
+       ref($self->data) eq SGMLS_Entity) {
+       return $self->data->name;
+    } else {
+       return $self->data;
+    }
+}
+                               # Look up an entity in the parse.
+sub entity {
+    my ($self,$ename) = (@_);
+    return $self->parse->entity($ename);
+}
+                               # Look up a notation in the parse.
+sub notation {
+    my ($self,$nname) = (@_);
+    return $self->parse->notation($nname);
+}
+    
+
+#
+# Data class for a single SGML attribute.  The object will know its
+# type, and will keep a value unless the type is 'IMPLIED', in which
+# case no meaningful value is available.
+#
+# Attribute types are as follow:
+#      Type                    Value
+# ---------------------------------------
+#     IMPLIED                 [none]
+#     CDATA                   string
+#     NOTATION                SGMLS_Notation
+#     ENTITY                  SGMLS_Entity
+#     TOKEN                   string
+#
+package SGMLS_Attribute;
+use Carp;
+                               # Constructor.
+sub new {
+    my ($class,$name,$type,$value) = @_;
+    return bless [$name,$type,$value,{}];
+}
+                               # Accessors.
+sub name { return $_[0]->[0]; }
+sub type { return $_[0]->[1]; }
+sub value { return $_[0]->[2]; }
+sub ext { return $_[0]->[3]; }
+                               # Return 1 if the value is implied.
+sub is_implied {
+    my $self = shift;
+    return ($self->type eq 'IMPLIED');
+}
+                               # Set the attribute's type.
+sub set_type {
+    my ($self,$type) = @_;
+    $self->[1] = $type;
+}
+
+                               # Set the attribute's value.
+sub set_value {
+    my ($self,$value) = @_;
+    $self->[2] = $value;
+}
+
+
+#
+# Data class for a single element of an SGML document.  The object will not
+# know about its children (data or other elements), but it keeps track of its
+# parent and its attributes.
+#
+package SGMLS_Element;
+use Carp;
+                               # Constructor.
+sub new {
+    my ($class,$name,$parent,$attributes,$parse) = @_;
+    return bless [$name,$parent,$attributes,$parse,{}];
+}
+                               # Accessors.
+sub name { return $_[0]->[0]; }
+sub parent { return $_[0]->[1]; }
+sub parse { return $_[0]->[3]; }
+sub ext { return $_[0]->[4]; }
+
+                               # Return the associative array of
+                               # attributes, parsing it the first
+                               # time through.
+sub attributes {
+    my $self = shift;
+    if (ref($self->[2]) eq 'ARRAY') {
+       my $new = {};
+       foreach (@{$self->[2]}) {
+           /^(\S+) (IMPLIED|CDATA|NOTATION|ENTITY|TOKEN)( (.*))?$/
+               || croak "Bad attribute event data: $_";
+           my ($name,$type,$value) = ($1,$2,$4);
+           if ($type eq 'NOTATION') {
+               $value = $self->parse->notation($value);
+           } elsif ($type eq 'ENTITY') {
+               $value = $self->parse->entity($value);
+           }
+           $new->{$name} =
+               new SGMLS_Attribute($name,$type,$value);
+       }
+       $self->[2] = $new;
+    }
+    return $self->[2];
+}
+                               # Return a list of attribute names.
+sub attribute_names {
+    my $self = shift;
+    return keys(%{$self->attributes});
+}
+                               # Find an attribute by name.
+sub attribute {
+    my ($self,$aname) = @_;
+    return $self->attributes->{$aname};
+}
+                               # Add a new attribute.
+sub set_attribute {
+    my ($self,$attribute) = @_;
+    $self->attributes->{$attribute->name} = $attribute;
+}
+                               # Check parent by name.
+sub in {
+    my ($self,$name) = @_;
+    if ($self->parent && $self->parent->name eq $name) {
+       return $self->parent;
+    } else {
+       return '';
+    }
+}
+                               # Check ancestors by name.
+sub within {
+    my ($self,$name) = @_;
+    for ($self = $self->parent; $self; $self = $self->parent) {
+       return $self if ($self->name eq $name);
+    }
+    return '';
+}
+    
+
+#
+# Data class for an SGML notation.  The only information available
+# will be the name, the sysid, and the pubid -- the rest is up to the
+# processing application.
+#
+package SGMLS_Notation;
+use Carp;
+                               # Constructor.
+sub new {
+    my ($class,$name,$sysid,$pubid) = @_;
+    return bless [$name,$sysid,$pubid,{}];
+}
+                               # Accessors.
+sub name { return $_[0]->[0]; }
+sub sysid { return $_[0]->[1]; }
+sub pubid { return $_[0]->[2]; }
+sub ext { return $_[0]->[3]; }
+
+#
+# Data class for a single SGML entity.  All entities will have a name
+# and a type.  Internal entities will be of type CDATA or SDATA only,
+# and will have a value rather than a notation and sysid/pubid.  External
+# CDATA, NDATA, and SDATA entities will always have notations attached,
+# and SUBDOC entities are always external (and will be parsed by SGMLS).
+#
+# Entity types are as follow:
+#      Type     Internal    External
+# -----------------------------------------------------------
+#     CDATA      x           x
+#     NDATA                  x
+#     SDATA      x           x
+#     SUBDOC                 x
+# (newer versions of NSGMLS only:)
+#     PI         x
+#     TEXT       x           x
+#
+package SGMLS_Entity;
+use Carp;
+                               # Constructor.
+sub new {
+    my ($class,$name,$type,$value,$sysid,$pubid,$filenames,$notation) = @_;
+    return bless [$name,$type,$value,{},$sysid,$pubid,$filenames,$notation,{}];
+}
+                               # Accessors.
+sub name { return $_[0]->[0]; }
+sub type { return $_[0]->[1]; }
+sub value { return $_[0]->[2]; }
+sub data_attributes { return $_[0]->[3]; }
+sub sysid { return $_[0]->[4]; }
+sub pubid { return $_[0]->[5]; }
+sub filenames { return $_[0]->[6]; }
+sub notation { return $_[0]->[7]; }
+sub ext { return $_[0]->[8]; }
+                               # Return a list of data-attribute names.
+sub data_attribute_names {
+    my $self = shift;
+    return keys(%{$self->data_attributes});
+}
+                               # Find a data attribute by name.
+sub data_attribute {
+    my ($self,$aname) = @_;
+    return $self->data_attributes->{$aname};
+}
+                               # Add a new data attribute.
+sub set_data_attribute {
+    my ($self,$data_attribute) = @_;
+    $self->data_attributes()->{$data_attribute->name} = $data_attribute;
+}
+
+    
+
+#
+# Data class for a single SGMLS parse.  The constructor takes a single
+# argument, a file handle from which the SGMLS ESIS events will be read
+# (it may be a pipe, a fifo, a file, a socket, etc.).  It is essential
+# that no two SGMLS objects have the same handle.
+#
+package SGMLS;
+                               # Constructor.
+sub new {
+    my ($class,$handle) = @_;
+
+    # Force unqualified filehandles into caller's package
+    my ($package) = caller;
+    $handle =~ s/^[^':]+$/$package\:\:$&/;
+
+    return bless {
+       'handle' => $handle,
+       'event_stack' => [],
+       'current_element' => '',
+       'current_attributes' => [],
+       'current_entities' => {},
+       'entity_stack' => [],
+       'current_notations' => {},
+       'notation_stack' => [],
+       'current_sysid' => '',
+       'current_pubid' => '',
+       'current_filenames' => [],
+       'current_file' => '',
+       'current_line' => '',
+       'appinfo' => '',
+       'ext' => {}
+       };
+}
+                               # Accessors.
+sub element { return $_[0]->{'current_element'}; }
+sub file { return $_[0]->{'current_file'}; }
+sub line { return $_[0]->{'current_line'}; }
+sub appinfo { return $_[0]->{'appinfo'}; }
+sub ext { return $_[0]->{'ext'}; }
+
+                               # Given its name, look up a notation.
+sub notation {
+    my ($self,$nname) = @_;
+    return $self->{'current_notations'}->{$nname};
+}
+                               # Given its name, look up an entity.
+sub entity {
+    my ($self,$ename) = @_;
+    return $self->{'current_entities'}->{$ename};
+}
+
+                               # Return the next SGMLS_Event, or ''
+                               # if the document has finished.
+sub next_event {
+    my $self = shift;
+    my $handle = $self->{'handle'};
+
+                               # If there are any queued up events,
+                               # grab them first.
+    if ($#{$self->{event_stack}} >= 0) {
+       return pop @{$self->{event_stack}};
+    }
+
+  dispatch: while (!eof($handle)) {
+
+      my $c = getc($handle);
+      my $data = <$handle>;
+      chop $data;
+
+      ($c eq '(') && do {      # start an element
+         $self->{'current_element'} =
+             new SGMLS_Element($data,
+                               $self->{'current_element'},
+                               $self->{'current_attributes'},
+                               $self);
+         $self->{'current_attributes'} = [];
+         return new SGMLS_Event('start_element',
+                                $self->{'current_element'},
+                                $self);
+      };
+      
+      ($c eq ')') && do {      # end an element
+         my $old = $self->{'current_element'};
+         $self->{'current_element'} = $self->{'current_element'}->parent;
+         return new SGMLS_Event('end_element',$old,$self);
+      };
+      
+      ($c eq '-') && do {      # some data
+         my $sdata_flag = 0;
+         my $out = '';
+         while ($data =~ /\\(\\|n|\||[0-7]{1,3})/) {
+             $out .= $`;
+             $data = $';
+                               # beginning or end of SDATA
+             if ($1 eq '|') {
+                 if ("$out" ne '') {
+                     unshift(@{$self->{'event_stack'}},
+                             new SGMLS_Event($sdata_flag?'sdata':'cdata',
+                                             $out,
+                                             $self));
+                     $out = '';
+                 }
+                 $sdata_flag = !$sdata_flag;
+                               # record end
+             } elsif ($1 eq 'n') {
+                 if ("$out" ne '') {
+                     unshift(@{$self->{'event_stack'}},
+                             new SGMLS_Event($sdata_flag?'sdata':'cdata',
+                                             $out,
+                                             $self));
+                     $out = '';
+                 }
+                 unshift(@{$self->{'event_stack'}},
+                         new SGMLS_Event('re','',$self));
+             } elsif ($1 eq '\\') {
+                 $out .= '\\';
+             } else {
+                 $out .= chr(oct($1));
+             }
+         }
+         $out .= $data;
+         if ("$out" ne '') {
+             unshift(@{$self->{'event_stack'}},
+                     new SGMLS_Event($sdata_flag?'sdata':'cdata',
+                                     $out,
+                                     $self));
+         }
+             return $self->next_event;
+      };
+      
+      ($c eq '&') && do {      # external entity reference
+         return new SGMLS_Event('entity',
+                                ($self->{'current_entities'}->{$data}
+                                 || croak "Unknown external entity: $data\n"),
+                                $self);
+      };
+      
+      ($c eq '?') && do {      # processing instruction
+         return new SGMLS_Event('pi',
+                                $data,
+                                $self);
+      };
+      
+      ($c eq 'A') && do {      # attribute declaration
+                               # (will parse only on demand)
+         push @{$self->{'current_attributes'}}, $data;
+         next dispatch;
+      };
+      
+      ($c eq 'a') && do {      # link attribute declaration
+         # NOT YET IMPLEMENTED!
+         next dispatch;
+      };
+      
+      ($c eq 'D') && do {      # data attribute declaration
+         $data =~ /^(\S+) (\S+) (\S+)( (.*))?$/
+           || croak "Bad data-attribute event data: $data";
+         my ($ename,$aname,$type,$value) = ($1,$2,$3,$5);
+         my $entity = $self->{'current_entities'}->{$ename};
+         my $attribute = new SGMLS_Attribute($aname,$type,$value);
+         $entity->set_data_attribute($attribute);
+         next dispatch;
+      };
+      
+      ($c eq 'N') && do {      # notation declaration
+         $self->{'current_notations'}->{$data} =
+             new SGMLS_Notation($data,
+                                $self->{'current_sysid'},
+                                $self->{'current_pubid'});
+         $self->{'current_sysid'} = '';
+         $self->{'current_pubid'} = '';
+         next dispatch;
+      };
+      
+      ($c eq 'E') && do {      # external entity declaration
+         $data =~ /^(\S+) (\S+) (\S+)$/
+             || croak "Bad external entity event data: $data";
+         my ($name,$type,$nname) = ($1,$2,$3);
+         my $notation = $self->{'current_notations'}->{$nname} if $nname;
+         $self->{'current_entities'}->{$name} =
+             new SGMLS_Entity($name,
+                              $type,
+                              '',
+                              $self->{'current_sysid'},
+                              $self->{'current_pubid'},
+                              $self->{'current_filenames'},
+                              $notation);
+         $self->{'current_sysid'} = '';
+         $self->{'current_pubid'} = '';
+         $self->{'current_filenames'} = [];
+         next dispatch;
+      };
+      
+      ($c eq 'I') && do {      # internal entity declaration
+         $data =~ /^(\S+) (\S+) (.*)$/
+             || croak "Bad external entity event data: $data";
+         my ($name,$type,$value) = ($1,$2,$3);
+         $self->{'current_entities'}->{$name} =
+             new SGMLS_Entity($name, $type, $value);
+         next dispatch;
+      };
+      
+      ($c eq 'T') && do {      # external text entity declaration
+         $self->{'current_entities'}->{$data} =
+             new SGMLS_Entity($data,
+                              'TEXT',
+                              '',
+                              $self->{'current_sysid'},
+                              $self->{'current_pubid'},
+                              $self->{'current_filenames'},
+                              '');
+         $self->{'current_sysid'} = '';
+         $self->{'current_pubid'} = '';
+         $self->{'current_filenames'} = [];
+         next dispatch;
+      };
+      
+      ($c eq 'S') && do {      # subdocument entity declaration
+         $self->{'current_entities'}->{$data} =
+             new SGMLS_Entity($data,
+                              'SUBDOC',
+                              '',
+                              $self->{'current_sysid'},
+                              $self->{'current_pubid'},
+                              $self->{'current_filenames'},
+                              '');
+         $self->{'current_sysid'} = '';
+         $self->{'current_pubid'} = '';
+         $self->{'current_filenames'} = [];
+         next dispatch;
+      };
+      
+      ($c eq 's') && do {      # system id
+         $self->{'current_sysid'} = $data;
+         next dispatch;
+      };
+      
+      ($c eq 'p') && do {      # public id
+         $self->{'current_pubid'} = $data;
+         next dispatch;
+      };
+      
+      ($c eq 'f') && do {      # generated filename
+         push @{$self->{'current_filenames'}}, $data;
+         next dispatch;
+      };
+      
+      ($c eq '{') && do {      # begin subdocument entity
+         my $subdoc = ($self->{'current_entities'}->{$data}||
+                       croak "Unknown SUBDOC entity $data\n");
+         push @{$self->{'notation_stack'}}, $self->{'current_notations'};
+         push @{$self->{'entity_stack'}}, $self->{'current_entities'};
+         $self->{'current_notations'} = {};
+         $self->{'current_entities'} = {};
+         return new SGMLS_Event('start_subdoc',
+                                $subdoc,
+                                $self);
+      };
+      
+      ($c eq '}') && do {      # end subdocument entity
+         $self->{'current_notations'} = pop @{$self->{'notation_stack'}};
+         $self->{'current_entities'} = pop @{$self->{'entity_stack'}};
+         return new SGMLS_Event('end_subdoc',
+                                ($self->{'current_entities'}->{$data} ||
+                                 croak "Unknown SUBDOC entity $data\n"),
+                                $self);
+      };
+
+      ($c eq 'L') && do {      # line number (and file name)
+         $data =~ /^(\d+)( (.*))?$/;
+         $self->{'current_line'} = $1;
+         $self->{'current_file'} = $3 if $3;
+         next dispatch;
+      };
+      
+      ($c eq '#') && do {      # APPINFO parameter
+         $self->{'appinfo'} = $data;
+         next dispatch;
+      };
+      
+      ($c eq 'C') && do {      # document is conforming
+         return new SGMLS_Event('conforming','',$self);
+      };
+  }
+    return '';
+}
+
+1;
+
+########################################################################
+# Local Variables:
+# mode: perl
+# End:
+########################################################################
diff --git a/TODO b/TODO
new file mode 100644 (file)
index 0000000..6c31e66
--- /dev/null
+++ b/TODO
@@ -0,0 +1,6 @@
+SGMLS.pm: things to do
+
+- add support for SDATA, etc. in attribute values (see BUGS).
+- add a switch to skel.pl to allow handlers to be sorted into
+alphabetical order if desired.
+- allow for more customisation in SGMLS.pm data classes.
\ No newline at end of file
diff --git a/elisp/README b/elisp/README
new file mode 100644 (file)
index 0000000..99cbe16
--- /dev/null
@@ -0,0 +1,22 @@
+This directory contains sgmls.el, a LISP front-end for the SGMLS
+parser and any associated post-processors.  By default, it is set up
+to use James Clark's sgmls with the sgmlsasp post-processor, but you
+can reconfigure it for use with sgmlspl by adding the following code
+to your ~/.emacs file:
+
+  (setq-default sgmls-postprocessor "sgmlspl")
+
+You can also choose a central directory for your sgmlspl scripts, as
+in the following example:
+
+  (setq-default sgmls-spec-directory "~/lib/perl5")
+
+There are many, many more options -- read the comments at the top of
+the file for details.
+
+
+David Megginson,
+Acting Director, Writing Centre,
+University of Ottawa
+
+<dmeggins@aix1.uottawa.ca>
\ No newline at end of file
diff --git a/elisp/sgmls.el b/elisp/sgmls.el
new file mode 100644 (file)
index 0000000..2f4d0d9
--- /dev/null
@@ -0,0 +1,437 @@
+;;;; sgmls.el --- LISP front end for SGMLS and a postprocessor.
+
+;;; Copyright (C) 1994 David Megginson
+
+;;; Author: David Megginson <dmeggins@aix1.uottawa.ca>
+
+;;; Like Gnu Emacs, 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 2 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
+;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;;; GNU General Public License for more details.
+;;; 
+;;; You should have received a copy of the GNU General Public License
+;;; along with Gnu Emacs, which is required to run it; if not, write to
+;;; the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA
+;;; 02139, USA.
+
+\f
+;;;; Commentary
+
+;;; A LISP front end for the SGMLS parser and any postprocessors.
+
+;;; This package provides a convenient front end for the free SGMLS
+;;; parser and any postprocessors (such as perl scripts or the simple
+;;; SGMLSASP program supplied with SGMLS).  With a single command,
+;;; emacs will cause an SGML source file to be parsed and processed in
+;;; the background, placing the final output in a separate buffer.
+
+
+;;;; USAGE
+
+;;; Place this file somewhere in your load path, byte-compile it if
+;;; you wish (it is not speed-critical), and add one of the following
+;;; sequences to your default.el or .emacs file:
+;;;
+;;;   (autoload 'sgmls "sgmls" nil t)
+;;;   (autoload 'sgmls-edit-spec "sgmls" nil t)
+;;;   (autoload 'sgmls-start-process "sgmls")
+;;;
+;;; __OR__
+;;;
+;;;   (require 'sgmls)
+;;;
+;;; The first will load sgmls.el only upon demand, while the second
+;;; will load it unconditionally whenever emacs starts.  You may then
+;;; run the package simply by typing "M-x sgmls" (you may, of course,
+;;; prefer to bind it to a keystroke).
+
+
+;;;; CONFIGURATION
+
+;;; This package is highly configurable, but its default setup should
+;;; work well for the average user.  All of the options are documented
+;;; in the next section under "User Options" -- the most important are
+;;; `sgmls-spec', which contains the name of the file containing a
+;;; specification for the postprocessor; `sgmls-spec-directory', which
+;;; contains a default directory for the specs; `sgmls-postprocessor',
+;;; which contains the name of the postprocessor program ("sgmlsasp"
+;;; by default); and `sgmls-decl' (or `sgml-declaration' from
+;;; psgml.el), which contains the name of the file containing an SGML
+;;; declaration.  All of these options are buffer-local, and may be
+;;; set in the "Local Variables:" section of a file.
+;;;
+;;; If you call `sgmls' with prefix argument, you will be given an
+;;; opportunity to review and override all of the default settings.
+
+
+;;;; KNOWN BUGS
+
+;;; Because of the way that Emacs and this package handles the
+;;; processes, errors are not handled cleanly.  The exit status
+;;; displayed when the process terminates applies only to the
+;;; postprocessor; the exit status of the SGMLS parser itself, which
+;;; is the first element in the pipeline, is not indicated unless the
+;;; postprocessor is smart enough to notice that something is wrong.
+;;; Furthermore, since Emacs always mixes the stdout and stderr of its
+;;; subprocesses together, any error messages will simply be embedded
+;;; in the middle of the output buffer.
+
+
+\f
+;;;; User Options.
+
+(defvar sgmls-parser-command nil
+  "*Command for running SGMLS.")
+(make-variable-buffer-local 'sgmls-parser-command)
+
+(defvar sgmls-postprocessor-command nil
+  "*Command for running SGMLS postprocessor")
+(make-variable-buffer-local 'sgmls-postprocessor-command)
+
+(defvar sgmls-parser "sgmls"
+  "*Name of SGMLS program on local system (buffer-local).")
+(make-variable-buffer-local 'sgmls-parser)
+
+(defvar sgmls-parser-options ""
+  "*Options for SGMLS parser.")
+(make-variable-buffer-local 'sgmls-parser-options)
+
+(defvar sgmls-declaration nil
+  "*Default SGML declaration (buffer-local).
+If this variable is not set, the variable `sgml-declaration' (from
+psgml.el) will be tried.")
+(make-variable-buffer-local 'sgmls-declaration)
+
+(defvar sgmls-source-file nil
+  "*Default SGML source file (buffer-local).
+By default, this will usually be the file associated with the current
+buffer, but it can also be generated from the `sgml-parent-document'
+variable (from psgml.el), or set manually.")
+(make-variable-buffer-local 'sgmls-source-file)
+
+(defvar sgmls-postprocessor "sgmlsasp"
+  "*Name of SGMLS postprocessor on local system (buffer-local).")
+(make-variable-buffer-local 'sgmls-postprocessor)
+
+(defvar sgmls-postprocessor-options ""
+  "*Options for SGMLS postprocessor.")
+(make-variable-buffer-local 'sgmls-postprocessor-options)
+
+(defvar sgmls-spec nil
+  "*Default specification file or argument for postprocessor (buffer-local).
+This may be specified relative to `sgmls-spec-directory'.")
+(make-variable-buffer-local 'sgmls-spec)
+
+(defvar sgmls-spec-directory nil
+  "*Default directory for sgmls-spec.")
+(make-variable-buffer-local 'sgmls-spec-directory)
+
+(defvar sgmls-output-file nil
+  "*Default file name for sgmls output file (buffer-local).
+This may be specified relative to `sgmls-output-directory', and may be
+generated automatically from the source file using `sgmls-output-file-ext'.")
+(make-variable-buffer-local 'sgmls-output-file)
+
+(defvar sgmls-output-file-ext nil
+  "*Default extension for sgmls output file (buffer-local).
+If `sgmls-output-file' is not set, it will be generated from the source
+file using the extension provided here.")
+(make-variable-buffer-local 'sgmls-output-file-ext)
+
+(defvar before-sgmls-hooks nil
+  "*Hooks to run on the output buffer before SGMLS starts (buffer-local).")
+(make-variable-buffer-local 'before-sgmls-hooks)
+
+(defvar after-sgmls-hooks nil
+  "*Hooks to run on the output buffer after SGMLS finishes (buffer-local).")
+(make-variable-buffer-local 'after-sgmls-hooks)
+
+
+;;; Internal variables.
+
+(defvar sgmls::parser-error-file nil)
+(make-variable-buffer-local 'sgmls::parser-error-file)
+
+(defvar sgmls::postprocessor-error-file)
+(make-variable-buffer-local 'sgmls::postprocessor-error-file)
+
+
+\f
+;;;; User-level commands and functions.
+
+;;
+;; Interactive function to set up command line and run sgmls.
+;;
+(defun sgmls (flag)
+  "Run sgmls and a postprocessor, putting the output into a file buffer.
+With a prefix argument, allow the caller to review and override any
+default values.  The variables `sgmls-parser' and
+`sgmls-postprocessor' contain the actual names of the programs which
+will be run (in a shell command sent to `shell-file-name')."
+
+  (interactive "P")
+
+  (if (or flag (not sgmls-parser-command))
+      (setq sgmls-parser-command
+           (format "%s %s %s %s"
+                   sgmls-parser
+                   sgmls-parser-options
+                   (sgmls::generate-declaration)
+                   (sgmls::generate-source-file))))
+  (setq sgmls-parser-command
+       (read-string "Parser command: " 
+                    (cons sgmls-parser-command 1)))
+
+  (if (or flag (not sgmls-postprocessor-command))
+      (setq sgmls-postprocessor-command
+           (format "%s %s %s"
+                   sgmls-postprocessor
+                   sgmls-postprocessor-options
+                   (sgmls::generate-spec flag))))
+  (setq sgmls-postprocessor-command
+       (read-string "Postprocessor command: " 
+                    (cons sgmls-postprocessor-command 1)))
+
+  (sgmls-start-process
+   (format "%s 2>%s | %s 2>%s"
+          sgmls-parser-command
+          (sgmls::generate-parser-error-file)
+          sgmls-postprocessor-command
+          (sgmls::generate-postprocessor-error-file))
+   (find-file-noselect (sgmls::generate-output-file flag))))
+
+
+;;
+;; Edit the spec associated with a buffer.
+;;
+(defun sgmls-edit-spec ()
+  "Edit the SGMLS spec associated with a buffer.
+If the local variable `sgmls-spec' is set, the file will be loaded with
+`find-file-other-window'; otherwise, an error will be signaled."
+  (interactive)
+  (if sgmls-spec
+      (find-file-other-window
+       (expand-file-name sgmls-spec sgmls-spec-directory))
+    (error "No spec is currently assigned (see `sgmls-spec').")))
+     
+
+;;
+;; Actually run sgmls and the sgmls post-processor.
+;;
+(defun sgmls-start-process (command buffer)
+  "Run an SGMLS command, placing its output into the given buffer.
+The command should be a string which will be passed to the shell."
+  (save-some-buffers)
+  (let ((old-buffer (current-buffer))
+       (parser-error-file sgmls::parser-error-file)
+       (postprocessor-error-file sgmls::postprocessor-error-file)
+       (before-hooks before-sgmls-hooks)
+       (after-hooks after-sgmls-hooks)
+       proc)
+    (set-buffer buffer)
+    (display-buffer buffer)
+    (setq sgmls::parser-error-file parser-error-file)
+    (setq sgmls::postprocessor-error-file postprocessor-error-file)
+    (setq before-sgmls-hooks before-hooks)
+    (setq after-sgmls-hooks after-hooks)
+    (if (and (> (point-max) (point-min))
+            (yes-or-no-p 
+             (format "Discard current contents of buffer %s? "
+                     (buffer-name buffer))))
+       (erase-buffer))
+    (goto-char (point-max))
+    (run-hooks 'before-sgmls-hooks)
+    (set-buffer old-buffer)
+    (setq proc (start-process "sgmls" 
+                             buffer 
+                             "nice"
+                             shell-file-name 
+                             "-c" 
+                             command))
+    (set-process-sentinel proc (function sgmls::process-sentinel))
+    (message "Converting from %s to %s (process: %s)..."
+            (file-name-nondirectory sgmls-source-file)
+            (file-name-nondirectory sgmls-output-file)
+            (process-name proc))
+    proc))
+
+
+\f
+;;;; Internal functions.
+
+;;
+;; Sentinel for end of program run.
+;;
+(defun sgmls::process-sentinel (proc message)
+  (let ((old-buffer (current-buffer))
+       (stat (process-status proc))
+       msg)
+    (unwind-protect
+       (progn
+         (set-buffer (process-buffer proc))
+         (cond ((eq stat 'exit)
+                (setq msg
+                      (format 
+                       "SGMLS: process \"%s\" finished with status %d." 
+                       (process-name proc)
+                       (process-exit-status proc)))
+                (goto-char (point-min))
+                (run-hooks 'after-sgmls-hooks)
+                (display-buffer (process-buffer proc)))
+               ((or (eq stat 'signal) (eq stat 'closed))
+                (error "SGMLS: %S %s." proc message)))
+         (sgmls::check-error-files proc
+                                   sgmls::parser-error-file
+                                   sgmls::postprocessor-error-file))
+    (delete-file sgmls::parser-error-file)
+    (delete-file sgmls::postprocessor-error-file)
+    (set-buffer old-buffer)
+    (if msg (message msg)))))
+
+;;
+;; Check whether there is anything in the error files.
+;;
+(defun sgmls::check-error-files (proc parser-file postprocessor-file)
+  (let ((old-buffer (current-buffer))
+       (parser-buffer 
+        (get-buffer-create (concat "**"
+                                   (buffer-name
+                                    (process-buffer proc))
+                                   ": parser errors**")))
+       (postprocessor-buffer
+        (get-buffer-create (concat "**"
+                                   (buffer-name
+                                    (process-buffer proc))
+                                   ": postprocessor errors**")))
+       window)
+    (set-buffer parser-buffer)
+    (erase-buffer)
+    (insert-file parser-file)
+    (if (> (point-max) (point-min))
+       (setq window (display-buffer parser-buffer))
+      (kill-buffer parser-buffer))
+    (if window
+       (set-window-dedicated-p window t))
+    (set-buffer postprocessor-buffer)
+    (erase-buffer)
+    (insert-file postprocessor-file)
+    (if (> (point-max) (point-min))
+       (display-buffer postprocessor-buffer)
+      (kill-buffer postprocessor-buffer))
+    (set-buffer old-buffer)
+    (cond (window
+          (set-window-dedicated-p window nil)
+          (balance-windows)))))
+
+;;
+;; Generate a declaration to use for sgmls.  By default, return the
+;; empty string unless `sgmls-decl' or `sgml-declaration' is set to
+;; something.  Flag currently has no effect.
+;;
+(defun sgmls::generate-declaration ()
+  (cond (sgmls-declaration)
+       ((and (boundp 'sgml-declaration) sgml-declaration) sgml-declaration)
+       (t "")))
+
+;;
+;; Return the name of a source file to use.  Will try
+;; `sgml-parent-document' (from psgml.el) first, then will look for
+;; the buffer's file name, then will prompt only if all else fails.
+;;
+(defun sgmls::generate-source-file ()
+  (cond ((boundp 'sgmls-parent-document)
+        (if (consp sgml-parent-document)
+            (setq sgmls-source-file (car sgml-parent-document))
+          (setq sgmls-source-file sgml-parent-document)))
+       (t (setq sgmls-source-file 
+                (file-name-nondirectory (buffer-file-name)))))
+  sgmls-source-file)
+
+;;
+;; Return the name of a spec to use.
+;;
+(defun sgmls::generate-spec (flag)
+  (let ((buffer-file-name nil))
+    (if sgmls-spec-directory
+       (setq sgmls-spec-directory 
+             (file-name-as-directory sgmls-spec-directory)))
+    (if (or flag (null sgmls-spec))
+       (setq sgmls-spec
+             (read-file-name 
+              "SGMLS spec: "
+              (if sgmls-spec
+                  (file-name-directory sgmls-spec)
+                sgmls-spec-directory)
+              nil
+              1
+              (if sgmls-spec
+                  (file-name-nondirectory sgmls-spec)))))
+    (if (and (file-readable-p sgmls-spec)
+            (not (file-directory-p sgmls-spec)))
+       sgmls-spec
+      (if (and (file-readable-p 
+               (expand-file-name sgmls-spec sgmls-spec-directory))
+              (not (file-directory-p
+                    (expand-file-name sgmls-spec sgmls-spec-directory))))
+         (setq sgmls-spec (expand-file-name sgmls-spec sgmls-spec-directory))
+       (error "SGMLS spec \"%s\" is not readable or is a directory." 
+              sgmls-spec)))))
+
+;;
+;; Return the name of a temporary file to use for recording errors
+;; from the parser or the postprocessor.
+;;
+(defun sgmls::generate-parser-error-file ()
+  (setq sgmls::parser-error-file 
+       (make-temp-name "/tmp/sgmlspa")))
+
+;;
+;; Return the name of a file for SGMLS postprocessor output.
+;;
+(defun sgmls::generate-output-file (flag)
+
+  ;; Try to set up default values.
+  (if (and (not sgmls-output-file)
+          sgmls-output-file-ext 
+          (buffer-file-name)
+          (or (string-match "^\\(.*\\)\\(\\.[^.]*\\)$" (buffer-file-name))
+              (string-match "^\\(.+\\)$" (buffer-file-name))))
+      (setq sgmls-output-file
+           (expand-file-name
+            (concat (substring (buffer-file-name)
+                               (match-beginning 1)
+                               (match-end 1))
+                    "."
+                    sgmls-output-file-ext))))
+
+  ;; Prompt if necessary.
+  (setq sgmls-output-file
+       (read-file-name "SGMLS output file: "
+                       nil
+                       sgmls-output-file
+                       nil
+                       (if sgmls-output-file
+                           (file-name-nondirectory 
+                            sgmls-output-file))))
+
+  (if (string= (expand-file-name sgmls-source-file)
+              (expand-file-name sgmls-output-file))
+      (progn
+       (setq sgmls-output-file nil)
+       (error "SGMLS: source file and output file are the same.")))
+
+  sgmls-output-file)
+
+;;
+;; Generate the name of a temporary file to use for postprocessor errors.
+;;
+(defun sgmls::generate-postprocessor-error-file ()
+  (setq sgmls::postprocessor-error-file 
+       (make-temp-name (concat "/tmp/sgmlspp"))))
+
+(provide 'sgmls)
diff --git a/packaging/perl-SGMLSpm.changes b/packaging/perl-SGMLSpm.changes
new file mode 100644 (file)
index 0000000..76da9e0
--- /dev/null
@@ -0,0 +1,75 @@
+* Fri Aug 31 19:28:21 UTC 2012 - tracy.graydon@intel.com
+- TIVI-153: add as dependency for iputils. Imported from MeeGo trunk 
+
+* Wed Feb 27 2008 Tom "spot" Callaway <tcallawa@redhat.com> - 1.03ii-18
+- Rebuild for perl 5.10 (again)
+
+* Fri Jan 25 2008 Tom "spot" Callaway <tcallawa@redhat.com> - 1.03ii-17
+- rebuild for new perl
+
+* Thu Oct 26 2007 Ondrej Vasik <ovasik@redhat.com> - 1.03ii-16.4
+- added base documentation
+- fixed indents
+
+* Mon Oct 22 2007 Ondrej Vasik <ovasik@redhat.com> - 1.03ii-16.3
+- added dist tag
+- License to GPL+
+- spec file cleanup (all things from merge review by pnemade #226278)
+
+* Wed Jul 12 2006 Jesse Keating <jkeating@redhat.com> - 1.03ii-16.2.1
+- rebuild
+
+* Fri Feb 03 2006 Jason Vas Dias <jvdias@redhat.com> - 1.03ii-16.2
+- rebuild for new perl-5.8.8
+
+* Fri Dec 16 2005 Jesse Keating <jkeating@redhat.com>
+- rebuilt for new gcc
+
+* Fri Dec 16 2005 Jesse Keating <jkeating@redhat.com>
+- rebuilt for new gcj
+
+* Sat Apr 30 2005 Jose Pedro Oliveira <jpo at di.uminho.pt> - 1.03ii-15
+- Specfile cleanup. (#156483)
+
+* Wed Sep 22 2004 Than Ngo <than@redhat.com>
+- rebuilt
+
+* Fri Feb 13 2004 Elliot Lee <sopwith@redhat.com>
+- rebuilt
+
+* Wed May 28 2003 Tim Waugh <twaugh@redhat.com> 1.03ii-12
+- Use vendorlib not sitelib (bug #73493).
+- Own %%{perldir}/SGMLS (bug #73922).
+
+* Tue Jan 28 2003 Tim Waugh <twaugh@redhat.com> 1.03ii-11
+- Rebuilt.
+
+* Wed Jan 22 2003 Tim Powers <timp@redhat.com>
+- rebuilt
+
+* Sat Dec 14 2002 Tim Powers <timp@redhat.com> 
+- don't use rpms internal dep generator
+
+* Mon Nov 25 2002 Tim Waugh <twaugh@redhat.com> 1.03ii-9
+- Fix URL (bug #71895).
+
+* Mon Nov 25 2002 Tim Waugh <twaugh@redhat.com> 1.03ii-8
+- Rebuild to get automatic provides: right.
+
+* Wed Nov 20 2002 Tim Powers <timp@redhat.com> 1.03ii-7
+- rebuild in current collinst
+
+* Mon Jun 17 2002 Tim Waugh <twaugh@redhat.com> 1.03ii-6
+- Rebuild in new environment.
+
+* Sun Jan 14 2001 Tim Waugh <twaugh@redhat.com> 1.03ii-5
+- Add defattr to files section.
+
+* Mon Jan 08 2001 Tim Waugh <twaugh@redhat.com>
+- Change group.
+- rm before install.
+- Change Copyright: to License:.
+- Remove Packager: line.
+
+* Mon Jan 08 2001 Tim Waugh <twaugh@redhat.com>
+- Based on Eric Bischoff's new-trials packages.
diff --git a/packaging/perl-SGMLSpm.spec b/packaging/perl-SGMLSpm.spec
new file mode 100644 (file)
index 0000000..f9d4203
--- /dev/null
@@ -0,0 +1,46 @@
+#specfile originally created for Fedora, modified for Moblin Linux
+Name:           perl-SGMLSpm
+Version:        1.03ii
+Release:        18
+Summary:        Perl library for parsing the output of nsgmls
+
+Group:          Development/Libraries
+License:        GPLv2+
+URL:            http://search.cpan.org/dist/SGMLSpm/
+Source0:        http://www.cpan.org/authors/id/D/DM/DMEGG/SGMLSpm-%{version}.tar.gz
+BuildRoot:      %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
+
+BuildArch:      noarch
+BuildRequires:  perl
+Requires:  perl(:MODULE_COMPAT_%(eval "`%{__perl} -V:version`"; echo $version))
+Requires:       openjade
+
+%description
+Perl programs can use the SGMLSpm module to help convert SGML, HTML or XML
+documents into new formats.
+
+
+%prep
+%setup -q -n SGMLSpm
+
+%build
+
+%install
+rm -rf $RPM_BUILD_ROOT
+install -d -m 755 $RPM_BUILD_ROOT{%{_bindir},%{perl_vendorlib}}
+make install_system \
+    BINDIR=$RPM_BUILD_ROOT%{_bindir} \
+    PERL5DIR=$RPM_BUILD_ROOT%{perl_vendorlib}
+
+%clean
+rm -rf $RPM_BUILD_ROOT
+
+
+%files
+%defattr(-,root,root,-)
+%doc README COPYING
+%{_bindir}/sgmlspl
+%{perl_vendorlib}/SGMLS*
+%{perl_vendorlib}/skel.pl
+
+
diff --git a/sgmlspl.pl b/sgmlspl.pl
new file mode 100755 (executable)
index 0000000..c91a6cb
--- /dev/null
@@ -0,0 +1,317 @@
+#!/usr/bin/perl
+########################################################################
+# sgmlspl: a simple SGML postprocesser for the SGMLS and NSGMLS
+#          parsers (requires SGMLS.pm library).
+#
+# Copyright (c) 1995 by David Megginson <dmeggins@aix1.uottawa.ca>
+#
+# 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 2 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
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# 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, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+# $Log: sgmlspl.pl,v $
+# Revision 1.8  1995/12/03  21:46:31  david
+# Eliminated all use of the SGMLS_Event::key method.
+#
+# Revision 1.7  1995/11/15  20:22:24  david
+# Changed "use Output" to "use SGMLS::Output".  Qualified the STDIN
+# filehandle for the SGMLS object with the main:: package name.
+#
+# Revision 1.6  1995/08/12  16:15:14  david
+# Revised version for 1.01 distribution.
+#
+# Revision 1.5  1995/04/27  11:52:25  david
+# Changed 'print' to 'main::output' for re handler; empty string
+# translates into an empty sub {} rather than a sub printing an empty
+# string; instead of evaluating every argument as a perl script, take
+# only the first as a perl script and the rest as its arguments; allow
+# empty scripts or scripts which do not end with '1;'; pass the event
+# itself as the second argument to each handler, after the event data.
+#
+# Revision 1.4  1995/04/23  14:44:58  david
+# Use the Output package.  Fixed the $version variable.
+#
+# Revision 1.3  1995/04/22  21:02:49  david
+# Added some missing 'last SWITCH;' statements in the sgmls function.
+#
+# Revision 1.2  1995/04/22  20:58:48  david
+# Added $SGMLS_PL::version variable and changed SDATA notation from
+# [SDATA] to |SDATA|.
+#
+# Revision 1.1  1995/04/22  14:40:50  david
+# Initial revision
+#
+########################################################################
+
+use SGMLS::Output;
+
+package SGMLS_PL;
+use SGMLS;
+
+$version = '$Id: sgmlspl.pl,v 1.8 1995/12/03 21:46:31 david Exp $';
+
+#
+# Set up handler defaults.
+#
+$start_document_handler = sub {};
+$end_document_handler = sub {};
+$start_element_handlers = { '' => sub {} };
+$end_element_handlers = { '' => sub {} };
+$cdata_handler = sub { main::output($_[0]); };
+$sdata_handlers = { '' => sub { main::output($_[0]);} };
+$re_handler = sub { main::output("\n"); };
+$pi_handler = sub { '' => sub {} };
+$entity_handlers = { '' => sub {} };
+$start_subdoc_handlers = { '' => sub {} };
+$end_subdoc_handlers = { '' => sub {} };
+$conforming_handler = sub {};
+
+#
+# Main access point: declare handlers for different SGML events.
+#
+# Usage: sgml(event, handler);
+#
+# The event may be one of the following strings, or a special pattern.
+# The generic events are as follow:
+#
+#   'start'                 The beginning of the document.
+#   'end'                   The end of the document.
+#   'start_element'         The beginning of an element.
+#   'end_element'           The end of an element.
+#   'cdata'                 Regular character data.
+#   'sdata'                 Special system-specific data.
+#   're'                    A record-end.
+#   'pi'                    A processing instruction.
+#   'entity'                An external-entity reference.
+#   'start_subdoc'          The beginning of a subdocument entity.
+#   'end_subdoc'            The end of a subdocument entity.
+#   'conforming'            The document is conforming.
+#
+# In addition to these generic events, it is possible to handlers
+# for certain specific, named events, as follow:
+#
+#   '<GI>'                  The beginning of element GI.
+#   '</GI>'                 The end of element GI.
+#   '[SDATA]'               The system-specific data SDATA.
+#   '&ENAME;'               A reference to the external entity ENAME.
+#   '{ENAME}'               The beginning of the subdocument-entity ENAME.
+#   '{/ENAME}'              The end of the subdocument-entity ENAME.
+#
+#
+# The handler may be a string, which will simply be printed when the
+# event occurs (this is usually useful only for the specific, named
+# events), or a reference to an anonymous subroutine, which will
+# receive two arguments: the event data and the event itself.  For 
+# example,
+#
+#   sgml('<FOO>', "\n\\begin{foo}\n");
+#
+# and
+#
+#   sgml('<FOO>', sub { output("\n\\begin{foo}\n"); });
+#
+# will have identical results.
+#
+sub main::sgml {
+    my ($spec,$handler) = (@_);
+    if (ref($handler) ne 'CODE') {
+       $handler =~ s/\\/\\\\/g;
+       $handler =~ s/'/\\'/g;
+       if ($handler eq '') {
+           $handler = sub {};
+       } else {
+           $handler = eval "sub { main::output('$handler'); };";
+       }
+    }
+  SWITCH: {
+                               # start-document handler
+      $spec eq 'start' && do {
+         $start_document_handler = $handler;
+         last SWITCH;
+      };
+                               # end-document handler
+      $spec eq 'end' && do {
+         $end_document_handler = $handler;
+         last SWITCH;
+      };
+                               # start-element handler
+      $spec =~ /^<([^\/].*|)>$/ && do {
+         $start_element_handlers->{$1} = $handler;
+         last SWITCH;
+      };
+                               # generic start-element handler
+      $spec eq 'start_element' && do {
+         $start_element_handlers->{''} = $handler;
+         last SWITCH;
+      };
+                               # end-element handler
+      $spec =~ /^<\/(.*)>$/ && do {
+         $end_element_handlers->{$1} = $handler;
+         last SWITCH;
+      };
+                               # generic end-element handler
+      $spec =~ 'end_element' && do {
+         $end_element_handlers->{''} = $handler;
+         last SWITCH;
+      };
+                               # cdata handler
+      $spec eq 'cdata' && do {
+         $cdata_handler = $handler;
+         last SWITCH;
+      };
+                               # sdata handler
+      $spec =~ /^\|(.*)\|$/ && do {
+         $sdata_handlers->{$1} = $handler;
+         last SWITCH;
+      };
+                               # generic sdata handler
+      $spec eq 'sdata' && do {
+         $sdata_handlers->{''} = $handler;
+         last SWITCH;
+      };
+                               # record-end handler
+      $spec eq 're' && do {
+         $re_handler = $handler;
+         last SWITCH;
+      };
+                               # processing-instruction handler
+      $spec eq 'pi' && do {
+         $pi_handler = $handler;
+         last SWITCH;
+      };
+                               # entity-reference handler
+      $spec =~ /^\&(.*);$/ && do {
+         $entity_handlers->{$1} = $handler;
+         last SWITCH;
+      };
+                               # generic entity-reference handler
+      $spec eq 'entity' && do {
+         $entity_handlers->{''} = $handler;
+         last SWITCH;
+      };
+                               # start-subdoc handler
+      $spec =~ /^\{([^\/].*|)\}$/ && do {
+         $start_subdoc_handlers->{$1} = $handler;
+         last SWITCH;
+      };
+                               # generic start-subdoc handler
+      $spec eq 'start_subdoc' && do {
+         $start_subdoc_handlers->{''} = $handler;
+         last SWITCH;
+      };
+                               # end-subdoc handler
+      $spec =~ /^\{\/(.*)\}$/ && do {
+         $end_subdoc_handlers->{$1} = $handler;
+         last SWITCH;
+      };
+                               # generic end-subdoc handler
+      $spec eq 'end_subdoc' && do {
+         $end_subdoc_handlers->{''} = $handler;
+         last SWITCH;
+      };
+                               # conforming handler
+      $spec eq 'conforming' && do {
+         $conforming_handler = $handler;
+         last SWITCH;
+      };
+
+      die "Bad SGML handler pattern: $spec\n";
+  }
+}
+
+
+#
+# The first argument on the command line is a perl module which will be
+# read here and evaluated in the 'main' package -- everything else will
+# be an argument to it.
+#
+package main;
+
+$ARGV = shift;
+unless ($ARGV eq '' || do $ARGV) {
+    if (!-e $ARGV) {
+       die "FATAL: $ARGV does not exist.\n";
+    } elsif (!-r $ARGV) {
+       die "FATAL: $ARGV exists but is read-protected.\n";
+    } elsif ($@) {
+       die "FATAL: $@\n";
+    }
+}
+
+
+#
+# Do the actual work, using the SGMLS package.
+#
+package SGMLS_PL;
+
+$parse = new SGMLS(main::STDIN);       # a new parse object
+
+&{$start_document_handler}();  # run the start handler.
+
+                               # run the appropriate handler for each
+                               # event
+while ($event = $parse->next_event) {
+    my $type = $event->type;
+  SWITCH: {
+      $type eq 'start_element' && do {
+         &{($start_element_handlers->{$event->data->name}||
+               $start_element_handlers->{''} || sub {})}($event->data,$event);
+         last SWITCH;
+      };
+      $type eq 'end_element' && do {
+         &{($end_element_handlers->{$event->data->name}||
+               $end_element_handlers->{''} || sub {})}($event->data,$event);
+         last SWITCH;
+      };
+      $type eq 'cdata' && do {
+         &{$cdata_handler}($event->data,$event);
+         last SWITCH;
+      };
+      $type eq 'sdata' && do {
+         &{($sdata_handlers->{$event->data}||
+            $sdata_handlers->{''} || sub {})}($event->data,$event);
+         last SWITCH;
+      };
+      $type eq 're' && do {
+         &{$re_handler}($event->data,$event);
+         last SWITCH;
+      };
+      $type eq 'pi' && do {
+         &{$pi_handler}($event->data,$event);
+         last SWITCH;
+      };
+      $type eq 'entity' && do {
+         &{($entity_handlers->{$event->data->name}||
+            $entity_handlers->{''} || sub {})}($event->data,$event);
+         last SWITCH;
+      };
+      $type eq 'start_subdoc' && do {
+         &{($start_subdoc_handlers->{$event->data->name}||
+            $start_subdoc_handlers->{''} || sub {})}($event->data,$event);
+         last SWITCH;
+      };
+      $type eq 'end_subdoc' && do {
+         &{($end_subdoc_handlers->{$event->data->name}||
+            $end_subdoc_handlers->{''} || sub {})}($event->data,$event);
+         last SWITCH;
+      };
+      $type eq 'conforming' && do {
+         &{$conforming_handler}($event->data,$event);
+         last SWITCH;
+      };
+
+      die "Unknown SGML event type: $type\n";
+  }
+}
+                               
+&{$end_document_handler}();    # run the end handler
diff --git a/skel.pl b/skel.pl
new file mode 100644 (file)
index 0000000..f10c1ff
--- /dev/null
+++ b/skel.pl
@@ -0,0 +1,178 @@
+########################################################################
+# skel.pl: an SGMLSPL script for producing scripts (!!).
+#
+# Copyright (c) 1995 by David Megginson <dmeggins@aix1.uottawa.ca>
+#
+# 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 2 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
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# 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, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+#
+# Changes:
+#
+# $Log: skel.pl,v $
+# Revision 1.4  1995/11/15  20:21:07  david
+# Changed "use Output" to "use SGMLS::Output".
+#
+# Revision 1.3  1995/08/24  15:04:38  david
+# Fixed commented-out 're' handler.
+#
+# Revision 1.2  1995/08/12  16:16:42  david
+# Revised version for 1.01 distribution.
+#
+# Revision 1.1  1995/04/23  14:49:35  david
+# Initial revision
+#
+########################################################################
+
+use SGMLS;
+use SGMLS::Output;
+
+$version = '$Id: skel.pl,v 1.4 1995/11/15 20:21:07 david Exp $';
+
+%subdocs = ();                 # Subdocument entities seen so far.
+%entities = ();                        # External data entities seen so far.
+%sdata = ();                   # SDATA strings seen so far.
+%elements = ();                        # Elements seen so far.
+$pi = 0;                       # Any processing instructions?
+
+$intro = 0;                    # Have we printed the banner yet?
+
+$| = 1;
+
+sgml('end_element', '');       # Ignore the ends of elements.
+sgml('end_subdoc', '');                # Ignore the ends of subdocument entities.
+sgml('cdata', '');             # Ignore CDATA.
+sgml('re', '');                        # Ignore Record Ends.
+
+                               # Note any processing instructions.
+sgml('pi', sub { $pi = 1; });
+
+                               # Keep track of all subdocument entities.
+sgml('start_subdoc', sub {
+    my $entity = shift;
+    $entities{$entity->name} = 1;
+});
+                               # Keep track of all external data entities.
+sgml('entity', sub {
+    my $entity = shift;
+    $entities{$entity->name} = 1;
+});
+                               # Keep track of all SDATA strings
+sgml('sdata', sub {
+    my $sdata = shift;
+    $sdata{$sdata} = 1;
+});
+
+                               # Display element handlers as they appear.
+sgml('start_element', sub {
+    my $element = shift;
+    unless ($intro) {
+       $intro = 1;
+       do_intro($element->name);
+    }
+    if (!$elements{$element->name}) {
+       output "# Element: " . $element->name . "\n";
+       output "sgml('<" . $element->name . ">', \"\");\n";
+       output "sgml('</" . $element->name . ">', \"\");\n\n";
+       $elements{$element->name} = 1;
+    }
+});
+
+sgml('end', sub {
+                               # generate subdoc handlers
+    my @keys = keys(%subdocs);
+    if ($#keys > 0) {
+       output "#\n# Subdocument Entity Handlers\n#\n\n";
+        foreach (@keys) {
+           output "# Subdocument Entity: $_\n";
+           output "sgml('{" . $_ . "}', \"\");\n";
+           output "sgml('{/" . $_ . "}', \"\");\n\n";
+       }
+    }
+                               # generate entity handlers
+    my @keys = keys(%entities);
+    if ($#keys > 0) {
+       output "#\n# External Data Entity Handlers\n#\n\n";
+        foreach (@keys) {
+           output "sgml('&" . $_ . ";', \"\");\n";
+       }
+    }
+                               # generate sdata handlers
+    my @keys = keys(%sdata);
+    if ($#keys > 0) {
+       output "#\n# SDATA Handlers\n#\n\n";
+        foreach (@keys) {
+           output "sgml('|" . $_ . "|', \"\");\n";
+       }
+    }
+
+    if ($pi) {
+       output "#\n# Processing-Instruction Handler\n#\n";
+       output "sgml('pi', sub {});\n\n";
+    }
+
+    output <<END;
+#
+# Default handlers (uncomment these if needed).  Right now, these are set
+# up to gag on any unrecognised elements, sdata, processing-instructions,
+# or entities.
+#
+# sgml('start_element',sub { die "Unknown element: " . \$_[0]->name; });
+# sgml('end_element','');
+# sgml('cdata',sub { output \$_[0]; });
+# sgml('sdata',sub { die "Unknown SDATA: " . \$_[0]; });
+# sgml('re',"\\n");
+# sgml('pi',sub { die "Unknown processing instruction: " . \$_[0]; });
+# sgml('entity',sub { die "Unknown external entity: " . \$_[0]->name; });
+# sgml('start_subdoc',sub { die "Unknown subdoc entity: " . \$_[0]->name; });
+# sgml('end_subdoc','');
+# sgml('conforming','');
+
+1;
+END
+});
+
+
+
+                               # Function to print the banner.
+sub do_intro {
+    my $doctype = shift;
+    output <<END;
+########################################################################
+# SGMLSPL script produced automatically by the script sgmlspl.pl
+#
+# Document Type: $doctype
+# Edited by: 
+########################################################################
+
+use SGMLS;                     # Use the SGMLS package.
+use SGMLS::Output;             # Use stack-based output.
+
+#
+# Document Handlers.
+#
+sgml('start', sub {});
+sgml('end', sub {});
+
+#
+# Element Handlers.
+#
+
+END
+}
+
+1;
+        
+    
+
diff --git a/test-SGMLS.pl b/test-SGMLS.pl
new file mode 100644 (file)
index 0000000..f18f972
--- /dev/null
@@ -0,0 +1,13 @@
+use SGMLS;
+
+$\ = "\n";
+
+$parse = new SGMLS(STDIN);
+
+while ($event = $parse->next_event) {
+    print "Event type: " . $event->type;
+    print "Data: " . $event->data;
+    print "File: " . $event->file || "[unavailable]";
+    print "Line: " . $event->line || "[unavailable]";
+    print "";
+}