summaryrefslogtreecommitdiffstats
path: root/contrib/texinfo
diff options
context:
space:
mode:
authorjmacd <jmacd@FreeBSD.org>1997-01-11 02:12:38 +0000
committerjmacd <jmacd@FreeBSD.org>1997-01-11 02:12:38 +0000
commit58ff11de31aa3832448101bc51ddf144fd5a29b4 (patch)
treecc1b5b231b9a50d0219c9921e490665c5cea9eca /contrib/texinfo
downloadFreeBSD-src-58ff11de31aa3832448101bc51ddf144fd5a29b4.zip
FreeBSD-src-58ff11de31aa3832448101bc51ddf144fd5a29b4.tar.gz
This is unmodified GNU texinfo-3.9 source. I'll be commiting a few
patches in a bit. -josh
Diffstat (limited to 'contrib/texinfo')
-rw-r--r--contrib/texinfo/COPYING339
-rw-r--r--contrib/texinfo/ChangeLog2346
-rw-r--r--contrib/texinfo/INSTALL181
-rw-r--r--contrib/texinfo/INTRODUCTION119
-rw-r--r--contrib/texinfo/Makefile.in211
-rw-r--r--contrib/texinfo/NEWS93
-rw-r--r--contrib/texinfo/README163
-rw-r--r--contrib/texinfo/TODO35
-rwxr-xr-xcontrib/texinfo/configure1876
-rw-r--r--contrib/texinfo/configure.in42
-rw-r--r--contrib/texinfo/dir16
-rw-r--r--contrib/texinfo/dir-example309
-rw-r--r--contrib/texinfo/emacs/Makefile.in88
-rw-r--r--contrib/texinfo/emacs/detexinfo.el250
-rwxr-xr-xcontrib/texinfo/emacs/elisp-comp7
-rw-r--r--contrib/texinfo/emacs/info.el1846
-rw-r--r--contrib/texinfo/emacs/informat.el429
-rw-r--r--contrib/texinfo/emacs/makeinfo.el247
-rw-r--r--contrib/texinfo/emacs/new-useful-setqs180
-rw-r--r--contrib/texinfo/emacs/texinfmt.el3979
-rw-r--r--contrib/texinfo/emacs/texinfo.el932
-rw-r--r--contrib/texinfo/emacs/texnfo-tex.el346
-rw-r--r--contrib/texinfo/emacs/texnfo-upd.el2058
-rw-r--r--contrib/texinfo/info/Makefile.in227
-rw-r--r--contrib/texinfo/info/NEWS200
-rw-r--r--contrib/texinfo/info/README37
-rw-r--r--contrib/texinfo/info/clib.c112
-rw-r--r--contrib/texinfo/info/clib.h42
-rw-r--r--contrib/texinfo/info/dir.c273
-rw-r--r--contrib/texinfo/info/display.c561
-rw-r--r--contrib/texinfo/info/display.h76
-rw-r--r--contrib/texinfo/info/doc.h58
-rw-r--r--contrib/texinfo/info/dribble5
-rw-r--r--contrib/texinfo/info/dribble.c71
-rw-r--r--contrib/texinfo/info/dribble.h41
-rw-r--r--contrib/texinfo/info/echo_area.c1508
-rw-r--r--contrib/texinfo/info/echo_area.h63
-rw-r--r--contrib/texinfo/info/filesys.c617
-rw-r--r--contrib/texinfo/info/filesys.h84
-rw-r--r--contrib/texinfo/info/footnotes.c265
-rw-r--r--contrib/texinfo/info/footnotes.h46
-rw-r--r--contrib/texinfo/info/gc.c95
-rw-r--r--contrib/texinfo/info/gc.h36
-rw-r--r--contrib/texinfo/info/general.h94
-rw-r--r--contrib/texinfo/info/indices.c667
-rw-r--r--contrib/texinfo/info/indices.h39
-rw-r--r--contrib/texinfo/info/info-stnd.texi1365
-rw-r--r--contrib/texinfo/info/info-utils.c672
-rw-r--r--contrib/texinfo/info/info-utils.h140
-rw-r--r--contrib/texinfo/info/info.1229
-rw-r--r--contrib/texinfo/info/info.c565
-rw-r--r--contrib/texinfo/info/info.h100
-rw-r--r--contrib/texinfo/info/info.texi916
-rw-r--r--contrib/texinfo/info/infodoc.c771
-rw-r--r--contrib/texinfo/info/infomap.c274
-rw-r--r--contrib/texinfo/info/infomap.h82
-rw-r--r--contrib/texinfo/info/m-x.c195
-rw-r--r--contrib/texinfo/info/makedoc.c481
-rw-r--r--contrib/texinfo/info/man.c643
-rw-r--r--contrib/texinfo/info/man.h36
-rw-r--r--contrib/texinfo/info/nodemenu.c329
-rw-r--r--contrib/texinfo/info/nodes.c1207
-rw-r--r--contrib/texinfo/info/nodes.h168
-rw-r--r--contrib/texinfo/info/search.c519
-rw-r--r--contrib/texinfo/info/search.h75
-rw-r--r--contrib/texinfo/info/session.c4263
-rw-r--r--contrib/texinfo/info/session.h146
-rw-r--r--contrib/texinfo/info/signals.c173
-rw-r--r--contrib/texinfo/info/signals.h89
-rw-r--r--contrib/texinfo/info/termdep.h76
-rw-r--r--contrib/texinfo/info/terminal.c769
-rw-r--r--contrib/texinfo/info/terminal.h129
-rw-r--r--contrib/texinfo/info/tilde.c376
-rw-r--r--contrib/texinfo/info/tilde.h58
-rw-r--r--contrib/texinfo/info/userdoc.texi1270
-rw-r--r--contrib/texinfo/info/variables.c272
-rw-r--r--contrib/texinfo/info/variables.h64
-rw-r--r--contrib/texinfo/info/window.c1482
-rw-r--r--contrib/texinfo/info/window.h229
-rw-r--r--contrib/texinfo/info/xmalloc.c80
-rwxr-xr-xcontrib/texinfo/install-sh250
-rw-r--r--contrib/texinfo/libtxi/Makefile.in82
-rw-r--r--contrib/texinfo/libtxi/alloca.c504
-rw-r--r--contrib/texinfo/libtxi/bzero.c44
-rw-r--r--contrib/texinfo/libtxi/getopt.c762
-rw-r--r--contrib/texinfo/libtxi/getopt.h129
-rw-r--r--contrib/texinfo/libtxi/getopt1.c180
-rw-r--r--contrib/texinfo/libtxi/memcpy.c20
-rw-r--r--contrib/texinfo/libtxi/memmove.c24
-rw-r--r--contrib/texinfo/libtxi/strdup.c43
-rw-r--r--contrib/texinfo/makeinfo/Makefile.in112
-rw-r--r--contrib/texinfo/makeinfo/macro.texi177
-rw-r--r--contrib/texinfo/makeinfo/makeinfo.c9349
-rw-r--r--contrib/texinfo/makeinfo/makeinfo.h193
-rw-r--r--contrib/texinfo/makeinfo/makeinfo.texi303
-rw-r--r--contrib/texinfo/makeinfo/multi.c418
-rw-r--r--contrib/texinfo/texinfo.tex4692
-rw-r--r--contrib/texinfo/texinfo.texi16886
-rw-r--r--contrib/texinfo/util/Makefile.in101
-rw-r--r--contrib/texinfo/util/deref.c238
-rwxr-xr-xcontrib/texinfo/util/fixfonts84
-rwxr-xr-xcontrib/texinfo/util/gen-dir-node176
-rw-r--r--contrib/texinfo/util/install-info.c1111
-rwxr-xr-xcontrib/texinfo/util/mkinstalldirs40
-rwxr-xr-xcontrib/texinfo/util/tex3patch71
-rwxr-xr-xcontrib/texinfo/util/texi2dvi364
-rw-r--r--contrib/texinfo/util/texindex.c1793
107 files changed, 77698 insertions, 0 deletions
diff --git a/contrib/texinfo/COPYING b/contrib/texinfo/COPYING
new file mode 100644
index 0000000..916d1f0
--- /dev/null
+++ b/contrib/texinfo/COPYING
@@ -0,0 +1,339 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ 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.
+
+ 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.)
+
+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.
+
+ 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.
+
+ 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
+
+ Appendix: 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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/contrib/texinfo/ChangeLog b/contrib/texinfo/ChangeLog
new file mode 100644
index 0000000..06d0464
--- /dev/null
+++ b/contrib/texinfo/ChangeLog
@@ -0,0 +1,2346 @@
+Fri Oct 4 07:49:49 1996 Karl Berry <karl@cs.umb.edu>
+
+ * Version 3.9.
+
+ * Makefile.in (install): Say to install texinfo.tex manually.
+
+ * util/texi2dvi,
+ * util/texindex.c,
+ * makeinfo/makeinfo.c,
+ * info/info.c: Include only the current year in the copyright message.
+
+ * util/texi2dvi: Exit successfully.
+ From: Andreas Schwab <schwab@issan.informatik.uni-dortmund.de>.
+
+Thu Oct 3 12:58:32 1996 Karl Berry <karl@cs.umb.edu>
+
+ * Rename install.sh to the preferred install-sh.
+
+ * Makefile.in (VERSION),
+ * util/texi2dvi,
+ * util/texindex.c,
+ * util/install-info.c,
+ * makeinfo/makeinfo.c (minor_version, print_version_info),
+ * info/info.c: Update version number.
+
+ * util/texi2dvi: Only show diff if verbose.
+
+ * util/install-info.c (main): Check for a missing dir file as well
+ as a missing info files.
+ (main): At start of a node, completely initialize the newly-malloced
+ node structure.
+
+ * texinfo.texi: Fix incorrect uses of @key,
+ insert missing newline in Installing Dir Entries' @menu item,
+ document install-info invocation.
+
+ * Makefile.in (DISTFILES): Do not put .gdbinit's in distribution.
+ (dist): Use || instead of && (and invert sense) so make doesn't think
+ the command failed.
+ (dist): Exclude more junk.
+
+ * makeinfo/makeinfo.c (cm_xref): Back out patch from Tom T., since
+ we generate a good-enough error message that is suppressible
+ without it.
+
+ * util/gen-dir-node: The recommended name for the top-level info
+ file is dir, not dir.info.
+
+ * util/install-info.c (main): At `Mark the end of the Top node',
+ make sure the node name is non-NULL before comparing it. From
+ lvirden@cas.org.
+
+ * configure.in (AC_REPLACE_FUNCS): Use this for memcpy, memmove,
+ and strdup.
+ (AC_CHECK_FUNCS): Instead of this.
+ Because both bcopy and memmove are missing on the 3b2, as reported by
+ Gaylen Miller <gaylen@proaxis.com>, hence we must provide our own.
+ * libtxi/Makefile.in (LIBOBJS): New variable.
+ (OBJS): Include it.
+ * libtxi/memcpy.c, libtxi/memmove.c, libtxi/strdup.c: New files,
+ taken from fileutils 3.13.
+ * makeinfo/makeinfo.c,
+ * info/clib.c (strdup): Move to libtxi.
+
+Wed Oct 2 18:23:30 1996 Karl Berry <karl@cs.umb.edu>
+
+ * info/info-utils.h (memcpy) [!HAVE_MEMCPY],
+ * info/termdep.h (memcpy) [!HAVE_MEMCPY],
+ * makeinfo/makeinfo.c (memmove) [!HAVE_MEMMOVE]: Remove this
+ #ifdef, as we now include it in libtxi if missing.
+
+Tue Oct 1 17:41:52 1996 Karl Berry <karl@cs.umb.edu>
+
+ * makeinfo/Makefile.in (install),
+ * info/Makefile.in (install),
+ * Makefile.in (install): Use new option name --info-dir instead of
+ --infodir.
+
+ * makeinfo/multi.c (out_char): New fn. Replace all calls to
+ putc/fprintf with calls to this.
+
+ * util/install-info.c: Rename --infodir to info-dir.
+
+Mon Sep 30 10:07:21 1996 Karl Berry <karl@cs.umb.edu>
+
+ * Version 3.8.
+
+ * texinfo.tex: Untabify.
+
+ * texinfo.tex (\ptexl, \ptexL): Do not save, we have our own
+ commands now.
+ (\onepageout): Reformat for readability, and call \indexdummies
+ to avoid expansion of Texinfo commands (e.g., accents) in \write's.
+ (\,, \dotaccent, \ringaccent, \tieaccent, \ubaraccent, udotaccent,
+ \questiondown, \exclamdown, \dotless): New macros.
+ (\l): Let plain TeX definition remain, instead of switching
+ to ``lisp'' font.
+ (\multitable): Ensure space between the columns,
+ insert struts to make interline spacing constant,
+ use real strut instead of a box containing `Xy'.
+ (\indexdummies): Do not define \rm, \char, but
+ do define \@, \{, \}, \dotless, and \,. And \t should generate
+ \t, not \r.
+ (\indexnofonts): Define \, and \dotless as \indexdummyfont,
+ and let \@ be @.
+ (\doind): Reformat for readability, and use temp control sequence
+ names that actually make sense.
+ (\doublecolumnout, \pagesofar, \enddoublecolumns): Restore
+ Knuth's original code to avoid spurious overfull vbox messages.
+ (No boxes are actually overfull).
+ (\shortcontents): Do not allow hyphenations.
+ (\dochapentry, \tocentry): Make glue above and below flexible, to allow
+ better page breaks.
+ (\tex): Reset \, to its plain TeX meaning,
+ and do not reset \l.
+
+ * COPYING: Update for new FSF address (from gcc dist).
+
+ * libtxi/Makefile.in: Various simplifications.
+
+Sun Sep 29 12:58:44 1996 Karl Berry <karl@cs.umb.edu>
+
+ * util/texi2dvi: Use $progname instead of $0 for --version.
+
+ * util/install-info.c (xmalloc, xrealloc): Declare malloc and
+ realloc as returning void *,
+ to avoid ptr/int problems on Digital Unix.
+
+ * info/tilde.c (tilde_expand_word): Declare getenv as returning char *,
+ to avoid warning on Digital Unix.
+
+ * makeinfo/multi.c (multitable_active): Declare extern here to
+ avoid ld warning on rs6000.
+
+ * util/texindex.c (usage): Avoid ??' trigraph.
+
+ * util/install-info.c: Include <sys/fcntl.h> or <fnctl.h>,
+ according to HAVE_SYS_FCNTL_H,
+ and only include <sys/file.h> if HAVE_SYS_FILE_H.
+ (readlines): Oops, had NULL's and 0's reversed for ptr/int members.
+
+ * info/terminal.c (terminal_goto_xy): Remove spurious extra ;.
+
+ * util/install-info.c: Untabify. (input_sections): Initialize.
+ (find_lines): Initialize the terminating element of the array.
+ (print_help): Document --infodir.
+ (main): Compare the basename of infile sans .info to the dir entry,
+ not infile itself.
+ * util/Makefile.in (clean): Remove the install-info binary.
+
+ * info/Makefile.in (distclean): Remove *.info* files.
+
+ * Makefile.in (install),
+ * info/Makefile.in (install),
+ * makeinfo/Makefile.in (install): Use --infodir instead of --info-file.
+
+ * info/info.c,
+ * makeinfo/makeinfo.c: Avoid newlines in string constants for the
+ sake of SunOS cc.
+
+ * makeinfo/multi.c: Do not assume ANSI C.
+
+ * info/info.texi: Oops, need @end vtable for a @vtable.
+
+Sat Sep 28 16:31:28 1996 Karl Berry <karl@cs.umb.edu>
+
+ * Makefile.in (texinfo): Do not depend on sub-all, as then
+ makeinfo is always run. Instead, depend on texinfo.texi.
+
+ * makeinfo/Makefile.in (info, dvi): New targets.
+ makeinfo.info, makeinfo.dvi: Do not depend on macro.texi for now.
+
+ * info/Makefile.in (install): Must call install-info twice.
+
+ * info/info-stnd.texi,
+ * info/info.texi,
+ * makeinfo/makeinfo.texi: Include direntry.
+
+ * emacs/Makefile.in: Use && after cd, etc.
+
+ * texinfo.texi: Kludges so makeinfo -E will not create spurious
+ differences. Add new direntries.
+
+ * util/install-info.c,
+ * util/texindex.c,
+ * makeinfo/makeinfo.c,
+ * info/info.c: Standardize --version output.
+
+ * makeinfo/makeinfo.c (defun_internal): Don't insert index command
+ if expanding macros.
+ (cm_footnotestyle): Don't change the footnote style if it was set
+ on the command line.
+
+ * util/texi2dvi: Recompute original index files each time through loop.
+ Make indentation uniform.
+ Use same basename for the temp input files.
+ Standardize --version output.
+
+ * info/Makefile.in (install),
+ * makeinfo/Makefile.in (install): Insert $(POST_INSTALL).
+
+Fri Sep 27 13:27:30 1996 Karl Berry <karl@cs.umb.edu>
+
+ * texinfo.texi (Format with texi2dvi): Rewrite now that the script
+ runs in a loop.
+
+ * info/Makefile.in (MAKEINFO): Simplify to ../makeinfo/makeinfo.
+
+Fri Sep 27 00:26:03 1996 Miles Bader <miles@gnu.ai.mit.edu>
+
+ * info/terminal.c [HAVE_TERMIOS_H] (terminal_prep_terminal,
+ terminal_unprep_terminal): Add code for termios.
+ [HAVE_TERMIOS_H] (original_termios, ttybuff): New variables.
+ * info/termdep.h: [HAVE_TERMIOS_H]: Add include of <termios.h>.
+ * configure.in: Add check for <termios.h>.
+
+Thu Sep 26 10:46:34 1996 Karl Berry <karl@cs.umb.edu>
+
+ * emacs/texnfo-upd.el,
+ * emacs/texinfo.el,
+ * emacs/texinfmt.el: Update from bob for new Texinfo commands, etc.
+
+ * emacs/info.el, emacs/informat.el, emacs/makeinfo.el,
+ emacs/texnfo-tex.el: Update from Emacs 19.34 dist.
+
+ * emacs/elisp-comp: Use TMPDIR if set.
+
+ * util/Makefile.in (libdir): Remove.
+
+ * makeinfo/Makefile.in (install),
+ * Makefile.in (install),
+ * info/Makefile.in (install): Run install-info.
+ (libdir): Remove.
+
+ * texinfo.texi: Various fixes as I make this go through TeX.
+
+ * util/install-info.c: Quote newlines in help message.
+
+ * util/texi2dvi (texi2dvi): Run TeX until the aux/index files
+ stabilize, instead of just twice. From: David Shaw
+ <daves@gsms01.alcatel.com.au>.
+
+Tue Sep 24 14:43:03 1996 Karl Berry <karl@cs.umb.edu>
+
+ * dir: Blank dir file for installation on new systems.
+
+Mon Sep 23 12:18:43 1996 Karl Berry <karl@cs.umb.edu>
+
+ * makeinfo/makeinfo.c (args_from_string): Do not back up at a };
+ that leads to an infinite loop.
+
+Sat Sep 21 17:48:04 1996 Karl Berry <karl@cs.umb.edu>
+
+ * makeinfo/makeinfo.c (cm_xref): Do not seg fault if outside of
+ any node. From: Tom Tromey <tromey@creche.cygnus.com>.
+ (cm_ctrl): Make obsolete.
+
+Tue Sep 17 13:30:08 1996 Karl Berry <karl@cs.umb.edu>
+
+ * texinfo.tex (\inforef): Move to more appropriate place.
+ (\pounds): Remove spurious extra $.
+ (\email): Typeset argument in angle brackets.
+ (\macro): Use \doignore for robustness, instead of just letting TeX
+ parse the argument.
+ (\unmacro): Define.
+
+Sat Sep 14 16:17:35 1996 Karl Berry <karl@cs.umb.edu>
+
+ * texinfo.texi: Document multitables, new ISBN number.
+
+Wed Sep 11 18:01:24 1996 Karl Berry <karl@cs.umb.edu>
+
+ * makeinfo/multi.c (struct env): Remove unused output_position
+ field; this needs to be global.
+ (setup_multitable_parameters): Implement template-defined multitables.
+ (output_multitable_row): Remove trailing whitespace.
+
+ * makeinfo/makeinfo.c (_READ_BUFFER_GROWTH, struct _defines):
+ Remove leading underscore for POSIX/ANSI pedants.
+ (init_conversion): Initialize output_position here.
+ (init_paragraph): Instead of here, where it loses with the
+ multitable calls, eventually resulting in negative counts to the
+ write call when the output file is split.
+
+ * texinfo.texi: First cut at macro documentation.
+ Change accent doc to use tables.
+ Remove whitespace experiments, they are now the default.
+
+Mon Sep 9 14:16:24 1996 Karl Berry <karl@cs.umb.edu>
+
+ * makeinfo/makeinfo.c: Use putc instead of fprintf where possible.
+ (cm_accent): Put _ from @ubaraccent after argument.
+
+ * util/texindex.c (strerror) [!strerror]: Conditionalize
+ declaration.
+
+Sat Sep 7 14:13:24 1996 Karl Berry <karl@cs.umb.edu>
+
+ * makeinfo/makeinfo.c (commandTable): Obsolete @setchapterstyle.
+
+Thu Sep 5 15:45:11 1996 Karl Berry <karl@cs.umb.edu>
+
+ * makeinfo/makeinfo.c (convert_from_loaded_file): Oops, fix
+ wording of initial output comment.
+
+ * makeinfo/makeinfo.c (cm_angle_brackets): Rename from cm_key.
+ (commandTable): @email should produce angle brackets.
+ @key: Change name.
+
+Tue Sep 3 14:52:17 1996 Karl Berry <karl@cs.umb.edu>
+
+ * texinfo.tex (\hsize): Decrease.
+ (\hoffset): Increase.
+ (\setleading): Decrease dramatically.
+ This change affects 8.5x11 format only.
+
+ * texinfo.texi: Document accent commands.
+
+Mon Sep 2 11:10:49 1996 Karl Berry <karl@cs.umb.edu>
+
+ * makeinfo/makeinfo.c (commandTable): Deprecate @ichapter and
+ @titlespec.
+ Move all the deprecated @i<section> commands to the end of the list.
+
+ * texinfo.texi: Document @pounds{} and @centerchap{}.
+
+ * texinfo.tex (\centerchfplain): Rewrite to use \chfplain, and to
+ actually center.
+ (\unnchfplain): Just call \chfplain.
+ (\chfplain): Rewrite to be generally callable.
+ (\centerparametersmaybe): Hook, a no-op except with @centerchap.
+
+Sun Sep 1 15:01:49 1996 Karl Berry <karl@cs.umb.edu>
+
+ * texinfo.texi: Document @<whitespace>, rearrange spacing section.
+
+ * makeinfo.c (commandTable): Make @. @? @! insert themselves,
+ not be sentence-non-enders. They are sentence *enders*. Also,
+ make @\t and @\n insert a normal space character, not themselves.
+ Also, define @hyphenation.
+ (insert_space): New function.
+ (cm_ignore_sentence_ender): Remove this.
+ (flush_output): Check only for META-SPC, not META-<sentence-ender>.
+
+Fri Aug 30 18:55:30 1996 Karl Berry <karl@cs.umb.edu>
+
+ * texinfo.texi: Document @- and @hyphenation{}.
+ Miscellanous fixes.
+
+ * makeinfo/makeinfo.c (commandTable): Define @- as cm_no_op, since
+ makeinfo doesn't do hyphenation.
+
+Thu Aug 29 13:05:38 1996 Karl Berry <karl@cs.umb.edu>
+
+ * texinfo.tex (\key): Do not uppercase the argument; key names
+ can be mixed case, e.g., `Control'.
+
+ * makeinfo/makeinfo.c: @infotop, @infounnumbered,
+ @infounnumberedsec, @infounnumberedsubsec,
+ @infounnumberedsubsubsec, @infoappendix, @infoappendixsec,
+ @infoappendixsubsec, @infoappendixsubsubsec, @infochapter,
+ @infosection, @infosubsection, @infosubsubsection:
+ Remove these long-since obsolete commands.
+ @iappendix, @iappendixsection, @iappendixsec, @iappendixsubsec,
+ @iappendixsubsubsec, @ichapter, @isection, @isubsection,
+ @isubsubsection, @iunnumbered, @iunnumberedsec, @iunnumberedsubsec,
+ @iunnumberedsubsubsec:
+ Deprecate these.
+ @infoinclude:
+ Obsolete this.
+ @,: Have to take an argument, since have to do @,{c} not c@,; can't
+ feasibly implement the latter in TeX.
+
+ * makeinfo/makeinfo.c: Rename @d to @udotaccent, since this is
+ relatively infrequently used.
+
+Tue Aug 27 14:58:56 1996 Karl Berry <karl@cs.umb.edu>
+
+ * info/info.c (print_short_help),
+ * util/install-info.c (print_help),
+ * util/texi2dvi,
+ * makeinfo/makeinfo.c (usage) Include bug reporting address.
+
+Mon Aug 26 15:27:17 1996 Karl Berry <karl@cs.umb.edu>
+
+ * makeinfo/makeinfo.c (commandTable): Remove @input, @medbreak,
+ @smallbreak, @overfullrule, @br.
+
+Sun Aug 25 17:25:48 1996 Karl Berry <karl@cs.umb.edu>
+
+ * makeinfo/makeinfo.c (commandTable): Unify commands that perform
+ the same operation, such as cm_file, cm_samp, cm_email,
+ etc., which all do cm_code.
+
+ * texinfo.texi: Document @ifhtml ... @end ifhtml. Change
+ `PlainTeX' to `plain TeX'.
+
+Fri Aug 23 16:03:16 1996 Karl Berry <karl@cs.umb.edu>
+
+ * texinfo.tex (\pounds): New Texinfo command @pounds{}.
+ (\parskip): New smaller value.
+ (\chapheadingskip, \secheadingskip, \subsecheadingskip): New smaller
+ values, both for 8.5x11 and @smallbook formats. From Bob.
+
+ * makeinfo/makeinfo.c (cm_special_char): @pounds{} prints a #.
+ (commandTable): Add new command @pounds.
+
+Tue Aug 20 13:47:20 1996 Karl Berry <karl@cs.umb.edu>
+
+ * makeinfo/makeinfo.c (CommandTable): Restore "!", accidentally
+ removed previously.
+
+ * texinfo.tex (\key): Typeset a lozenge around the argument (from
+ gildea@intouchsys.com).
+ * makeinfo/makeinfo.c (cm_key): Surround arg with <...> to match
+ new lozenge style in TeX.
+
+Wed Aug 14 16:59:23 1996 Karl Berry <karl@cs.umb.edu>
+
+ * texinfo.texi: Propagate change from rms.
+
+Tue Aug 13 11:33:27 1996 Karl Berry <karl@cs.umb.edu>
+
+ * texinfo.texi: Propagate change from rms.
+
+ * texinfo.texi: Document other @headings options.
+
+Sun Aug 11 13:19:42 1996 Karl Berry <karl@cs.umb.edu>
+
+ * makeinfo/makeinfo.c (cm_accent, cm_special_char, cm_dotless):
+ New functions.
+ (CommandTable): Add new commands for all of plain.tex's
+ accents and non-English characters.
+
+Fri Aug 9 14:12:07 1996 Karl Berry <karl@cs.umb.edu>
+
+ * makeinfo/makeinfo.c (convert_from_loaded_file): Say we're making
+ ``text'' file if no_headers. Also, use `input_filename' instead
+ of just `name' for clarity.
+ (suffixes): Check for no suffix last, i.e., prefer `foo.texi' as an
+ input file to `foo'. (The latter is probably a binary.)
+
+Mon Aug 5 13:52:39 1996 Karl Berry <karl@cs.umb.edu>
+
+ * texinfo.tex (\heading, \subheading, \subsubheading): Can no
+ longer call the nonexistent \*secheadingi series. Instead, call
+ \plain*secheading.
+ (\plainsubsecheading, \plainsubsubsecheading): New macros, by analogy
+ with \plainsecheading.
+ (\unnumberedsubseczzz, \unnumberedsubsubseczzz): Call them.
+
+Sun Aug 4 16:46:10 1996 Karl Berry <karl@cs.umb.edu>
+
+ * makeinfo/makeinfo.c (flush_output): Mask out eighth bit, that we
+ turned on in non-sentence enders.
+
+Sat Aug 3 14:03:10 1996 Karl Berry <karl@cs.umb.edu>
+
+ * texinfo.tex (\HEADINGSdouble, \HEADINGSsingle,
+ HEADINGSdoubleafter, \HEADINGSsingleafter, \CHAPPAGoff,
+ \CHAPPAGon, \CHAPPAGodd): Set \contentsalignmacro, analogous to
+ \pagealignmacro.
+ (\startcontents): Call \contentsalignmacro instead of \pagealignmacro.
+
+Mon Jul 29 14:44:33 1996 Karl Berry <karl@cs.umb.edu>
+
+ * texinfo.tex (\indexfonts): Make leading be 12pt. Otherwise, it's
+ too crammed.
+ (\smalllispx): Remove \setleading{10pt}. That was too small.
+ (\doprintindex): Do not call \tex ... \Etex. Index files are Texinfo
+ source, not TeX source, except for using \ instead of @ as the
+ escape character (for now).
+
+Sun Jul 28 13:37:05 1996 Karl Berry <karl@cs.umb.edu>
+
+ * texinfo.tex (paragraphindent): Move to more reasonable place in
+ the source file.
+ (chapfonts, secfonts, subsecfonts, indexfonts): Call \setleading.
+ (\chfplain, \secheading, \plainsecheading, \subsecheading,
+ \subsubheading): Rewrite to properly \hangindent the title.
+ (\sectionheading): New generic macro to print section titles.
+
+ * texinfo.texi: Update the `Obtaining TeX' node.
+
+Fri Jul 26 14:11:48 1996 Karl Berry <karl@cs.umb.edu>
+
+ * util/texi2dvi: Do macro expansion with makeinfo before running TeX.
+ Various expansion safety measures added for test; avoid use of -o.
+
+ * makeinfo/makeinfo.c (usage): More usage message tweaks.
+
+Fri Jul 26 11:55:37 1996 Karl Berry <karl@laurie>
+
+ * util/texi2dvi: Format usage message to conform to the other *utils.
+
+Thu Jul 25 17:05:47 1996 Karl Berry <karl@cs.umb.edu>
+
+ * emacs/Makefile.in: Do not compile the Elisp by default. We
+ don't install it, so it confuses people to compile it.
+
+Sun Jul 21 07:20:09 1996 Karl Berry <karl@cs.umb.edu>
+
+ * util/Makefile.in (install-info): Dependency should be
+ install-info.o, not install-info. Also, update copyright years.
+
+ * makeinfo/makeinfo.c (cm_printindex): Don't call execute_string
+ to print index entries, we've already done the expansion now.
+
+ * makeinfo/makeinfo.h: Add copyright. Finish merge of rms changes.
+ * makeinfo/makeinfo.c: Finish merge, add my expansion changes again.
+ * makeinfo/multi.c: Add copyright message.
+
+Fri Jul 19 10:35:22 1996 Karl Berry <karl@cs.umb.edu>
+
+ * info/info.c: Update copyright date.
+
+ * info/info.texi,
+ * util/install-info.c,
+ * emacs/Makefile.in,
+ * emacs/texnfo-tex.el,
+ * emacs/Makefile.in: Change FSF address.
+
+ * Merged changes from bfox -- below, plus multitable changes, plus
+ lots more.
+
+ Sun Apr 14 08:49:50 1996 Brian J. Fox <bfox@nirvana.samsara.com>
+
+ * makeinfo/makeinfo.c (remember_node_reference): Numerous commands
+ call remember_node_reference. If a node has not yet been defined,
+ use the empty string as the current node for those cases.
+
+ Mon Feb 12 17:35:38 1996 Brian J. Fox <bfox@nirvana.samsara.com>
+
+ * makeinfo/makeinfo.c (push_node_filename): Clean up calls to
+ xmalloc and xrealloc. Only have to call xrealloc.
+
+ Fri Jan 26 08:00:38 1996 Brian J. Fox <bfox@nirvana.samsara.com>
+
+ * info/session.c (info_input_buffer_space_available): Fix typo
+ which forced the limitation of the sizeof (int) instead of sizeof
+ (buffer).
+
+ * Makefile.in (PACKVER): now at 3.8. Add TERMIOS support to
+ Info. Minor bugs fixed in Makeinfo.
+
+Sat Jul 13 11:58:57 1996 Karl Berry <karl@cs.umb.edu>
+
+ * texinfo.texi (ftable vtable): Mention example.
+
+Sun Jun 30 14:59:51 1996 Karl Berry <karl@goldman.gnu.ai.mit.edu>
+
+ * makeinfo/makeinfo.c (cm_email): New function for new @email command.
+ * texinfo.texi (email): New node documenting it.
+
+Wed Apr 17 18:07:34 1996 Richard Stallman <rms@mole.gnu.ai.mit.edu>
+
+ * makeinfo/makeinfo.c (cm_kbd): Do nothing if in @example or @code.
+ (struct brace_element): New field in_fixed_with_font.
+ (remember_brace_1): Save in_fixed_with_font.
+ (pop_and_call_brace): Restore in_fixed_with_font.
+ (cm_code): Don't decrement in_fixed_with_font at end of construct.
+ (struct istack_elt): New field in_fixed_with_font.
+ (push_insertion, pop_insertion): Save and restore in_fixed_with_font.
+ (end_insertion): Don't decrement in_fixed_with_font here.
+ (not_fixed_width): New function.
+ (cm_sc, cm_var, cm_italic, cm_roman, cm_titlefont):
+ Use not_fixed_width.
+
+Sat Apr 13 23:22:05 1996 Richard Stallman <rms@mole.gnu.ai.mit.edu>
+
+ * util/install-info.c (main): Fatal error if no input file spec'd.
+ Look for START-INFO-DIR-ENTRY, not BEGIN-INFO-DIR-ENTRY.
+
+Thu Apr 11 18:21:50 1996 Richard Stallman <rms@mole.gnu.ai.mit.edu>
+
+ * makeinfo/makeinfo.c (cm_enddots): New function.
+ (self_delimiting): Accept -, ^ and ".
+ (CommandTable): Add commands -, ^, ", enddots, centerchap.
+
+Sun Mar 24 12:18:32 1996 Richard Stallman <rms@mole.gnu.ai.mit.edu>
+
+ * makeinfo/makeinfo.c (enum insertion_type): Add `direntry'.
+ (insertion_type_names): Add "direntry".
+ (cm_dircategory): New function.
+ (cm_direntry): New function.
+ (CommandTable): Add "dircategory" and "direntry".
+ (insert_string): New function.
+ (end_insertion): Handle direntry.
+ (begin_insertion): Handle direntry.
+
+Sun Mar 24 11:10:05 1996 Karl Berry <karl@spiff.gnu.ai.mit.edu>
+
+ * makeinfo/makeinfo.c (cm_url): New function for new @url command.
+
+Fri Feb 23 21:14:40 1996 Richard Stallman <rms@mole.gnu.ai.mit.edu>
+
+ * info/Makefile.in (install, uninstall): Use manprefix.
+
+Fri Feb 23 19:50:18 1996 Richard Stallman <rms@whiz-bang.gnu.ai.mit.edu>
+
+ * util/Makefile.in (install-info, install-info.o): New targets.
+ (all): Depend on install-info.
+ (install, uninstall): Operate on install-info.
+
+ * install-info.c: New file.
+
+Wed Jan 3 10:01:45 1996 Brian J. Fox <bfox@nirvana.datawave.net>
+
+ * makeinfo/makeinfo.c (make_index_entries_unique): Be a little bit
+ stricter about what makes two index entries identical.
+
+Fri Dec 29 13:00:24 1995 Brian J. Fox <bfox@wizard.datawave.net>
+
+ * makeinfo/makeinfo.c (Whole File): Add @detailmenu for allowing
+ detailed menu listings to appear while still defaulting nodes.
+
+Wed Dec 27 13:54:30 1995 Brian Fox <bfox@albert.gnu.ai.mit.edu>
+
+ * makeinfo/makeinfo.c (cm_code): Always notice that we are in
+ fixed_width_font, even if other formatting changes are not to take
+ place.
+
+Sat Dec 23 11:48:43 1995 Brian J. Fox <bfox@wizard.datawave.net>
+
+ * info/man.c: (clean_manpage) Remove ^L's from page.
+
+ * makeinfo/makeinfo.c (get_brace_args): Change some memcpy's to
+ memmoves.
+
+ * info/info.c (main): Prefer caseless matches over partial
+ matches.
+
+ * Makefile.in (All Subdir Targets): Change suggested by Debian
+ people which allows errors in recursive makes to kill the
+ top-level make.
+
+ * makeinfo/Makefile.in (makeinfo.dvi): New target.
+
+ * info/info.c (main): Print version of containing texinfo package.
+
+ * makeinfo/makeinfo.c (flush_output): Don't strip high-bit from
+ sentence_enders.
+ Print the version number of the containing texinfo package.
+
+ * info/man.c (locate_manpage_xref): Count the 0th entry.
+
+ * makeinfo/makeinfo.c (cm_menu): If a menu is seen before a node
+ has been defined, warn, and create the node `Top'.
+
+Wed Jun 21 03:19:39 1995 Brian Fox <bfox@albert.gnu.ai.mit.edu>
+
+ * makeinfo/makeinfo.c (cm_infoinclude): Clean up after printing
+ error if the file couldn't be included.
+ (discard_braces): Print errors only for those unmatched open
+ braces that belong to a texinfo command.
+
+ * */Makefile.in: Use @CFLAGS@ and @LDFLAGS@.
+
+ * makeinfo/makeinfo.c: End `node_search_string' and friends with a
+ terminating null character.
+
+Wed Jun 21 01:23:49 1995 Jim Meyering (meyering@comco.com)
+
+ * makeinfo/makeinfo.c: Close comment after #endif.
+
+Tue Jun 20 04:58:26 1995 Brian Fox <bfox@albert.gnu.ai.mit.edu>
+
+ * emacs/Makefile.in (install): Fix typo: "fle" -> "file".
+
+ * Makefile.in (VERSION): Bump to 3.6
+
+ * info/clib.c: Include general.h for `info_toupper' and friends.
+
+ * info/clib.h: strncmp and strncascmp return an int. What kind of
+ drugs was I on?
+
+Mon Jun 19 23:34:47 1995 Brian Fox <bfox@albert.gnu.ai.mit.edu>
+
+ * makeinfo/makeinfo.c (make_index_entries_unique): Copy the last
+ index entry.
+
+Mon Jun 19 21:55:49 1995 Noah Friedman <friedman@prep.ai.mit.edu>
+
+ * util/texi2dvi (--version): New option.
+ Cosmetic changes.
+
+Mon Jun 19 16:06:40 1995 Brian Fox <bfox@albert.gnu.ai.mit.edu>
+
+ * makeinfo/makeinfo.c (cm_macro): Fix typo. `x != y' is not the
+ same as `x |= y'.
+
+ * info/Makefile.in (exec_prefix): Use @exec_prefix@ not $(prefix).
+ * makeinfo/Makefile.in (exec_prefix): Use @exec_prefix@ not $(prefix).
+ * util/Makefile.in (exec_prefix): Use @exec_prefix@ not $(prefix).
+ * libtxi/Makefile.in (exec_prefix): Use @exec_prefix@ not $(prefix).
+
+ * emacs/Makefile.in (uninstall): New target.
+ (install): Use the definition of $(lispdir), don't dynamically
+ find it. Use INSTALL_DATA not cp.
+ (exec_prefix): use @exec_prefix@ not $(prefix).
+
+ * makeinfo/makeinfo.c (apply): If there isn't an actual argument
+ for a named argument, default it to "".
+
+ * Makefile.in (VERSION): Now at 3.5.
+ (texinfo): Make ./makeinfo/makeinfo depend on sub-all for parallel
+ makes.
+
+ * emacs/Makefile.in (ELISP_OBJS): Explictly declare .el and .elc
+ in the SUFFIXES list.
+
+ * makeinfo/makeinfo.c (cm_today): Special case for losing alpha.
+ * (minor_version): Increase to 63.
+
+ * info/info.c (version_string): Now at 2.14.
+ * info/tilde.c: Declare getenv to return (char *).
+ * info/window.c (build_message_buffer): Jump through hoops to keep
+ DEC Alpha's happy.
+
+ * info/xmalloc.c: Declare malloc and realloc as (void *) returning
+ functions.
+
+Sun Jun 18 12:47:21 1995 Richard Stallman <rms@mole.gnu.ai.mit.edu>
+
+ * emacs/detexinfo.el (detexinfo-line-cmds-without-arg):
+ Handle ifhtml.
+
+Fri Jun 16 13:48:14 1995 Brian Fox <bfox@albert.gnu.ai.mit.edu>
+
+ * util/texindex.c: Update TEXINDEX_VERSION_STRING for texinfo 3.4
+
+ * (All *.c *.h *.in): Change FSF old address to new.
+ * texinfo.texi (Obtaining TeX): Change FSF old address to new
+ address. Change Old phone numbers to new phone numbers.
+
+ * Makefile.in (VERSION): Change to 3.4.
+
+Thu Jun 15 22:49:07 1995 Robert J. Chassell <bob@hill.gnu.ai.mit.edu>
+
+ * texinfo.texi, emacs/=development/cover.texi: update
+ Texinfo distribution package version number
+
+Thu Jun 15 09:23:02 1995 Brian J. Fox <bfox@wizard.datawave.net>
+
+ * info/info.c: (minor_version): Set to 13.
+
+ * info/clib.c,h: New files gather together replacement functions
+ for those POSIX-style C library functions that are not present on
+ the target system.
+
+ * info/Makefile.in (SRCS): Add clib.c and clib.h. makedoc now
+ needs clib.o to build on systems missing various string.h stuff.
+
+ * info/variables.c (whole file): Call strdup, not savestring.
+ * info/tilde.c (whole file): Call strdup, not savestring.
+ * info/search.c (whole file): Call strdup, not savestring.
+ * info/nodes.c (whole file): Call strdup, not savestring.
+ * info/nodemenu.c (whole file): Call strdup, not savestring.
+ * info/man.c (whole file): Call strdup, not savestring.
+ * info/makedoc.c (whole file): Call strdup, not savestring.
+ * info/m-x.c (whole file): Call strdup, not savestring.
+ * info/info.c (whole file): Call strdup, not savestring.
+ * info/indices.c (whole file): Call strdup, not savestring.
+ * info/echo_area.c (whole file): Call strdup, not savestring.
+ * info/session.c (whole file): Call strdup, not savestring.
+ * info/filesys.c (whole file): Call strdup, not savestring.
+
+ * makeinfo/makeinfo.c (minor_version): Change to 1.62.
+ * makeinfo/makeinfo.c (get_execution_string): Initialize `i' to 0
+ in case there are no execution_strings.
+
+Wed Jun 14 17:48:06 1995 Brian J. Fox <bfox@wizard.datawave.net>
+
+ * texinfo.texi: include "texinfo.tex", not "texinfo".
+ * info/session.c (forget_window_and_nodes): Place a sequence point
+ in between "info_windows[i] = info_windows[++i];" as per various
+ compiler experts.
+
+ * makeinfo/makeinfo.c (strdup): Create this function if the system
+ doesn't have it.
+ (discard_insertions): Use the insertion's filename, not the
+ current input file.
+ (push_insertion): Remember the current input file with each
+ insertion.
+ (pop_insertion): Free storage used by remembered input file.
+
+ * makeinfo/makeinfo.c (whole file): Use `strdup' instead of
+ `savestring'.
+ * configure.in: Check for `strdup'.
+
+Wed Jun 14 15:58:51 1995 Brian Fox <bfox@albert.gnu.ai.mit.edu>
+
+ * libtxi/Makefile.in (prefix): Use @prefix@, not /usr/local/
+
+Wed Jun 14 10:50:57 1995 Brian J. Fox <bfox@wizard.datawave.net>
+
+ * Makefile.in (DISTFILES): Don't include *.elc files in the list
+ of files to distribute.
+ (installdirs): Include `emacs' in the list of sub-dirs with
+ Makefile.in's.
+
+ * emacs/elisp-comp: Shell script which batch compiles the *.el files.
+ * emacs/Makefile.in: New file contains targets to build the elc files.
+ * configure.in: Add `emacs/Makefile' to the list of created makefiles.
+ * makeinfo/makeinfo.c (whole file): Give every function a return
+ type. All cm_xxx functions are now void. Add declarations for
+ functions to top of file.
+
+Mon Jun 12 12:00:57 1995 Brian J. Fox <bfox@wizard.datawave.net>
+
+ * info/man.c (reference_section_starters): Add versions of "SEE
+ ALSO" and "RELATED INFORMATION" with tabs instead of spaces as
+ well.
+
+ * util/texindex.c: Back out changes for OFF_T. Explicity coerce
+ the result of lseek to a long, and use longs everywhere.
+
+ * texinfo.texi: Change "@end shorttitlepage" to "@end titlepage".
+ * makeinfo/makeinfo.c: Make @shorttitlepage ignore the rest of the
+ line.
+
+ * util/texindex.c (strrchr): Create if not present.
+ Test for HAVE_STRCHR and HAVE_STRING_H.
+ (main): Make PROGRAM_NAME be just the last path componenet of argv[0].
+ (decode_command): Rewrite.
+ (usage): Rewrite. Now texindex handles --version.
+
+ * makeinfo/makeinfo.c (make_index_entries_unique): Rewrite from
+ scratch.
+
+ * Don't distribute created info files with texinfo. After all,
+ the user will have the tools necessary to create them, yes?
+
+ * Makefile.in (distclean): Remove *.log
+
+ * info/man.c (read_from_fd): Change timeout value for select to 15
+ seconds. Some systems (e.g., albert.ai.mit.edu) actually need
+ more than 10 seconds to format a man page.
+
+ * info/tilde.c: Fix typo in declaration for
+ `tilde_expansion_failure_hook'.
+
+Wed Jun 7 13:36:53 1995 Brian Fox <bfox@albert.gnu.ai.mit.edu>
+
+ * info/tilde.h: Change type of tilde_expansion_failure_hook to
+ a pointer to a function returning a (char *).
+ * info/tilde.c: Change type of tilde_expansion_failure_hook to a
+ pointer to function returning a (char *).
+
+ * makeinfo/makeinfo.c (get_execution_string): Don't use `i' in the
+ latter assignment, use `execution_strings_index' instead.
+
+ * info/man.c (read_from_fd): Change logic to avoid using FIONREAD.
+
+ * info/xmalloc.c (xrealloc): Use (void *), not (caddr_t *).
+ * info/xmalloc.c (xmalloc): Use (void *), not (caddr_t *).
+
+ * Makefile.in (DISTFILES): Don't find RCS no "=" directories.
+
+ * util/Makefile.in (prefix): Use @prefix@ as the value.
+ * info/Makefile.in (prefix): Use @prefix@ as the value.
+ * makeinfo/Makefile.in (prefix): Use @prefix@ as the value.
+
+Wed Jun 7 12:29:28 1995 Robert J. Chassell <bob@hill.gnu.ai.mit.edu>
+
+ * texinfo.texi: Correct minor typos.
+
+ * emacs/texinfmt.el: Don't require @shorttitlepage to be inside
+ of @iftex ... @end iftex
+
+Mon May 8 18:33:52 1995 Brian J. Fox <bfox@wizard.datawave.net>
+
+ * info/nodes.c: #include "man.h" if HANDLE_MAN_PAGES.
+ (info_get_node_of_file_buffer): If the file buffer is one
+ associated with manpages, call the manpage node finding
+ function instead.
+ (info_find_file_internal): If the file buffer is one associated
+ with manpages, avoid doing any file I/O.
+ (info_reload_file_buffer_contents): Ditto.
+ (info_find_file_internal): Call create_manpage_file_buffer instead
+ of info_load_file_internal.
+
+ * info/info.c: #include "man.h" if HANDLE_MAN_PAGES.
+ (main): If the initial node cannot be found, perhaps find it as a
+ manpage.
+ * info/info-utils.c: #include "man.h" if HANDLE_MAN_PAGES.
+ (info_xrefs_of_node): If handling man pages, and this is a manpage
+ node, use xrefs_of_manpage.
+
+ * info/session.c (info_set_input_from_file): Only fclose (stream)
+ if it is non-null and not stdin.
+ #include "man.h" if HANDLE_MAN_PAGES.
+ (info_menu_or_ref_item): If handling man pages, and this is a
+ manpage node, get the xrefs from manpage_xrefs_in_binding.
+ (info_man): Compile in for M-x man if handling man pages.
+ (info_move_to_xref): If handling man pages, and the current node
+ is a manpage node, use locate_manpage_xref to get xrefs.
+
+Thu May 4 08:55:23 1995 Brian J. Fox <bfox@wizard.datawave.net>
+
+ * info/info.c (main): If the output device is not a terminal, and
+ no output filename has been specified, make user_output_filename
+ be "-", so that the info is written to stdout, and turn on the
+ dumping of subnodes.
+
+Thu Apr 13 18:05:06 1995 Daniel Hagerty <hag@churchy.gnu.ai.mit.edu>
+
+ * texinfo.texi: Fixed @end titlepage/@end shorttitlepage
+
+Sat Apr 8 12:51:49 1995 Roland McGrath <roland@churchy.gnu.ai.mit.edu>
+
+ * makeinfo/makeinfo.c [! HAVE_STRERROR] (strerror): New function,
+ snarfed from ../info/filesys.c.
+ (cm_infoinclude): Use strerror instead of sys_errlist.
+
+Tue Apr 4 18:44:00 1995 Brian J. Fox <bfox@wizard.datawave.net>
+
+ * util/texindex.c (sort_offline): Change TOTAL to be an off_t.
+ * util/texindex.c (sort_in_core): Change TOTAL to be an off_t.
+ * util/texindex.c (MAX_IN_CORE_SORT): Cast to off_t.
+
+Sun Apr 2 16:20:13 1995 Brian J. Fox <bfox@wizard.datawave.net>
+
+ * info/Makefile.in: Define DEFAULT_INFOPATH in case we are
+ compiling in the current directory.
+ * info/Makefile.in (info.o): Add filesys.h because of DEFAULT_INFOPATH.
+ * info/(search.c,h, nodes.c info-utils.c) Use strcasecmp and
+ strncasecmp instead of stricmp and strnicmp. Define strcasecmp
+ and strncasecmp in search.c if !HAVE_STRCASECMP.
+ * info/search.c: If HAVE_STRING_H include it.
+ * info/nodes.c: If HAVE_STRING_H include it.
+ * info/info-utils.c: If HAVE_STRING_H include it.
+ * info/info.h: If HAVE_STRING_H include it.
+ * configure.in (AC_HAVE_FUNCS): Check for strcasecmp.
+ * makeinfo/makeinfo.c (strcasecmp): Define if !HAVE_STRCASECMP.
+ * makeinfo/makeinfo.c (entire file): Use `strcasecmp' instead of
+ `stricmp'.
+ * makeinfo/makeinfo.c (cm_ifeq): New command takes three args.
+ Compares first two, executes remainder if the first two are
+ string-wise eq.
+ * makeinfo/makeinfo.c (ifhtml): Add to command list. Shouldn't be
+ used, but it is by people who don't want to hack macros.
+
+Sat Apr 1 09:20:14 1995 Brian J. Fox <bfox@wizard.datawave.net>
+
+ * makeinfo/makeinfo.c (begin_insertion): Fix reversed arguments to
+ line_error.
+
+ * info/info-stnd.texi: Use "end" footnote style instead of "separate".
+
+ * info/Makefile.in: Change "rm -f" to $(RM).
+
+ * info/general.h: Define zero_mem in terms of memset if we have
+ it, else in terms of bzero if we have that, else as inline code.
+
+ * info/NEWS: Updated to reflect changes in 2.11.
+
+Fri Mar 31 22:38:31 1995 Brian J. Fox <bfox@wizard.datawave.net>
+
+ * Makefile (DISTFILES): Don't include *.a, *orig, nor *.e
+ files.
+ (DISTFILES):
+
+Sat Mar 4 12:16:29 1995 Brian J. Fox <bfox@wizard.datawave.net>
+
+ * Makefile.in: Use @prefix@ instead of hardwired `/usr/local'.
+ Clean up makefile rules which make in subdirs.
+ (ALL_SUBDIRS): Add makeinfo/macros to list of subdirectories.
+
+ * configure.in (AC_CHECK_FUNCS): Add `bcopy' to list of things to
+ check for.
+
+Fri Mar 3 13:54:10 1995 Robert J. Chassell <bob@hill.gnu.ai.mit.edu>
+
+ * texinfo.texi: Minor changes for incremental new edition 2.20.
+
+Fri Mar 3 19:01:36 1995 Brian J. Fox <bfox@wizard.datawave.net>
+
+ * filesys.c (filesys_read_info_file): Local variable ST_SIZE is a
+ long which has the value of finfo->st_size casted to it.
+ * nodes.c (whole file): Similar changes.
+
+ These changes and the following for makedoc.c were required for
+ proper operation on HPm68k NetBSD.
+
+Mon Feb 27 15:16:27 1995 Brian J. Fox <bfox@wizard.datawave.net>
+
+ * makedoc.c (process_one_file): Local variable FILE_SIZE is a long
+ which has the value of finfo.st_size casted to it.
+
+
+Fri Mar 3 18:58:38 1995 Brian J. Fox <bfox@wizard.datawave.net>
+
+ * makeinfo.c (find_and_load): Cast fileinfo.st_size to a long for
+ internal use. This makes things work on NetBSD.
+
+
+Fri Mar 3 13:54:10 1995 Robert J. Chassell <bob@hill.gnu.ai.mit.edu>
+
+ * texinfo.texi: Minor changes for incremental new edition 2.20.
+
+Fri Mar 3 09:41:39 1995 Brian J. Fox <bfox@wizard.datawave.net>
+
+ * configure.in (TERMLIBS): Use AC_CHECK_LIB instead of
+ AC_HAVE_LIBRARY.
+
+Mon Jan 9 16:55:31 1995 Brian Fox <bfox@churchy.gnu.ai.mit.edu>
+
+ * Makefile.in (DISTFILES): Add the directory EMACS-BACKUPS to the
+ list of things to avoid distributing.
+
+Tue Nov 29 17:48:37 1994 David J. MacKenzie <djm@duality.gnu.ai.mit.edu>
+
+ * configure.in: Check for off_t.
+ * util/texindex.c (main): Use it.
+
+Fri Nov 11 14:46:28 1994 David J. MacKenzie <djm@duality.gnu.ai.mit.edu>
+
+ * configure.in: Update for Autoconf v2.
+
+Thu Oct 13 02:17:38 1994 Richard Stallman <rms@mole.gnu.ai.mit.edu>
+
+ * emacs/detexinfo.el (detexinfo): Handle @!, @?, @^, @".
+
+Mon Aug 1 03:26:13 1994 Richard Stallman <rms@mole.gnu.ai.mit.edu>
+
+ * texindex.c: Move the memset define down past string.h include.
+
+Tue Jun 28 14:21:43 1994 David J. MacKenzie (djm@churchy.gnu.ai.mit.edu)
+
+ * makeinfo/makeinfo.c: Add --help option.
+ (usage): Take args for stream and error code.
+ Change callers.
+ (print_version_info): Write to stdout, not stderr.
+
+Wed May 18 18:55:24 1994 Brian J. Fox (bfox@ai.mit.edu)
+
+ * info/session.c (forget_window_and_nodes): Negate test for
+ internal_info_node_p. We only want to free the text if it is
+ not an internal node.
+
+Thu Mar 10 03:07:18 1994 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * texindex.c (memset): Fix invalid parm name (was 0).
+
+Thu Feb 10 12:56:52 1994 Noah Friedman (friedman@prep.ai.mit.edu)
+
+ * makeinfo/makeinfo.c (current_item_function): Don't loop if elt
+ is NULL.
+
+Wed Feb 9 12:21:09 1994 Brian J. Fox (bfox@ai.mit.edu)
+
+ * makeinfo/makeinfo.c (minor_version): Release now at 1.60.
+
+ * makeinfo/makeinfo.c (expand_filename): Additional fixes. Now
+ when called with NULL filename, makes an output filename from the
+ input filename.
+ (convert_from_loaded_file): If REQUIRE_SETFILENAME is #defined (no
+ longer the default case) then error if no @setfilename was found
+ in the file. If REQUIRE_SETFILENAME is not #defined, the input
+ file starts either at the first line, or at the second line if the
+ first line contains the text "\input", and the output filename is
+ the input file name without directory and with ".info" replacing
+ any extension found.
+ (convert_from_loaded_file): Fixed bug in search for first
+ occurence of "@setfilename".
+
+Tue Feb 8 14:16:58 1994 Noah Friedman (friedman@prep.ai.mit.edu)
+
+ * configure.in: Check for sys/file.h.
+ info/dir.c, info/filesys.c, info/makedoc.c, info/nodes.c,
+ info/session.c, info/termdep.h, makeinfo/makeinfo.c
+ [HAVE_SYS_FILE_H]: Include <sys/file.h>.
+
+ * makeinfo/makeinfo.c (convert_from_loaded_file): Print
+ real_output_filename instead of output_filename, so user knows
+ exactly where output file is going.
+
+ Fri Jun 11 14:34:30 1993 Ian Lance Taylor (ian@cygnus.com)
+ * configure.in: Check for sigprocmask and sigsetmask.
+ * info/signals.h (HAVE_SIGSETMASK): Don't define.
+ (HAVE_SIGPROCMASK): Use instead of _POSIX_VERSION.
+ (BLOCK_SIGNAL, UNBLOCK_SIGNAL): If neither HAVE_SIGPROCMASK nor
+ HAVE_SIGSETMASK is defined, define these to do nothing.
+ * info/signals.c (sigprocmask): Don't compile if HAVE_SIGSETMASK
+ is not defined.
+
+ * info/terminal.c (terminal_prep_terminal): Don't clobber VINTR
+ and VQUIT in conditionals.
+
+Mon Feb 7 18:10:22 1994 Brian J. Fox (bfox@ai.mit.edu)
+
+ * makeinfo/makeinfo.c (full_pathname): Correct to really return
+ the full pathname of the input argument. Now makeinfo
+ /foo/bar.texi, where /foo/bar.texi contains "@setfilename
+ bar.info", correctly leaves the output file in "./bar.info".
+ Note that "@setfilename ../bar.info" still works; this is already
+ an absolute pathname.
+
+Sat Feb 5 13:04:05 1994 Brian J. Fox (bfox@ai.mit.edu)
+
+ * makeinfo/makeinfo.c: Version 1.59 released.
+
+ * makeinfo/makeinfo.c (whole file): Large number of changes allow
+ the "-E filename" option to be used to write a macro expanded
+ output file. On a file which contains no @include's and no
+ @macro's, the output file is identical to the input file.
+
+ * makeinfo/makeinfo.c (declarations): Remove cm_tex (). It is
+ never used since it is implemented with `command_name_condition'.
+
+ * makeinfo/makeinfo.c (add_char): Shift braces following the
+ current break point if we have deleted any characters.
+ (adjust_braces_following): New function adjusts all of the markers
+ in the brace stack which follow HERE by AMOUNT. This fixes a bug
+ where (for example) @var{} immediately following a line break
+ which is the end of a sentence modified the output incorrectly.
+
+Wed Feb 2 14:14:03 1994 Brian J. Fox (bfox@ai.mit.edu)
+
+ * makeinfo: Version 1.58.
+
+ * makeinfo/makeinfo.c (cm_node): Add extra hair to allow
+ backtracking through execution strings. Add extra hair to allow
+ the first node seen after a @top node is seen to adjust the
+ sectioning level of the @top node and associated menus.
+ Fix a few typos.
+ Add facility for macros to invoke the original definition. This
+ works by not allowing a single macro to recurse. Mutual recursion
+ is also disallowed with this plan.
+
+ * makeinfo/macros: New directory contains shippable macros.
+ * makeinfo/macros/simpledoc.texi: Macros which simplify the most
+ common uses of TeXinfo. See the example file.
+ Macros are now a reasonable way to get people started using
+ TeXinfo.
+
+Mon Jan 31 12:54:36 1994 Brian J. Fox (bfox@ai.mit.edu)
+
+ * makeinfo/makeinfo.c (minor_version): Increase to 57.
+
+ * makeinfo/makeinfo.c (cm_node): Call execute_string on the node,
+ next, prev, and up pointers.
+ (reader_loop): Change logic for `@bye'. No longer required at the
+ ends of executed strings.
+ (execute_string): Do not append `@bye' to the string to execute.
+
+ * makeinfo/makeinfo.c (whole file): Use COMMAND_PREFIX instead of
+ hardcoding `@' character in strings and searches.
+
+ * makeinfo/makeinfo.c (read_command): If HAVE_MACROS is defined,
+ then recognize and execute macros here.
+ (CommandTable): Add "macro" and "unmacro" to table if HAVE_MACROS
+ is defined.
+
+ * makeinfo/makeinfo.c (cm_macro, cm_unmacro, execute_macro)
+ makeinfo/makeinfo.c (get_macro_args, find_macro, add_macro)
+ makeinfo/makeinfo.c (delete_macro, array_len, apply):
+ New functions implement macro facility if HAVE_MACROS is
+ defined.
+
+ * makeinfo/macro.texi (new file): Examples of using the new macro
+ facility.
+
+Mon Jan 31 10:24:52 1994 Noah Friedman (friedman@prep.ai.mit.edu)
+
+ * makeinfo/makeinfo.c (executing_string): Restore global
+ declaration.
+
+Mon Jan 24 23:48:26 1994 Noah Friedman (friedman@prep.ai.mit.edu)
+
+ * texinfo.texi: Various typo fixes from Bob Chassell
+ <bob@gnu.ai.mit.edu>.
+
+Thu Jan 6 13:34:21 1994 Noah Friedman (friedman@prep.ai.mit.edu)
+
+ * texinfo.texi: Turned on smallbook format and @set smallbook.
+
+Wed Dec 15 20:08:43 1993 Noah Friedman (friedman@prep.ai.mit.edu)
+
+ * info/filesys.h (DEFAULT_INFOPATH): Added /usr/local/info,
+ /opt/gnu/info, /usr/share/info, and /usr/local/share/info.
+
+Tue Dec 14 19:10:20 1993 Noah Friedman (friedman@prep.ai.mit.edu)
+
+ * libtxi/Makefile.in (ALLOCA): Define from configure.
+
+Fri Dec 10 04:33:12 1993 Noah Friedman (friedman@prep.ai.mit.edu)
+
+ * util/texi2dvi: Put under RCS control.
+
+Sun Dec 26 11:55:46 1993 Brian J. Fox (bfox@ai.mit.edu)
+
+ * info/session.c (info_numeric_digit_arg_loop): Fix doc string.
+
+ * info/infodoc.c (create_internal_info_help_node): Print out list
+ of functions which have to keystroke equivalent if we support
+ NAMED_FUNCTIONS.
+
+ * info/filesys.c (compress_suffixes): Add ".gz" for "gunzip" to
+ alist.
+
+ * info/footnotes.c (make_footnotes_node): If refs[i] doesn't have
+ a nodename, then it couldn't be a reference to a footnote.
+
+ * info/nodemenu.c (get_visited_nodes): Handle the case where
+ filter_func has left no possible buffers to select.
+
+Sat Dec 25 10:35:56 1993 Brian J. Fox (bfox@ai.mit.edu)
+
+ * info/infodoc.c (create_internal_info_help_node): Conditionalize
+ generation of the help node based on the #define
+ HELP_NODE_GETS_REGENERATED. When this is not set (the default)
+ the help node is generated exactly once, and is not gc'able.
+ Otherwise, a new node is always created for the help window, and
+ the old node gets garbage collected by the gc system.
+ (info_find_or_create_help_window): Conditionalize window node
+ selected based on the #define HELP_NODE_GETS_REGENERATED.
+
+ * info/dir.c (add_menu_to_file_buffer): Place exactly one blank
+ line between directory entries.
+
+ * info/info.c (version_string): Update minor version to "11".
+
+ * info/info.h: Update comment to "2.11".
+
+ * info/dir.c (maybe_build_dir_node): Only add the contents of a
+ new file if it is not identical to the file of the DIR buffer.
+
+ * info/nodes.c (info_get_node): Call `maybe_build_dir_node' on
+ "dir" as well as "localdir" to mimic emacs-19.22 "dir" merging
+ behaviour.
+
+Fri Dec 3 13:41:44 1993 Brian J. Fox (bfox@ai.mit.edu)
+
+ * info/info-utils.c (canonicalize_whitespace): Suppress whitespace
+ found at the start of STRING.
+
+Sat Nov 20 14:00:50 1993 Brian J. Fox (bfox@hippie)
+
+ * info/indices.c (DECLARE_INFO_COMMAND): Fix typo in assignment to
+ `old_offset' (= instead of ==).
+
+Tue Nov 2 12:22:40 1993 Brian J. Fox (bfox@ai.mit.edu)
+
+ * makeinfo/makeinfo.c (make_index_entries_unique): New function
+ makes a sorted array have all unique entries by appending numbers
+ to the ends of strings.
+ (sort_index): Call `make_index_entries_unique'.
+
+Mon Sep 20 12:04:05 1993 Brian J. Fox (bfox@ai.mit.edu)
+
+ * makeinfo/makeinfo.c (get_execution_string): New Function returns
+ a pointer to an EXECUTION_STRING structure.
+ (execute_string): No longer uses a static string; call
+ `get_execution_string' instead in order to get a free buffer for
+ consing.
+
+Sun May 23 07:00:20 1993 Noah Friedman (friedman@prep.ai.mit.edu)
+
+ * Texinfo 3.1 released.
+
+Sat May 22 18:21:27 1993 Noah Friedman (friedman@prep.ai.mit.edu)
+
+ * info/info.c (info_patch_level): Increment constant to 1.
+
+ * info/Makefile.in (DEFAULT_INFOPATH): Default definition deleted.
+ Makefile.in: Put it here instead.
+ * Makefile.in (MDEFINES): Add DEFAULT_INFOPATH.
+
+ * configure.in: check for vfprintf and vsprintf.
+
+ * makeinfo/makeinfo.c: Version 1.55.
+
+ * makeinfo/makeinfo.c (add_word_args, execute_string) [HAVE_VARARGS_H]:
+ Don't use this definition unless HAVE_VSPRINTF is also defined.
+ (error, line_error, warning) [HAVE_VARARGS_H]: Don't use this
+ definition unless HAVE_VFPRINTF is also defined.
+ Remove indentation of all cpp directives, except for #pragma.
+
+Fri May 21 14:34:24 1993 Noah Friedman (friedman@prep.ai.mit.edu)
+
+ * texinfo.texi: Rename to texi.texi.
+ Change @setfilenname and START-INFO-DIR-ENTRY to `texi.info'.
+
+ * Makefile.in (MDEFINES): Pass LDFLAGS to sub-makes.
+ (realclean): Delete `configure'.
+ Changed all references to texinfo.info to texi.info
+
+ * configure.in: Add AC_PROG_RANLIB, and AC_CONST.
+ Check for `rindex' function.
+ Check for varargs.h.
+ Clean up symbol names for header files so a single AC_HAVE_HEADERS
+ can be used.
+ (AC_INIT): Use texi.texi instead of makeinfo/makeinfo.c
+
+ * info/info-utils.h: Copy definitions of bcopy, index, and rindex
+ (with appropriate #ifdef wrappers) from termdep.h. These are
+ included by a mutually exclusive set of files.
+
+ * info/termdep.h [HAVE_SYS_PTEM]: Use HAVE_SYS_PTEM_H instead.
+
+ * info/terminal.c, info/termdep.h [HAVE_TERMIO]: Use HAVE_TERMIO_H
+ instead.
+
+ * info/makedoc.c, info/filesys.c [!O_RDONLY]: Include fcntl.h or
+ sys/fnctl.h, depending on whether HAVE_SYS_FCNTL_H is set.
+
+ * info/termdep.h: Remove all indentation in #-exprs.
+ Remove old assumptions about bcopy, index, and rindex.
+ [HAVE_BCOPY]: Define bcopy.
+ [HAVE_RINDEX]: Define index and rindex.
+
+ * info/nodes.c (info_get_node): Don't call stricmp if nodename is
+ NULL. Remove indentation in #-exprs.
+
+ * info/echo_area.c (echo_area_stack_depth): Declare static.
+
+ * info/Makefile.in (DEFAULT_INFOPATH): Make separate Makefile
+ variable so it can be overridden more easily by the user. Add `.'
+ to beginning of path.
+ (clean): Delete core.* (386bsd core files).
+ (MAKEDOC): Variable removed. Refer to `makedoc' explicitly.
+ (funs.h): Add `:' commands after if, to avoid spurious nonzero
+ exit statuses.
+
+ * info/userdoc.texi: Improved comments explaining its purpose.
+
+ * makeinfo/makeinfo.c [HAVE_VARARGS_H]: Include varargs.h.
+ (error, line_error, warning, add_word_args,
+ execute_string)[HAVE_VARARGS_H]: New versions that
+ use varargs. From bfox.
+
+ * makeinfo/Makefile.in (clean): Delete core.* (386bsd core files).
+
+ * util/Makefile.in (clean): Remove core.* (386bsd core files).
+
+ * libtxi/Makefile.in: Remove all references to $(common).
+ (RANLIB): New variable, set from autoconf.
+ (libtxi.a): Use $(RANLIB) instead of `ranlib' in target rules.
+ (clean): Delete core.* (386bsd core files).
+
+Tue May 18 12:08:24 1993 Robert J. Chassell (bob at grackle.stockbridge.ma.us)
+
+ * emacs/texinfmt.el (texinfo-format-refill): Do not fill a section
+ title line with the asterisks, hyphens, etc. that underline
+ it in any circumstance.
+
+Sun May 16 13:53:43 1993 Noah Friedman (friedman@prep.ai.mit.edu)
+
+ * util/mkinstalldirs: handle relative pathnames.
+
+Fri May 14 20:18:49 1993 Noah Friedman (friedman@prep.ai.mit.edu)
+
+ * util/mkinstalldirs: initialize IFS if unset.
+
+Tue May 11 06:33:14 1993 Noah Friedman (friedman@prep.ai.mit.edu)
+
+ * makeinfo/makeinfo.c (cm_item): don't dereference item_func if NULL.
+
+Mon May 10 14:50:31 1993 Noah Friedman (friedman@prep.ai.mit.edu)
+
+ * Texinfo 3.0 released.
+
+ * Makefile.in (ALLOCA): Provide for substitution.
+
+Mon May 10 10:12:53 1993 Noah Friedman (friedman@prep.ai.mit.edu)
+
+ * emacs/texinfmt.el (texinfmt-version): Updated year.
+
+Fri Apr 16 04:48:03 1993 Noah Friedman (friedman@prep.ai.mit.edu)
+
+ * makeinfo/makeinfo.c: Version 1.54 from bfox.
+
+ * util/fixfonts: Replace instances of `[..]' with `test'.
+ Use more portable `test' arguments: `z$foo = z' instead of `! $foo'.
+ Robustify quoting in eval assignments.
+ (textfmdir, texpkdir, texgfdir): Don't override definition from
+ environment, if any.
+ Trap EXIT, SIGHUP, SIGINT, SIGQUIT, SIGTERM to delete temp files
+ instead of trying to remove them explicitly before calling exit.
+ When changing cwd, do so in subshell, in case various tex*dir
+ variables are relative.
+ Don't use `head', `dirname', or `basename'. These don't behave
+ consistently and/or don't even exist on some systems. They can
+ all be emulated with `sed' anyway.
+ (tempfile2_line1): New variable. Use it instead of running
+ process to extract first line out of tempfile2 multiple times.
+ Eliminate some gratuitous uses of $tempfile2, such as in for loops.
+
+Fri Mar 26 23:25:13 1993 Noah Friedman (friedman@prep.ai.mit.edu)
+
+ * texinfo.texi: @setfilename texinfo.info.
+
+ * makeinfo/makeinfo.c (reader_loop, end_insertion): Fix typos in
+ comments.
+ (handle_variable_internal): Handle the case that there further
+ menu text after a false ifset/ifclear.
+
+ * util/texi2dvi: Version 0.4
+ Replace all instances of `[ ... ]' with `test'.
+ Updated bug-reporting address.
+
+Thu Mar 25 12:31:30 1993 Noah Friedman (friedman@prep.ai.mit.edu)
+
+ * info/Makefile.in (install): Install info.1 man page.
+ (uninstall): Remove installed info.1 man page.
+
+ * info/infoman.texi: Standalone manual renamed to info-stnd.texi.
+ Makefile.in: Targets updated appropriately.
+
+ * info/Makefile.in (LDEFS): New variable. Use it for info-local
+ macros, since DEFS will be inherited from parent make and any
+ local definitions will get clobbered.
+
+ * info/RELEASE: Renamed to info/NEWS.
+
+ * README: New file.
+
+ * Makefile.in (topclean): New target.
+
+ * Getting-started: Renamed to INTRODUCTION. Former name is too
+ long (over 14 chars).
+
+ * New-features: Renamed to NEWS.
+
+ * Makefile.in (MDEFINES): Set it.
+
+ * Makefile.in (dist): Use --gzip option to tar to make sure
+ resulting file is compressed with gzip. Change tar file
+ extension from `.Z' to `.z'.
+
+ * Makefile.in (DISTFILES): Filter out any file or directory names
+ starting with `='.
+
+ * fixfonts: Moved to util/fixfonts.
+
+ * RELEASE: Deleted.
+
+ * makeinfo/Makefile.in (VPATH): Use $(srcdir), not @srcdir@.
+ (common): Use ../libtxi, not ../common.
+ (makeinfo.in): Run makeinfo with --no-split.
+
+ * makeinfo/makeinfo.texi: Changes from bob.
+
+ * util/Makefile.in (VPATH): Use $(srcdir), not @srcdir@.
+ (common): Use ../libtxi, not ../common.
+
+ * util/fixfonts: Moved from top-level directory.
+
+Wed Mar 24 10:21:31 1993 Robert J. Chassell (bob at grackle)
+
+ * emacs/texinfmt.el (texinfo-format-region): Do not require
+ `@setfilename' line; delete `\input texinfo' line if part of
+ region.
+
+ * emacs/texinfmt.el (texinfo-raise-lower-sections): Raise or lower the
+ hierarchical level of chapters, sections, etc. according to
+ `@raisesections' and `@lowersections' commands.
+
+Thu Mar 18 16:02:27 1993 Robert J. Chassell (bob at grackle)
+
+ * emacs/texinfo.el (texinfo-show-structure): Indent *Occur* buffer
+ according to the structure of the file.
+
+Sat Mar 6 05:16:44 1993 Noah Friedman (friedman@prep.ai.mit.edu)
+
+ * util/texi2dvi: use ${1+"$@"}, not just "$@".
+
+Tue Feb 2 08:38:06 1993 Noah Friedman (friedman@prep.ai.mit.edu)
+
+ * info/Makefile.in: Replace all "--nosplit" arguments to makeinfo
+ with "--no-split"
+
+Sun Jan 31 18:16:58 1993 Noah Friedman (friedman@prep.ai.mit.edu)
+
+ * util/texi2dvi: Don't put .dvi and related auxillary files in same
+ directory as source files. Put them in current directory instead.
+ (TEXINPUTS_orig): New variable.
+ (file_texi): Variable removed.
+ (filename_texi): New variable.
+ (command_line_filename): Use this wherever references to file_texi
+ occured except in setting filename_noext.
+ (TEXINPUTS): Current directory and source directory where input
+ file resides prepended to standard path before invoking TeX.
+
+Wed Jan 27 16:24:37 1993 Noah Friedman (friedman@prep.ai.mit.edu)
+
+ * util/Makefile.in: overhauled.
+
+Tue Jan 26 21:04:23 1993 Noah Friedman (friedman@prep.ai.mit.edu)
+
+ * Makefile.in, info/Makefile.in, makeinfo/Makefile.in: Overhauled.
+
+ * configure.in: Renamed from texinfo.in.
+ Incorporated makeinfo/makeinfo.in, info/info.in, and
+ util/util.in. Create all child Makefiles.
+
+ * makeinfo/makeinfo.in, info/info.in: Deleted (incorporated into
+ top configure.in).
+
+ * util/util.in: Deleted (incorporated into ../configure.in).
+
+Mon Jan 25 10:59:49 1993 Brian Fox (bfox@cubit)
+
+ * info/info.c: New version 2.9; new variable INFO_PATCH_LEVEL
+ appears in the version string if it is non-zero. New function
+ version_string () produces the current version string, as in 2.8-p1.
+
+ * info/dir.c: New file implements Gillespies `localdir' hacks.
+
+ * info/nodes.c (info_get_node): Now calls maybe_build_dir_node ()
+ if the file name to look for is "dir".
+
+ * info/nodes.h: New flag N_CannotGC unconditionally prevents garbage
+ collection of a file buffer's contents. Used when "dir" is made
+ from at least one "localdir".
+
+Fri Jan 22 11:36:42 1993 Brian Fox (bfox@cubit)
+
+ * info/footnotes.c: Do not declare auto_footnotes_p as "extern" in
+ this file.
+
+Thu Jan 21 08:57:08 1993 Brian Fox (bfox@cubit)
+
+ * info/info.c: New version 2.8.
+
+ * info/userdoc.texi, info/infoman.texi, info/info.texi: Fully
+ document Info; create both online and printed manual versions.
+ "userdoc.texi" contains exactly the documentation for GNU Info 2.x.
+ "infoman.texi" is a wrapper for that file; it is meant to produce
+ printed documentation. "info.texi" has the user documentation as a
+ complete chapter within itself, but continues to contain the Info
+ tutorial.
+
+ * info/makedoc.c: Convert "ea_" into "echo_area_" when creating the
+ command name.
+
+Fri Jan 15 16:50:35 1993 Brian Fox (bfox@cubit)
+
+ * info/search.c (skip_node_characters): New argument NEWLINES_OKAY if
+ non-zero says that newlines should be skipped over during parsing.
+
+ * info/info-utils.c (info_parse_node): New argument NEWLINES_OKAY if
+ non-zero says that newlines should be skipped while parsing out
+ the nodename specification.
+
+Wed Jan 13 14:42:33 1993 Brian Fox (bfox@cubit)
+
+ * info/makedoc.c: Remove "info_" from the front of the command name
+ before installing it.
+
+ * info/session.c (info_menu_or_ref_item): A label of "Menu" is okay if
+ the builder is not info_menu_of_node ();
+
+ * info/m-x.c: New function replace_in_documentation () replaces \\[foo]
+ with the keystrokes you type to get that command. Now used in
+ indices.c, info.c, infodoc.c.
+
+Mon Jan 11 10:27:41 1993 Brian Fox (bfox@cubit)
+
+ * info/variables.c, h: New files contain describe-variable and stuff
+ moved out of m-x.c.
+
+ * info/m-x.c: Move VARIABLE_ALIST and variable functions into
+ variables.c. Add documentation string to variable definition.
+
+ * info/echo_area.c (push_echo_area): Zero the contents of
+ echo_area_completion_items after pushing the vars.
+
+Sat Jan 9 11:59:47 1993 Brian Fox (bfox@cubit)
+
+ * info/Makefile.in: Add footnotes.c,h,o to the appropriate Makefile
+ variables.
+
+ * info/window.c (window_tile_windows): New function divides the
+ available space among the visible windows.
+
+ * info/session.c (info_tile_windows): New function calls
+ window_tile_windows.
+
+ * info/footnotes.c, footnotes.h: New file implements functions for
+ aiding automatic footnote display when entering a node which has
+ footnotes.
+
+ * info/m-x.c: New user-variable "automatic-footnotes".
+
+ * info/window.c (window_physical_lines) New function counts the
+ carriage returns found in NODE.
+
+Wed Jan 6 11:24:19 1993 Brian Fox (bfox@cubit)
+
+ * info/general.h: #include <unistd.h> if we have it.
+
+Tue Jan 5 11:12:33 1993 Brian Fox (bfox@cubit)
+
+ * info/info-utils.c (info_concatenate_references): If either arg is
+ NULL, return the other arg.
+
+ * info/indices.c (info_indices_of_file_buffer): Simplified and
+ corrected loop through tags/nodes of file buffer looking for
+ indices.
+
+ * info/search.c (skip_node_characters): Rewrite "if" statement for
+ clarification and conciseness.
+
+Fri Jan 1 03:18:26 1993 Brian Fox (bfox@cubit)
+
+ * info/info.in: Check for setvbuf (), and check to see whether the args
+ are reversed.
+
+ * info/dribble.c (open_dribble_file) Check HAVE_SETVBUF and
+ SETVBUF_REVERSED when setting the buffering on info_dribble_file.
+
+Thu Dec 31 20:14:13 1992 Brian Fox (bfox@cubit)
+
+ * info/session.c (info_select_reference) If the node couldn't be found,
+ look for the label as a filename (i.e., "(LABEL)Top").
+
+Wed Dec 30 01:57:50 1992 Brian Fox (bfox@cubit)
+
+ * New Version 2.7 Beta.
+
+ * info/echo_area.c: Numerous functions now do something with the
+ numeric argument. Kill ring implemented, as well as yank and
+ yank_pop. Also transpose-chars.
+
+ * info/window.c (window_make_modeline): Check node->flags for
+ N_IsCompressed and display "zz" in the modeline if the node comes
+ from a file which is compressed on disk.
+
+Mon Dec 28 17:33:12 1992 Brian Fox (bfox@cubit)
+
+ * info/filesys.c, info/nodes.c: New member of FILE_BUFFER "FILESIZE"
+ contains the size of file_buffer->contents. finfo.st_size is no
+ longer relied upon to read the contents of files, since the new
+ function (filesys_read_info_file) can read compressed files.
+
+ * info/filesys.c (info_find_fullpath) If a file starts with a slash (or
+ tilde expansion causes it to start with a slash) still call
+ info_find_file_in_path () on it so that we can find files with
+ compression suffixes.
+
+ * info/m-x.c: New variable "gc-compressed-files".
+
+Tue Dec 22 03:45:28 1992 Brian Fox (bfox@cubit)
+
+ * info/info.c: Version 2.6 Beta.
+
+ * info/indices.c (info_index_next): Improve the final search for the
+ matched index entry.
+
+ * info/session.c (move_to_screen_line): New function implements `M-r'.
+ Given a numeric argument, move point to the start of that line in
+ the current window; without an arg, move to the center line.
+ * infomap.c: Put move_to_screen_line () on `M-r'.
+
+ * info/nodes.c (adjust_nodestart): Don't set N_UpdateTags unless the
+ node came from a tags table.
+
+ * info/nodes.c (info_find_file_internal): If the filename being looked
+ for doesn't start with a `/', then additionally compare the
+ filename against the fullpath of the file buffer sans the
+ directory name. This can happen when selecting nodemenu items.
+
+Mon Dec 21 10:07:18 1992 Brian Fox (bfox@cubit)
+
+ * info/session.c, info/display.c: Remove all references to
+ active_window_ch, active_window_cv, cursor_h, and cursor_v. The
+ single function display_cursor_at_point () is used for all cursor
+ movement, and to place the terminal's cursor at the right location
+ on the screen.
+
+Sat Dec 19 12:01:33 1992 Brian Fox (bfox@cubit)
+
+ * info/nodemenu.c: New file implements a few functions for manipulating
+ previously visited nodes. `list-visited-nodes' produces a menu of
+ the nodes that could be reached by info_history_node () in some
+ window. `select-visited-node' is similar to `list-visited-node'
+ followed by `info-menu-item', but doesn't display a window with
+ the visited nodes menu.
+
+ * info/session.c (info_numeric_arg_digit_loop): If redisplay had been
+ interrupted, then redisplay all of the windows while waiting for
+ input.
+
+ * info/display.c (display_was_interrupted_p): New variable keeps track
+ of interrupted display. Used in
+ info/session.c:info_numeric_arg_digit_loop ().
+
+ * info/session.c (info_global_next, info_global_prev): Use the numeric
+ argument passed to determine how many nodes to move.
+
+ * info/session.c (info_scroll_forward, info_scroll_backward): If the
+ invoking key is not SPC or DEL only do Page Only scrolling.
+
+Thu Dec 17 01:34:22 1992 Brian Fox (bfox@cubit)
+
+ * info/display.c (display_update_one_window): Allow W_NoWrap to affect
+ window display.
+
+ * info/window.c (calculate_line_starts): Now takes a WINDOW * as an
+ argument, and simply does the calculation, placing the results
+ into window->line_starts and window->line_count. It also handles
+ W_NoWrap in window->flags.
+
+Mon Dec 14 02:18:55 1992 Brian Fox (bfox@cubit)
+
+ * info/session.c (info_backward_scroll): Don't try to get previous node
+ if the top of the node isn't currently being displayed.
+
+ * info/window.c (window_adjust_pagetop) Use new variable
+ "window_scroll_step" to attempt to control the amount which the
+ window scrolls.
+
+ * info/m-x.c (info_variables) Add "scroll-step" to the list.
+
+Thu Dec 10 08:52:10 1992 Brian Fox (bfox@cubit)
+
+ * info/m-x.c: New variable entry show-index-matches. When set to
+ non-zero the matched portion of the search string is indicated
+ with ` and '. Perhaps I should use `|' inst|ea|d?
+
+ * info/echo_area.c (ea_possible_completions): Always build completions
+ before checking to see how many there were.
+
+ * info/info-utils.c: (info_concatenate_references): New utility
+ function concatenates references.
+
+ * info/Makefile.in: Add indices.c and indices.h to SRCS and HDRS.
+ Add indices.c to CMDFILES.
+
+ * info/indices.c, info/indices.h: New file implements `i' and `,'
+ commands of info, and provides index searching capabilities.
+
+ * info/echo_area.c (info_read_completing_in_echo_area): Split off into
+ separate callable function info_read_completing_internal ().
+
+ * info/echo_area.c (info_read_maybe_completing): New function calls
+ info_read_completing_internal () with non-forcing argument.
+
+ * info/session.c: Rename down_next_upnext_or_error () and
+ prev_up_or_error () to forward_move_node_structure (), and
+ backward_move_node_structure (). Implement new commands
+ info_global_next () and info_global_prev ().
+
+ * info/infomap.c (initialize_info_keymaps): Bind `[' and `]' to
+ backward_, forward_move_node_structure () respectively.
+
+ * info/session.c (info_menu_digit): Called with "0" as arg, select the
+ last menu item.
+
+ * info/infomap.c (initialize_info_keymaps): "0" calls
+ info_menu_digit ().
+
+ * info/session.c (info_move_to_xref): Take dir into account when there
+ are xrefs and menu items in the node and we are wrapping
+ backwards.
+
+Tue Dec 8 09:57:58 1992 Brian Fox (bfox@cubit)
+
+ * info/info.c: Version 2.5 Beta.
+
+ * info/terminal.c (terminal_insert_lines, terminal_delete_lines) Do not
+ expect tgoto to return a new string; it returns the address of a
+ static buffer.
+
+ * info/infodoc.c (info_find_or_create_help_window) Correct check for
+ prior existing help node.
+
+ * info/m-x.c (set_variable): Allow variables to have a list of choices.
+ Add new variable scroll-behaviour.
+
+ * info/session.c (down_next_upnext_or_error, prev_up_or_error) New
+ functions implement user-controlled behaviour when attempting to
+ scroll past the bottom or top of a node. New variable
+ info_scroll_behaviour is user visible as "scroll-behaviour".
+
+ * info/session.c (info_scroll_forward, info_scroll_backward) Call new
+ functions for user-controlled scroll behaviour.
+
+ * info/terminal.c (terminal_initialize_terminal) Set PC from BC not
+ from BUFFER.
+
+Mon Dec 7 11:26:12 1992 Brian Fox (bfox@cubit)
+
+ * util/texindex.c: Change EXIT_SUCCESS and EXIT_FATAL to TI_NO_ERROR
+ and TI_FATAL_ERROR respectively. This avoids namespace conflicts
+ on NeXT 2.0.
+
+Sat Dec 5 00:07:59 1992 Brian Fox (bfox@cubit)
+
+ * info/info.c: New option "--subnodes" says to recursively dump the
+ menus of the nodes that you wish to dump. Menu items which point
+ to external nodes are not dumped, and no node is dumped twice.
+
+Thu Dec 3 16:11:02 1992 Brian Fox (bfox@cubit)
+
+ * info/session.c (info_error) Don't ring the bell if
+ info_error_rings_bell_p is zero. (info_abort_key) Ring the bell
+ if printing "Quit" in the echo area wouldn't do it.
+
+ * info/m-x.c (set_variable) New functions allows setting of
+ variables in the echo area. Currently, only visilble-bell and
+ errors-ring-bell are implemented.
+
+Wed Dec 2 13:11:37 1992 Brian Fox (bfox@cubit)
+
+ * info/nodes.c, info/makedoc.c: If O_RDONLY is not defined by
+ sys/file.h, include sys/fcntl.h.
+
+ * info/filesys.c (info_file_in_path): Expand leading tildes found
+ within directory names.
+
+ * info/terminal.c (terminal_initialize_terminal) Set ospeed to 13 if
+ not settable any other way. It is an index into an array of
+ output speeds.
+
+ * info/display.c (free_display) Do not free a NULL display.
+
+ * info/display.c (string_width): New functions returns the width of
+ STRING when printed at HPOS.
+
+Sun Nov 29 01:24:42 1992 Brian Fox (bfox@cubit)
+
+ * info/info.c: New version 2.4 beta.
+
+ * info/general.h: #define info_toupper and info_tolower which check
+ their arguments before performing any conversion.
+
+ * info/search.c, info/echo_area.c: Use info_toupper.
+
+Sat Nov 28 14:23:24 1992 Brian Fox (bfox@cubit)
+
+ * info/session.c (info_scroll_forward, info_scroll_backward) If at
+ last/first page of the node, and the last command was
+ forward/backward, do info_next/prev/_node.
+
+ * info/session.c: New function info_select_reference_this_line gets
+ menu or cross reference immediately.
+
+ * info/infomap.c (initialize_info_keymaps): Add info_keymap[LFD] to
+ invoke info_select_reference_this_line ().
+
+ * info/session.c (info_last_reference) Rename to
+ info_history_reference. Wrote info_last_reference, and
+ info_first_reference which go to the last or first node of an info
+ file.
+
+Fri Nov 27 00:59:02 1992 Brian Fox (bfox@cubit)
+
+ * info/info.c: New version 2.3. Completed implementing contents of
+ TODO file.
+
+ * info/session.c (info_redraw_display): Fix C-l with numeric arg.
+
+Thu Nov 26 20:14:18 1992 Brian Fox (bfox@cubit)
+
+ * info/m-x.c: New file implements reading named commands in the echo
+ area, along with a new function "info-set-screen-height".
+ Compilation of this file and some code in others controlled by the
+ Makefile variable NAMED_COMMANDS (set to -DNAMED_COMMANDS).
+
+ * info/window.c (window_new_screen_size) Rewrite from scratch, allowing
+ clean growth and shrinkage of the screen. New variable
+ window_deletion_notifier is a pointer to a function to call when
+ the screen changes size, and some windows have to get deleted.
+ The function is called with the window to be deleted as an
+ argument, and it should clean up dangling references to that
+ window.
+
+ * info/session.c (initialize_info_session): Set
+ window_deletion_function to forget_window_and_nodes.
+
+ * info/display.c (display_update_one_window): If the first row of the
+ window to display wouldn't appear in the_screen, don't try to
+ display it. This happens when the screen has been made
+ unreasonably small, and we attempt to display the echo area.
+
+Tue Nov 24 00:47:20 1992 Brian Fox (bfox@cubit)
+
+ * Release Info 2.2.
+
+ * info/session.c: New functions implement reading typeahead and
+ implement C-g flushing typed ahead characters.
+ (info_search_internal): allows C-g to exit multi-file searches.
+
+Mon Nov 23 01:53:35 1992 Brian Fox (bfox@cubit)
+
+ * info/nodes.c: Remove calls to sscanf (), replacing them with calls to
+ atol (), since that is much faster.
+ (get_nodes_of_tags_table) Only check for "(Indirect)" if we
+ haven't parsed any nodes out of the tags table. Increase the
+ amount that file_buffer->nodes grows to 100 from 50. These two
+ together sufficiently speed up the parsing process.
+
+ * info/nodes.c: info_get_node_of_file_buffer_tags (),
+ info_get_node_of_file_buffer_nodes (): Search the appropriate list
+ and return a node. This was simply a cut and paste edit to
+ functionalize the code.
+
+ * info/TODO: Remove suggestion for partial tag parsing, since tag
+ parsing is much faster now.
+
+Sat Nov 21 02:48:23 1992 Brian Fox (bfox@cubit)
+
+ * info/makedoc.c: New File replaces makedoc.sh shell script.
+
+ * info/infomap.c: Install info_isearch (on C-s) and
+ info_reverse_isearch (on C-r) for Info windows.
+
+ * info/session.c (incremental_search, info_isearch,
+ info_reverse_isearch) New functions implement incremental
+ searching.
+
+Fri Nov 20 00:01:35 1992 Brian Fox (bfox@cubit)
+
+ * info/terminal.c (terminal_initialize_terminal): Declare and set up
+ `ospeed'. Turn off C-s and C-q processing.
+
+ * info/session.c (info_show_point) When this function is called, the
+ desired result is to show the point immediately. So now it calls
+ set_window_pagetop () if the new pagetop is not the same as the
+ old one. This means that info_prev_line (), info_next_line (),
+ info_forward_word (), and info_backward_word () can all scroll the
+ window if they have to.
+
+Thu Nov 19 12:27:07 1992 Brian Fox (bfox@cubit)
+
+ * info/session.c (set_window_pagetop): Add scrolling to make this
+ faster.
+
+ * info/echo_area.c (push/pop_echo_area): Remember the list of items to
+ complete over.
+
+ * info/session.c (info_forward_char): Don't let point get equal to
+ nodelen, only to nodelen - 1.
+
+ * info/display.c: New function display_scroll_display () scrolls the
+ rmembered display as well as the text on the actual display.
+
+ * info/terminal.c: New functions terminal_scroll_terminal (),
+ terminal_scroll_down (), and terminal_scroll_up (). All
+ implemented using "al" and "dl" termcap capabilities. (i.e.,
+ insert and delete line).
+
+Wed Nov 18 15:05:14 1992 Brian Fox (bfox@cubit)
+
+ * info/termdep.h: Only define HAVE_FCNTL_H if !aix and !ultrix.
+
+Tue Nov 17 20:35:08 1992 Brian Fox (bfox@cubit)
+
+ * First Beta Release of Info 2.0.
+
+Sun Nov 1 02:21:05 1992 Noah Friedman (friedman@prep.ai.mit.edu)
+
+ * util/texi2dvi (--force): Option removed. Always run tex at least
+ once, don't bother checking if .dvi file is newer than source.
+
+Fri Oct 30 02:16:28 1992 Noah Friedman (friedman@prep.ai.mit.edu)
+
+ * util/texi2dvi (-D): debugging option renamed from '-d'.
+ Made check to enable debugging more terse.
+ When checking if index files have changed, use
+ variable $this_file instead of $file in for loop.
+ (file_texi): wherever the variable $file was used to reference
+ the texinfo file, substituted $file_texi.
+
+Sat Oct 17 07:30:34 1992 Brian J. Fox (bfox@helios)
+
+ * util/texindex.c: Remove references to USG replacing them with a
+ define declaring the actual feature required or missing.
+
+Thu Oct 15 16:17:47 1992 Robert J. Chassell (bob@nutrimat.gnu.ai.mit.edu)
+
+ * emacs/texinfmt.el (texinfo-format-setfilename): Remove date from
+ Info file header so regression testing is easier.
+
+Tue Sep 15 16:28:35 1992 Robert J. Chassell (bob at grackle)
+
+ * emacs/texinfmt.el (texinfmt-version): New variable.
+ (texinfo-format-setfilename): Include date and
+ version in Info file header.
+ Better documentation for @definfoenclose
+ Handle whitespace after @end iftex, etc.
+
+Thu Sep 3 09:25:37 1992 Robert J. Chassell (bob at grackle)
+
+ * emacs/texnfo-upd.el: Fix typo re `texinfo-sequential-node-update.'
+
+Tue Aug 18 08:56:24 1992 Robert J. Chassell (bob at grackle)
+
+ * emacs/texinfmt.el (texinfo-value): Revise syntax.
+
+ * emacs/texnfo-upd.el (texinfo-start-menu-description):
+ New function to insert title as description in a menu.
+ (texinfo-make-menu-list): Remove automatic title insertion.
+
+ * emacs/texinfo.el (texinfo-mode-map): Add keybinding for
+ texinfo-start-menu-description.
+
+Wed Jul 29 11:58:53 1992 Robert J. Chassell (bob at grackle)
+
+ * emacs/texinfmt.el (texinfo-set): Revise to set a string to the flag.
+ (texinfo-value): @value{flag}: New command which inserts the
+ string to which the flag is set.
+
+Tue Jul 7 15:10:52 1992 Robert J. Chassell (bob at grackle)
+
+ * emacs/texnfo-upd.el (texinfo-master-menu): Error message if file
+ contains too few nodes for a master menu.
+ (texinfo-insert-master-menu-list): Only attempt to insert detailed
+ master menu if there is one.
+
+Wed Jun 10 15:26:18 1992 Robert J. Chassell (bob at grackle)
+
+ * emacs/texinfmt.el (texinfo-append-refill): Refill properly when lines
+ begin with within-paragraph @-commands.
+
+Tue Jun 9 12:28:11 1992 Robert J. Chassell (bob at grackle)
+
+ * emacs/texinfmt.el: Add `texinfo-deffn-formatting-property' and
+ `texinfo-defun-indexing-property' to @deffn commands.
+
+Mon Jun 8 11:52:01 1992 Robert J. Chassell (bob at grackle)
+
+ * emacs/texnfo-upd.el: Replace `(mark-whole-buffer)' with
+ `(push-mark (point-max) t) (goto-char (point-min))'
+ to avoid `Mark set' messages.
+
+Fri Jun 5 15:15:16 1992 Robert J. Chassell (bob@kropotkin.gnu.ai.mit.edu)
+
+ * emacs/texnfo-upd.el (texinfo-check-for-node-name): Offer section
+ title as prompt.
+ (texinfo-copy-next-section-title): Copy title correctly.
+
+Thu May 28 20:34:17 1992 Robert J. Chassell (bob@hill.gnu.ai.mit.edu)
+
+ * emacs/texinfmt.el: @vtable defined, parallel to @ftable, for
+ variables.
+ (texinfo-append-refill): set case-fold-search nil so @TeX is not
+ confused with @tex.
+
+Thu Mar 26 21:36:41 1992 Robert J. Chassell (bob@kropotkin.gnu.ai.mit.edu)
+
+ * emacs/makeinfo.el: Rename temp buffer from `*Makeinfo*' back to
+ `*compilation*' so `next-error' works; unfortunately,
+ `*compilation*' is written into the code as the name
+ `next-error' needs.
+ Rename `makeinfo-recenter-makeinfo-buffer' back to
+ `makeinfo-recenter-makeinfo-buffer'
+
+Thu May 14 21:14:25 1992 Noah Friedman (friedman@prep.ai.mit.edu)
+
+ * util/fixfonts: Enclosed most variable references with "" to prevent
+ potential globbing and other weirdness. Eliminated uses of
+ ${var-value}, which unfortunately isn't portable.
+
+ * util/texi2dvi: rewritten from scratch.
+
+Sat Apr 18 23:46:25 1992 Charles Hannum (mycroft@hal.gnu.ai.mit.edu)
+
+ * util/fixfonts: Re-evaluate prefix and libdir if inherited (to resolve
+ variable references from make).
+ (texlibdir): Don't add '/tex', since it's already there.
+
+Fri Apr 10 14:51:23 1992 Noah Friedman (friedman@prep.ai.mit.edu)
+
+ * util/fixfonts: set prefix and libdir only if they are not already
+ defined (i.e. not inherited from the environment).
+ Changed default path for libdir to be consistent with Makefile.
+
+Tue Mar 3 13:17:42 1992 Robert J. Chassell (bob at grackle)
+
+ * emacs/texnfo-upd.el (texinfo-insert-master-menu-list): Insert a
+ master menu only after `Top' node and before next node.
+ (texinfo-copy-menu): Error message if menu empty.
+
+Mon Feb 24 15:47:49 1992 Robert J. Chassell (bob at grackle)
+
+ * emacs/texinfmt.el (texinfo-format-region): Make sure region ends in a
+ newline.
+ (texinfo-itemize-item): Recognize all non-whitespace on same line
+ as @item command.
+
+Sat Feb 22 02:15:00 1992 Brian Fox (bfox at gnuwest.fsf.org)
+
+ * util/texindex.c: New version 1.45 has cleanups, should compile under
+ VMS quietly.
+
+Wed Feb 12 10:50:51 1992 Robert J. Chassell (bob at grackle)
+
+ * emacs/makeinfo.el: Rename temp buffer as *Makeinfo*.
+ Rename `makeinfo-recenter-compilation-buffer'.
+ (makeinfo-buffer): Offer to save buffer if it is modified.
+ (makeinfo-compile): Do not offer to save other buffers.
+ (makeinfo-compilation-sentinel): Switch to Info file.
+
+Tue Feb 4 13:07:39 1992 Robert J. Chassell (bob at grackle)
+
+ * emacs/texinfmt.el (texinfo-print-index): Format so that node names in
+ the index are lined up.
+
+Mon Feb 3 09:08:14 1992 Robert J. Chassell (bob at grackle)
+
+ * emacs/texinfmt.el (texinfo-itemize-item): Format entry when text
+ is on the same line as @item command. Also, handle @-commands.
+ (texinfo-format-region, texinfo-format-buffer-1): Set fill column
+ to local value of Texinfo buffer.
+
+ * emacs/texnfo-upd.el (texinfo-pointer-name): Find only those
+ section commands that are accompanied by `@node' lines.
+
+Tue Jan 14 16:10:16 1992 Robert J. Chassell (bob at grackle)
+
+ * emacs/texnfo-upd.el: Ensure that no commands depend on the value of
+ case-fold-search.
+
+Fri Jan 10 15:13:55 1992 Robert J. Chassell (bob at kropotkin)
+
+ * emacs/texinfmt.el (texinfo-append-refill): Replace use of
+ unsupported function `looking-at-backward' with
+ `re-search-backward'.
+
+Mon Dec 23 23:46:42 1991 David J. MacKenzie (djm at wookumz.gnu.ai.mit.edu)
+
+ * util/texindex.c: Change POSIX ifdefs to HAVE_UNISTD_H and
+ _POSIX_VERSION.
+
+Mon Dec 16 15:01:36 1991 Robert J. Chassell (bob at grackle)
+
+ * emacs/texinfmt.el (texinfo-append-refill): New function appends
+ @refill to all appropriate paragraphs so you no longer need to
+ append @refill command yourself.
+ (texinfo-format-region, texinfo-format-buffer-1,
+ texinfo-format-include): Call `texinfo-append-refill'.
+
+Fri Dec 6 01:25:09 1991 David J. MacKenzie (djm at wookumz.gnu.ai.mit.edu)
+
+ * util/texindex.c: Conditionalize on _AIX (which is predefined) instead
+ of AIX, just like makeinfo does.
+
+Tue Nov 26 10:21:04 1991 Robert J. Chassell (bob at grackle)
+
+ * emacs/texnfo-upd.el (texinfo-section-types-regexp): `@subtitle' no
+ longer treated as subsection.
+
+Sat Nov 16 08:27:42 1991 Richard Stallman (rms at mole.gnu.ai.mit.edu)
+
+ * util/fixfonts: New file, from Karl Berry.
+
+Tue Nov 12 16:13:24 1991 Robert J. Chassell (bob at grackle)
+
+ * emacs/texinfmt.el: Create @end smalllisp.
+
+Mon Nov 11 16:50:13 1991 Robert J. Chassell (bob at grackle)
+
+ * emacs/texinfo.el (texinfo-environment-regexp): Add all other block
+ enclosing Texinfo commands.
+
+Thu Nov 7 10:23:51 1991 Robert J. Chassell (bob at grackle)
+
+ * emacs/texinfo.el (texinfo-insert-@end): Attempt to insert correct end
+ command statement, eg, @end table. Fails with nested lists.
+ (texinfo-insert-*): Accept prefix arg to surround following N
+ words with braces for command.
+
+Thu Oct 31 21:31:41 1991 Robert J. Chassell (bob at kropotki)
+
+ * emacs/texinfmt.el (texinfo-clear): Clear flag even if flag not
+ previously set.
+
+Wed Oct 23 11:15:58 1991 Robert J. Chassell (bob at grackle)
+
+ * emacs/texinfo.el (texinfo-mode): page-delimiter now finds top node as
+ well as chapters.
+
+Tue Oct 22 11:46:12 1991 Robert J. Chassell (bob at grackle)
+
+ * emacs/texinfmt.el (texinfo-do-flushright): Test whether a line is too
+ long for the flush right command (line length must be less than
+ the value of fill column).
+
+ * emacs/texnfo-tex.el (texinfo-tex-buffer): Prompt for original file
+ even if point moved to *texinfo-tex-shell*.
+ texinfo-tex-original-file: variable to hold file name.
+
+Wed Oct 16 08:32:05 1991 Robert J. Chassell (bob at grackle)
+
+ * emacs/texinfmt.el (texinfo-format-center): Expand string before
+ centering so @-commands not included.
+
+Thu Oct 10 22:01:47 1991 Robert J. Chassell (bob at kropotki)
+
+ * emacs/texnfo-tex.el (texinfo-show-tex-print-queue): Do not kill a
+ running process; do start a process none exists.
+
+Thu Sep 26 21:58:47 1991 Robert J. Chassell (bob at kropotki)
+
+ * util/texi2dvi: Misc. bugs fixed.
+
+ * emacs/texinfo.el: Remove extraneous references to TeX.
+
+Thu Sep 19 20:45:29 1991 Robert J. Chassell (bob at kropotki)
+
+ * emacs/texinfmt.el: add @cartouche as a noop (makes box with rounded
+ corners in TeX)
+
+Tue Sep 10 20:44:57 1991 Robert J. Chassell (bob at grackle)
+
+ * emacs/texnfo-upd.el (texinfo-make-one-menu): Copy node-name correctly
+ for message.
+
+Thu Aug 29 17:54:07 1991 Robert J. Chassell (bob at kropotki)
+
+ * emacs/texnfo-tex.el (texinfo-quit-tex-job): Do not set mark.
+
+Wed Aug 21 10:36:21 1991 Robert J. Chassell (bob at grackle)
+
+ * emacs/texnfo-upd.el: (texinfo-copy-menu-title): Copy title as it
+ should rather than node line.
+
+Mon Aug 5 15:27:12 1991 Robert J. Chassell (bob at grackle)
+
+ * emacs/texinfmt.el (texinfo-format-convert): Changed regexp that
+ looks for three hyphens in a row to find those between word
+ constituent characters, as now, for Oxford Univ. style dashes and
+ also between spaces, for Cambridge Univ. Press style dashes.
+
+ * emacs/texnfo-tex.el (texinfo-tex-start-shell): Runs "/bin/sh" so
+ `explicit-shell-file-name' is not set globally.
+
+ * emacs/texnfo-upd.el: Rewrite messages.
+ (texinfo-find-higher-level-node): Stop search at limit.
+ (texinfo-copy-menu-title): Rewrite to handle outer include files.
+ (texinfo-multi-file-update): Update all nodes properly;
+ rewrite doc string and interactive.
+
+Sat Aug 3 10:46:13 1991 Robert J. Chassell (bob at grackle)
+
+ * emacs/texnfo-upd.el (texinfo-all-menus-update): Fixed typo that
+ caused the function to create a master menu when it shouldn't.
+
+ * emacs/texinfo.el (texinfo-mode): Make `indent-tabs-mode' a local
+ variable and set to nil to prevent TABs troubles with TeX.
+
+Wed Jul 31 11:07:08 1991 Robert J. Chassell (bob at grackle)
+
+ * emacs/texnfo-tex.el (texinfo-quit-tex-job): New function: quit
+ currently running TeX job, by sending an `x' to it.
+ (texinfo-tex-shell-sentinel): New function to
+ restart texinfo-tex-shell after it is killed.
+ (texinfo-kill-tex-job): Rewrite to use kill-process rather than
+ quit-process; uses `texinfo-tex-shell-sentinel' to restart
+ texinfo-tex-shell after it is killed.
+ (texinfo-tex-region, texinfo-tex-buffer): Replace
+ texinfo-kill-tex-job with quit-process.
+
+ * emacs/texinfo.el (texinfo-define-common-keys): Add keybinding for
+ texinfo-quit-tex-job
+
+Wed Jul 10 15:15:03 1991 Robert J. Chassell (bob at grackle)
+
+ * emacs/texinfmt.el: New commands @set, @clear, @ifset...@end
+ ifset, and @ifclear...@end ifclear.
+ Definition functions rewritten to make them easier to
+ maintain.
+
+Wed Jul 3 19:37:04 1991 Robert J. Chassell (bob at kropotki)
+
+ * emacs/texinfmt.el (texinfo-format-deftypefn-index): Remove reference
+ to data-type to make consistent with texinfo.tex and makeinfo.
+ texinfo.el: Fix page-delimiter and texinfo-chapter-level-regexp
+ variables.
+
+Thu Jun 27 18:35:36 1991 Robert J. Chassell (bob at nutrimat)
+
+ * emacs/texinfmt.el: Add @dmn as `texinfo-format-noop'.
+ texinfo2.texi: Document @dmn.
+ texinfmt.el (texinfo{,-end}-{eleterate,ecapitate} renamed
+ {alphaenumerate, capsenumerate}.
+
+Fri Jun 14 12:46:32 1991 Robert J. Chassell (bob at churchy.gnu.ai.mit.edu)
+
+ * emacs/texinfmt.el (texinfo-format-defun-1): @defivar prints name
+ correctly.
+
+Thu Jun 6 21:38:33 1991 Robert J. Chassell (bob at churchy.gnu.ai.mit.edu)
+
+ * emacs/texinfo.el (texinfo-mode): Set page delimiter to
+ 'texinfo-chapter-level-regexp' so that page commands work by
+ chapter or equivalent.
+
+ * emacs/texinfmt.el (texinfo-format-defun-1): @defop prints name
+ correctly.
+ (batch-texinfo-format): replace unsupported
+ 'buffer-disable-undo' with 'buffer-flush-undo'
+
+Fri Apr 5 15:17:17 1991 Robert J. Chassell (bob at wookumz.gnu.ai.mit.edu)
+
+ * emacs/makeinfo.el (makeinfo-compilation-sentinel): Check for
+ existance of makeinfo-temp-file to avoid harmless error message.
+ texinfo2.texi: Minor typos fixed.
+
+Thu Mar 28 19:13:24 1991 Robert J. Chassell (bob at pogo.gnu.ai.mit.edu)
+
+ * util/texi2dvi: Revised.
+
+Mon Mar 11 12:35:51 1991 Robert J. Chassell (bob at grackle)
+
+ * emacs/texinfmt.el: (@footnotestyle): New command to set
+ footnotestyle.
+ (@paragraphindent): New command to set indentation.
+ (texinfo-format-refill): Add indentation feature so as to
+ indent paragraph or leave indentation asis before refilling
+ according to value set by @paragraphindent command.
+ (texinfo-format-region): Insert header, if any, into Info buffer.
+ (texinfo-format-separate-node, texinfo-format-end-node): Run
+ texinfo-format-scan on footnote text only once.
+ (texinfo-format-scan): Shorten `---' to `--'.
+
+ * emacs/texinfo.el: Define key for `texinfo-master-menu'; define
+ start and end of header expressions.
+
+ * emacs/texnfo-upd.el (texinfo-all-menus-update): Update
+ pre-existing master menu, if there is one.
+
+Fri May 11 14:36:07 1990 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * util/texindex.c: Rename `lines' to `nlines'.
+ (bzero): Pass arg to lib$movc5 through non-register var.
+ (perror_with_file, pfatal_with_file): Move extern decls and includes
+ to top of file.
+ [VMS]: If not using VMS C, define away `noshare' keyword.
+ Include perror.h.
+
+Mon Jul 11 18:02:29 1988 Chris Hanson (cph at kleph)
+
+ * util/texindex.c (indexify): when comparing to initial strings to
+ decide whether to change the header, must use `strncmp' to avoid
+ comparing entire strings of which initials are a substring.
+
+Sun Jun 26 18:46:16 1988 Richard Stallman (rms at sugar-bombs.ai.mit.edu)
+
+ * util/texindex.c (sort_in_core, sort_offline, parsefile):
+ Give up on input file if any line doesn't start with backslash.
diff --git a/contrib/texinfo/INSTALL b/contrib/texinfo/INSTALL
new file mode 100644
index 0000000..a2c8722
--- /dev/null
+++ b/contrib/texinfo/INSTALL
@@ -0,0 +1,181 @@
+Basic Installation
+==================
+
+ These are generic installation instructions.
+
+ The `configure' shell script attempts to guess correct values for
+various system-dependent variables used during compilation. It uses
+those values to create a `Makefile' in each directory of the package.
+It may also create one or more `.h' files containing system-dependent
+definitions. Finally, it creates a shell script `config.status' that
+you can run in the future to recreate the current configuration, a file
+`config.cache' that saves the results of its tests to speed up
+reconfiguring, and a file `config.log' containing compiler output
+(useful mainly for debugging `configure').
+
+ If you need to do unusual things to compile the package, please try
+to figure out how `configure' could check whether to do them, and mail
+diffs or instructions to the address given in the `README' so they can
+be considered for the next release. If at some point `config.cache'
+contains results you don't want to keep, you may remove or edit it.
+
+ The file `configure.in' is used to create `configure' by a program
+called `autoconf'. You only need `configure.in' if you want to change
+it or regenerate `configure' using a newer version of `autoconf'.
+
+The simplest way to compile this package is:
+
+ 1. `cd' to the directory containing the package's source code and type
+ `./configure' to configure the package for your system. If you're
+ using `csh' on an old version of System V, you might need to type
+ `sh ./configure' instead to prevent `csh' from trying to execute
+ `configure' itself.
+
+ Running `configure' takes awhile. While running, it prints some
+ messages telling which features it is checking for.
+
+ 2. Type `make' to compile the package.
+
+ 3. Optionally, type `make check' to run any self-tests that come with
+ the package.
+
+ 4. Type `make install' to install the programs and any data files and
+ documentation.
+
+ 5. You can remove the program binaries and object files from the
+ source code directory by typing `make clean'. To also remove the
+ files that `configure' created (so you can compile the package for
+ a different kind of computer), type `make distclean'. There is
+ also a `make maintainer-clean' target, but that is intended mainly
+ for the package's developers. If you use it, you may have to get
+ all sorts of other programs in order to regenerate files that came
+ with the distribution.
+
+Compilers and Options
+=====================
+
+ Some systems require unusual options for compilation or linking that
+the `configure' script does not know about. You can give `configure'
+initial values for variables by setting them in the environment. Using
+a Bourne-compatible shell, you can do that on the command line like
+this:
+ CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure
+
+Or on systems that have the `env' program, you can do it like this:
+ env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure
+
+Compiling For Multiple Architectures
+====================================
+
+ You can compile the package for more than one kind of computer at the
+same time, by placing the object files for each architecture in their
+own directory. To do this, you must use a version of `make' that
+supports the `VPATH' variable, such as GNU `make'. `cd' to the
+directory where you want the object files and executables to go and run
+the `configure' script. `configure' automatically checks for the
+source code in the directory that `configure' is in and in `..'.
+
+ If you have to use a `make' that does not supports the `VPATH'
+variable, you have to compile the package for one architecture at a time
+in the source code directory. After you have installed the package for
+one architecture, use `make distclean' before reconfiguring for another
+architecture.
+
+Installation Names
+==================
+
+ By default, `make install' will install the package's files in
+`/usr/local/bin', `/usr/local/man', etc. You can specify an
+installation prefix other than `/usr/local' by giving `configure' the
+option `--prefix=PATH'.
+
+ You can specify separate installation prefixes for
+architecture-specific files and architecture-independent files. If you
+give `configure' the option `--exec-prefix=PATH', the package will use
+PATH as the prefix for installing programs and libraries.
+Documentation and other data files will still use the regular prefix.
+
+ In addition, if you use an unusual directory layout you can give
+options like `--bindir=PATH' to specify different values for particular
+kinds of files. Run `configure --help' for a list of the directories
+you can set and what kinds of files go in them.
+
+ If the package supports it, you can cause programs to be installed
+with an extra prefix or suffix on their names by giving `configure' the
+option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
+
+Optional Features
+=================
+
+ Some packages pay attention to `--enable-FEATURE' options to
+`configure', where FEATURE indicates an optional part of the package.
+They may also pay attention to `--with-PACKAGE' options, where PACKAGE
+is something like `gnu-as' or `x' (for the X Window System). The
+`README' should mention any `--enable-' and `--with-' options that the
+package recognizes.
+
+ For packages that use the X Window System, `configure' can usually
+find the X include and library files automatically, but if it doesn't,
+you can use the `configure' options `--x-includes=DIR' and
+`--x-libraries=DIR' to specify their locations.
+
+Specifying the System Type
+==========================
+
+ There may be some features `configure' can not figure out
+automatically, but needs to determine by the type of host the package
+will run on. Usually `configure' can figure that out, but if it prints
+a message saying it can not guess the host type, give it the
+`--host=TYPE' option. TYPE can either be a short name for the system
+type, such as `sun4', or a canonical name with three fields:
+ CPU-COMPANY-SYSTEM
+
+See the file `config.sub' for the possible values of each field. If
+`config.sub' isn't included in this package, then this package doesn't
+need to know the host type.
+
+ If you are building compiler tools for cross-compiling, you can also
+use the `--target=TYPE' option to select the type of system they will
+produce code for and the `--build=TYPE' option to select the type of
+system on which you are compiling the package.
+
+Sharing Defaults
+================
+
+ If you want to set default values for `configure' scripts to share,
+you can create a site shell script called `config.site' that gives
+default values for variables like `CC', `cache_file', and `prefix'.
+`configure' looks for `PREFIX/share/config.site' if it exists, then
+`PREFIX/etc/config.site' if it exists. Or, you can set the
+`CONFIG_SITE' environment variable to the location of the site script.
+A warning: not all `configure' scripts look for a site script.
+
+Operation Controls
+==================
+
+ `configure' recognizes the following options to control how it
+operates.
+
+`--cache-file=FILE'
+ Use and save the results of the tests in FILE instead of
+ `./config.cache'. Set FILE to `/dev/null' to disable caching, for
+ debugging `configure'.
+
+`--help'
+ Print a summary of the options to `configure', and exit.
+
+`--quiet'
+`--silent'
+`-q'
+ Do not print messages saying which checks are being made.
+
+`--srcdir=DIR'
+ Look for the package's source code in directory DIR. Usually
+ `configure' can determine that directory automatically.
+
+`--version'
+ Print the version of Autoconf used to generate the `configure'
+ script, and exit.
+
+`configure' also accepts some other, not widely useful, options.
+
diff --git a/contrib/texinfo/INTRODUCTION b/contrib/texinfo/INTRODUCTION
new file mode 100644
index 0000000..1d298ca
--- /dev/null
+++ b/contrib/texinfo/INTRODUCTION
@@ -0,0 +1,119 @@
+Getting Started with Texinfo
+============================
+
+25 March 1993
+
+Most of the installation instructions are described in the file `INSTALL'.
+One additional note to make is that if your info files are in a nonstandard
+place (i.e. not in the `info' directory immediately under $prefix) you may
+wish to change the default info path as specified via DEFAULT_INFOPATH in
+info/Makefile.in.
+
+"Texinfo" is a documentation system that uses a single source file to
+produce both on-line information and printed output. Using Texinfo,
+you can create a printed document with the normal features of a book,
+including chapters, sections, cross references, and indices. From the
+same Texinfo source file, you can create a menu-driven, on-line Info
+file with nodes, menus, cross references, and indices.
+
+The name of the Texinfo source documentation file is `texinfo.texi'.
+You can produce both on-line information and printed output from this
+source file. The documentation describes Texinfo in detail, including
+how to write Texinfo files, how to format them for both hard copy and
+Info, and how to install Info files.
+
+To get started, you need to create either a printed manual or an
+on-line Info file from the `texinfo.texi' file. You do not need to
+create both, although you will probably want both eventually.
+
+To learn how to use Info, read the info documentation. You can do this in
+one of two ways: using the standalone `info' program, or using Info mode in
+GNU Emacs.
+
+ * If you want to use the `info' program, type
+
+ $ info -f info-stnd
+
+ * If you want to use Emacs, start up emacs and type `C-h i' [M-x info].
+ Follow the instructions to learn how to use Info.
+
+After learning how to use Info, you can read the Texinfo documentation.
+Using the standalone `info', type the following at the shell prompt:
+
+ $ info -f texinfo
+
+To use read this manual in Emacs, you first need to edit the Info-directory
+menu (the file `dir' in the system info directory) to contain the
+appropriate node. To learn how to do this, see node: Add in the Info
+documentation.
+
+The Texinfo documentation describes Texinfo in detail; among other things,
+it tells how to install Info files in the usual manner. (See node: Install
+an Info File.)
+
+The `info-stnd.info' file describes the standalone Info reader in detail. To
+read this file, type
+
+ $ info -f info-stnd
+
+If you are using GNU Emacs, you may want to install the Emacs Lisp files
+permanently. Move them them to a directory in the load-path for Emacs;
+otherwise Emacs will not be able to load the autoloaded support files, such
+as `texinfmt.el'.
+
+The `texinfo.el' file contains the autoload commands; it is the only
+file that needs to be loaded initially. If your Emacs does not
+automatically load `texinfo.el', you can tell it to do so by placing
+the following in `default.el' or in your `.emacs' file:
+
+ (load "texinfo")
+
+
+To create a printed manual
+==========================
+
+You need:
+
+ * The `tex' program, which typesets the manual using TeX.
+ * The `texinfo.tex' definition file that tells TeX how to typeset
+ a Texinfo file.
+ * The `texindex' program, which sorts the unsorted index files
+ created by TeX.
+ * A printing program such as `lp' or `lpr',
+ * A printer.
+
+This Texinfo distribution package contains `texinfo.tex', the C source
+for `texindex', and the handy shell script `texi2dvi'. The `tex'
+program is not part of this distribution, but is available separately.
+(See `How to Obtain TeX' in the Texinfo documentation.)
+
+ * Install `tex'. (`texindex' is installed automagically by
+ `make install' in this distribution.)
+
+ * Move the `texinfo.tex' file to an appropriate directory; the current
+ directory will do. (`/usr/local/lib/tex/inputs' might be a good place.
+ See ``Preparing to Use TeX'' in the Texinfo manual, for more
+ information.)
+
+After following those instructions, type the following to make the .dvi
+files:
+
+ $ make texinfo.dvi
+ $ (cd info; make info.dvi info-stnd.dvi)
+ $ (cd makeinfo; make makeinfo.dvi)
+
+You can then print the resulting .dvi files with the `lpr' command (on BSD
+systems. On SysV systems the command is `lp'. Consult your man pages for
+more information).
+
+For example, the command to print the texinfo.dvi file might be:
+
+ $ lpr -d texinfo.dvi
+
+The name of the printing command depends on the system; `lpr -d' is
+common, and is illustrated here. You may use a different name for the
+printing command.
+
+Please report bugs to bug-texinfo@prep.ai.mit.edu.
+
+Happy formatting.
diff --git a/contrib/texinfo/Makefile.in b/contrib/texinfo/Makefile.in
new file mode 100644
index 0000000..3e93b61
--- /dev/null
+++ b/contrib/texinfo/Makefile.in
@@ -0,0 +1,211 @@
+# Makefile for Texinfo distribution.
+# $Id: Makefile.in,v 1.11 1996/10/04 18:40:33 karl Exp $
+#
+# Copyright (C) 1993, 96 Free Software Foundation, Inc.
+
+# 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+#### Start of system configuration section. ####
+
+srcdir = @srcdir@
+VPATH = $(srcdir):$(common)
+
+common = $(srcdir)/libtxi
+
+CC = @CC@
+
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_DATA = @INSTALL_DATA@
+
+LN = ln
+RM = rm -f
+TAR = tar
+MKDIR = mkdir
+
+DEFS = @DEFS@
+LIBS = @LIBS@
+LOADLIBES = $(LIBS)
+
+ALLOCA = @ALLOCA@
+
+SHELL = /bin/sh
+
+CFLAGS = @CFLAGS@
+LDFLAGS = @LDFLAGS@
+
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+bindir = $(exec_prefix)/bin
+# Prefix for each installed program, normally empty or `g'.
+binprefix =
+# Prefix for each installed man page, normally empty or `g'.
+manprefix =
+manext = 1
+mandir = $(prefix)/man/man$(manext)
+infodir = $(prefix)/info
+
+# For info program.
+DEFAULT_INFOPATH = $(infodir):.
+
+#### End of system configuration section. ####
+
+VERSION = 3.9
+DISTNAME = texinfo-$(VERSION)
+
+# Subdirectories that have makefiles
+SUBDIRS = libtxi makeinfo info util emacs
+
+# All subdirectories that go into a distribution
+ALL_SUBDIRS = $(SUBDIRS) makeinfo/macros
+
+MDEFINES = bindir='$(bindir)' mandir='$(mandir)' manext='$(manext)' \
+ prefix='$(prefix)' binprefix='$(binprefix)' \
+ manprefix='$(manprefix)' infodir='$(infodir)' CFLAGS='$(CFLAGS)' \
+ CC='$(CC)' ALLOCA='$(ALLOCA)' LDFLAGS='$(LDFLAGS)' \
+ DEFAULT_INFOPATH='$(DEFAULT_INFOPATH)'
+
+all: sub-all texinfo
+
+install: all installdirs
+ test -f $(infodir)/dir || $(INSTALL_DATA) $(srcdir)/dir $(infodir)
+ for dir in $(SUBDIRS); do \
+ echo making $@ in $$dir; \
+ (cd $$dir && $(MAKE) $(MDEFINES) $@ || exit 1); \
+ done
+ d=$(srcdir); test -f ./texinfo && d=.; \
+ (cd $$d && for f in texinfo texinfo-* ; do \
+ $(INSTALL_DATA) $$f $(infodir)/$$f; done)
+ $(POST_INSTALL)
+ ./util/install-info --info-dir=$(infodir) $(infodir)/texinfo
+ @echo Please install $(srcdir)/texinfo.tex manually.
+
+installdirs:
+ -$(SHELL) $(srcdir)/util/mkinstalldirs $(bindir) $(datadir) $(infodir) $(mandir)
+
+uninstall:
+ for dir in $(SUBDIRS); do \
+ echo making $@ in $$dir; \
+ (cd $$dir && $(MAKE) $(MDEFINES) $@ || exit 1); \
+ done
+ $(RM) $(infodir)/texinfo $(infodir)/texinfo-*
+
+Makefile: Makefile.in config.status
+ $(SHELL) ./config.status
+
+config.status: configure
+ $(SHELL) ./config.status --recheck
+
+configure: configure.in
+ cd $(srcdir) && autoconf
+
+sub-all TAGS:
+ for dir in $(SUBDIRS); do \
+ echo making $@ in $$dir; \
+ (cd $$dir && $(MAKE) $(MDEFINES) $@ || exit 1); \
+ done
+.PHONY: sub-all
+
+clean mostlyclean:
+ for dir in $(SUBDIRS); do \
+ echo making $@ in $$dir; \
+ (cd $$dir && $(MAKE) $(MDEFINES) $@ || exit 1); \
+ done
+
+distclean: clean texclean
+ for dir in $(SUBDIRS); do \
+ echo making $@ in $$dir; \
+ (cd $$dir && $(MAKE) $(MDEFINES) $@ || exit 1); \
+ done
+ $(RM) Makefile *.status *.cache *.log texinfo texinfo-? texinfo-??
+
+texclean:
+ $(RM) *.aux *.cp *.cps *.dvi *.fn *.fns *.ky *.kys *.pg *.pgs
+ $(RM) *.toc *.tp *.tps *.vr *.vrs
+
+realclean: distclean
+
+# Let's hope we weren't cross-compiling.
+# If we depend on sub-all, this always gets remade. Annoying.
+info texinfo: texinfo.texi
+ ./makeinfo/makeinfo -I$(srcdir) texinfo.texi
+.PHONY: info
+
+dvi texinfo.dvi:
+ PATH="$(srcdir)/util:$${PATH}" TEXINPUTS="$(srcdir):$(common):$${TEXINPUTS}" texi2dvi $(srcdir)/texinfo.texi
+.PHONY: dvi
+
+dist: DISTFILES
+ $(RM) -r $(DISTNAME)
+ $(MKDIR) $(DISTNAME)
+ for d in `find . -type d ! -name RCS -print`; do \
+ d=`echo $$d | grep -v '[@=]'`; \
+ test -z "$$d" || test "$$d" = . || test "$$d" = "./$(DISTNAME)" \
+ || mkdir $(DISTNAME)/$$d; done
+ for f in `cat DISTFILES`; do \
+ $(LN) $(srcdir)/$$f $(DISTNAME)/$$f || \
+ { echo copying $$f; cp -p $(srcdir)/$$f $(DISTNAME)/$$f ; } \
+ done
+ (cd $(DISTNAME); $(MAKE) $(MFLAGS) distclean)
+ $(TAR) chvf - $(DISTNAME) | gzip >$(DISTNAME).tar.gz
+ $(RM) -r $(DISTNAME)
+
+# Gets rid of most of the unwanted files. Verify manually (if necessary)
+# that this produces a list of all the files desired in the distribution.
+DISTFILES: force
+ (cd $(srcdir); find . ! -type d -print) \
+ | sed '/\/RCS\//d; \
+ /\/EMACS-BACKUPS\//d; \
+ /\.tar.*/d; \
+ /~$$/d; /\.o$$/d; \
+ /\.gdbinit$$/d; \
+ /\.orig$$/d; \
+ /\#$$/d; \
+ /\/info\/info$$/d; \
+ /\.info$$/d; \
+ /\.elc/d; \
+ /\/makeinfo\/makeinfo$$/d; \
+ /\/$(DISTNAME)\/.*$$/d; \
+ /\/util\/texindex$$/d; \
+ /texinfo$$/d; \
+ /texinfo-[0-9]+$$/d; \
+ /\/.*\.BAK$$/d; \
+ /\/.*\.a$$/d; \
+ /\/core$$/d; \
+ /\/*\.core$$/d; \
+ /\/core\..*$$/d; \
+ /\/a.out$$/d; \
+ /\/[=@]/d; \
+ /\/conftest\.c$$/d; \
+ /\/DISTFILES$$/d; \
+ /\/foo$$/d; \
+ /\/bar$$/d; \
+ /\.toc$$/d; \
+ /\.bak$$/d; \
+ /\.aux$$/d; /\.log$$/d; \
+ /\.cps$$/d; /\.cp$$/d; \
+ /\.fns$$/d; /\.fn$$/d; \
+ /\.tps$$/d; /\.tp$$/d; \
+ /\.vrs$$/d; /\.vr$$/d; \
+ /\.pgs$$/d; /\.pg$$/d; \
+ /\.kys$$/d; /\.ky$$/d; \
+ /\.ops$$/d; /\.op$$/d; \
+ s/^.\///; /^\.$$/d;' \
+ | sort | uniq > DISTFILES
+
+force:
+
+# Prevent GNU make v3 from overflowing arg limit on SysV.
+.NOEXPORT:
diff --git a/contrib/texinfo/NEWS b/contrib/texinfo/NEWS
new file mode 100644
index 0000000..ffc7093
--- /dev/null
+++ b/contrib/texinfo/NEWS
@@ -0,0 +1,93 @@
+This file records noteworthy changes.
+
+3.9 (4 October 1996)
+* makeinfo:
+ - Give a suppressible (with --no-validate) error for references
+ outside of any node.
+ - Keep track of multitable output correctly for split files; this
+ caused nodes after the first multitable to be ``undefined''.
+* install-info:
+ - Rename --infodir option to --info-dir.
+ - More robust error checking to avoid various crashes.
+* configure: Include replacements for memcpy and memmove functions in
+ the distribution, in case they are missing.
+
+3.8 (30 September 1996)
+* Define and/or document new and/or previously existing commands:
+ Accents: @" @' @, @" @= @^ @` @~ @H @d @dotaccent @dotless @ringaccent
+ @tieaccent @u @ubaraccent @v
+ Special characters: @AA @AE @L @O @OE @aa @ae @exclamdown @l @o @oe
+ @pounds @questiondown @ss
+ Special punctuation: @! @? @enddots
+ dir file maintenance: @dircategory @direntry; also new program, install-info
+ HTML support: @email @url @ifhtml...@end ifhtml
+ Macros: @macro @unmacro
+ Tables: @multitable @tab
+ Hyphenation: @- @hyphenation
+ Spacing: @ @<TAB> @<NEWLINE>
+ Sectioning:
+ @headings singleafter/doubleafter (change heading style after current page)
+ @centerchap
+ @setchapterstyle
+ Other:
+ @shorttitlepage (simple title pages)
+ @detailmenu...@end detailmenu (help makeinfo parse master menus)
+* Makeinfo prefers an input file named `foo.texinfo' or `foo.texi' or
+ `foo.txinfo' to just `foo' (the latter most likely being an executable).
+* Makeinfo implements @. @! @? correctly, as end-of-sentence punctuation.
+* @key marks its argument with a lozenge in TeX and <...> in Info.
+* TeX output has substantially decreased interline spacing and other
+ formatting changes.
+* Remove these obsolete and never-documented commands:
+ @infotop
+ @infoappendix @infoappendixsec @infoappendixsubsec @infoappendixsubsubsec
+ @infochapter @infosection @infosubsection @infosubsubsection
+ @infounnumbered @infounnumberedsec @infounnumberedsubsec
+ @infounnumberedsubsubsec
+ @input
+ @smallbreak @medbreak
+ @overfullrule
+ @br
+* Deprecate these obsolete commands, to be removed in the next release:
+ @ctrl
+ @infoinclude
+ @iappendix @iappendixsection @iappendixsec @iappendixsubsec
+ @iappendixsubsubsec
+ @ichapter @isection @isubsection @isubsubsection
+ @iunnumbered @iunnumberedsec @iunnumberedsubsec @iunnumberedsubsubsec
+ @setchapterstyle
+ @titlespec
+
+3.7 (24 December 1995)
+* Have --version print texinfo release number as well as the individual
+ program version.
+* Better man page cleaning.
+* Update Elisp files from current Emacs release.
+
+3.6 (21 June 1995)
+* Unmatched brace error reporting improved.
+* Missing comment terminator prevented compilation.
+
+3.5 (20 June 1995)
+* Autoconf update.
+* Support for parallel makes.
+* make install does not install Elisp files.
+
+3.4 (19 June 1995)
+* Handle @ifhtml in Elisp.
+* Update FSF address.
+
+3.3 (15 June 1995)
+* Portability changes.
+* Compile Elisp files.
+* Don't distribute .info* files.
+
+3.2 (9 June 1995)
+* Standalone Info can read Unix man pages.
+* New commands: @! @? @^ @" @enddots.
+* makeinfo -E does macro expansion (and nothing else).
+
+3.1 (23 May 1993)
+Just bug fixes, see ChangeLog for full details.
+
+texinfo-3.0: first release of Texinfo version 2, with many new commands.
diff --git a/contrib/texinfo/README b/contrib/texinfo/README
new file mode 100644
index 0000000..357a98f
--- /dev/null
+++ b/contrib/texinfo/README
@@ -0,0 +1,163 @@
+Texinfo, Version 3
+==================
+
+This is the README file for version 3 of the Texinfo distribution.
+Files within this distribution have their own version and edition
+numbers. When you refer to a file, please mention its own number, as
+well as the version number of the Texinfo distribution.
+
+PLEASE REPORT BUGS TO: bug-texinfo@prep.ai.mit.edu
+
+Texinfo is a documentation system that uses a single source file to
+produce both on-line information and printed output. This means that
+instead of writing two different documents, one for the on-line help
+or other on-line information and the other for a typeset manual or
+other printed work, you need write only one document. When the work
+is revised, you need revise only one document. You can read the
+on-line information, known as an "Info file", with an Info
+documentation-reading program. By convention, Texinfo source file
+names end with a `.texi' or `.texinfo' extension. Texinfo is
+described in the Texinfo manual (the file ./texinfo.texi).
+
+You can write and format Texinfo files into Info files within GNU Emacs,
+and read them using the Emacs Info reader. If you do not have Emacs,
+you can format Texinfo files into Info files using `makeinfo' and read
+them using `info'. Use TeX, which is not included in this package (see
+`How to Obtain TeX' in the Texinfo manual for information), to typeset
+Texinfo files for printing.
+
+For instructions on compiling and installing info, makeinfo, texi2dvi,
+and texindex, please read the file `INSTALL'. The Emacs Lisp files are
+not installed by default; to install them, use `make install' in the
+`emacs' subdirectory. The Info tree uses a file `dir' as its root node;
+a sample `dir' file is included in the distribution, but not installed
+anywhere. Use it or not as you like.
+
+This distribution includes (but is not limited to) the following files:
+
+ README This file.
+
+ INTRODUCTION This file tells you how to create
+ readable files from the Texinfo source
+ files in this distribution.
+
+Texinfo source files:
+
+ texinfo.texi This manual describes Texinfo. It
+ tells how to use Texinfo to write
+ documentation, how to use Texinfo mode
+ in GNU Emacs, how to use TeX,
+ makeinfo, and the Emacs Lisp Texinfo
+ formatting commands.
+
+ info.texi This manual tells you how to use
+ Info. This document comes as part of
+ GNU Emacs. If you do not have Emacs,
+ you can format this Texinfo source
+ file with makeinfo or TeX and then
+ read the resulting Info file with the
+ standalone Info reader that is part of
+ this distribution.
+
+ info-stnd.texi This manual tells you how to use
+ the standalone GNU Info reader that is
+ included in this distribution as a C
+ source file, `info.c'.
+
+ makeinfo.texi This manual tells you how to use
+ makeinfo. The same information is
+ contained in a chapter of the Texinfo
+ manual; it has been extracted here for
+ your convenience.
+
+
+Printing related files:
+
+ texinfo.tex This TeX definitions file tells
+ the TeX program how to typeset a
+ Texinfo file into a DVI file ready for
+ printing.
+
+ texindex.c This file contains the source for
+ the `texindex' program that generates
+ sorted indices used by TeX when
+ typesetting a file for printing.
+
+ texi2dvi This is a shell script for
+ producing an indexed DVI file using
+ TeX and texindex. Must be used if the
+ source document uses Texinfo @macros.
+
+
+GNU Emacs related files:
+
+ texinfmt.el This Emacs Lisp file provides the
+ functions that GNU Emacs uses to
+ format a Texinfo file into an Info
+ file.
+
+ texinfo.el This file provides Texinfo mode
+ for GNU Emacs.
+
+ texnfo-upd.el These files provides commands to
+ texnfo-tex.el help you write Texinfo files
+ makeinfo.el using GNU Emacs Texinfo mode.
+
+ detexinfo.el This extra utility file contains functions
+ to remove Texinfo commands from a
+ Texinfo source file.
+
+ info.el These are the standard GNU Emacs
+ informat.el Info reading and support files,
+ included here for your convenience.
+
+
+Source files for standalone C programs:
+
+ makeinfo.c This file contains the source for
+ the `makeinfo' program that you can
+ use to create an Info file from a
+ Texinfo file.
+
+ info.c This file contains the source for
+ the `info' program that you can use to
+ view Info files on an ASCII terminal.
+
+ getopt.c Various support files
+ getopt1.c
+ getopt.h
+
+
+C Installation files:
+
+ configure This file creates creates a Makefile
+ which in turn creates an `info' or
+ `makeinfo' executable, or a C sources
+ distribution.
+
+ configure.in This is a template for creating
+ `configure' using m4 macros.
+
+ Makefile.in This is a template for `configure'
+ to use to make a Makefile.
+
+
+Other files:
+
+ NEWS This contains a summary of new
+ features since the first edition
+ of Texinfo.
+
+ info.1 This is a `man' page that briefly
+ describes the standalone `info'
+ program.
+
+ fixfonts This is a shell script to install the
+ `lcircle10' TeX fonts as an alias for
+ the `circle10' fonts. In some older
+ TeX distributions the names are
+ different.
+
+ tex3patch This handles a bug for version
+ 3.0 of TeX that does not occur in
+ more recent versions.
diff --git a/contrib/texinfo/TODO b/contrib/texinfo/TODO
new file mode 100644
index 0000000..de5b571
--- /dev/null
+++ b/contrib/texinfo/TODO
@@ -0,0 +1,35 @@
+If you are interested in working on any of these,
+email bug-texinfo@prep.ai.mit.edu.
+
+* Use Automake.
+
+* Use a config header file instead of @DEFS@.
+
+* A detexinfo program, like detex or delatex. This command would
+ strip all the texinfo commands out, and would be used as a filter on
+ the way to a speller. An option would be to NOT strip comments out.
+ makeinfo --no-headers come close.
+
+* Change bars. This is difficult or impossible in TeX,
+ unfortunately. To do it right requires device driver support.
+
+* The dark corner symbol for the gawk manual.
+
+* Better i18n support, including support for 8-bit input
+ characters. Requires fonts, and the DC fonts are not (as of this
+ writing) free.
+
+* @exercise/@answer command for, e.g., gawk.
+
+* @figure.
+
+* HTML output in makeinfo.
+
+* Include a complete functional summary, a la a reference card, in the manual.
+
+* Use @ as the escape character, and Texinfo syntax generally, in the
+ table of contents, aux, and index files. Eliminate all the crazy
+ redefinitions of every Texinfo command (which lists always seem to be
+ incomplete).
+
+* Improve the manuals for makeinfo, standalone info, etc.
diff --git a/contrib/texinfo/configure b/contrib/texinfo/configure
new file mode 100755
index 0000000..b02b278
--- /dev/null
+++ b/contrib/texinfo/configure
@@ -0,0 +1,1876 @@
+#! /bin/sh
+
+# Guess values for system-dependent variables and create Makefiles.
+# Generated automatically using autoconf version 2.10
+# Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc.
+#
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+
+# Defaults:
+ac_help=
+ac_default_prefix=/usr/local
+# Any additions from configure.in:
+
+# Initialize some variables set by options.
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+build=NONE
+cache_file=./config.cache
+exec_prefix=NONE
+host=NONE
+no_create=
+nonopt=NONE
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+target=NONE
+verbose=
+x_includes=NONE
+x_libraries=NONE
+bindir='${exec_prefix}/bin'
+sbindir='${exec_prefix}/sbin'
+libexecdir='${exec_prefix}/libexec'
+datadir='${prefix}/share'
+sysconfdir='${prefix}/etc'
+sharedstatedir='${prefix}/com'
+localstatedir='${prefix}/var'
+libdir='${exec_prefix}/lib'
+includedir='${prefix}/include'
+oldincludedir='/usr/include'
+infodir='${prefix}/info'
+mandir='${prefix}/man'
+
+# Initialize some other variables.
+subdirs=
+MFLAGS= MAKEFLAGS=
+
+ac_prev=
+for ac_option
+do
+
+ # If the previous option needs an argument, assign it.
+ if test -n "$ac_prev"; then
+ eval "$ac_prev=\$ac_option"
+ ac_prev=
+ continue
+ fi
+
+ case "$ac_option" in
+ -*=*) ac_optarg=`echo "$ac_option" | sed 's/[-_a-zA-Z0-9]*=//'` ;;
+ *) ac_optarg= ;;
+ esac
+
+ # Accept the important Cygnus configure options, so we can diagnose typos.
+
+ case "$ac_option" in
+
+ -bindir | --bindir | --bindi | --bind | --bin | --bi)
+ ac_prev=bindir ;;
+ -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
+ bindir="$ac_optarg" ;;
+
+ -build | --build | --buil | --bui | --bu)
+ ac_prev=build ;;
+ -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+ build="$ac_optarg" ;;
+
+ -cache-file | --cache-file | --cache-fil | --cache-fi \
+ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+ ac_prev=cache_file ;;
+ -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+ cache_file="$ac_optarg" ;;
+
+ -datadir | --datadir | --datadi | --datad | --data | --dat | --da)
+ ac_prev=datadir ;;
+ -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \
+ | --da=*)
+ datadir="$ac_optarg" ;;
+
+ -disable-* | --disable-*)
+ ac_feature=`echo $ac_option|sed -e 's/-*disable-//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_feature| sed 's/[-a-zA-Z0-9_]//g'`"; then
+ { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; }
+ fi
+ ac_feature=`echo $ac_feature| sed 's/-/_/g'`
+ eval "enable_${ac_feature}=no" ;;
+
+ -enable-* | --enable-*)
+ ac_feature=`echo $ac_option|sed -e 's/-*enable-//' -e 's/=.*//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_feature| sed 's/[-_a-zA-Z0-9]//g'`"; then
+ { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; }
+ fi
+ ac_feature=`echo $ac_feature| sed 's/-/_/g'`
+ case "$ac_option" in
+ *=*) ;;
+ *) ac_optarg=yes ;;
+ esac
+ eval "enable_${ac_feature}='$ac_optarg'" ;;
+
+ -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
+ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
+ | --exec | --exe | --ex)
+ ac_prev=exec_prefix ;;
+ -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
+ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
+ | --exec=* | --exe=* | --ex=*)
+ exec_prefix="$ac_optarg" ;;
+
+ -gas | --gas | --ga | --g)
+ # Obsolete; use --with-gas.
+ with_gas=yes ;;
+
+ -help | --help | --hel | --he)
+ # Omit some internal or obsolete options to make the list less imposing.
+ # This message is too long to be a string in the A/UX 3.1 sh.
+ cat << EOF
+Usage: configure [options] [host]
+Options: [defaults in brackets after descriptions]
+Configuration:
+ --cache-file=FILE cache test results in FILE
+ --help print this message
+ --no-create do not create output files
+ --quiet, --silent do not print \`checking...' messages
+ --version print the version of autoconf that created configure
+Directory and file names:
+ --prefix=PREFIX install architecture-independent files in PREFIX
+ [$ac_default_prefix]
+ --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX
+ [same as prefix]
+ --bindir=DIR user executables in DIR [EPREFIX/bin]
+ --sbindir=DIR system admin executables in DIR [EPREFIX/sbin]
+ --libexecdir=DIR program executables in DIR [EPREFIX/libexec]
+ --datadir=DIR read-only architecture-independent data in DIR
+ [PREFIX/share]
+ --sysconfdir=DIR read-only single-machine data in DIR [PREFIX/etc]
+ --sharedstatedir=DIR modifiable architecture-independent data in DIR
+ [PREFIX/com]
+ --localstatedir=DIR modifiable single-machine data in DIR [PREFIX/var]
+ --libdir=DIR object code libraries in DIR [EPREFIX/lib]
+ --includedir=DIR C header files in DIR [PREFIX/include]
+ --oldincludedir=DIR C header files for non-gcc in DIR [/usr/include]
+ --infodir=DIR info documentation in DIR [PREFIX/info]
+ --mandir=DIR man documentation in DIR [PREFIX/man]
+ --srcdir=DIR find the sources in DIR [configure dir or ..]
+ --program-prefix=PREFIX prepend PREFIX to installed program names
+ --program-suffix=SUFFIX append SUFFIX to installed program names
+ --program-transform-name=PROGRAM
+ run sed PROGRAM on installed program names
+EOF
+ cat << EOF
+Host type:
+ --build=BUILD configure for building on BUILD [BUILD=HOST]
+ --host=HOST configure for HOST [guessed]
+ --target=TARGET configure for TARGET [TARGET=HOST]
+Features and packages:
+ --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no)
+ --enable-FEATURE[=ARG] include FEATURE [ARG=yes]
+ --with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
+ --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
+ --x-includes=DIR X include files are in DIR
+ --x-libraries=DIR X library files are in DIR
+EOF
+ if test -n "$ac_help"; then
+ echo "--enable and --with options recognized:$ac_help"
+ fi
+ exit 0 ;;
+
+ -host | --host | --hos | --ho)
+ ac_prev=host ;;
+ -host=* | --host=* | --hos=* | --ho=*)
+ host="$ac_optarg" ;;
+
+ -includedir | --includedir | --includedi | --included | --include \
+ | --includ | --inclu | --incl | --inc)
+ ac_prev=includedir ;;
+ -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
+ | --includ=* | --inclu=* | --incl=* | --inc=*)
+ includedir="$ac_optarg" ;;
+
+ -infodir | --infodir | --infodi | --infod | --info | --inf)
+ ac_prev=infodir ;;
+ -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
+ infodir="$ac_optarg" ;;
+
+ -libdir | --libdir | --libdi | --libd)
+ ac_prev=libdir ;;
+ -libdir=* | --libdir=* | --libdi=* | --libd=*)
+ libdir="$ac_optarg" ;;
+
+ -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
+ | --libexe | --libex | --libe)
+ ac_prev=libexecdir ;;
+ -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
+ | --libexe=* | --libex=* | --libe=*)
+ libexecdir="$ac_optarg" ;;
+
+ -localstatedir | --localstatedir | --localstatedi | --localstated \
+ | --localstate | --localstat | --localsta | --localst \
+ | --locals | --local | --loca | --loc | --lo)
+ ac_prev=localstatedir ;;
+ -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+ | --localstate=* | --localstat=* | --localsta=* | --localst=* \
+ | --locals=* | --local=* | --loca=* | --loc=* | --lo=*)
+ localstatedir="$ac_optarg" ;;
+
+ -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
+ ac_prev=mandir ;;
+ -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
+ mandir="$ac_optarg" ;;
+
+ -nfp | --nfp | --nf)
+ # Obsolete; use --without-fp.
+ with_fp=no ;;
+
+ -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+ | --no-cr | --no-c)
+ no_create=yes ;;
+
+ -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+ no_recursion=yes ;;
+
+ -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
+ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
+ | --oldin | --oldi | --old | --ol | --o)
+ ac_prev=oldincludedir ;;
+ -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
+ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
+ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
+ oldincludedir="$ac_optarg" ;;
+
+ -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+ ac_prev=prefix ;;
+ -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+ prefix="$ac_optarg" ;;
+
+ -program-prefix | --program-prefix | --program-prefi | --program-pref \
+ | --program-pre | --program-pr | --program-p)
+ ac_prev=program_prefix ;;
+ -program-prefix=* | --program-prefix=* | --program-prefi=* \
+ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
+ program_prefix="$ac_optarg" ;;
+
+ -program-suffix | --program-suffix | --program-suffi | --program-suff \
+ | --program-suf | --program-su | --program-s)
+ ac_prev=program_suffix ;;
+ -program-suffix=* | --program-suffix=* | --program-suffi=* \
+ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
+ program_suffix="$ac_optarg" ;;
+
+ -program-transform-name | --program-transform-name \
+ | --program-transform-nam | --program-transform-na \
+ | --program-transform-n | --program-transform- \
+ | --program-transform | --program-transfor \
+ | --program-transfo | --program-transf \
+ | --program-trans | --program-tran \
+ | --progr-tra | --program-tr | --program-t)
+ ac_prev=program_transform_name ;;
+ -program-transform-name=* | --program-transform-name=* \
+ | --program-transform-nam=* | --program-transform-na=* \
+ | --program-transform-n=* | --program-transform-=* \
+ | --program-transform=* | --program-transfor=* \
+ | --program-transfo=* | --program-transf=* \
+ | --program-trans=* | --program-tran=* \
+ | --progr-tra=* | --program-tr=* | --program-t=*)
+ program_transform_name="$ac_optarg" ;;
+
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil)
+ silent=yes ;;
+
+ -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
+ ac_prev=sbindir ;;
+ -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
+ | --sbi=* | --sb=*)
+ sbindir="$ac_optarg" ;;
+
+ -sharedstatedir | --sharedstatedir | --sharedstatedi \
+ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
+ | --sharedst | --shareds | --shared | --share | --shar \
+ | --sha | --sh)
+ ac_prev=sharedstatedir ;;
+ -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
+ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
+ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
+ | --sha=* | --sh=*)
+ sharedstatedir="$ac_optarg" ;;
+
+ -site | --site | --sit)
+ ac_prev=site ;;
+ -site=* | --site=* | --sit=*)
+ site="$ac_optarg" ;;
+
+ -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+ ac_prev=srcdir ;;
+ -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+ srcdir="$ac_optarg" ;;
+
+ -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
+ | --syscon | --sysco | --sysc | --sys | --sy)
+ ac_prev=sysconfdir ;;
+ -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
+ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
+ sysconfdir="$ac_optarg" ;;
+
+ -target | --target | --targe | --targ | --tar | --ta | --t)
+ ac_prev=target ;;
+ -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+ target="$ac_optarg" ;;
+
+ -v | -verbose | --verbose | --verbos | --verbo | --verb)
+ verbose=yes ;;
+
+ -version | --version | --versio | --versi | --vers)
+ echo "configure generated by autoconf version 2.10"
+ exit 0 ;;
+
+ -with-* | --with-*)
+ ac_package=`echo $ac_option|sed -e 's/-*with-//' -e 's/=.*//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_package| sed 's/[-_a-zA-Z0-9]//g'`"; then
+ { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; }
+ fi
+ ac_package=`echo $ac_package| sed 's/-/_/g'`
+ case "$ac_option" in
+ *=*) ;;
+ *) ac_optarg=yes ;;
+ esac
+ eval "with_${ac_package}='$ac_optarg'" ;;
+
+ -without-* | --without-*)
+ ac_package=`echo $ac_option|sed -e 's/-*without-//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_package| sed 's/[-a-zA-Z0-9_]//g'`"; then
+ { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; }
+ fi
+ ac_package=`echo $ac_package| sed 's/-/_/g'`
+ eval "with_${ac_package}=no" ;;
+
+ --x)
+ # Obsolete; use --with-x.
+ with_x=yes ;;
+
+ -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
+ | --x-incl | --x-inc | --x-in | --x-i)
+ ac_prev=x_includes ;;
+ -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
+ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
+ x_includes="$ac_optarg" ;;
+
+ -x-libraries | --x-libraries | --x-librarie | --x-librari \
+ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
+ ac_prev=x_libraries ;;
+ -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
+ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
+ x_libraries="$ac_optarg" ;;
+
+ -*) { echo "configure: error: $ac_option: invalid option; use --help to show usage" 1>&2; exit 1; }
+ ;;
+
+ *)
+ if test -n "`echo $ac_option| sed 's/[-a-z0-9.]//g'`"; then
+ echo "configure: warning: $ac_option: invalid host type" 1>&2
+ fi
+ if test "x$nonopt" != xNONE; then
+ { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; }
+ fi
+ nonopt="$ac_option"
+ ;;
+
+ esac
+done
+
+if test -n "$ac_prev"; then
+ { echo "configure: error: missing argument to --`echo $ac_prev | sed 's/_/-/g'`" 1>&2; exit 1; }
+fi
+
+trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15
+
+# File descriptor usage:
+# 0 standard input
+# 1 file creation
+# 2 errors and warnings
+# 3 some systems may open it to /dev/tty
+# 4 used on the Kubota Titan
+# 6 checking for... messages and results
+# 5 compiler messages saved in config.log
+if test "$silent" = yes; then
+ exec 6>/dev/null
+else
+ exec 6>&1
+fi
+exec 5>./config.log
+
+echo "\
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+" 1>&5
+
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Also quote any args containing shell metacharacters.
+ac_configure_args=
+for ac_arg
+do
+ case "$ac_arg" in
+ -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+ | --no-cr | --no-c) ;;
+ -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) ;;
+ *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*)
+ ac_configure_args="$ac_configure_args '$ac_arg'" ;;
+ *) ac_configure_args="$ac_configure_args $ac_arg" ;;
+ esac
+done
+
+# NLS nuisances.
+# Only set LANG and LC_ALL to C if already set.
+# These must not be set unconditionally because not all systems understand
+# e.g. LANG=C (notably SCO).
+if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi
+if test "${LANG+set}" = set; then LANG=C; export LANG; fi
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -rf conftest* confdefs.h
+# AIX cpp loses on an empty file, so make sure it contains at least a newline.
+echo > confdefs.h
+
+# A filename unique to this package, relative to the directory that
+# configure is in, which we can look for to find out if srcdir is correct.
+ac_unique_file=texinfo.texi
+
+# Find the source files, if location was not specified.
+if test -z "$srcdir"; then
+ ac_srcdir_defaulted=yes
+ # Try the directory containing this script, then its parent.
+ ac_prog=$0
+ ac_confdir=`echo $ac_prog|sed 's%/[^/][^/]*$%%'`
+ test "x$ac_confdir" = "x$ac_prog" && ac_confdir=.
+ srcdir=$ac_confdir
+ if test ! -r $srcdir/$ac_unique_file; then
+ srcdir=..
+ fi
+else
+ ac_srcdir_defaulted=no
+fi
+if test ! -r $srcdir/$ac_unique_file; then
+ if test "$ac_srcdir_defaulted" = yes; then
+ { echo "configure: error: can not find sources in $ac_confdir or .." 1>&2; exit 1; }
+ else
+ { echo "configure: error: can not find sources in $srcdir" 1>&2; exit 1; }
+ fi
+fi
+srcdir=`echo "${srcdir}" | sed 's%\([^/]\)/*$%\1%'`
+
+# Prefer explicitly selected file to automatically selected ones.
+if test -z "$CONFIG_SITE"; then
+ if test "x$prefix" != xNONE; then
+ CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site"
+ else
+ CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site"
+ fi
+fi
+for ac_site_file in $CONFIG_SITE; do
+ if test -r "$ac_site_file"; then
+ echo "loading site script $ac_site_file"
+ . "$ac_site_file"
+ fi
+done
+
+if test -r "$cache_file"; then
+ echo "loading cache $cache_file"
+ . $cache_file
+else
+ echo "creating cache $cache_file"
+ > $cache_file
+fi
+
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+
+if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then
+ # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu.
+ if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then
+ ac_n= ac_c='
+' ac_t=' '
+ else
+ ac_n=-n ac_c= ac_t=
+ fi
+else
+ ac_n= ac_c='\c' ac_t=
+fi
+
+
+
+# Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
+ for ac_dir in $PATH; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_prog_CC="gcc"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+fi
+fi
+CC="$ac_cv_prog_CC"
+if test -n "$CC"; then
+ echo "$ac_t""$CC" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+if test -z "$CC"; then
+ # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
+ ac_prog_rejected=no
+ for ac_dir in $PATH; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ if test "$ac_dir/$ac_word" = "/usr/ucb/cc"; then
+ ac_prog_rejected=yes
+ continue
+ fi
+ ac_cv_prog_CC="cc"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+if test $ac_prog_rejected = yes; then
+ # We found a bogon in the path, so make sure we never use it.
+ set dummy $ac_cv_prog_CC
+ shift
+ if test $# -gt 0; then
+ # We chose a different compiler from the bogus one.
+ # However, it has the same basename, so the bogon will be chosen
+ # first if we set CC to just the basename; use the full file name.
+ shift
+ set dummy "$ac_dir/$ac_word" "$@"
+ shift
+ ac_cv_prog_CC="$@"
+ fi
+fi
+fi
+fi
+CC="$ac_cv_prog_CC"
+if test -n "$CC"; then
+ echo "$ac_t""$CC" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+ test -z "$CC" && { echo "configure: error: no acceptable cc found in \$PATH" 1>&2; exit 1; }
+fi
+
+echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.c <<EOF
+#ifdef __GNUC__
+ yes;
+#endif
+EOF
+if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:603: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
+ ac_cv_prog_gcc=yes
+else
+ ac_cv_prog_gcc=no
+fi
+fi
+
+echo "$ac_t""$ac_cv_prog_gcc" 1>&6
+if test $ac_cv_prog_gcc = yes; then
+ GCC=yes
+ if test "${CFLAGS+set}" != set; then
+ echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'ac_cv_prog_gcc_g'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ echo 'void f(){}' > conftest.c
+if test -z "`${CC-cc} -g -c conftest.c 2>&1`"; then
+ ac_cv_prog_gcc_g=yes
+else
+ ac_cv_prog_gcc_g=no
+fi
+rm -f conftest*
+
+fi
+
+echo "$ac_t""$ac_cv_prog_gcc_g" 1>&6
+ if test $ac_cv_prog_gcc_g = yes; then
+ CFLAGS="-g -O"
+ else
+ CFLAGS="-O"
+ fi
+ fi
+else
+ GCC=
+ test "${CFLAGS+set}" = set || CFLAGS="-g"
+fi
+
+echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6
+# On Suns, sometimes $CPP names a directory.
+if test -n "$CPP" && test -d "$CPP"; then
+ CPP=
+fi
+if test -z "$CPP"; then
+if eval "test \"`echo '$''{'ac_cv_prog_CPP'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ # This must be in double quotes, not single quotes, because CPP may get
+ # substituted into the Makefile and "${CC-cc}" will confuse make.
+ CPP="${CC-cc} -E"
+ # On the NeXT, cc -E runs the code through the compiler's parser,
+ # not just through cpp.
+ cat > conftest.$ac_ext <<EOF
+#line 655 "configure"
+#include "confdefs.h"
+#include <assert.h>
+Syntax Error
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:661: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out`
+if test -z "$ac_err"; then
+ :
+else
+ echo "$ac_err" >&5
+ rm -rf conftest*
+ CPP="${CC-cc} -E -traditional-cpp"
+ cat > conftest.$ac_ext <<EOF
+#line 670 "configure"
+#include "confdefs.h"
+#include <assert.h>
+Syntax Error
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:676: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out`
+if test -z "$ac_err"; then
+ :
+else
+ echo "$ac_err" >&5
+ rm -rf conftest*
+ CPP=/lib/cpp
+fi
+rm -f conftest*
+fi
+rm -f conftest*
+ ac_cv_prog_CPP="$CPP"
+fi
+ CPP="$ac_cv_prog_CPP"
+else
+ ac_cv_prog_CPP="$CPP"
+fi
+echo "$ac_t""$CPP" 1>&6
+
+if test $ac_cv_prog_gcc = yes; then
+ echo $ac_n "checking whether ${CC-cc} needs -traditional""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'ac_cv_prog_gcc_traditional'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_pattern="Autoconf.*'x'"
+ cat > conftest.$ac_ext <<EOF
+#line 703 "configure"
+#include "confdefs.h"
+#include <sgtty.h>
+Autoconf TIOCGETP
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ egrep "$ac_pattern" >/dev/null 2>&1; then
+ rm -rf conftest*
+ ac_cv_prog_gcc_traditional=yes
+else
+ rm -rf conftest*
+ ac_cv_prog_gcc_traditional=no
+fi
+rm -f conftest*
+
+
+ if test $ac_cv_prog_gcc_traditional = no; then
+ cat > conftest.$ac_ext <<EOF
+#line 721 "configure"
+#include "confdefs.h"
+#include <termio.h>
+Autoconf TCGETA
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ egrep "$ac_pattern" >/dev/null 2>&1; then
+ rm -rf conftest*
+ ac_cv_prog_gcc_traditional=yes
+fi
+rm -f conftest*
+
+ fi
+fi
+
+echo "$ac_t""$ac_cv_prog_gcc_traditional" 1>&6
+ if test $ac_cv_prog_gcc_traditional = yes; then
+ CC="$CC -traditional"
+ fi
+fi
+
+ac_aux_dir=
+for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do
+ if test -f $ac_dir/install-sh; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/install-sh -c"
+ break
+ elif test -f $ac_dir/install.sh; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/install.sh -c"
+ break
+ fi
+done
+if test -z "$ac_aux_dir"; then
+ { echo "configure: error: can not find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." 1>&2; exit 1; }
+fi
+ac_config_guess=$ac_aux_dir/config.guess
+ac_config_sub=$ac_aux_dir/config.sub
+ac_configure=$ac_aux_dir/configure # This should be Cygnus configure.
+
+# Find a good install program. We prefer a C program (faster),
+# so one script is as good as another. But avoid the broken or
+# incompatible versions:
+# SysV /etc/install, /usr/sbin/install
+# SunOS /usr/etc/install
+# IRIX /sbin/install
+# AIX /bin/install
+# AFS /usr/afsws/bin/install, which mishandles nonexistent args
+# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
+# ./install, which can be erroneously created by make from ./install.sh.
+echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6
+if test -z "$INSTALL"; then
+if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
+ for ac_dir in $PATH; do
+ # Account for people who put trailing slashes in PATH elements.
+ case "$ac_dir/" in
+ /|./|.//|/etc/*|/usr/sbin/*|/usr/etc/*|/sbin/*|/usr/afsws/bin/*|/usr/ucb/*) ;;
+ *)
+ # OSF1 and SCO ODT 3.0 have their own names for install.
+ for ac_prog in ginstall installbsd scoinst install; do
+ if test -f $ac_dir/$ac_prog; then
+ if test $ac_prog = install &&
+ grep dspmsg $ac_dir/$ac_prog >/dev/null 2>&1; then
+ # AIX install. It has an incompatible calling convention.
+ # OSF/1 installbsd also uses dspmsg, but is usable.
+ :
+ else
+ ac_cv_path_install="$ac_dir/$ac_prog -c"
+ break 2
+ fi
+ fi
+ done
+ ;;
+ esac
+ done
+ IFS="$ac_save_ifs"
+
+fi
+ if test "${ac_cv_path_install+set}" = set; then
+ INSTALL="$ac_cv_path_install"
+ else
+ # As a last resort, use the slow shell script. We don't cache a
+ # path for INSTALL within a source directory, because that will
+ # break other packages using the cache if that directory is
+ # removed, or if the path is relative.
+ INSTALL="$ac_install_sh"
+ fi
+fi
+echo "$ac_t""$INSTALL" 1>&6
+
+# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
+# It thinks the first close brace ends the variable substitution.
+test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
+
+test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
+
+# Extract the first word of "ranlib", so it can be a program name with args.
+set dummy ranlib; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$RANLIB"; then
+ ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
+ for ac_dir in $PATH; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_prog_RANLIB="ranlib"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+ test -z "$ac_cv_prog_RANLIB" && ac_cv_prog_RANLIB=":"
+fi
+fi
+RANLIB="$ac_cv_prog_RANLIB"
+if test -n "$RANLIB"; then
+ echo "$ac_t""$RANLIB" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+
+echo $ac_n "checking for POSIXized ISC""... $ac_c" 1>&6
+if test -d /etc/conf/kconfig.d &&
+ grep _POSIX_VERSION /usr/include/sys/unistd.h >/dev/null 2>&1
+then
+ echo "$ac_t""yes" 1>&6
+ ISC=yes # If later tests want to check for ISC.
+ cat >> confdefs.h <<\EOF
+#define _POSIX_SOURCE 1
+EOF
+
+ if test "$GCC" = yes; then
+ CC="$CC -posix"
+ else
+ CC="$CC -Xp"
+ fi
+else
+ echo "$ac_t""no" 1>&6
+ ISC=
+fi
+
+ac_safe=`echo "minix/config.h" | tr './\055' '___'`
+echo $ac_n "checking for minix/config.h""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 875 "configure"
+#include "confdefs.h"
+#include <minix/config.h>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:880: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out`
+if test -z "$ac_err"; then
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=yes"
+else
+ echo "$ac_err" >&5
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=no"
+fi
+rm -f conftest*
+fi
+if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ MINIX=yes
+else
+ echo "$ac_t""no" 1>&6
+MINIX=
+fi
+
+if test "$MINIX" = yes; then
+ cat >> confdefs.h <<\EOF
+#define _POSIX_SOURCE 1
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define _POSIX_1_SOURCE 2
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define _MINIX 1
+EOF
+
+fi
+
+
+# Needed on sysV68 for sigblock, sigsetmask.
+echo $ac_n "checking for -lbsd""... $ac_c" 1>&6
+ac_lib_var=`echo bsd'_'sigblock | tr './+\055' '__p_'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-lbsd $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 925 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char sigblock();
+
+int main() { return 0; }
+int t() {
+sigblock()
+; return 0; }
+EOF
+if { (eval echo configure:937: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_lib=HAVE_LIB`echo bsd | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_lib 1
+EOF
+
+ LIBS="-lbsd $LIBS"
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+
+TERMLIBS=
+for termlib in curses termcap terminfo termlib ; do
+ echo $ac_n "checking for -l${termlib}""... $ac_c" 1>&6
+ac_lib_var=`echo ${termlib}'_'tputs | tr './+\055' '__p_'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-l${termlib} $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 972 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char tputs();
+
+int main() { return 0; }
+int t() {
+tputs()
+; return 0; }
+EOF
+if { (eval echo configure:984: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ TERMLIBS="${TERMLIBS} -l${termlib}"; break
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+done
+
+
+# If we cannot run a trivial program, we must be cross compiling.
+echo $ac_n "checking whether cross-compiling""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'ac_cv_c_cross'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test "$cross_compiling" = yes; then
+ ac_cv_c_cross=yes
+else
+cat > conftest.$ac_ext <<EOF
+#line 1014 "configure"
+#include "confdefs.h"
+main(){return(0);}
+EOF
+{ (eval echo configure:1018: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }
+if test -s conftest && (./conftest; exit) 2>/dev/null; then
+ ac_cv_c_cross=no
+else
+ ac_cv_c_cross=yes
+fi
+fi
+rm -fr conftest*
+fi
+
+echo "$ac_t""$ac_cv_c_cross" 1>&6
+cross_compiling=$ac_cv_c_cross
+
+echo $ac_n "checking for ANSI C header files""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'ac_cv_header_stdc'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1036 "configure"
+#include "confdefs.h"
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <float.h>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:1044: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out`
+if test -z "$ac_err"; then
+ rm -rf conftest*
+ ac_cv_header_stdc=yes
+else
+ echo "$ac_err" >&5
+ rm -rf conftest*
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+if test $ac_cv_header_stdc = yes; then
+ # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
+cat > conftest.$ac_ext <<EOF
+#line 1059 "configure"
+#include "confdefs.h"
+#include <string.h>
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ egrep "memchr" >/dev/null 2>&1; then
+ :
+else
+ rm -rf conftest*
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+ # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
+cat > conftest.$ac_ext <<EOF
+#line 1077 "configure"
+#include "confdefs.h"
+#include <stdlib.h>
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ egrep "free" >/dev/null 2>&1; then
+ :
+else
+ rm -rf conftest*
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+ # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
+if test "$cross_compiling" = yes; then
+ :
+else
+cat > conftest.$ac_ext <<EOF
+#line 1098 "configure"
+#include "confdefs.h"
+#include <ctype.h>
+#define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
+#define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
+#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
+int main () { int i; for (i = 0; i < 256; i++)
+if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) exit(2);
+exit (0); }
+
+EOF
+{ (eval echo configure:1109: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }
+if test -s conftest && (./conftest; exit) 2>/dev/null; then
+ :
+else
+ ac_cv_header_stdc=no
+fi
+fi
+rm -fr conftest*
+fi
+fi
+
+echo "$ac_t""$ac_cv_header_stdc" 1>&6
+if test $ac_cv_header_stdc = yes; then
+ cat >> confdefs.h <<\EOF
+#define STDC_HEADERS 1
+EOF
+
+fi
+
+for ac_hdr in unistd.h termios.h termio.h strings.h string.h varargs.h \
+ sys/time.h sys/fcntl.h sys/ttold.h sys/ptem.h sys/file.h
+do
+ac_safe=`echo "$ac_hdr" | tr './\055' '___'`
+echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1137 "configure"
+#include "confdefs.h"
+#include <$ac_hdr>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:1142: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out`
+if test -z "$ac_err"; then
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=yes"
+else
+ echo "$ac_err" >&5
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=no"
+fi
+rm -f conftest*
+fi
+if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_hdr=HAVE_`echo $ac_hdr | tr 'abcdefghijklmnopqrstuvwxyz./\055' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ___'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_hdr 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+done
+
+
+echo $ac_n "checking for off_t""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'ac_cv_type_off_t'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1172 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#if STDC_HEADERS
+#include <stdlib.h>
+#endif
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ egrep "off_t" >/dev/null 2>&1; then
+ rm -rf conftest*
+ ac_cv_type_off_t=yes
+else
+ rm -rf conftest*
+ ac_cv_type_off_t=no
+fi
+rm -f conftest*
+
+fi
+echo "$ac_t""$ac_cv_type_off_t" 1>&6
+if test $ac_cv_type_off_t = no; then
+ cat >> confdefs.h <<\EOF
+#define off_t long
+EOF
+
+fi
+
+echo $ac_n "checking for working const""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'ac_cv_c_const'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1203 "configure"
+#include "confdefs.h"
+
+int main() { return 0; }
+int t() {
+
+/* Ultrix mips cc rejects this. */
+typedef int charset[2]; const charset x;
+/* SunOS 4.1.1 cc rejects this. */
+char const *const *ccp;
+char **p;
+/* NEC SVR4.0.2 mips cc rejects this. */
+struct point {int x, y;};
+static struct point const zero = {0,0};
+/* AIX XL C 1.02.0.0 rejects this.
+ It does not let you subtract one const X* pointer from another in an arm
+ of an if-expression whose if-part is not a constant expression */
+const char *g = "string";
+ccp = &g + (g ? g-g : 0);
+/* HPUX 7.0 cc rejects these. */
+++ccp;
+p = (char**) ccp;
+ccp = (char const *const *) p;
+{ /* SCO 3.2v4 cc rejects this. */
+ char *t;
+ char const *s = 0 ? (char *) 0 : (char const *) 0;
+
+ *t++ = 0;
+}
+{ /* Someone thinks the Sun supposedly-ANSI compiler will reject this. */
+ int x[] = {25, 17};
+ const int *foo = &x[0];
+ ++foo;
+}
+{ /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */
+ typedef const int *iptr;
+ iptr p = 0;
+ ++p;
+}
+{ /* AIX XL C 1.02.0.0 rejects this saying
+ "k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */
+ struct s { int j; const int *ap[3]; };
+ struct s *b; b->j = 5;
+}
+{ /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */
+ const int foo = 10;
+}
+
+; return 0; }
+EOF
+if { (eval echo configure:1253: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ ac_cv_c_const=yes
+else
+ rm -rf conftest*
+ ac_cv_c_const=no
+fi
+rm -f conftest*
+
+fi
+
+echo "$ac_t""$ac_cv_c_const" 1>&6
+if test $ac_cv_c_const = no; then
+ cat >> confdefs.h <<\EOF
+#define const
+EOF
+
+fi
+
+echo $ac_n "checking whether struct tm is in sys/time.h or time.h""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'ac_cv_struct_tm'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1277 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#include <time.h>
+int main() { return 0; }
+int t() {
+struct tm *tp; tp->tm_sec;
+; return 0; }
+EOF
+if { (eval echo configure:1286: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ ac_cv_struct_tm=time.h
+else
+ rm -rf conftest*
+ ac_cv_struct_tm=sys/time.h
+fi
+rm -f conftest*
+
+fi
+
+echo "$ac_t""$ac_cv_struct_tm" 1>&6
+if test $ac_cv_struct_tm = sys/time.h; then
+ cat >> confdefs.h <<\EOF
+#define TM_IN_SYS_TIME 1
+EOF
+
+fi
+
+
+# The Ultrix 4.2 mips builtin alloca declared by alloca.h only works
+# for constant arguments. Useless!
+echo $ac_n "checking for working alloca.h""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'ac_cv_header_alloca_h'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1313 "configure"
+#include "confdefs.h"
+#include <alloca.h>
+int main() { return 0; }
+int t() {
+char *p = alloca(2 * sizeof(int));
+; return 0; }
+EOF
+if { (eval echo configure:1321: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
+ rm -rf conftest*
+ ac_cv_header_alloca_h=yes
+else
+ rm -rf conftest*
+ ac_cv_header_alloca_h=no
+fi
+rm -f conftest*
+
+fi
+
+echo "$ac_t""$ac_cv_header_alloca_h" 1>&6
+if test $ac_cv_header_alloca_h = yes; then
+ cat >> confdefs.h <<\EOF
+#define HAVE_ALLOCA_H 1
+EOF
+
+fi
+
+echo $ac_n "checking for alloca""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'ac_cv_func_alloca'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1345 "configure"
+#include "confdefs.h"
+
+#ifdef __GNUC__
+# define alloca __builtin_alloca
+#else
+# if HAVE_ALLOCA_H
+# include <alloca.h>
+# else
+# ifdef _AIX
+ #pragma alloca
+# else
+# ifndef alloca /* predefined by HP cc +Olibcalls */
+char *alloca ();
+# endif
+# endif
+# endif
+#endif
+
+int main() { return 0; }
+int t() {
+char *p = (char *) alloca(1);
+; return 0; }
+EOF
+if { (eval echo configure:1369: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
+ rm -rf conftest*
+ ac_cv_func_alloca=yes
+else
+ rm -rf conftest*
+ ac_cv_func_alloca=no
+fi
+rm -f conftest*
+
+fi
+
+echo "$ac_t""$ac_cv_func_alloca" 1>&6
+if test $ac_cv_func_alloca = yes; then
+ cat >> confdefs.h <<\EOF
+#define HAVE_ALLOCA 1
+EOF
+
+fi
+
+if test $ac_cv_func_alloca = no; then
+ # The SVR3 libPW and SVR4 libucb both contain incompatible functions
+ # that cause trouble. Some versions do not even contain alloca or
+ # contain a buggy version. If you still want to use their alloca,
+ # use ar to extract alloca.o from them instead of compiling alloca.c.
+ ALLOCA=alloca.o
+ cat >> confdefs.h <<\EOF
+#define C_ALLOCA 1
+EOF
+
+
+echo $ac_n "checking whether alloca needs Cray hooks""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'ac_cv_os_cray'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1404 "configure"
+#include "confdefs.h"
+#if defined(CRAY) && ! defined(CRAY2)
+webecray
+#else
+wenotbecray
+#endif
+
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ egrep "webecray" >/dev/null 2>&1; then
+ rm -rf conftest*
+ ac_cv_os_cray=yes
+else
+ rm -rf conftest*
+ ac_cv_os_cray=no
+fi
+rm -f conftest*
+
+fi
+
+echo "$ac_t""$ac_cv_os_cray" 1>&6
+if test $ac_cv_os_cray = yes; then
+for ac_func in _getb67 GETB67 getb67; do
+ echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1433 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $ac_func(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char $ac_func();
+
+int main() { return 0; }
+int t() {
+
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+$ac_func();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:1457: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=yes"
+else
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=no"
+fi
+rm -f conftest*
+
+fi
+if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ cat >> confdefs.h <<EOF
+#define CRAY_STACKSEG_END $ac_func
+EOF
+
+ break
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+done
+fi
+
+echo $ac_n "checking stack direction for C alloca""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'ac_cv_c_stack_direction'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test "$cross_compiling" = yes; then
+ ac_cv_c_stack_direction=0
+else
+cat > conftest.$ac_ext <<EOF
+#line 1489 "configure"
+#include "confdefs.h"
+find_stack_direction ()
+{
+ static char *addr = 0;
+ auto char dummy;
+ if (addr == 0)
+ {
+ addr = &dummy;
+ return find_stack_direction ();
+ }
+ else
+ return (&dummy > addr) ? 1 : -1;
+}
+main ()
+{
+ exit (find_stack_direction() < 0);
+}
+EOF
+{ (eval echo configure:1508: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }
+if test -s conftest && (./conftest; exit) 2>/dev/null; then
+ ac_cv_c_stack_direction=1
+else
+ ac_cv_c_stack_direction=-1
+fi
+fi
+rm -fr conftest*
+fi
+
+echo "$ac_t""$ac_cv_c_stack_direction" 1>&6
+cat >> confdefs.h <<EOF
+#define STACK_DIRECTION $ac_cv_c_stack_direction
+EOF
+
+fi
+
+echo $ac_n "checking whether setvbuf arguments are reversed""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'ac_cv_func_setvbuf_reversed'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test "$cross_compiling" = yes; then
+ { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; }
+else
+cat > conftest.$ac_ext <<EOF
+#line 1533 "configure"
+#include "confdefs.h"
+#include <stdio.h>
+/* If setvbuf has the reversed format, exit 0. */
+main () {
+ /* This call has the arguments reversed.
+ A reversed system may check and see that the address of main
+ is not _IOLBF, _IONBF, or _IOFBF, and return nonzero. */
+ if (setvbuf(stdout, _IOLBF, (char *) main, BUFSIZ) != 0)
+ exit(1);
+ putc('\r', stdout);
+ exit(0); /* Non-reversed systems segv here. */
+}
+EOF
+{ (eval echo configure:1547: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }
+if test -s conftest && (./conftest; exit) 2>/dev/null; then
+ ac_cv_func_setvbuf_reversed=yes
+else
+ ac_cv_func_setvbuf_reversed=no
+fi
+fi
+rm -fr conftest*
+rm -f core core.* *.core
+fi
+
+echo "$ac_t""$ac_cv_func_setvbuf_reversed" 1>&6
+if test $ac_cv_func_setvbuf_reversed = yes; then
+ cat >> confdefs.h <<\EOF
+#define SETVBUF_REVERSED 1
+EOF
+
+fi
+
+for ac_func in setvbuf getcwd memset bzero strchr strcasecmp \
+ vfprintf vsprintf strerror sigprocmask sigsetmask
+do
+echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1574 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $ac_func(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char $ac_func();
+
+int main() { return 0; }
+int t() {
+
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+$ac_func();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:1598: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=yes"
+else
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=no"
+fi
+rm -f conftest*
+
+fi
+if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_func 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+done
+
+for ac_func in memcpy memmove strdup
+do
+echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1627 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $ac_func(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char $ac_func();
+
+int main() { return 0; }
+int t() {
+
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+$ac_func();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:1651: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=yes"
+else
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=no"
+fi
+rm -f conftest*
+
+fi
+if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ :
+else
+ echo "$ac_t""no" 1>&6
+LIBOBJS="$LIBOBJS ${ac_func}.o"
+fi
+
+done
+
+
+trap '' 1 2 15
+cat > confcache <<\EOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs. It is not useful on other systems.
+# If it contains results you don't want to keep, you may remove or edit it.
+#
+# By default, configure uses ./config.cache as the cache file,
+# creating it if it does not exist already. You can give configure
+# the --cache-file=FILE option to use a different cache file; that is
+# what configure does when it calls configure scripts in
+# subdirectories, so they share the cache.
+# Giving --cache-file=/dev/null disables caching, for debugging configure.
+# config.status only pays attention to the cache file if you give it the
+# --recheck option to rerun configure.
+#
+EOF
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+(set) 2>&1 |
+ sed -n "s/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=\${\1='\2'}/p" \
+ >> confcache
+if cmp -s $cache_file confcache; then
+ :
+else
+ if test -w $cache_file; then
+ echo "updating cache $cache_file"
+ cat confcache > $cache_file
+ else
+ echo "not updating unwritable cache $cache_file"
+ fi
+fi
+rm -f confcache
+
+trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+# Any assignment to VPATH causes Sun make to only execute
+# the first set of double-colon rules, so remove it if not needed.
+# If there is a colon in the path, we need to keep it.
+if test "x$srcdir" = x.; then
+ ac_vpsub='/^[ ]*VPATH[ ]*=[^:]*$/d'
+fi
+
+trap 'rm -f $CONFIG_STATUS conftest*; exit 1' 1 2 15
+
+# Transform confdefs.h into DEFS.
+# Protect against shell expansion while executing Makefile rules.
+# Protect against Makefile macro expansion.
+cat > conftest.defs <<\EOF
+s%#define \([A-Za-z_][A-Za-z0-9_]*\) *\(.*\)%-D\1=\2%g
+s%[ `~#$^&*(){}\\|;'"<>?]%\\&%g
+s%\[%\\&%g
+s%\]%\\&%g
+s%\$%$$%g
+EOF
+DEFS=`sed -f conftest.defs confdefs.h | tr '\012' ' '`
+rm -f conftest.defs
+
+
+# Without the "./", some shells look in PATH for config.status.
+: ${CONFIG_STATUS=./config.status}
+
+echo creating $CONFIG_STATUS
+rm -f $CONFIG_STATUS
+cat > $CONFIG_STATUS <<EOF
+#! /bin/sh
+# Generated automatically by configure.
+# Run this file to recreate the current configuration.
+# This directory was configured as follows,
+# on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
+#
+# $0 $ac_configure_args
+#
+# Compiler output produced by configure, useful for debugging
+# configure, is in ./config.log if it exists.
+
+ac_cs_usage="Usage: $CONFIG_STATUS [--recheck] [--version] [--help]"
+for ac_option
+do
+ case "\$ac_option" in
+ -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+ echo "running \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion"
+ exec \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion ;;
+ -version | --version | --versio | --versi | --vers | --ver | --ve | --v)
+ echo "$CONFIG_STATUS generated by autoconf version 2.10"
+ exit 0 ;;
+ -help | --help | --hel | --he | --h)
+ echo "\$ac_cs_usage"; exit 0 ;;
+ *) echo "\$ac_cs_usage"; exit 1 ;;
+ esac
+done
+
+ac_given_srcdir=$srcdir
+ac_given_INSTALL="$INSTALL"
+
+trap 'rm -fr `echo "Makefile libtxi/Makefile makeinfo/Makefile info/Makefile util/Makefile emacs/Makefile" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15
+EOF
+cat >> $CONFIG_STATUS <<EOF
+
+# Protect against being on the right side of a sed subst in config.status.
+sed 's/%@/@@/; s/@%/@@/; s/%g\$/@g/; /@g\$/s/[\\\\&%]/\\\\&/g;
+ s/@@/%@/; s/@@/@%/; s/@g\$/%g/' > conftest.subs <<\\CEOF
+$ac_vpsub
+$extrasub
+s%@CFLAGS@%$CFLAGS%g
+s%@CPPFLAGS@%$CPPFLAGS%g
+s%@CXXFLAGS@%$CXXFLAGS%g
+s%@DEFS@%$DEFS%g
+s%@LDFLAGS@%$LDFLAGS%g
+s%@LIBS@%$LIBS%g
+s%@exec_prefix@%$exec_prefix%g
+s%@prefix@%$prefix%g
+s%@program_transform_name@%$program_transform_name%g
+s%@bindir@%$bindir%g
+s%@sbindir@%$sbindir%g
+s%@libexecdir@%$libexecdir%g
+s%@datadir@%$datadir%g
+s%@sysconfdir@%$sysconfdir%g
+s%@sharedstatedir@%$sharedstatedir%g
+s%@localstatedir@%$localstatedir%g
+s%@libdir@%$libdir%g
+s%@includedir@%$includedir%g
+s%@oldincludedir@%$oldincludedir%g
+s%@infodir@%$infodir%g
+s%@mandir@%$mandir%g
+s%@CC@%$CC%g
+s%@CPP@%$CPP%g
+s%@INSTALL_PROGRAM@%$INSTALL_PROGRAM%g
+s%@INSTALL_DATA@%$INSTALL_DATA%g
+s%@RANLIB@%$RANLIB%g
+s%@TERMLIBS@%$TERMLIBS%g
+s%@ALLOCA@%$ALLOCA%g
+s%@LIBOBJS@%$LIBOBJS%g
+
+CEOF
+EOF
+cat >> $CONFIG_STATUS <<EOF
+
+CONFIG_FILES=\${CONFIG_FILES-"Makefile libtxi/Makefile makeinfo/Makefile info/Makefile util/Makefile emacs/Makefile"}
+EOF
+cat >> $CONFIG_STATUS <<\EOF
+for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then
+ # Support "outfile[:infile]", defaulting infile="outfile.in".
+ case "$ac_file" in
+ *:*) ac_file_in=`echo "$ac_file"|sed 's%.*:%%'`
+ ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;;
+ *) ac_file_in="${ac_file}.in" ;;
+ esac
+
+ # Adjust relative srcdir, etc. for subdirectories.
+
+ # Remove last slash and all that follows it. Not all systems have dirname.
+ ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'`
+ if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then
+ # The file is in a subdirectory.
+ test ! -d "$ac_dir" && mkdir "$ac_dir"
+ ac_dir_suffix="/`echo $ac_dir|sed 's%^\./%%'`"
+ # A "../" for each directory in $ac_dir_suffix.
+ ac_dots=`echo $ac_dir_suffix|sed 's%/[^/]*%../%g'`
+ else
+ ac_dir_suffix= ac_dots=
+ fi
+
+ case "$ac_given_srcdir" in
+ .) srcdir=.
+ if test -z "$ac_dots"; then top_srcdir=.
+ else top_srcdir=`echo $ac_dots|sed 's%/$%%'`; fi ;;
+ /*) srcdir="$ac_given_srcdir$ac_dir_suffix"; top_srcdir="$ac_given_srcdir" ;;
+ *) # Relative path.
+ srcdir="$ac_dots$ac_given_srcdir$ac_dir_suffix"
+ top_srcdir="$ac_dots$ac_given_srcdir" ;;
+ esac
+
+ case "$ac_given_INSTALL" in
+ [/$]*) INSTALL="$ac_given_INSTALL" ;;
+ *) INSTALL="$ac_dots$ac_given_INSTALL" ;;
+ esac
+ echo creating "$ac_file"
+ rm -f "$ac_file"
+ configure_input="Generated automatically from `echo $ac_file_in|sed 's%.*/%%'` by configure."
+ case "$ac_file" in
+ *Makefile*) ac_comsub="1i\\
+# $configure_input" ;;
+ *) ac_comsub= ;;
+ esac
+ sed -e "$ac_comsub
+s%@configure_input@%$configure_input%g
+s%@srcdir@%$srcdir%g
+s%@top_srcdir@%$top_srcdir%g
+s%@INSTALL@%$INSTALL%g
+" -f conftest.subs $ac_given_srcdir/$ac_file_in > $ac_file
+fi; done
+rm -f conftest.subs
+
+
+
+exit 0
+EOF
+chmod +x $CONFIG_STATUS
+rm -fr confdefs* $ac_clean_files
+test "$no_create" = yes || ${CONFIG_SHELL-/bin/sh} $CONFIG_STATUS || exit 1
+
diff --git a/contrib/texinfo/configure.in b/contrib/texinfo/configure.in
new file mode 100644
index 0000000..52950dc
--- /dev/null
+++ b/contrib/texinfo/configure.in
@@ -0,0 +1,42 @@
+dnl Process this file with autoconf to produce a configure script.
+dnl $Id: configure.in,v 1.3 1996/10/03 18:33:52 karl Exp $
+AC_INIT(texinfo.texi)
+
+dnl Checks for programs.
+AC_PROG_GCC_TRADITIONAL
+AC_PROG_INSTALL
+AC_PROG_RANLIB
+
+AC_ISC_POSIX
+AC_MINIX
+
+dnl Checks for libraries.
+# Needed on sysV68 for sigblock, sigsetmask.
+AC_CHECK_LIB(bsd, sigblock)
+
+TERMLIBS=
+for termlib in curses termcap terminfo termlib ; do
+ AC_CHECK_LIB(${termlib}, tputs,
+ [TERMLIBS="${TERMLIBS} -l${termlib}"; break])
+done
+AC_SUBST(TERMLIBS)
+
+dnl Checks for header files.
+AC_HEADER_STDC
+AC_CHECK_HEADERS(unistd.h termios.h termio.h strings.h string.h varargs.h \
+ sys/time.h sys/fcntl.h sys/ttold.h sys/ptem.h sys/file.h)
+
+dnl Checks for typedefs, structures, and compiler characteristics.
+AC_TYPE_OFF_T
+AC_C_CONST
+AC_STRUCT_TM
+
+dnl Checks for library functions.
+AC_FUNC_ALLOCA
+AC_FUNC_SETVBUF_REVERSED
+AC_CHECK_FUNCS(setvbuf getcwd memset bzero strchr strcasecmp \
+ vfprintf vsprintf strerror sigprocmask sigsetmask)
+dnl strcasecmp, strerror, xmalloc, xrealloc, probably others should be added.
+AC_REPLACE_FUNCS(memcpy memmove strdup)
+
+AC_OUTPUT(Makefile libtxi/Makefile makeinfo/Makefile info/Makefile util/Makefile emacs/Makefile)
diff --git a/contrib/texinfo/dir b/contrib/texinfo/dir
new file mode 100644
index 0000000..f1b1918
--- /dev/null
+++ b/contrib/texinfo/dir
@@ -0,0 +1,16 @@
+$Id: dir,v 1.2 1996/09/24 18:43:01 karl Exp $
+This is the file .../info/dir, which contains the topmost node of the
+Info hierarchy. The first time you invoke Info you start off
+looking at that node, which is (dir)Top.
+
+File: dir Node: Top This is the top of the INFO tree
+
+ This (the Directory node) gives a menu of major topics.
+ Typing "q" exits, "?" lists all Info commands, "d" returns here,
+ "h" gives a primer for first-timers,
+ "mEmacs<Return>" visits the Emacs topic, etc.
+
+ In Emacs, you can click mouse button 2 on a menu item or cross reference
+ to select it.
+
+* Menu:
diff --git a/contrib/texinfo/dir-example b/contrib/texinfo/dir-example
new file mode 100644
index 0000000..df5efc8
--- /dev/null
+++ b/contrib/texinfo/dir-example
@@ -0,0 +1,309 @@
+This is the directory file `dir' a.k.a. `DIR', which contains the
+topmost node of the Info hierarchy. This file is merely made available
+for your hacking pleasure, not official or standard in any way.
+If it doesn't make sense to you, or you don't like it, ignore it.
+
+$Id: dir,v 1.20 1996/10/04 18:39:29 karl Exp $
+
+File: dir Node: Top This is the top of the INFO tree.
+
+This node gives a menu of the major topics accessible through Info.
+
+ `q' quits;
+ `?' lists all Info commands;
+ `h' starts the Info tutorial;
+ `mTexinfo RET' visits the Texinfo manual, etc.
+
+* Menu:
+
+GNU packages
+* Bash: (bash). Bourne again shell.
+* Cpio: (cpio). Cpio archiver.
+* DC: (dc). Postfix arbitrary expression calculator.
+* Diff: (diff). Comparing and merging programs.
+* Ed: (ed). Line editor.
+* Emacs: (emacs). Extensible self-documenting text editor.
+* File utilities: (fileutils). GNU file utilities.
+* Finding files: (find). Operating on files matching certain criteria.
+* Font utilities: (fontu). Programs for font manipulation.
+* Gawk: (gawk). A text processing and scanning language.
+* Gzip: (gzip). General (de)compression.
+* Identifier DB: (id-utils). Identifier database utilities.
+* Ispell: (ispell). Interactive spelling corrector.
+* M4: (m4). Macro processor.
+* Make: (make). Remake files automatically.
+* Ptx: (ptx). Permuted index generator.
+* Shar: (sharutils). Shell archiver, uudecode/uuencode.
+* Shell utilities: (sh-utils). GNU shell utilities.
+* Tar: (tar). ``Tape'' archiver.
+* Text utilities: (textutils). GNU text utilities.
+* Time: (time). Measuring program resource usage.
+* UUCP: (uucp). Copying between machines, offline.
+* Wdiff: (wdiff). Word-by-word comparison.
+
+GNU programming tools
+* As: (as). Assembler.
+* Binutils: (binutils). ar/copy/objdump/nm/size/strip/ranlib.
+* Bison: (bison). LALR(1) parser generator.
+* CPP: (cpp). C preprocessor.
+* CVS: (cvs). Concurrent versions system for source control.
+* DejaGnu: (dejagnu). Testing framework.
+* Flex: (flex). A fast scanner generator.
+* Gasp: (gasp). GNU Assembler preprocessor.
+* Libtool: (libtool). Generic library support script.
+* GCC: (gcc). C compiler.
+* GDB: (gdb). Source-level debugger for C and C++.
+* Gperf: (gperf). Perfect hash function generator.
+* Gprof: (gprof). Profiler.
+* Indent: (indent). Prettyprinter for programs.
+* Ld: (ld). Linker.
+
+Texinfo documentation system
+* Info: (info). Documentation browsing system.
+* Texinfo: (texinfo). The GNU documentation format.
+* install-info: (texinfo)Invoking install-info. Updating info/dir entries.
+* texi2dvi: (texinfo)Format with texi2dvi. Printing Texinfo documentation.
+* texindex: (texinfo)Format with tex/texindex. Sorting Texinfo index files.
+* info program: (info-stnd). Standalone Info-reading program.
+* makeinfo: (makeinfo). Convert Texinfo source to Info or plain ASCII.
+
+GNU Emacs Lisp
+* Elisp: (elisp). GNU Emacs Lisp reference manual.
+* Intro Elisp: (emacs-lisp-intro). Introduction to Elisp programming.
+
+* Calc: (calc). Calculator and more.
+* CC-mode: (ccmode). Editing C, C++, and Objective C.
+* Common Lisp: (cl). Partial Common Lisp support for Emacs Lisp.
+* Dired-x: (dired-x). Extra directory editor features.
+* Edebug: (edebug). Source-level debugger for Emacs Lisp.
+* Ediff: (ediff). Comprehensive visual interface to diff & patch.
+* EDB: (edb). Database for Emacs.
+* Forms: (forms). Fill-in-the-form data entry.
+* Gmhist: (gmhist). Generic minibuffer history.
+* GNUS: (gnus). Netnews reading and posting.
+* Mailcrypt: (mailcrypt). Use PGP in Emacs.
+* MH-E: (mh-e). Emacs interface to the MH mail system.
+* PCL-CVS: (pcl-cvs). Emacs front end to CVS.
+* Supercite: (sc). Supercite for including other people's words.
+* VIP: (vip). vi emulation.
+* VIPER: (viper). The new VI-emulation mode in Emacs-19.29.
+* VM: (vm). Mail reader.
+* W3: (w3). WWW browser.
+
+GNU admin
+* Autoconf: (autoconf). Automatic generation of package configuration.
+* Automake: (automake). Making Makefile.in's.
+* Configure: (configure). Cygnus configure.
+* Gettext: (gettext). Internationalization.
+* Gnats: (gnats). Cygnus bug tracking system.
+* Maintaining: (maintain). Maintaining GNU software.
+* Remsync: (remsync). Remote synchronization of directory trees.
+* Send PR: (send-pr). Cygnus bug reporting for Gnats.
+* Source config: (cfg-paper). Some theory on configuring source packages.
+* Standards: (standards). GNU coding standards.
+
+GNU libraries
+* Annotate: (annotate). High-level GDB to GUI's.
+* BFD: (bfd). Binary file descriptors for object file IO.
+* GDB library: (libgdb). Application programming interface to GDB.
+* GDBM: (gdbm). Hashed databases.
+* History: (history). Recall previous lines of input.
+* Iostream: (iostream). C++ input/output.
+* Libc: (libc). C library.
+* Libg++: (libg++). C++ classes.
+* Mmalloc: (mmalloc). Memory-mapped malloc.
+* Readline: (readline). General command-line interface.
+* Regex: (regex). Regular expressions.
+* Termcap: (termcap). All about /etc/termcap.
+
+GNU programming documentation
+* GDB internals: (gdbint). Debugger internals.
+* Ld internals: (ldint). GNU linker internals.
+* Stabs: (stabs). Symbol table debugging information format.
+
+DOS
+* Demacs: (demacs). GNU Emacs for DOS.
+* GNUish: (gnuish). GNU utilities for DOS.
+
+TeX things
+* Afm2tfm: (dvips)Invoking afm2tfm. Making Type 1 fonts available to TeX.
+* Dvips: (dvips). DVI-to-PostScript translator.
+* Eplain: (eplain). Expanding on plain TeX.
+* Kpathsearch: (kpathsea). File lookup along search paths.
+* LaTeX: (latex). LaTeX.
+* MakeIndex: (makeindex). Index creation for TeX.
+* Naming fonts: (fontname). Filenames for TeX fonts.
+* TeXDraw: (texdraw). Drawing PostScript diagrams within TeX.
+* Web2c: (web2c). TeX, Metafont, and their companion programs.
+
+Other things
+* Amd: (amdref). Filesystem automounter.
+* CMUCL: (cmu-user). CMU Common Lisp.
+* File headers: (filehdr). Bibliographic information for computer files.
+* HTML: (snafu). Hypertext Markup Language 2.0 specification.
+* Jargon: (jargon). The jargon file.
+* Perl: (perl). Practical extraction and report language.
+* PRCS: (prcs). Project revision control system.
+* Screen: (screen). Virtual screen manager.
+* UMB C.S. Dept.: (csinfo). UMass/Boston Computer Science Dept. info.
+
+Individual utilities
+* aid: (id-utils)aid invocation. Matching strings.
+* ar: (binutils)ar. Create/modify/extract archives.
+* at-pr: (gnats)at-pr. Bug report timely reminders.
+* autoreconf: (autoconf)Invoking autoreconf. Remake multiple configure's.
+* autoscan: (autoconf)Invoking autoscan. Automate initial configure.in.
+* awk: (Gawk)Invoking gawk. Text processing and scanning.
+* basename: (sh-utils)basename invocation. Strip directory and suffix.
+* bibtex: (web2c)BibTeX invocation. Maintaining bibliographies.
+* c++filt: (binutils)c++filt. Demangle C++ symbols.
+* cat: (textutils)cat invocation. Concatenate and write files.
+* chgrp: (fileutils)chgrp invocation. Change file groups.
+* chmod: (fileutils)chmod invocation. Change file permissions.
+* chown: (fileutils)chown invocation. Change file owners/groups.
+* chroot: (sh-utils)chroot invocation. Specify the root directory.
+* cksum: (textutils)cksum invocation. Print POSIX CRC checksum.
+* cmp: (diff)Invoking cmp. Character-by-character diff.
+* comm: (textutils)comm invocation. Compare sorted files by line.
+* cp: (fileutils)cp invocation. Copy files.
+* csplit: (textutils)csplit invocation. Split by context.
+* cut: (textutils)cut invocation. Print selected parts of lines.
+* date: (sh-utils)date invocation. Print/set system date and time.
+* dd: (fileutils)dd invocation. Copy and convert a file.
+* df: (fileutils)df invocation. Report filesystems' disk usage.
+* diff3: (diff)Invoking diff3. Three-way diff.
+* dir: (fileutils)dir invocation. List directories briefly.
+* dirname: (sh-utils)dirname invocation. Strip non-directory suffix.
+* dmp: (web2c)Dmp invocation. Troff->MPX (MetaPost pictures).
+* du: (fileutils)du invocation. Report on disk usage.
+* dvicopy: (web2c)DVIcopy invocation. Virtual font expansion
+* dvitomp: (web2c)DVItoMP invocation. DVI to MPX (MetaPost pictures).
+* dvitype: (web2c)DVItype invocation. DVI to human-readable text.
+* echo: (sh-utils)echo invocation. Print a line of text.
+* edit-pr: (gnats)Invoking edit-pr. Changing bugs.
+* eid: (id-utils)eid invocation. Invoking an editor on matches.
+* emacsclient: (emacs)Emacs Server. Connecting to a running Emacs.
+* emacsserver: (emacs)Emacs Server. Connecting to a running Emacs.
+* env: (sh-utils)env invocation. Modify the environment.
+* etags: (emacs)Create Tags Table. Creating a TAGS table.
+* expand: (textutils)expand invocation. Convert tabs to spaces.
+* expr: (sh-utils)expr invocation. Evaluate expressions.
+* false: (sh-utils)false invocation. Do nothing, unsuccessfully.
+* fid: (id-utils)fid invocation. Listing a file's identifiers.
+* file-pr: (gnats)file-pr. Processing incoming traffic.
+* find: (find)Invoking find. Finding and acting on files.
+* fmt: (textutils)fmt invocation. Reformat paragraph text.
+* fold: (textutils)fold invocation. Wrap long input lines.
+* g++: (gcc)Invoking G++. The GNU C++ compiler.
+* gftodvi: (web2c)GFtoDVI invocation. Generic font proofsheets.
+* gftopk: (web2c)GFtoPK invocation. Generic to packed fonts.
+* gftype: (web2c)GFtype invocation. GF to human-readable text.
+* gid: (id-utils)gid invocation. Listing all matching lines.
+* groups: (sh-utils)groups invocation. Print group names a user is in.
+* gunzip: (gzip)Overview. Decompression.
+* head: (textutils)head invocation. Output the first part of files.
+* hostname: (sh-utils)hostname invocation. Print or set system name.
+* id: (sh-utils)id invocation. Print real/effective uid/gid.
+* idx: (id-utils)idx invocation. Testing mkid scanners.
+* ifnames: (autoconf)Invoking ifnames. List conditionals in source.
+* iid: (id-utils)iid invocation. Interactive complex queries.
+* inimf: (web2c)inimf invocation. Initial Metafont.
+* inimp: (web2c)inimp invocation. Initial MetaPost.
+* initex: (web2c)initex invocation. Initial TeX.
+* install: (fileutils)install invocation. Copy and change attributes.
+* join: (textutils)join invocation. Join lines on a common field.
+* kpsewhich: (kpathsea)Invoking kpsewhich. TeX file searching.
+* lid: (id-utils)lid invocation. Matching identifier patterns.
+* ln: (fileutils)ln invocation. Make links between files.
+* locate: (find)Invoking locate. Finding files in a database.
+* logname: (sh-utils)logname invocation. Print current login name.
+* ls: (fileutils)ls invocation. List directory contents.
+* makempx: (web2c)MakeMPX invocation. MetaPost label typesetting.
+* maketexmf: (kpathsea)MakeTeX scripts. MF source generation.
+* maketexpk: (kpathsea)MakeTeX scripts. PK bitmap generation.
+* maketextex: (kpathsea)MakeTeX scripts. TeX source generation.
+* maketextfm: (kpathsea)MakeTeX scripts. TeX font metric generation.
+* mf: (web2c)mf invocation. Creating typeface families.
+* mft: (web2c)MFT invocation. Prettyprinting Metafont source.
+* mkdir: (fileutils)mkdir invocation. Create directories.
+* mkfifo: (fileutils)mkfifo invocation. Create FIFOs: (named pipes).
+* mkid: (id-utils)mkid invocation. Creating an ID database.
+* mknod: (fileutils)mknod invocation. Create special files.
+* mp: (web2c)mp invocation. Creating technical diagrams.
+* mpto: (web2c)MPto invocation. MetaPost label extraction.
+* mv: (fileutils)mv invocation. Rename files.
+* newer: (web2c)Newer invocation. Compare modification times.
+* nice: (sh-utils)nice invocation. Modify scheduling priority.
+* nl: (textutils)nl invocation. Number lines and write files.
+* nlmconv: (binutils)nlmconv. Convert object to NetWare LM.
+* nm: (binutils)nm. List symbols in object files.
+* nohup: (sh-utils)nohup invocation. Immunize to hangups.
+* objcopy: (binutils)objcopy. Copy/translate object files.
+* objdump: (binutils)objdump. Display info from object files.
+* od: (textutils)od invocation. Dump files in octal, etc.
+* paste: (textutils)paste invocation. Merge lines of files.
+* patch: (diff)Invoking patch. Automatically applying diffs.
+* patgen: (web2c)Patgen invocation. Creating hyphenation patterns.
+* pathchk: (sh-utils)pathchk invocation. Check file name portability.
+* pid: (id-utils)pid invocation. Looking up filenames.
+* pktogf: (web2c)PKtoGF invocation. Packed to generic fonts.
+* pktype: (web2c)PKtype invocation. PK to human-readable text.
+* pltotf: (web2c)PLtoTF invocation. Property list to TFM.
+* pooltype: (web2c)Pooltype invocation. Display WEB pool files.
+* pr-addr: (gnats)pr-addr. Bug report address retrieval.
+* pr-edit: (gnats)pr-edit. The edit-pr driver.
+* pr: (textutils)pr invocation. Paginate or columnate files.
+* printenv: (sh-utils)printenv invocation. Print environment variables.
+* printf: (sh-utils)printf invocation. Format and print data.
+* pwd: (sh-utils)pwd invocation. Print working directory.
+* query-pr: (gnats)Invoking query-pr. Bug searching/reporting.
+* queue-pr: (gnats)queue-pr. Handling incoming traffic.
+* ranlib: (binutils)ranlib. Index archive file contents.
+* rm: (fileutils)rm invocation. Remove files.
+* rmdir: (fileutils)rmdir invocation. Remove empty directories.
+* sdiff: (diff)Invoking sdiff. Interactively merge files.
+* send-pr: (gnats)Invoking send-pr. Submitting bugs.
+* shar: (sharutils)shar invocation. Create shell archive.
+* size: (binutils)size. List object file section sizes.
+* sleep: (sh-utils)sleep invocation. Delay for a specified time.
+* sort: (textutils)sort invocation. Sort text files.
+* split: (textutils)split invocation. Split into fixed-size pieces.
+* strings: (binutils)strings. List printable strings.
+* strip: (binutils)strip. Discard symbols.
+* stty: (sh-utils)stty invocation. Print/change terminal settings.
+* su: (sh-utils)su invocation. Modify user and group id.
+* sum: (textutils)sum invocation. Print traditional checksum.
+* sync: (fileutils)sync invocation. Synchronize memory and disk.
+* tabs: (tput)Invoking tabs. Tab settings.
+* tac: (textutils)tac invocation. Reverse files.
+* tail: (textutils)tail invocation. Output the last part of files.
+* tangle: (web2c)Tangle invocation. WEB to Pascal.
+* tee: (sh-utils)tee invocation. Redirect to multiple files.
+* test: (sh-utils)test invocation. File/string tests.
+* tex: (web2c)tex invocation. Typesetting.
+* tftopl: (web2c)TFtoPL invocation. TFM -> property list.
+* touch: (fileutils)touch invocation. Change file timestamps.
+* tput: (tput)Invoking tput. Termcap in shell scripts.
+* tr: (textutils)tr invocation. Translate characters.
+* true: (sh-utils)true invocation. Do nothing, successfully.
+* tty: (sh-utils)tty invocation. Print terminal name.
+* uname: (sh-utils)uname invocation. Print system information.
+* unexpand: (textutils)unexpand invocation. Convert spaces to tabs.
+* uniq: (textutils)uniq invocation. Uniqify files.
+* unshar: (sharutils)unshar invocation. Extract from shell archive.
+* updatedb: (find)Invoking updatedb. Building the locate database.
+* users: (sh-utils)users invocation. Print current user names.
+* vdir: (fileutils)vdir invocation. List directories verbosely.
+* vftovp: (web2c)VFtoVP invocation. Virtual font -> virtual pl.
+* view-pr: (gnats)Invoking view-pr. Showing bug reports.
+* virmf: (web2c)virmf invocation. Virgin Metafont.
+* virmp: (web2c)virmp invocation. Virgin MetaPost.
+* virtex: (web2c)virtex invocation. Virgin TeX.
+* vptovf: (web2c)VPtoVF invocation. Virtual pl -> virtual font.
+* wc: (textutils)wc invocation. Byte, word, and line counts.
+* weave: (web2c)Weave invocation. WEB to TeX.
+* who: (sh-utils)who invocation. Print who is logged in.
+* whoami: (sh-utils)whoami invocation. Print effective user id.
+* xargs: (find)Invoking xargs. Operating on many files.
+* yes: (sh-utils)yes invocation. Print a string indefinitely.
+* zcat: (gzip)Overview. Decompression to stdout.
diff --git a/contrib/texinfo/emacs/Makefile.in b/contrib/texinfo/emacs/Makefile.in
new file mode 100644
index 0000000..f011b33
--- /dev/null
+++ b/contrib/texinfo/emacs/Makefile.in
@@ -0,0 +1,88 @@
+# Makefile for Texinfo/emacs.
+# Copyright (C) 1995, 96 Free Software Foundation, Inc.
+# $Id: Makefile.in,v 1.4 1996/09/28 21:34:34 karl Exp $
+
+# 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# Author: Brian J. Fox (bfox@ai.mit.edu)
+#
+
+srcdir = @srcdir@
+VPATH = $(srcdir)
+SHELL = /bin/sh
+RM = rm -f
+
+
+ELISP_SRCS = info.el makeinfo.el texinfo.el texnfo-upd.el \
+ texnfo-tex.el texinfmt.el informat.el detexinfo.el
+ELISP_OBJS = info.elc makeinfo.elc texinfo.elc texnfo-upd.elc \
+ texnfo-tex.elc texinfmt.elc informat.elc detexinfo.elc
+
+.SUFFIXES: .el .elc
+
+.el.elc:
+ $(srcdir)/elisp-comp $<
+
+all:
+sub-all: all
+
+elisp: $(ELISP_OBJS)
+.PHONY: elisp
+
+# Nobody likes any of these install targets. Fine. Install it
+# manually, then.
+install:
+ @echo Please install the Emacs Lisp files manually.
+
+uninstall:
+ @echo Please uninstall the Emacs Lisp files manually.
+
+# install: $(ELISP_OBJS)
+# @(echo "(print (car load-path))" >/tmp/elc.$$$$; \
+# lispdir=`emacs -batch -q -l /tmp/elc.$$$$ -nw | grep site-lisp`; \
+# rm /tmp/elc.$$$$; \
+# if [ "$$lispdir" != "" ]; then \
+# lispdir=`echo $$lispdir | sed -e 's/"//g'`; \
+# echo "Installing .elc files in $$lispdir."; \
+# $(CP) $(ELISP_OBJS) $$lispdir; \
+# else \
+# echo "To install the elisp files, please copy *.elc to the"; \
+# echo "emacs site-lisp directory."; \
+# fi)
+#
+# install: $(ELISP_OBJS)
+# for file in $(ELISP_OBJS); do \
+# $(INSTALL_DATA) $$file $(lispdir); \
+# done
+#
+# uninstall: $(ELISP_OBJS)
+# cd $(lispdir) && rm -f $(ELISP_OBJS)
+#
+informat.elc: info.elc
+makeinfo.elc: texinfo.elc
+texinfmt.elc: texinfo.elc
+texinfmt.elc: texnfo-upd.elc
+
+Makefile: $(srcdir)/Makefile.in ../config.status
+ cd .. && sh config.status
+
+realclean distclean: clean
+ $(RM) Makefile *.log
+
+clean: FORCE
+ $(RM) *.elc
+
+FORCE:
+
diff --git a/contrib/texinfo/emacs/detexinfo.el b/contrib/texinfo/emacs/detexinfo.el
new file mode 100644
index 0000000..fda9909
--- /dev/null
+++ b/contrib/texinfo/emacs/detexinfo.el
@@ -0,0 +1,250 @@
+;;; Here is a handy keybinding:
+
+(global-set-key "\C-x\\" 'detexinfo)
+
+;;;;;;;;;;;;;;;; detexinfo.el ;;;;;;;;;;;;;;;;
+;;;
+;;; Remove Texinfo commands from a Texinfo source file.
+;;;
+;;; Copyright (C) 1991, 1992 Free Software Foundation
+;;; Robert J. Chassell
+;;; bugs to bug-texinfo@prep.ai.mit.edu
+;;;
+;;; ==> test version <==
+;;; Fails if Texinfo source file contains formatting errors.
+;;;
+;;; Version 0.05 - 3 Jun 1992
+;;; Add to list of removed commands. Improve messages.
+;;;
+;;; Version 0.04 - 27 Jan 1992
+;;; Rewrite to insert detexinfo'd text into a temporary buffer.
+;;;
+;;; Version 0.03 - 27 Dec 1991
+;;; Improved messages.
+;;;
+;;; Version 0.02 - 13 Nov 1991
+;;; detexinfo-remove-inline-cmd, detexinfo-syntax-table: Handle
+;;; nested commands.
+;;; detexinfo: Handle nested @'s, eg @samp{@}} and @samp{@@};
+;;; replace @TeX{} with TeX.
+;;;
+;;; Version 0.01 - 13 Nov 1991
+;;;
+;;; Based on detex.el, by Bengt Martensson, 4 Oct 1987
+;;;
+;;;;;;;;;;;;;;;;
+
+(defvar detexinfo-buffer-name "*detexinfo*"
+ "*Name of the temporary buffer used by \\[detexinfo].")
+
+(defvar detexinfo-syntax-table nil)
+
+(if detexinfo-syntax-table
+ nil
+ (setq detexinfo-syntax-table (make-syntax-table))
+ (modify-syntax-entry ?\[ "." detexinfo-syntax-table)
+ (modify-syntax-entry ?\] "." detexinfo-syntax-table)
+ (modify-syntax-entry ?\" "." detexinfo-syntax-table)
+ (modify-syntax-entry ?\\ "." detexinfo-syntax-table)
+ (modify-syntax-entry ?\( "." detexinfo-syntax-table)
+ (modify-syntax-entry ?\) "." detexinfo-syntax-table)
+ (modify-syntax-entry ?{ "(}" detexinfo-syntax-table)
+ (modify-syntax-entry ?} "){" detexinfo-syntax-table))
+
+(defun detexinfo ()
+ "Remove Texinfo commands from current buffer, copying result to new buffer.
+BUG: Fails if Texinfo source file contains formatting errors."
+ (interactive)
+ (let ((input-buffer (current-buffer)))
+ ;; Find a buffer to use.
+ (switch-to-buffer (get-buffer-create detexinfo-buffer-name))
+ (setq major-mode 'detexinfo-mode)
+ (set-syntax-table detexinfo-syntax-table)
+ (erase-buffer)
+ (insert-buffer-substring input-buffer)
+
+ ;; Replace @{ and @} with %#* and *#% temporarily, so @samp{@{} works.
+ ;; What is a better way of doing this??
+ (goto-char (point-min))
+ (while (search-forward "@{" nil t) ; e.g., @samp{@{}
+ (replace-match "%#*"))
+ (goto-char (point-min))
+ (while (search-forward "@}" nil t)
+ (forward-char -3) ; e.g., @samp{@@}
+ (if (looking-at "@") ; Two @@ in a row
+ (progn
+ (delete-char 2)
+ (insert "%&%#"))
+ (forward-char 1)
+ (delete-char 2)
+ (insert "*#%")))
+
+ (goto-char (point-min))
+ ;; Remove @refill, the only inline command without braces.
+ (while (search-forward "@refill" nil t)
+ (replace-match ""))
+ ;; Replace @TeX{} with TeX
+ (goto-char (point-min))
+ (while (search-forward "@TeX{}" nil t) (replace-match "TeX" t t))
+
+ (detexinfo-remove-line-cmds-without-arg)
+ (detexinfo-remove-inline-cmds-without-arg)
+ (detexinfo-remove-inline-cmds-keep-arg)
+ (detexinfo-remove-line-cmds-deletable-arg)
+ (detexinfo-remove-line-cmds-maybe-delete-arg)
+ (detexinfo-remove-line-cmds-keep-arg)
+
+ ;; Now replace %#*, *#%, and %&%# with {, }, and @@.
+ (goto-char (point-min))
+ (while (search-forward "%#*" nil t)
+ (replace-match "{"))
+ (goto-char (point-min))
+ (while (search-forward "*#%" nil t)
+ (replace-match "}"))
+ (goto-char (point-min))
+ (while (search-forward "%&%#" nil t)
+ (replace-match "@@"))
+
+ ;; Scan for remaining two character @-commands
+ (goto-char (point-min))
+ (while (search-forward "@" nil t)
+ (cond ((looking-at "[*:]")
+ (delete-region (1- (point)) (1+ (point))))
+ ((looking-at "[{}^@.'`]\"?!")
+ (delete-region (1- (point)) (point)))))
+
+ (goto-char (point-min))
+ (message "Done...removed Texinfo commands from buffer. You may save it.")))
+
+(defun detexinfo-remove-whole-line (cmd)
+ "Delete Texinfo line command CMD at beginning of line and rest of line."
+ (goto-char (point-min))
+ (while
+ (re-search-forward
+ (concat "^@" cmd "[ \n]+") (point-max) t)
+ (goto-char (match-beginning 0))
+ (delete-region
+ (point) (save-excursion (end-of-line) (1+ (point))))))
+
+(defun detexinfo-remove-inline-cmd (cmd)
+ "Delete Texinfo inline command CMD, eg. @point, @code."
+ (goto-char (point-min))
+ (while
+ (re-search-forward (concat "@" cmd "{") (point-max) t)
+ (save-excursion
+ (forward-char -1)
+ (forward-sexp 1)
+ (delete-char -1)) ; delete right brace
+ (delete-region (point) (match-beginning 0))))
+
+;;;;;;;;;;;;;;;;
+
+;;; 1. @setfilename and other line commands with args to delete
+
+(defvar detexinfo-line-cmds-deletable-arg
+ '("enumerate" "ftable" "vtable" "itemize" "table"
+ "setfilename" "settitle" "setchapternewpage"
+ "footnotestyle" "paragraphindent"
+ "include" "need" "sp"
+ "clear" "ifclear" "ifset" "set"
+ "defcodeindex" "defindex" "syncodeindex" "synindex")
+ "List of Texinfo commands whose arguments should be deleted.")
+
+(defun detexinfo-remove-line-cmds-deletable-arg ()
+ "Delete Texinfo line commands together with their args, eg @setfilename."
+ (message "Removing commands such as @enumerate...with their arguments...")
+ (mapcar 'detexinfo-remove-whole-line
+ detexinfo-line-cmds-deletable-arg))
+
+;;; 2. @cindex and other cmds with args that may be deleted
+;;; This list is here just to make it easier to revise the
+;;; categories. In particular, you might want to keep the index entries.
+
+(defvar detexinfo-line-cmds-maybe-delete-arg
+ '("cindex" "findex" "kindex" "pindex" "tindex" "vindex" "node"
+ "c" "comment" "end" "headings" "printindex" "vskip"
+ "evenfooting" "evenheading" "everyfooting" "everyheading"
+ "oddfooting" "oddheading")
+ "List of Texinfo commands whose arguments may possibly be deleted.")
+
+(defun detexinfo-remove-line-cmds-maybe-delete-arg ()
+ "Delete Texinfo line commands together with their arguments, eg, @cindex."
+ (message "Removing commands such as @cindex...with their arguments...")
+ (mapcar 'detexinfo-remove-whole-line
+ detexinfo-line-cmds-maybe-delete-arg))
+
+;;; 3. @chapter and other line cmds with args to keep.
+
+(defvar detexinfo-line-cmds-keep-arg
+ '("top" "chapter" "section" "subsection" "subsubsection"
+ "unnumbered" "unnumberedsec" "unnumberedsubsec" "unnumberedsubsubsec"
+ "majorheading" "chapheading" "heading" "subheading" "subsubheading"
+ "appendix" "appendixsec" "appendixsubsec" "appendixsubsubsec"
+ "item" "itemx"
+ "title" "subtitle" "center" "author" "exdent"
+ "defcv" "deffn" "defivar" "defmac" "defmethod" "defop" "defopt"
+ "defspec" "deftp" "deftypefn" "deftypefun" "deftypvr"
+ "deftypevar" "defun" "defvar" "defvr")
+ "List of Texinfo line commands whose arguments should be kept.")
+
+(defun detexinfo-remove-line-cmds-keep-arg ()
+ "Delete Texinfo line commands but keep their arguments, eg @chapter."
+ (message "Removing commands such as @chapter...but not their arguments...")
+ (mapcar 'detexinfo-remove-line-cmd-keep-arg
+ detexinfo-line-cmds-keep-arg))
+
+(defun detexinfo-remove-line-cmd-keep-arg (cmd)
+ "Delete Texinfo line command CMD but keep its argument, eg @chapter."
+ (goto-char (point-min))
+ (while
+ (re-search-forward
+ (concat "^@" cmd "[ \n]+") (point-max) t)
+ (delete-region (match-beginning 0) (match-end 0))))
+
+;;; 4. @bye and other line commands without args.
+
+(defvar detexinfo-line-cmds-without-arg
+ '("bye" "contents" "display" "example" "finalout"
+ "flushleft" "flushright" "format" "group" "ifhtml" "ifinfo" "iftex"
+ "ignore" "lisp" "menu" "noindent" "page" "quotation"
+ "shortcontents" "smallbook" "smallexample" "smalllisp"
+ "summarycontents" "tex" "thischapter" "thischaptername"
+ "thisfile" "thispage" "thissection" "thistitle" "titlepage")
+ "List of Texinfo commands without arguments that should be deleted.")
+
+(defun detexinfo-remove-line-cmds-without-arg ()
+ "Delete line Texinfo commands that lack args, eg. @example."
+ (message "Removing commands such as @example...that lack arguments...")
+ (mapcar 'detexinfo-remove-whole-line
+ detexinfo-line-cmds-without-arg))
+
+;;; 5. @equiv and other inline cmds without args.
+
+(defvar detexinfo-inline-cmds-without-arg
+ '("equiv" "error" "expansion" "point" "print" "result"
+ "asis" "br" "bullet" "dots" "minus" "today")
+ "List of Texinfo inline commands without arguments that should be deleted.")
+
+(defun detexinfo-remove-inline-cmds-without-arg ()
+ "Delete Texinfo inline commands in that lack arguments."
+ (message "Removing within line commands such as @result...")
+ (mapcar 'detexinfo-remove-inline-cmd
+ detexinfo-inline-cmds-without-arg))
+
+;;; 6. @code and other inline cmds with args to keep
+
+(defvar detexinfo-inline-cmds-keep-arg
+ '("b" "cartouche" "cite" "code" "copyright" "ctrl" "dfn" "dmn"
+ "emph" "file" "footnote" "i" "inforef"
+ "kbd" "key" "pxref" "r" "ref" "samp" "sc" "titlefont"
+ "strong" "t" "var" "w" "xref")
+ "List of Texinfo inline commands with arguments that should be kept.")
+
+(defun detexinfo-remove-inline-cmds-keep-arg ()
+ "Delete Texinfo inline commands but keep its arg, eg. @code."
+ (message
+ "Removing within line commands such as @code...but not their arguments...")
+ (mapcar 'detexinfo-remove-inline-cmd
+ detexinfo-inline-cmds-keep-arg))
+
+;;;;;;;;;;;;;;;; end detexinfo.el ;;;;;;;;;;;;;;;;
diff --git a/contrib/texinfo/emacs/elisp-comp b/contrib/texinfo/emacs/elisp-comp
new file mode 100755
index 0000000..6505826
--- /dev/null
+++ b/contrib/texinfo/emacs/elisp-comp
@@ -0,0 +1,7 @@
+#!/bin/sh
+# $Id: elisp-comp,v 1.2 1996/09/26 23:41:08 karl Exp $
+# Trivial script to compile the Elisp files.
+setpath=${TMPDIR-/tmp}/elc.$$
+echo "(setq load-path (cons nil load-path))" > $setpath
+emacs -batch -l $setpath -f batch-byte-compile "$@"
+rm -f $setpath
diff --git a/contrib/texinfo/emacs/info.el b/contrib/texinfo/emacs/info.el
new file mode 100644
index 0000000..ead6ab92
--- /dev/null
+++ b/contrib/texinfo/emacs/info.el
@@ -0,0 +1,1846 @@
+;;; info.el --- info package for Emacs.
+
+;; Copyright (C) 1985, 1986, 1992, 1993, 1994 Free Software Foundation, Inc.
+
+;; Maintainer: FSF
+;; Keywords: help
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs 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, or (at your option)
+;; any later version.
+
+;; GNU Emacs 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; see the file COPYING. If not, write to the
+;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+;;; Commentary:
+
+;; Note that nowadays we expect info files to be made using makeinfo.
+
+;;; Code:
+
+(defvar Info-history nil
+ "List of info nodes user has visited.
+Each element of list is a list (FILENAME NODENAME BUFFERPOS).")
+
+(defvar Info-enable-edit nil
+ "*Non-nil means the \\<Info-mode-map>\\[Info-edit] command in Info can edit the current node.
+This is convenient if you want to write info files by hand.
+However, we recommend that you not do this.
+It is better to write a Texinfo file and generate the Info file from that,
+because that gives you a printed manual as well.")
+
+(defvar Info-enable-active-nodes nil
+ "Non-nil allows Info to execute Lisp code associated with nodes.
+The Lisp code is executed when the node is selected.")
+(put 'Info-enable-active-nodes 'risky-local-variable t)
+
+(defvar Info-fontify t
+ "*Non-nil enables highlighting and fonts in Info nodes.")
+
+(defvar Info-fontify-maximum-menu-size 30000
+ "*Maximum size of menu to fontify if `Info-fontify' is non-nil.")
+
+(defvar Info-directory-list
+ (let ((path (getenv "INFOPATH"))
+ ;; This is for older Emacs versions
+ ;; which might get this info.el from the Texinfo distribution.
+ (path-separator (if (boundp 'path-separator) path-separator
+ (if (eq system-type 'ms-dos) ";" ":")))
+ (source (expand-file-name "info/" source-directory))
+ (sibling (if installation-directory
+ (expand-file-name "info/" installation-directory)))
+ alternative)
+ (if path
+ (let ((list nil)
+ idx)
+ (while (> (length path) 0)
+ (setq idx (or (string-match path-separator path) (length path))
+ list (cons (substring path 0 idx) list)
+ path (substring path (min (1+ idx)
+ (length path)))))
+ (nreverse list))
+ (if (and sibling (file-exists-p sibling))
+ (setq alternative sibling)
+ (setq alternative source))
+ (if (or (member alternative Info-default-directory-list)
+ (not (file-exists-p alternative))
+ ;; On DOS/NT, we use movable executables always,
+ ;; and we must always find the Info dir at run time.
+ (if (or (eq system-type 'ms-dos) (eq system-type 'windows-nt))
+ nil
+ ;; Use invocation-directory for Info only if we used it for
+ ;; exec-directory also.
+ (not (string= exec-directory
+ (expand-file-name "lib-src/"
+ installation-directory)))))
+ Info-default-directory-list
+ (reverse (cons alternative
+ (cdr (reverse Info-default-directory-list)))))))
+ "List of directories to search for Info documentation files.
+nil means not yet initialized. In this case, Info uses the environment
+variable INFOPATH to initialize it, or `Info-default-directory-list'
+if there is no INFOPATH variable in the environment.
+The last element of `Info-default-directory-list' is the directory
+where Emacs installs the Info files that come with it.
+
+If you run the Emacs executable from the `src' directory in the Emacs
+source tree, the `info' directory in the source tree is used as the last
+element, in place of the installation Info directory. This is useful
+when you run a version of Emacs without installing it.")
+
+(defvar Info-additional-directory-list nil
+ "List of additional directories to search for Info documentation files.
+These directories are not searched for merging the `dir' file.")
+
+(defvar Info-current-file nil
+ "Info file that Info is now looking at, or nil.
+This is the name that was specified in Info, not the actual file name.
+It doesn't contain directory names or file name extensions added by Info.")
+
+(defvar Info-current-subfile nil
+ "Info subfile that is actually in the *info* buffer now,
+or nil if current info file is not split into subfiles.")
+
+(defvar Info-current-node nil
+ "Name of node that Info is now looking at, or nil.")
+
+(defvar Info-tag-table-marker (make-marker)
+ "Marker pointing at beginning of current Info file's tag table.
+Marker points nowhere if file has no tag table.")
+
+(defvar Info-current-file-completions nil
+ "Cached completion list for current Info file.")
+
+(defvar Info-index-alternatives nil
+ "List of possible matches for last Info-index command.")
+
+(defvar Info-standalone nil
+ "Non-nil if Emacs was started solely as an Info browser.")
+
+(defvar Info-suffix-list
+ (if (eq system-type 'ms-dos)
+ '( (".gz" . "gunzip")
+ (".z" . "gunzip")
+ (".inf" . nil)
+ ("" . nil))
+ '( (".info.Z" . "uncompress")
+ (".info.Y" . "unyabba")
+ (".info.gz" . "gunzip")
+ (".info.z" . "gunzip")
+ (".info" . nil)
+ (".Z" . "uncompress")
+ (".Y" . "unyabba")
+ (".gz" . "gunzip")
+ (".z" . "gunzip")
+ ("" . nil)))
+ "List of file name suffixes and associated decoding commands.
+Each entry should be (SUFFIX . STRING); the file is given to
+the command as standard input. If STRING is nil, no decoding is done.
+Because the SUFFIXes are tried in order, the empty string should
+be last in the list.")
+
+;; Concatenate SUFFIX onto FILENAME. SUFFIX should start with a dot.
+;; First, on ms-dos, delete some of the extension in FILENAME
+;; to make room.
+(defun info-insert-file-contents-1 (filename suffix)
+ (if (not (eq system-type 'ms-dos))
+ (concat filename suffix)
+ (let* ((sans-exts (file-name-sans-extension filename))
+ ;; How long is the extension in FILENAME (not counting the dot).
+ (ext-len (max 0 (- (length filename) (length sans-exts) 1)))
+ ext-left)
+ ;; SUFFIX starts with a dot. If FILENAME already has one,
+ ;; get rid of the one in SUFFIX (unless suffix is empty).
+ (or (and (<= ext-len 0)
+ (not (eq (aref filename (1- (length filename))) ?.)))
+ (= (length suffix) 0)
+ (setq suffix (substring suffix 1)))
+ ;; How many chars of that extension should we keep?
+ (setq ext-left (min ext-len (max 0 (- 3 (length suffix)))))
+ ;; Get rid of the rest of the extension, and add SUFFIX.
+ (concat (substring filename 0 (- (length filename)
+ (- ext-len ext-left)))
+ suffix))))
+
+(defun info-insert-file-contents (filename &optional visit)
+ "Insert the contents of an info file in the current buffer.
+Do the right thing if the file has been compressed or zipped."
+ (let ((tail Info-suffix-list)
+ fullname decoder)
+ (if (file-exists-p filename)
+ ;; FILENAME exists--see if that name contains a suffix.
+ ;; If so, set DECODE accordingly.
+ (progn
+ (while (and tail
+ (not (string-match
+ (concat (regexp-quote (car (car tail))) "$")
+ filename)))
+ (setq tail (cdr tail)))
+ (setq fullname filename
+ decoder (cdr (car tail))))
+ ;; Try adding suffixes to FILENAME and see if we can find something.
+ (while (and tail
+ (not (file-exists-p (info-insert-file-contents-1
+ filename (car (car tail))))))
+ (setq tail (cdr tail)))
+ ;; If we found a file with a suffix, set DECODER according to the suffix
+ ;; and set FULLNAME to the file's actual name.
+ (setq fullname (info-insert-file-contents-1 filename (car (car tail)))
+ decoder (cdr (car tail)))
+ (or tail
+ (error "Can't find %s or any compressed version of it" filename)))
+ ;; check for conflict with jka-compr
+ (if (and (featurep 'jka-compr)
+ (jka-compr-installed-p)
+ (jka-compr-get-compression-info fullname))
+ (setq decoder nil))
+ (insert-file-contents fullname visit)
+ (if decoder
+ (let ((buffer-read-only nil)
+ (default-directory (or (file-name-directory fullname)
+ default-directory)))
+ (call-process-region (point-min) (point-max) decoder t t)))))
+
+;;;###autoload (add-hook 'same-window-buffer-names "*info*")
+
+;;;###autoload
+(defun info (&optional file)
+ "Enter Info, the documentation browser.
+Optional argument FILE specifies the file to examine;
+the default is the top-level directory of Info.
+
+In interactive use, a prefix argument directs this command
+to read a file name from the minibuffer.
+
+The search path for Info files is in the variable `Info-directory-list'.
+The top-level Info directory is made by combining all the files named `dir'
+in all the directories in that path."
+ (interactive (if current-prefix-arg
+ (list (read-file-name "Info file name: " nil nil t))))
+ (if file
+ (Info-goto-node (concat "(" file ")"))
+ (if (get-buffer "*info*")
+ (pop-to-buffer "*info*")
+ (Info-directory))))
+
+;;;###autoload
+(defun info-standalone ()
+ "Run Emacs as a standalone Info reader.
+Usage: emacs -f info-standalone [filename]
+In standalone mode, \\<Info-mode-map>\\[Info-exit] exits Emacs itself."
+ (setq Info-standalone t)
+ (if (and command-line-args-left
+ (not (string-match "^-" (car command-line-args-left))))
+ (condition-case err
+ (progn
+ (info (car command-line-args-left))
+ (setq command-line-args-left (cdr command-line-args-left)))
+ (error (send-string-to-terminal
+ (format "%s\n" (if (eq (car-safe err) 'error)
+ (nth 1 err) err)))
+ (save-buffers-kill-emacs)))
+ (info)))
+
+;; Go to an info node specified as separate filename and nodename.
+;; no-going-back is non-nil if recovering from an error in this function;
+;; it says do not attempt further (recursive) error recovery.
+(defun Info-find-node (filename nodename &optional no-going-back)
+ ;; Convert filename to lower case if not found as specified.
+ ;; Expand it.
+ (if filename
+ (let (temp temp-downcase found)
+ (setq filename (substitute-in-file-name filename))
+ (if (string= (downcase filename) "dir")
+ (setq found t)
+ (let ((dirs (if (string-match "^\\./" filename)
+ ;; If specified name starts with `./'
+ ;; then just try current directory.
+ '("./")
+ (if (file-name-absolute-p filename)
+ ;; No point in searching for an
+ ;; absolute file name
+ '(nil)
+ (if Info-additional-directory-list
+ (append Info-directory-list
+ Info-additional-directory-list)
+ Info-directory-list)))))
+ ;; Search the directory list for file FILENAME.
+ (while (and dirs (not found))
+ (setq temp (expand-file-name filename (car dirs)))
+ (setq temp-downcase
+ (expand-file-name (downcase filename) (car dirs)))
+ ;; Try several variants of specified name.
+ (let ((suffix-list Info-suffix-list))
+ (while (and suffix-list (not found))
+ (cond ((file-exists-p
+ (info-insert-file-contents-1
+ temp (car (car suffix-list))))
+ (setq found temp))
+ ((file-exists-p
+ (info-insert-file-contents-1
+ temp-downcase (car (car suffix-list))))
+ (setq found temp-downcase)))
+ (setq suffix-list (cdr suffix-list))))
+ (setq dirs (cdr dirs)))))
+ (if found
+ (setq filename found)
+ (error "Info file %s does not exist" filename))))
+ ;; Record the node we are leaving.
+ (if (and Info-current-file (not no-going-back))
+ (setq Info-history
+ (cons (list Info-current-file Info-current-node (point))
+ Info-history)))
+ ;; Go into info buffer.
+ (switch-to-buffer "*info*")
+ (buffer-disable-undo (current-buffer))
+ (or (eq major-mode 'Info-mode)
+ (Info-mode))
+ (widen)
+ (setq Info-current-node nil)
+ (unwind-protect
+ (progn
+ ;; Switch files if necessary
+ (or (null filename)
+ (equal Info-current-file filename)
+ (let ((buffer-read-only nil))
+ (setq Info-current-file nil
+ Info-current-subfile nil
+ Info-current-file-completions nil
+ Info-index-alternatives nil
+ buffer-file-name nil)
+ (erase-buffer)
+ (if (eq filename t)
+ (Info-insert-dir)
+ (info-insert-file-contents filename t)
+ (setq default-directory (file-name-directory filename)))
+ (set-buffer-modified-p nil)
+ ;; See whether file has a tag table. Record the location if yes.
+ (set-marker Info-tag-table-marker nil)
+ (goto-char (point-max))
+ (forward-line -8)
+ ;; Use string-equal, not equal, to ignore text props.
+ (or (string-equal nodename "*")
+ (not (search-forward "\^_\nEnd tag table\n" nil t))
+ (let (pos)
+ ;; We have a tag table. Find its beginning.
+ ;; Is this an indirect file?
+ (search-backward "\nTag table:\n")
+ (setq pos (point))
+ (if (save-excursion
+ (forward-line 2)
+ (looking-at "(Indirect)\n"))
+ ;; It is indirect. Copy it to another buffer
+ ;; and record that the tag table is in that buffer.
+ (save-excursion
+ (let ((buf (current-buffer)))
+ (set-buffer (get-buffer-create " *info tag table*"))
+ (buffer-disable-undo (current-buffer))
+ (setq case-fold-search t)
+ (erase-buffer)
+ (insert-buffer-substring buf)
+ (set-marker Info-tag-table-marker
+ (match-end 0))))
+ (set-marker Info-tag-table-marker pos))))
+ (setq Info-current-file
+ (if (eq filename t) "dir" filename))))
+ ;; Use string-equal, not equal, to ignore text props.
+ (if (string-equal nodename "*")
+ (progn (setq Info-current-node nodename)
+ (Info-set-mode-line))
+ ;; Search file for a suitable node.
+ (let ((guesspos (point-min))
+ (regexp (concat "Node: *" (regexp-quote nodename) " *[,\t\n\177]")))
+ ;; First get advice from tag table if file has one.
+ ;; Also, if this is an indirect info file,
+ ;; read the proper subfile into this buffer.
+ (if (marker-position Info-tag-table-marker)
+ (save-excursion
+ (set-buffer (marker-buffer Info-tag-table-marker))
+ (goto-char Info-tag-table-marker)
+ (if (re-search-forward regexp nil t)
+ (progn
+ (setq guesspos (read (current-buffer)))
+ ;; If this is an indirect file,
+ ;; determine which file really holds this node
+ ;; and read it in.
+ (if (not (eq (current-buffer) (get-buffer "*info*")))
+ (setq guesspos
+ (Info-read-subfile guesspos))))
+ (error "No such node: %s" nodename))))
+ (goto-char (max (point-min) (- guesspos 1000)))
+ ;; Now search from our advised position (or from beg of buffer)
+ ;; to find the actual node.
+ (catch 'foo
+ (while (search-forward "\n\^_" nil t)
+ (forward-line 1)
+ (let ((beg (point)))
+ (forward-line 1)
+ (if (re-search-backward regexp beg t)
+ (throw 'foo t))))
+ (error "No such node: %s" nodename)))
+ (Info-select-node)))
+ ;; If we did not finish finding the specified node,
+ ;; go back to the previous one.
+ (or Info-current-node no-going-back (null Info-history)
+ (let ((hist (car Info-history)))
+ (setq Info-history (cdr Info-history))
+ (Info-find-node (nth 0 hist) (nth 1 hist) t)
+ (goto-char (nth 2 hist)))))
+ (goto-char (point-min)))
+
+;; Cache the contents of the (virtual) dir file, once we have merged
+;; it for the first time, so we can save time subsequently.
+(defvar Info-dir-contents nil)
+
+;; Cache for the directory we decided to use for the default-directory
+;; of the merged dir text.
+(defvar Info-dir-contents-directory nil)
+
+;; Record the file attributes of all the files from which we
+;; constructed Info-dir-contents.
+(defvar Info-dir-file-attributes nil)
+
+;; Construct the Info directory node by merging the files named `dir'
+;; from various directories. Set the *info* buffer's
+;; default-directory to the first directory we actually get any text
+;; from.
+(defun Info-insert-dir ()
+ (if (and Info-dir-contents Info-dir-file-attributes
+ ;; Verify that none of the files we used has changed
+ ;; since we used it.
+ (eval (cons 'and
+ (mapcar '(lambda (elt)
+ (let ((curr (file-attributes (car elt))))
+ ;; Don't compare the access time.
+ (if curr (setcar (nthcdr 4 curr) 0))
+ (setcar (nthcdr 4 (cdr elt)) 0)
+ (equal (cdr elt) curr)))
+ Info-dir-file-attributes))))
+ (insert Info-dir-contents)
+ (let ((dirs Info-directory-list)
+ buffers buffer others nodes dirs-done)
+
+ (setq Info-dir-file-attributes nil)
+
+ ;; Search the directory list for the directory file.
+ (while dirs
+ (let ((truename (file-truename (expand-file-name (car dirs)))))
+ (or (member truename dirs-done)
+ (member (directory-file-name truename) dirs-done)
+ ;; Try several variants of specified name.
+ ;; Try upcasing, appending `.info', or both.
+ (let* (file
+ (attrs
+ (or
+ (progn (setq file (expand-file-name "dir" truename))
+ (file-attributes file))
+ (progn (setq file (expand-file-name "DIR" truename))
+ (file-attributes file))
+ (progn (setq file (expand-file-name "dir.info" truename))
+ (file-attributes file))
+ (progn (setq file (expand-file-name "DIR.INFO" truename))
+ (file-attributes file)))))
+ (setq dirs-done
+ (cons truename
+ (cons (directory-file-name truename)
+ dirs-done)))
+ (if attrs
+ (save-excursion
+ (or buffers
+ (message "Composing main Info directory..."))
+ (set-buffer (generate-new-buffer "info dir"))
+ (insert-file-contents file)
+ (setq buffers (cons (current-buffer) buffers)
+ Info-dir-file-attributes
+ (cons (cons file attrs)
+ Info-dir-file-attributes))))))
+ (or (cdr dirs) (setq Info-dir-contents-directory (car dirs)))
+ (setq dirs (cdr dirs))))
+
+ (or buffers
+ (error "Can't find the Info directory node"))
+ ;; Distinguish the dir file that comes with Emacs from all the
+ ;; others. Yes, that is really what this is supposed to do.
+ ;; If it doesn't work, fix it.
+ (setq buffer (car buffers)
+ others (cdr buffers))
+
+ ;; Insert the entire original dir file as a start; note that we've
+ ;; already saved its default directory to use as the default
+ ;; directory for the whole concatenation.
+ (insert-buffer buffer)
+
+ ;; Look at each of the other buffers one by one.
+ (while others
+ (let ((other (car others)))
+ ;; In each, find all the menus.
+ (save-excursion
+ (set-buffer other)
+ (goto-char (point-min))
+ ;; Find each menu, and add an elt to NODES for it.
+ (while (re-search-forward "^\\* Menu:" nil t)
+ (let (beg nodename end)
+ (forward-line 1)
+ (setq beg (point))
+ (search-backward "\n\^_")
+ (search-forward "Node: ")
+ (setq nodename (Info-following-node-name))
+ (search-forward "\n\^_" nil 'move)
+ (beginning-of-line)
+ (setq end (point))
+ (setq nodes (cons (list nodename other beg end) nodes))))))
+ (setq others (cdr others)))
+ ;; Add to the main menu a menu item for each other node.
+ (re-search-forward "^\\* Menu:")
+ (forward-line 1)
+ (let ((menu-items '("top"))
+ (nodes nodes)
+ (case-fold-search t)
+ (end (save-excursion (search-forward "\^_" nil t) (point))))
+ (while nodes
+ (let ((nodename (car (car nodes))))
+ (save-excursion
+ (or (member (downcase nodename) menu-items)
+ (re-search-forward (concat "^\\* "
+ (regexp-quote nodename)
+ "::")
+ end t)
+ (progn
+ (insert "* " nodename "::" "\n")
+ (setq menu-items (cons nodename menu-items))))))
+ (setq nodes (cdr nodes))))
+ ;; Now take each node of each of the other buffers
+ ;; and merge it into the main buffer.
+ (while nodes
+ (let ((nodename (car (car nodes))))
+ (goto-char (point-min))
+ ;; Find the like-named node in the main buffer.
+ (if (re-search-forward (concat "\n\^_.*\n.*Node: "
+ (regexp-quote nodename)
+ "[,\n\t]")
+ nil t)
+ (progn
+ (search-forward "\n\^_" nil 'move)
+ (beginning-of-line)
+ (insert "\n"))
+ ;; If none exists, add one.
+ (goto-char (point-max))
+ (insert "\^_\nFile: dir\tNode: " nodename "\n\n* Menu:\n\n"))
+ ;; Merge the text from the other buffer's menu
+ ;; into the menu in the like-named node in the main buffer.
+ (apply 'insert-buffer-substring (cdr (car nodes))))
+ (setq nodes (cdr nodes)))
+ ;; Kill all the buffers we just made.
+ (while buffers
+ (kill-buffer (car buffers))
+ (setq buffers (cdr buffers)))
+ (message "Composing main Info directory...done"))
+ (setq Info-dir-contents (buffer-string)))
+ (setq default-directory Info-dir-contents-directory))
+
+(defun Info-read-subfile (nodepos)
+ (set-buffer (marker-buffer Info-tag-table-marker))
+ (goto-char (point-min))
+ (search-forward "\n\^_")
+ (let (lastfilepos
+ lastfilename)
+ (forward-line 2)
+ (catch 'foo
+ (while (not (looking-at "\^_"))
+ (if (not (eolp))
+ (let ((beg (point))
+ thisfilepos thisfilename)
+ (search-forward ": ")
+ (setq thisfilename (buffer-substring beg (- (point) 2)))
+ (setq thisfilepos (read (current-buffer)))
+ ;; read in version 19 stops at the end of number.
+ ;; Advance to the next line.
+ (forward-line 1)
+ (if (> thisfilepos nodepos)
+ (throw 'foo t))
+ (setq lastfilename thisfilename)
+ (setq lastfilepos thisfilepos))
+ (forward-line 1))))
+ (set-buffer (get-buffer "*info*"))
+ (or (equal Info-current-subfile lastfilename)
+ (let ((buffer-read-only nil))
+ (setq buffer-file-name nil)
+ (widen)
+ (erase-buffer)
+ (info-insert-file-contents lastfilename)
+ (set-buffer-modified-p nil)
+ (setq Info-current-subfile lastfilename)))
+ (goto-char (point-min))
+ (search-forward "\n\^_")
+ (+ (- nodepos lastfilepos) (point))))
+
+;; Select the info node that point is in.
+(defun Info-select-node ()
+ (save-excursion
+ ;; Find beginning of node.
+ (search-backward "\n\^_")
+ (forward-line 2)
+ ;; Get nodename spelled as it is in the node.
+ (re-search-forward "Node:[ \t]*")
+ (setq Info-current-node
+ (buffer-substring-no-properties (point)
+ (progn
+ (skip-chars-forward "^,\t\n")
+ (point))))
+ (Info-set-mode-line)
+ ;; Find the end of it, and narrow.
+ (beginning-of-line)
+ (let (active-expression)
+ (narrow-to-region (point)
+ (if (re-search-forward "\n[\^_\f]" nil t)
+ (prog1
+ (1- (point))
+ (if (looking-at "[\n\^_\f]*execute: ")
+ (progn
+ (goto-char (match-end 0))
+ (setq active-expression
+ (read (current-buffer))))))
+ (point-max)))
+ (if Info-enable-active-nodes (eval active-expression))
+ (if Info-fontify (Info-fontify-node))
+ (run-hooks 'Info-selection-hook))))
+
+(defun Info-set-mode-line ()
+ (setq mode-line-buffer-identification
+ (concat
+ "Info: ("
+ (if Info-current-file
+ (file-name-nondirectory Info-current-file)
+ "")
+ ")"
+ (or Info-current-node ""))))
+
+;; Go to an info node specified with a filename-and-nodename string
+;; of the sort that is found in pointers in nodes.
+
+(defun Info-goto-node (nodename)
+ "Go to info node named NAME. Give just NODENAME or (FILENAME)NODENAME."
+ (interactive (list (Info-read-node-name "Goto node: ")))
+ (let (filename)
+ (string-match "\\s *\\((\\s *\\([^\t)]*\\)\\s *)\\s *\\|\\)\\(.*\\)"
+ nodename)
+ (setq filename (if (= (match-beginning 1) (match-end 1))
+ ""
+ (substring nodename (match-beginning 2) (match-end 2)))
+ nodename (substring nodename (match-beginning 3) (match-end 3)))
+ (let ((trim (string-match "\\s *\\'" filename)))
+ (if trim (setq filename (substring filename 0 trim))))
+ (let ((trim (string-match "\\s *\\'" nodename)))
+ (if trim (setq nodename (substring nodename 0 trim))))
+ (if transient-mark-mode (deactivate-mark))
+ (Info-find-node (if (equal filename "") nil filename)
+ (if (equal nodename "") "Top" nodename))))
+
+;; This function is used as the "completion table" while reading a node name.
+;; It does completion using the alist in completion-table
+;; unless STRING starts with an open-paren.
+(defun Info-read-node-name-1 (string predicate code)
+ (let ((no-completion (and (> (length string) 0) (eq (aref string 0) ?\())))
+ (cond ((eq code nil)
+ (if no-completion
+ string
+ (try-completion string completion-table predicate)))
+ ((eq code t)
+ (if no-completion
+ nil
+ (all-completions string completion-table predicate)))
+ ((eq code 'lambda)
+ (if no-completion
+ t
+ (assoc string completion-table))))))
+
+(defun Info-read-node-name (prompt &optional default)
+ (let* ((completion-ignore-case t)
+ (completion-table (Info-build-node-completions))
+ (nodename (completing-read prompt 'Info-read-node-name-1)))
+ (if (equal nodename "")
+ (or default
+ (Info-read-node-name prompt))
+ nodename)))
+
+(defun Info-build-node-completions ()
+ (or Info-current-file-completions
+ (let ((compl nil))
+ (save-excursion
+ (save-restriction
+ (if (marker-buffer Info-tag-table-marker)
+ (progn
+ (set-buffer (marker-buffer Info-tag-table-marker))
+ (widen)
+ (goto-char Info-tag-table-marker)
+ (while (re-search-forward "\nNode: \\(.*\\)\177" nil t)
+ (setq compl
+ (cons (list (buffer-substring (match-beginning 1)
+ (match-end 1)))
+ compl))))
+ (widen)
+ (goto-char (point-min))
+ (while (search-forward "\n\^_" nil t)
+ (forward-line 1)
+ (let ((beg (point)))
+ (forward-line 1)
+ (if (re-search-backward "Node: *\\([^,\n]*\\) *[,\n\t]"
+ beg t)
+ (setq compl
+ (cons (list (buffer-substring (match-beginning 1)
+ (match-end 1)))
+ compl))))))))
+ (setq Info-current-file-completions compl))))
+
+(defun Info-restore-point (hl)
+ "If this node has been visited, restore the point value when we left."
+ (while hl
+ (if (and (equal (nth 0 (car hl)) Info-current-file)
+ ;; Use string-equal, not equal, to ignore text props.
+ (string-equal (nth 1 (car hl)) Info-current-node))
+ (progn
+ (goto-char (nth 2 (car hl)))
+ (setq hl nil)) ;terminate the while at next iter
+ (setq hl (cdr hl)))))
+
+(defvar Info-last-search nil
+ "Default regexp for \\<Info-mode-map>\\[Info-search] command to search for.")
+
+(defun Info-search (regexp)
+ "Search for REGEXP, starting from point, and select node it's found in."
+ (interactive "sSearch (regexp): ")
+ (if transient-mark-mode (deactivate-mark))
+ (if (equal regexp "")
+ (setq regexp Info-last-search)
+ (setq Info-last-search regexp))
+ (let ((found ()) current
+ (onode Info-current-node)
+ (ofile Info-current-file)
+ (opoint (point))
+ (osubfile Info-current-subfile))
+ (save-excursion
+ (save-restriction
+ (widen)
+ (if (null Info-current-subfile)
+ (progn (re-search-forward regexp) (setq found (point)))
+ (condition-case err
+ (progn (re-search-forward regexp) (setq found (point)))
+ (search-failed nil)))))
+ (if (not found) ;can only happen in subfile case -- else would have erred
+ (unwind-protect
+ (let ((list ()))
+ (set-buffer (marker-buffer Info-tag-table-marker))
+ (goto-char (point-min))
+ (search-forward "\n\^_\nIndirect:")
+ (save-restriction
+ (narrow-to-region (point)
+ (progn (search-forward "\n\^_")
+ (1- (point))))
+ (goto-char (point-min))
+ (search-forward (concat "\n" osubfile ": "))
+ (beginning-of-line)
+ (while (not (eobp))
+ (re-search-forward "\\(^.*\\): [0-9]+$")
+ (goto-char (+ (match-end 1) 2))
+ (setq list (cons (cons (read (current-buffer))
+ (buffer-substring (match-beginning 1)
+ (match-end 1)))
+ list))
+ (goto-char (1+ (match-end 0))))
+ (setq list (nreverse list)
+ current (car (car list))
+ list (cdr list)))
+ (while list
+ (message "Searching subfile %s..." (cdr (car list)))
+ (Info-read-subfile (car (car list)))
+ (setq list (cdr list))
+;; (goto-char (point-min))
+ (if (re-search-forward regexp nil t)
+ (setq found (point) list ())))
+ (if found
+ (message "")
+ (signal 'search-failed (list regexp))))
+ (if (not found)
+ (progn (Info-read-subfile opoint)
+ (goto-char opoint)
+ (Info-select-node)))))
+ (widen)
+ (goto-char found)
+ (Info-select-node)
+ ;; Use string-equal, not equal, to ignore text props.
+ (or (and (string-equal onode Info-current-node)
+ (equal ofile Info-current-file))
+ (setq Info-history (cons (list ofile onode opoint)
+ Info-history)))))
+
+;; Extract the value of the node-pointer named NAME.
+;; If there is none, use ERRORNAME in the error message;
+;; if ERRORNAME is nil, just return nil.
+(defun Info-extract-pointer (name &optional errorname)
+ (save-excursion
+ (goto-char (point-min))
+ (forward-line 1)
+ (if (re-search-backward (concat name ":") nil t)
+ (progn
+ (goto-char (match-end 0))
+ (Info-following-node-name))
+ (if (eq errorname t)
+ nil
+ (error "Node has no %s" (capitalize (or errorname name)))))))
+
+;; Return the node name in the buffer following point.
+;; ALLOWEDCHARS, if non-nil, goes within [...] to make a regexp
+;; saying which chas may appear in the node name.
+(defun Info-following-node-name (&optional allowedchars)
+ (skip-chars-forward " \t")
+ (buffer-substring-no-properties
+ (point)
+ (progn
+ (while (looking-at (concat "[" (or allowedchars "^,\t\n") "]"))
+ (skip-chars-forward (concat (or allowedchars "^,\t\n") "("))
+ (if (looking-at "(")
+ (skip-chars-forward "^)")))
+ (skip-chars-backward " ")
+ (point))))
+
+(defun Info-next ()
+ "Go to the next node of this node."
+ (interactive)
+ (Info-goto-node (Info-extract-pointer "next")))
+
+(defun Info-prev ()
+ "Go to the previous node of this node."
+ (interactive)
+ (Info-goto-node (Info-extract-pointer "prev[ious]*" "previous")))
+
+(defun Info-up ()
+ "Go to the superior node of this node."
+ (interactive)
+ (Info-goto-node (Info-extract-pointer "up"))
+ (Info-restore-point Info-history))
+
+(defun Info-last ()
+ "Go back to the last node visited."
+ (interactive)
+ (or Info-history
+ (error "This is the first Info node you looked at"))
+ (let (filename nodename opoint)
+ (setq filename (car (car Info-history)))
+ (setq nodename (car (cdr (car Info-history))))
+ (setq opoint (car (cdr (cdr (car Info-history)))))
+ (setq Info-history (cdr Info-history))
+ (Info-find-node filename nodename)
+ (setq Info-history (cdr Info-history))
+ (goto-char opoint)))
+
+(defun Info-directory ()
+ "Go to the Info directory node."
+ (interactive)
+ (Info-find-node "dir" "top"))
+
+(defun Info-follow-reference (footnotename)
+ "Follow cross reference named NAME to the node it refers to.
+NAME may be an abbreviation of the reference name."
+ (interactive
+ (let ((completion-ignore-case t)
+ completions default alt-default (start-point (point)) str i bol eol)
+ (save-excursion
+ ;; Store end and beginning of line.
+ (end-of-line)
+ (setq eol (point))
+ (beginning-of-line)
+ (setq bol (point))
+
+ (goto-char (point-min))
+ (while (re-search-forward "\\*note[ \n\t]*\\([^:]*\\):" nil t)
+ (setq str (buffer-substring
+ (match-beginning 1)
+ (1- (point))))
+ ;; See if this one should be the default.
+ (and (null default)
+ (<= (match-beginning 0) start-point)
+ (<= start-point (point))
+ (setq default t))
+ ;; See if this one should be the alternate default.
+ (and (null alt-default)
+ (and (<= bol (match-beginning 0))
+ (<= (point) eol))
+ (setq alt-default t))
+ (setq i 0)
+ (while (setq i (string-match "[ \n\t]+" str i))
+ (setq str (concat (substring str 0 i) " "
+ (substring str (match-end 0))))
+ (setq i (1+ i)))
+ ;; Record as a completion and perhaps as default.
+ (if (eq default t) (setq default str))
+ (if (eq alt-default t) (setq alt-default str))
+ (setq completions
+ (cons (cons str nil)
+ completions))))
+ ;; If no good default was found, try an alternate.
+ (or default
+ (setq default alt-default))
+ ;; If only one cross-reference found, then make it default.
+ (if (eq (length completions) 1)
+ (setq default (car (car completions))))
+ (if completions
+ (let ((input (completing-read (if default
+ (concat "Follow reference named: ("
+ default ") ")
+ "Follow reference named: ")
+ completions nil t)))
+ (list (if (equal input "")
+ default input)))
+ (error "No cross-references in this node"))))
+ (let (target beg i (str (concat "\\*note " (regexp-quote footnotename))))
+ (while (setq i (string-match " " str i))
+ (setq str (concat (substring str 0 i) "[ \t\n]+" (substring str (1+ i))))
+ (setq i (+ i 6)))
+ (save-excursion
+ (goto-char (point-min))
+ (or (re-search-forward str nil t)
+ (error "No cross-reference named %s" footnotename))
+ (goto-char (+ (match-beginning 0) 5))
+ (setq target
+ (Info-extract-menu-node-name "Bad format cross reference" t)))
+ (while (setq i (string-match "[ \t\n]+" target i))
+ (setq target (concat (substring target 0 i) " "
+ (substring target (match-end 0))))
+ (setq i (+ i 1)))
+ (Info-goto-node target)))
+
+(defun Info-extract-menu-node-name (&optional errmessage multi-line)
+ (skip-chars-forward " \t\n")
+ (let ((beg (point))
+ str i)
+ (skip-chars-forward "^:")
+ (forward-char 1)
+ (setq str
+ (if (looking-at ":")
+ (buffer-substring-no-properties beg (1- (point)))
+ (skip-chars-forward " \t\n")
+ (Info-following-node-name (if multi-line "^.,\t" "^.,\t\n"))))
+ (while (setq i (string-match "\n" str i))
+ (aset str i ?\ ))
+ ;; Collapse multiple spaces.
+ (while (string-match " +" str)
+ (setq str (replace-match " " t t str)))
+ str))
+
+;; No one calls this.
+;;(defun Info-menu-item-sequence (list)
+;; (while list
+;; (Info-menu (car list))
+;; (setq list (cdr list))))
+
+(defun Info-complete-menu-item (string predicate action)
+ (let ((case-fold-search t))
+ (cond ((eq action nil)
+ (let (completions
+ (pattern (concat "\n\\* \\("
+ (regexp-quote string)
+ "[^:\t\n]*\\):")))
+ (save-excursion
+ (set-buffer Info-complete-menu-buffer)
+ (goto-char (point-min))
+ (search-forward "\n* Menu:")
+ (while (re-search-forward pattern nil t)
+ (setq completions (cons (cons (format "%s"
+ (buffer-substring
+ (match-beginning 1)
+ (match-end 1)))
+ (match-beginning 1))
+ completions))))
+ (try-completion string completions predicate)))
+ ((eq action t)
+ (let (completions
+ (pattern (concat "\n\\* \\("
+ (regexp-quote string)
+ "[^:\t\n]*\\):")))
+ (save-excursion
+ (set-buffer Info-complete-menu-buffer)
+ (goto-char (point-min))
+ (search-forward "\n* Menu:")
+ (while (re-search-forward pattern nil t)
+ (setq completions (cons (cons (format "%s"
+ (buffer-substring
+ (match-beginning 1)
+ (match-end 1)))
+ (match-beginning 1))
+ completions))))
+ (all-completions string completions predicate)))
+ (t
+ (save-excursion
+ (set-buffer Info-complete-menu-buffer)
+ (goto-char (point-min))
+ (search-forward "\n* Menu:")
+ (re-search-forward (concat "\n\\* "
+ (regexp-quote string)
+ ":")
+ nil t))))))
+
+
+(defun Info-menu (menu-item)
+ "Go to node for menu item named (or abbreviated) NAME.
+Completion is allowed, and the menu item point is on is the default."
+ (interactive
+ (let ((completions '())
+ ;; If point is within a menu item, use that item as the default
+ (default nil)
+ (p (point))
+ beg
+ (last nil))
+ (save-excursion
+ (goto-char (point-min))
+ (if (not (search-forward "\n* menu:" nil t))
+ (error "No menu in this node"))
+ (setq beg (point))
+ (and (< (point) p)
+ (save-excursion
+ (goto-char p)
+ (end-of-line)
+ (re-search-backward "\n\\* \\([^:\t\n]*\\):" beg t)
+ (setq default (format "%s" (buffer-substring
+ (match-beginning 1)
+ (match-end 1)))))))
+ (let ((item nil))
+ (while (null item)
+ (setq item (let ((completion-ignore-case t)
+ (Info-complete-menu-buffer (current-buffer)))
+ (completing-read (if default
+ (format "Menu item (default %s): "
+ default)
+ "Menu item: ")
+ 'Info-complete-menu-item nil t)))
+ ;; we rely on the fact that completing-read accepts an input
+ ;; of "" even when the require-match argument is true and ""
+ ;; is not a valid possibility
+ (if (string= item "")
+ (if default
+ (setq item default)
+ ;; ask again
+ (setq item nil))))
+ (list item))))
+ ;; there is a problem here in that if several menu items have the same
+ ;; name you can only go to the node of the first with this command.
+ (Info-goto-node (Info-extract-menu-item menu-item)))
+
+(defun Info-extract-menu-item (menu-item)
+ (setq menu-item (regexp-quote menu-item))
+ (save-excursion
+ (goto-char (point-min))
+ (or (search-forward "\n* menu:" nil t)
+ (error "No menu in this node"))
+ (or (re-search-forward (concat "\n\\* " menu-item ":") nil t)
+ (re-search-forward (concat "\n\\* " menu-item) nil t)
+ (error "No such item in menu"))
+ (beginning-of-line)
+ (forward-char 2)
+ (Info-extract-menu-node-name)))
+
+;; If COUNT is nil, use the last item in the menu.
+(defun Info-extract-menu-counting (count)
+ (save-excursion
+ (goto-char (point-min))
+ (or (search-forward "\n* menu:" nil t)
+ (error "No menu in this node"))
+ (if count
+ (or (search-forward "\n* " nil t count)
+ (error "Too few items in menu"))
+ (while (search-forward "\n* " nil t)
+ nil))
+ (Info-extract-menu-node-name)))
+
+(defun Info-nth-menu-item ()
+ "Go to the node of the Nth menu item.
+N is the digit argument used to invoke this command."
+ (interactive)
+ (Info-goto-node
+ (Info-extract-menu-counting
+ (- (aref (this-command-keys) (1- (length (this-command-keys)))) ?0))))
+
+(defun Info-top-node ()
+ "Go to the Top node of this file."
+ (interactive)
+ (Info-goto-node "Top"))
+
+(defun Info-final-node ()
+ "Go to the final node in this file."
+ (interactive)
+ (Info-goto-node "Top")
+ (let (Info-history)
+ ;; Go to the last node in the menu of Top.
+ (Info-goto-node (Info-extract-menu-counting nil))
+ ;; If the last node in the menu is not last in pointer structure,
+ ;; move forward until we can't go any farther.
+ (while (Info-forward-node t t) nil)
+ ;; Then keep moving down to last subnode, unless we reach an index.
+ (while (and (not (string-match "\\<index\\>" Info-current-node))
+ (save-excursion (search-forward "\n* Menu:" nil t)))
+ (Info-goto-node (Info-extract-menu-counting nil)))))
+
+(defun Info-forward-node (&optional not-down no-error)
+ "Go forward one node, considering all nodes as forming one sequence."
+ (interactive)
+ (goto-char (point-min))
+ (forward-line 1)
+ ;; three possibilities, in order of priority:
+ ;; 1. next node is in a menu in this node (but not in an index)
+ ;; 2. next node is next at same level
+ ;; 3. next node is up and next
+ (cond ((and (not not-down)
+ (save-excursion (search-forward "\n* menu:" nil t))
+ (not (string-match "\\<index\\>" Info-current-node)))
+ (Info-goto-node (Info-extract-menu-counting 1))
+ t)
+ ((save-excursion (search-backward "next:" nil t))
+ (Info-next)
+ t)
+ ((and (save-excursion (search-backward "up:" nil t))
+ ;; Use string-equal, not equal, to ignore text props.
+ (not (string-equal (downcase (Info-extract-pointer "up"))
+ "top")))
+ (let ((old-node Info-current-node))
+ (Info-up)
+ (let (Info-history success)
+ (unwind-protect
+ (setq success (Info-forward-node t no-error))
+ (or success (Info-goto-node old-node))))))
+ (no-error nil)
+ (t (error "No pointer forward from this node"))))
+
+(defun Info-backward-node ()
+ "Go backward one node, considering all nodes as forming one sequence."
+ (interactive)
+ (let ((prevnode (Info-extract-pointer "prev[ious]*" t))
+ (upnode (Info-extract-pointer "up" t)))
+ (cond ((and upnode (string-match "(" upnode))
+ (error "First node in file"))
+ ((and upnode (or (null prevnode)
+ ;; Use string-equal, not equal,
+ ;; to ignore text properties.
+ (string-equal (downcase prevnode)
+ (downcase upnode))))
+ (Info-up))
+ (prevnode
+ ;; If we move back at the same level,
+ ;; go down to find the last subnode*.
+ (Info-prev)
+ (let (Info-history)
+ (while (and (not (string-match "\\<index\\>" Info-current-node))
+ (save-excursion (search-forward "\n* Menu:" nil t)))
+ (Info-goto-node (Info-extract-menu-counting nil)))))
+ (t
+ (error "No pointer backward from this node")))))
+
+(defun Info-exit ()
+ "Exit Info by selecting some other buffer."
+ (interactive)
+ (if Info-standalone
+ (save-buffers-kill-emacs)
+ (switch-to-buffer (prog1 (other-buffer (current-buffer))
+ (bury-buffer (current-buffer))))))
+
+(defun Info-next-menu-item ()
+ (interactive)
+ (save-excursion
+ (forward-line -1)
+ (search-forward "\n* menu:" nil t)
+ (or (search-forward "\n* " nil t)
+ (error "No more items in menu"))
+ (Info-goto-node (Info-extract-menu-node-name))))
+
+(defun Info-last-menu-item ()
+ (interactive)
+ (save-excursion
+ (forward-line 1)
+ (let ((beg (save-excursion
+ (and (search-backward "\n* menu:" nil t)
+ (point)))))
+ (or (and beg (search-backward "\n* " beg t))
+ (error "No previous items in menu")))
+ (Info-goto-node (save-excursion
+ (goto-char (match-end 0))
+ (Info-extract-menu-node-name)))))
+
+(defmacro Info-no-error (&rest body)
+ (list 'condition-case nil (cons 'progn (append body '(t))) '(error nil)))
+
+(defun Info-next-preorder ()
+ "Go to the next subnode or the next node, or go up a level."
+ (interactive)
+ (cond ((Info-no-error (Info-next-menu-item)))
+ ((Info-no-error (Info-next)))
+ ((Info-no-error (Info-up))
+ ;; Since we have already gone thru all the items in this menu,
+ ;; go up to the end of this node.
+ (goto-char (point-max))
+ ;; Since logically we are done with the node with that menu,
+ ;; move on from it.
+ (Info-next-preorder))
+ (t
+ (error "No more nodes"))))
+
+(defun Info-last-preorder ()
+ "Go to the last node, popping up a level if there is none."
+ (interactive)
+ (cond ((Info-no-error
+ (Info-last-menu-item)
+ ;; If we go down a menu item, go to the end of the node
+ ;; so we can scroll back through it.
+ (goto-char (point-max)))
+ ;; Keep going down, as long as there are nested menu nodes.
+ (while (Info-no-error
+ (Info-last-menu-item)
+ ;; If we go down a menu item, go to the end of the node
+ ;; so we can scroll back through it.
+ (goto-char (point-max))))
+ (recenter -1))
+ ((Info-no-error (Info-prev))
+ (goto-char (point-max))
+ (while (Info-no-error
+ (Info-last-menu-item)
+ ;; If we go down a menu item, go to the end of the node
+ ;; so we can scroll back through it.
+ (goto-char (point-max))))
+ (recenter -1))
+ ((Info-no-error (Info-up))
+ (goto-char (point-min))
+ (or (search-forward "\n* Menu:" nil t)
+ (goto-char (point-max))))
+ (t (error "No previous nodes"))))
+
+(defun Info-scroll-up ()
+ "Scroll one screenful forward in Info, considering all nodes as one sequence.
+Once you scroll far enough in a node that its menu appears on the screen,
+the next scroll moves into its first subnode. When you scroll past
+the end of a node, that goes to the next node or back up to the parent node."
+ (interactive)
+ (if (or (< (window-start) (point-min))
+ (> (window-start) (point-max)))
+ (set-window-start (selected-window) (point)))
+ (let ((virtual-end (save-excursion
+ (goto-char (point-min))
+ (if (search-forward "\n* Menu:" nil t)
+ (point)
+ (point-max)))))
+ (if (or (< virtual-end (window-start))
+ (pos-visible-in-window-p virtual-end))
+ (Info-next-preorder)
+ (scroll-up))))
+
+(defun Info-scroll-down ()
+ "Scroll one screenful back in Info, considering all nodes as one sequence.
+Within the menu of a node, this goes to its last subnode.
+When you scroll past the beginning of a node, that goes to the
+previous node or back up to the parent node."
+ (interactive)
+ (if (or (< (window-start) (point-min))
+ (> (window-start) (point-max)))
+ (set-window-start (selected-window) (point)))
+ (let* ((current-point (point))
+ (virtual-end (save-excursion
+ (beginning-of-line)
+ (setq current-point (point))
+ (goto-char (point-min))
+ (search-forward "\n* Menu:"
+ current-point
+ t))))
+ (if (or virtual-end (pos-visible-in-window-p (point-min)))
+ (Info-last-preorder)
+ (scroll-down))))
+
+(defun Info-next-reference (&optional recur)
+ "Move cursor to the next cross-reference or menu item in the node."
+ (interactive)
+ (let ((pat "\\*note[ \n\t]*\\([^:]*\\):\\|^\\* .*:")
+ (old-pt (point)))
+ (or (eobp) (forward-char 1))
+ (or (re-search-forward pat nil t)
+ (progn
+ (goto-char (point-min))
+ (or (re-search-forward pat nil t)
+ (progn
+ (goto-char old-pt)
+ (error "No cross references in this node")))))
+ (goto-char (match-beginning 0))
+ (if (looking-at "\\* Menu:")
+ (if recur
+ (error "No cross references in this node")
+ (Info-next-reference t)))))
+
+(defun Info-prev-reference (&optional recur)
+ "Move cursor to the previous cross-reference or menu item in the node."
+ (interactive)
+ (let ((pat "\\*note[ \n\t]*\\([^:]*\\):\\|^\\* .*:")
+ (old-pt (point)))
+ (or (re-search-backward pat nil t)
+ (progn
+ (goto-char (point-max))
+ (or (re-search-backward pat nil t)
+ (progn
+ (goto-char old-pt)
+ (error "No cross references in this node")))))
+ (goto-char (match-beginning 0))
+ (if (looking-at "\\* Menu:")
+ (if recur
+ (error "No cross references in this node")
+ (Info-prev-reference t)))))
+
+(defun Info-index (topic)
+ "Look up a string in the index for this file.
+The index is defined as the first node in the top-level menu whose
+name contains the word \"Index\", plus any immediately following
+nodes whose names also contain the word \"Index\".
+If there are no exact matches to the specified topic, this chooses
+the first match which is a case-insensitive substring of a topic.
+Use the `,' command to see the other matches.
+Give a blank topic name to go to the Index node itself."
+ (interactive "sIndex topic: ")
+ (let ((orignode Info-current-node)
+ (rnode nil)
+ (pattern (format "\n\\* \\([^\n:]*%s[^\n:]*\\):[ \t]*\\([^.\n]*\\)\\.[ \t]*\\([0-9]*\\)"
+ (regexp-quote topic)))
+ node)
+ (Info-goto-node "Top")
+ (or (search-forward "\n* menu:" nil t)
+ (error "No index"))
+ (or (re-search-forward "\n\\* \\(.*\\<Index\\>\\)" nil t)
+ (error "No index"))
+ (goto-char (match-beginning 1))
+ ;; Here, and subsequently in this function,
+ ;; we bind Info-history to nil for internal node-switches
+ ;; so that we don't put junk in the history.
+ ;; In the first Info-goto-node call, above, we do update the history
+ ;; because that is what the user's previous node choice into it.
+ (let ((Info-history nil))
+ (Info-goto-node (Info-extract-menu-node-name)))
+ (or (equal topic "")
+ (let ((matches nil)
+ (exact nil)
+ (Info-history nil)
+ found)
+ (while
+ (progn
+ (goto-char (point-min))
+ (while (re-search-forward pattern nil t)
+ (setq matches
+ (cons (list (buffer-substring (match-beginning 1)
+ (match-end 1))
+ (buffer-substring (match-beginning 2)
+ (match-end 2))
+ Info-current-node
+ (string-to-int (concat "0"
+ (buffer-substring
+ (match-beginning 3)
+ (match-end 3)))))
+ matches)))
+ (and (setq node (Info-extract-pointer "next" t))
+ (string-match "\\<Index\\>" node)))
+ (Info-goto-node node))
+ (or matches
+ (progn
+ (Info-goto-node orignode)
+ (error "No `%s' in index" topic)))
+ ;; Here it is a feature that assoc is case-sensitive.
+ (while (setq found (assoc topic matches))
+ (setq exact (cons found exact)
+ matches (delq found matches)))
+ (setq Info-index-alternatives (nconc exact (nreverse matches)))
+ (Info-index-next 0)))))
+
+(defun Info-index-next (num)
+ "Go to the next matching index item from the last `i' command."
+ (interactive "p")
+ (or Info-index-alternatives
+ (error "No previous `i' command in this file"))
+ (while (< num 0)
+ (setq num (+ num (length Info-index-alternatives))))
+ (while (> num 0)
+ (setq Info-index-alternatives
+ (nconc (cdr Info-index-alternatives)
+ (list (car Info-index-alternatives)))
+ num (1- num)))
+ (Info-goto-node (nth 1 (car Info-index-alternatives)))
+ (if (> (nth 3 (car Info-index-alternatives)) 0)
+ (forward-line (nth 3 (car Info-index-alternatives)))
+ (forward-line 3) ; don't search in headers
+ (let ((name (car (car Info-index-alternatives))))
+ (Info-find-index-name name)))
+ (message "Found `%s' in %s. %s"
+ (car (car Info-index-alternatives))
+ (nth 2 (car Info-index-alternatives))
+ (if (cdr Info-index-alternatives)
+ "(Press `,' for more)"
+ "(Only match)")))
+
+(defun Info-find-index-name (name)
+ "Move point to the place within the current node where NAME is defined."
+ (if (or (re-search-forward (format
+ "[a-zA-Z]+: %s\\( \\|$\\)"
+ (regexp-quote name)) nil t)
+ (search-forward (format "`%s'" name) nil t)
+ (and (string-match "\\`.*\\( (.*)\\)\\'" name)
+ (search-forward
+ (format "`%s'" (substring name 0 (match-beginning 1)))
+ nil t))
+ (search-forward name nil t))
+ (beginning-of-line)
+ (goto-char (point-min))))
+
+(defun Info-undefined ()
+ "Make command be undefined in Info."
+ (interactive)
+ (ding))
+
+(defun Info-help ()
+ "Enter the Info tutorial."
+ (interactive)
+ (delete-other-windows)
+ (Info-find-node "info"
+ (if (< (window-height) 23)
+ "Help-Small-Screen"
+ "Help")))
+
+(defun Info-summary ()
+ "Display a brief summary of all Info commands."
+ (interactive)
+ (save-window-excursion
+ (switch-to-buffer "*Help*")
+ (erase-buffer)
+ (insert (documentation 'Info-mode))
+ (help-mode)
+ (goto-char (point-min))
+ (let (ch flag)
+ (while (progn (setq flag (not (pos-visible-in-window-p (point-max))))
+ (message (if flag "Type Space to see more"
+ "Type Space to return to Info"))
+ (if (not (eq ?\ (setq ch (read-event))))
+ (progn (setq unread-command-events (list ch)) nil)
+ flag))
+ (scroll-up)))
+ (bury-buffer "*Help*")))
+
+(defun Info-get-token (pos start all &optional errorstring)
+ "Return the token around POS,
+POS must be somewhere inside the token
+START is a regular expression which will match the
+ beginning of the tokens delimited string
+ALL is a regular expression with a single
+ parenthesized subpattern which is the token to be
+ returned. E.g. '{\(.*\)}' would return any string
+ enclosed in braces around POS.
+SIG optional fourth argument, controls action on no match
+ nil: return nil
+ t: beep
+ a string: signal an error, using that string."
+ (save-excursion
+ (goto-char pos)
+ (re-search-backward start (max (point-min) (- pos 200)) 'yes)
+ (let (found)
+ (while (and (re-search-forward all (min (point-max) (+ pos 200)) 'yes)
+ (not (setq found (and (<= (match-beginning 0) pos)
+ (> (match-end 0) pos))))))
+ (if (and found (<= (match-beginning 0) pos)
+ (> (match-end 0) pos))
+ (buffer-substring (match-beginning 1) (match-end 1))
+ (cond ((null errorstring)
+ nil)
+ ((eq errorstring t)
+ (beep)
+ nil)
+ (t
+ (error "No %s around position %d" errorstring pos)))))))
+
+(defun Info-mouse-follow-nearest-node (click)
+ "\\<Info-mode-map>Follow a node reference near point.
+Like \\[Info-menu], \\[Info-follow-reference], \\[Info-next], \\[Info-prev] or \\[Info-up] command, depending on where you click.
+At end of the node's text, moves to the next node, or up if none."
+ (interactive "e")
+ (let* ((start (event-start click))
+ (window (car start))
+ (pos (car (cdr start))))
+ (select-window window)
+ (goto-char pos))
+ (and (not (Info-try-follow-nearest-node))
+ (save-excursion (forward-line 1) (eobp))
+ (Info-next-preorder)))
+
+(defun Info-follow-nearest-node ()
+ "\\<Info-mode-map>Follow a node reference near point.
+Like \\[Info-menu], \\[Info-follow-reference], \\[Info-next], \\[Info-prev] or \\[Info-up] command, depending on where point is.
+If no reference to follow, moves to the next node, or up if none."
+ (interactive)
+ (or (Info-try-follow-nearest-node)
+ (Info-next-preorder)))
+
+;; Common subroutine.
+(defun Info-try-follow-nearest-node ()
+ "Follow a node reference near point. Return non-nil if successful."
+ (let (node)
+ (cond
+ ((setq node (Info-get-token (point) "\\*note[ \n]"
+ "\\*note[ \n]\\([^:]*\\):"))
+ (Info-follow-reference node))
+ ((setq node (Info-get-token (point) "\\* " "\\* \\([^:]*\\)::"))
+ (Info-goto-node node))
+ ((setq node (Info-get-token (point) "\\* " "\\* \\([^:]*\\):"))
+ (Info-menu node))
+ ((setq node (Info-get-token (point) "Up: " "Up: \\([^,\n\t]*\\)"))
+ (Info-goto-node node))
+ ((setq node (Info-get-token (point) "Next: " "Next: \\([^,\n\t]*\\)"))
+ (Info-goto-node node))
+ ((setq node (Info-get-token (point) "File: " "File: \\([^,\n\t]*\\)"))
+ (Info-goto-node "Top"))
+ ((setq node (Info-get-token (point) "Prev: " "Prev: \\([^,\n\t]*\\)"))
+ (Info-goto-node node)))
+ node))
+
+(defvar Info-mode-map nil
+ "Keymap containing Info commands.")
+(if Info-mode-map
+ nil
+ (setq Info-mode-map (make-keymap))
+ (suppress-keymap Info-mode-map)
+ (define-key Info-mode-map "." 'beginning-of-buffer)
+ (define-key Info-mode-map " " 'Info-scroll-up)
+ (define-key Info-mode-map "\C-m" 'Info-follow-nearest-node)
+ (define-key Info-mode-map "\t" 'Info-next-reference)
+ (define-key Info-mode-map "\e\t" 'Info-prev-reference)
+ (define-key Info-mode-map "1" 'Info-nth-menu-item)
+ (define-key Info-mode-map "2" 'Info-nth-menu-item)
+ (define-key Info-mode-map "3" 'Info-nth-menu-item)
+ (define-key Info-mode-map "4" 'Info-nth-menu-item)
+ (define-key Info-mode-map "5" 'Info-nth-menu-item)
+ (define-key Info-mode-map "6" 'Info-nth-menu-item)
+ (define-key Info-mode-map "7" 'Info-nth-menu-item)
+ (define-key Info-mode-map "8" 'Info-nth-menu-item)
+ (define-key Info-mode-map "9" 'Info-nth-menu-item)
+ (define-key Info-mode-map "0" 'undefined)
+ (define-key Info-mode-map "?" 'Info-summary)
+ (define-key Info-mode-map "]" 'Info-forward-node)
+ (define-key Info-mode-map "[" 'Info-backward-node)
+ (define-key Info-mode-map "<" 'Info-top-node)
+ (define-key Info-mode-map ">" 'Info-final-node)
+ (define-key Info-mode-map "b" 'beginning-of-buffer)
+ (define-key Info-mode-map "d" 'Info-directory)
+ (define-key Info-mode-map "e" 'Info-edit)
+ (define-key Info-mode-map "f" 'Info-follow-reference)
+ (define-key Info-mode-map "g" 'Info-goto-node)
+ (define-key Info-mode-map "h" 'Info-help)
+ (define-key Info-mode-map "i" 'Info-index)
+ (define-key Info-mode-map "l" 'Info-last)
+ (define-key Info-mode-map "m" 'Info-menu)
+ (define-key Info-mode-map "n" 'Info-next)
+ (define-key Info-mode-map "p" 'Info-prev)
+ (define-key Info-mode-map "q" 'Info-exit)
+ (define-key Info-mode-map "s" 'Info-search)
+ ;; For consistency with Rmail.
+ (define-key Info-mode-map "\M-s" 'Info-search)
+ (define-key Info-mode-map "t" 'Info-top-node)
+ (define-key Info-mode-map "u" 'Info-up)
+ (define-key Info-mode-map "," 'Info-index-next)
+ (define-key Info-mode-map "\177" 'Info-scroll-down)
+ (define-key Info-mode-map [mouse-2] 'Info-mouse-follow-nearest-node)
+ )
+
+;; Info mode is suitable only for specially formatted data.
+(put 'info-mode 'mode-class 'special)
+
+(defun Info-mode ()
+ "\\<Info-mode-map>
+Info mode provides commands for browsing through the Info documentation tree.
+Documentation in Info is divided into \"nodes\", each of which discusses
+one topic and contains references to other nodes which discuss related
+topics. Info has commands to follow the references and show you other nodes.
+
+\\[Info-help] Invoke the Info tutorial.
+
+Selecting other nodes:
+\\[Info-mouse-follow-nearest-node]
+ Follow a node reference you click on.
+ This works with menu items, cross references, and
+ the \"next\", \"previous\" and \"up\", depending on where you click.
+\\[Info-next] Move to the \"next\" node of this node.
+\\[Info-prev] Move to the \"previous\" node of this node.
+\\[Info-up] Move \"up\" from this node.
+\\[Info-menu] Pick menu item specified by name (or abbreviation).
+ Picking a menu item causes another node to be selected.
+\\[Info-directory] Go to the Info directory node.
+\\[Info-follow-reference] Follow a cross reference. Reads name of reference.
+\\[Info-last] Move to the last node you were at.
+\\[Info-index] Look up a topic in this file's Index and move to that node.
+\\[Info-index-next] (comma) Move to the next match from a previous `i' command.
+
+Moving within a node:
+\\[Info-scroll-up] Normally, scroll forward a full screen. If the end of the buffer is
+already visible, try to go to the next menu entry, or up if there is none.
+\\[Info-scroll-down] Normally, scroll backward. If the beginning of the buffer is
+already visible, try to go to the previous menu entry, or up if there is none.
+\\[beginning-of-buffer] Go to beginning of node.
+
+Advanced commands:
+\\[Info-exit] Quit Info: reselect previously selected buffer.
+\\[Info-edit] Edit contents of selected node.
+1 Pick first item in node's menu.
+2, 3, 4, 5 Pick second ... fifth item in node's menu.
+\\[Info-goto-node] Move to node specified by name.
+ You may include a filename as well, as (FILENAME)NODENAME.
+\\[universal-argument] \\[info] Move to new Info file with completion.
+\\[Info-search] Search through this Info file for specified regexp,
+ and select the node in which the next occurrence is found.
+\\[Info-next-reference] Move cursor to next cross-reference or menu item.
+\\[Info-prev-reference] Move cursor to previous cross-reference or menu item."
+ (kill-all-local-variables)
+ (setq major-mode 'Info-mode)
+ (setq mode-name "Info")
+ (use-local-map Info-mode-map)
+ (set-syntax-table text-mode-syntax-table)
+ (setq local-abbrev-table text-mode-abbrev-table)
+ (setq case-fold-search t)
+ (setq buffer-read-only t)
+ (make-local-variable 'Info-current-file)
+ (make-local-variable 'Info-current-subfile)
+ (make-local-variable 'Info-current-node)
+ (make-local-variable 'Info-tag-table-marker)
+ (make-local-variable 'Info-history)
+ (make-local-variable 'Info-index-alternatives)
+ (if (memq (framep (selected-frame)) '(x pc))
+ (progn
+ (make-face 'info-node)
+ (make-face 'info-menu-5)
+ (make-face 'info-xref)
+ (or (face-differs-from-default-p 'info-node)
+ (if (face-differs-from-default-p 'bold-italic)
+ (copy-face 'bold-italic 'info-node)
+ (copy-face 'bold 'info-node)))
+ (or (face-differs-from-default-p 'info-menu-5)
+ (set-face-underline-p 'info-menu-5 t))
+ (or (face-differs-from-default-p 'info-xref)
+ (copy-face 'bold 'info-xref)))
+ (setq Info-fontify nil))
+ (Info-set-mode-line)
+ (run-hooks 'Info-mode-hook))
+
+(defvar Info-edit-map nil
+ "Local keymap used within `e' command of Info.")
+(if Info-edit-map
+ nil
+ (setq Info-edit-map (nconc (make-sparse-keymap) text-mode-map))
+ (define-key Info-edit-map "\C-c\C-c" 'Info-cease-edit))
+
+;; Info-edit mode is suitable only for specially formatted data.
+(put 'info-edit-mode 'mode-class 'special)
+
+(defun Info-edit-mode ()
+ "Major mode for editing the contents of an Info node.
+Like text mode with the addition of `Info-cease-edit'
+which returns to Info mode for browsing.
+\\{Info-edit-map}"
+ (use-local-map Info-edit-map)
+ (setq major-mode 'Info-edit-mode)
+ (setq mode-name "Info Edit")
+ (kill-local-variable 'mode-line-buffer-identification)
+ (setq buffer-read-only nil)
+ (force-mode-line-update)
+ (buffer-enable-undo (current-buffer))
+ (run-hooks 'Info-edit-mode-hook))
+
+(defun Info-edit ()
+ "Edit the contents of this Info node.
+Allowed only if variable `Info-enable-edit' is non-nil."
+ (interactive)
+ (or Info-enable-edit
+ (error "Editing info nodes is not enabled"))
+ (Info-edit-mode)
+ (message "%s" (substitute-command-keys
+ "Editing: Type \\<Info-edit-map>\\[Info-cease-edit] to return to info")))
+
+(defun Info-cease-edit ()
+ "Finish editing Info node; switch back to Info proper."
+ (interactive)
+ ;; Do this first, so nothing has changed if user C-g's at query.
+ (and (buffer-modified-p)
+ (y-or-n-p "Save the file? ")
+ (save-buffer))
+ (use-local-map Info-mode-map)
+ (setq major-mode 'Info-mode)
+ (setq mode-name "Info")
+ (Info-set-mode-line)
+ (setq buffer-read-only t)
+ (force-mode-line-update)
+ (and (marker-position Info-tag-table-marker)
+ (buffer-modified-p)
+ (message "Tags may have changed. Use Info-tagify if necessary")))
+
+(defvar Info-file-list-for-emacs
+ '("ediff" "forms" "gnus" "info" ("mh" . "mh-e") "sc")
+ "List of Info files that describe Emacs commands.
+An element can be a file name, or a list of the form (PREFIX . FILE)
+where PREFIX is a name prefix and FILE is the file to look in.
+If the element is just a file name, the file name also serves as the prefix.")
+
+(defun Info-find-emacs-command-nodes (command)
+ "Return a list of locations documenting COMMAND.
+The `info-file' property of COMMAND says which Info manual to search.
+If COMMAND has no property, the variable `Info-file-list-for-emacs'
+defines heuristics for which Info manual to try.
+The locations are of the format used in Info-history, i.e.
+\(FILENAME NODENAME BUFFERPOS\)."
+ (let ((where '())
+ (cmd-desc (concat "^\\* " (regexp-quote (symbol-name command))
+ ":\\s *\\(.*\\)\\.$"))
+ (info-file "emacs")) ;default
+ ;; Determine which info file this command is documented in.
+ (if (get command 'info-file)
+ (setq info-file (get command 'info-file))
+ ;; If it doesn't say explicitly, test its name against
+ ;; various prefixes that we know.
+ (let ((file-list Info-file-list-for-emacs))
+ (while file-list
+ (let* ((elt (car file-list))
+ (name (if (consp elt)
+ (car elt)
+ elt))
+ (file (if (consp elt) (cdr elt) elt))
+ (regexp (concat "\\`" (regexp-quote name)
+ "\\(\\'\\|-\\)")))
+ (if (string-match regexp (symbol-name command))
+ (setq info-file file file-list nil))
+ (setq file-list (cdr file-list))))))
+ (save-excursion
+ (condition-case nil
+ (Info-find-node info-file "Command Index")
+ ;; Some manuals may not have a separate Command Index node,
+ ;; so try just Index instead.
+ (error
+ (Info-find-node info-file "Index")))
+ ;; Take the index node off the Info history.
+ (setq Info-history (cdr Info-history))
+ (goto-char (point-max))
+ (while (re-search-backward cmd-desc nil t)
+ (setq where (cons (list Info-current-file
+ (buffer-substring
+ (match-beginning 1)
+ (match-end 1))
+ 0)
+ where)))
+ where)))
+
+;;;###autoload
+(defun Info-goto-emacs-command-node (command)
+ "Go to the Info node in the Emacs manual for command COMMAND.
+The command is found by looking up in Emacs manual's Command Index
+or in another manual found via COMMAND's `info-file' property or
+the variable `Info-file-list-for-emacs'."
+ (interactive "CFind documentation for command: ")
+ (or (commandp command)
+ (signal 'wrong-type-argument (list 'commandp command)))
+ (let ((where (Info-find-emacs-command-nodes command)))
+ (if where
+ (let ((num-matches (length where)))
+ ;; Get Info running, and pop to it in another window.
+ (save-window-excursion
+ (info))
+ (pop-to-buffer "*info*")
+ (Info-find-node (car (car where))
+ (car (cdr (car where))))
+ (if (> num-matches 1)
+ (progn
+ ;; Info-find-node already pushed (car where) onto
+ ;; Info-history. Put the other nodes that were found on
+ ;; the history.
+ (setq Info-history (nconc (cdr where) Info-history))
+ (message "Found %d other entr%s. Use %s to see %s."
+ (1- num-matches)
+ (if (> num-matches 2) "ies" "y")
+ (substitute-command-keys "\\[Info-last]")
+ (if (> num-matches 2) "them" "it")))))
+ (error "Couldn't find documentation for %s" command))))
+
+;;;###autoload
+(defun Info-goto-emacs-key-command-node (key)
+ "Go to the Info node in the Emacs manual the command bound to KEY, a string.
+Interactively, if the binding is execute-extended-command, a command is read.
+The command is found by looking up in Emacs manual's Command Index
+or in another manual found via COMMAND's `info-file' property or
+the variable `Info-file-list-for-emacs'."
+ (interactive "kFind documentation for key:")
+ (let ((command (key-binding key)))
+ (cond ((null command)
+ (message "%s is undefined" (key-description key)))
+ ((and (interactive-p)
+ (eq command 'execute-extended-command))
+ (Info-goto-emacs-command-node
+ (read-command "Find documentation for command: ")))
+ (t
+ (Info-goto-emacs-command-node command)))))
+
+(defvar Info-title-face-alist
+ '((?* bold underline)
+ (?= bold-italic underline)
+ (?- italic underline))
+ "*Alist of face or list of faces to use for pseudo-underlined titles.
+The alist key is the character the title is underlined with (?*, ?= or ?-).")
+
+(defun Info-fontify-node ()
+ (save-excursion
+ (let ((buffer-read-only nil))
+ (goto-char (point-min))
+ (if (looking-at "^File: [^,: \t]+,?[ \t]+")
+ (progn
+ (goto-char (match-end 0))
+ (while
+ (looking-at "[ \t]*[^:, \t\n]+:[ \t]+\\([^:,\t\n]+\\),?")
+ (goto-char (match-end 0))
+ (put-text-property (match-beginning 1) (match-end 1)
+ 'face 'info-xref)
+ (put-text-property (match-beginning 1) (match-end 1)
+ 'mouse-face 'highlight))))
+ (goto-char (point-min))
+ (while (re-search-forward "\n\\([^ \t\n].+\\)\n\\(\\*+\\|=+\\|-+\\)$"
+ nil t)
+ (put-text-property (match-beginning 1) (match-end 1)
+ 'face
+ (cdr (assq (preceding-char) Info-title-face-alist)))
+ (put-text-property (match-end 1) (match-end 2)
+ 'invisible t))
+ (goto-char (point-min))
+ (while (re-search-forward "\\*Note[ \n\t]+\\([^:]*\\):" nil t)
+ (if (= (char-after (1- (match-beginning 0))) ?\") ; hack
+ nil
+ (put-text-property (match-beginning 1) (match-end 1)
+ 'face 'info-xref)
+ (put-text-property (match-beginning 1) (match-end 1)
+ 'mouse-face 'highlight)))
+ (goto-char (point-min))
+ (if (and (search-forward "\n* Menu:" nil t)
+ (not (string-match "\\<Index\\>" Info-current-node))
+ ;; Don't take time to annotate huge menus
+ (< (- (point-max) (point)) Info-fontify-maximum-menu-size))
+ (let ((n 0))
+ (while (re-search-forward "^\\* \\([^:\t\n]*\\):" nil t)
+ (setq n (1+ n))
+ (if (memq n '(5 9)) ; visual aids to help with 1-9 keys
+ (put-text-property (match-beginning 0)
+ (1+ (match-beginning 0))
+ 'face 'info-menu-5))
+ (put-text-property (match-beginning 1) (match-end 1)
+ 'face 'info-node)
+ (put-text-property (match-beginning 1) (match-end 1)
+ 'mouse-face 'highlight))))
+ (set-buffer-modified-p nil))))
+
+(provide 'info)
+
+;;; info.el ends here
diff --git a/contrib/texinfo/emacs/informat.el b/contrib/texinfo/emacs/informat.el
new file mode 100644
index 0000000..0b195b9
--- /dev/null
+++ b/contrib/texinfo/emacs/informat.el
@@ -0,0 +1,429 @@
+;;; informat.el --- info support functions package for Emacs
+
+;; Copyright (C) 1986 Free Software Foundation, Inc.
+
+;; Maintainer: FSF
+;; Keywords: help
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs 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, or (at your option)
+;; any later version.
+
+;; GNU Emacs 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; see the file COPYING. If not, write to the
+;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+;;; Code:
+
+(require 'info)
+
+;;;###autoload
+(defun Info-tagify ()
+ "Create or update Info-file tag table in current buffer."
+ (interactive)
+ ;; Save and restore point and restrictions.
+ ;; save-restrictions would not work
+ ;; because it records the old max relative to the end.
+ ;; We record it relative to the beginning.
+ (message "Tagifying %s ..." (file-name-nondirectory (buffer-file-name)))
+ (let ((omin (point-min))
+ (omax (point-max))
+ (nomax (= (point-max) (1+ (buffer-size))))
+ (opoint (point)))
+ (unwind-protect
+ (progn
+ (widen)
+ (goto-char (point-min))
+ (if (search-forward "\^_\nIndirect:\n" nil t)
+ (message "Cannot tagify split info file")
+ (let ((regexp "Node:[ \t]*\\([^,\n\t]*\\)[,\t\n]")
+ (case-fold-search t)
+ list)
+ (while (search-forward "\n\^_" nil t)
+ ;; We want the 0-origin character position of the ^_.
+ ;; That is the same as the Emacs (1-origin) position
+ ;; of the newline before it.
+ (let ((beg (match-beginning 0)))
+ (forward-line 2)
+ (if (re-search-backward regexp beg t)
+ (setq list
+ (cons (list (buffer-substring-no-properties
+ (match-beginning 1)
+ (match-end 1))
+ beg)
+ list)))))
+ (goto-char (point-max))
+ (forward-line -8)
+ (let ((buffer-read-only nil))
+ (if (search-forward "\^_\nEnd tag table\n" nil t)
+ (let ((end (point)))
+ (search-backward "\nTag table:\n")
+ (beginning-of-line)
+ (delete-region (point) end)))
+ (goto-char (point-max))
+ (insert "\^_\f\nTag table:\n")
+ (move-marker Info-tag-table-marker (point))
+ (setq list (nreverse list))
+ (while list
+ (insert "Node: " (car (car list)) ?\177)
+ (princ (car (cdr (car list))) (current-buffer))
+ (insert ?\n)
+ (setq list (cdr list)))
+ (insert "\^_\nEnd tag table\n")))))
+ (goto-char opoint)
+ (narrow-to-region omin (if nomax (1+ (buffer-size))
+ (min omax (point-max))))))
+ (message "Tagifying %s ... done" (file-name-nondirectory (buffer-file-name))))
+
+;;;###autoload
+(defun Info-split ()
+ "Split an info file into an indirect file plus bounded-size subfiles.
+Each subfile will be up to 50,000 characters plus one node.
+
+To use this command, first visit a large Info file that has a tag
+table. The buffer is modified into a (small) indirect info file which
+should be saved in place of the original visited file.
+
+The subfiles are written in the same directory the original file is
+in, with names generated by appending `-' and a number to the original
+file name. The indirect file still functions as an Info file, but it
+contains just the tag table and a directory of subfiles."
+
+ (interactive)
+ (if (< (buffer-size) 70000)
+ (error "This is too small to be worth splitting"))
+ (goto-char (point-min))
+ (search-forward "\^_")
+ (forward-char -1)
+ (let ((start (point))
+ (chars-deleted 0)
+ subfiles
+ (subfile-number 1)
+ (case-fold-search t)
+ (filename (file-name-sans-versions buffer-file-name)))
+ (goto-char (point-max))
+ (forward-line -8)
+ (setq buffer-read-only nil)
+ (or (search-forward "\^_\nEnd tag table\n" nil t)
+ (error "Tag table required; use M-x Info-tagify"))
+ (search-backward "\nTag table:\n")
+ (if (looking-at "\nTag table:\n\^_")
+ (error "Tag table is just a skeleton; use M-x Info-tagify"))
+ (beginning-of-line)
+ (forward-char 1)
+ (save-restriction
+ (narrow-to-region (point-min) (point))
+ (goto-char (point-min))
+ (while (< (1+ (point)) (point-max))
+ (goto-char (min (+ (point) 50000) (point-max)))
+ (search-forward "\^_" nil 'move)
+ (setq subfiles
+ (cons (list (+ start chars-deleted)
+ (concat (file-name-nondirectory filename)
+ (format "-%d" subfile-number)))
+ subfiles))
+ ;; Put a newline at end of split file, to make Unix happier.
+ (insert "\n")
+ (write-region (point-min) (point)
+ (concat filename (format "-%d" subfile-number)))
+ (delete-region (1- (point)) (point))
+ ;; Back up over the final ^_.
+ (forward-char -1)
+ (setq chars-deleted (+ chars-deleted (- (point) start)))
+ (delete-region start (point))
+ (setq subfile-number (1+ subfile-number))))
+ (while subfiles
+ (goto-char start)
+ (insert (nth 1 (car subfiles))
+ (format ": %d" (1- (car (car subfiles))))
+ "\n")
+ (setq subfiles (cdr subfiles)))
+ (goto-char start)
+ (insert "\^_\nIndirect:\n")
+ (search-forward "\nTag Table:\n")
+ (insert "(Indirect)\n")))
+
+;;;###autoload
+(defun Info-validate ()
+ "Check current buffer for validity as an Info file.
+Check that every node pointer points to an existing node."
+ (interactive)
+ (save-excursion
+ (save-restriction
+ (widen)
+ (goto-char (point-min))
+ (if (search-forward "\nTag table:\n(Indirect)\n" nil t)
+ (error "Don't yet know how to validate indirect info files: \"%s\""
+ (buffer-name (current-buffer))))
+ (goto-char (point-min))
+ (let ((allnodes '(("*")))
+ (regexp "Node:[ \t]*\\([^,\n\t]*\\)[,\t\n]")
+ (case-fold-search t)
+ (tags-losing nil)
+ (lossages ()))
+ (while (search-forward "\n\^_" nil t)
+ (forward-line 1)
+ (let ((beg (point)))
+ (forward-line 1)
+ (if (re-search-backward regexp beg t)
+ (let ((name (downcase
+ (buffer-substring-no-properties
+ (match-beginning 1)
+ (progn
+ (goto-char (match-end 1))
+ (skip-chars-backward " \t")
+ (point))))))
+ (if (assoc name allnodes)
+ (setq lossages
+ (cons (list name "Duplicate node-name" nil)
+ lossages))
+ (setq allnodes
+ (cons (list name
+ (progn
+ (end-of-line)
+ (and (re-search-backward
+ "prev[ious]*:" beg t)
+ (progn
+ (goto-char (match-end 0))
+ (downcase
+ (Info-following-node-name)))))
+ beg)
+ allnodes)))))))
+ (goto-char (point-min))
+ (while (search-forward "\n\^_" nil t)
+ (forward-line 1)
+ (let ((beg (point))
+ thisnode next)
+ (forward-line 1)
+ (if (re-search-backward regexp beg t)
+ (save-restriction
+ (search-forward "\n\^_" nil 'move)
+ (narrow-to-region beg (point))
+ (setq thisnode (downcase
+ (buffer-substring-no-properties
+ (match-beginning 1)
+ (progn
+ (goto-char (match-end 1))
+ (skip-chars-backward " \t")
+ (point)))))
+ (end-of-line)
+ (and (search-backward "next:" nil t)
+ (setq next (Info-validate-node-name "invalid Next"))
+ (assoc next allnodes)
+ (if (equal (car (cdr (assoc next allnodes)))
+ thisnode)
+ ;; allow multiple `next' pointers to one node
+ (let ((tem lossages))
+ (while tem
+ (if (and (equal (car (cdr (car tem)))
+ "should have Previous")
+ (equal (car (car tem))
+ next))
+ (setq lossages (delq (car tem) lossages)))
+ (setq tem (cdr tem))))
+ (setq lossages
+ (cons (list next
+ "should have Previous"
+ thisnode)
+ lossages))))
+ (end-of-line)
+ (if (re-search-backward "prev[ious]*:" nil t)
+ (Info-validate-node-name "invalid Previous"))
+ (end-of-line)
+ (if (search-backward "up:" nil t)
+ (Info-validate-node-name "invalid Up"))
+ (if (re-search-forward "\n* Menu:" nil t)
+ (while (re-search-forward "\n\\* " nil t)
+ (Info-validate-node-name
+ (concat "invalid menu item "
+ (buffer-substring (point)
+ (save-excursion
+ (skip-chars-forward "^:")
+ (point))))
+ (Info-extract-menu-node-name))))
+ (goto-char (point-min))
+ (while (re-search-forward "\\*note[ \n]*[^:\t]*:" nil t)
+ (goto-char (+ (match-beginning 0) 5))
+ (skip-chars-forward " \n")
+ (Info-validate-node-name
+ (concat "invalid reference "
+ (buffer-substring (point)
+ (save-excursion
+ (skip-chars-forward "^:")
+ (point))))
+ (Info-extract-menu-node-name "Bad format cross-reference")))))))
+ (setq tags-losing (not (Info-validate-tags-table)))
+ (if (or lossages tags-losing)
+ (with-output-to-temp-buffer " *problems in info file*"
+ (while lossages
+ (princ "In node \"")
+ (princ (car (car lossages)))
+ (princ "\", ")
+ (let ((tem (nth 1 (car lossages))))
+ (cond ((string-match "\n" tem)
+ (princ (substring tem 0 (match-beginning 0)))
+ (princ "..."))
+ (t
+ (princ tem))))
+ (if (nth 2 (car lossages))
+ (progn
+ (princ ": ")
+ (let ((tem (nth 2 (car lossages))))
+ (cond ((string-match "\n" tem)
+ (princ (substring tem 0 (match-beginning 0)))
+ (princ "..."))
+ (t
+ (princ tem))))))
+ (terpri)
+ (setq lossages (cdr lossages)))
+ (if tags-losing (princ "\nTags table must be recomputed\n")))
+ ;; Here if info file is valid.
+ ;; If we already made a list of problems, clear it out.
+ (save-excursion
+ (if (get-buffer " *problems in info file*")
+ (progn
+ (set-buffer " *problems in info file*")
+ (kill-buffer (current-buffer)))))
+ (message "File appears valid"))))))
+
+(defun Info-validate-node-name (kind &optional name)
+ (if name
+ nil
+ (goto-char (match-end 0))
+ (skip-chars-forward " \t")
+ (if (= (following-char) ?\()
+ nil
+ (setq name
+ (buffer-substring-no-properties
+ (point)
+ (progn
+ (skip-chars-forward "^,\t\n")
+ (skip-chars-backward " ")
+ (point))))))
+ (if (null name)
+ nil
+ (setq name (downcase name))
+ (or (and (> (length name) 0) (= (aref name 0) ?\())
+ (assoc name allnodes)
+ (setq lossages
+ (cons (list thisnode kind name) lossages))))
+ name)
+
+(defun Info-validate-tags-table ()
+ (goto-char (point-min))
+ (if (not (search-forward "\^_\nEnd tag table\n" nil t))
+ t
+ (not (catch 'losing
+ (let* ((end (match-beginning 0))
+ (start (progn (search-backward "\nTag table:\n")
+ (1- (match-end 0))))
+ tem)
+ (setq tem allnodes)
+ (while tem
+ (goto-char start)
+ (or (equal (car (car tem)) "*")
+ (search-forward (concat "Node: "
+ (car (car tem))
+ "\177")
+ end t)
+ (throw 'losing 'x))
+ (setq tem (cdr tem)))
+ (goto-char (1+ start))
+ (while (looking-at ".*Node: \\(.*\\)\177\\([0-9]+\\)$")
+ (setq tem (downcase (buffer-substring-no-properties
+ (match-beginning 1)
+ (match-end 1))))
+ (setq tem (assoc tem allnodes))
+ (if (or (not tem)
+ (< 1000 (progn
+ (goto-char (match-beginning 2))
+ (setq tem (- (car (cdr (cdr tem)))
+ (read (current-buffer))))
+ (if (> tem 0) tem (- tem)))))
+ (throw 'losing 'y))
+ (forward-line 1)))
+ (if (looking-at "\^_\n")
+ (forward-line 1))
+ (or (looking-at "End tag table\n")
+ (throw 'losing 'z))
+ nil))))
+
+;;;###autoload
+(defun batch-info-validate ()
+ "Runs `Info-validate' on the files remaining on the command line.
+Must be used only with -batch, and kills Emacs on completion.
+Each file will be processed even if an error occurred previously.
+For example, invoke \"emacs -batch -f batch-info-validate $info/ ~/*.info\""
+ (if (not noninteractive)
+ (error "batch-info-validate may only be used -batch."))
+ (let ((version-control t)
+ (auto-save-default nil)
+ (find-file-run-dired nil)
+ (kept-old-versions 259259)
+ (kept-new-versions 259259))
+ (let ((error 0)
+ file
+ (files ()))
+ (while command-line-args-left
+ (setq file (expand-file-name (car command-line-args-left)))
+ (cond ((not (file-exists-p file))
+ (message ">> %s does not exist!" file)
+ (setq error 1
+ command-line-args-left (cdr command-line-args-left)))
+ ((file-directory-p file)
+ (setq command-line-args-left (nconc (directory-files file)
+ (cdr command-line-args-left))))
+ (t
+ (setq files (cons file files)
+ command-line-args-left (cdr command-line-args-left)))))
+ (while files
+ (setq file (car files)
+ files (cdr files))
+ (let ((lose nil))
+ (condition-case err
+ (progn
+ (if buffer-file-name (kill-buffer (current-buffer)))
+ (find-file file)
+ (buffer-disable-undo (current-buffer))
+ (set-buffer-modified-p nil)
+ (fundamental-mode)
+ (let ((case-fold-search nil))
+ (goto-char (point-max))
+ (cond ((search-backward "\n\^_\^L\nTag table:\n" nil t)
+ (message "%s already tagified" file))
+ ((< (point-max) 30000)
+ (message "%s too small to bother tagifying" file))
+ (t
+ (Info-tagify))))
+ (let ((loss-name " *problems in info file*"))
+ (message "Checking validity of info file %s..." file)
+ (if (get-buffer loss-name)
+ (kill-buffer loss-name))
+ (Info-validate)
+ (if (not (get-buffer loss-name))
+ nil ;(message "Checking validity of info file %s... OK" file)
+ (message "----------------------------------------------------------------------")
+ (message ">> PROBLEMS IN INFO FILE %s" file)
+ (save-excursion
+ (set-buffer loss-name)
+ (princ (buffer-substring-no-properties
+ (point-min) (point-max))))
+ (message "----------------------------------------------------------------------")
+ (setq error 1 lose t)))
+ (if (and (buffer-modified-p)
+ (not lose))
+ (progn (message "Saving modified %s" file)
+ (save-buffer))))
+ (error (message ">> Error: %s" (prin1-to-string err))))))
+ (kill-emacs error))))
+
+;;; informat.el ends here
diff --git a/contrib/texinfo/emacs/makeinfo.el b/contrib/texinfo/emacs/makeinfo.el
new file mode 100644
index 0000000..a649d52
--- /dev/null
+++ b/contrib/texinfo/emacs/makeinfo.el
@@ -0,0 +1,247 @@
+;;; makeinfo.el --- run makeinfo conveniently
+
+;; Copyright (C) 1991, 1993 Free Software Foundation, Inc.
+
+;; Author: Robert J. Chassell
+;; Maintainer: FSF
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs 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, or (at your option)
+;; any later version.
+
+;; GNU Emacs 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; see the file COPYING. If not, write to the
+;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+;;; Commentary:
+
+;;; The Texinfo mode `makeinfo' related commands are:
+
+;; makeinfo-region to run makeinfo on the current region.
+;; makeinfo-buffer to run makeinfo on the current buffer, or
+;; with optional prefix arg, on current region
+;; kill-compilation to kill currently running makeinfo job
+;; makeinfo-recenter-makeinfo-buffer to redisplay *compilation* buffer
+
+;;; Keybindings (defined in `texinfo.el')
+
+;; makeinfo bindings
+; (define-key texinfo-mode-map "\C-c\C-m\C-r" 'makeinfo-region)
+; (define-key texinfo-mode-map "\C-c\C-m\C-b" 'makeinfo-buffer)
+; (define-key texinfo-mode-map "\C-c\C-m\C-k" 'kill-compilation)
+; (define-key texinfo-mode-map "\C-c\C-m\C-l"
+; 'makeinfo-recenter-compilation-buffer)
+
+;;; Code:
+
+;;; Variables used by `makeinfo'
+
+(require 'compile)
+
+(defvar makeinfo-run-command "makeinfo"
+ "*Command used to run `makeinfo' subjob.
+The name of the file is appended to this string, separated by a space.")
+
+(defvar makeinfo-options "--fill-column=70"
+ "*String containing options for running `makeinfo'.
+Do not include `--footnote-style' or `--paragraph-indent';
+the proper way to specify those is with the Texinfo commands
+`@footnotestyle` and `@paragraphindent'.")
+
+(require 'texinfo)
+
+(defvar makeinfo-compilation-process nil
+ "Process that runs `makeinfo'. Should start out nil.")
+
+(defvar makeinfo-temp-file nil
+ "Temporary file name used for text being sent as input to `makeinfo'.")
+
+(defvar makeinfo-output-file-name nil
+ "Info file name used for text output by `makeinfo'.")
+
+
+;;; The `makeinfo' function definitions
+
+(defun makeinfo-region (region-beginning region-end)
+ "Make Info file from region of current Texinfo file, and switch to it.
+
+This command does not offer the `next-error' feature since it would
+apply to a temporary file, not the original; use the `makeinfo-buffer'
+command to gain use of `next-error'."
+
+ (interactive "r")
+ (let (filename-or-header
+ filename-or-header-beginning
+ filename-or-header-end)
+ ;; Cannot use `let' for makeinfo-temp-file or
+ ;; makeinfo-output-file-name since `makeinfo-compilation-sentinel'
+ ;; needs them.
+
+ (setq makeinfo-temp-file
+ (concat
+ (make-temp-name
+ (substring (buffer-file-name)
+ 0
+ (or (string-match "\\.tex" (buffer-file-name))
+ (length (buffer-file-name)))))
+ ".texinfo"))
+
+ (save-excursion
+ (save-restriction
+ (widen)
+ (goto-char (point-min))
+ (let ((search-end (save-excursion (forward-line 100) (point))))
+ ;; Find and record the Info filename,
+ ;; or else explain that a filename is needed.
+ (if (re-search-forward
+ "^@setfilename[ \t]+\\([^ \t\n]+\\)[ \t]*"
+ search-end t)
+ (setq makeinfo-output-file-name
+ (buffer-substring (match-beginning 1) (match-end 1)))
+ (error
+ "The texinfo file needs a line saying: @setfilename <name>"))
+
+ ;; Find header and specify its beginning and end.
+ (goto-char (point-min))
+ (if (and
+ (prog1
+ (search-forward tex-start-of-header search-end t)
+ (beginning-of-line)
+ ;; Mark beginning of header.
+ (setq filename-or-header-beginning (point)))
+ (prog1
+ (search-forward tex-end-of-header nil t)
+ (beginning-of-line)
+ ;; Mark end of header
+ (setq filename-or-header-end (point))))
+
+ ;; Insert the header into the temporary file.
+ (write-region
+ (min filename-or-header-beginning region-beginning)
+ filename-or-header-end
+ makeinfo-temp-file nil nil)
+
+ ;; Else no header; insert @filename line into temporary file.
+ (goto-char (point-min))
+ (search-forward "@setfilename" search-end t)
+ (beginning-of-line)
+ (setq filename-or-header-beginning (point))
+ (forward-line 1)
+ (setq filename-or-header-end (point))
+ (write-region
+ (min filename-or-header-beginning region-beginning)
+ filename-or-header-end
+ makeinfo-temp-file nil nil))
+
+ ;; Insert the region into the file.
+ (write-region
+ (max region-beginning filename-or-header-end)
+ region-end
+ makeinfo-temp-file t nil)
+
+ ;; Run the `makeinfo-compile' command in the *compilation* buffer
+ (save-excursion
+ (makeinfo-compile
+ (concat makeinfo-run-command
+ " "
+ makeinfo-options
+ " "
+ makeinfo-temp-file)
+ "Use `makeinfo-buffer' to gain use of the `next-error' command"
+ nil)))))))
+
+;;; Actually run makeinfo. COMMAND is the command to run.
+;;; ERROR-MESSAGE is what to say when next-error can't find another error.
+;;; If PARSE-ERRORS is non-nil, do try to parse error messages.
+(defun makeinfo-compile (command error-message parse-errors)
+ (let ((buffer
+ (compile-internal command error-message nil
+ (and (not parse-errors)
+ ;; If we do want to parse errors, pass nil.
+ ;; Otherwise, use this function, which won't
+ ;; ever find any errors.
+ '(lambda (&rest ignore)
+ (setq compilation-error-list nil))))))
+ (set-process-sentinel (get-buffer-process buffer)
+ 'makeinfo-compilation-sentinel)))
+
+;; Delete makeinfo-temp-file after processing is finished,
+;; and visit Info file.
+;; This function is called when the compilation process changes state.
+;; Based on `compilation-sentinel' in compile.el
+(defun makeinfo-compilation-sentinel (proc msg)
+ (compilation-sentinel proc msg)
+ (if (and makeinfo-temp-file (file-exists-p makeinfo-temp-file))
+ (delete-file makeinfo-temp-file))
+ ;; Always use the version on disk.
+ (if (get-file-buffer makeinfo-output-file-name)
+ (progn (set-buffer makeinfo-output-file-name)
+ (revert-buffer t t))
+ (find-file makeinfo-output-file-name))
+ (goto-char (point-min)))
+
+(defun makeinfo-buffer ()
+ "Make Info file from current buffer.
+
+Use the \\[next-error] command to move to the next error
+\(if there are errors\)."
+
+ (interactive)
+ (cond ((null buffer-file-name)
+ (error "Buffer not visiting any file"))
+ ((buffer-modified-p)
+ (if (y-or-n-p "Buffer modified; do you want to save it? ")
+ (save-buffer))))
+
+ ;; Find and record the Info filename,
+ ;; or else explain that a filename is needed.
+ (save-excursion
+ (goto-char (point-min))
+ (let ((search-end (save-excursion (forward-line 100) (point))))
+ (if (re-search-forward
+ "^@setfilename[ \t]+\\([^ \t\n]+\\)[ \t]*"
+ search-end t)
+ (setq makeinfo-output-file-name
+ (buffer-substring (match-beginning 1) (match-end 1)))
+ (error
+ "The texinfo file needs a line saying: @setfilename <name>"))))
+
+ (save-excursion
+ (makeinfo-compile
+ (concat makeinfo-run-command " " makeinfo-options
+ " " buffer-file-name)
+ "No more errors."
+ t)))
+
+(defun makeinfo-recenter-compilation-buffer (linenum)
+ "Redisplay `*compilation*' buffer so most recent output can be seen.
+The last line of the buffer is displayed on
+line LINE of the window, or centered if LINE is nil."
+ (interactive "P")
+ (let ((makeinfo-buffer (get-buffer "*compilation*"))
+ (old-buffer (current-buffer)))
+ (if (null makeinfo-buffer)
+ (message "No *compilation* buffer")
+ (pop-to-buffer makeinfo-buffer)
+ (bury-buffer makeinfo-buffer)
+ (goto-char (point-max))
+ (recenter (if linenum
+ (prefix-numeric-value linenum)
+ (/ (window-height) 2)))
+ (pop-to-buffer old-buffer)
+ )))
+
+;;; Place `provide' at end of file.
+(provide 'makeinfo)
+
+;;; makeinfo.el ends here
+
diff --git a/contrib/texinfo/emacs/new-useful-setqs b/contrib/texinfo/emacs/new-useful-setqs
new file mode 100644
index 0000000..4241ae4
--- /dev/null
+++ b/contrib/texinfo/emacs/new-useful-setqs
@@ -0,0 +1,180 @@
+;; -*- Mode: Emacs-Lisp -*-
+
+;; This is the `new-useful-setqs' file
+;; This overrides old defvars since they were revised.
+
+(setq texinfmt-version "2.35 of 10 September 1996")
+
+(setq texinfo-master-menu-header
+ "\n@detailmenu\n --- The Detailed Node Listing ---\n")
+
+(setq texinfo-environment-regexp
+ (concat
+ "^@"
+ "\\("
+ "cartouche\\|"
+ "display\\|"
+ "end\\|"
+ "enumerate\\|"
+ "example\\|"
+ "f?table\\|"
+ "flushleft\\|"
+ "flushright\\|"
+ "format\\|"
+ "group\\|"
+ "ifhtml\\|"
+ "ifinfo\\|"
+ "iftex\\|"
+ "ignore\\|"
+ "itemize\\|"
+ "lisp\\|"
+ "macro\\|"
+ "multitable\\|"
+ "quotation\\|"
+ "smallexample\\|"
+ "smalllisp\\|"
+ "tex"
+ "\\)")
+)
+
+(setq texinfo-no-refill-regexp
+ (concat
+ "^@"
+ "\\("
+ "example\\|"
+ "smallexample\\|"
+ "lisp\\|"
+ "smalllisp\\|"
+ "display\\|"
+ "format\\|"
+ "flushleft\\|"
+ "flushright\\|"
+ "menu\\|"
+ "multitable\\|"
+ "titlepage\\|"
+ "iftex\\|"
+ "ifhtml\\|"
+ "tex\\|"
+ "html"
+ "\\)"))
+
+
+(setq texinfo-accent-commands
+ (concat
+ "@OE\\|"
+ "@oe\\|"
+ "@AA\\|"
+ "@aa\\|"
+ "@AE\\|"
+ "@ae\\|"
+ "@ss\\|"
+ "@^\\|"
+ "@`\\|"
+ "@'\\|"
+ "@\"\\|"
+ "@,\\|"
+ "@=\\|"
+ "@~\\|"
+ "@questiondown{\\|"
+ "@exclamdown{\\|"
+ "@L{\\|"
+ "@l{\\|"
+ "@O{\\|"
+ "@o{\\|"
+ "@dotaccent{\\|"
+ "@ubaraccent{\\|"
+ "@d{\\|"
+ "@H{\\|"
+ "@ringaccent{\\|"
+ "@tieaccent{\\|"
+ "@u{\\|"
+ "@v{\\|"
+ "@dotless{"
+ ))
+
+(setq texinfo-part-of-para-regexp
+ (concat
+ "^@"
+ "\\("
+ "b{\\|"
+ "bullet{\\|"
+ "cite{\\|"
+ "code{\\|"
+ "emph{\\|"
+ "equiv{\\|"
+ "error{\\|"
+ "expansion{\\|"
+ "file{\\|"
+ "i{\\|"
+ "inforef{\\|"
+ "kbd{\\|"
+ "key{\\|"
+ "lisp{\\|"
+ "email{\\|"
+ "minus{\\|"
+ "point{\\|"
+ "print{\\|"
+ "pxref{\\|"
+ "r{\\|"
+ "ref{\\|"
+ "result{\\|"
+ "samp{\\|"
+ "sc{\\|"
+ "t{\\|"
+ "TeX{\\|"
+ "today{\\|"
+ "url{\\|"
+ "var{\\|"
+ "w{\\|"
+ "xref{\\|"
+ "@-\\|" ; @- is a descretionary hyphen (not an accent) (a noop).
+ texinfo-accent-commands
+ "\\)"
+ ))
+
+(setq texinfo-raisesections-alist
+ '((@chapter . @chapter) ; Cannot go higher
+ (@unnumbered . @unnumbered)
+ (@centerchap . @unnumbered)
+
+ (@majorheading . @majorheading)
+ (@chapheading . @chapheading)
+ (@appendix . @appendix)
+
+ (@section . @chapter)
+ (@unnumberedsec . @unnumbered)
+ (@heading . @chapheading)
+ (@appendixsec . @appendix)
+
+ (@subsection . @section)
+ (@unnumberedsubsec . @unnumberedsec)
+ (@subheading . @heading)
+ (@appendixsubsec . @appendixsec)
+
+ (@subsubsection . @subsection)
+ (@unnumberedsubsubsec . @unnumberedsubsec)
+ (@subsubheading . @subheading)
+ (@appendixsubsubsec . @appendixsubsec)))
+
+(setq texinfo-lowersections-alist
+ '((@chapter . @section)
+ (@unnumbered . @unnumberedsec)
+ (@centerchap . @unnumberedsec)
+ (@majorheading . @heading)
+ (@chapheading . @heading)
+ (@appendix . @appendixsec)
+
+ (@section . @subsection)
+ (@unnumberedsec . @unnumberedsubsec)
+ (@heading . @subheading)
+ (@appendixsec . @appendixsubsec)
+
+ (@subsection . @subsubsection)
+ (@unnumberedsubsec . @unnumberedsubsubsec)
+ (@subheading . @subsubheading)
+ (@appendixsubsec . @appendixsubsubsec)
+
+ (@subsubsection . @subsubsection) ; Cannot go lower.
+ (@unnumberedsubsubsec . @unnumberedsubsubsec)
+ (@subsubheading . @subsubheading)
+ (@appendixsubsubsec . @appendixsubsubsec)))
diff --git a/contrib/texinfo/emacs/texinfmt.el b/contrib/texinfo/emacs/texinfmt.el
new file mode 100644
index 0000000..c0d0963
--- /dev/null
+++ b/contrib/texinfo/emacs/texinfmt.el
@@ -0,0 +1,3979 @@
+;;; texinfmt.el --- format Texinfo files into Info files.
+
+;; Copyright (C) 1985, 1986, 1988, 1990, 1991,
+;; 1992, 1993, 1994, 1995, 1996 Free Software Foundation, Inc.
+
+;; Author: Robert J. Chassell
+;; Date: 10 Sep 1996
+;; Maintainer: Robert J. Chassell <bug-texinfo@prep.ai.mit.edu>
+;; Keywords: maint, tex, docs
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs 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, or (at your option)
+;; any later version.
+
+;; GNU Emacs 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; see the file COPYING. If not, write to the
+;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+;;; Code:
+
+;;; Emacs lisp functions to convert Texinfo files to Info files.
+
+(defvar texinfmt-version "2.35 of 10 September 1996")
+
+(defun texinfmt-version (&optional here)
+ "Show the version of texinfmt.el in the minibuffer.
+If optional argument HERE is non-nil, insert info at point."
+ (interactive "P")
+ (let ((version-string
+ (format "Version of \`texinfmt.el\': %s" texinfmt-version)))
+ (if here
+ (insert version-string)
+ (if (interactive-p)
+ (message "%s" version-string)
+ version-string))))
+
+
+;;; Variable definitions
+
+(require 'texinfo) ; So `texinfo-footnote-style' is defined.
+(require 'texnfo-upd) ; So `texinfo-section-types-regexp' is defined.
+
+(defvar texinfo-format-syntax-table nil)
+
+(defvar texinfo-vindex)
+(defvar texinfo-findex)
+(defvar texinfo-cindex)
+(defvar texinfo-pindex)
+(defvar texinfo-tindex)
+(defvar texinfo-kindex)
+(defvar texinfo-last-node)
+(defvar texinfo-node-names)
+(defvar texinfo-enclosure-list)
+(defvar texinfo-alias-list)
+
+(defvar texinfo-command-start)
+(defvar texinfo-command-end)
+(defvar texinfo-command-name)
+(defvar texinfo-defun-type)
+(defvar texinfo-last-node-pos)
+(defvar texinfo-stack)
+(defvar texinfo-short-index-cmds-alist)
+(defvar texinfo-short-index-format-cmds-alist)
+(defvar texinfo-format-filename)
+(defvar texinfo-footnote-number)
+(defvar texinfo-start-of-header)
+(defvar texinfo-end-of-header)
+(defvar texinfo-raisesections-alist)
+(defvar texinfo-lowersections-alist)
+
+;;; Syntax table
+
+(if texinfo-format-syntax-table
+ nil
+ (setq texinfo-format-syntax-table (make-syntax-table))
+ (modify-syntax-entry ?\" " " texinfo-format-syntax-table)
+ (modify-syntax-entry ?\\ " " texinfo-format-syntax-table)
+ (modify-syntax-entry ?@ "\\" texinfo-format-syntax-table)
+ (modify-syntax-entry ?\^q "\\" texinfo-format-syntax-table)
+ (modify-syntax-entry ?\[ "." texinfo-format-syntax-table)
+ (modify-syntax-entry ?\] "." texinfo-format-syntax-table)
+ (modify-syntax-entry ?\( "." texinfo-format-syntax-table)
+ (modify-syntax-entry ?\) "." texinfo-format-syntax-table)
+ (modify-syntax-entry ?{ "(}" texinfo-format-syntax-table)
+ (modify-syntax-entry ?} "){" texinfo-format-syntax-table)
+ (modify-syntax-entry ?\' "." texinfo-format-syntax-table))
+
+
+;;; Top level buffer and region formatting functions
+
+;;;###autoload
+(defun texinfo-format-buffer (&optional notagify)
+ "Process the current buffer as texinfo code, into an Info file.
+The Info file output is generated in a buffer visiting the Info file
+names specified in the @setfilename command.
+
+Non-nil argument (prefix, if interactive) means don't make tag table
+and don't split the file if large. You can use Info-tagify and
+Info-split to do these manually."
+ (interactive "P")
+ (let ((lastmessage "Formatting Info file..."))
+ (message lastmessage)
+ (texinfo-format-buffer-1)
+ (if notagify
+ nil
+ (if (> (buffer-size) 30000)
+ (progn
+ (message (setq lastmessage "Making tags table for Info file..."))
+ (Info-tagify)))
+ (if (> (buffer-size) 100000)
+ (progn
+ (message (setq lastmessage "Splitting Info file..."))
+ (Info-split))))
+ (message (concat lastmessage
+ (if (interactive-p) "done. Now save it." "done.")))))
+
+(defvar texinfo-region-buffer-name "*Info Region*"
+ "*Name of the temporary buffer used by \\[texinfo-format-region].")
+
+;;;###autoload
+(defun texinfo-format-region (region-beginning region-end)
+ "Convert the current region of the Texinfo file to Info format.
+This lets you see what that part of the file will look like in Info.
+The command is bound to \\[texinfo-format-region]. The text that is
+converted to Info is stored in a temporary buffer."
+ (interactive "r")
+ (message "Converting region to Info format...")
+ (let (texinfo-command-start
+ texinfo-command-end
+ texinfo-command-name
+ texinfo-vindex
+ texinfo-findex
+ texinfo-cindex
+ texinfo-pindex
+ texinfo-tindex
+ texinfo-kindex
+ texinfo-stack
+ (texinfo-format-filename "")
+ texinfo-example-start
+ texinfo-last-node-pos
+ texinfo-last-node
+ texinfo-node-names
+ (texinfo-footnote-number 0)
+ last-input-buffer
+ (fill-column-for-info fill-column)
+ (input-buffer (current-buffer))
+ (input-directory default-directory)
+ (header-text "")
+ (header-beginning 1)
+ (header-end 1))
+
+;;; Copy lines between beginning and end of header lines,
+;;; if any, or else copy the `@setfilename' line, if any.
+ (save-excursion
+ (save-restriction
+ (widen)
+ (goto-char (point-min))
+ (let ((search-end (save-excursion (forward-line 100) (point))))
+ (if (or
+ ;; Either copy header text.
+ (and
+ (prog1
+ (search-forward tex-start-of-header search-end t)
+ (forward-line 1)
+ ;; Mark beginning of header.
+ (setq header-beginning (point)))
+ (prog1
+ (search-forward tex-end-of-header nil t)
+ (beginning-of-line)
+ ;; Mark end of header
+ (setq header-end (point))))
+ ;; Or copy @filename line.
+ (prog2
+ (goto-char (point-min))
+ (search-forward "@setfilename" search-end t)
+ (beginning-of-line)
+ (setq header-beginning (point))
+ (forward-line 1)
+ (setq header-end (point))))
+
+ ;; Copy header
+ (setq header-text
+ (buffer-substring
+ (min header-beginning region-beginning)
+ header-end))))))
+
+;;; Find a buffer to use.
+ (switch-to-buffer (get-buffer-create texinfo-region-buffer-name))
+ (erase-buffer)
+ ;; Insert the header into the buffer.
+ (insert header-text)
+ ;; Insert the region into the buffer.
+ (insert-buffer-substring
+ input-buffer
+ (max region-beginning header-end)
+ region-end)
+ ;; Make sure region ends in a newline.
+ (or (= (preceding-char) ?\n)
+ (insert "\n"))
+
+ (goto-char (point-min))
+ (texinfo-mode)
+ (message "Converting region to Info format...")
+ (setq fill-column fill-column-for-info)
+ ;; Install a syntax table useful for scanning command operands.
+ (set-syntax-table texinfo-format-syntax-table)
+
+ ;; Insert @include files so `texinfo-raise-lower-sections' can
+ ;; work on them without losing track of multiple
+ ;; @raise/@lowersections commands.
+ (while (re-search-forward "^@include" nil t)
+ (setq texinfo-command-end (point))
+ (let ((filename (concat input-directory
+ (texinfo-parse-line-arg))))
+ (re-search-backward "^@include")
+ (delete-region (point) (save-excursion (forward-line 1) (point)))
+ (message "Reading included file: %s" filename)
+ (save-excursion
+ (save-restriction
+ (narrow-to-region
+ (point)
+ (+ (point) (car (cdr (insert-file-contents filename)))))
+ (goto-char (point-min))
+ ;; Remove `@setfilename' line from included file, if any,
+ ;; so @setfilename command not duplicated.
+ (if (re-search-forward
+ "^@setfilename" (save-excursion (forward-line 100) (point)) t)
+ (progn
+ (beginning-of-line)
+ (delete-region
+ (point) (save-excursion (forward-line 1) (point)))))))))
+
+ ;; Raise or lower level of each section, if necessary.
+ (goto-char (point-min))
+ (texinfo-raise-lower-sections)
+ ;; Append @refill to appropriate paragraphs for filling.
+ (goto-char (point-min))
+ (texinfo-append-refill)
+ ;; If the region includes the effective end of the data,
+ ;; discard everything after that.
+ (goto-char (point-max))
+ (if (re-search-backward "^@bye" nil t)
+ (delete-region (point) (point-max)))
+ ;; Make sure buffer ends in a newline.
+ (or (= (preceding-char) ?\n)
+ (insert "\n"))
+ ;; Don't use a previous value of texinfo-enclosure-list.
+ (setq texinfo-enclosure-list nil)
+ (setq texinfo-alias-list nil)
+
+ (goto-char (point-min))
+ (if (looking-at "\\\\input[ \t]+texinfo")
+ (delete-region (point) (save-excursion (forward-line 1) (point))))
+
+ ;; Insert Info region title text.
+ (goto-char (point-min))
+ (if (search-forward
+ "@setfilename" (save-excursion (forward-line 100) (point)) t)
+ (progn
+ (setq texinfo-command-end (point))
+ (beginning-of-line)
+ (setq texinfo-command-start (point))
+ (let ((arg (texinfo-parse-arg-discard)))
+ (insert " "
+ texinfo-region-buffer-name
+ " buffer for: `")
+ (insert (file-name-nondirectory (expand-file-name arg)))
+ (insert "', -*-Text-*-\n")))
+ ;; Else no `@setfilename' line
+ (insert " "
+ texinfo-region-buffer-name
+ " buffer -*-Text-*-\n"))
+ (insert "produced by `texinfo-format-region'\n"
+ "from a region in: "
+ (if (buffer-file-name input-buffer)
+ (concat "`"
+ (file-name-sans-versions
+ (file-name-nondirectory
+ (buffer-file-name input-buffer)))
+ "'")
+ (concat "buffer `" (buffer-name input-buffer) "'"))
+ "\nusing `texinfmt.el' version "
+ texinfmt-version
+ ".\n\n")
+
+ ;; Now convert for real.
+ (goto-char (point-min))
+ (texinfo-format-scan)
+ (goto-char (point-min))
+
+ (message "Done.")))
+
+
+;;; Primary internal formatting function for the whole buffer.
+
+(defun texinfo-format-buffer-1 ()
+ (let (texinfo-format-filename
+ texinfo-example-start
+ texinfo-command-start
+ texinfo-command-end
+ texinfo-command-name
+ texinfo-last-node
+ texinfo-last-node-pos
+ texinfo-vindex
+ texinfo-findex
+ texinfo-cindex
+ texinfo-pindex
+ texinfo-tindex
+ texinfo-kindex
+ texinfo-stack
+ texinfo-node-names
+ (texinfo-footnote-number 0)
+ last-input-buffer
+ outfile
+ (fill-column-for-info fill-column)
+ (input-buffer (current-buffer))
+ (input-directory default-directory))
+ (setq texinfo-enclosure-list nil)
+ (setq texinfo-alias-list nil)
+ (save-excursion
+ (goto-char (point-min))
+ (or (search-forward "@setfilename" nil t)
+ (error "Texinfo file needs an `@setfilename FILENAME' line."))
+ (setq texinfo-command-end (point))
+ (setq outfile (texinfo-parse-line-arg)))
+ (find-file outfile)
+ (texinfo-mode)
+ (setq fill-column fill-column-for-info)
+ (set-syntax-table texinfo-format-syntax-table)
+ (erase-buffer)
+ (insert-buffer-substring input-buffer)
+ (message "Converting %s to Info format..." (buffer-name input-buffer))
+
+ ;; Insert @include files so `texinfo-raise-lower-sections' can
+ ;; work on them without losing track of multiple
+ ;; @raise/@lowersections commands.
+ (goto-char (point-min))
+ (while (re-search-forward "^@include" nil t)
+ (setq texinfo-command-end (point))
+ (let ((filename (concat input-directory
+ (texinfo-parse-line-arg))))
+ (re-search-backward "^@include")
+ (delete-region (point) (save-excursion (forward-line 1) (point)))
+ (message "Reading included file: %s" filename)
+ (save-excursion
+ (save-restriction
+ (narrow-to-region
+ (point)
+ (+ (point) (car (cdr (insert-file-contents filename)))))
+ (goto-char (point-min))
+ ;; Remove `@setfilename' line from included file, if any,
+ ;; so @setfilename command not duplicated.
+ (if (re-search-forward
+ "^@setfilename"
+ (save-excursion (forward-line 100) (point)) t)
+ (progn
+ (beginning-of-line)
+ (delete-region
+ (point) (save-excursion (forward-line 1) (point)))))))))
+ ;; Raise or lower level of each section, if necessary.
+ (goto-char (point-min))
+ (texinfo-raise-lower-sections)
+ ;; Append @refill to appropriate paragraphs
+ (goto-char (point-min))
+ (texinfo-append-refill)
+ (goto-char (point-min))
+ (search-forward "@setfilename")
+ (beginning-of-line)
+ (delete-region (point-min) (point))
+ ;; Remove @bye at end of file, if it is there.
+ (goto-char (point-max))
+ (if (search-backward "@bye" nil t)
+ (delete-region (point) (point-max)))
+ ;; Make sure buffer ends in a newline.
+ (or (= (preceding-char) ?\n)
+ (insert "\n"))
+ ;; Scan the whole buffer, converting to Info format.
+ (texinfo-format-scan)
+ ;; Return data for indices.
+ (goto-char (point-min))
+ (list outfile
+ texinfo-vindex texinfo-findex texinfo-cindex
+ texinfo-pindex texinfo-tindex texinfo-kindex)))
+
+
+;;; Perform non-@-command file conversions: quotes and hyphens
+
+(defun texinfo-format-convert (min max)
+ ;; Convert left and right quotes to typewriter font quotes.
+ (goto-char min)
+ (while (search-forward "``" max t)
+ (replace-match "\""))
+ (goto-char min)
+ (while (search-forward "''" max t)
+ (replace-match "\""))
+ ;; Convert three hyphens in a row to two.
+ (goto-char min)
+ (while (re-search-forward "\\( \\|\\w\\)\\(---\\)\\( \\|\\w\\)" max t)
+ (delete-region (1+ (match-beginning 2)) (+ 2 (match-beginning
+ 2)))))
+
+
+;;; Handle paragraph filling
+
+;; Keep as concatinated lists for ease of maintenance
+
+(defvar texinfo-no-refill-regexp
+ (concat
+ "^@"
+ "\\("
+ "example\\|"
+ "smallexample\\|"
+ "lisp\\|"
+ "smalllisp\\|"
+ "display\\|"
+ "format\\|"
+ "flushleft\\|"
+ "flushright\\|"
+ "menu\\|"
+ "multitable\\|"
+ "titlepage\\|"
+ "iftex\\|"
+ "ifhtml\\|"
+ "tex\\|"
+ "html"
+ "\\)")
+ "Regexp specifying environments in which paragraphs are not filled.")
+
+(defvar texinfo-accent-commands
+ (concat
+ "@^\\|"
+ "@`\\|"
+ "@'\\|"
+ "@\"\\|"
+ "@,\\|"
+ "@=\\|"
+ "@~\\|"
+ "@OE{\\|"
+ "@oe{\\|"
+ "@AA{\\|"
+ "@aa{\\|"
+ "@AE{\\|"
+ "@ae{\\|"
+ "@ss{\\|"
+ "@questiondown{\\|"
+ "@exclamdown{\\|"
+ "@L{\\|"
+ "@l{\\|"
+ "@O{\\|"
+ "@o{\\|"
+ "@dotaccent{\\|"
+ "@ubaraccent{\\|"
+ "@d{\\|"
+ "@H{\\|"
+ "@ringaccent{\\|"
+ "@tieaccent{\\|"
+ "@u{\\|"
+ "@v{\\|"
+ "@dotless{"
+ ))
+
+(defvar texinfo-part-of-para-regexp
+ (concat
+ "^@"
+ "\\("
+ "b{\\|"
+ "bullet{\\|"
+ "cite{\\|"
+ "code{\\|"
+ "emph{\\|"
+ "equiv{\\|"
+ "error{\\|"
+ "expansion{\\|"
+ "file{\\|"
+ "i{\\|"
+ "inforef{\\|"
+ "kbd{\\|"
+ "key{\\|"
+ "lisp{\\|"
+ "email{\\|"
+ "minus{\\|"
+ "point{\\|"
+ "print{\\|"
+ "pxref{\\|"
+ "r{\\|"
+ "ref{\\|"
+ "result{\\|"
+ "samp{\\|"
+ "sc{\\|"
+ "t{\\|"
+ "TeX{\\|"
+ "today{\\|"
+ "url{\\|"
+ "var{\\|"
+ "w{\\|"
+ "xref{\\|"
+ "@-\\|" ; @- is a descretionary hyphen (not an accent) (a noop).
+ texinfo-accent-commands
+ "\\)"
+ )
+ "Regexp specifying @-commands found within paragraphs.")
+
+(defun texinfo-append-refill ()
+ "Append @refill at end of each paragraph that should be filled.
+Do not append @refill to paragraphs within @example and similar environments.
+Do not append @refill to paragraphs containing @w{TEXT} or @*."
+
+ ;; It is necessary to append @refill before other processing because
+ ;; the other processing removes information that tells Texinfo
+ ;; whether the text should or should not be filled.
+
+ (while (< (point) (point-max))
+ (let ((refill-blank-lines "^[ \t\n]*$")
+ (case-fold-search nil)) ; Don't confuse @TeX and @tex....
+ (beginning-of-line)
+ ;; 1. Skip over blank lines;
+ ;; skip over lines beginning with @-commands,
+ ;; but do not skip over lines
+ ;; that are no-refill environments such as @example or
+ ;; that begin with within-paragraph @-commands such as @code.
+ (while (and (looking-at (concat "^@\\|^\\\\\\|" refill-blank-lines))
+ (not (looking-at
+ (concat
+ "\\("
+ texinfo-no-refill-regexp
+ "\\|"
+ texinfo-part-of-para-regexp
+ "\\)")))
+ (< (point) (point-max)))
+ (forward-line 1))
+ ;; 2. Skip over @example and similar no-refill environments.
+ (if (looking-at texinfo-no-refill-regexp)
+ (let ((environment
+ (buffer-substring (match-beginning 1) (match-end 1))))
+ (progn (re-search-forward (concat "^@end " environment) nil t)
+ (forward-line 1)))
+ ;; Else
+ ;; 3. Do not refill a paragraph containing @w or @*, or ending
+ ;; with @<newline> followed by a newline.
+ (if (or
+ (>= (point) (point-max))
+ (re-search-forward
+ "@w{\\|@\\*\\|@\n\n"
+ (save-excursion
+ (forward-paragraph)
+ (forward-line 1)
+ (point)) t))
+ ;; Go to end of paragraph and do nothing.
+ (forward-paragraph)
+ ;; 4. Else go to end of paragraph and insert @refill
+ (forward-paragraph)
+ (forward-line -1)
+ (end-of-line)
+ (delete-region
+ (point)
+ (save-excursion (skip-chars-backward " \t") (point)))
+ ;; `looking-at-backward' not available in v. 18.57
+ ;; (if (not (looking-at-backward "@refill\\|@bye")) ;)
+ (if (not (re-search-backward
+ "@refill\\|@bye"
+ (save-excursion (beginning-of-line) (point))
+ t))
+ (insert "@refill"))
+ (forward-line 1))))))
+
+
+;;; Handle `@raisesections' and `@lowersections' commands
+
+;; These commands change the hierarchical level of chapter structuring
+;; commands.
+;;
+;; @raisesections changes @subsection to @section,
+;; @section to @chapter,
+;; etc.
+;;
+;; @lowersections changes @chapter to @section
+;; @subsection to @subsubsection,
+;; etc.
+;;
+;; An @raisesections/@lowersections command changes only those
+;; structuring commands that follow the @raisesections/@lowersections
+;; command.
+;;
+;; Repeated @raisesections/@lowersections continue to raise or lower
+;; the heading level.
+;;
+;; An @lowersections command cancels an @raisesections command, and
+;; vice versa.
+;;
+;; You cannot raise or lower "beyond" chapters or subsubsections, but
+;; trying to do so does not elicit an error---you just get more
+;; headings that mean the same thing as you keep raising or lowering
+;; (for example, after a single @raisesections, both @chapter and
+;; @section produce chapter headings).
+
+(defun texinfo-raise-lower-sections ()
+ "Raise or lower the hierarchical level of chapters, sections, etc.
+
+This function acts according to `@raisesections' and `@lowersections'
+commands in the Texinfo file.
+
+For example, an `@lowersections' command is useful if you wish to
+include what is written as an outer or standalone Texinfo file in
+another Texinfo file as an inner, included file. The `@lowersections'
+command changes chapters to sections, sections to subsections and so
+on.
+
+@raisesections changes @subsection to @section,
+ @section to @chapter,
+ @heading to @chapheading,
+ etc.
+
+@lowersections changes @chapter to @section,
+ @subsection to @subsubsection,
+ @heading to @subheading,
+ etc.
+
+An `@raisesections' or `@lowersections' command changes only those
+structuring commands that follow the `@raisesections' or
+`@lowersections' command.
+
+An `@lowersections' command cancels an `@raisesections' command, and
+vice versa.
+
+Repeated use of the commands continue to raise or lower the hierarchical
+level a step at a time.
+
+An attempt to raise above `chapters' reproduces chapter commands; an
+attempt to lower below subsubsections reproduces subsubsection
+commands."
+
+ ;; `texinfo-section-types-regexp' is defined in `texnfo-upd.el';
+ ;; it is a regexp matching chapter, section, other headings
+ ;; (but not the top node).
+
+ (let (type (level 0))
+ (while
+ (re-search-forward
+ (concat
+ "\\(\\(^@\\(raise\\|lower\\)sections\\)\\|\\("
+ texinfo-section-types-regexp
+ "\\)\\)")
+ nil t)
+ (beginning-of-line)
+ (save-excursion (setq type (read (current-buffer))))
+ (cond
+
+ ;; 1. Increment level
+ ((eq type '@raisesections)
+ (setq level (1+ level))
+ (delete-region
+ (point) (save-excursion (forward-line 1) (point))))
+
+ ;; 2. Decrement level
+ ((eq type '@lowersections)
+ (setq level (1- level))
+ (delete-region
+ (point) (save-excursion (forward-line 1) (point))))
+
+ ;; Now handle structuring commands
+ ((cond
+
+ ;; 3. Raise level when positive
+ ((> level 0)
+ (let ((count level)
+ (new-level type))
+ (while (> count 0)
+ (setq new-level
+ (cdr (assq new-level texinfo-raisesections-alist)))
+ (setq count (1- count)))
+ (kill-word 1)
+ (insert (symbol-name new-level))))
+
+ ;; 4. Do nothing except move point when level is zero
+ ((= level 0) (forward-line 1))
+
+ ;; 5. Lower level when positive
+ ((< level 0)
+ (let ((count level)
+ (new-level type))
+ (while (< count 0)
+ (setq new-level
+ (cdr (assq new-level texinfo-lowersections-alist)))
+ (setq count (1+ count)))
+ (kill-word 1)
+ (insert (symbol-name new-level))))))))))
+
+(defvar texinfo-raisesections-alist
+ '((@chapter . @chapter) ; Cannot go higher
+ (@unnumbered . @unnumbered)
+ (@centerchap . @unnumbered)
+
+ (@majorheading . @majorheading)
+ (@chapheading . @chapheading)
+ (@appendix . @appendix)
+
+ (@section . @chapter)
+ (@unnumberedsec . @unnumbered)
+ (@heading . @chapheading)
+ (@appendixsec . @appendix)
+
+ (@subsection . @section)
+ (@unnumberedsubsec . @unnumberedsec)
+ (@subheading . @heading)
+ (@appendixsubsec . @appendixsec)
+
+ (@subsubsection . @subsection)
+ (@unnumberedsubsubsec . @unnumberedsubsec)
+ (@subsubheading . @subheading)
+ (@appendixsubsubsec . @appendixsubsec))
+ "*An alist of next higher levels for chapters, sections. etc.
+For example, section to chapter, subsection to section.
+Used by `texinfo-raise-lower-sections'.
+The keys specify types of section; the values correspond to the next
+higher types.")
+
+(defvar texinfo-lowersections-alist
+ '((@chapter . @section)
+ (@unnumbered . @unnumberedsec)
+ (@centerchap . @unnumberedsec)
+ (@majorheading . @heading)
+ (@chapheading . @heading)
+ (@appendix . @appendixsec)
+
+ (@section . @subsection)
+ (@unnumberedsec . @unnumberedsubsec)
+ (@heading . @subheading)
+ (@appendixsec . @appendixsubsec)
+
+ (@subsection . @subsubsection)
+ (@unnumberedsubsec . @unnumberedsubsubsec)
+ (@subheading . @subsubheading)
+ (@appendixsubsec . @appendixsubsubsec)
+
+ (@subsubsection . @subsubsection) ; Cannot go lower.
+ (@unnumberedsubsubsec . @unnumberedsubsubsec)
+ (@subsubheading . @subsubheading)
+ (@appendixsubsubsec . @appendixsubsubsec))
+ "*An alist of next lower levels for chapters, sections. etc.
+For example, chapter to section, section to subsection.
+Used by `texinfo-raise-lower-sections'.
+The keys specify types of section; the values correspond to the next
+lower types.")
+
+
+;;; Perform those texinfo-to-info conversions that apply to the whole input
+;;; uniformly.
+
+(defun texinfo-format-scan ()
+ (texinfo-format-convert (point-min) (point-max))
+ ;; Scan for @-commands.
+ (goto-char (point-min))
+ (while (search-forward "@" nil t)
+ ;;
+ ;; These are the single-character accent commands: @^ @` @' @" @= @~
+ ;; In Info, they are simply quoted and the @ deleted.
+ ;; Other single-character commands:
+ ;; @* forces a line break,
+ ;; @- is a discretionary hyphenation point; does nothing in Info.
+ ;; @<space>, @<tab>, @<newline> each produce a single space,
+ ;; unless followed by a newline.
+ ;;
+ ;; Old version 2.34 expression: (looking-at "[@{}^'` *\"?!]")
+ (if (looking-at "[@{}^'`\"=~ \t\n*?!-]")
+ ;; @*, causes a line break.
+ (cond
+ ;; @*, a line break
+ ((= (following-char) ?*)
+ ;; remove command
+ (delete-region (1- (point)) (1+ (point)))
+ ;; insert return if not at end of line;
+ ;; else line is already broken.
+ (if (not (= (following-char) ?\n))
+ (insert ?\n)))
+ ;; @-, deleted
+ ((= (following-char) ?-)
+ (delete-region (1- (point)) (1+ (point))))
+ ;; @<space>, @<tab>, @<newline>: produce a single space,
+ ;; unless followed by a newline.
+ ((= (following-char) ? )
+ (delete-region (1- (point)) (1+ (point)))
+ ;; insert single space if not at end of line;
+ ;; else line is already broken.
+ (if (not (= (following-char) ?\n))
+ (insert ? )))
+ ((= (following-char) ?\t)
+ (delete-region (1- (point)) (1+ (point)))
+ ;; insert single space if not at end of line;
+ ;; else line is already broken.
+ (if (not (= (following-char) ?\n))
+ (insert ? )))
+ ;; following char is a carriage return
+ ((= (following-char) ?
+)
+ ;; remove command
+ (delete-region (1- (point)) (1+ (point)))
+ ;; insert single space if not at end of line;
+ ;; else line is already broken.
+ (if (not (= (following-char) ?\n))
+ (insert ? )))
+ ;; Otherwise: the other characters are simply quoted. Delete the @.
+ (t
+ (delete-char -1)
+ (forward-char 1)))
+ ;; @ is followed by a command-word; find the end of the word.
+ (setq texinfo-command-start (1- (point)))
+ (if (= (char-syntax (following-char)) ?w)
+ (forward-word 1)
+ (forward-char 1))
+ (setq texinfo-command-end (point))
+ ;; Handle let aliasing
+ (setq texinfo-command-name
+ (let (trial
+ (cmdname
+ (buffer-substring
+ (1+ texinfo-command-start) texinfo-command-end)))
+ (while (setq trial (assoc cmdname texinfo-alias-list))
+ (setq cmdname (cdr trial)))
+ (intern cmdname)))
+ ;; Call the handler for this command.
+ (let ((enclosure-type
+ (assoc
+ (symbol-name texinfo-command-name)
+ texinfo-enclosure-list)))
+ (if enclosure-type
+ (progn
+ (insert
+ (car (car (cdr enclosure-type)))
+ (texinfo-parse-arg-discard)
+ (car (cdr (car (cdr enclosure-type)))))
+ (goto-char texinfo-command-start))
+ (let ((cmd (get texinfo-command-name 'texinfo-format)))
+ (if cmd (funcall cmd) (texinfo-unsupported)))))))
+
+ (cond (texinfo-stack
+ (goto-char (nth 2 (car texinfo-stack)))
+ (error "Unterminated @%s" (car (car texinfo-stack))))))
+
+(put 'begin 'texinfo-format 'texinfo-format-begin)
+(defun texinfo-format-begin ()
+ (texinfo-format-begin-end 'texinfo-format))
+
+(put 'end 'texinfo-format 'texinfo-format-end)
+(defun texinfo-format-end ()
+ (texinfo-format-begin-end 'texinfo-end))
+
+(defun texinfo-format-begin-end (prop)
+ (setq texinfo-command-name (intern (texinfo-parse-line-arg)))
+ (let ((cmd (get texinfo-command-name prop)))
+ (if cmd (funcall cmd)
+ (texinfo-unsupported))))
+
+;;; Parsing functions
+
+(defun texinfo-parse-line-arg ()
+ "Return argument of @-command as string.
+Argument is separated from command either by a space or by a brace.
+If a space, return rest of line, with beginning and ending white
+space removed. If a brace, return string between braces.
+Leave point after argument."
+ (goto-char texinfo-command-end)
+ (let ((start (point)))
+ (cond ((looking-at " ")
+ (skip-chars-forward " ")
+ (setq start (point))
+ (end-of-line)
+ (skip-chars-backward " ")
+ (delete-region (point) (progn (end-of-line) (point)))
+ (setq texinfo-command-end (1+ (point))))
+ ((looking-at "{")
+ (setq start (1+ (point)))
+ (forward-list 1)
+ (setq texinfo-command-end (point))
+ (forward-char -1))
+ (t
+ (error "Invalid texinfo command arg format")))
+ (prog1 (buffer-substring start (point))
+ (if (eolp) (forward-char 1)))))
+
+(defun texinfo-parse-expanded-arg ()
+ (goto-char texinfo-command-end)
+ (let ((start (point))
+ marker)
+ (cond ((looking-at " ")
+ (skip-chars-forward " ")
+ (setq start (point))
+ (end-of-line)
+ (setq texinfo-command-end (1+ (point))))
+ ((looking-at "{")
+ (setq start (1+ (point)))
+ (forward-list 1)
+ (setq texinfo-command-end (point))
+ (forward-char -1))
+ (t
+ (error "Invalid texinfo command arg format")))
+ (setq marker (move-marker (make-marker) texinfo-command-end))
+ (texinfo-format-expand-region start (point))
+ (setq texinfo-command-end (marker-position marker))
+ (move-marker marker nil)
+ (prog1 (buffer-substring start (point))
+ (if (eolp) (forward-char 1)))))
+
+(defun texinfo-format-expand-region (start end)
+ (save-restriction
+ (narrow-to-region start end)
+ (let (texinfo-command-start
+ texinfo-command-end
+ texinfo-command-name
+ texinfo-stack)
+ (texinfo-format-scan))
+ (goto-char (point-max))))
+
+(defun texinfo-parse-arg-discard ()
+ "Delete command and argument; return argument of command."
+ (prog1 (texinfo-parse-line-arg)
+ (texinfo-discard-command)))
+
+(defun texinfo-discard-command ()
+ (delete-region texinfo-command-start texinfo-command-end))
+
+(defun texinfo-optional-braces-discard ()
+ "Discard braces following command, if any."
+ (goto-char texinfo-command-end)
+ (let ((start (point)))
+ (cond ((looking-at "[ \t]*\n")) ; do nothing
+ ((looking-at "{") ; remove braces, if any
+ (forward-list 1)
+ (setq texinfo-command-end (point)))
+ (t
+ (error
+ "Invalid `texinfo-optional-braces-discard' format \(need braces?\)")))
+ (delete-region texinfo-command-start texinfo-command-end)))
+
+(defun texinfo-format-parse-line-args ()
+ (let ((start (1- (point)))
+ next beg end
+ args)
+ (skip-chars-forward " ")
+ (while (not (eolp))
+ (setq beg (point))
+ (re-search-forward "[\n,]")
+ (setq next (point))
+ (if (bolp) (setq next (1- next)))
+ (forward-char -1)
+ (skip-chars-backward " ")
+ (setq end (point))
+ (setq args (cons (if (> end beg) (buffer-substring beg end))
+ args))
+ (goto-char next)
+ (skip-chars-forward " "))
+ (if (eolp) (forward-char 1))
+ (setq texinfo-command-end (point))
+ (nreverse args)))
+
+(defun texinfo-format-parse-args ()
+ (let ((start (1- (point)))
+ next beg end
+ args)
+ (search-forward "{")
+ (save-excursion
+ (texinfo-format-expand-region
+ (point)
+ (save-excursion (up-list 1) (1- (point)))))
+ ;; The following does not handle cross references of the form:
+ ;; `@xref{bullet, , @code{@@bullet}@{@}}.' because the
+ ;; re-search-forward finds the first right brace after the second
+ ;; comma.
+ (while (/= (preceding-char) ?\})
+ (skip-chars-forward " \t\n")
+ (setq beg (point))
+ (re-search-forward "[},]")
+ (setq next (point))
+ (forward-char -1)
+ (skip-chars-backward " \t\n")
+ (setq end (point))
+ (cond ((< beg end)
+ (goto-char beg)
+ (while (search-forward "\n" end t)
+ (replace-match " "))))
+ (setq args (cons (if (> end beg) (buffer-substring beg end))
+ args))
+ (goto-char next))
+ (if (eolp) (forward-char 1))
+ (setq texinfo-command-end (point))
+ (nreverse args)))
+
+(defun texinfo-format-parse-defun-args ()
+ (goto-char texinfo-command-end)
+ (let ((start (point)))
+ (end-of-line)
+ (setq texinfo-command-end (1+ (point)))
+ (let ((marker (move-marker (make-marker) texinfo-command-end)))
+ (texinfo-format-expand-region start (point))
+ (setq texinfo-command-end (marker-position marker))
+ (move-marker marker nil))
+ (goto-char start)
+ (let ((args '())
+ beg end)
+ (skip-chars-forward " ")
+ (while (not (eolp))
+ (cond ((looking-at "{")
+ (setq beg (1+ (point)))
+ (forward-list 1)
+ (setq end (1- (point))))
+ (t
+ (setq beg (point))
+ (re-search-forward "[\n ]")
+ (forward-char -1)
+ (setq end (point))))
+ (setq args (cons (buffer-substring beg end) args))
+ (skip-chars-forward " "))
+ (forward-char 1)
+ (nreverse args))))
+
+(defun texinfo-discard-line ()
+ (goto-char texinfo-command-end)
+ (skip-chars-forward " \t")
+ (or (eolp)
+ (error "Extraneous text at end of command line."))
+ (goto-char texinfo-command-start)
+ (or (bolp)
+ (error "Extraneous text at beginning of command line."))
+ (delete-region (point) (progn (forward-line 1) (point))))
+
+(defun texinfo-discard-line-with-args ()
+ (goto-char texinfo-command-start)
+ (delete-region (point) (progn (forward-line 1) (point))))
+
+
+;;; @setfilename
+
+;; Only `texinfo-format-buffer' handles @setfilename with this
+;; definition; `texinfo-format-region' handles @setfilename, if any,
+;; specially.
+(put 'setfilename 'texinfo-format 'texinfo-format-setfilename)
+(defun texinfo-format-setfilename ()
+ (let ((arg (texinfo-parse-arg-discard)))
+ (message "Formatting Info file: %s" arg)
+ (setq texinfo-format-filename
+ (file-name-nondirectory (expand-file-name arg)))
+ (insert "Info file: "
+ texinfo-format-filename ", -*-Text-*-\n"
+ ;; Date string removed so that regression testing is easier.
+ ;; "produced on "
+ ;; (substring (current-time-string) 8 10) " "
+ ;; (substring (current-time-string) 4 7) " "
+ ;; (substring (current-time-string) -4) " "
+ "produced by `texinfo-format-buffer'\n"
+ "from file"
+ (if (buffer-file-name input-buffer)
+ (concat " `"
+ (file-name-sans-versions
+ (file-name-nondirectory
+ (buffer-file-name input-buffer)))
+ "'")
+ (concat "buffer `" (buffer-name input-buffer) "'"))
+ "\nusing `texinfmt.el' version "
+ texinfmt-version
+ ".\n\n")))
+
+;;; @node, @menu, @detailmenu
+
+(put 'node 'texinfo-format 'texinfo-format-node)
+(put 'nwnode 'texinfo-format 'texinfo-format-node)
+(defun texinfo-format-node ()
+ (let* ((args (texinfo-format-parse-line-args))
+ (name (nth 0 args))
+ (next (nth 1 args))
+ (prev (nth 2 args))
+ (up (nth 3 args)))
+ (texinfo-discard-command)
+ (setq texinfo-last-node name)
+ (let ((tem (downcase name)))
+ (if (assoc tem texinfo-node-names)
+ (error "Duplicate node name: %s" name)
+ (setq texinfo-node-names (cons (list tem) texinfo-node-names))))
+ (setq texinfo-footnote-number 0)
+ ;; insert "\n\^_" unconditionally since this is what info is looking for
+ (insert "\n\^_\nFile: " texinfo-format-filename
+ ", Node: " name)
+ (if next
+ (insert ", Next: " next))
+ (if prev
+ (insert ", Prev: " prev))
+ (if up
+ (insert ", Up: " up))
+ (insert ?\n)
+ (setq texinfo-last-node-pos (point))))
+
+(put 'menu 'texinfo-format 'texinfo-format-menu)
+(defun texinfo-format-menu ()
+ (texinfo-discard-line)
+ (insert "* Menu:\n\n"))
+
+(put 'menu 'texinfo-end 'texinfo-discard-command)
+
+;; The @detailmenu should be removed eventually.
+
+;; According to Karl Berry, 31 August 1996:
+;;
+;; You don't like, I don't like it. I agree, it would be better just to
+;; fix the bug [in `makeinfo']. .. At this point, since inserting those
+;; two commands in the Elisp fn is trivial, I don't especially want to
+;; expend more effort...
+;;
+;; I added a couple sentences of documentation to the manual (putting the
+;; blame on makeinfo where it belongs :-().
+
+(put 'detailmenu 'texinfo-format 'texinfo-discard-line)
+(put 'detailmenu 'texinfo-end 'texinfo-discard-command)
+
+;; (Also see `texnfo-upd.el')
+
+
+;;; Cross references
+
+;; @xref {NODE, FNAME, NAME, FILE, DOCUMENT}
+;; -> *Note FNAME: (FILE)NODE
+;; If FILE is missing,
+;; *Note FNAME: NODE
+;; If FNAME is empty and NAME is present
+;; *Note NAME: Node
+;; If both NAME and FNAME are missing
+;; *Note NODE::
+;; texinfo ignores the DOCUMENT argument.
+;; -> See section <xref to NODE> [NAME, else NODE], page <xref to NODE>
+;; If FILE is specified, (FILE)NODE is used for xrefs.
+;; If fifth argument DOCUMENT is specified, produces
+;; See section <xref to NODE> [NAME, else NODE], page <xref to NODE>
+;; of DOCUMENT
+
+;; @ref a reference that does not put `See' or `see' in
+;; the hardcopy and is the same as @xref in Info
+(put 'ref 'texinfo-format 'texinfo-format-xref)
+
+(put 'xref 'texinfo-format 'texinfo-format-xref)
+(defun texinfo-format-xref ()
+ (let ((args (texinfo-format-parse-args)))
+ (texinfo-discard-command)
+ (insert "*Note ")
+ (let ((fname (or (nth 1 args) (nth 2 args))))
+ (if (null (or fname (nth 3 args)))
+ (insert (car args) "::")
+ (insert (or fname (car args)) ": ")
+ (if (nth 3 args)
+ (insert "(" (nth 3 args) ")"))
+ (insert (car args))))))
+
+(put 'pxref 'texinfo-format 'texinfo-format-pxref)
+(defun texinfo-format-pxref ()
+ (texinfo-format-xref)
+ (or (save-excursion
+ (forward-char -2)
+ (looking-at "::"))
+ (insert ".")))
+
+;; @inforef{NODE, FNAME, FILE}
+;; Like @xref{NODE, FNAME,,FILE} in texinfo.
+;; In Tex, generates "See Info file FILE, node NODE"
+(put 'inforef 'texinfo-format 'texinfo-format-inforef)
+(defun texinfo-format-inforef ()
+ (let ((args (texinfo-format-parse-args)))
+ (texinfo-discard-command)
+ (if (nth 1 args)
+ (insert "*Note " (nth 1 args) ": (" (nth 2 args) ")" (car args))
+ (insert "*Note " "(" (nth 2 args) ")" (car args) "::"))))
+
+
+;;; Section headings
+
+(put 'majorheading 'texinfo-format 'texinfo-format-chapter)
+(put 'chapheading 'texinfo-format 'texinfo-format-chapter)
+(put 'ichapter 'texinfo-format 'texinfo-format-chapter)
+(put 'chapter 'texinfo-format 'texinfo-format-chapter)
+(put 'iappendix 'texinfo-format 'texinfo-format-chapter)
+(put 'appendix 'texinfo-format 'texinfo-format-chapter)
+(put 'iunnumbered 'texinfo-format 'texinfo-format-chapter)
+(put 'top 'texinfo-format 'texinfo-format-chapter)
+(put 'unnumbered 'texinfo-format 'texinfo-format-chapter)
+(put 'centerchap 'texinfo-format 'texinfo-format-chapter)
+(defun texinfo-format-chapter ()
+ (texinfo-format-chapter-1 ?*))
+
+(put 'heading 'texinfo-format 'texinfo-format-section)
+(put 'isection 'texinfo-format 'texinfo-format-section)
+(put 'section 'texinfo-format 'texinfo-format-section)
+(put 'iappendixsection 'texinfo-format 'texinfo-format-section)
+(put 'appendixsection 'texinfo-format 'texinfo-format-section)
+(put 'iappendixsec 'texinfo-format 'texinfo-format-section)
+(put 'appendixsec 'texinfo-format 'texinfo-format-section)
+(put 'iunnumberedsec 'texinfo-format 'texinfo-format-section)
+(put 'unnumberedsec 'texinfo-format 'texinfo-format-section)
+(defun texinfo-format-section ()
+ (texinfo-format-chapter-1 ?=))
+
+(put 'subheading 'texinfo-format 'texinfo-format-subsection)
+(put 'isubsection 'texinfo-format 'texinfo-format-subsection)
+(put 'subsection 'texinfo-format 'texinfo-format-subsection)
+(put 'iappendixsubsec 'texinfo-format 'texinfo-format-subsection)
+(put 'appendixsubsec 'texinfo-format 'texinfo-format-subsection)
+(put 'iunnumberedsubsec 'texinfo-format 'texinfo-format-subsection)
+(put 'unnumberedsubsec 'texinfo-format 'texinfo-format-subsection)
+(defun texinfo-format-subsection ()
+ (texinfo-format-chapter-1 ?-))
+
+(put 'subsubheading 'texinfo-format 'texinfo-format-subsubsection)
+(put 'isubsubsection 'texinfo-format 'texinfo-format-subsubsection)
+(put 'subsubsection 'texinfo-format 'texinfo-format-subsubsection)
+(put 'iappendixsubsubsec 'texinfo-format 'texinfo-format-subsubsection)
+(put 'appendixsubsubsec 'texinfo-format 'texinfo-format-subsubsection)
+(put 'iunnumberedsubsubsec 'texinfo-format 'texinfo-format-subsubsection)
+(put 'unnumberedsubsubsec 'texinfo-format 'texinfo-format-subsubsection)
+(defun texinfo-format-subsubsection ()
+ (texinfo-format-chapter-1 ?.))
+
+(defun texinfo-format-chapter-1 (belowchar)
+ (let ((arg (texinfo-parse-arg-discard)))
+ (message "Formatting: %s ... " arg) ; So we can see where we are.
+ (insert ?\n arg ?\n "@SectionPAD " belowchar ?\n)
+ (forward-line -2)))
+
+(put 'SectionPAD 'texinfo-format 'texinfo-format-sectionpad)
+(defun texinfo-format-sectionpad ()
+ (let ((str (texinfo-parse-arg-discard)))
+ (forward-char -1)
+ (let ((column (current-column)))
+ (forward-char 1)
+ (while (> column 0)
+ (insert str)
+ (setq column (1- column))))
+ (insert ?\n)))
+
+
+;;; Space controlling commands: @. and @:, and the soft hyphen.
+
+(put '\. 'texinfo-format 'texinfo-format-\.)
+(defun texinfo-format-\. ()
+ (texinfo-discard-command)
+ (insert "."))
+
+(put '\: 'texinfo-format 'texinfo-format-\:)
+(defun texinfo-format-\: ()
+ (texinfo-discard-command))
+
+(put '\- 'texinfo-format 'texinfo-format-soft-hyphen)
+(defun texinfo-format-soft-hyphen ()
+ (texinfo-discard-command))
+
+
+;;; @center, @sp, and @br
+
+(put 'center 'texinfo-format 'texinfo-format-center)
+(defun texinfo-format-center ()
+ (let ((arg (texinfo-parse-expanded-arg)))
+ (texinfo-discard-command)
+ (insert arg)
+ (insert ?\n)
+ (save-restriction
+ (goto-char (1- (point)))
+ (let ((indent-tabs-mode nil))
+ (center-line)))))
+
+(put 'sp 'texinfo-format 'texinfo-format-sp)
+(defun texinfo-format-sp ()
+ (let* ((arg (texinfo-parse-arg-discard))
+ (num (read arg)))
+ (insert-char ?\n num)))
+
+(put 'br 'texinfo-format 'texinfo-format-paragraph-break)
+(defun texinfo-format-paragraph-break ()
+ "Force a paragraph break.
+If used within a line, follow `@br' with braces."
+ (texinfo-optional-braces-discard)
+ ;; insert one return if at end of line;
+ ;; else insert two returns, to generate a blank line.
+ (if (= (following-char) ?\n)
+ (insert ?\n)
+ (insert-char ?\n 2)))
+
+
+;;; @footnote and @footnotestyle
+
+;; In Texinfo, footnotes are created with the `@footnote' command.
+;; This command is followed immediately by a left brace, then by the text of
+;; the footnote, and then by a terminating right brace. The
+;; template for a footnote is:
+;;
+;; @footnote{TEXT}
+;;
+;; Info has two footnote styles:
+;;
+;; * In the End of node style, all the footnotes for a single node
+;; are placed at the end of that node. The footnotes are
+;; separated from the rest of the node by a line of dashes with
+;; the word `Footnotes' within it.
+;;
+;; * In the Separate node style, all the footnotes for a single node
+;; are placed in an automatically constructed node of their own.
+
+;; Footnote style is specified by the @footnotestyle command, either
+;; @footnotestyle separate
+;; or
+;; @footnotestyle end
+;;
+;; The default is separate
+
+(defvar texinfo-footnote-style "separate"
+ "Footnote style, either separate or end.")
+
+(put 'footnotestyle 'texinfo-format 'texinfo-footnotestyle)
+(defun texinfo-footnotestyle ()
+ "Specify whether footnotes are at end of node or in separate nodes.
+Argument is either end or separate."
+ (setq texinfo-footnote-style (texinfo-parse-arg-discard)))
+
+(defvar texinfo-footnote-number)
+
+(put 'footnote 'texinfo-format 'texinfo-format-footnote)
+(defun texinfo-format-footnote ()
+ "Format a footnote in either end of node or separate node style.
+The texinfo-footnote-style variable controls which style is used."
+ (setq texinfo-footnote-number (1+ texinfo-footnote-number))
+ (cond ((string= texinfo-footnote-style "end")
+ (texinfo-format-end-node))
+ ((string= texinfo-footnote-style "separate")
+ (texinfo-format-separate-node))))
+
+(defun texinfo-format-separate-node ()
+ "Format footnote in Separate node style, with notes in own node.
+The node is constructed automatically."
+ (let* (start
+ (arg (texinfo-parse-line-arg))
+ (node-name-beginning
+ (save-excursion
+ (re-search-backward
+ "^File: \\w+\\(\\w\\|\\s_\\|\\.\\|,\\)*[ \t]+Node:")
+ (match-end 0)))
+ (node-name
+ (save-excursion
+ (buffer-substring
+ (progn (goto-char node-name-beginning) ; skip over node command
+ (skip-chars-forward " \t") ; and over spaces
+ (point))
+ (if (search-forward
+ ","
+ (save-excursion (end-of-line) (point)) t) ; bound search
+ (1- (point))
+ (end-of-line) (point))))))
+ (texinfo-discard-command) ; remove or insert whitespace, as needed
+ (delete-region (save-excursion (skip-chars-backward " \t\n") (point))
+ (point))
+ (insert (format " (%d) (*Note %s-Footnotes::)"
+ texinfo-footnote-number node-name))
+ (fill-paragraph nil)
+ (save-excursion
+ (if (re-search-forward "^@node" nil 'move)
+ (forward-line -1))
+
+ ;; two cases: for the first footnote, we must insert a node header;
+ ;; for the second and subsequent footnotes, we need only insert
+ ;; the text of the footnote.
+
+ (if (save-excursion
+ (re-search-backward
+ (concat node-name "-Footnotes, Up: ")
+ node-name-beginning
+ t))
+ (progn ; already at least one footnote
+ (setq start (point))
+ (insert (format "\n(%d) %s\n" texinfo-footnote-number arg))
+ (fill-region start (point)))
+ ;; else not yet a footnote
+ (insert "\n\^_\nFile: " texinfo-format-filename
+ " Node: " node-name "-Footnotes, Up: " node-name "\n")
+ (setq start (point))
+ (insert (format "\n(%d) %s\n" texinfo-footnote-number arg))
+ (fill-region start (point))))))
+
+(defun texinfo-format-end-node ()
+ "Format footnote in the End of node style, with notes at end of node."
+ (let (start
+ (arg (texinfo-parse-line-arg)))
+ (texinfo-discard-command) ; remove or insert whitespace, as needed
+ (delete-region (save-excursion (skip-chars-backward " \t\n") (point))
+ (point))
+ (insert (format " (%d) " texinfo-footnote-number))
+ (fill-paragraph nil)
+ (save-excursion
+ (if (search-forward "\n--------- Footnotes ---------\n" nil t)
+ (progn ; already have footnote, put new one before end of node
+ (if (re-search-forward "^@node" nil 'move)
+ (forward-line -1))
+ (setq start (point))
+ (insert (format "\n(%d) %s\n" texinfo-footnote-number arg))
+ (fill-region start (point)))
+ ;; else no prior footnote
+ (if (re-search-forward "^@node" nil 'move)
+ (forward-line -1))
+ (insert "\n--------- Footnotes ---------\n")
+ (setq start (point))
+ (insert (format "\n(%d) %s\n" texinfo-footnote-number arg))))))
+
+
+;;; @itemize, @enumerate, and similar commands
+
+;; @itemize pushes (itemize "COMMANDS" STARTPOS) on texinfo-stack.
+;; @enumerate pushes (enumerate 0 STARTPOS).
+;; @item dispatches to the texinfo-item prop of the first elt of the list.
+;; For itemize, this puts in and rescans the COMMANDS.
+;; For enumerate, this increments the number and puts it in.
+;; In either case, it puts a Backspace at the front of the line
+;; which marks it not to be indented later.
+;; All other lines get indented by 5 when the @end is reached.
+
+(defvar texinfo-stack-depth 0
+ "Count of number of unpopped texinfo-push-stack calls.
+Used by @refill indenting command to avoid indenting within lists, etc.")
+
+(defun texinfo-push-stack (check arg)
+ (setq texinfo-stack-depth (1+ texinfo-stack-depth))
+ (setq texinfo-stack
+ (cons (list check arg texinfo-command-start)
+ texinfo-stack)))
+
+(defun texinfo-pop-stack (check)
+ (setq texinfo-stack-depth (1- texinfo-stack-depth))
+ (if (null texinfo-stack)
+ (error "Unmatched @end %s" check))
+ (if (not (eq (car (car texinfo-stack)) check))
+ (error "@end %s matches @%s"
+ check (car (car texinfo-stack))))
+ (prog1 (cdr (car texinfo-stack))
+ (setq texinfo-stack (cdr texinfo-stack))))
+
+(put 'itemize 'texinfo-format 'texinfo-itemize)
+(defun texinfo-itemize ()
+ (texinfo-push-stack
+ 'itemize
+ (progn (skip-chars-forward " \t")
+ (if (eolp)
+ "@bullet"
+ (texinfo-parse-line-arg))))
+ (texinfo-discard-line-with-args)
+ (setq fill-column (- fill-column 5)))
+
+(put 'itemize 'texinfo-end 'texinfo-end-itemize)
+(defun texinfo-end-itemize ()
+ (setq fill-column (+ fill-column 5))
+ (texinfo-discard-command)
+ (let ((stacktop
+ (texinfo-pop-stack 'itemize)))
+ (texinfo-do-itemize (nth 1 stacktop))))
+
+(put 'enumerate 'texinfo-format 'texinfo-enumerate)
+(defun texinfo-enumerate ()
+ (texinfo-push-stack
+ 'enumerate
+ (progn (skip-chars-forward " \t")
+ (if (eolp)
+ 1
+ (read (current-buffer)))))
+ (if (and (symbolp (car (cdr (car texinfo-stack))))
+ (> 1 (length (symbol-name (car (cdr (car texinfo-stack)))))))
+ (error
+ "@enumerate: Use a number or letter, eg: 1, A, a, 3, B, or d." ))
+ (texinfo-discard-line-with-args)
+ (setq fill-column (- fill-column 5)))
+
+(put 'enumerate 'texinfo-end 'texinfo-end-enumerate)
+(defun texinfo-end-enumerate ()
+ (setq fill-column (+ fill-column 5))
+ (texinfo-discard-command)
+ (let ((stacktop
+ (texinfo-pop-stack 'enumerate)))
+ (texinfo-do-itemize (nth 1 stacktop))))
+
+;; @alphaenumerate never became a standard part of Texinfo
+(put 'alphaenumerate 'texinfo-format 'texinfo-alphaenumerate)
+(defun texinfo-alphaenumerate ()
+ (texinfo-push-stack 'alphaenumerate (1- ?a))
+ (setq fill-column (- fill-column 5))
+ (texinfo-discard-line))
+
+(put 'alphaenumerate 'texinfo-end 'texinfo-end-alphaenumerate)
+(defun texinfo-end-alphaenumerate ()
+ (setq fill-column (+ fill-column 5))
+ (texinfo-discard-command)
+ (let ((stacktop
+ (texinfo-pop-stack 'alphaenumerate)))
+ (texinfo-do-itemize (nth 1 stacktop))))
+
+;; @capsenumerate never became a standard part of Texinfo
+(put 'capsenumerate 'texinfo-format 'texinfo-capsenumerate)
+(defun texinfo-capsenumerate ()
+ (texinfo-push-stack 'capsenumerate (1- ?A))
+ (setq fill-column (- fill-column 5))
+ (texinfo-discard-line))
+
+(put 'capsenumerate 'texinfo-end 'texinfo-end-capsenumerate)
+(defun texinfo-end-capsenumerate ()
+ (setq fill-column (+ fill-column 5))
+ (texinfo-discard-command)
+ (let ((stacktop
+ (texinfo-pop-stack 'capsenumerate)))
+ (texinfo-do-itemize (nth 1 stacktop))))
+
+;; At the @end, indent all the lines within the construct
+;; except those marked with backspace. FROM says where
+;; construct started.
+(defun texinfo-do-itemize (from)
+ (save-excursion
+ (while (progn (forward-line -1)
+ (>= (point) from))
+ (if (= (following-char) ?\b)
+ (save-excursion
+ (delete-char 1)
+ (end-of-line)
+ (delete-char 6))
+ (if (not (looking-at "[ \t]*$"))
+ (save-excursion (insert " ")))))))
+
+(put 'item 'texinfo-format 'texinfo-item)
+(put 'itemx 'texinfo-format 'texinfo-item)
+(defun texinfo-item ()
+ (funcall (get (car (car texinfo-stack)) 'texinfo-item)))
+
+(put 'itemize 'texinfo-item 'texinfo-itemize-item)
+(defun texinfo-itemize-item ()
+ ;; (texinfo-discard-line) ; Did not handle text on same line as @item.
+ (delete-region (1+ (point)) (save-excursion (beginning-of-line) (point)))
+ (if (looking-at "[ \t]*[^ \t\n]+")
+ ;; Text on same line as @item command.
+ (insert "\b " (nth 1 (car texinfo-stack)) " \n")
+ ;; Else text on next line.
+ (insert "\b " (nth 1 (car texinfo-stack)) " "))
+ (forward-line -1))
+
+(put 'enumerate 'texinfo-item 'texinfo-enumerate-item)
+(defun texinfo-enumerate-item ()
+ (texinfo-discard-line)
+ (let (enumerating-symbol)
+ (cond ((integerp (car (cdr (car texinfo-stack))))
+ (setq enumerating-symbol (car (cdr (car texinfo-stack))))
+ (insert ?\b (format "%3d. " enumerating-symbol) ?\n)
+ (setcar (cdr (car texinfo-stack)) (1+ enumerating-symbol)))
+ ((symbolp (car (cdr (car texinfo-stack))))
+ (setq enumerating-symbol
+ (symbol-name (car (cdr (car texinfo-stack)))))
+ (if (or (equal ?\[ (string-to-char enumerating-symbol))
+ (equal ?\{ (string-to-char enumerating-symbol)))
+ (error
+ "Too many items in enumerated list; alphabet ends at Z."))
+ (insert ?\b (format "%3s. " enumerating-symbol) ?\n)
+ (setcar (cdr (car texinfo-stack))
+ (make-symbol
+ (char-to-string
+ (1+
+ (string-to-char enumerating-symbol))))))
+ (t
+ (error
+ "@enumerate: Use a number or letter, eg: 1, A, a, 3, B or d." )))
+ (forward-line -1)))
+
+(put 'alphaenumerate 'texinfo-item 'texinfo-alphaenumerate-item)
+(defun texinfo-alphaenumerate-item ()
+ (texinfo-discard-line)
+ (let ((next (1+ (car (cdr (car texinfo-stack))))))
+ (if (> next ?z)
+ (error "More than 26 items in @alphaenumerate; get a bigger alphabet."))
+ (setcar (cdr (car texinfo-stack)) next)
+ (insert "\b " next ". \n"))
+ (forward-line -1))
+
+(put 'capsenumerate 'texinfo-item 'texinfo-capsenumerate-item)
+(defun texinfo-capsenumerate-item ()
+ (texinfo-discard-line)
+ (let ((next (1+ (car (cdr (car texinfo-stack))))))
+ (if (> next ?Z)
+ (error "More than 26 items in @capsenumerate; get a bigger alphabet."))
+ (setcar (cdr (car texinfo-stack)) next)
+ (insert "\b " next ". \n"))
+ (forward-line -1))
+
+
+;;; @table
+
+;; The `@table' command produces two-column tables.
+
+(put 'table 'texinfo-format 'texinfo-table)
+(defun texinfo-table ()
+ (texinfo-push-stack
+ 'table
+ (progn (skip-chars-forward " \t")
+ (if (eolp)
+ "@asis"
+ (texinfo-parse-line-arg))))
+ (texinfo-discard-line-with-args)
+ (setq fill-column (- fill-column 5)))
+
+(put 'table 'texinfo-item 'texinfo-table-item)
+(defun texinfo-table-item ()
+ (let ((arg (texinfo-parse-arg-discard))
+ (itemfont (car (cdr (car texinfo-stack)))))
+ (insert ?\b itemfont ?\{ arg "}\n \n"))
+ (forward-line -2))
+
+(put 'table 'texinfo-end 'texinfo-end-table)
+(defun texinfo-end-table ()
+ (setq fill-column (+ fill-column 5))
+ (texinfo-discard-command)
+ (let ((stacktop
+ (texinfo-pop-stack 'table)))
+ (texinfo-do-itemize (nth 1 stacktop))))
+
+;; @description appears to be an undocumented variant on @table that
+;; does not require an arg. It fails in texinfo.tex 2.58 and is not
+;; part of makeinfo.c The command appears to be a relic of the past.
+(put 'description 'texinfo-end 'texinfo-end-table)
+(put 'description 'texinfo-format 'texinfo-description)
+(defun texinfo-description ()
+ (texinfo-push-stack 'table "@asis")
+ (setq fill-column (- fill-column 5))
+ (texinfo-discard-line))
+
+
+;;; @ftable, @vtable
+
+;; The `@ftable' and `@vtable' commands are like the `@table' command
+;; but they also insert each entry in the first column of the table
+;; into the function or variable index.
+
+;; Handle the @ftable and @vtable commands:
+
+(put 'ftable 'texinfo-format 'texinfo-ftable)
+(put 'vtable 'texinfo-format 'texinfo-vtable)
+
+(defun texinfo-ftable () (texinfo-indextable 'ftable))
+(defun texinfo-vtable () (texinfo-indextable 'vtable))
+
+(defun texinfo-indextable (table-type)
+ (texinfo-push-stack table-type (texinfo-parse-arg-discard))
+ (setq fill-column (- fill-column 5)))
+
+;; Handle the @item commands within ftable and vtable:
+
+(put 'ftable 'texinfo-item 'texinfo-ftable-item)
+(put 'vtable 'texinfo-item 'texinfo-vtable-item)
+
+(defun texinfo-ftable-item () (texinfo-indextable-item 'texinfo-findex))
+(defun texinfo-vtable-item () (texinfo-indextable-item 'texinfo-vindex))
+
+(defun texinfo-indextable-item (index-type)
+ (let ((item (texinfo-parse-arg-discard))
+ (itemfont (car (cdr (car texinfo-stack))))
+ (indexvar index-type))
+ (insert ?\b itemfont ?\{ item "}\n \n")
+ (set indexvar
+ (cons
+ (list item texinfo-last-node)
+ (symbol-value indexvar)))
+ (forward-line -2)))
+
+;; Handle @end ftable, @end vtable
+
+(put 'ftable 'texinfo-end 'texinfo-end-ftable)
+(put 'vtable 'texinfo-end 'texinfo-end-vtable)
+
+(defun texinfo-end-ftable () (texinfo-end-indextable 'ftable))
+(defun texinfo-end-vtable () (texinfo-end-indextable 'vtable))
+
+(defun texinfo-end-indextable (table-type)
+ (setq fill-column (+ fill-column 5))
+ (texinfo-discard-command)
+ (let ((stacktop
+ (texinfo-pop-stack table-type)))
+ (texinfo-do-itemize (nth 1 stacktop))))
+
+
+;;; @multitable ... @end multitable
+
+;; Produce a multi-column table, with as many columns as desired.
+;;
+;; A multi-column table has this template:
+;;
+;; @multitable {A1} {A2} {A3}
+;; @item A1 @tab A2 @tab A3
+;; @item B1 @tab B2 @tab B3
+;; @item C1 @tab C2 @tab C3
+;; @end multitable
+;;
+;; where the width of the text in brackets specifies the width of the
+;; respective column.
+;;
+;; Or else:
+;;
+;; @multitable @columnfractions .25 .3 .45
+;; @item A1 @tab A2 @tab A3
+;; @item B1 @tab B2 @tab B3
+;; @end multitable
+;;
+;; where the fractions specify the width of each column as a percent
+;; of the current width of the text (i.e., of the fill-column).
+;;
+;; Long lines of text are filled within columns.
+;;
+;; Using the Emacs Lisp formatter, texinfmt.el,
+;; the whitespace between columns can be increased by setting
+;; `extra-inter-column-width' to a value greater than 0. By default,
+;; there is at least one blank space between columns.
+;;
+;; The Emacs Lisp formatter, texinfmt.el, ignores the following four
+;; commands that are defined in texinfo.tex for printed output.
+;;
+;; @multitableparskip,
+;; @multitableparindent,
+;; @multitablecolmargin,
+;; @multitablelinespace.
+
+;; How @multitable works.
+;; =====================
+;;
+;; `texinfo-multitable' reads the @multitable line and determines from it
+;; how wide each column should be.
+;;
+;; Also, it pushes this information, along with an identifying symbol,
+;; onto the `texinfo-stack'. At the @end multitable command, the stack
+;; is checked for its matching @multitable command, and then popped, or
+;; else an error is signaled. Also, this command pushes the location of
+;; the start of the table onto the stack.
+;;
+;; `texinfo-end-multitable' checks the `texinfo-stack' that the @end
+;; multitable truly is ending a corresponding beginning, and if it is,
+;; pops the stack.
+;;
+;; `texinfo-multitable-widths' is called by `texinfo-multitable'.
+;; The function returns a list of the widths of each column in a
+;; multi-column table, based on the information supplied by the arguments
+;; to the @multitable command (by arguments, I mean the text on the rest
+;; of the @multitable line, not the remainder of the multi-column table
+;; environment).
+;;
+;; `texinfo-multitable-item' formats a row within a multicolumn table.
+;; This command is executed when texinfmt sees @item inside @multitable.
+;; Cells in row are separated by `@tab's. Widths of cells are specified
+;; by the arguments in the @multitable line. Cells are filled. All cells
+;; are made to be the same height by padding their bottoms, as needed,
+;; with blanks.
+;;
+;; `texinfo-multitable-extract-row' is called by `texinfo-multitable-item'.
+;; This function returns the text in a multitable row, as a string.
+;; The start of a row is marked by an @item and the end of row is the
+;; beginning of next @item or beginning of the @end multitable line.
+;; Cells within a row are separated by @tab.
+;;
+;; Note that @tab, the cell separators, are not treated as independent
+;; Texinfo commands.
+
+(defvar extra-inter-column-width 0
+"*Insert NUMBER of additional columns of whitespace between entries of
+a multi-column table.")
+
+(defvar multitable-temp-buffer-name "*multitable-temporary-buffer*")
+(defvar multitable-temp-rectangle-name "texinfo-multitable-temp-")
+
+;; These commands are defined in texinfo.tex for printed output.
+(put 'multitableparskip 'texinfo-format 'texinfo-discard-line-with-args)
+(put 'multitableparindent 'texinfo-format 'texinfo-discard-line-with-args)
+(put 'multitablecolmargin 'texinfo-format 'texinfo-discard-line-with-args)
+(put 'multitablelinespace 'texinfo-format 'texinfo-discard-line-with-args)
+
+(put 'multitable 'texinfo-format 'texinfo-multitable)
+(defun texinfo-multitable ()
+ "Produce multi-column tables.
+
+A multi-column table has this template:
+
+ @multitable {A1} {A2} {A3}
+ @item A1 @tab A2 @tab A3
+ @item B1 @tab B2 @tab B3
+ @item C1 @tab C2 @tab C3
+ @end multitable
+
+where the width of the text in brackets specifies the width of the
+respective column.
+
+Or else:
+
+ @multitable @columnfractions .25 .3 .45
+ @item A1 @tab A2 @tab A3
+ @item B1 @tab B2 @tab B3
+ @end multitable
+
+where the fractions specify the width of each column as a percent
+of the current width of the text (i.e., of the fill-column).
+
+Long lines of text are filled within columns.
+
+Using the Emacs Lisp formatter, texinfmt.el,
+the whitespace between columns can be increased by setting
+`extra-inter-column-width' to a value greater than 0. By default,
+there is at least one blank space between columns.
+
+The Emacs Lisp formatter, texinfmt.el, ignores the following four
+commands that are defined in texinfo.tex for printed output.
+
+ @multitableparskip,
+ @multitableparindent,
+ @multitablecolmargin,
+ @multitablelinespace."
+
+;; This function pushes information onto the `texinfo-stack'.
+;; A stack element consists of:
+;; - type-of-command, i.e., multitable
+;; - the information about column widths, and
+;; - the position of texinfo-command-start.
+;; e.g., ('multitable (1 2 3 4) 123)
+;; The command line is then deleted.
+ (texinfo-push-stack
+ 'multitable
+ ;; push width information on stack
+ (texinfo-multitable-widths))
+ (texinfo-discard-line-with-args))
+
+(put 'multitable 'texinfo-end 'texinfo-end-multitable)
+(defun texinfo-end-multitable ()
+ "Discard the @end multitable line and pop the stack of multitable."
+ (texinfo-discard-command)
+ (texinfo-pop-stack 'multitable))
+
+(defun texinfo-multitable-widths ()
+ "Return list of widths of each column in a multi-column table."
+ (let (texinfo-multitable-width-list)
+ ;; Fractions format:
+ ;; @multitable @columnfractions .25 .3 .45
+ ;;
+ ;; Template format:
+ ;; @multitable {Column 1 template} {Column 2} {Column 3 example}
+ ;; Place point before first argument
+ (skip-chars-forward " \t")
+ (cond
+ ;; Check for common misspelling
+ ((looking-at "@columnfraction ")
+ (error "In @multitable, @columnfractions misspelled"))
+ ;; Case 1: @columnfractions .25 .3 .45
+ ((looking-at "@columnfractions")
+ (forward-word 1)
+ (while (not (eolp))
+ (setq texinfo-multitable-width-list
+ (cons
+ (truncate
+ (1-
+ (* fill-column (read (get-buffer (current-buffer))))))
+ texinfo-multitable-width-list))))
+ ;;
+ ;; Case 2: {Column 1 template} {Column 2} {Column 3 example}
+ ((looking-at "{")
+ (let ((start-of-templates (point)))
+ (while (not (eolp))
+ (skip-chars-forward " \t")
+ (let* ((start-of-template (1+ (point)))
+ (end-of-template
+ ;; forward-sexp works with braces in Texinfo mode
+ (progn (forward-sexp 1) (1- (point)))))
+ (setq texinfo-multitable-width-list
+ (cons (- end-of-template start-of-template)
+ texinfo-multitable-width-list))
+ ;; Remove carriage return from within a template, if any.
+ ;; This helps those those who want to use more than
+ ;; one line's worth of words in @multitable line.
+ (narrow-to-region start-of-template end-of-template)
+ (goto-char (point-min))
+ (while (search-forward "
+" nil t)
+ (delete-char -1))
+ (goto-char (point-max))
+ (widen)
+ (forward-char 1)))))
+ ;;
+ ;; Case 3: Trouble
+ (t
+ (error
+ "You probably need to specify column widths for @multitable correctly.")))
+ ;; Check whether columns fit on page.
+ (let ((desired-columns
+ (+
+ ;; between column spaces
+ (length texinfo-multitable-width-list)
+ ;; additional between column spaces, if any
+ extra-inter-column-width
+ ;; sum of spaces for each entry
+ (apply '+ texinfo-multitable-width-list))))
+ (if (> desired-columns fill-column)
+ (error
+ (format
+ "Multi-column table width, %d chars, is greater than page width, %d chars."
+ desired-columns fill-column))))
+ texinfo-multitable-width-list))
+
+;; @item A1 @tab A2 @tab A3
+(defun texinfo-multitable-extract-row ()
+ "Return multitable row, as a string.
+End of row is beginning of next @item or beginning of @end.
+Cells within rows are separated by @tab."
+ (skip-chars-forward " \t")
+ (let* ((start (point))
+ (end (progn
+ (re-search-forward "@item\\|@end")
+ (match-beginning 0)))
+ (row (progn (goto-char end)
+ (skip-chars-backward " ")
+ ;; remove whitespace at end of argument
+ (delete-region (point) end)
+ (buffer-substring start (point)))))
+ (delete-region texinfo-command-start end)
+ row))
+
+(put 'multitable 'texinfo-item 'texinfo-multitable-item)
+(defun texinfo-multitable-item ()
+ "Format a row within a multicolumn table.
+Cells in row are separated by @tab.
+Widths of cells are specified by the arguments in the @multitable line.
+All cells are made to be the same height.
+This command is executed when texinfmt sees @item inside @multitable."
+ (let ((original-buffer (current-buffer))
+ (table-widths (reverse (car (cdr (car texinfo-stack)))))
+ (existing-fill-column fill-column)
+ start
+ end
+ (table-column 0)
+ (table-entry-height 0)
+ ;; unformatted row looks like: A1 @tab A2 @tab A3
+ ;; extract-row command deletes the source line in the table.
+ (unformated-row (texinfo-multitable-extract-row)))
+ ;; Use a temporary buffer
+ (set-buffer (get-buffer-create multitable-temp-buffer-name))
+ (delete-region (point-min) (point-max))
+ (insert unformated-row)
+ (goto-char (point-min))
+;; 1. Check for correct number of @tab in line.
+ (let ((tab-number 1)) ; one @tab between two columns
+ (while (search-forward "@tab" nil t)
+ (setq tab-number (1+ tab-number)))
+ (if (/= tab-number (length table-widths))
+ (error "Wrong number of @tab's in a @multitable row.")))
+ (goto-char (point-min))
+;; 2. Format each cell, and copy to a rectangle
+ ;; buffer looks like this: A1 @tab A2 @tab A3
+ ;; Cell #1: format up to @tab
+ ;; Cell #2: format up to @tab
+ ;; Cell #3: format up to eob
+ (while (not (eobp))
+ (setq start (point))
+ (setq end (save-excursion
+ (if (search-forward "@tab" nil 'move)
+ ;; Delete the @tab command, including the @-sign
+ (delete-region
+ (point)
+ (progn (forward-word -1) (1- (point)))))
+ (point)))
+ ;; Set fill-column *wider* than needed to produce inter-column space
+ (setq fill-column (+ 1
+ extra-inter-column-width
+ (nth table-column table-widths)))
+ (narrow-to-region start end)
+ ;; Remove whitespace before and after entry.
+ (skip-chars-forward " ")
+ (delete-region (point) (save-excursion (beginning-of-line) (point)))
+ (goto-char (point-max))
+ (skip-chars-backward " ")
+ (delete-region (point) (save-excursion (end-of-line) (point)))
+ ;; Temorarily set texinfo-stack to nil so texinfo-format-scan
+ ;; does not see an unterminated @multitable.
+ (let (texinfo-stack) ; nil
+ (texinfo-format-scan))
+ (let (fill-prefix) ; no fill prefix
+ (fill-region (point-min) (point-max)))
+ (setq table-entry-height
+ (max table-entry-height (count-lines (point-min) (point-max))))
+;; 3. Move point to end of bottom line, and pad that line to fill column.
+ (goto-char (point-min))
+ (forward-line (1- table-entry-height))
+ (let* ((beg (point)) ; beginning of line
+ ;; add one more space for inter-column spacing
+ (needed-whitespace
+ (1+
+ (- fill-column
+ (-
+ (progn (end-of-line) (point)) ; end of existing line
+ beg)))))
+ (insert (make-string
+ (if (> needed-whitespace 0) needed-whitespace 1)
+ ? )))
+ ;; now, put formatted cell into a rectangle
+ (set (intern (concat multitable-temp-rectangle-name
+ (int-to-string table-column)))
+ (extract-rectangle (point-min) (point)))
+ (delete-region (point-min) (point))
+ (goto-char (point-max))
+ (setq table-column (1+ table-column))
+ (widen))
+;; 4. Add extra lines to rectangles so all are of same height
+ (let ((total-number-of-columns table-column)
+ (column-number 0)
+ here)
+ (while (> table-column 0)
+ (let ((this-rectangle (int-to-string table-column)))
+ (while (< (length this-rectangle) table-entry-height)
+ (setq this-rectangle (append this-rectangle '("")))))
+ (setq table-column (1- table-column)))
+;; 5. Insert formatted rectangles in original buffer
+ (switch-to-buffer original-buffer)
+ (open-line table-entry-height)
+ (while (< column-number total-number-of-columns)
+ (setq here (point))
+ (insert-rectangle
+ (eval (intern
+ (concat multitable-temp-rectangle-name
+ (int-to-string column-number)))))
+ (goto-char here)
+ (end-of-line)
+ (setq column-number (1+ column-number))))
+ (kill-buffer multitable-temp-buffer-name)
+ (setq fill-column existing-fill-column)))
+
+
+;;; @ifinfo, @iftex, @tex, @ifhtml, @html
+
+(put 'ifinfo 'texinfo-format 'texinfo-discard-line)
+(put 'ifinfo 'texinfo-end 'texinfo-discard-command)
+
+(put 'iftex 'texinfo-format 'texinfo-format-iftex)
+(defun texinfo-format-iftex ()
+ (delete-region texinfo-command-start
+ (progn (re-search-forward "@end iftex[ \t]*\n")
+ (point))))
+
+(put 'ifhtml 'texinfo-format 'texinfo-format-ifhtml)
+(defun texinfo-format-ifhtml ()
+ (delete-region texinfo-command-start
+ (progn (re-search-forward "@end ifhtml[ \t]*\n")
+ (point))))
+
+(put 'tex 'texinfo-format 'texinfo-format-tex)
+(defun texinfo-format-tex ()
+ (delete-region texinfo-command-start
+ (progn (re-search-forward "@end tex[ \t]*\n")
+ (point))))
+
+(put 'html 'texinfo-format 'texinfo-format-html)
+(defun texinfo-format-html ()
+ (delete-region texinfo-command-start
+ (progn (re-search-forward "@end html[ \t]*\n")
+ (point))))
+
+
+;;; @titlepage
+
+(put 'titlepage 'texinfo-format 'texinfo-format-titlepage)
+(defun texinfo-format-titlepage ()
+ (delete-region texinfo-command-start
+ (progn (re-search-forward "@end titlepage[ \t]*\n")
+ (point))))
+
+(put 'endtitlepage 'texinfo-format 'texinfo-discard-line)
+
+;; @titlespec an alternative titling command; ignored by Info
+
+(put 'titlespec 'texinfo-format 'texinfo-format-titlespec)
+(defun texinfo-format-titlespec ()
+ (delete-region texinfo-command-start
+ (progn (re-search-forward "@end titlespec[ \t]*\n")
+ (point))))
+
+(put 'endtitlespec 'texinfo-format 'texinfo-discard-line)
+
+
+;;; @today
+
+(put 'today 'texinfo-format 'texinfo-format-today)
+
+;; Produces Day Month Year style of output. eg `1 Jan 1900'
+;; The `@today{}' command requires a pair of braces, like `@dots{}'.
+(defun texinfo-format-today ()
+ (texinfo-parse-arg-discard)
+ (insert (format "%s %s %s"
+ (substring (current-time-string) 8 10)
+ (substring (current-time-string) 4 7)
+ (substring (current-time-string) -4))))
+
+
+;;; @ignore
+
+(put 'ignore 'texinfo-format 'texinfo-format-ignore)
+(defun texinfo-format-ignore ()
+ (delete-region texinfo-command-start
+ (progn (re-search-forward "@end ignore[ \t]*\n")
+ (point))))
+
+(put 'endignore 'texinfo-format 'texinfo-discard-line)
+
+
+;;; Define the Info enclosure command: @definfoenclose
+
+;; A `@definfoenclose' command may be used to define a highlighting
+;; command for Info, but not for TeX. A command defined using
+;; `@definfoenclose' marks text by enclosing it in strings that precede
+;; and follow the text.
+;;
+;; Presumably, if you define a command with `@definfoenclose` for Info,
+;; you will also define the same command in the TeX definitions file,
+;; `texinfo.tex' in a manner appropriate for typesetting.
+;;
+;; Write a `@definfoenclose' command on a line and follow it with three
+;; arguments separated by commas (commas are used as separators in an
+;; `@node' line in the same way). The first argument to
+;; `@definfoenclose' is the @-command name \(without the `@'\); the
+;; second argument is the Info start delimiter string; and the third
+;; argument is the Info end delimiter string. The latter two arguments
+;; enclose the highlighted text in the Info file. A delimiter string
+;; may contain spaces. Neither the start nor end delimiter is
+;; required. However, if you do not provide a start delimiter, you
+;; must follow the command name with two commas in a row; otherwise,
+;; the Info formatting commands will misinterpret the end delimiter
+;; string as a start delimiter string.
+;;
+;; If you do a @definfoenclose{} on the name of a pre-defined macro (such
+;; as @emph{}, @strong{}, @tt{}, or @i{}) the enclosure definition will
+;; override the built-in definition.
+;;
+;; An enclosure command defined this way takes one argument in braces.
+;;
+;; For example, you can write:
+;;
+;; @ifinfo
+;; @definfoenclose phoo, //, \\
+;; @end ifinfo
+;;
+;; near the beginning of a Texinfo file at the beginning of the lines
+;; to define `@phoo' as an Info formatting command that inserts `//'
+;; before and `\\' after the argument to `@phoo'. You can then write
+;; `@phoo{bar}' wherever you want `//bar\\' highlighted in Info.
+;;
+;; Also, for TeX formatting, you could write
+;;
+;; @iftex
+;; @global@let@phoo=@i
+;; @end iftex
+;;
+;; to define `@phoo' as a command that causes TeX to typeset
+;; the argument to `@phoo' in italics.
+;;
+;; Note that each definition applies to its own formatter: one for TeX,
+;; the other for texinfo-format-buffer or texinfo-format-region.
+;;
+;; Here is another example: write
+;;
+;; @definfoenclose headword, , :
+;;
+;; near the beginning of the file, to define `@headword' as an Info
+;; formatting command that inserts nothing before and a colon after the
+;; argument to `@headword'.
+
+(put 'definfoenclose 'texinfo-format 'texinfo-define-info-enclosure)
+(defun texinfo-define-info-enclosure ()
+ (let* ((args (texinfo-format-parse-line-args))
+ (command-name (nth 0 args))
+ (beginning-delimiter (or (nth 1 args) ""))
+ (end-delimiter (or (nth 2 args) "")))
+ (texinfo-discard-command)
+ (setq texinfo-enclosure-list
+ (cons
+ (list command-name
+ (list
+ beginning-delimiter
+ end-delimiter))
+ texinfo-enclosure-list))))
+
+
+;;; @var, @code and the like
+
+(put 'var 'texinfo-format 'texinfo-format-var)
+;; @sc a small caps font for TeX; formatted as `var' in Info
+(put 'sc 'texinfo-format 'texinfo-format-var)
+(defun texinfo-format-var ()
+ (insert (upcase (texinfo-parse-arg-discard)))
+ (goto-char texinfo-command-start))
+
+(put 'url 'texinfo-format 'texinfo-format-code)
+(put 'cite 'texinfo-format 'texinfo-format-code)
+(put 'code 'texinfo-format 'texinfo-format-code)
+(put 'file 'texinfo-format 'texinfo-format-code)
+(put 'samp 'texinfo-format 'texinfo-format-code)
+(defun texinfo-format-code ()
+ (insert "`" (texinfo-parse-arg-discard) "'")
+ (goto-char texinfo-command-start))
+
+(put 'emph 'texinfo-format 'texinfo-format-emph)
+(put 'strong 'texinfo-format 'texinfo-format-emph)
+(defun texinfo-format-emph ()
+ (insert "*" (texinfo-parse-arg-discard) "*")
+ (goto-char texinfo-command-start))
+
+(put 'dfn 'texinfo-format 'texinfo-format-defn)
+(put 'defn 'texinfo-format 'texinfo-format-defn)
+(defun texinfo-format-defn ()
+ (insert "\"" (texinfo-parse-arg-discard) "\"")
+ (goto-char texinfo-command-start))
+
+(put 'email 'texinfo-format 'texinfo-format-key)
+(put 'key 'texinfo-format 'texinfo-format-key)
+(defun texinfo-format-key ()
+ (insert "<" (texinfo-parse-arg-discard) ">")
+ (goto-char texinfo-command-start))
+
+(put 'bullet 'texinfo-format 'texinfo-format-bullet)
+(defun texinfo-format-bullet ()
+ "Insert an asterisk.
+If used within a line, follow `@bullet' with braces."
+ (texinfo-optional-braces-discard)
+ (insert "*"))
+
+
+;;; @kbd
+
+;; Inside of @example ... @end example and similar environments,
+;; @kbd does nothing; but outside of such environments, it places
+;; single quotation markes around its argument.
+
+(defvar texinfo-format-kbd-regexp
+ (concat
+ "^@"
+ "\\("
+ "example\\|"
+ "smallexample\\|"
+ "lisp\\|"
+ "smalllisp"
+ "\\)")
+ "Regexp specifying environments in which @kbd does not put `...'
+ around argument.")
+
+(defvar texinfo-format-kbd-end-regexp
+ (concat
+ "^@end "
+ "\\("
+ "example\\|"
+ "smallexample\\|"
+ "lisp\\|"
+ "smalllisp"
+ "\\)")
+ "Regexp specifying end of environments in which @kbd does not put `...'
+ around argument. (See `texinfo-format-kbd-regexp')")
+
+(put 'kbd 'texinfo-format 'texinfo-format-kbd)
+(defun texinfo-format-kbd ()
+ "Place single quote marks around arg, except in @example and similar."
+ ;; Search forward for @end example closer than an @example.
+ ;; Can stop search at nearest @node or texinfo-section-types-regexp
+ (let* ((stop
+ (save-excursion
+ (re-search-forward
+ (concat "^@node\\|\\(" texinfo-section-types-regexp "\\)")
+ nil
+ 'move-to-end) ; if necessary, return point at end of buffer
+ (point)))
+ (example-location
+ (save-excursion
+ (re-search-forward texinfo-format-kbd-regexp stop 'move-to-end)
+ (point)))
+ (end-example-location
+ (save-excursion
+ (re-search-forward texinfo-format-kbd-end-regexp stop 'move-to-end)
+ (point))))
+ ;; If inside @example, @end example will be closer than @example
+ ;; or end of search i.e., end-example-location less than example-location
+ (if (>= end-example-location example-location)
+ ;; outside an @example or equivalent
+ (insert "`" (texinfo-parse-arg-discard) "'")
+ ;; else, in @example; do not surround with `...'
+ (insert (texinfo-parse-arg-discard)))
+ (goto-char texinfo-command-start)))
+
+
+;;; @example, @lisp, @quotation, @display, @smalllisp, @smallexample
+
+(put 'display 'texinfo-format 'texinfo-format-example)
+(put 'example 'texinfo-format 'texinfo-format-example)
+(put 'lisp 'texinfo-format 'texinfo-format-example)
+(put 'quotation 'texinfo-format 'texinfo-format-example)
+(put 'smallexample 'texinfo-format 'texinfo-format-example)
+(put 'smalllisp 'texinfo-format 'texinfo-format-example)
+(defun texinfo-format-example ()
+ (texinfo-push-stack 'example nil)
+ (setq fill-column (- fill-column 5))
+ (texinfo-discard-line))
+
+(put 'example 'texinfo-end 'texinfo-end-example)
+(put 'display 'texinfo-end 'texinfo-end-example)
+(put 'lisp 'texinfo-end 'texinfo-end-example)
+(put 'quotation 'texinfo-end 'texinfo-end-example)
+(put 'smallexample 'texinfo-end 'texinfo-end-example)
+(put 'smalllisp 'texinfo-end 'texinfo-end-example)
+(defun texinfo-end-example ()
+ (setq fill-column (+ fill-column 5))
+ (texinfo-discard-command)
+ (let ((stacktop
+ (texinfo-pop-stack 'example)))
+ (texinfo-do-itemize (nth 1 stacktop))))
+
+(put 'exdent 'texinfo-format 'texinfo-format-exdent)
+(defun texinfo-format-exdent ()
+ (texinfo-discard-command)
+ (delete-region (point)
+ (progn
+ (skip-chars-forward " ")
+ (point)))
+ (insert ?\b)
+ ;; Cancel out the deletion that texinfo-do-itemize
+ ;; is going to do at the end of this line.
+ (save-excursion
+ (end-of-line)
+ (insert "\n ")))
+
+
+;;; @cartouche
+
+;; The @cartouche command is a noop in Info; in a printed manual,
+;; it makes a box with rounded corners.
+
+(put 'cartouche 'texinfo-format 'texinfo-discard-line)
+(put 'cartouche 'texinfo-end 'texinfo-discard-command)
+
+
+;;; @flushleft and @format
+
+;; The @flushleft command left justifies every line but leaves the
+;; right end ragged. As far as Info is concerned, @flushleft is a
+;; `do-nothing' command
+
+;; The @format command is similar to @example except that it does not
+;; indent; this means that in Info, @format is similar to @flushleft.
+
+(put 'format 'texinfo-format 'texinfo-format-flushleft)
+(put 'flushleft 'texinfo-format 'texinfo-format-flushleft)
+(defun texinfo-format-flushleft ()
+ (texinfo-discard-line))
+
+(put 'format 'texinfo-end 'texinfo-end-flushleft)
+(put 'flushleft 'texinfo-end 'texinfo-end-flushleft)
+(defun texinfo-end-flushleft ()
+ (texinfo-discard-command))
+
+
+;;; @flushright
+
+;; The @flushright command right justifies every line but leaves the
+;; left end ragged. Spaces and tabs at the right ends of lines are
+;; removed so that visible text lines up on the right side.
+
+(put 'flushright 'texinfo-format 'texinfo-format-flushright)
+(defun texinfo-format-flushright ()
+ (texinfo-push-stack 'flushright nil)
+ (texinfo-discard-line))
+
+(put 'flushright 'texinfo-end 'texinfo-end-flushright)
+(defun texinfo-end-flushright ()
+ (texinfo-discard-command)
+
+ (let ((stacktop
+ (texinfo-pop-stack 'flushright)))
+
+ (texinfo-do-flushright (nth 1 stacktop))))
+
+(defun texinfo-do-flushright (from)
+ (save-excursion
+ (while (progn (forward-line -1)
+ (>= (point) from))
+
+ (beginning-of-line)
+ (insert
+ (make-string
+ (- fill-column
+ (save-excursion
+ (end-of-line)
+ (skip-chars-backward " \t")
+ (delete-region (point) (progn (end-of-line) (point)))
+ (current-column)))
+ ? )))))
+
+
+;;; @ctrl, @TeX, @copyright, @minus, @dots, @enddots, @pounds
+
+(put 'ctrl 'texinfo-format 'texinfo-format-ctrl)
+(defun texinfo-format-ctrl ()
+ (let ((str (texinfo-parse-arg-discard)))
+ (insert (logand 31 (aref str 0)))))
+
+(put 'TeX 'texinfo-format 'texinfo-format-TeX)
+(defun texinfo-format-TeX ()
+ (texinfo-parse-arg-discard)
+ (insert "TeX"))
+
+(put 'copyright 'texinfo-format 'texinfo-format-copyright)
+(defun texinfo-format-copyright ()
+ (texinfo-parse-arg-discard)
+ (insert "(C)"))
+
+(put 'minus 'texinfo-format 'texinfo-format-minus)
+(defun texinfo-format-minus ()
+ "Insert a minus sign.
+If used within a line, follow `@minus' with braces."
+ (texinfo-optional-braces-discard)
+ (insert "-"))
+
+(put 'dots 'texinfo-format 'texinfo-format-dots)
+(defun texinfo-format-dots ()
+ (texinfo-parse-arg-discard)
+ (insert "..."))
+
+(put 'enddots 'texinfo-format 'texinfo-format-enddots)
+(defun texinfo-format-enddots ()
+ (texinfo-parse-arg-discard)
+ (insert "...."))
+
+(put 'pounds 'texinfo-format 'texinfo-format-pounds)
+(defun texinfo-format-pounds ()
+ (texinfo-parse-arg-discard)
+ (insert "#"))
+
+
+;;; Refilling and indenting: @refill, @paragraphindent, @noindent
+
+;;; Indent only those paragraphs that are refilled as a result of an
+;;; @refill command.
+
+;; * If the value is `asis', do not change the existing indentation at
+;; the starts of paragraphs.
+
+;; * If the value zero, delete any existing indentation.
+
+;; * If the value is greater than zero, indent each paragraph by that
+;; number of spaces.
+
+;;; But do not refill paragraphs with an @refill command that are
+;;; preceded by @noindent or are part of a table, list, or deffn.
+
+(defvar texinfo-paragraph-indent "asis"
+ "Number of spaces for @refill to indent a paragraph; else to leave as is.")
+
+(put 'paragraphindent 'texinfo-format 'texinfo-paragraphindent)
+
+(defun texinfo-paragraphindent ()
+ "Specify the number of spaces for @refill to indent a paragraph.
+Default is to leave the number of spaces as is."
+ (let ((arg (texinfo-parse-arg-discard)))
+ (if (string= "asis" arg)
+ (setq texinfo-paragraph-indent "asis")
+ (setq texinfo-paragraph-indent (string-to-int arg)))))
+
+(put 'refill 'texinfo-format 'texinfo-format-refill)
+(defun texinfo-format-refill ()
+ "Refill paragraph. Also, indent first line as set by @paragraphindent.
+Default is to leave paragraph indentation as is."
+ (texinfo-discard-command)
+ (forward-paragraph -1)
+ (if (looking-at "[ \t\n]*$") (forward-line 1))
+ ;; Do not indent if an entry in a list, table, or deffn,
+ ;; or if paragraph is preceded by @noindent.
+ ;; Otherwise, indent
+ (cond
+ ;; delete a @noindent line and do not indent paragraph
+ ((save-excursion (forward-line -1)
+ (looking-at "^@noindent"))
+ (forward-line -1)
+ (delete-region (point) (progn (forward-line 1) (point))))
+ ;; do nothing if "asis"
+ ((equal texinfo-paragraph-indent "asis"))
+ ;; do no indenting in list, etc.
+ ((> texinfo-stack-depth 0))
+ ;; otherwise delete existing whitespace and indent
+ (t
+ (delete-region (point) (progn (skip-chars-forward " \t") (point)))
+ (insert (make-string texinfo-paragraph-indent ? ))))
+ (forward-paragraph 1)
+ (forward-line -1)
+ (end-of-line)
+ ;; Do not fill a section title line with asterisks, hyphens, etc. that
+ ;; are used to underline it. This could occur if the line following
+ ;; the underlining is not an index entry and has text within it.
+ (let* ((previous-paragraph-separate paragraph-separate)
+ (paragraph-separate
+ (concat paragraph-separate "\\|[-=.]+\\|\\*\\*+"))
+ (previous-paragraph-start paragraph-start)
+ (paragraph-start
+ (concat paragraph-start "\\|[-=.]+\\|\\*\\*+")))
+ (unwind-protect
+ (fill-paragraph nil)
+ (setq paragraph-separate previous-paragraph-separate)
+ (setq paragraph-start previous-paragraph-start))))
+
+(put 'noindent 'texinfo-format 'texinfo-noindent)
+(defun texinfo-noindent ()
+ (save-excursion
+ (forward-paragraph 1)
+ (if (search-backward "@refill"
+ (save-excursion (forward-line -1) (point)) t)
+ () ; leave @noindent command so @refill command knows not to indent
+ ;; else
+ (texinfo-discard-line))))
+
+
+;;; Index generation
+
+(put 'vindex 'texinfo-format 'texinfo-format-vindex)
+(defun texinfo-format-vindex ()
+ (texinfo-index 'texinfo-vindex))
+
+(put 'cindex 'texinfo-format 'texinfo-format-cindex)
+(defun texinfo-format-cindex ()
+ (texinfo-index 'texinfo-cindex))
+
+(put 'findex 'texinfo-format 'texinfo-format-findex)
+(defun texinfo-format-findex ()
+ (texinfo-index 'texinfo-findex))
+
+(put 'pindex 'texinfo-format 'texinfo-format-pindex)
+(defun texinfo-format-pindex ()
+ (texinfo-index 'texinfo-pindex))
+
+(put 'tindex 'texinfo-format 'texinfo-format-tindex)
+(defun texinfo-format-tindex ()
+ (texinfo-index 'texinfo-tindex))
+
+(put 'kindex 'texinfo-format 'texinfo-format-kindex)
+(defun texinfo-format-kindex ()
+ (texinfo-index 'texinfo-kindex))
+
+(defun texinfo-index (indexvar)
+ (let ((arg (texinfo-parse-expanded-arg)))
+ (texinfo-discard-command)
+ (set indexvar
+ (cons (list arg
+ texinfo-last-node
+ ;; Region formatting may not provide last node position.
+ (if texinfo-last-node-pos
+ (1+ (count-lines texinfo-last-node-pos (point)))
+ 1))
+ (symbol-value indexvar)))))
+
+(defconst texinfo-indexvar-alist
+ '(("cp" . texinfo-cindex)
+ ("fn" . texinfo-findex)
+ ("vr" . texinfo-vindex)
+ ("tp" . texinfo-tindex)
+ ("pg" . texinfo-pindex)
+ ("ky" . texinfo-kindex)))
+
+
+;;; @defindex @defcodeindex
+(put 'defindex 'texinfo-format 'texinfo-format-defindex)
+(put 'defcodeindex 'texinfo-format 'texinfo-format-defindex)
+
+(defun texinfo-format-defindex ()
+ (let* ((index-name (texinfo-parse-arg-discard)) ; eg: `aa'
+ (indexing-command (intern (concat index-name "index")))
+ (index-formatting-command ; eg: `texinfo-format-aaindex'
+ (intern (concat "texinfo-format-" index-name "index")))
+ (index-alist-name ; eg: `texinfo-aaindex'
+ (intern (concat "texinfo-" index-name "index"))))
+
+ (set index-alist-name nil)
+
+ (put indexing-command ; eg, aaindex
+ 'texinfo-format
+ index-formatting-command) ; eg, texinfo-format-aaindex
+
+ ;; eg: "aa" . texinfo-aaindex
+ (or (assoc index-name texinfo-indexvar-alist)
+ (setq texinfo-indexvar-alist
+ (cons
+ (cons index-name
+ index-alist-name)
+ texinfo-indexvar-alist)))
+
+ (fset index-formatting-command
+ (list 'lambda 'nil
+ (list 'texinfo-index
+ (list 'quote index-alist-name))))))
+
+
+;;; @synindex @syncodeindex
+
+(put 'synindex 'texinfo-format 'texinfo-format-synindex)
+(put 'syncodeindex 'texinfo-format 'texinfo-format-synindex)
+
+(defun texinfo-format-synindex ()
+ (let* ((args (texinfo-parse-arg-discard))
+ (second (cdr (read-from-string args)))
+ (joiner (symbol-name (car (read-from-string args))))
+ (joined (symbol-name (car (read-from-string args second)))))
+
+ (if (assoc joiner texinfo-short-index-cmds-alist)
+ (put
+ (cdr (assoc joiner texinfo-short-index-cmds-alist))
+ 'texinfo-format
+ (or (cdr (assoc joined texinfo-short-index-format-cmds-alist))
+ (intern (concat "texinfo-format-" joined "index"))))
+ (put
+ (intern (concat joiner "index"))
+ 'texinfo-format
+ (or (cdr(assoc joined texinfo-short-index-format-cmds-alist))
+ (intern (concat "texinfo-format-" joined "index")))))))
+
+(defconst texinfo-short-index-cmds-alist
+ '(("cp" . cindex)
+ ("fn" . findex)
+ ("vr" . vindex)
+ ("tp" . tindex)
+ ("pg" . pindex)
+ ("ky" . kindex)))
+
+(defconst texinfo-short-index-format-cmds-alist
+ '(("cp" . texinfo-format-cindex)
+ ("fn" . texinfo-format-findex)
+ ("vr" . texinfo-format-vindex)
+ ("tp" . texinfo-format-tindex)
+ ("pg" . texinfo-format-pindex)
+ ("ky" . texinfo-format-kindex)))
+
+
+;;; Sort and index (for VMS)
+
+;; Sort an index which is in the current buffer between START and END.
+;; Used on VMS, where the `sort' utility is not available.
+(defun texinfo-sort-region (start end)
+ (require 'sort)
+ (save-restriction
+ (narrow-to-region start end)
+ (sort-subr nil 'forward-line 'end-of-line 'texinfo-sort-startkeyfun)))
+
+;; Subroutine for sorting an index.
+;; At start of a line, return a string to sort the line under.
+(defun texinfo-sort-startkeyfun ()
+ (let ((line
+ (buffer-substring (point) (save-excursion (end-of-line) (point)))))
+ ;; Canonicalize whitespace and eliminate funny chars.
+ (while (string-match "[ \t][ \t]+\\|[^a-z0-9 ]+" line)
+ (setq line (concat (substring line 0 (match-beginning 0))
+ " "
+ (substring line (match-end 0) (length line)))))
+ line))
+
+
+;;; @printindex
+
+(put 'printindex 'texinfo-format 'texinfo-format-printindex)
+
+(defun texinfo-format-printindex ()
+ (let ((indexelts (symbol-value
+ (cdr (assoc (texinfo-parse-arg-discard)
+ texinfo-indexvar-alist))))
+ opoint)
+ (insert "\n* Menu:\n\n")
+ (setq opoint (point))
+ (texinfo-print-index nil indexelts)
+
+ (if (memq system-type '(vax-vms windows-nt ms-dos))
+ (texinfo-sort-region opoint (point))
+ (shell-command-on-region opoint (point) "sort -fd" 1))))
+
+(defun texinfo-print-index (file indexelts)
+ (while indexelts
+ (if (stringp (car (car indexelts)))
+ (progn
+ (insert "* " (car (car indexelts)) ": " )
+ (indent-to 32)
+ (insert
+ (if file (concat "(" file ")") "")
+ (nth 1 (car indexelts)) ".")
+ (indent-to 54)
+ (insert
+ (if (nth 2 (car indexelts))
+ (format " %d." (nth 2 (car indexelts)))
+ "")
+ "\n"))
+ ;; index entries from @include'd file
+ (texinfo-print-index (nth 1 (car indexelts))
+ (nth 2 (car indexelts))))
+ (setq indexelts (cdr indexelts))))
+
+
+;;; Glyphs: @equiv, @error, etc
+
+;; @equiv to show that two expressions are equivalent
+;; @error to show an error message
+;; @expansion to show what a macro expands to
+;; @point to show the location of point in an example
+;; @print to show what an evaluated expression prints
+;; @result to indicate the value returned by an expression
+
+(put 'equiv 'texinfo-format 'texinfo-format-equiv)
+(defun texinfo-format-equiv ()
+ (texinfo-parse-arg-discard)
+ (insert "=="))
+
+(put 'error 'texinfo-format 'texinfo-format-error)
+(defun texinfo-format-error ()
+ (texinfo-parse-arg-discard)
+ (insert "error-->"))
+
+(put 'expansion 'texinfo-format 'texinfo-format-expansion)
+(defun texinfo-format-expansion ()
+ (texinfo-parse-arg-discard)
+ (insert "==>"))
+
+(put 'point 'texinfo-format 'texinfo-format-point)
+(defun texinfo-format-point ()
+ (texinfo-parse-arg-discard)
+ (insert "-!-"))
+
+(put 'print 'texinfo-format 'texinfo-format-print)
+(defun texinfo-format-print ()
+ (texinfo-parse-arg-discard)
+ (insert "-|"))
+
+(put 'result 'texinfo-format 'texinfo-format-result)
+(defun texinfo-format-result ()
+ (texinfo-parse-arg-discard)
+ (insert "=>"))
+
+
+;;; Accent commands
+
+;; Info presumes a plain ASCII output, so the accented characters do
+;; not look as they would if typeset, or output with a different
+;; character set.
+
+;; See the `texinfo-accent-commands' variable
+;; in the section for `texinfo-append-refill'.
+;; Also, see the defun for `texinfo-format-scan'
+;; for single-character accent commands.
+
+;; Command Info output Name
+
+;; These do not have braces:
+;; @^ ==> ^ circumflex accent
+;; @` ==> ` grave accent
+;; @' ==> ' acute accent
+;; @" ==> " umlaut accent
+;; @= ==> = overbar accent
+;; @~ ==> ~ tilde accent
+
+;; These have braces, but take no argument:
+;; @OE{} ==> OE French-OE-ligature
+;; @oe{} ==> oe
+;; @AA{} ==> AA Scandinavian-A-with-circle
+;; @aa{} ==> aa
+;; @AE{} ==> AE Latin-Scandinavian-AE
+;; @ae{} ==> ae
+;; @ss{} ==> ss German-sharp-S
+
+;; @questiondown{} ==> ? upside-down-question-mark
+;; @exclamdown{} ==> ! upside-down-exclamation-mark
+;; @L{} ==> L/ Polish suppressed-L (Lslash)
+;; @l{} ==> l/ Polish suppressed-L (Lslash) (lower case)
+;; @O{} ==> O/ Scandinavian O-with-slash
+;; @o{} ==> o/ Scandinavian O-with-slash (lower case)
+
+;; These have braces, and take an argument:
+;; @,{c} ==> c, cedilla accent
+;; @dotaccent{o} ==> .o overdot-accent
+;; @ubaraccent{o} ==> _o underbar-accent
+;; @udotaccent{o} ==> o-. underdot-accent
+;; @H{o} ==> ""o long Hungarian umlaut
+;; @ringaccent{o} ==> *o ring accent
+;; @tieaccent{oo} ==> [oo tie after accent
+;; @u{o} ==> (o breve accent
+;; @v{o} ==> <o hacek accent
+;; @dotless{i} ==> i dotless i and dotless j
+
+;; ==========
+
+;; Note: The defun texinfo-format-scan
+;; looks at "[@{}^'`\",=~ *?!-]"
+;; In the case of @*, a line break is inserted;
+;; in the other cases, the characters are simply quoted and the @ is deleted.
+;; Thus, `texinfo-format-scan' handles the following
+;; single-character accent commands: @^ @` @' @" @, @- @= @~
+
+;; @^ ==> ^ circumflex accent
+;; (put '^ 'texinfo-format 'texinfo-format-circumflex-accent)
+;; (defun texinfo-format-circumflex-accent ()
+;; (texinfo-discard-command)
+;; (insert "^"))
+;;
+;; @` ==> ` grave accent
+;; (put '\` 'texinfo-format 'texinfo-format-grave-accent)
+;; (defun texinfo-format-grave-accent ()
+;; (texinfo-discard-command)
+;; (insert "\`"))
+;;
+;; @' ==> ' acute accent
+;; (put '\' 'texinfo-format 'texinfo-format-acute-accent)
+;; (defun texinfo-format-acute-accent ()
+;; (texinfo-discard-command)
+;; (insert "'"))
+;;
+;; @" ==> " umlaut accent
+;; (put '\" 'texinfo-format 'texinfo-format-umlaut-accent)
+;; (defun texinfo-format-umlaut-accent ()
+;; (texinfo-discard-command)
+;; (insert "\""))
+;;
+;; @= ==> = overbar accent
+;; (put '= 'texinfo-format 'texinfo-format-overbar-accent)
+;; (defun texinfo-format-overbar-accent ()
+;; (texinfo-discard-command)
+;; (insert "="))
+;;
+;; @~ ==> ~ tilde accent
+;; (put '~ 'texinfo-format 'texinfo-format-tilde-accent)
+;; (defun texinfo-format-tilde-accent ()
+;; (texinfo-discard-command)
+;; (insert "~"))
+
+;; @OE{} ==> OE French-OE-ligature
+(put 'OE 'texinfo-format 'texinfo-format-French-OE-ligature)
+(defun texinfo-format-French-OE-ligature ()
+ (insert "OE" (texinfo-parse-arg-discard))
+ (goto-char texinfo-command-start))
+
+;; @oe{} ==> oe
+(put 'oe 'texinfo-format 'texinfo-format-French-oe-ligature)
+(defun texinfo-format-French-oe-ligature () ; lower case
+ (insert "oe" (texinfo-parse-arg-discard))
+ (goto-char texinfo-command-start))
+
+;; @AA{} ==> AA Scandinavian-A-with-circle
+(put 'AA 'texinfo-format 'texinfo-format-Scandinavian-A-with-circle)
+(defun texinfo-format-Scandinavian-A-with-circle ()
+ (insert "AA" (texinfo-parse-arg-discard))
+ (goto-char texinfo-command-start))
+
+;; @aa{} ==> aa
+(put 'aa 'texinfo-format 'texinfo-format-Scandinavian-a-with-circle)
+(defun texinfo-format-Scandinavian-a-with-circle () ; lower case
+ (insert "aa" (texinfo-parse-arg-discard))
+ (goto-char texinfo-command-start))
+
+;; @AE{} ==> AE Latin-Scandinavian-AE
+(put 'AE 'texinfo-format 'texinfo-format-Latin-Scandinavian-AE)
+(defun texinfo-format-Latin-Scandinavian-AE ()
+ (insert "AE" (texinfo-parse-arg-discard))
+ (goto-char texinfo-command-start))
+
+;; @ae{} ==> ae
+(put 'ae 'texinfo-format 'texinfo-format-Latin-Scandinavian-ae)
+(defun texinfo-format-Latin-Scandinavian-ae () ; lower case
+ (insert "ae" (texinfo-parse-arg-discard))
+ (goto-char texinfo-command-start))
+
+;; @ss{} ==> ss German-sharp-S
+(put 'ss 'texinfo-format 'texinfo-format-German-sharp-S)
+(defun texinfo-format-German-sharp-S ()
+ (insert "ss" (texinfo-parse-arg-discard))
+ (goto-char texinfo-command-start))
+
+;; @questiondown{} ==> ? upside-down-question-mark
+(put 'questiondown 'texinfo-format 'texinfo-format-upside-down-question-mark)
+(defun texinfo-format-upside-down-question-mark ()
+ (insert "?" (texinfo-parse-arg-discard))
+ (goto-char texinfo-command-start))
+
+;; @exclamdown{} ==> ! upside-down-exclamation-mark
+(put 'exclamdown 'texinfo-format 'texinfo-format-upside-down-exclamation-mark)
+(defun texinfo-format-upside-down-exclamation-mark ()
+ (insert "!" (texinfo-parse-arg-discard))
+ (goto-char texinfo-command-start))
+
+;; @L{} ==> L/ Polish suppressed-L (Lslash)
+(put 'L 'texinfo-format 'texinfo-format-Polish-suppressed-L)
+(defun texinfo-format-Polish-suppressed-L ()
+ (insert (texinfo-parse-arg-discard) "/L")
+ (goto-char texinfo-command-start))
+
+;; @l{} ==> l/ Polish suppressed-L (Lslash) (lower case)
+(put 'l 'texinfo-format 'texinfo-format-Polish-suppressed-l-lower-case)
+(defun texinfo-format-Polish-suppressed-l-lower-case ()
+ (insert (texinfo-parse-arg-discard) "/l")
+ (goto-char texinfo-command-start))
+
+
+;; @O{} ==> O/ Scandinavian O-with-slash
+(put 'O 'texinfo-format 'texinfo-format-Scandinavian-O-with-slash)
+(defun texinfo-format-Scandinavian-O-with-slash ()
+ (insert (texinfo-parse-arg-discard) "O/")
+ (goto-char texinfo-command-start))
+
+;; @o{} ==> o/ Scandinavian O-with-slash (lower case)
+(put 'o 'texinfo-format 'texinfo-format-Scandinavian-o-with-slash-lower-case)
+(defun texinfo-format-Scandinavian-o-with-slash-lower-case ()
+ (insert (texinfo-parse-arg-discard) "o/")
+ (goto-char texinfo-command-start))
+
+;; Take arguments
+
+;; @,{c} ==> c, cedilla accent
+(put ', 'texinfo-format 'texinfo-format-cedilla-accent)
+(defun texinfo-format-cedilla-accent ()
+ (insert (texinfo-parse-arg-discard) ",")
+ (goto-char texinfo-command-start))
+
+
+;; @dotaccent{o} ==> .o overdot-accent
+(put 'dotaccent 'texinfo-format 'texinfo-format-overdot-accent)
+(defun texinfo-format-overdot-accent ()
+ (insert "." (texinfo-parse-arg-discard))
+ (goto-char texinfo-command-start))
+
+;; @ubaraccent{o} ==> _o underbar-accent
+(put 'ubaraccent 'texinfo-format 'texinfo-format-underbar-accent)
+(defun texinfo-format-underbar-accent ()
+ (insert "_" (texinfo-parse-arg-discard))
+ (goto-char texinfo-command-start))
+
+;; @udotaccent{o} ==> o-. underdot-accent
+(put 'udotaccent 'texinfo-format 'texinfo-format-underdot-accent)
+(defun texinfo-format-underdot-accent ()
+ (insert (texinfo-parse-arg-discard) "-.")
+ (goto-char texinfo-command-start))
+
+;; @H{o} ==> ""o long Hungarian umlaut
+(put 'H 'texinfo-format 'texinfo-format-long-Hungarian-umlaut)
+(defun texinfo-format-long-Hungarian-umlaut ()
+ (insert "\"\"" (texinfo-parse-arg-discard))
+ (goto-char texinfo-command-start))
+
+;; @ringaccent{o} ==> *o ring accent
+(put 'ringaccent 'texinfo-format 'texinfo-format-ring-accent)
+(defun texinfo-format-ring-accent ()
+ (insert "*" (texinfo-parse-arg-discard))
+ (goto-char texinfo-command-start))
+
+;; @tieaccent{oo} ==> [oo tie after accent
+(put 'tieaccent 'texinfo-format 'texinfo-format-tie-after-accent)
+(defun texinfo-format-tie-after-accent ()
+ (insert "[" (texinfo-parse-arg-discard))
+ (goto-char texinfo-command-start))
+
+
+;; @u{o} ==> (o breve accent
+(put 'u 'texinfo-format 'texinfo-format-breve-accent)
+(defun texinfo-format-breve-accent ()
+ (insert "(" (texinfo-parse-arg-discard))
+ (goto-char texinfo-command-start))
+
+;; @v{o} ==> <o hacek accent
+(put 'v 'texinfo-format 'texinfo-format-hacek-accent)
+(defun texinfo-format-hacek-accent ()
+ (insert "<" (texinfo-parse-arg-discard))
+ (goto-char texinfo-command-start))
+
+
+;; @dotless{i} ==> i dotless i and dotless j
+(put 'dotless 'texinfo-format 'texinfo-format-dotless)
+(defun texinfo-format-dotless ()
+ (insert (texinfo-parse-arg-discard))
+ (goto-char texinfo-command-start))
+
+
+;;; Definition formatting: @deffn, @defun, etc
+
+;; What definition formatting produces:
+;;
+;; @deffn category name args...
+;; In Info, `Category: name ARGS'
+;; In index: name: node. line#.
+;;
+;; @defvr category name
+;; In Info, `Category: name'
+;; In index: name: node. line#.
+;;
+;; @deftp category name attributes...
+;; `category name attributes...' Note: @deftp args in lower case.
+;; In index: name: node. line#.
+;;
+;; Specialized function-like or variable-like entity:
+;;
+;; @defun, @defmac, @defspec, @defvar, @defopt
+;;
+;; @defun name args In Info, `Function: name ARGS'
+;; @defmac name args In Info, `Macro: name ARGS'
+;; @defvar name In Info, `Variable: name'
+;; etc.
+;; In index: name: node. line#.
+;;
+;; Generalized typed-function-like or typed-variable-like entity:
+;; @deftypefn category data-type name args...
+;; In Info, `Category: data-type name args...'
+;; @deftypevr category data-type name
+;; In Info, `Category: data-type name'
+;; In index: name: node. line#.
+;;
+;; Specialized typed-function-like or typed-variable-like entity:
+;; @deftypefun data-type name args...
+;; In Info, `Function: data-type name ARGS'
+;; In index: name: node. line#.
+;;
+;; @deftypevar data-type name
+;; In Info, `Variable: data-type name'
+;; In index: name: node. line#. but include args after name!?
+;;
+;; Generalized object oriented entity:
+;; @defop category class name args...
+;; In Info, `Category on class: name ARG'
+;; In index: name on class: node. line#.
+;;
+;; @defcv category class name
+;; In Info, `Category of class: name'
+;; In index: name of class: node. line#.
+;;
+;; Specialized object oriented entity:
+;; @defmethod class name args...
+;; In Info, `Method on class: name ARGS'
+;; In index: name on class: node. line#.
+;;
+;; @defivar class name
+;; In Info, `Instance variable of class: name'
+;; In index: name of class: node. line#.
+
+
+;;; The definition formatting functions
+
+(defun texinfo-format-defun ()
+ (texinfo-push-stack 'defun nil)
+ (setq fill-column (- fill-column 5))
+ (texinfo-format-defun-1 t))
+
+(defun texinfo-end-defun ()
+ (setq fill-column (+ fill-column 5))
+ (texinfo-discard-command)
+ (let ((start (nth 1 (texinfo-pop-stack 'defun))))
+ (texinfo-do-itemize start)
+ ;; Delete extra newline inserted after header.
+ (save-excursion
+ (goto-char start)
+ (delete-char -1))))
+
+(defun texinfo-format-defunx ()
+ (texinfo-format-defun-1 nil))
+
+(defun texinfo-format-defun-1 (first-p)
+ (let ((parse-args (texinfo-format-parse-defun-args))
+ (texinfo-defun-type (get texinfo-command-name 'texinfo-defun-type)))
+ (texinfo-discard-command)
+ ;; Delete extra newline inserted after previous header line.
+ (if (not first-p)
+ (delete-char -1))
+ (funcall
+ (get texinfo-command-name 'texinfo-deffn-formatting-property) parse-args)
+ ;; Insert extra newline so that paragraph filling does not mess
+ ;; with header line.
+ (insert "\n\n")
+ (rplaca (cdr (cdr (car texinfo-stack))) (point))
+ (funcall
+ (get texinfo-command-name 'texinfo-defun-indexing-property) parse-args)))
+
+;;; Formatting the first line of a definition
+
+;; @deffn, @defvr, @deftp
+(put 'deffn 'texinfo-deffn-formatting-property 'texinfo-format-deffn)
+(put 'deffnx 'texinfo-deffn-formatting-property 'texinfo-format-deffn)
+(put 'defvr 'texinfo-deffn-formatting-property 'texinfo-format-deffn)
+(put 'defvrx 'texinfo-deffn-formatting-property 'texinfo-format-deffn)
+(put 'deftp 'texinfo-deffn-formatting-property 'texinfo-format-deffn)
+(put 'deftpx 'texinfo-deffn-formatting-property 'texinfo-format-deffn)
+(defun texinfo-format-deffn (parsed-args)
+ ;; Generalized function-like, variable-like, or generic data-type entity:
+ ;; @deffn category name args...
+ ;; In Info, `Category: name ARGS'
+ ;; @deftp category name attributes...
+ ;; `category name attributes...' Note: @deftp args in lower case.
+ (let ((category (car parsed-args))
+ (name (car (cdr parsed-args)))
+ (args (cdr (cdr parsed-args))))
+ (insert " -- " category ": " name)
+ (while args
+ (insert " "
+ (if (or (= ?& (aref (car args) 0))
+ (eq (eval (car texinfo-defun-type)) 'deftp-type))
+ (car args)
+ (upcase (car args))))
+ (setq args (cdr args)))))
+
+;; @defun, @defmac, @defspec, @defvar, @defopt: Specialized, simple
+(put 'defun 'texinfo-deffn-formatting-property
+ 'texinfo-format-specialized-defun)
+(put 'defunx 'texinfo-deffn-formatting-property
+ 'texinfo-format-specialized-defun)
+(put 'defmac 'texinfo-deffn-formatting-property
+ 'texinfo-format-specialized-defun)
+(put 'defmacx 'texinfo-deffn-formatting-property
+ 'texinfo-format-specialized-defun)
+(put 'defspec 'texinfo-deffn-formatting-property
+ 'texinfo-format-specialized-defun)
+(put 'defspecx 'texinfo-deffn-formatting-property
+ 'texinfo-format-specialized-defun)
+(put 'defvar 'texinfo-deffn-formatting-property
+ 'texinfo-format-specialized-defun)
+(put 'defvarx 'texinfo-deffn-formatting-property
+ 'texinfo-format-specialized-defun)
+(put 'defopt 'texinfo-deffn-formatting-property
+ 'texinfo-format-specialized-defun)
+(put 'defoptx 'texinfo-deffn-formatting-property
+ 'texinfo-format-specialized-defun)
+(defun texinfo-format-specialized-defun (parsed-args)
+ ;; Specialized function-like or variable-like entity:
+ ;; @defun name args In Info, `Function: Name ARGS'
+ ;; @defmac name args In Info, `Macro: Name ARGS'
+ ;; @defvar name In Info, `Variable: Name'
+ ;; Use cdr of texinfo-defun-type to determine category:
+ (let ((category (car (cdr texinfo-defun-type)))
+ (name (car parsed-args))
+ (args (cdr parsed-args)))
+ (insert " -- " category ": " name)
+ (while args
+ (insert " "
+ (if (= ?& (aref (car args) 0))
+ (car args)
+ (upcase (car args))))
+ (setq args (cdr args)))))
+
+;; @deftypefn, @deftypevr: Generalized typed
+(put 'deftypefn 'texinfo-deffn-formatting-property 'texinfo-format-deftypefn)
+(put 'deftypefnx 'texinfo-deffn-formatting-property 'texinfo-format-deftypefn)
+(put 'deftypevr 'texinfo-deffn-formatting-property 'texinfo-format-deftypefn)
+(put 'deftypevrx 'texinfo-deffn-formatting-property 'texinfo-format-deftypefn)
+(defun texinfo-format-deftypefn (parsed-args)
+ ;; Generalized typed-function-like or typed-variable-like entity:
+ ;; @deftypefn category data-type name args...
+ ;; In Info, `Category: data-type name args...'
+ ;; @deftypevr category data-type name
+ ;; In Info, `Category: data-type name'
+ ;; Note: args in lower case, unless modified in command line.
+ (let ((category (car parsed-args))
+ (data-type (car (cdr parsed-args)))
+ (name (car (cdr (cdr parsed-args))))
+ (args (cdr (cdr (cdr parsed-args)))))
+ (insert " -- " category ": " data-type " " name)
+ (while args
+ (insert " " (car args))
+ (setq args (cdr args)))))
+
+;; @deftypefun, @deftypevar: Specialized typed
+(put 'deftypefun 'texinfo-deffn-formatting-property 'texinfo-format-deftypefun)
+(put 'deftypefunx 'texinfo-deffn-formatting-property
+ 'texinfo-format-deftypefun)
+(put 'deftypevar 'texinfo-deffn-formatting-property 'texinfo-format-deftypefun)
+(put 'deftypevarx 'texinfo-deffn-formatting-property
+ 'texinfo-format-deftypefun)
+(defun texinfo-format-deftypefun (parsed-args)
+ ;; Specialized typed-function-like or typed-variable-like entity:
+ ;; @deftypefun data-type name args...
+ ;; In Info, `Function: data-type name ARGS'
+ ;; @deftypevar data-type name
+ ;; In Info, `Variable: data-type name'
+ ;; Note: args in lower case, unless modified in command line.
+ ;; Use cdr of texinfo-defun-type to determine category:
+ (let ((category (car (cdr texinfo-defun-type)))
+ (data-type (car parsed-args))
+ (name (car (cdr parsed-args)))
+ (args (cdr (cdr parsed-args))))
+ (insert " -- " category ": " data-type " " name)
+ (while args
+ (insert " " (car args))
+ (setq args (cdr args)))))
+
+;; @defop: Generalized object-oriented
+(put 'defop 'texinfo-deffn-formatting-property 'texinfo-format-defop)
+(put 'defopx 'texinfo-deffn-formatting-property 'texinfo-format-defop)
+(defun texinfo-format-defop (parsed-args)
+ ;; Generalized object oriented entity:
+ ;; @defop category class name args...
+ ;; In Info, `Category on class: name ARG'
+ ;; Note: args in upper case; use of `on'
+ (let ((category (car parsed-args))
+ (class (car (cdr parsed-args)))
+ (name (car (cdr (cdr parsed-args))))
+ (args (cdr (cdr (cdr parsed-args)))))
+ (insert " -- " category " on " class ": " name)
+ (while args
+ (insert " " (upcase (car args)))
+ (setq args (cdr args)))))
+
+;; @defcv: Generalized object-oriented
+(put 'defcv 'texinfo-deffn-formatting-property 'texinfo-format-defcv)
+(put 'defcvx 'texinfo-deffn-formatting-property 'texinfo-format-defcv)
+(defun texinfo-format-defcv (parsed-args)
+ ;; Generalized object oriented entity:
+ ;; @defcv category class name
+ ;; In Info, `Category of class: name'
+ ;; Note: args in upper case; use of `of'
+ (let ((category (car parsed-args))
+ (class (car (cdr parsed-args)))
+ (name (car (cdr (cdr parsed-args))))
+ (args (cdr (cdr (cdr parsed-args)))))
+ (insert " -- " category " of " class ": " name)
+ (while args
+ (insert " " (upcase (car args)))
+ (setq args (cdr args)))))
+
+;; @defmethod: Specialized object-oriented
+(put 'defmethod 'texinfo-deffn-formatting-property 'texinfo-format-defmethod)
+(put 'defmethodx 'texinfo-deffn-formatting-property 'texinfo-format-defmethod)
+(defun texinfo-format-defmethod (parsed-args)
+ ;; Specialized object oriented entity:
+ ;; @defmethod class name args...
+ ;; In Info, `Method on class: name ARGS'
+ ;; Note: args in upper case; use of `on'
+ ;; Use cdr of texinfo-defun-type to determine category:
+ (let ((category (car (cdr texinfo-defun-type)))
+ (class (car parsed-args))
+ (name (car (cdr parsed-args)))
+ (args (cdr (cdr parsed-args))))
+ (insert " -- " category " on " class ": " name)
+ (while args
+ (insert " " (upcase (car args)))
+ (setq args (cdr args)))))
+
+;; @defivar: Specialized object-oriented
+(put 'defivar 'texinfo-deffn-formatting-property 'texinfo-format-defivar)
+(put 'defivarx 'texinfo-deffn-formatting-property 'texinfo-format-defivar)
+(defun texinfo-format-defivar (parsed-args)
+ ;; Specialized object oriented entity:
+ ;; @defivar class name
+ ;; In Info, `Instance variable of class: name'
+ ;; Note: args in upper case; use of `of'
+ ;; Use cdr of texinfo-defun-type to determine category:
+ (let ((category (car (cdr texinfo-defun-type)))
+ (class (car parsed-args))
+ (name (car (cdr parsed-args)))
+ (args (cdr (cdr parsed-args))))
+ (insert " -- " category " of " class ": " name)
+ (while args
+ (insert " " (upcase (car args)))
+ (setq args (cdr args)))))
+
+
+;;; Indexing for definitions
+
+;; An index entry has three parts: the `entry proper', the node name, and the
+;; line number. Depending on the which command is used, the entry is
+;; formatted differently:
+;;
+;; @defun,
+;; @defmac,
+;; @defspec,
+;; @defvar,
+;; @defopt all use their 1st argument as the entry-proper
+;;
+;; @deffn,
+;; @defvr,
+;; @deftp
+;; @deftypefun
+;; @deftypevar all use their 2nd argument as the entry-proper
+;;
+;; @deftypefn,
+;; @deftypevr both use their 3rd argument as the entry-proper
+;;
+;; @defmethod uses its 2nd and 1st arguments as an entry-proper
+;; formatted: NAME on CLASS
+
+;; @defop uses its 3rd and 2nd arguments as an entry-proper
+;; formatted: NAME on CLASS
+;;
+;; @defivar uses its 2nd and 1st arguments as an entry-proper
+;; formatted: NAME of CLASS
+;;
+;; @defcv uses its 3rd and 2nd argument as an entry-proper
+;; formatted: NAME of CLASS
+
+(put 'defun 'texinfo-defun-indexing-property 'texinfo-index-defun)
+(put 'defunx 'texinfo-defun-indexing-property 'texinfo-index-defun)
+(put 'defmac 'texinfo-defun-indexing-property 'texinfo-index-defun)
+(put 'defmacx 'texinfo-defun-indexing-property 'texinfo-index-defun)
+(put 'defspec 'texinfo-defun-indexing-property 'texinfo-index-defun)
+(put 'defspecx 'texinfo-defun-indexing-property 'texinfo-index-defun)
+(put 'defvar 'texinfo-defun-indexing-property 'texinfo-index-defun)
+(put 'defvarx 'texinfo-defun-indexing-property 'texinfo-index-defun)
+(put 'defopt 'texinfo-defun-indexing-property 'texinfo-index-defun)
+(put 'defoptx 'texinfo-defun-indexing-property 'texinfo-index-defun)
+(defun texinfo-index-defun (parsed-args)
+ ;; use 1st parsed-arg as entry-proper
+ ;; `index-list' will be texinfo-findex or the like
+ (let ((index-list (get texinfo-command-name 'texinfo-defun-index)))
+ (set index-list
+ (cons
+ ;; Three elements: entry-proper, node-name, line-number
+ (list
+ (car parsed-args)
+ texinfo-last-node
+ ;; Region formatting may not provide last node position.
+ (if texinfo-last-node-pos
+ (1+ (count-lines texinfo-last-node-pos (point)))
+ 1))
+ (symbol-value index-list)))))
+
+(put 'deffn 'texinfo-defun-indexing-property 'texinfo-index-deffn)
+(put 'deffnx 'texinfo-defun-indexing-property 'texinfo-index-deffn)
+(put 'defvr 'texinfo-defun-indexing-property 'texinfo-index-deffn)
+(put 'defvrx 'texinfo-defun-indexing-property 'texinfo-index-deffn)
+(put 'deftp 'texinfo-defun-indexing-property 'texinfo-index-deffn)
+(put 'deftpx 'texinfo-defun-indexing-property 'texinfo-index-deffn)
+(put 'deftypefun 'texinfo-defun-indexing-property 'texinfo-index-deffn)
+(put 'deftypefunx 'texinfo-defun-indexing-property 'texinfo-index-deffn)
+(put 'deftypevar 'texinfo-defun-indexing-property 'texinfo-index-deffn)
+(put 'deftypevarx 'texinfo-defun-indexing-property 'texinfo-index-deffn)
+(defun texinfo-index-deffn (parsed-args)
+ ;; use 2nd parsed-arg as entry-proper
+ ;; `index-list' will be texinfo-findex or the like
+ (let ((index-list (get texinfo-command-name 'texinfo-defun-index)))
+ (set index-list
+ (cons
+ ;; Three elements: entry-proper, node-name, line-number
+ (list
+ (car (cdr parsed-args))
+ texinfo-last-node
+ ;; Region formatting may not provide last node position.
+ (if texinfo-last-node-pos
+ (1+ (count-lines texinfo-last-node-pos (point)))
+ 1))
+ (symbol-value index-list)))))
+
+(put 'deftypefn 'texinfo-defun-indexing-property 'texinfo-index-deftypefn)
+(put 'deftypefnx 'texinfo-defun-indexing-property 'texinfo-index-deftypefn)
+(put 'deftypevr 'texinfo-defun-indexing-property 'texinfo-index-deftypefn)
+(put 'deftypevrx 'texinfo-defun-indexing-property 'texinfo-index-deftypefn)
+(defun texinfo-index-deftypefn (parsed-args)
+ ;; use 3rd parsed-arg as entry-proper
+ ;; `index-list' will be texinfo-findex or the like
+ (let ((index-list (get texinfo-command-name 'texinfo-defun-index)))
+ (set index-list
+ (cons
+ ;; Three elements: entry-proper, node-name, line-number
+ (list
+ (car (cdr (cdr parsed-args)))
+ texinfo-last-node
+ ;; Region formatting may not provide last node position.
+ (if texinfo-last-node-pos
+ (1+ (count-lines texinfo-last-node-pos (point)))
+ 1))
+ (symbol-value index-list)))))
+
+(put 'defmethod 'texinfo-defun-indexing-property 'texinfo-index-defmethod)
+(put 'defmethodx 'texinfo-defun-indexing-property 'texinfo-index-defmethod)
+(defun texinfo-index-defmethod (parsed-args)
+ ;; use 2nd on 1st parsed-arg as entry-proper
+ ;; `index-list' will be texinfo-findex or the like
+ (let ((index-list (get texinfo-command-name 'texinfo-defun-index)))
+ (set index-list
+ (cons
+ ;; Three elements: entry-proper, node-name, line-number
+ (list
+ (format "%s on %s"
+ (car (cdr parsed-args))
+ (car parsed-args))
+ texinfo-last-node
+ ;; Region formatting may not provide last node position.
+ (if texinfo-last-node-pos
+ (1+ (count-lines texinfo-last-node-pos (point)))
+ 1))
+ (symbol-value index-list)))))
+
+(put 'defop 'texinfo-defun-indexing-property 'texinfo-index-defop)
+(put 'defopx 'texinfo-defun-indexing-property 'texinfo-index-defop)
+(defun texinfo-index-defop (parsed-args)
+ ;; use 3rd on 2nd parsed-arg as entry-proper
+ ;; `index-list' will be texinfo-findex or the like
+ (let ((index-list (get texinfo-command-name 'texinfo-defun-index)))
+ (set index-list
+ (cons
+ ;; Three elements: entry-proper, node-name, line-number
+ (list
+ (format "%s on %s"
+ (car (cdr (cdr parsed-args)))
+ (car (cdr parsed-args)))
+ texinfo-last-node
+ ;; Region formatting may not provide last node position.
+ (if texinfo-last-node-pos
+ (1+ (count-lines texinfo-last-node-pos (point)))
+ 1))
+ (symbol-value index-list)))))
+
+(put 'defivar 'texinfo-defun-indexing-property 'texinfo-index-defivar)
+(put 'defivarx 'texinfo-defun-indexing-property 'texinfo-index-defivar)
+(defun texinfo-index-defivar (parsed-args)
+ ;; use 2nd of 1st parsed-arg as entry-proper
+ ;; `index-list' will be texinfo-findex or the like
+ (let ((index-list (get texinfo-command-name 'texinfo-defun-index)))
+ (set index-list
+ (cons
+ ;; Three elements: entry-proper, node-name, line-number
+ (list
+ (format "%s of %s"
+ (car (cdr parsed-args))
+ (car parsed-args))
+ texinfo-last-node
+ ;; Region formatting may not provide last node position.
+ (if texinfo-last-node-pos
+ (1+ (count-lines texinfo-last-node-pos (point)))
+ 1))
+ (symbol-value index-list)))))
+
+(put 'defcv 'texinfo-defun-indexing-property 'texinfo-index-defcv)
+(put 'defcvx 'texinfo-defun-indexing-property 'texinfo-index-defcv)
+(defun texinfo-index-defcv (parsed-args)
+ ;; use 3rd of 2nd parsed-arg as entry-proper
+ ;; `index-list' will be texinfo-findex or the like
+ (let ((index-list (get texinfo-command-name 'texinfo-defun-index)))
+ (set index-list
+ (cons
+ ;; Three elements: entry-proper, node-name, line-number
+ (list
+ (format "%s of %s"
+ (car (cdr (cdr parsed-args)))
+ (car (cdr parsed-args)))
+ texinfo-last-node
+ ;; Region formatting may not provide last node position.
+ (if texinfo-last-node-pos
+ (1+ (count-lines texinfo-last-node-pos (point)))
+ 1))
+ (symbol-value index-list)))))
+
+
+;;; Properties for definitions
+
+;; Each definition command has six properties:
+;;
+;; 1. texinfo-deffn-formatting-property to format definition line
+;; 2. texinfo-defun-indexing-property to create index entry
+;; 3. texinfo-format formatting command
+;; 4. texinfo-end end formatting command
+;; 5. texinfo-defun-type type of deffn to format
+;; 6. texinfo-defun-index type of index to use
+;;
+;; The `x' forms of each definition command are used for the second
+;; and subsequent header lines.
+
+;; The texinfo-deffn-formatting-property and texinfo-defun-indexing-property
+;; are listed just before the appropriate formatting and indexing commands.
+
+(put 'deffn 'texinfo-format 'texinfo-format-defun)
+(put 'deffnx 'texinfo-format 'texinfo-format-defunx)
+(put 'deffn 'texinfo-end 'texinfo-end-defun)
+(put 'deffn 'texinfo-defun-type '('deffn-type nil))
+(put 'deffnx 'texinfo-defun-type '('deffn-type nil))
+(put 'deffn 'texinfo-defun-index 'texinfo-findex)
+(put 'deffnx 'texinfo-defun-index 'texinfo-findex)
+
+(put 'defun 'texinfo-format 'texinfo-format-defun)
+(put 'defunx 'texinfo-format 'texinfo-format-defunx)
+(put 'defun 'texinfo-end 'texinfo-end-defun)
+(put 'defun 'texinfo-defun-type '('defun-type "Function"))
+(put 'defunx 'texinfo-defun-type '('defun-type "Function"))
+(put 'defun 'texinfo-defun-index 'texinfo-findex)
+(put 'defunx 'texinfo-defun-index 'texinfo-findex)
+
+(put 'defmac 'texinfo-format 'texinfo-format-defun)
+(put 'defmacx 'texinfo-format 'texinfo-format-defunx)
+(put 'defmac 'texinfo-end 'texinfo-end-defun)
+(put 'defmac 'texinfo-defun-type '('defun-type "Macro"))
+(put 'defmacx 'texinfo-defun-type '('defun-type "Macro"))
+(put 'defmac 'texinfo-defun-index 'texinfo-findex)
+(put 'defmacx 'texinfo-defun-index 'texinfo-findex)
+
+(put 'defspec 'texinfo-format 'texinfo-format-defun)
+(put 'defspecx 'texinfo-format 'texinfo-format-defunx)
+(put 'defspec 'texinfo-end 'texinfo-end-defun)
+(put 'defspec 'texinfo-defun-type '('defun-type "Special form"))
+(put 'defspecx 'texinfo-defun-type '('defun-type "Special form"))
+(put 'defspec 'texinfo-defun-index 'texinfo-findex)
+(put 'defspecx 'texinfo-defun-index 'texinfo-findex)
+
+(put 'defvr 'texinfo-format 'texinfo-format-defun)
+(put 'defvrx 'texinfo-format 'texinfo-format-defunx)
+(put 'defvr 'texinfo-end 'texinfo-end-defun)
+(put 'defvr 'texinfo-defun-type '('deffn-type nil))
+(put 'defvrx 'texinfo-defun-type '('deffn-type nil))
+(put 'defvr 'texinfo-defun-index 'texinfo-vindex)
+(put 'defvrx 'texinfo-defun-index 'texinfo-vindex)
+
+(put 'defvar 'texinfo-format 'texinfo-format-defun)
+(put 'defvarx 'texinfo-format 'texinfo-format-defunx)
+(put 'defvar 'texinfo-end 'texinfo-end-defun)
+(put 'defvar 'texinfo-defun-type '('defun-type "Variable"))
+(put 'defvarx 'texinfo-defun-type '('defun-type "Variable"))
+(put 'defvar 'texinfo-defun-index 'texinfo-vindex)
+(put 'defvarx 'texinfo-defun-index 'texinfo-vindex)
+
+(put 'defconst 'texinfo-format 'texinfo-format-defun)
+(put 'defconstx 'texinfo-format 'texinfo-format-defunx)
+(put 'defconst 'texinfo-end 'texinfo-end-defun)
+(put 'defconst 'texinfo-defun-type '('defun-type "Constant"))
+(put 'defconstx 'texinfo-defun-type '('defun-type "Constant"))
+(put 'defconst 'texinfo-defun-index 'texinfo-vindex)
+(put 'defconstx 'texinfo-defun-index 'texinfo-vindex)
+
+(put 'defcmd 'texinfo-format 'texinfo-format-defun)
+(put 'defcmdx 'texinfo-format 'texinfo-format-defunx)
+(put 'defcmd 'texinfo-end 'texinfo-end-defun)
+(put 'defcmd 'texinfo-defun-type '('defun-type "Command"))
+(put 'defcmdx 'texinfo-defun-type '('defun-type "Command"))
+(put 'defcmd 'texinfo-defun-index 'texinfo-findex)
+(put 'defcmdx 'texinfo-defun-index 'texinfo-findex)
+
+(put 'defopt 'texinfo-format 'texinfo-format-defun)
+(put 'defoptx 'texinfo-format 'texinfo-format-defunx)
+(put 'defopt 'texinfo-end 'texinfo-end-defun)
+(put 'defopt 'texinfo-defun-type '('defun-type "User Option"))
+(put 'defoptx 'texinfo-defun-type '('defun-type "User Option"))
+(put 'defopt 'texinfo-defun-index 'texinfo-vindex)
+(put 'defoptx 'texinfo-defun-index 'texinfo-vindex)
+
+(put 'deftp 'texinfo-format 'texinfo-format-defun)
+(put 'deftpx 'texinfo-format 'texinfo-format-defunx)
+(put 'deftp 'texinfo-end 'texinfo-end-defun)
+(put 'deftp 'texinfo-defun-type '('deftp-type nil))
+(put 'deftpx 'texinfo-defun-type '('deftp-type nil))
+(put 'deftp 'texinfo-defun-index 'texinfo-tindex)
+(put 'deftpx 'texinfo-defun-index 'texinfo-tindex)
+
+;;; Object-oriented stuff is a little hairier.
+
+(put 'defop 'texinfo-format 'texinfo-format-defun)
+(put 'defopx 'texinfo-format 'texinfo-format-defunx)
+(put 'defop 'texinfo-end 'texinfo-end-defun)
+(put 'defop 'texinfo-defun-type '('defop-type nil))
+(put 'defopx 'texinfo-defun-type '('defop-type nil))
+(put 'defop 'texinfo-defun-index 'texinfo-findex)
+(put 'defopx 'texinfo-defun-index 'texinfo-findex)
+
+(put 'defmethod 'texinfo-format 'texinfo-format-defun)
+(put 'defmethodx 'texinfo-format 'texinfo-format-defunx)
+(put 'defmethod 'texinfo-end 'texinfo-end-defun)
+(put 'defmethod 'texinfo-defun-type '('defmethod-type "Method"))
+(put 'defmethodx 'texinfo-defun-type '('defmethod-type "Method"))
+(put 'defmethod 'texinfo-defun-index 'texinfo-findex)
+(put 'defmethodx 'texinfo-defun-index 'texinfo-findex)
+
+(put 'defcv 'texinfo-format 'texinfo-format-defun)
+(put 'defcvx 'texinfo-format 'texinfo-format-defunx)
+(put 'defcv 'texinfo-end 'texinfo-end-defun)
+(put 'defcv 'texinfo-defun-type '('defop-type nil))
+(put 'defcvx 'texinfo-defun-type '('defop-type nil))
+(put 'defcv 'texinfo-defun-index 'texinfo-vindex)
+(put 'defcvx 'texinfo-defun-index 'texinfo-vindex)
+
+(put 'defivar 'texinfo-format 'texinfo-format-defun)
+(put 'defivarx 'texinfo-format 'texinfo-format-defunx)
+(put 'defivar 'texinfo-end 'texinfo-end-defun)
+(put 'defivar 'texinfo-defun-type '('defmethod-type "Instance variable"))
+(put 'defivarx 'texinfo-defun-type '('defmethod-type "Instance variable"))
+(put 'defivar 'texinfo-defun-index 'texinfo-vindex)
+(put 'defivarx 'texinfo-defun-index 'texinfo-vindex)
+
+;;; Typed functions and variables
+
+(put 'deftypefn 'texinfo-format 'texinfo-format-defun)
+(put 'deftypefnx 'texinfo-format 'texinfo-format-defunx)
+(put 'deftypefn 'texinfo-end 'texinfo-end-defun)
+(put 'deftypefn 'texinfo-defun-type '('deftypefn-type nil))
+(put 'deftypefnx 'texinfo-defun-type '('deftypefn-type nil))
+(put 'deftypefn 'texinfo-defun-index 'texinfo-findex)
+(put 'deftypefnx 'texinfo-defun-index 'texinfo-findex)
+
+(put 'deftypefun 'texinfo-format 'texinfo-format-defun)
+(put 'deftypefunx 'texinfo-format 'texinfo-format-defunx)
+(put 'deftypefun 'texinfo-end 'texinfo-end-defun)
+(put 'deftypefun 'texinfo-defun-type '('deftypefun-type "Function"))
+(put 'deftypefunx 'texinfo-defun-type '('deftypefun-type "Function"))
+(put 'deftypefun 'texinfo-defun-index 'texinfo-findex)
+(put 'deftypefunx 'texinfo-defun-index 'texinfo-findex)
+
+(put 'deftypevr 'texinfo-format 'texinfo-format-defun)
+(put 'deftypevrx 'texinfo-format 'texinfo-format-defunx)
+(put 'deftypevr 'texinfo-end 'texinfo-end-defun)
+(put 'deftypevr 'texinfo-defun-type '('deftypefn-type nil))
+(put 'deftypevrx 'texinfo-defun-type '('deftypefn-type nil))
+(put 'deftypevr 'texinfo-defun-index 'texinfo-vindex)
+(put 'deftypevrx 'texinfo-defun-index 'texinfo-vindex)
+
+(put 'deftypevar 'texinfo-format 'texinfo-format-defun)
+(put 'deftypevarx 'texinfo-format 'texinfo-format-defunx)
+(put 'deftypevar 'texinfo-end 'texinfo-end-defun)
+(put 'deftypevar 'texinfo-defun-type '('deftypevar-type "Variable"))
+(put 'deftypevarx 'texinfo-defun-type '('deftypevar-type "Variable"))
+(put 'deftypevar 'texinfo-defun-index 'texinfo-vindex)
+(put 'deftypevarx 'texinfo-defun-index 'texinfo-vindex)
+
+
+;;; @set, @clear, @ifset, @ifclear
+
+;; If a flag is set with @set FLAG, then text between @ifset and @end
+;; ifset is formatted normally, but if the flag is is cleared with
+;; @clear FLAG, then the text is not formatted; it is ignored.
+
+;; If a flag is cleared with @clear FLAG, then text between @ifclear
+;; and @end ifclear is formatted normally, but if the flag is is set with
+;; @set FLAG, then the text is not formatted; it is ignored. @ifclear
+;; is the opposite of @ifset.
+
+;; If a flag is set to a string with @set FLAG,
+;; replace @value{FLAG} with the string.
+;; If a flag with a value is cleared,
+;; @value{FLAG} is invalid,
+;; as if there had never been any @set FLAG previously.
+
+(put 'clear 'texinfo-format 'texinfo-clear)
+(defun texinfo-clear ()
+ "Clear the value of the flag."
+ (let* ((arg (texinfo-parse-arg-discard))
+ (flag (car (read-from-string arg)))
+ (value (substring arg (cdr (read-from-string arg)))))
+ (put flag 'texinfo-whether-setp 'flag-cleared)
+ (put flag 'texinfo-set-value "")))
+
+(put 'set 'texinfo-format 'texinfo-set)
+(defun texinfo-set ()
+ "Set the value of the flag, optionally to a string.
+The command `@set foo This is a string.'
+sets flag foo to the value: `This is a string.'
+The command `@value{foo}' expands to the value."
+ (let* ((arg (texinfo-parse-arg-discard))
+ (flag (car (read-from-string arg)))
+ (value (substring arg (cdr (read-from-string arg)))))
+ (put flag 'texinfo-whether-setp 'flag-set)
+ (put flag 'texinfo-set-value value)))
+
+(put 'value 'texinfo-format 'texinfo-value)
+(defun texinfo-value ()
+ "Insert the string to which the flag is set.
+The command `@set foo This is a string.'
+sets flag foo to the value: `This is a string.'
+The command `@value{foo}' expands to the value."
+ (let ((arg (texinfo-parse-arg-discard)))
+ (cond ((and
+ (eq (get (car (read-from-string arg)) 'texinfo-whether-setp)
+ 'flag-set)
+ (get (car (read-from-string arg)) 'texinfo-set-value))
+ (insert (get (car (read-from-string arg)) 'texinfo-set-value)))
+ ((eq (get (car (read-from-string arg)) 'texinfo-whether-setp)
+ 'flag-cleared)
+ (insert (format "{No value for \"%s\"}" arg)))
+ ((eq (get (car (read-from-string arg)) 'texinfo-whether-setp) nil)
+ (insert (format "{No value for \"%s\"}" arg))))))
+
+(put 'ifset 'texinfo-end 'texinfo-discard-command)
+(put 'ifset 'texinfo-format 'texinfo-if-set)
+(defun texinfo-if-set ()
+ "If set, continue formatting; else do not format region up to @end ifset"
+ (let ((arg (texinfo-parse-arg-discard)))
+ (cond
+ ((eq (get (car (read-from-string arg)) 'texinfo-whether-setp)
+ 'flag-set)
+ ;; Format the text (i.e., do not remove it); do nothing here.
+ ())
+ ((eq (get (car (read-from-string arg)) 'texinfo-whether-setp)
+ 'flag-cleared)
+ ;; Clear region (i.e., cause the text to be ignored).
+ (delete-region texinfo-command-start
+ (progn (re-search-forward "@end ifset[ \t]*\n")
+ (point))))
+ ((eq (get (car (read-from-string arg)) 'texinfo-whether-setp)
+ nil)
+ ;; In this case flag is neither set nor cleared.
+ ;; Act as if set, i.e. do nothing.
+ ()))))
+
+(put 'ifclear 'texinfo-end 'texinfo-discard-command)
+(put 'ifclear 'texinfo-format 'texinfo-if-clear)
+(defun texinfo-if-clear ()
+ "If clear, continue formatting; if set, do not format up to @end ifset"
+ (let ((arg (texinfo-parse-arg-discard)))
+ (cond
+ ((eq (get (car (read-from-string arg)) 'texinfo-whether-setp)
+ 'flag-set)
+ ;; Clear region (i.e., cause the text to be ignored).
+ (delete-region texinfo-command-start
+ (progn (re-search-forward "@end ifclear[ \t]*\n")
+ (point))))
+ ((eq (get (car (read-from-string arg)) 'texinfo-whether-setp)
+ 'flag-cleared)
+ ;; Format the text (i.e., do not remove it); do nothing here.
+ ())
+ ((eq (get (car (read-from-string arg)) 'texinfo-whether-setp)
+ nil)
+ ;; In this case flag is neither set nor cleared.
+ ;; Act as if clear, i.e. do nothing.
+ ()))))
+
+
+;;; @ifeq
+
+(put 'ifeq 'texinfo-format 'texinfo-format-ifeq)
+(defun texinfo-format-ifeq ()
+ "If ARG1 and ARG2 caselessly string compare to same string, performs COMMAND.
+Otherwise produces no output.
+
+Thus:
+ @ifeq{ arg1 , arg1 , @code{foo}} bar
+
+ ==> `foo' bar.
+but
+ @ifeq{ arg1 , arg2 , @code{foo}} bar
+
+ ==> bar
+
+Note that the Texinfo command and its arguments must be arguments to
+the @ifeq command."
+ ;; compare-buffer-substrings does not exist in version 18; don't use
+ (goto-char texinfo-command-end)
+ (let* ((case-fold-search t)
+ (stop (save-excursion (forward-sexp 1) (point)))
+ start end
+ ;; @ifeq{arg1, arg2, @command{optional-args}}
+ (arg1
+ (progn
+ (forward-char 1)
+ (skip-chars-forward " ")
+ (setq start (point))
+ (search-forward "," stop t)
+ (skip-chars-backward ", ")
+ (buffer-substring start (point))))
+ (arg2
+ (progn
+ (search-forward "," stop t)
+ (skip-chars-forward " ")
+ (setq start (point))
+ (search-forward "," stop t)
+ (skip-chars-backward ", ")
+ (buffer-substring start (point))))
+ (texinfo-command
+ (progn
+ (search-forward "," stop t)
+ (skip-chars-forward " ")
+ (setq start (point))
+ (goto-char (1- stop))
+ (skip-chars-backward " ")
+ (buffer-substring start (point)))))
+ (delete-region texinfo-command-start stop)
+ (if (equal arg1 arg2)
+ (insert texinfo-command))
+ (goto-char texinfo-command-start)))
+
+
+;;; Process included files: `@include' command
+
+;; Updated 19 October 1990
+;; In the original version, include files were ignored by Info but
+;; incorporated in to the printed manual. To make references to the
+;; included file, the Texinfo source file has to refer to the included
+;; files using the `(filename)nodename' format for referring to other
+;; Info files. Also, the included files had to be formatted on their
+;; own. It was just like they were another file.
+
+;; Currently, include files are inserted into the buffer that is
+;; formatted for Info. If large, the resulting info file is split and
+;; tagified. For current include files to work, the master menu must
+;; refer to all the nodes, and the highest level nodes in the include
+;; files must have the correct next, prev, and up pointers.
+
+;; The included file may have an @setfilename and even an @settitle,
+;; but not an `\input texinfo' line.
+
+;; Updated 24 March 1993
+;; In order for @raisesections and @lowersections to work, included
+;; files must be inserted into the buffer holding the outer file
+;; before other Info formatting takes place. So @include is no longer
+;; is treated like other @-commands.
+(put 'include 'texinfo-format 'texinfo-format-noop)
+
+;; Original definition:
+;; (defun texinfo-format-include ()
+;; (let ((filename (texinfo-parse-arg-discard))
+;; (default-directory input-directory)
+;; subindex)
+;; (setq subindex
+;; (save-excursion
+;; (progn (find-file
+;; (cond ((file-readable-p (concat filename ".texinfo"))
+;; (concat filename ".texinfo"))
+;; ((file-readable-p (concat filename ".texi"))
+;; (concat filename ".texi"))
+;; ((file-readable-p (concat filename ".tex"))
+;; (concat filename ".tex"))
+;; ((file-readable-p filename)
+;; filename)
+;; (t (error "@include'd file %s not found"
+;; filename))))
+;; (texinfo-format-buffer-1))))
+;; (texinfo-subindex 'texinfo-vindex (car subindex) (nth 1 subindex))
+;; (texinfo-subindex 'texinfo-findex (car subindex) (nth 2 subindex))
+;; (texinfo-subindex 'texinfo-cindex (car subindex) (nth 3 subindex))
+;; (texinfo-subindex 'texinfo-pindex (car subindex) (nth 4 subindex))
+;; (texinfo-subindex 'texinfo-tindex (car subindex) (nth 5 subindex))
+;; (texinfo-subindex 'texinfo-kindex (car subindex) (nth 6 subindex))))
+;;
+;;(defun texinfo-subindex (indexvar file content)
+;; (set indexvar (cons (list 'recurse file content)
+;; (symbol-value indexvar))))
+
+;; Second definition:
+;; (put 'include 'texinfo-format 'texinfo-format-include)
+;; (defun texinfo-format-include ()
+;; (let ((filename (concat input-directory
+;; (texinfo-parse-arg-discard)))
+;; (default-directory input-directory))
+;; (message "Reading: %s" filename)
+;; (save-excursion
+;; (save-restriction
+;; (narrow-to-region
+;; (point)
+;; (+ (point) (car (cdr (insert-file-contents filename)))))
+;; (goto-char (point-min))
+;; (texinfo-append-refill)
+;; (texinfo-format-convert (point-min) (point-max))))
+;; (setq last-input-buffer input-buffer) ; to bypass setfilename
+;; ))
+
+
+;;; Numerous commands do nothing in Info
+;; These commands are defined in texinfo.tex for printed output.
+
+
+;;; various noops, such as @b{foo}, that take arguments in braces
+
+(put 'b 'texinfo-format 'texinfo-format-noop)
+(put 'i 'texinfo-format 'texinfo-format-noop)
+(put 'r 'texinfo-format 'texinfo-format-noop)
+(put 't 'texinfo-format 'texinfo-format-noop)
+(put 'w 'texinfo-format 'texinfo-format-noop)
+(put 'asis 'texinfo-format 'texinfo-format-noop)
+(put 'dmn 'texinfo-format 'texinfo-format-noop)
+(put 'math 'texinfo-format 'texinfo-format-noop)
+(put 'titlefont 'texinfo-format 'texinfo-format-noop)
+(defun texinfo-format-noop ()
+ (insert (texinfo-parse-arg-discard))
+ (goto-char texinfo-command-start))
+
+;; @hyphenation command discards an argument within braces
+(put 'hyphenation 'texinfo-format 'texinfo-discard-command-and-arg)
+(defun texinfo-discard-command-and-arg ()
+ "Discard both @-command and its argument in braces."
+ (goto-char texinfo-command-end)
+ (forward-list 1)
+ (setq texinfo-command-end (point))
+ (delete-region texinfo-command-start texinfo-command-end))
+
+
+;;; Do nothing commands, such as @smallbook, that have no args and no braces
+;; These must appear on a line of their own
+
+(put 'bye 'texinfo-format 'texinfo-discard-line)
+(put 'smallbook 'texinfo-format 'texinfo-discard-line)
+(put 'finalout 'texinfo-format 'texinfo-discard-line)
+(put 'overfullrule 'texinfo-format 'texinfo-discard-line)
+(put 'smallbreak 'texinfo-format 'texinfo-discard-line)
+(put 'medbreak 'texinfo-format 'texinfo-discard-line)
+(put 'bigbreak 'texinfo-format 'texinfo-discard-line)
+
+
+;;; These noop commands discard the rest of the line.
+
+(put 'c 'texinfo-format 'texinfo-discard-line-with-args)
+(put 'comment 'texinfo-format 'texinfo-discard-line-with-args)
+(put 'contents 'texinfo-format 'texinfo-discard-line-with-args)
+(put 'group 'texinfo-end 'texinfo-discard-line-with-args)
+(put 'group 'texinfo-format 'texinfo-discard-line-with-args)
+(put 'headings 'texinfo-format 'texinfo-discard-line-with-args)
+(put 'setchapterstyle 'texinfo-format 'texinfo-discard-line-with-args)
+(put 'hsize 'texinfo-format 'texinfo-discard-line-with-args)
+(put 'itemindent 'texinfo-format 'texinfo-discard-line-with-args)
+(put 'lispnarrowing 'texinfo-format 'texinfo-discard-line-with-args)
+(put 'need 'texinfo-format 'texinfo-discard-line-with-args)
+(put 'nopara 'texinfo-format 'texinfo-discard-line-with-args)
+(put 'page 'texinfo-format 'texinfo-discard-line-with-args)
+(put 'parindent 'texinfo-format 'texinfo-discard-line-with-args)
+(put 'setchapternewpage 'texinfo-format 'texinfo-discard-line-with-args)
+(put 'setq 'texinfo-format 'texinfo-discard-line-with-args)
+(put 'settitle 'texinfo-format 'texinfo-discard-line-with-args)
+(put 'setx 'texinfo-format 'texinfo-discard-line-with-args)
+(put 'shortcontents 'texinfo-format 'texinfo-discard-line-with-args)
+(put 'shorttitlepage 'texinfo-format 'texinfo-discard-line-with-args)
+(put 'summarycontents 'texinfo-format 'texinfo-discard-line-with-args)
+(put 'input 'texinfo-format 'texinfo-discard-line-with-args)
+(put 'dircategory 'texinfo-format 'texinfo-discard-line-with-args)
+
+
+;;; Some commands cannot be handled
+
+(defun texinfo-unsupported ()
+ (error "%s is not handled by texinfo"
+ (buffer-substring texinfo-command-start texinfo-command-end)))
+
+;;; Batch formatting
+
+(defun batch-texinfo-format ()
+ "Runs texinfo-format-buffer on the files remaining on the command line.
+Must be used only with -batch, and kills emacs on completion.
+Each file will be processed even if an error occurred previously.
+For example, invoke
+ \"emacs -batch -funcall batch-texinfo-format $docs/ ~/*.texinfo\"."
+ (if (not noninteractive)
+ (error "batch-texinfo-format may only be used -batch."))
+ (let ((version-control t)
+ (auto-save-default nil)
+ (find-file-run-dired nil)
+ (kept-old-versions 259259)
+ (kept-new-versions 259259))
+ (let ((error 0)
+ file
+ (files ()))
+ (while command-line-args-left
+ (setq file (expand-file-name (car command-line-args-left)))
+ (cond ((not (file-exists-p file))
+ (message ">> %s does not exist!" file)
+ (setq error 1
+ command-line-args-left (cdr command-line-args-left)))
+ ((file-directory-p file)
+ (setq command-line-args-left
+ (nconc (directory-files file)
+ (cdr command-line-args-left))))
+ (t
+ (setq files (cons file files)
+ command-line-args-left (cdr command-line-args-left)))))
+ (while files
+ (setq file (car files)
+ files (cdr files))
+ (condition-case err
+ (progn
+ (if buffer-file-name (kill-buffer (current-buffer)))
+ (find-file file)
+ (buffer-disable-undo (current-buffer))
+ (set-buffer-modified-p nil)
+ (texinfo-mode)
+ (message "texinfo formatting %s..." file)
+ (texinfo-format-buffer nil)
+ (if (buffer-modified-p)
+ (progn (message "Saving modified %s" (buffer-file-name))
+ (save-buffer))))
+ (error
+ (message ">> Error: %s" (prin1-to-string err))
+ (message ">> point at")
+ (let ((s (buffer-substring (point)
+ (min (+ (point) 100)
+ (point-max))))
+ (tem 0))
+ (while (setq tem (string-match "\n+" s tem))
+ (setq s (concat (substring s 0 (match-beginning 0))
+ "\n>> "
+ (substring s (match-end 0)))
+ tem (1+ tem)))
+ (message ">> %s" s))
+ (setq error 1))))
+ (kill-emacs error))))
+
+
+;;; Place `provide' at end of file.
+(provide 'texinfmt)
+
+;;; texinfmt.el ends here.
diff --git a/contrib/texinfo/emacs/texinfo.el b/contrib/texinfo/emacs/texinfo.el
new file mode 100644
index 0000000..0a1ab13
--- /dev/null
+++ b/contrib/texinfo/emacs/texinfo.el
@@ -0,0 +1,932 @@
+;;; texinfo.el--major mode for editing Texinfo files.
+
+;; Copyright (C) 1985, '88, '89, '90, '91,
+;; '92, '93, '96 Free Software Foundation, Inc.
+
+;; Author: Robert J. Chassell
+;; Date: 6 Sep 1996
+;; Maintainer: bug-texinfo@prep.ai.mit.edu
+;; Keywords: maint, tex, docs
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs 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, or (at your option)
+;; any later version.
+
+;; GNU Emacs 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; see the file COPYING. If not, write to the
+;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+
+;;; Autoloads:
+
+(autoload 'makeinfo-region
+ "makeinfo"
+ "Make Info file from region of current Texinfo file, and switch to it.
+
+This command does not offer the `next-error' feature since it would
+apply to a temporary file, not the original; use the `makeinfo-buffer'
+command to gain use of `next-error'."
+ t nil)
+
+(autoload 'makeinfo-buffer
+ "makeinfo"
+ "Make Info file from current buffer.
+
+Use the \\[next-error] command to move to the next error
+\(if there are errors\)."
+ t nil)
+
+(autoload 'kill-compilation
+ "compile"
+ "Kill the process made by the \\[compile] command."
+ t nil)
+
+(autoload 'makeinfo-recenter-compilation-buffer
+ "makeinfo"
+ "Redisplay `*compilation*' buffer so most recent output can be seen.
+The last line of the buffer is displayed on
+line LINE of the window, or centered if LINE is nil."
+ t nil)
+
+(autoload 'texinfo-update-node
+ "texnfo-upd"
+ "Without any prefix argument, update the node in which point is located.
+Non-nil argument (prefix, if interactive) means update the nodes in the
+marked region.
+
+The functions for creating or updating nodes and menus, and their
+keybindings, are:
+
+ texinfo-update-node (&optional region-p) \\[texinfo-update-node]
+ texinfo-every-node-update () \\[texinfo-every-node-update]
+ texinfo-sequential-node-update (&optional region-p)
+
+ texinfo-make-menu (&optional region-p) \\[texinfo-make-menu]
+ texinfo-all-menus-update () \\[texinfo-all-menus-update]
+ texinfo-master-menu ()
+
+ texinfo-indent-menu-description (column &optional region-p)
+
+The `texinfo-column-for-description' variable specifies the column to
+which menu descriptions are indented. Its default value is 32."
+ t nil)
+
+(autoload 'texinfo-every-node-update
+ "texnfo-upd"
+ "Update every node in a Texinfo file."
+ t nil)
+
+(autoload 'texinfo-sequential-node-update
+ "texnfo-upd"
+ "Update one node (or many) in a Texinfo file with sequential pointers.
+
+This function causes the `Next' or `Previous' pointer to point to the
+immediately preceding or following node, even if it is at a higher or
+lower hierarchical level in the document. Continually pressing `n' or
+`p' takes you straight through the file.
+
+Without any prefix argument, update the node in which point is located.
+Non-nil argument (prefix, if interactive) means update the nodes in the
+marked region.
+
+This command makes it awkward to navigate among sections and
+subsections; it should be used only for those documents that are meant
+to be read like a novel rather than a reference, and for which the
+Info `g*' command is inadequate."
+ t nil)
+
+(autoload 'texinfo-make-menu
+ "texnfo-upd"
+ "Without any prefix argument, make or update a menu.
+Make the menu for the section enclosing the node found following point.
+
+Non-nil argument (prefix, if interactive) means make or update menus
+for nodes within or part of the marked region.
+
+Whenever a menu exists, and is being updated, the descriptions that
+are associated with node names in the pre-existing menu are
+incorporated into the new menu. Otherwise, the nodes' section titles
+are inserted as descriptions."
+ t nil)
+
+(autoload 'texinfo-all-menus-update
+ "texnfo-upd"
+ "Update every regular menu in a Texinfo file.
+Remove pre-existing master menu, if there is one.
+
+If called with a non-nil argument, this function first updates all the
+nodes in the buffer before updating the menus."
+ t nil)
+
+(autoload 'texinfo-master-menu
+ "texnfo-upd"
+ "Make a master menu for a whole Texinfo file.
+Non-nil argument (prefix, if interactive) means first update all
+existing nodes and menus. Remove pre-existing master menu, if there is one.
+
+This function creates a master menu that follows the top node. The
+master menu includes every entry from all the other menus. It
+replaces any existing ordinary menu that follows the top node.
+
+If called with a non-nil argument, this function first updates all the
+menus in the buffer (incorporating descriptions from pre-existing
+menus) before it constructs the master menu.
+
+The function removes the detailed part of an already existing master
+menu. This action depends on the pre-existing master menu using the
+standard `texinfo-master-menu-header'.
+
+The master menu has the following format, which is adapted from the
+recommendation in the Texinfo Manual:
+
+ * The first part contains the major nodes in the Texinfo file: the
+ nodes for the chapters, chapter-like sections, and the major
+ appendices. This includes the indices, so long as they are in
+ chapter-like sections, such as unnumbered sections.
+
+ * The second and subsequent parts contain a listing of the other,
+ lower level menus, in order. This way, an inquirer can go
+ directly to a particular node if he or she is searching for
+ specific information.
+
+Each of the menus in the detailed node listing is introduced by the
+title of the section containing the menu."
+ t nil)
+
+(autoload 'texinfo-indent-menu-description
+ "texnfo-upd"
+ "Indent every description in menu following point to COLUMN.
+Non-nil argument (prefix, if interactive) means indent every
+description in every menu in the region. Does not indent second and
+subsequent lines of a multi-line description."
+ t nil)
+
+(autoload 'texinfo-insert-node-lines
+ "texnfo-upd"
+ "Insert missing `@node' lines in region of Texinfo file.
+Non-nil argument (prefix, if interactive) means also to insert the
+section titles as node names; and also to insert the section titles as
+node names in pre-existing @node lines that lack names."
+ t nil)
+
+(autoload 'texinfo-start-menu-description
+ "texnfo-upd"
+ "In this menu entry, insert the node's section title as a description.
+Position point at beginning of description ready for editing.
+Do not insert a title if the line contains an existing description.
+
+You will need to edit the inserted text since a useful description
+complements the node name rather than repeats it as a title does."
+ t nil)
+
+(autoload 'texinfo-multiple-files-update
+ "texnfo-upd"
+ "Update first node pointers in each file included in OUTER-FILE;
+create or update main menu in the outer file that refers to such nodes.
+This does not create or update menus or pointers within the included files.
+
+With optional MAKE-MASTER-MENU argument (prefix arg, if interactive),
+insert a master menu in OUTER-FILE. This does not create or update
+menus or pointers within the included files.
+
+With optional UPDATE-EVERYTHING argument (numeric prefix arg, if
+interactive), update all the menus and all the `Next', `Previous', and
+`Up' pointers of all the files included in OUTER-FILE before inserting
+a master menu in OUTER-FILE.
+
+The command also updates the `Top' level node pointers of OUTER-FILE.
+
+Notes:
+
+ * this command does NOT save any files--you must save the
+ outer file and any modified, included files.
+
+ * except for the `Top' node, this command does NOT handle any
+ pre-existing nodes in the outer file; hence, indices must be
+ enclosed in an included file.
+
+Requirements:
+
+ * each of the included files must contain exactly one highest
+ hierarchical level node,
+ * this highest node must be the first node in the included file,
+ * each highest hierarchical level node must be of the same type.
+
+Thus, normally, each included file contains one, and only one,
+chapter."
+ t nil)
+
+
+;;; Code:
+
+;;; Don't you dare insert any `require' calls at top level in this file--rms.
+
+;;; Syntax table
+
+(defvar texinfo-mode-syntax-table nil)
+
+(if texinfo-mode-syntax-table
+ nil
+ (setq texinfo-mode-syntax-table (make-syntax-table))
+ (modify-syntax-entry ?\" " " texinfo-mode-syntax-table)
+ (modify-syntax-entry ?\\ " " texinfo-mode-syntax-table)
+ (modify-syntax-entry ?@ "\\" texinfo-mode-syntax-table)
+ (modify-syntax-entry ?\^q "\\" texinfo-mode-syntax-table)
+ (modify-syntax-entry ?\[ "(]" texinfo-mode-syntax-table)
+ (modify-syntax-entry ?\] ")[" texinfo-mode-syntax-table)
+ (modify-syntax-entry ?{ "(}" texinfo-mode-syntax-table)
+ (modify-syntax-entry ?} "){" texinfo-mode-syntax-table)
+ (modify-syntax-entry ?\' "w" texinfo-mode-syntax-table))
+
+;; Written by Wolfgang Bangerth <zcg51122@rpool1.rus.uni-stuttgart.de>
+;; To override this example, set either `imenu-generic-expression'
+;; or `imenu-create-index-function'.
+(defvar texinfo-imenu-generic-expression
+ '((nil "^@node[ \t]+\\([^,\n]*\\)" 1)
+ ("Chapters" "^@chapter[ \t]+\\(.*\\)$" 1))
+
+ "Imenu generic expression for TexInfo mode. See `imenu-generic-expression'.")
+
+(defvar texinfo-font-lock-keywords
+ '(;; All but the first 2 had an OVERRIDE of t.
+ ;; It didn't seem to be any better, and it's slower--simon.
+ ("^\\(@c\\|@comment\\)\\>.*" . font-lock-comment-face) ;comments
+ ;; Robert J. Chassell <bob@gnu.ai.mit.edu> says remove this line.
+ ;("\\$\\([^$]*\\)\\$" 1 font-lock-string-face t)
+ ("@\\([a-zA-Z]+\\|[^ \t\n]\\)" 1 font-lock-keyword-face) ;commands
+ ("^\\*\\(.*\\)[\t ]*$" 1 font-lock-function-name-face t) ;menu items
+ ("@\\(emph\\|strong\\|b\\|i\\){\\([^}]+\\)" 2 font-lock-comment-face)
+ ("@\\(file\\|kbd\\|key\\){\\([^}]+\\)" 2 font-lock-string-face)
+ ("@\\(samp\\|code\\|var\\|math\\){\\([^}]+\\)"
+ 2 font-lock-variable-name-face)
+ ("@\\(cite\\|xref\\|pxref\\){\\([^}]+\\)" 2 font-lock-reference-face)
+ ("@\\(end\\|itemx?\\) +\\(.+\\)" 2 font-lock-function-name-face keep)
+ )
+ "Additional expressions to highlight in TeXinfo mode.")
+
+(defvar texinfo-section-list
+ '(("top" 1)
+ ("majorheading" 1)
+ ("chapter" 2)
+ ("unnumbered" 2)
+ ("appendix" 2)
+ ("chapheading" 2)
+ ("section" 3)
+ ("unnumberedsec" 3)
+ ("appendixsec" 3)
+ ("heading" 3)
+ ("subsection" 4)
+ ("unnumberedsubsec" 4)
+ ("appendixsubsec" 4)
+ ("subheading" 4)
+ ("subsubsection" 5)
+ ("unnumberedsubsubsec" 5)
+ ("appendixsubsubsec" 5)
+ ("subsubheading" 5))
+ "Alist of sectioning commands and their relative level.")
+
+(defun texinfo-outline-level ()
+ ;; Calculate level of current texinfo outline heading.
+ (save-excursion
+ (if (bobp)
+ 0
+ (forward-char 1)
+ (let* ((word (buffer-substring-no-properties
+ (point) (progn (forward-word 1) (point))))
+ (entry (assoc word texinfo-section-list)))
+ (if entry
+ (nth 1 entry)
+ 5)))))
+
+
+;;; Keybindings
+(defvar texinfo-mode-map nil)
+
+;;; Keys common both to Texinfo mode and to TeX shell.
+
+(defun texinfo-define-common-keys (keymap)
+ "Define the keys both in Texinfo mode and in the texinfo-tex-shell."
+ (define-key keymap "\C-c\C-t\C-k" 'tex-kill-job)
+ (define-key keymap "\C-c\C-t\C-x" 'texinfo-quit-job)
+ (define-key keymap "\C-c\C-t\C-l" 'tex-recenter-output-buffer)
+ (define-key keymap "\C-c\C-t\C-d" 'texinfo-delete-from-print-queue)
+ (define-key keymap "\C-c\C-t\C-q" 'tex-show-print-queue)
+ (define-key keymap "\C-c\C-t\C-p" 'texinfo-tex-print)
+ (define-key keymap "\C-c\C-t\C-i" 'texinfo-texindex)
+
+ (define-key keymap "\C-c\C-t\C-r" 'texinfo-tex-region)
+ (define-key keymap "\C-c\C-t\C-b" 'texinfo-tex-buffer))
+
+;; Mode documentation displays commands in reverse order
+;; from how they are listed in the texinfo-mode-map.
+
+(if texinfo-mode-map
+ nil
+ (setq texinfo-mode-map (make-sparse-keymap))
+
+ ;; bindings for `texnfo-tex.el'
+ (texinfo-define-common-keys texinfo-mode-map)
+
+ ;; bindings for `makeinfo.el'
+ (define-key texinfo-mode-map "\C-c\C-m\C-k" 'kill-compilation)
+ (define-key texinfo-mode-map "\C-c\C-m\C-l"
+ 'makeinfo-recenter-compilation-buffer)
+ (define-key texinfo-mode-map "\C-c\C-m\C-r" 'makeinfo-region)
+ (define-key texinfo-mode-map "\C-c\C-m\C-b" 'makeinfo-buffer)
+
+ ;; bindings for `texinfmt.el'
+ (define-key texinfo-mode-map "\C-c\C-e\C-r" 'texinfo-format-region)
+ (define-key texinfo-mode-map "\C-c\C-e\C-b" 'texinfo-format-buffer)
+
+ ;; bindings for updating nodes and menus
+
+ (define-key texinfo-mode-map "\C-c\C-um" 'texinfo-master-menu)
+
+ (define-key texinfo-mode-map "\C-c\C-u\C-m" 'texinfo-make-menu)
+ (define-key texinfo-mode-map "\C-c\C-u\C-n" 'texinfo-update-node)
+ (define-key texinfo-mode-map "\C-c\C-u\C-e" 'texinfo-every-node-update)
+ (define-key texinfo-mode-map "\C-c\C-u\C-a" 'texinfo-all-menus-update)
+
+ (define-key texinfo-mode-map "\C-c\C-s" 'texinfo-show-structure)
+
+ (define-key texinfo-mode-map "\C-c}" 'up-list)
+ (define-key texinfo-mode-map "\C-c]" 'up-list)
+ (define-key texinfo-mode-map "\C-c{" 'texinfo-insert-braces)
+
+ ;; bindings for inserting strings
+
+ (define-key texinfo-mode-map "\C-c\C-c\C-d" 'texinfo-start-menu-description)
+
+ (define-key texinfo-mode-map "\C-c\C-cv" 'texinfo-insert-@var)
+ (define-key texinfo-mode-map "\C-c\C-ct" 'texinfo-insert-@table)
+ (define-key texinfo-mode-map "\C-c\C-cs" 'texinfo-insert-@samp)
+ (define-key texinfo-mode-map "\C-c\C-co" 'texinfo-insert-@noindent)
+ (define-key texinfo-mode-map "\C-c\C-cn" 'texinfo-insert-@node)
+ (define-key texinfo-mode-map "\C-c\C-ck" 'texinfo-insert-@kbd)
+ (define-key texinfo-mode-map "\C-c\C-ci" 'texinfo-insert-@item)
+ (define-key texinfo-mode-map "\C-c\C-cf" 'texinfo-insert-@file)
+ (define-key texinfo-mode-map "\C-c\C-cx" 'texinfo-insert-@example)
+ (define-key texinfo-mode-map "\C-c\C-ce" 'texinfo-insert-@end)
+ (define-key texinfo-mode-map "\C-c\C-cd" 'texinfo-insert-@dfn)
+ (define-key texinfo-mode-map "\C-c\C-cc" 'texinfo-insert-@code))
+
+
+;;; Texinfo mode
+
+(defvar texinfo-chapter-level-regexp
+ "chapter\\|unnumbered \\|appendix \\|majorheading\\|chapheading"
+ "Regular expression matching Texinfo chapter-level headings.
+This does not match `@node' and does not match the `@top' command.")
+
+;;;###autoload
+(defun texinfo-mode ()
+ "Major mode for editing Texinfo files.
+
+ It has these extra commands:
+\\{texinfo-mode-map}
+
+ These are files that are used as input for TeX to make printed manuals
+and also to be turned into Info files with \\[makeinfo-buffer] or
+the `makeinfo' program. These files must be written in a very restricted and
+modified version of TeX input format.
+
+ Editing commands are like text-mode except that the syntax table is
+set up so expression commands skip Texinfo bracket groups. To see
+what the Info version of a region of the Texinfo file will look like,
+use \\[makeinfo-region], which runs `makeinfo' on the current region.
+
+ You can show the structure of a Texinfo file with \\[texinfo-show-structure].
+This command shows the structure of a Texinfo file by listing the
+lines with the @-sign commands for @chapter, @section, and the like.
+These lines are displayed in another window called the *Occur* window.
+In that window, you can position the cursor over one of the lines and
+use \\[occur-mode-goto-occurrence], to jump to the corresponding spot
+in the Texinfo file.
+
+ In addition, Texinfo mode provides commands that insert various
+frequently used @-sign commands into the buffer. You can use these
+commands to save keystrokes. And you can insert balanced braces with
+\\[texinfo-insert-braces] and later use the command \\[up-list] to
+move forward past the closing brace.
+
+Also, Texinfo mode provides functions for automatically creating or
+updating menus and node pointers. These functions
+
+ * insert the `Next', `Previous' and `Up' pointers of a node,
+ * insert or update the menu for a section, and
+ * create a master menu for a Texinfo source file.
+
+Here are the functions:
+
+ texinfo-update-node \\[texinfo-update-node]
+ texinfo-every-node-update \\[texinfo-every-node-update]
+ texinfo-sequential-node-update
+
+ texinfo-make-menu \\[texinfo-make-menu]
+ texinfo-all-menus-update \\[texinfo-all-menus-update]
+ texinfo-master-menu
+
+ texinfo-indent-menu-description (column &optional region-p)
+
+The `texinfo-column-for-description' variable specifies the column to
+which menu descriptions are indented.
+
+Passed an argument (a prefix argument, if interactive), the
+`texinfo-update-node' and `texinfo-make-menu' functions do their jobs
+in the region.
+
+To use the updating commands, you must structure your Texinfo file
+hierarchically, such that each `@node' line, with the exception of the
+Top node, is accompanied by some kind of section line, such as an
+`@chapter' or `@section' line.
+
+If the file has a `top' node, it must be called `top' or `Top' and
+be the first node in the file.
+
+Entering Texinfo mode calls the value of text-mode-hook, and then the
+value of texinfo-mode-hook."
+ (interactive)
+ (text-mode)
+ (setq mode-name "Texinfo")
+ (setq major-mode 'texinfo-mode)
+ (use-local-map texinfo-mode-map)
+ (set-syntax-table texinfo-mode-syntax-table)
+ (make-local-variable 'page-delimiter)
+ (setq page-delimiter
+ (concat
+ "^@node [ \t]*[Tt]op\\|^@\\("
+ texinfo-chapter-level-regexp
+ "\\)"))
+ (make-local-variable 'require-final-newline)
+ (setq require-final-newline t)
+ (make-local-variable 'indent-tabs-mode)
+ (setq indent-tabs-mode nil)
+ (make-local-variable 'paragraph-separate)
+ (setq paragraph-separate (concat "^\b\\|^@[a-zA-Z]*[ \n]\\|" paragraph-separate))
+ (make-local-variable 'paragraph-start)
+ (setq paragraph-start (concat "^\b\\|^@[a-zA-Z]*[ \n]\\|" paragraph-start))
+ (make-local-variable 'fill-column)
+ (setq fill-column 72)
+ (make-local-variable 'comment-start)
+ (setq comment-start "@c ")
+ (make-local-variable 'comment-start-skip)
+ (setq comment-start-skip "@c +")
+ (make-local-variable 'words-include-escapes)
+ (setq words-include-escapes t)
+ (make-local-variable 'imenu-generic-expression)
+ (setq imenu-generic-expression texinfo-imenu-generic-expression)
+ (make-local-variable 'font-lock-defaults)
+ (setq font-lock-defaults '(texinfo-font-lock-keywords t))
+ (make-local-variable 'outline-regexp)
+ (setq outline-regexp
+ (concat "@\\("
+ (mapconcat 'car texinfo-section-list "\\>\\|")
+ "\\>\\)"))
+ (make-local-variable 'outline-level)
+ (setq outline-level 'texinfo-outline-level)
+ (make-local-variable 'tex-start-of-header)
+ (setq tex-start-of-header "%**start")
+ (make-local-variable 'tex-end-of-header)
+ (setq tex-end-of-header "%**end")
+ (run-hooks 'text-mode-hook 'texinfo-mode-hook))
+
+
+;;; Insert string commands
+
+;; Keep as concatinated lists for ease of maintenance
+(defconst texinfo-environment-regexp
+ (concat
+ "^@"
+ "\\("
+ "cartouche\\|"
+ "display\\|"
+ "end\\|"
+ "enumerate\\|"
+ "example\\|"
+ "f?table\\|"
+ "flushleft\\|"
+ "flushright\\|"
+ "format\\|"
+ "group\\|"
+ "ifhtml\\|"
+ "ifinfo\\|"
+ "iftex\\|"
+ "ignore\\|"
+ "itemize\\|"
+ "lisp\\|"
+ "macro\\|"
+ "multitable\\|"
+ "quotation\\|"
+ "smallexample\\|"
+ "smalllisp\\|"
+ "tex"
+ "\\)")
+ "Regexp for environment-like TexInfo list commands.
+ Subexpression 1 is what goes into the corresponding `@end' statement.")
+
+;; The following texinfo-insert-@end command not only inserts a SPC
+;; after the @end, but tries to find out what belongs there. It is
+;; not very smart: it does not understand nested lists.
+
+(defun texinfo-insert-@end ()
+ "Insert the matching `@end' for the last Texinfo command that needs one."
+ (interactive)
+ (let ((depth 1) string)
+ (save-excursion
+ (while (and (> depth 0)
+ (re-search-backward texinfo-environment-regexp nil t)
+ (if (looking-at "@end")
+ (setq depth (1+ depth))
+ (setq depth (1- depth)))))
+ (looking-at texinfo-environment-regexp)
+ (if (zerop depth)
+ (setq string
+ (buffer-substring (match-beginning 1)
+ (match-end 1)))))
+ (insert "@end ")
+ (if string (insert string "\n"))))
+
+;; The following insert commands accept a prefix arg N, which is the
+;; number of words (actually s-exprs) that should be surrounded by
+;; braces. Thus you can first paste a variable name into a .texinfo
+;; buffer, then say C-u 1 C-c C-c v at the beginning of the just
+;; pasted variable name to put @var{...} *around* the variable name.
+;; Operate on previous word or words with negative arg.
+
+;; These commands use texinfo-insert-@-with-arg
+(defun texinfo-insert-@-with-arg (string &optional arg)
+ (if arg
+ (progn
+ (setq arg (prefix-numeric-value arg))
+ (if (< arg 0)
+ (progn
+ (skip-chars-backward " \t\n\r\f")
+ (save-excursion
+ (forward-sexp arg)
+ (insert "@" string "{"))
+ (insert "}"))
+ (skip-chars-forward " \t\n\r\f")
+ (insert "@" string "{")
+ (forward-sexp arg)
+ (insert "}")))
+ (insert "@" string "{}")
+ (backward-char)))
+
+(defun texinfo-insert-braces ()
+ "Make a pair of braces and be poised to type inside of them.
+Use \\[up-list] to move forward out of the braces."
+ (interactive)
+ (insert "{}")
+ (backward-char))
+
+(defun texinfo-insert-@code (&optional arg)
+ "Insert a `@code{...}' command in a Texinfo buffer.
+A numeric argument says how many words the braces should surround.
+The default is not to surround any existing words with the braces."
+ (interactive "P")
+ (texinfo-insert-@-with-arg "code" arg))
+
+(defun texinfo-insert-@dfn (&optional arg)
+ "Insert a `@dfn{...}' command in a Texinfo buffer.
+A numeric argument says how many words the braces should surround.
+The default is not to surround any existing words with the braces."
+ (interactive "P")
+ (texinfo-insert-@-with-arg "dfn" arg))
+
+(defun texinfo-insert-@example ()
+ "Insert the string `@example' in a Texinfo buffer."
+ (interactive)
+ (insert "@example\n"))
+
+(defun texinfo-insert-@file (&optional arg)
+ "Insert a `@file{...}' command in a Texinfo buffer.
+A numeric argument says how many words the braces should surround.
+The default is not to surround any existing words with the braces."
+ (interactive "P")
+ (texinfo-insert-@-with-arg "file" arg))
+
+(defun texinfo-insert-@item ()
+ "Insert the string `@item' in a Texinfo buffer."
+ (interactive)
+ (insert "@item")
+ (newline))
+
+(defun texinfo-insert-@kbd (&optional arg)
+ "Insert a `@kbd{...}' command in a Texinfo buffer.
+A numeric argument says how many words the braces should surround.
+The default is not to surround any existing words with the braces."
+ (interactive "P")
+ (texinfo-insert-@-with-arg "kbd" arg))
+
+(defun texinfo-insert-@node ()
+ "Insert the string `@node' in a Texinfo buffer.
+This also inserts on the following line a comment indicating
+the order of arguments to @node."
+ (interactive)
+ (insert "@node \n@comment node-name, next, previous, up")
+ (forward-line -1)
+ (forward-char 6))
+
+(defun texinfo-insert-@noindent ()
+ "Insert the string `@noindent' in a Texinfo buffer."
+ (interactive)
+ (insert "@noindent\n"))
+
+(defun texinfo-insert-@samp (&optional arg)
+ "Insert a `@samp{...}' command in a Texinfo buffer.
+A numeric argument says how many words the braces should surround.
+The default is not to surround any existing words with the braces."
+ (interactive "P")
+ (texinfo-insert-@-with-arg "samp" arg))
+
+(defun texinfo-insert-@table (&optional arg)
+ "Insert the string `@table' in a Texinfo buffer."
+ (interactive "P")
+ (insert "@table "))
+
+(defun texinfo-insert-@var (&optional arg)
+ "Insert a `@var{}' command in a Texinfo buffer.
+A numeric argument says how many words the braces should surround.
+The default is not to surround any existing words with the braces."
+ (interactive "P")
+ (texinfo-insert-@-with-arg "var" arg))
+
+;;; Texinfo file structure
+
+;; These are defined in texnfo-upd.el.
+;; texinfo-section-types-regexp
+;; texinfo-section-level-regexp
+;; texinfo-subsection-level-regexp
+;; texinfo-subsubsection-level-regexp
+
+;; `texinfo-show-structure' requires texnfo-upd.el
+(defun texinfo-show-structure (&optional nodes-too)
+ "Show the structure of a Texinfo file.
+List the lines in the file that begin with the @-sign commands for
+@chapter, @section, and the like.
+
+With optional argument (prefix if interactive), list both the lines
+with @-sign commands for @chapter, @section, and the like, and list
+@node lines.
+
+Lines with structuring commands beginning in them are displayed in
+another buffer named `*Occur*'. In that buffer, you can move point to
+one of those lines and then use \\<occur-mode-map>\\[occur-mode-goto-occurrence],
+to jump to the corresponding spot in the Texinfo source file."
+
+ (interactive "P")
+ (require 'texnfo-upd)
+ (save-excursion
+ (goto-char (point-min))
+ (if nodes-too
+ (occur (concat "\\(^@node\\)\\|" texinfo-section-types-regexp))
+ (occur texinfo-section-types-regexp)))
+ (pop-to-buffer "*Occur*")
+ (goto-char (point-min))
+ (flush-lines "-----")
+ ;; Now format the "*Occur*" buffer to show the structure.
+ ;; Thanks to ceder@signum.se (Per Cederqvist)
+ (goto-char (point-max))
+ (let ((margin 5))
+ (while (re-search-backward "^ *[0-9]*:" nil 0)
+ (re-search-forward ":")
+ (setq margin
+ (cond
+ ((looking-at
+ (concat "@\\(" texinfo-chapter-level-regexp "\\)")) 5)
+ ;; ((looking-at "@chapter ") 5)
+ ;; ((looking-at "@unnumbered ") 5)
+ ;; ((looking-at "@appendix ") 5)
+ ;; ((looking-at "@majorheading ") 5)
+ ;; ((looking-at "@chapheading ") 5)
+
+ ((looking-at
+ (concat "@\\(" texinfo-section-level-regexp "\\)")) 9)
+ ;; ((looking-at "@section ") 9)
+ ;; ((looking-at "@unnumberedsec ") 9)
+ ;; ((looking-at "@appendixsec ") 9)
+ ;; ((looking-at "@heading ") 9)
+
+ ((looking-at
+ (concat "@\\(" texinfo-subsection-level-regexp "\\)")) 13)
+ ;; ((looking-at "@subsection ") 13)
+ ;; ((looking-at "@unnumberedsubsec ") 13)
+ ;; ((looking-at "@appendixsubsec ") 13)
+ ;; ((looking-at "@subheading ") 13)
+
+ ((looking-at
+ (concat "@\\(" texinfo-subsubsection-level-regexp "\\)")) 17)
+ ;; ((looking-at "@subsubsection ") 17)
+ ;; ((looking-at "@unnumberedsubsubsec ") 17)
+ ;; ((looking-at "@appendixsubsubsec ") 17)
+ ;; ((looking-at "@subsubheading ") 17)
+ (t margin)))
+ (indent-to-column margin)
+ (beginning-of-line))))
+
+;;; The tex and print function definitions:
+
+(defvar texinfo-texi2dvi-command "texi2dvi"
+ "*Command used by `texinfo-tex-buffer' to run TeX and texindex on a buffer.")
+
+(defvar texinfo-tex-command "tex"
+ "*Command used by `texinfo-tex-region' to run TeX on a region.")
+
+(defvar texinfo-texindex-command "texindex"
+ "*Command used by `texinfo-texindex' to sort unsorted index files.")
+
+(defvar texinfo-delete-from-print-queue-command "lprm"
+ "*Command string used to delete a job from the line printer queue.
+Command is used by \\[texinfo-delete-from-print-queue] based on
+number provided by a previous \\[tex-show-print-queue]
+command.")
+
+(defvar texinfo-tex-trailer "@bye"
+ "String appended after a region sent to TeX by `texinfo-tex-region'.")
+
+(defun texinfo-tex-region (beg end)
+ "Run TeX on the current region.
+This works by writing a temporary file (`tex-zap-file') in the directory
+that is the value of `tex-directory', then running TeX on that file.
+
+The first line of the buffer is copied to the
+temporary file; and if the buffer has a header, it is written to the
+temporary file before the region itself. The buffer's header is all lines
+between the strings defined by `tex-start-of-header' and `tex-end-of-header'
+inclusive. The header must start in the first 100 lines.
+
+The value of `texinfo-tex-trailer' is appended to the temporary file after the region."
+ (interactive "r")
+ (require 'tex-mode)
+ (if (get-buffer "*tex-shell*")
+ (tex-kill-job)
+ (tex-start-shell))
+ (or tex-zap-file (setq tex-zap-file (make-temp-name "#tz")))
+ (let ((tex-out-file (concat tex-zap-file ".tex"))
+ (temp-buffer (get-buffer-create " tex-Output-Buffer"))
+ (zap-directory
+ (file-name-as-directory (expand-file-name tex-directory))))
+ (save-excursion
+ (save-restriction
+ (widen)
+ (goto-char (point-min))
+ (forward-line 100)
+ (let ((search-end (point))
+ (hbeg (point-min)) (hend (point-min))
+ (default-directory zap-directory))
+ (goto-char (point-min))
+
+ ;; Copy first line, the `\input texinfo' line, to temp file
+ (write-region (point)
+ (save-excursion (end-of-line) (point))
+ tex-out-file nil nil)
+
+ ;; Don't copy first line twice if region includes it.
+ (forward-line 1)
+ (if (< beg (point)) (setq beg (point)))
+
+ ;; Initialize the temp file with either the header or nothing
+ (if (search-forward tex-start-of-header search-end t)
+ (progn
+ (beginning-of-line)
+ (setq hbeg (point)) ; Mark beginning of header.
+ (if (search-forward tex-end-of-header nil t)
+ (progn (beginning-of-line)
+ (setq hend (point))) ; Mark end of header.
+ (setq hbeg (point-min))))) ; Else no header.
+
+ ;; Copy header to temp file.
+ (write-region (min hbeg beg) hend tex-out-file t nil)
+
+ ;; Copy region to temp file.
+ (write-region (max beg hend) end tex-out-file t nil))
+
+ ;; This is a kludge to insert the tex-trailer into the tex-out-file.
+ ;; We have to create a special buffer in which to insert
+ ;; the tex-trailer first because there is no function with
+ ;; which to append a literal string directly to a file.
+ (let ((local-tex-trailer texinfo-tex-trailer))
+ (set-buffer temp-buffer)
+ (erase-buffer)
+ ;; make sure trailer isn't hidden by a comment
+ (insert-string "\n")
+ (if local-tex-trailer (insert-string local-tex-trailer))
+ (tex-set-buffer-directory temp-buffer zap-directory)
+ (write-region (point-min) (point-max) tex-out-file t nil))
+
+;;; The following is sufficient in Emacs 19.
+;;; (write-region (concat "\n" texinfo-tex-trailer) nil
+;;; tex-out-file t nil)
+ ))
+
+ (tex-set-buffer-directory "*tex-shell*" zap-directory)
+ (tex-send-command tex-shell-cd-command zap-directory)
+ (tex-send-command texinfo-tex-command tex-out-file)
+ ;; alternatively:
+ ;; (send-string "tex-shell" (concat tex-shell-cd-command " "
+ ;; zap-directory "\n"))
+ ;; (send-string "tex-shell" (concat texinfo-tex-command " "
+ ;; tex-out-file "\n"))
+ (tex-recenter-output-buffer 0)))
+
+(defun texinfo-tex-buffer ()
+ "Run TeX on visited file, once or twice, to make a correct `.dvi' file."
+ (interactive)
+
+ ;; Make sure TeX shell is running.
+ (require 'tex-mode)
+ (if (get-buffer "*tex-shell*")
+ (quit-process (get-process "tex-shell") t)
+ (tex-start-shell))
+
+ (cond ((null buffer-file-name)
+ (error "Buffer not visiting any file!"))
+ ((buffer-modified-p)
+ (error "Buffer has been modified since last saved!")))
+
+ (setq tex-zap-file buffer-file-name)
+
+ (tex-send-command tex-shell-cd-command (file-name-directory tex-zap-file))
+
+ (tex-send-command texinfo-texi2dvi-command tex-zap-file)
+
+ ;; alternatively:
+ ;; (send-string "tex-shell"
+ ;; (concat tex-shell-cd-command
+ ;; " " (file-name-directory tex-zap-file) "\n"))
+ ;; )
+ ;;
+ ;; (send-string "tex-shell"
+ ;; (concat texinfo-texi2dvi-command " " tex-zap-file "\n"))
+
+
+ (tex-recenter-output-buffer 0))
+
+(defun texinfo-texindex ()
+ "Run `texindex' on unsorted index files.
+The index files are made by \\[texinfo-tex-region] or \\[texinfo-tex-buffer].
+This runs the shell command defined by `texinfo-texindex-command'."
+ (interactive)
+ (require 'tex-mode)
+ (tex-send-command texinfo-texindex-command (concat tex-zap-file ".??"))
+ ;; alternatively
+ ;; (send-string "tex-shell"
+ ;; (concat texinfo-texindex-command
+ ;; " " tex-zap-file ".??" "\n"))
+ (tex-recenter-output-buffer nil))
+
+(defun texinfo-tex-print ()
+ "Print `.dvi' file made by \\[texinfo-tex-region] or \\[texinfo-tex-buffer].
+This runs the shell command defined by `tex-dvi-print-command'."
+ (interactive)
+ (require 'tex-mode)
+ (tex-send-command tex-dvi-print-command (concat tex-zap-file ".dvi"))
+ ;; alternatively:
+ ;; (send-string "tex-shell"
+ ;; (concat tex-dvi-print-command
+ ;; " " tex-zap-file ".dvi" "\n"))
+ (tex-recenter-output-buffer nil))
+
+(defun texinfo-quit-job ()
+ "Quit currently running TeX job, by sending an `x' to it."
+ (interactive)
+ (if (not (get-process "tex-shell"))
+ (error "No TeX shell running"))
+ (tex-send-command "x"))
+;; alternatively:
+;; save-excursion
+;; (set-buffer (get-buffer "*tex-shell*"))
+;; (goto-char (point-max))
+;; (insert "x")
+;; (comint-send-input)
+
+(defun texinfo-delete-from-print-queue (job-number)
+ "Delete job from the line printer spooling queue.
+You are prompted for the job number (use a number shown by a previous
+\\[tex-show-print-queue] command)."
+ (interactive "nPrinter job number for deletion: ")
+ (require 'tex-mode)
+ (if (tex-shell-running)
+ (tex-kill-job)
+ (tex-start-shell))
+ (tex-send-command texinfo-delete-from-print-queue-command job-number)
+ ;; alternatively
+ ;; (send-string "tex-shell"
+ ;; (concat
+ ;; texinfo-delete-from-print-queue-command
+ ;; " "
+ ;; job-number"\n"))
+ (tex-recenter-output-buffer nil))
+
+(provide 'texinfo)
+
+;;; texinfo.el ends here
diff --git a/contrib/texinfo/emacs/texnfo-tex.el b/contrib/texinfo/emacs/texnfo-tex.el
new file mode 100644
index 0000000..225ea68
--- /dev/null
+++ b/contrib/texinfo/emacs/texnfo-tex.el
@@ -0,0 +1,346 @@
+;;;; texnfo-tex.el
+
+;;; Texinfo mode TeX and hardcopy printing commands.
+
+;; These commands are for running TeX on a region of a Texinfo file in
+;; GNU Emacs, or on the whole buffer, and for printing the resulting
+;; DVI file.
+
+;;; Version 2.07 22 October 1991
+;;; Robert J. Chassell
+;;; Please send bug reports to: bug-texinfo@prep.ai.mit.edu
+
+;;; Copyright (C) 1989, 1990, 1991 Free Software Foundation, Inc.
+
+
+;;; This file is part of GNU Emacs.
+
+;; GNU Emacs 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, or (at your option)
+;; any later version.
+
+;; GNU Emacs 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; see the file COPYING. If not, write to
+;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+
+
+;;; The Texinfo mode TeX related commands are:
+
+; texinfo-tex-region to run tex on the current region.
+; texinfo-tex-buffer to run tex on the current buffer.
+; texinfo-texindex to sort unsorted index files.
+; texinfo-tex-print to print the .dvi file made by tex.
+; texinfo-kill-tex-job to kill the currently running tex job.
+; texinfo-recenter-tex-output-buffer to redisplay tex output buffer.
+; texinfo-show-tex-print-queue to show the print queue.
+
+
+;;; Keys common both to Texinfo mode and to TeX shell.
+
+;; Defined in `texinfo.el'
+; (defun texinfo-define-common-keys (keymap)
+; "Define the keys both in Texinfo mode and in the texinfo-tex-shell."
+; (define-key keymap "\C-c\C-t\C-k" 'texinfo-kill-tex-job)
+; (define-key keymap "\C-c\C-t\C-x" 'texinfo-quit-tex-job)
+; (define-key keymap "\C-c\C-t\C-l" 'texinfo-recenter-tex-output-buffer)
+; (define-key keymap "\C-c\C-t\C-d" 'texinfo-delete-from-tex-print-queue)
+; (define-key keymap "\C-c\C-t\C-q" 'texinfo-show-tex-print-queue)
+; (define-key keymap "\C-c\C-t\C-p" 'texinfo-tex-print)
+; (define-key keymap "\C-c\C-t\C-i" 'texinfo-texindex)
+; (define-key keymap "\C-c\C-t\C-r" 'texinfo-tex-region)
+; (define-key keymap "\C-c\C-t\C-b" 'texinfo-tex-buffer))
+
+;; See also texinfo-tex-start-shell.
+;; The following is executed in the `texinfo.el' file
+;(texinfo-define-common-keys texinfo-mode-map)
+
+
+;;; Variable definitions:
+
+(require 'shell)
+
+(defvar texinfo-tex-shell-cd-command "cd"
+ "Command to give to shell running TeX to change directory.")
+
+(defvar texinfo-tex-command "tex"
+ "*Command used by texinfo-tex-region to run tex on a region.")
+
+(defvar texinfo-texindex-command "texindex"
+ "*Command used by texinfo-texindex to sort unsorted index files.")
+
+(defvar texinfo-tex-dvi-print-command "lpr -d"
+ "*Command string used by \\[tex-print] to print a .dvi file.")
+
+(defvar texinfo-show-tex-queue-command "lpq"
+ "*Command string used to show the Texinfo TeX print queue.
+Command is used by \\[texinfo-show-tex-print-queue] and it
+should show the queue that \\[texinfo-tex-print] puts jobs on.")
+
+(defvar texinfo-delete-from-print-queue-command "lprm"
+ "*Command string used to delete a job from the line printer queue.
+Command is used by \\[texinfo-delete-from-tex-print-queue] based on
+number provided by a previous \\[texinfo-show-tex-print-queue]
+command.")
+
+(defvar texinfo-tex-trailer "@bye"
+ "String appended after a region sent to TeX by texinfo-tex-region.")
+
+(defvar texinfo-tex-original-file ""
+ "Original name of file on which to run TeX.")
+
+(defvar texinfo-tex-temp-file nil
+ "Temporary file name used for text being sent as input to TeX.")
+
+(defvar texinfo-tex-root-temp-file nil
+ "Temporary file name used for text being sent as input to TeX.")
+
+
+;;; Texinfo TeX main functions
+
+(defun texinfo-tex-region (beginning end)
+ "Run tex on the current region.
+
+A temporary file is written in the default directory, and tex is run
+in that directory. The first line of the file is copied to the
+temporary file; and if the buffer has a header, it is written to the
+temporary file before the region itself. The buffer's header is all
+lines between the strings defined by texinfo-start-of-header and
+texinfo-end-of-header inclusive. The header must start in the first 100
+lines. The value of texinfo-tex-trailer is appended to the temporary file
+after the region."
+
+ (interactive "r")
+ (if (get-buffer "*texinfo-tex-shell*")
+ (quit-process (get-process "texinfo-tex-shell") t)
+ (texinfo-tex-start-shell))
+
+ (setq texinfo-tex-root-temp-file
+ (expand-file-name
+ (make-temp-name
+ (prin1-to-string (read (buffer-name))))))
+
+ (let ((texinfo-tex-temp-file (concat texinfo-tex-root-temp-file ".tex")))
+ (save-excursion
+ (save-restriction
+ (widen)
+ (goto-char (point-min))
+ (forward-line 100)
+ (let ((search-end (point))
+ (header-beginning (point-min)) (header-end (point-min)))
+ (goto-char (point-min))
+ ;; Copy first line, the `\input texinfo' line, to temp file
+ (write-region (point)
+ (save-excursion (forward-line 1) (point))
+ texinfo-tex-temp-file nil nil)
+ ;; Don't copy first line twice if region includes it.
+ (forward-line 1)
+ (if (< beginning (point)) (setq beginning (point)))
+ ;; Initialize the temp file with either the header or nothing
+ (if (search-forward texinfo-start-of-header search-end t)
+ (progn
+ (beginning-of-line)
+ (setq header-beginning (point)) ; Mark beginning of header.
+ (if (search-forward texinfo-end-of-header nil t)
+ (progn (beginning-of-line)
+ (setq header-end (point))) ; Mark end of header.
+ (setq header-beginning (point-min))))) ; Else no header.
+ ;; Copy header to temp file.
+ (write-region
+ (min header-beginning beginning )
+ header-end
+ texinfo-tex-temp-file t nil)
+ ;; Copy region to temp file.
+ (write-region
+ (max beginning header-end)
+ end
+ texinfo-tex-temp-file t nil)
+ ;; This is a kludge to insert the texinfo-tex-trailer into the
+ ;; texinfo-tex-temp-file. We have to create a special buffer
+ ;; in which to insert the texinfo-tex-trailer first because there is
+ ;; no function with which to append a literal string directly
+ ;; to a file.
+ (let ((local-tex-trailer texinfo-tex-trailer)
+ (temp-buffer (get-buffer-create " texinfo-trailer-buffer")))
+ (set-buffer temp-buffer)
+ (erase-buffer)
+ ;; make sure trailer isn't hidden by a comment
+ (insert-string "\n")
+ (if local-tex-trailer (insert local-tex-trailer))
+ (write-region (point-min) (point-max)
+ texinfo-tex-temp-file t nil)))
+ (set-process-sentinel (get-process "texinfo-tex-shell")
+ 'texinfo-tex-shell-sentinel)
+ (send-string "texinfo-tex-shell"
+ (concat texinfo-tex-shell-cd-command " "
+ default-directory "\n"))
+ (send-string "texinfo-tex-shell"
+ (concat texinfo-tex-command " "
+ texinfo-tex-temp-file "\n "))
+ (texinfo-recenter-tex-output-buffer 0)))))
+
+(defun texinfo-tex-buffer (buffer)
+ "Run TeX on current buffer.
+After running TeX the first time, you may have to run \\[texinfo-texindex]
+and then \\[texinfo-tex-buffer] again."
+ (interactive
+ (list
+ ;; Sometimes you put point into *texinfo-tex-shell*; this prompts
+ ;; you for the correct file regardless.
+ (if (and
+ (string= (buffer-name (current-buffer)) "*texinfo-tex-shell*")
+ texinfo-tex-root-temp-file)
+ (read-string (format "Run TeX on: ")
+ texinfo-tex-original-file)
+ (read-string (format "Run TeX on: ") (buffer-name (current-buffer))))))
+
+ ;; Set to original buffer if in *texinfo-tex-shell*; otherwise,
+ ;; record name of current buffer.
+ (if (string= (buffer-name (current-buffer)) "*texinfo-tex-shell*")
+ (set-buffer buffer)
+ (setq texinfo-tex-original-file
+ (buffer-name (current-buffer))))
+
+ (if (get-buffer "*texinfo-tex-shell*")
+ (quit-process (get-process "texinfo-tex-shell") t)
+ (texinfo-tex-start-shell))
+ (cond ((null buffer-file-name)
+ (error "Buffer not visiting any file!"))
+ ((buffer-modified-p)
+ (error "Buffer has been modified since last saved!"))
+ (t (set-process-sentinel (get-process "texinfo-tex-shell")
+ 'texinfo-tex-shell-sentinel)
+ (send-string "texinfo-tex-shell"
+ (concat texinfo-tex-shell-cd-command
+ " "
+ (file-name-directory
+ (buffer-file-name
+ (get-buffer buffer)))
+ "\n"))
+ (send-string "texinfo-tex-shell"
+ (concat texinfo-tex-command " " buffer "\n "))
+
+ ;; so the texinfo-tex-print command works
+ (setq texinfo-tex-root-temp-file
+ (substring buffer 0
+ (or (string-match "\\.tex" buffer)
+ (length buffer))))
+
+ (texinfo-recenter-tex-output-buffer 0))))
+
+(defun texinfo-texindex ()
+ "Run texindex on unsorted index files.
+The index files are made by \\[texinfo-tex-region] or \\[texinfo-tex-buffer].
+Runs the shell command defined by texinfo-texindex-command."
+ (interactive)
+ (send-string "texinfo-tex-shell"
+ (concat texinfo-texindex-command
+ " " texinfo-tex-root-temp-file ".??" "\n"))
+ (texinfo-recenter-tex-output-buffer nil))
+
+(defun texinfo-tex-print ()
+ "Print .dvi file made by \\[texinfo-tex-region] or \\[texinfo-tex-buffer].
+Runs the shell command defined by texinfo-tex-dvi-print-command."
+ (interactive)
+ (send-string "texinfo-tex-shell"
+ (concat texinfo-tex-dvi-print-command
+ " " texinfo-tex-root-temp-file ".dvi" "\n"))
+ (texinfo-recenter-tex-output-buffer nil))
+
+
+;;; Texinfo TeX utility functions
+
+(defun texinfo-tex-start-shell ()
+ (save-excursion
+ (require 'texinfo)
+ (set-buffer (make-shell "texinfo-tex-shell" "/bin/sh" nil "-v"))
+ (setq texinfo-tex-shell-map (copy-keymap shell-mode-map))
+ (texinfo-define-common-keys texinfo-tex-shell-map)
+ (use-local-map texinfo-tex-shell-map)
+ (run-hooks 'texinfo-tex-shell-hook)
+ (if (zerop (buffer-size))
+ (sleep-for 1))))
+
+(defun texinfo-quit-tex-job ()
+ "Quit currently running TeX job, by sending an `x' to it."
+ (interactive)
+ (if (not (get-process "texinfo-tex-shell"))
+ (error "No TeX shell running."))
+ (save-excursion
+ (set-buffer (get-buffer "*texinfo-tex-shell*"))
+ (goto-char (point-max))
+ (insert "x")
+ (shell-send-input)))
+
+(defun texinfo-kill-tex-job ()
+ "Kill the currently running TeX job."
+ (interactive)
+ (if (get-process "texinfo-tex-shell")
+ ;; Use `texinfo-tex-shell-sentinel' to restart
+ ;; texinfo-tex-shell after it is killed.
+ (kill-process (get-process "texinfo-tex-shell"))))
+
+(defun texinfo-tex-shell-sentinel (process event)
+ "Restart texinfo-tex-shell after it is killed."
+ (if (equal event "killed\n")
+ (save-excursion
+ (set-buffer "*texinfo-tex-shell*")
+ (insert "\n")
+ (texinfo-tex-start-shell))))
+
+(defun texinfo-recenter-tex-output-buffer (linenum)
+ "Redisplay buffer of TeX job output so that most recent output can be seen.
+The last line of the buffer is displayed on
+line LINE of the window, or centered if LINE is nil."
+ (interactive "P")
+ (let ((texinfo-tex-shell (get-buffer "*texinfo-tex-shell*"))
+ (old-buffer (current-buffer)))
+ (if (null texinfo-tex-shell)
+ (message "No TeX output buffer")
+ (pop-to-buffer texinfo-tex-shell)
+ (bury-buffer texinfo-tex-shell)
+ (goto-char (point-max))
+ (recenter (if linenum
+ (prefix-numeric-value linenum)
+ (/ (window-height) 2)))
+ (pop-to-buffer old-buffer)
+ )))
+
+(defun texinfo-show-tex-print-queue ()
+ "Show the print queue that \\[texinfo-tex-print] put your job on.
+Runs the shell command defined by texinfo-show-tex-queue-command."
+ (interactive)
+ (if (not (texinfo-tex-shell-running-p))
+ (texinfo-tex-start-shell))
+ (send-string "texinfo-tex-shell"
+ (concat texinfo-show-tex-queue-command "\n"))
+ (texinfo-recenter-tex-output-buffer nil))
+
+(defun texinfo-delete-from-tex-print-queue (job-number)
+ "Delete job from the line printer spooling queue.
+You are prompted for the job number (shown by a previous
+\\[texinfo-show-tex-print-queue] command."
+ (interactive "nPrinter job number for deletion: ")
+ (if (texinfo-tex-shell-running-p)
+ (texinfo-kill-tex-job)
+ (texinfo-tex-start-shell))
+ (send-string "texinfo-tex-shell"
+ (concat
+ texinfo-delete-from-print-queue-command
+ " "
+ job-number"\n"))
+ (texinfo-recenter-tex-output-buffer nil))
+
+(defun texinfo-tex-shell-running-p ()
+ (and (get-process "texinfo-tex-shell")
+ (eq (process-status (get-process "texinfo-tex-shell")) 'run)))
+
+
+;;; Place `provide' at end of file.
+(provide 'texnfo-tex)
+;;;;;;;;;;;;;;;; end texnfo-tex.el ;;;;;;;;;;;;;;;;
diff --git a/contrib/texinfo/emacs/texnfo-upd.el b/contrib/texinfo/emacs/texnfo-upd.el
new file mode 100644
index 0000000..4827fe5
--- /dev/null
+++ b/contrib/texinfo/emacs/texnfo-upd.el
@@ -0,0 +1,2058 @@
+;;; texnfo-upd.el --- utilities for updating nodes and menus in Texinfo files
+
+;; Copyright 1989, 1990, 1991, 1992, 1996 Free Software Foundation, Inc.
+
+;; Author: Robert J. Chassell
+;; Date: 12 Sep 1996
+;; Maintainer: Robert J. Chassell <bug-texinfo@prep.ai.mit.edu>
+;; Keywords: maint, tex, docs
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs 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, or (at your option)
+;; any later version.
+
+;; GNU Emacs 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; see the file COPYING. If not, write to the
+;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+;;; Commentary:
+
+;; Known bug: update commands fail to ignore @ignore.
+
+;; Summary: how to use the updating commands
+
+;; The node and menu updating functions automatically
+
+;; * insert missing `@node' lines,
+;; * insert the `Next', `Previous' and `Up' pointers of a node,
+;; * insert or update the menu for a section,
+;; * create a master menu for a Texinfo source file.
+;;
+;; Passed an argument, the `texinfo-update-node' and
+;; `texinfo-make-menu' functions do their jobs in the region.
+;;
+;; In brief, the functions for creating or updating nodes and menus, are:
+;;
+;; texinfo-update-node (&optional region-p)
+;; texinfo-every-node-update ()
+;; texinfo-sequential-node-update (&optional region-p)
+;;
+;; texinfo-make-menu (&optional region-p)
+;; texinfo-all-menus-update ()
+;; texinfo-master-menu ()
+;;
+;; texinfo-insert-node-lines (&optional title-p)
+;;
+;; texinfo-indent-menu-description (column &optional region-p)
+
+;; The `texinfo-column-for-description' variable specifies the column to
+;; which menu descriptions are indented.
+
+;; Texinfo file structure
+;; ----------------------
+
+;; To use the updating commands, you must structure your Texinfo file
+;; hierarchically. Each `@node' line, with the exception of the top
+;; node, must be accompanied by some kind of section line, such as an
+;; `@chapter' or `@section' line. Each node-line/section-line
+;; combination must look like this:
+
+;; @node Lists and Tables, Cross References, Structuring, Top
+;; @comment node-name, next, previous, up
+;; @chapter Making Lists and Tables
+
+;; or like this (without the `@comment' line):
+
+;; @node Lists and Tables, Cross References, Structuring, Top
+;; @chapter Making Lists and Tables
+
+;; If the file has a `top' node, it must be called `top' or `Top' and
+;; be the first node in the file.
+
+
+;;; The update node functions described in detail
+
+;; The `texinfo-update-node' function without an argument inserts
+;; the correct next, previous and up pointers for the node in which
+;; point is located (i.e., for the node preceding point).
+
+;; With an argument, the `texinfo-update-node' function inserts the
+;; correct next, previous and up pointers for the nodes inside the
+;; region.
+
+;; It does not matter whether the `@node' line has pre-existing
+;; `Next', `Previous', or `Up' pointers in it. They are removed.
+
+;; The `texinfo-every-node-update' function runs `texinfo-update-node'
+;; on the whole buffer.
+
+;; The `texinfo-sequential-node-update' function inserts the
+;; immediately following and preceding node into the `Next' or
+;; `Previous' pointers regardless of their hierarchical level. This is
+;; only useful for certain kinds of text, like a novel, which you go
+;; through sequentially.
+
+
+;;; The menu making functions described in detail
+
+;; The `texinfo-make-menu' function without an argument creates or
+;; updates a menu for the section encompassing the node that follows
+;; point. With an argument, it makes or updates menus for the nodes
+;; within or part of the marked region.
+
+;; Whenever an existing menu is updated, the descriptions from
+;; that menu are incorporated into the new menu. This is done by copying
+;; descriptions from the existing menu to the entries in the new menu
+;; that have the same node names. If the node names are different, the
+;; descriptions are not copied to the new menu.
+
+;; Menu entries that refer to other Info files are removed since they
+;; are not a node within current buffer. This is a deficiency.
+
+;; The `texinfo-all-menus-update' function runs `texinfo-make-menu'
+;; on the whole buffer.
+
+;; The `texinfo-master-menu' function creates an extended menu located
+;; after the top node. (The file must have a top node.) The function
+;; first updates all the regular menus in the buffer (incorporating the
+;; descriptions from pre-existing menus), and then constructs a master
+;; menu that includes every entry from every other menu. (However, the
+;; function cannot update an already existing master menu; if one
+;; exists, it must be removed before calling the function.)
+
+;; The `texinfo-indent-menu-description' function indents every
+;; description in the menu following point, to the specified column.
+;; Non-nil argument (prefix, if interactive) means indent every
+;; description in every menu in the region. This function does not
+;; indent second and subsequent lines of a multi-line description.
+
+;; The `texinfo-insert-node-lines' function inserts `@node' before the
+;; `@chapter', `@section', and such like lines of a region in a Texinfo
+;; file where the `@node' lines are missing.
+;;
+;; With a non-nil argument (prefix, if interactive), the function not
+;; only inserts `@node' lines but also inserts the chapter or section
+;; titles as the names of the corresponding nodes; and inserts titles
+;; as node names in pre-existing `@node' lines that lack names.
+;;
+;; Since node names should be more concise than section or chapter
+;; titles, node names so inserted will need to be edited manually.
+
+
+;;; Code:
+
+;;; The menu making functions
+
+(defun texinfo-make-menu (&optional region-p)
+ "Without any prefix argument, make or update a menu.
+Make the menu for the section enclosing the node found following point.
+
+Non-nil argument (prefix, if interactive) means make or update menus
+for nodes within or part of the marked region.
+
+Whenever a menu exists, and is being updated, the descriptions that
+are associated with node names in the pre-existing menu are
+incorporated into the new menu. Otherwise, the nodes' section titles
+are inserted as descriptions."
+
+ (interactive "P")
+ (if (not region-p)
+ (let ((level (texinfo-hierarchic-level)))
+ (texinfo-make-one-menu level)
+ (message "Done...updated the menu. You may save the buffer."))
+ ;; else
+ (message "Making or updating menus in %s... " (buffer-name))
+ (let ((beginning (region-beginning))
+ (region-end (region-end))
+ (level (progn ; find section type following point
+ (goto-char (region-beginning))
+ (texinfo-hierarchic-level))))
+ (if (= region-end beginning)
+ (error "Please mark a region!"))
+ (save-excursion
+ (save-restriction
+ (widen)
+
+ (while (texinfo-find-lower-level-node level region-end)
+ (setq level (texinfo-hierarchic-level)) ; new, lower level
+ (texinfo-make-one-menu level))
+
+ (while (and (< (point) region-end)
+ (texinfo-find-higher-level-node level region-end))
+ (setq level (texinfo-hierarchic-level))
+ (while (texinfo-find-lower-level-node level region-end)
+ (setq level (texinfo-hierarchic-level)) ; new, lower level
+ (texinfo-make-one-menu level))))))
+ (message "Done...updated menus. You may save the buffer.")))
+
+(defun texinfo-make-one-menu (level)
+ "Make a menu of all the appropriate nodes in this section.
+`Appropriate nodes' are those associated with sections that are
+at the level specified by LEVEL. Point is left at the end of menu."
+ (let*
+ ((case-fold-search t)
+ (beginning
+ (save-excursion
+ (goto-char (texinfo-update-menu-region-beginning level))
+ (end-of-line)
+ (point)))
+ (end (texinfo-update-menu-region-end level))
+ (first (texinfo-menu-first-node beginning end))
+ (node-name (progn
+ (goto-char beginning)
+ (beginning-of-line)
+ (texinfo-copy-node-name)))
+ (new-menu-list (texinfo-make-menu-list beginning end level)))
+ (if (texinfo-old-menu-p beginning first)
+ (progn
+ (texinfo-incorporate-descriptions new-menu-list)
+ (texinfo-incorporate-menu-entry-names new-menu-list)
+ (texinfo-delete-old-menu beginning first)))
+ (texinfo-insert-menu new-menu-list node-name)))
+
+(defun texinfo-all-menus-update (&optional update-all-nodes-p)
+ "Update every regular menu in a Texinfo file.
+Update pre-existing master menu, if there is one.
+
+If called with a non-nil argument, this function first updates all the
+nodes in the buffer before updating the menus."
+ (interactive "P")
+ (let ((case-fold-search t)
+ master-menu-p)
+ (save-excursion
+ (push-mark (point-max) t)
+ (goto-char (point-min))
+ (message "Checking for a master menu in %s ... "(buffer-name))
+ (save-excursion
+ (if (re-search-forward texinfo-master-menu-header nil t)
+ ;; Remove detailed master menu listing
+ (progn
+ (setq master-menu-p t)
+ (goto-char (match-beginning 0))
+ (let ((end-of-detailed-menu-descriptions
+ (save-excursion ; beginning of end menu line
+ (goto-char (texinfo-menu-end))
+ (beginning-of-line) (forward-char -1)
+ (point))))
+ (delete-region (point) end-of-detailed-menu-descriptions)))))
+
+ (if update-all-nodes-p
+ (progn
+ (message "Updating all nodes in %s ... " (buffer-name))
+ (sleep-for 2)
+ (push-mark (point-max) t)
+ (goto-char (point-min))
+ ;; Using the mark to pass bounds this way
+ ;; is kludgy, but it's not worth fixing. -- rms.
+ (let ((mark-active t))
+ (texinfo-update-node t))))
+
+ (message "Updating all menus in %s ... " (buffer-name))
+ (sleep-for 2)
+ (push-mark (point-max) t)
+ (goto-char (point-min))
+ ;; Using the mark to pass bounds this way
+ ;; is kludgy, but it's not worth fixing. -- rms.
+ (let ((mark-active t))
+ (texinfo-make-menu t))
+
+ (if master-menu-p
+ (progn
+ (message "Updating the master menu in %s... " (buffer-name))
+ (sleep-for 2)
+ (texinfo-master-menu nil))))
+
+ (message "Done...updated all the menus. You may save the buffer.")))
+
+(defun texinfo-find-lower-level-node (level region-end)
+ "Search forward from point for node at any level lower than LEVEL.
+Search is limited to the end of the marked region, REGION-END,
+and to the end of the menu region for the level.
+
+Return t if the node is found, else nil. Leave point at the beginning
+of the node if one is found; else do not move point."
+ (let ((case-fold-search t))
+ (if (and (< (point) region-end)
+ (re-search-forward
+ (concat
+ "\\(^@node\\).*\n" ; match node line
+ "\\(\\(\\(^@c\\).*\n\\)" ; match comment line, if any
+ "\\|" ; or
+ "\\(^@ifinfo[ ]*\n\\)\\)?" ; ifinfo line, if any
+ (eval (cdr (assoc level texinfo-update-menu-lower-regexps))))
+ ;; the next higher level node marks the end of this
+ ;; section, and no lower level node will be found beyond
+ ;; this position even if region-end is farther off
+ (texinfo-update-menu-region-end level)
+ t))
+ (goto-char (match-beginning 1)))))
+
+(defun texinfo-find-higher-level-node (level region-end)
+ "Search forward from point for node at any higher level than argument LEVEL.
+Search is limited to the end of the marked region, REGION-END.
+
+Return t if the node is found, else nil. Leave point at the beginning
+of the node if one is found; else do not move point."
+ (let ((case-fold-search t))
+ (cond
+ ((or (string-equal "top" level) (string-equal "chapter" level))
+ (if (re-search-forward "^@node [ \t]*top[ \t]*\\(,\\|$\\)" region-end t)
+ (progn (beginning-of-line) t)))
+ (t
+ (if (re-search-forward
+ (concat
+ "\\(^@node\\).*\n" ; match node line
+ "\\(\\(\\(^@c\\).*\n\\)" ; match comment line, if any
+ "\\|" ; or
+ "\\(^@ifinfo[ ]*\n\\)\\)?" ; ifinfo line, if any
+ (eval (cdr (assoc level texinfo-update-menu-higher-regexps))))
+ region-end t)
+ (progn (beginning-of-line) t))))))
+
+
+;;; Making the list of new menu entries
+
+(defun texinfo-make-menu-list (beginning end level)
+ "Make a list of node names and their descriptions.
+Point is left at the end of the menu region, but the menu is not inserted.
+
+First argument is position from which to start making menu list;
+second argument is end of region in which to try to locate entries;
+third argument is the level of the nodes that are the entries.
+
+Node names and descriptions are dotted pairs of strings. Each pair is
+an element of the list. If the description does not exist, the
+element consists only of the node name."
+ (goto-char beginning)
+ (let (new-menu-list)
+ (while (texinfo-menu-locate-entry-p level end)
+ (setq new-menu-list
+ (cons (cons
+ (texinfo-copy-node-name)
+ (prog1 "" (forward-line 1)))
+ ;; Use following to insert section titles automatically.
+ ;; (texinfo-copy-section-title))
+ new-menu-list)))
+ (reverse new-menu-list)))
+
+(defun texinfo-menu-locate-entry-p (level search-end)
+ "Find a node that will be part of menu for this section.
+First argument is a string such as \"section\" specifying the general
+hierarchical level of the menu; second argument is a position
+specifying the end of the search.
+
+The function returns t if the node is found, else nil. It searches
+forward from point, and leaves point at the beginning of the node.
+
+The function finds entries of the same type. Thus `subsections' and
+`unnumberedsubsecs' will appear in the same menu."
+ (let ((case-fold-search t))
+ (if (re-search-forward
+ (concat
+ "\\(^@node\\).*\n" ; match node line
+ "\\(\\(\\(^@c\\).*\n\\)" ; match comment line, if any
+ "\\|" ; or
+ "\\(^@ifinfo[ ]*\n\\)\\)?" ; ifinfo line, if any
+ (eval
+ (cdr (assoc level texinfo-update-menu-same-level-regexps))))
+ search-end
+ t)
+ (goto-char (match-beginning 1)))))
+
+(defun texinfo-copy-node-name ()
+ "Return the node name as a string.
+
+Start with point at the beginning of the node line; copy the text
+after the node command up to the first comma on the line, if any, and
+return the text as a string. Leaves point at the beginning of the
+line. If there is no node name, returns an empty string."
+
+ (save-excursion
+ (buffer-substring
+ (progn (forward-word 1) ; skip over node command
+ (skip-chars-forward " \t") ; and over spaces
+ (point))
+ (if (search-forward
+ ","
+ (save-excursion (end-of-line) (point)) t) ; bound search
+ (1- (point))
+ (end-of-line) (point)))))
+
+(defun texinfo-copy-section-title ()
+ "Return the title of the section as a string.
+The title is used as a description line in the menu when one does not
+already exist.
+
+Move point to the beginning of the appropriate section line by going
+to the start of the text matched by last regexp searched for, which
+must have been done by `texinfo-menu-locate-entry-p'."
+
+ ;; could use the same re-search as in `texinfo-menu-locate-entry-p'
+ ;; instead of using `match-beginning'; such a variation would be
+ ;; more general, but would waste information already collected
+
+ (goto-char (match-beginning 7)) ; match section name
+
+ (buffer-substring
+ (progn (forward-word 1) ; skip over section type
+ (skip-chars-forward " \t") ; and over spaces
+ (point))
+ (progn (end-of-line) (point))))
+
+
+;;; Handling the old menu
+
+(defun texinfo-old-menu-p (beginning first)
+ "Move point to the beginning of the menu for this section, if any.
+Otherwise move point to the end of the first node of this section.
+Return t if a menu is found, nil otherwise.
+
+First argument is the position of the beginning of the section in which
+the menu will be located; second argument is the position of the first
+node within the section.
+
+If no menu is found, the function inserts two newlines just before the
+end of the section, and leaves point there where a menu ought to be."
+ (goto-char beginning)
+ (if (not (re-search-forward "^@menu" first 'goto-end))
+ (progn (insert "\n\n") (forward-line -2) nil)
+ t))
+
+(defun texinfo-incorporate-descriptions (new-menu-list)
+ "Copy the old menu line descriptions that exist to the new menu.
+
+Point must be at beginning of old menu.
+
+If the node-name of the new menu is found in the old menu, insert the
+old description into the new entry.
+
+For this function, the new menu is a list made up of lists of dotted
+pairs in which the first element of the pair is the node name and the
+second element the description. The new menu is changed destructively.
+The old menu is the menu as it appears in the texinfo file."
+
+ (let ((new-menu-list-pointer new-menu-list)
+ (end-of-menu (texinfo-menu-end)))
+ (while new-menu-list
+ (save-excursion ; keep point at beginning of menu
+ (if (re-search-forward
+ ;; Existing nodes can have the form
+ ;; * NODE NAME:: DESCRIPTION
+ ;; or
+ ;; * MENU ITEM: NODE NAME. DESCRIPTION.
+ ;;
+ ;; Recognize both when looking for the description.
+ (concat "\\* \\(" ; so only menu entries are found
+ (car (car new-menu-list)) "::"
+ "\\|"
+ ".*: " (car (car new-menu-list)) "[.,\t\n]"
+ "\\)"
+ ) ; so only complete entries are found
+ end-of-menu
+ t)
+ (setcdr (car new-menu-list)
+ (texinfo-menu-copy-old-description end-of-menu))))
+ (setq new-menu-list (cdr new-menu-list)))
+ (setq new-menu-list new-menu-list-pointer)))
+
+(defun texinfo-incorporate-menu-entry-names (new-menu-list)
+ "Copy any old menu entry names to the new menu.
+
+Point must be at beginning of old menu.
+
+If the node-name of the new menu entry cannot be found in the old
+menu, do nothing.
+
+For this function, the new menu is a list made up of lists of dotted
+pairs in which the first element of the pair is the node name and the
+second element is the description (or nil).
+
+If we find an existing menu entry name, we change the first element of
+the pair to be another dotted pair in which the car is the menu entry
+name and the cdr is the node name.
+
+NEW-MENU-LIST is changed destructively. The old menu is the menu as it
+appears in the texinfo file."
+
+ (let ((new-menu-list-pointer new-menu-list)
+ (end-of-menu (texinfo-menu-end)))
+ (while new-menu-list
+ (save-excursion ; keep point at beginning of menu
+ (if (re-search-forward
+ ;; Existing nodes can have the form
+ ;; * NODE NAME:: DESCRIPTION
+ ;; or
+ ;; * MENU ITEM: NODE NAME. DESCRIPTION.
+ ;;
+ ;; We're interested in the second case.
+ (concat "\\* " ; so only menu entries are found
+ "\\(.*\\): " (car (car new-menu-list)) "[.,\t\n]")
+ end-of-menu
+ t)
+ (setcar
+ (car new-menu-list) ; replace the node name
+ (cons (buffer-substring (match-beginning 1) (match-end 1))
+ (car (car new-menu-list)))))
+ (setq new-menu-list (cdr new-menu-list))))
+ (setq new-menu-list new-menu-list-pointer)))
+
+(defun texinfo-menu-copy-old-description (end-of-menu)
+ "Return description field of old menu line as string.
+Point must be located just after the node name. Point left before description.
+Single argument, END-OF-MENU, is position limiting search."
+ (skip-chars-forward "[:.,\t\n ]+")
+ ;; don't copy a carriage return at line beginning with asterisk!
+ ;; do copy a description that begins with an `@'!
+ ;; !! Known bug: does not copy descriptions starting with ^|\{?* etc.
+ (if (and (looking-at "\\(\\w+\\|@\\)")
+ (not (looking-at "\\(^\\* \\|^@end menu\\)")))
+ (buffer-substring
+ (point)
+ (save-excursion
+ (re-search-forward "\\(^\\* \\|^@end menu\\)" end-of-menu t)
+ (forward-line -1)
+ (end-of-line) ; go to end of last description line
+ (point)))
+ ""))
+
+(defun texinfo-menu-end ()
+ "Return position of end of menu. Does not change location of point.
+Signal an error if not end of menu."
+ (save-excursion
+ (if (re-search-forward "^@end menu" nil t)
+ (point)
+ (error "Menu does not have an end."))))
+
+(defun texinfo-delete-old-menu (beginning first)
+ "Delete the old menu. Point must be in or after menu.
+First argument is position of the beginning of the section in which
+the menu will be located; second argument is the position of the first
+node within the section."
+ ;; No third arg to search, so error if search fails.
+ (re-search-backward "^@menu" beginning)
+ (delete-region (point)
+ (save-excursion
+ (re-search-forward "^@end menu" first)
+ (point))))
+
+
+;;; Inserting new menu
+
+;; try 32, but perhaps 24 is better
+(defvar texinfo-column-for-description 32
+ "*Column at which descriptions start in a Texinfo menu.")
+
+(defun texinfo-insert-menu (menu-list node-name)
+ "Insert formatted menu at point.
+Indents the first line of the description, if any, to the value of
+texinfo-column-for-description.
+
+MENU-LIST has form:
+
+ \(\(\"node-name1\" . \"description\"\)
+ \(\"node-name2\" . \"description\"\) ... \)
+
+However, the description field might be nil.
+
+Also, the node-name field might itself be a dotted pair (call it P) of
+strings instead of just a string. In that case, the car of P
+is the menu entry name, and the cdr of P is the node name."
+
+ (insert "@menu\n")
+ (while menu-list
+ ;; Every menu entry starts with a star and a space.
+ (insert "* ")
+
+ ;; Insert the node name (and menu entry name, if present).
+ (let ((node-part (car (car menu-list))))
+ (if (stringp node-part)
+ ;; "Double colon" entry line; menu entry and node name are the same,
+ (insert (format "%s::" node-part))
+ ;; "Single colon" entry line; menu entry and node name are different.
+ (insert (format "%s: %s." (car node-part) (cdr node-part)))))
+
+ ;; Insert the description, if present.
+ (if (cdr (car menu-list))
+ (progn
+ ;; Move to right place.
+ (indent-to texinfo-column-for-description 2)
+ ;; Insert description.
+ (insert (format "%s" (cdr (car menu-list))))))
+
+ (insert "\n") ; end this menu entry
+ (setq menu-list (cdr menu-list)))
+ (insert "@end menu")
+ (message
+ "Updated \"%s\" level menu following node: %s ... " level node-name))
+
+
+;;; Starting menu descriptions by inserting titles
+
+(defun texinfo-start-menu-description ()
+ "In this menu entry, insert the node's section title as a description.
+Position point at beginning of description ready for editing.
+Do not insert a title if the line contains an existing description.
+
+You will need to edit the inserted text since a useful description
+complements the node name rather than repeats it as a title does."
+
+ (interactive)
+ (let (beginning end node-name title)
+ (save-excursion
+ (beginning-of-line)
+ (if (search-forward "* " (save-excursion (end-of-line) (point)) t)
+ (progn (skip-chars-forward " \t")
+ (setq beginning (point)))
+ (error "This is not a line in a menu!"))
+
+ (cond
+ ;; "Double colon" entry line; menu entry and node name are the same,
+ ((search-forward "::" (save-excursion (end-of-line) (point)) t)
+ (if (looking-at "[ \t]*[^ \t\n]+")
+ (error "Descriptive text already exists."))
+ (skip-chars-backward ": \t")
+ (setq node-name (buffer-substring beginning (point))))
+
+ ;; "Single colon" entry line; menu entry and node name are different.
+ ((search-forward ":" (save-excursion (end-of-line) (point)) t)
+ (skip-chars-forward " \t")
+ (setq beginning (point))
+ ;; Menu entry line ends in a period, comma, or tab.
+ (if (re-search-forward "[.,\t]"
+ (save-excursion (forward-line 1) (point)) t)
+ (progn
+ (if (looking-at "[ \t]*[^ \t\n]+")
+ (error "Descriptive text already exists."))
+ (skip-chars-backward "., \t")
+ (setq node-name (buffer-substring beginning (point))))
+ ;; Menu entry line ends in a return.
+ (re-search-forward ".*\n"
+ (save-excursion (forward-line 1) (point)) t)
+ (skip-chars-backward " \t\n")
+ (setq node-name (buffer-substring beginning (point)))
+ (if (= 0 (length node-name))
+ (error "No node name on this line.")
+ (insert "."))))
+ (t (error "No node name on this line.")))
+ ;; Search for node that matches node name, and copy the section title.
+ (if (re-search-forward
+ (concat
+ "^@node[ \t]+"
+ node-name
+ ".*\n" ; match node line
+ "\\("
+ "\\(\\(^@c \\|^@comment\\).*\n\\)" ; match comment line, if any
+ "\\|" ; or
+ "\\(^@ifinfo[ ]*\n\\)" ; ifinfo line, if any
+ "\\)?")
+ nil t)
+ (progn
+ (setq title
+ (buffer-substring
+ ;; skip over section type
+ (progn (forward-word 1)
+ ;; and over spaces
+ (skip-chars-forward " \t")
+ (point))
+ (progn (end-of-line)
+ (skip-chars-backward " \t")
+ (point)))))
+ (error "Cannot find node to match node name in menu entry.")))
+ ;; Return point to the menu and insert the title.
+ (end-of-line)
+ (delete-region
+ (point)
+ (save-excursion (skip-chars-backward " \t") (point)))
+ (indent-to texinfo-column-for-description 2)
+ (save-excursion (insert title))))
+
+
+;;; Handling description indentation
+
+;; Since the make-menu functions indent descriptions, these functions
+;; are useful primarily for indenting a single menu specially.
+
+(defun texinfo-indent-menu-description (column &optional region-p)
+ "Indent every description in menu following point to COLUMN.
+Non-nil argument (prefix, if interactive) means indent every
+description in every menu in the region. Does not indent second and
+subsequent lines of a multi-line description."
+
+ (interactive
+ "nIndent menu descriptions to (column number): \nP")
+ (save-excursion
+ (save-restriction
+ (widen)
+ (if (not region-p)
+ (progn
+ (re-search-forward "^@menu")
+ (texinfo-menu-indent-description column)
+ (message
+ "Indented descriptions in menu. You may save the buffer."))
+ ;;else
+ (message "Indenting every menu description in region... ")
+ (goto-char (region-beginning))
+ (while (and (< (point) (region-end))
+ (texinfo-locate-menu-p))
+ (forward-line 1)
+ (texinfo-menu-indent-description column))
+ (message "Indenting done. You may save the buffer.")))))
+
+(defun texinfo-menu-indent-description (to-column-number)
+ "Indent the Texinfo file menu description to TO-COLUMN-NUMBER.
+Start with point just after the word `menu' in the `@menu' line and
+leave point on the line before the `@end menu' line. Does not indent
+second and subsequent lines of a multi-line description."
+ (let* ((beginning-of-next-line (point)))
+ (while (< beginning-of-next-line
+ (save-excursion ; beginning of end menu line
+ (goto-char (texinfo-menu-end))
+ (beginning-of-line)
+ (point)))
+
+ (if (re-search-forward "\\* \\(.*::\\|.*: [^.,\t\n]+[.,\t]\\)"
+ (texinfo-menu-end)
+ t)
+ (progn
+ (let ((beginning-white-space (point)))
+ (skip-chars-forward " \t") ; skip over spaces
+ (if (looking-at "\\(@\\|\\w\\)+") ; if there is text
+ (progn
+ ;; remove pre-existing indentation
+ (delete-region beginning-white-space (point))
+ (indent-to-column to-column-number))))))
+ ;; position point at beginning of next line
+ (forward-line 1)
+ (setq beginning-of-next-line (point)))))
+
+
+;;; Making the master menu
+
+(defun texinfo-master-menu (update-all-nodes-menus-p)
+ "Make a master menu for a whole Texinfo file.
+Non-nil argument (prefix, if interactive) means first update all
+existing nodes and menus. Remove pre-existing master menu, if there is one.
+
+This function creates a master menu that follows the top node. The
+master menu includes every entry from all the other menus. It
+replaces any existing ordinary menu that follows the top node.
+
+If called with a non-nil argument, this function first updates all the
+menus in the buffer (incorporating descriptions from pre-existing
+menus) before it constructs the master menu.
+
+The function removes the detailed part of an already existing master
+menu. This action depends on the pre-existing master menu using the
+standard `texinfo-master-menu-header'.
+
+The master menu has the following format, which is adapted from the
+recommendation in the Texinfo Manual:
+
+ * The first part contains the major nodes in the Texinfo file: the
+ nodes for the chapters, chapter-like sections, and the major
+ appendices. This includes the indices, so long as they are in
+ chapter-like sections, such as unnumbered sections.
+
+ * The second and subsequent parts contain a listing of the other,
+ lower level menus, in order. This way, an inquirer can go
+ directly to a particular node if he or she is searching for
+ specific information.
+
+Each of the menus in the detailed node listing is introduced by the
+title of the section containing the menu."
+
+ (interactive "P")
+ (let ((case-fold-search t))
+ (widen)
+ (goto-char (point-min))
+
+ ;; Move point to location after `top'.
+ (if (not (re-search-forward "^@node [ \t]*top[ \t]*\\(,\\|$\\)" nil t))
+ (error "This buffer needs a Top node!"))
+
+ (let ((first-chapter
+ (save-excursion
+ (or (re-search-forward "^@node" nil t)
+ (error "Too few nodes for a master menu!"))
+ (point))))
+ (if (re-search-forward texinfo-master-menu-header first-chapter t)
+ ;; Remove detailed master menu listing
+ (progn
+ (goto-char (match-beginning 0))
+ (let ((end-of-detailed-menu-descriptions
+ (save-excursion ; beginning of end menu line
+ (goto-char (texinfo-menu-end))
+ (beginning-of-line) (forward-char -1)
+ (point))))
+ (delete-region (point) end-of-detailed-menu-descriptions)))))
+
+ (if update-all-nodes-menus-p
+ (progn
+ (message "Making a master menu in %s ...first updating all nodes... "
+ (buffer-name))
+ (sleep-for 2)
+ (push-mark (point-max) t)
+ (goto-char (point-min))
+ (texinfo-update-node t)
+
+ (message "Updating all menus in %s ... " (buffer-name))
+ (sleep-for 2)
+ (push-mark (point-max) t)
+ (goto-char (point-min))
+ (texinfo-make-menu t)))
+
+ (message "Now making the master menu in %s... " (buffer-name))
+ (sleep-for 2)
+ (goto-char (point-min))
+ (texinfo-insert-master-menu-list
+ (texinfo-master-menu-list))
+
+ ;; Remove extra newlines that texinfo-insert-master-menu-list
+ ;; may have inserted.
+
+ (save-excursion
+ (goto-char (point-min))
+
+ (if (re-search-forward texinfo-master-menu-header nil t)
+ (progn
+ (goto-char (match-beginning 0))
+ (insert "\n")
+ (delete-blank-lines)
+ (goto-char (point-min))))
+
+ (re-search-forward "^@menu")
+ (forward-line -1)
+ (delete-blank-lines)
+
+ (re-search-forward "^@end menu")
+ (forward-line 1)
+ (delete-blank-lines))
+
+ (message
+ "Done...completed making master menu. You may save the buffer.")))
+
+(defun texinfo-master-menu-list ()
+ "Return a list of menu entries and header lines for the master menu.
+
+Start with the menu for chapters and indices and then find each
+following menu and the title of the node preceding that menu.
+
+The master menu list has this form:
+
+ \(\(\(... \"entry-1-2\" \"entry-1\"\) \"title-1\"\)
+ \(\(... \"entry-2-2\" \"entry-2-1\"\) \"title-2\"\)
+ ...\)
+
+However, there does not need to be a title field."
+
+ (let (master-menu-list)
+ (while (texinfo-locate-menu-p)
+ (setq master-menu-list
+ (cons (list
+ (texinfo-copy-menu)
+ (texinfo-copy-menu-title))
+ master-menu-list)))
+ (reverse master-menu-list)))
+
+(defun texinfo-insert-master-menu-list (master-menu-list)
+ "Format and insert the master menu in the current buffer."
+ (goto-char (point-min))
+ ;; Insert a master menu only after `Top' node and before next node
+ ;; \(or include file if there is no next node\).
+ (if (not (re-search-forward "^@node [ \t]*top[ \t]*\\(,\\|$\\)" nil t))
+ (error "This buffer needs a Top node!"))
+ (let ((first-chapter
+ (save-excursion (re-search-forward "^@node\\|^@include") (point))))
+ (if (not (re-search-forward "^@menu" first-chapter t))
+ (error
+ "Buffer lacks ordinary `Top' menu in which to insert master.")))
+ (beginning-of-line)
+ (delete-region ; buffer must have ordinary top menu
+ (point)
+ (save-excursion (re-search-forward "^@end menu") (point)))
+
+ (save-excursion ; leave point at beginning of menu
+ ;; Handle top of menu
+ (insert "\n@menu\n")
+ ;; Insert chapter menu entries
+ (setq this-very-menu-list (reverse (car (car master-menu-list))))
+ ;; Tell user what is going on.
+ (message "Inserting chapter menu entry: %s ... " this-very-menu-list)
+ (while this-very-menu-list
+ (insert "* " (car this-very-menu-list) "\n")
+ (setq this-very-menu-list (cdr this-very-menu-list)))
+
+ (setq master-menu-list (cdr master-menu-list))
+
+ ;; Only insert detailed master menu if there is one....
+ (if (car (car master-menu-list))
+;; @detailmenu added 5 Sept 1996 at Karl Berry's request to avert a
+;; bug in `makeinfo'; all agree this is a bad kluge and should
+;; eventually be removed. @detailmenu ... @end detailmenu is a noop
+;; in `texinfmt.el' See @end detailmenu below
+;; also see `texinfo-all-menus-update' above, `texinfo-master-menu',
+;; `texinfo-multiple-files-update'
+ (insert texinfo-master-menu-header))
+
+ ;; Now, insert all the other menus
+
+ ;; The menu master-menu-list has a form like this:
+ ;; ((("beta" "alpha") "title-A")
+ ;; (("delta" "gamma") "title-B"))
+
+ (while master-menu-list
+
+ (message
+ "Inserting menu for %s .... " (car (cdr (car master-menu-list))))
+ ;; insert title of menu section
+ (insert "\n" (car (cdr (car master-menu-list))) "\n\n")
+
+ ;; insert each menu entry
+ (setq this-very-menu-list (reverse (car (car master-menu-list))))
+ (while this-very-menu-list
+ (insert "* " (car this-very-menu-list) "\n")
+ (setq this-very-menu-list (cdr this-very-menu-list)))
+
+ (setq master-menu-list (cdr master-menu-list)))
+
+ ;; Finish menu
+;; @detailmenu (see note above)
+ (insert "\n@end detailmenu")
+ (insert "\n@end menu\n\n")))
+
+(defvar texinfo-master-menu-header
+ "\n@detailmenu\n --- The Detailed Node Listing ---\n"
+ "String inserted before lower level entries in Texinfo master menu.
+It comes after the chapter-level menu entries.")
+
+(defun texinfo-locate-menu-p ()
+ "Find the next menu in the texinfo file.
+If found, leave point after word `menu' on the `@menu' line, and return t.
+If a menu is not found, do not move point and return nil."
+ (re-search-forward "\\(^@menu\\)" nil t))
+
+(defun texinfo-copy-menu-title ()
+ "Return the title of the section preceding the menu as a string.
+If such a title cannot be found, return an empty string. Do not move
+point."
+ (let ((case-fold-search t))
+ (save-excursion
+ (if (re-search-backward
+ (concat
+ "\\(^@top"
+ "\\|" ; or
+ texinfo-section-types-regexp ; all other section types
+ "\\)")
+ nil
+ t)
+ (progn
+ (beginning-of-line)
+ (forward-word 1) ; skip over section type
+ (skip-chars-forward " \t") ; and over spaces
+ (buffer-substring
+ (point)
+ (progn (end-of-line) (point))))
+ ""))))
+
+(defun texinfo-copy-menu ()
+ "Return the entries of an existing menu as a list.
+Start with point just after the word `menu' in the `@menu' line
+and leave point on the line before the `@end menu' line."
+ (let* (this-menu-list
+ (end-of-menu (texinfo-menu-end)) ; position of end of `@end menu'
+ (last-entry (save-excursion ; position of beginning of
+ ; last `* ' entry
+ (goto-char end-of-menu)
+ ;; handle multi-line description
+ (if (not (re-search-backward "^\\* " nil t))
+ (error "No entries in menu."))
+ (point))))
+ (while (< (point) last-entry)
+ (if (re-search-forward "^\\* " end-of-menu t)
+ (progn
+ (setq this-menu-list
+ (cons
+ (buffer-substring
+ (point)
+ ;; copy multi-line descriptions
+ (save-excursion
+ (re-search-forward "\\(^\\* \\|^@e\\)" nil t)
+ (- (point) 3)))
+ this-menu-list)))))
+ this-menu-list))
+
+
+;;; Determining the hierarchical level in the texinfo file
+
+(defun texinfo-specific-section-type ()
+ "Return the specific type of next section, as a string.
+For example, \"unnumberedsubsec\". Return \"top\" for top node.
+
+Searches forward for a section. Hence, point must be before the
+section whose type will be found. Does not move point. Signal an
+error if the node is not the top node and a section is not found."
+ (let ((case-fold-search t))
+ (save-excursion
+ (cond
+ ((re-search-forward "^@node [ \t]*top[ \t]*\\(,\\|$\\)"
+;;; Following search limit by cph but causes a bug
+;;; (save-excursion
+;;; (end-of-line)
+;;; (point))
+ nil
+ t)
+ "top")
+ ((re-search-forward texinfo-section-types-regexp nil t)
+ (buffer-substring-no-properties
+ (progn (beginning-of-line) ; copy its name
+ (1+ (point)))
+ (progn (forward-word 1)
+ (point))))
+ (t
+ (error
+ "texinfo-specific-section-type: Chapter or section not found."))))))
+
+(defun texinfo-hierarchic-level ()
+ "Return the general hierarchal level of the next node in a texinfo file.
+Thus, a subheading or appendixsubsec is of type subsection."
+ (let ((case-fold-search t))
+ (cdr (assoc
+ (texinfo-specific-section-type)
+ texinfo-section-to-generic-alist))))
+
+
+;;; Locating the major positions
+
+(defun texinfo-update-menu-region-beginning (level)
+ "Locate beginning of higher level section this section is within.
+Return position of the beginning of the node line; do not move point.
+Thus, if this level is subsection, searches backwards for section node.
+Only argument is a string of the general type of section."
+ (let ((case-fold-search t))
+ ;; !! Known bug: if section immediately follows top node, this
+ ;; returns the beginning of the buffer as the beginning of the
+ ;; higher level section.
+ (cond
+ ((or (string-equal "top" level)
+ (string-equal "chapter" level))
+ (save-excursion
+ (goto-char (point-min))
+ (re-search-forward "^@node [ \t]*top[ \t]*\\(,\\|$\\)" nil t)
+ (beginning-of-line)
+ (point)))
+ (t
+ (save-excursion
+ (re-search-backward
+ (concat
+ "\\(^@node\\).*\n" ; match node line
+ "\\(\\(\\(^@c\\).*\n\\)" ; match comment line, if any
+ "\\|" ; or
+ "\\(^@ifinfo[ ]*\n\\)\\)?" ; ifinfo line, if any
+ (eval
+ (cdr (assoc level texinfo-update-menu-higher-regexps))))
+ nil
+ 'goto-beginning)
+ (point))))))
+
+(defun texinfo-update-menu-region-end (level)
+ "Locate end of higher level section this section is within.
+Return position; do not move point. Thus, if this level is a
+subsection, find the node for the section this subsection is within.
+If level is top or chapter, returns end of file. Only argument is a
+string of the general type of section."
+ (let ((case-fold-search t))
+ (save-excursion
+ (if (re-search-forward
+ (concat
+ "\\(^@node\\).*\n" ; match node line
+ "\\(\\(\\(^@c\\).*\n\\)" ; match comment line, if any
+ "\\|" ; or
+ "\\(^@ifinfo[ ]*\n\\)\\)?" ; ifinfo line, if any
+ (eval
+ ;; Never finds end of level above chapter so goes to end.
+ (cdr (assoc level texinfo-update-menu-higher-regexps))))
+ nil
+ 'goto-end)
+ (match-beginning 1)
+ (point-max)))))
+
+(defun texinfo-menu-first-node (beginning end)
+ "Locate first node of the section the menu will be placed in.
+Return position; do not move point.
+The menu will be located just before this position.
+
+First argument is the position of the beginning of the section in
+which the menu will be located; second argument is the position of the
+end of that region; it limits the search."
+
+ (save-excursion
+ (goto-char beginning)
+ (forward-line 1)
+ (re-search-forward "^@node" end t)
+ (beginning-of-line)
+ (point)))
+
+
+;;; Alists and regular expressions for defining hierarchical levels
+
+(defvar texinfo-section-to-generic-alist
+ '(("top" . "top")
+
+ ("chapter" . "chapter")
+ ("unnumbered" . "chapter")
+ ("majorheading" . "chapter")
+ ("chapheading" . "chapter")
+ ("appendix" . "chapter")
+
+ ("section" . "section")
+ ("unnumberedsec" . "section")
+ ("heading" . "section")
+ ("appendixsec" . "section")
+
+ ("subsection" . "subsection")
+ ("unnumberedsubsec" . "subsection")
+ ("subheading" . "subsection")
+ ("appendixsubsec" . "subsection")
+
+ ("subsubsection" . "subsubsection")
+ ("unnumberedsubsubsec" . "subsubsection")
+ ("subsubheading" . "subsubsection")
+ ("appendixsubsubsec" . "subsubsection"))
+ "*An alist of specific and corresponding generic Texinfo section types.
+The keys are strings specifying specific types of section; the values
+are strings of their corresponding general types.")
+
+;; We used to look for just sub, but that found @subtitle.
+(defvar texinfo-section-types-regexp
+ "^@\\(chapter \\|sect\\|subs\\|subh\\|unnum\\|major\\|chapheading \\|heading \\|appendix\\)"
+ "Regexp matching chapter, section, other headings (but not the top node).")
+
+(defvar texinfo-chapter-level-regexp
+ "chapter\\|unnumbered \\|appendix \\|majorheading\\|chapheading"
+ "Regular expression matching just the Texinfo chapter level headings.")
+
+(defvar texinfo-section-level-regexp
+ "section\\|unnumberedsec\\|heading \\|appendixsec"
+ "Regular expression matching just the Texinfo section level headings.")
+
+(defvar texinfo-subsection-level-regexp
+ "subsection\\|unnumberedsubsec\\|subheading\\|appendixsubsec"
+ "Regular expression matching just the Texinfo subsection level headings.")
+
+(defvar texinfo-subsubsection-level-regexp
+ "subsubsection\\|unnumberedsubsubsec\\|subsubheading\\|appendixsubsubsec"
+ "Regular expression matching just the Texinfo subsubsection level headings.")
+
+(defvar texinfo-update-menu-same-level-regexps
+ '(("top" . "top[ \t]+")
+ ("chapter" .
+ (concat "\\(^@\\)\\(" texinfo-chapter-level-regexp "\\)[ \t]*"))
+ ("section" .
+ (concat "\\(^@\\)\\(" texinfo-section-level-regexp "\\)[ \t]*"))
+ ("subsection" .
+ (concat "\\(^@\\)\\(" texinfo-subsection-level-regexp "\\)[ \t]+"))
+ ("subsubsection" .
+ (concat "\\(^@\\)\\(" texinfo-subsubsection-level-regexp "\\)[ \t]+")))
+ "*Regexps for searching for same level sections in a Texinfo file.
+The keys are strings specifying the general hierarchical level in the
+document; the values are regular expressions.")
+
+(defvar texinfo-update-menu-higher-regexps
+ '(("top" . "^@node [ \t]*DIR")
+ ("chapter" . "^@node [ \t]*top[ \t]*\\(,\\|$\\)")
+ ("section" .
+ (concat
+ "\\(^@\\("
+ texinfo-chapter-level-regexp
+ "\\)[ \t]*\\)"))
+ ("subsection" .
+ (concat
+ "\\(^@\\("
+ texinfo-section-level-regexp
+ "\\|"
+ texinfo-chapter-level-regexp
+ "\\)[ \t]*\\)"))
+ ("subsubsection" .
+ (concat
+ "\\(^@\\("
+ texinfo-subsection-level-regexp
+ "\\|"
+ texinfo-section-level-regexp
+ "\\|"
+ texinfo-chapter-level-regexp
+ "\\)[ \t]*\\)")))
+ "*Regexps for searching for higher level sections in a Texinfo file.
+The keys are strings specifying the general hierarchical level in the
+document; the values are regular expressions.")
+
+(defvar texinfo-update-menu-lower-regexps
+ '(("top" .
+ (concat
+ "\\(^@\\("
+ texinfo-chapter-level-regexp
+ "\\|"
+ texinfo-section-level-regexp
+ "\\|"
+ texinfo-subsection-level-regexp
+ "\\|"
+ texinfo-subsubsection-level-regexp
+ "\\)[ \t]*\\)"))
+ ("chapter" .
+ (concat
+ "\\(^@\\("
+ texinfo-section-level-regexp
+ "\\|"
+ texinfo-subsection-level-regexp
+ "\\|"
+ texinfo-subsubsection-level-regexp
+ "\\)[ \t]*\\)"))
+ ("section" .
+ (concat
+ "\\(^@\\("
+ texinfo-subsection-level-regexp
+ "\\|"
+ texinfo-subsubsection-level-regexp
+ "\\)[ \t]+\\)"))
+ ("subsection" .
+ (concat
+ "\\(^@\\("
+ texinfo-subsubsection-level-regexp
+ "\\)[ \t]+\\)"))
+ ("subsubsection" . "nothing lower"))
+ "*Regexps for searching for lower level sections in a Texinfo file.
+The keys are strings specifying the general hierarchical level in the
+document; the values are regular expressions.")
+
+
+;;; Updating a node
+
+;;;###autoload
+(defun texinfo-update-node (&optional region-p)
+ "Without any prefix argument, update the node in which point is located.
+Non-nil argument (prefix, if interactive) means update the nodes in the
+marked region.
+
+The functions for creating or updating nodes and menus, and their
+keybindings, are:
+
+ texinfo-update-node (&optional region-p) \\[texinfo-update-node]
+ texinfo-every-node-update () \\[texinfo-every-node-update]
+ texinfo-sequential-node-update (&optional region-p)
+
+ texinfo-make-menu (&optional region-p) \\[texinfo-make-menu]
+ texinfo-all-menus-update () \\[texinfo-all-menus-update]
+ texinfo-master-menu ()
+
+ texinfo-indent-menu-description (column &optional region-p)
+
+The `texinfo-column-for-description' variable specifies the column to
+which menu descriptions are indented. Its default value is 32."
+
+ (interactive "P")
+ (if (not region-p)
+ ;; update a single node
+ (let ((auto-fill-function nil) (auto-fill-hook nil))
+ (if (not (re-search-backward "^@node" (point-min) t))
+ (error "Node line not found before this position."))
+ (texinfo-update-the-node)
+ (message "Done...updated the node. You may save the buffer."))
+ ;; else
+ (let ((auto-fill-function nil)
+ (auto-fill-hook nil)
+ (beginning (region-beginning))
+ (end (region-end)))
+ (if (= end beginning)
+ (error "Please mark a region!"))
+ (save-restriction
+ (narrow-to-region beginning end)
+ (goto-char beginning)
+ (push-mark (point) t)
+ (while (re-search-forward "^@node" (point-max) t)
+ (beginning-of-line)
+ (texinfo-update-the-node))
+ (message "Done...updated nodes in region. You may save the buffer.")))))
+
+;;;###autoload
+(defun texinfo-every-node-update ()
+ "Update every node in a Texinfo file."
+ (interactive)
+ (save-excursion
+ (push-mark (point-max) t)
+ (goto-char (point-min))
+ ;; Using the mark to pass bounds this way
+ ;; is kludgy, but it's not worth fixing. -- rms.
+ (let ((mark-active t))
+ (texinfo-update-node t))
+ (message "Done...updated every node. You may save the buffer.")))
+
+(defun texinfo-update-the-node ()
+ "Update one node. Point must be at the beginning of node line.
+Leave point at the end of the node line."
+ (texinfo-check-for-node-name)
+ (texinfo-delete-existing-pointers)
+ (message "Updating node: %s ... " (texinfo-copy-node-name))
+ (save-restriction
+ (widen)
+ (let*
+ ((case-fold-search t)
+ (level (texinfo-hierarchic-level))
+ (beginning (texinfo-update-menu-region-beginning level))
+ (end (texinfo-update-menu-region-end level)))
+ (if (string-equal level "top")
+ (texinfo-top-pointer-case)
+ ;; else
+ (texinfo-insert-pointer beginning end level 'next)
+ (texinfo-insert-pointer beginning end level 'previous)
+ (texinfo-insert-pointer beginning end level 'up)
+ (texinfo-clean-up-node-line)))))
+
+(defun texinfo-top-pointer-case ()
+ "Insert pointers in the Top node. This is a special case.
+
+The `Next' pointer is a pointer to a chapter or section at a lower
+hierarchical level in the file. The `Previous' and `Up' pointers are
+to `(dir)'. Point must be at the beginning of the node line, and is
+left at the end of the node line."
+
+ (texinfo-clean-up-node-line)
+ (insert ", "
+ (save-excursion
+ ;; There may be an @chapter or other such command between
+ ;; the top node line and the next node line, as a title
+ ;; for an `ifinfo' section. This @chapter command must
+ ;; must be skipped. So the procedure is to search for
+ ;; the next `@node' line, and then copy its name.
+ (if (re-search-forward "^@node" nil t)
+ (progn
+ (beginning-of-line)
+ (texinfo-copy-node-name))
+ " "))
+ ", (dir), (dir)"))
+
+(defun texinfo-check-for-node-name ()
+ "Determine whether the node has a node name. Prompt for one if not.
+Point must be at beginning of node line. Does not move point."
+ (save-excursion
+ (let ((initial (texinfo-copy-next-section-title)))
+ ;; This is not clean. Use `interactive' to read the arg.
+ (forward-word 1) ; skip over node command
+ (skip-chars-forward " \t") ; and over spaces
+ (if (not (looking-at "[^,\t\n ]+")) ; regexp based on what Info looks for
+ ; alternatively, use "[a-zA-Z]+"
+ (let ((node-name
+ (read-from-minibuffer
+ "Node name (use no @, commas, colons, or apostrophes): "
+ initial)))
+ (insert " " node-name))))))
+
+(defun texinfo-delete-existing-pointers ()
+ "Delete `Next', `Previous', and `Up' pointers.
+Starts from the current position of the cursor, and searches forward
+on the line for a comma and if one is found, deletes the rest of the
+line, including the comma. Leaves point at beginning of line."
+ (let ((eol-point (save-excursion (end-of-line) (point))))
+ (if (search-forward "," eol-point t)
+ (delete-region (1- (point)) eol-point)))
+ (beginning-of-line))
+
+(defun texinfo-find-pointer (beginning end level direction)
+ "Move point to section associated with next, previous, or up pointer.
+Return type of pointer (either 'normal or 'no-pointer).
+
+The first and second arguments bound the search for a pointer to the
+beginning and end, respectively, of the enclosing higher level
+section. The third argument is a string specifying the general kind
+of section such as \"chapter\" or \"section\". When looking for the
+`Next' pointer, the section found will be at the same hierarchical
+level in the Texinfo file; when looking for the `Previous' pointer,
+the section found will be at the same or higher hierarchical level in
+the Texinfo file; when looking for the `Up' pointer, the section found
+will be at some level higher in the Texinfo file. The fourth argument
+\(one of 'next, 'previous, or 'up\) specifies whether to find the
+`Next', `Previous', or `Up' pointer."
+ (let ((case-fold-search t))
+ (cond ((eq direction 'next)
+ (forward-line 3) ; skip over current node
+ ;; Search for section commands accompanied by node lines;
+ ;; ignore section commands in the middle of nodes.
+ (if (re-search-forward
+ ;; A `Top' node is never a next pointer, so won't find it.
+ (concat
+ ;; Match node line.
+ "\\(^@node\\).*\n"
+ ;; Match comment or ifinfo line, if any
+ "\\(\\(\\(^@c\\).*\n\\)\\|\\(^@ifinfo[ ]*\n\\)\\)?"
+ (eval
+ (cdr (assoc level texinfo-update-menu-same-level-regexps))))
+ end
+ t)
+ 'normal
+ 'no-pointer))
+ ((eq direction 'previous)
+ (if (re-search-backward
+ (concat
+ "\\("
+ ;; Match node line.
+ "\\(^@node\\).*\n"
+ ;; Match comment or ifinfo line, if any
+ "\\(\\(\\(^@c\\).*\n\\)\\|\\(^@ifinfo[ ]*\n\\)\\)?"
+ (eval
+ (cdr (assoc level texinfo-update-menu-same-level-regexps)))
+ "\\|"
+ ;; Match node line.
+ "\\(^@node\\).*\n"
+ ;; Match comment or ifinfo line, if any
+ "\\(\\(\\(^@c\\).*\n\\)\\|\\(^@ifinfo[ ]*\n\\)\\)?"
+ (eval
+ (cdr (assoc level texinfo-update-menu-higher-regexps)))
+ "\\|"
+ ;; Handle `Top' node specially.
+ "^@node [ \t]*top[ \t]*\\(,\\|$\\)"
+ "\\)")
+ beginning
+ t)
+ 'normal
+ 'no-pointer))
+ ((eq direction 'up)
+ (if (re-search-backward
+ (concat
+ "\\("
+ ;; Match node line.
+ "\\(^@node\\).*\n"
+ ;; Match comment or ifinfo line, if any
+ "\\(\\(\\(^@c\\).*\n\\)\\|\\(^@ifinfo[ ]*\n\\)\\)?"
+ (eval (cdr (assoc level texinfo-update-menu-higher-regexps)))
+ "\\|"
+ ;; Handle `Top' node specially.
+ "^@node [ \t]*top[ \t]*\\(,\\|$\\)"
+ "\\)")
+ (save-excursion
+ (goto-char beginning)
+ (beginning-of-line)
+ (point))
+ t)
+ 'normal
+ 'no-pointer))
+ (t
+ (error "texinfo-find-pointer: lack proper arguments")))))
+
+(defun texinfo-pointer-name (kind)
+ "Return the node name preceding the section command.
+The argument is the kind of section, either normal or no-pointer."
+ (let (name)
+ (cond ((eq kind 'normal)
+ (end-of-line) ; this handles prev node top case
+ (re-search-backward ; when point is already
+ "^@node" ; at the beginning of @node line
+ (save-excursion (forward-line -3))
+ t)
+ (setq name (texinfo-copy-node-name)))
+ ((eq kind 'no-pointer)
+ (setq name " "))) ; put a blank in the pointer slot
+ name))
+
+(defun texinfo-insert-pointer (beginning end level direction)
+ "Insert the `Next', `Previous' or `Up' node name at point.
+Move point forward.
+
+The first and second arguments bound the search for a pointer to the
+beginning and end, respectively, of the enclosing higher level
+section. The third argument is the hierarchical level of the Texinfo
+file, a string such as \"section\". The fourth argument is direction
+towards which the pointer is directed, one of `next, `previous, or
+'up."
+
+ (end-of-line)
+ (insert
+ ", "
+ (save-excursion
+ (texinfo-pointer-name
+ (texinfo-find-pointer beginning end level direction)))))
+
+(defun texinfo-clean-up-node-line ()
+ "Remove extra commas, if any, at end of node line."
+ (end-of-line)
+ (skip-chars-backward ", ")
+ (delete-region (point) (save-excursion (end-of-line) (point))))
+
+
+;;; Updating nodes sequentially
+;; These sequential update functions insert `Next' or `Previous'
+;; pointers that point to the following or preceding nodes even if they
+;; are at higher or lower hierarchical levels. This means that if a
+;; section contains one or more subsections, the section's `Next'
+;; pointer will point to the subsection and not the following section.
+;; (The subsection to which `Next' points will most likely be the first
+;; item on the section's menu.)
+
+;;;###autoload
+(defun texinfo-sequential-node-update (&optional region-p)
+ "Update one node (or many) in a Texinfo file with sequential pointers.
+
+This function causes the `Next' or `Previous' pointer to point to the
+immediately preceding or following node, even if it is at a higher or
+lower hierarchical level in the document. Continually pressing `n' or
+`p' takes you straight through the file.
+
+Without any prefix argument, update the node in which point is located.
+Non-nil argument (prefix, if interactive) means update the nodes in the
+marked region.
+
+This command makes it awkward to navigate among sections and
+subsections; it should be used only for those documents that are meant
+to be read like a novel rather than a reference, and for which the
+Info `g*' command is inadequate."
+
+ (interactive "P")
+ (if (not region-p)
+ ;; update a single node
+ (let ((auto-fill-function nil) (auto-fill-hook nil))
+ (if (not (re-search-backward "^@node" (point-min) t))
+ (error "Node line not found before this position."))
+ (texinfo-sequentially-update-the-node)
+ (message
+ "Done...sequentially updated the node . You may save the buffer."))
+ ;; else
+ (let ((auto-fill-function nil)
+ (auto-fill-hook nil)
+ (beginning (region-beginning))
+ (end (region-end)))
+ (if (= end beginning)
+ (error "Please mark a region!"))
+ (save-restriction
+ (narrow-to-region beginning end)
+ (goto-char beginning)
+ (push-mark (point) t)
+ (while (re-search-forward "^@node" (point-max) t)
+ (beginning-of-line)
+ (texinfo-sequentially-update-the-node))
+ (message
+ "Done...updated the nodes in sequence. You may save the buffer.")))))
+
+(defun texinfo-sequentially-update-the-node ()
+ "Update one node such that the pointers are sequential.
+A `Next' or `Previous' pointer points to any preceding or following node,
+regardless of its hierarchical level."
+
+ (texinfo-check-for-node-name)
+ (texinfo-delete-existing-pointers)
+ (message
+ "Sequentially updating node: %s ... " (texinfo-copy-node-name))
+ (save-restriction
+ (widen)
+ (let*
+ ((case-fold-search t)
+ (level (texinfo-hierarchic-level)))
+ (if (string-equal level "top")
+ (texinfo-top-pointer-case)
+ ;; else
+ (texinfo-sequentially-insert-pointer level 'next)
+ (texinfo-sequentially-insert-pointer level 'previous)
+ (texinfo-sequentially-insert-pointer level 'up)
+ (texinfo-clean-up-node-line)))))
+
+(defun texinfo-sequentially-find-pointer (level direction)
+ "Find next or previous pointer sequentially in Texinfo file, or up pointer.
+Move point to section associated with the pointer. Find point even if
+it is in a different section.
+
+Return type of pointer (either 'normal or 'no-pointer).
+
+The first argument is a string specifying the general kind of section
+such as \"chapter\" or \"section\". The section found will be at the
+same hierarchical level in the Texinfo file, or, in the case of the up
+pointer, some level higher. The second argument (one of 'next,
+'previous, or 'up) specifies whether to find the `Next', `Previous',
+or `Up' pointer."
+ (let ((case-fold-search t))
+ (cond ((eq direction 'next)
+ (forward-line 3) ; skip over current node
+ (if (re-search-forward
+ texinfo-section-types-regexp
+ (point-max)
+ t)
+ 'normal
+ 'no-pointer))
+ ((eq direction 'previous)
+ (if (re-search-backward
+ texinfo-section-types-regexp
+ (point-min)
+ t)
+ 'normal
+ 'no-pointer))
+ ((eq direction 'up)
+ (if (re-search-backward
+ (eval (cdr (assoc level texinfo-update-menu-higher-regexps)))
+ beginning
+ t)
+ 'normal
+ 'no-pointer))
+ (t
+ (error "texinfo-sequential-find-pointer: lack proper arguments")))))
+
+(defun texinfo-sequentially-insert-pointer (level direction)
+ "Insert the `Next', `Previous' or `Up' node name at point.
+Move point forward.
+
+The first argument is the hierarchical level of the Texinfo file, a
+string such as \"section\". The second argument is direction, one of
+`next, `previous, or 'up."
+
+ (end-of-line)
+ (insert
+ ", "
+ (save-excursion
+ (texinfo-pointer-name
+ (texinfo-sequentially-find-pointer level direction)))))
+
+
+;;; Inserting `@node' lines
+;; The `texinfo-insert-node-lines' function inserts `@node' lines as needed
+;; before the `@chapter', `@section', and such like lines of a region
+;; in a Texinfo file.
+
+(defun texinfo-insert-node-lines (beginning end &optional title-p)
+ "Insert missing `@node' lines in region of Texinfo file.
+Non-nil argument (prefix, if interactive) means also to insert the
+section titles as node names; and also to insert the section titles as
+node names in pre-existing @node lines that lack names."
+ (interactive "r\nP")
+
+ ;; Use marker; after inserting node lines, leave point at end of
+ ;; region and mark at beginning.
+
+ (let (beginning-marker end-marker title last-section-position)
+
+ ;; Save current position on mark ring and set mark to end.
+ (push-mark end t)
+ (setq end-marker (mark-marker))
+
+ (goto-char beginning)
+ (while (re-search-forward
+ texinfo-section-types-regexp
+ end-marker
+ 'end)
+ ;; Copy title if desired.
+ (if title-p
+ (progn
+ (beginning-of-line)
+ (forward-word 1)
+ (skip-chars-forward " \t")
+ (setq title (buffer-substring
+ (point)
+ (save-excursion (end-of-line) (point))))))
+ ;; Insert node line if necessary.
+ (if (re-search-backward
+ "^@node"
+ ;; Avoid finding previous node line if node lines are close.
+ (or last-section-position
+ (save-excursion (forward-line -2) (point))) t)
+ ;; @node is present, and point at beginning of that line
+ (forward-word 1) ; Leave point just after @node.
+ ;; Else @node missing; insert one.
+ (beginning-of-line) ; Beginning of `@section' line.
+ (insert "@node\n")
+ (backward-char 1)) ; Leave point just after `@node'.
+ ;; Insert title if desired.
+ (if title-p
+ (progn
+ (skip-chars-forward " \t")
+ ;; Use regexp based on what info looks for
+ ;; (alternatively, use "[a-zA-Z]+");
+ ;; this means we only insert a title if none exists.
+ (if (not (looking-at "[^,\t\n ]+"))
+ (progn
+ (beginning-of-line)
+ (forward-word 1)
+ (insert " " title)
+ (message "Inserted title %s ... " title)))))
+ ;; Go forward beyond current section title.
+ (re-search-forward texinfo-section-types-regexp
+ (save-excursion (forward-line 3) (point)) t)
+ (setq last-section-position (point))
+ (forward-line 1))
+
+ ;; Leave point at end of region, mark at beginning.
+ (set-mark beginning)
+
+ (if title-p
+ (message
+ "Done inserting node lines and titles. You may save the buffer.")
+ (message "Done inserting node lines. You may save the buffer."))))
+
+
+;;; Update and create menus for multi-file Texinfo sources
+
+;; 1. M-x texinfo-multiple-files-update
+;;
+;; Read the include file list of an outer Texinfo file and
+;; update all highest level nodes in the files listed and insert a
+;; main menu in the outer file after its top node.
+
+;; 2. C-u M-x texinfo-multiple-files-update
+;;
+;; Same as 1, but insert a master menu. (Saves reupdating lower
+;; level menus and nodes.) This command simply reads every menu,
+;; so if the menus are wrong, the master menu will be wrong.
+;; Similarly, if the lower level node pointers are wrong, they
+;; will stay wrong.
+
+;; 3. C-u 2 M-x texinfo-multiple-files-update
+;;
+;; Read the include file list of an outer Texinfo file and
+;; update all nodes and menus in the files listed and insert a
+;; master menu in the outer file after its top node.
+
+;;; Note: these functions:
+;;;
+;;; * Do not save or delete any buffers. You may fill up your memory.
+;;; * Do not handle any pre-existing nodes in outer file.
+;;; Hence, you may need a file for indices.
+
+
+;;; Auxiliary functions for multiple file updating
+
+(defun texinfo-multi-file-included-list (outer-file)
+ "Return a list of the included files in OUTER-FILE."
+ (let ((included-file-list (list outer-file))
+ start)
+ (save-excursion
+ (switch-to-buffer (find-file-noselect outer-file))
+ (widen)
+ (goto-char (point-min))
+ (while (re-search-forward "^@include" nil t)
+ (skip-chars-forward " \t")
+ (setq start (point))
+ (end-of-line)
+ (skip-chars-backward " \t")
+ (setq included-file-list
+ (cons (buffer-substring start (point))
+ included-file-list)))
+ (nreverse included-file-list))))
+
+(defun texinfo-copy-next-section-title ()
+ "Return the name of the immediately following section as a string.
+
+Start with point at the beginning of the node line. Leave point at the
+same place. If there is no title, returns an empty string."
+
+ (save-excursion
+ (end-of-line)
+ (let ((node-end (or
+ (save-excursion
+ (if (re-search-forward "\\(^@node\\)" nil t)
+ (match-beginning 0)))
+ (point-max))))
+ (if (re-search-forward texinfo-section-types-regexp node-end t)
+ (progn
+ (beginning-of-line)
+ ;; copy title
+ (let ((title
+ (buffer-substring
+ (progn (forward-word 1) ; skip over section type
+ (skip-chars-forward " \t") ; and over spaces
+ (point))
+ (progn (end-of-line) (point)))))
+ title))
+ ""))))
+
+(defun texinfo-multi-file-update (files &optional update-everything)
+ "Update first node pointers in each file in FILES.
+Return a list of the node names.
+
+The first file in the list is an outer file; the remaining are
+files included in the outer file with `@include' commands.
+
+If optional arg UPDATE-EVERYTHING non-nil, update every menu and
+pointer in each of the included files.
+
+Also update the `Top' level node pointers of the outer file.
+
+Requirements:
+
+ * the first file in the FILES list must be the outer file,
+ * each of the included files must contain exactly one highest
+ hierarchical level node,
+ * this node must be the first node in the included file,
+ * each highest hierarchical level node must be of the same type.
+
+Thus, normally, each included file contains one, and only one,
+chapter."
+
+;; The menu-list has the form:
+;;
+;; \(\(\"node-name1\" . \"title1\"\)
+;; \(\"node-name2\" . \"title2\"\) ... \)
+;;
+;; However, there does not need to be a title field and this function
+;; does not fill it; however a comment tells you how to do so.
+;; You would use the title field if you wanted to insert titles in the
+;; description slot of a menu as a description.
+
+ (let ((case-fold-search t)
+ menu-list)
+
+ ;; Find the name of the first node of the first included file.
+ (switch-to-buffer (find-file-noselect (car (cdr files))))
+ (widen)
+ (goto-char (point-min))
+ (if (not (re-search-forward "^@node" nil t))
+ (error "No `@node' line found in %s !" (buffer-name)))
+ (beginning-of-line)
+ (texinfo-check-for-node-name)
+ (setq next-node-name (texinfo-copy-node-name))
+
+ (setq menu-list
+ (cons (cons
+ next-node-name
+ (prog1 "" (forward-line 1)))
+ ;; Use following to insert section titles automatically.
+ ;; (texinfo-copy-next-section-title)
+ menu-list))
+
+ ;; Go to outer file
+ (switch-to-buffer (find-file-noselect (car files)))
+ (goto-char (point-min))
+ (if (not (re-search-forward "^@node [ \t]*top[ \t]*\\(,\\|$\\)" nil t))
+ (error "This buffer needs a Top node!"))
+ (beginning-of-line)
+ (texinfo-delete-existing-pointers)
+ (end-of-line)
+ (insert ", " next-node-name ", (dir), (dir)")
+ (beginning-of-line)
+ (setq previous-node-name "Top")
+ (setq files (cdr files))
+
+ (while files
+
+ (if (not (cdr files))
+ ;; No next file
+ (setq next-node-name "")
+ ;; Else,
+ ;; find the name of the first node in the next file.
+ (switch-to-buffer (find-file-noselect (car (cdr files))))
+ (widen)
+ (goto-char (point-min))
+ (if (not (re-search-forward "^@node" nil t))
+ (error "No `@node' line found in %s !" (buffer-name)))
+ (beginning-of-line)
+ (texinfo-check-for-node-name)
+ (setq next-node-name (texinfo-copy-node-name))
+ (setq menu-list
+ (cons (cons
+ next-node-name
+ (prog1 "" (forward-line 1)))
+ ;; Use following to insert section titles automatically.
+ ;; (texinfo-copy-next-section-title)
+ menu-list)))
+
+ ;; Go to node to be updated.
+ (switch-to-buffer (find-file-noselect (car files)))
+ (goto-char (point-min))
+ (if (not (re-search-forward "^@node" nil t))
+ (error "No `@node' line found in %s !" (buffer-name)))
+ (beginning-of-line)
+
+ ;; Update other menus and nodes if requested.
+ (if update-everything (texinfo-all-menus-update t))
+
+ (beginning-of-line)
+ (texinfo-delete-existing-pointers)
+ (end-of-line)
+ (insert ", " next-node-name ", " previous-node-name ", " up-node-name)
+
+ (beginning-of-line)
+ (setq previous-node-name (texinfo-copy-node-name))
+
+ (setq files (cdr files)))
+ (nreverse menu-list)))
+
+(defun texinfo-multi-files-insert-main-menu (menu-list)
+ "Insert formatted main menu at point.
+Indents the first line of the description, if any, to the value of
+texinfo-column-for-description."
+
+ (insert "@menu\n")
+ (while menu-list
+ ;; Every menu entry starts with a star and a space.
+ (insert "* ")
+
+ ;; Insert the node name (and menu entry name, if present).
+ (let ((node-part (car (car menu-list))))
+ (if (stringp node-part)
+ ;; "Double colon" entry line; menu entry and node name are the same,
+ (insert (format "%s::" node-part))
+ ;; "Single colon" entry line; menu entry and node name are different.
+ (insert (format "%s: %s." (car node-part) (cdr node-part)))))
+
+ ;; Insert the description, if present.
+ (if (cdr (car menu-list))
+ (progn
+ ;; Move to right place.
+ (indent-to texinfo-column-for-description 2)
+ ;; Insert description.
+ (insert (format "%s" (cdr (car menu-list))))))
+
+ (insert "\n") ; end this menu entry
+ (setq menu-list (cdr menu-list)))
+ (insert "@end menu"))
+
+(defun texinfo-multi-file-master-menu-list (files-list)
+ "Return master menu list from files in FILES-LIST.
+Menu entries in each file collected using `texinfo-master-menu-list'.
+
+The first file in FILES-LIST must be the outer file; the others must
+be the files included within it. A main menu must already exist."
+ (save-excursion
+ (let (master-menu-list)
+ (while files-list
+ (switch-to-buffer (find-file-noselect (car files-list)))
+ (message "Working on: %s " (current-buffer))
+ (goto-char (point-min))
+ (setq master-menu-list
+ (append master-menu-list (texinfo-master-menu-list)))
+ (setq files-list (cdr files-list)))
+ master-menu-list)))
+
+
+;;; The multiple-file update function
+
+(defun texinfo-multiple-files-update
+ (outer-file &optional update-everything make-master-menu)
+ "Update first node pointers in each file included in OUTER-FILE;
+create or update the `Top' level node pointers and the main menu in
+the outer file that refers to such nodes. This does not create or
+update menus or pointers within the included files.
+
+With optional MAKE-MASTER-MENU argument (prefix arg, if interactive),
+insert a master menu in OUTER-FILE in addition to creating or updating
+pointers in the first @node line in each included file and creating or
+updating the `Top' level node pointers of the outer file. This does
+not create or update other menus and pointers within the included
+files.
+
+With optional UPDATE-EVERYTHING argument (numeric prefix arg, if
+interactive), update all the menus and all the `Next', `Previous', and
+`Up' pointers of all the files included in OUTER-FILE before inserting
+a master menu in OUTER-FILE. Also, update the `Top' level node
+pointers of OUTER-FILE.
+
+Notes:
+
+ * this command does NOT save any files--you must save the
+ outer file and any modified, included files.
+
+ * except for the `Top' node, this command does NOT handle any
+ pre-existing nodes in the outer file; hence, indices must be
+ enclosed in an included file.
+
+Requirements:
+
+ * each of the included files must contain exactly one highest
+ hierarchical level node,
+ * this highest node must be the first node in the included file,
+ * each highest hierarchical level node must be of the same type.
+
+Thus, normally, each included file contains one, and only one,
+chapter."
+
+ (interactive (cons
+ (read-string
+ "Name of outer `include' file: "
+ (buffer-file-name))
+ (cond ((not current-prefix-arg)
+ '(nil nil))
+ ((listp current-prefix-arg)
+ '(t nil)) ; make-master-menu
+ ((numberp current-prefix-arg)
+ '(t t)) ; update-everything
+ )))
+
+ (let* ((included-file-list (texinfo-multi-file-included-list outer-file))
+ (files included-file-list)
+ main-menu-list
+ next-node-name
+ previous-node-name
+ (up-node-name "Top"))
+
+;;; Update the pointers
+;;; and collect the names of the nodes and titles
+ (setq main-menu-list (texinfo-multi-file-update files update-everything))
+
+;;; Insert main menu
+
+ ;; Go to outer file
+ (switch-to-buffer (find-file-noselect (car included-file-list)))
+ (if (texinfo-old-menu-p
+ (point-min)
+ (save-excursion
+ (re-search-forward "^@include")
+ (beginning-of-line)
+ (point)))
+
+ ;; If found, leave point after word `menu' on the `@menu' line.
+ (progn
+ (texinfo-incorporate-descriptions main-menu-list)
+ ;; Delete existing menu.
+ (beginning-of-line)
+ (delete-region
+ (point)
+ (save-excursion (re-search-forward "^@end menu") (point)))
+ ;; Insert main menu
+ (texinfo-multi-files-insert-main-menu main-menu-list))
+
+ ;; Else no current menu; insert it before `@include'
+ (texinfo-multi-files-insert-main-menu main-menu-list))
+
+;;; Insert master menu
+
+ (if make-master-menu
+ (progn
+ ;; First, removing detailed part of any pre-existing master menu
+ (goto-char (point-min))
+ (if (re-search-forward texinfo-master-menu-header nil t)
+ ;; Remove detailed master menu listing
+ (progn
+ (goto-char (match-beginning 0))
+ (let ((end-of-detailed-menu-descriptions
+ (save-excursion ; beginning of end menu line
+ (goto-char (texinfo-menu-end))
+ (beginning-of-line) (forward-char -1)
+ (point))))
+ (delete-region (point) end-of-detailed-menu-descriptions))))
+
+ ;; Create a master menu and insert it
+ (texinfo-insert-master-menu-list
+ (texinfo-multi-file-master-menu-list
+ included-file-list)))))
+
+ ;; Remove unwanted extra lines.
+ (save-excursion
+ (goto-char (point-min))
+
+ (re-search-forward "^@menu")
+ (forward-line -1)
+ (insert "\n") ; Ensure at least one blank line.
+ (delete-blank-lines)
+
+ (re-search-forward "^@end menu")
+ (forward-line 1)
+ (insert "\n") ; Ensure at least one blank line.
+ (delete-blank-lines))
+
+ (message "Multiple files updated."))
+
+
+;;; Place `provide' at end of file.
+(provide 'texnfo-upd)
+
+;;; texnfo-upd.el ends here
diff --git a/contrib/texinfo/info/Makefile.in b/contrib/texinfo/info/Makefile.in
new file mode 100644
index 0000000..2f08d61
--- /dev/null
+++ b/contrib/texinfo/info/Makefile.in
@@ -0,0 +1,227 @@
+# Makefile for texinfo/info. -*- Indented-Text -*-
+# $Id: Makefile.in,v 1.9 1996/10/01 21:44:44 karl Exp $
+#
+# Copyright (C) 1993,96 Free Software Foundation, Inc.
+
+# 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+#### Start of system configuration section. ####
+
+srcdir = @srcdir@
+VPATH = $(srcdir):$(common)
+
+common = $(srcdir)/../libtxi
+util = $(srcdir)/../util
+
+CC = @CC@
+
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_DATA = @INSTALL_DATA@
+
+LN = ln
+RM = rm -f
+MKDIR = mkdir
+MAKEINFO= ../makeinfo/makeinfo
+
+DEFS = @DEFS@
+
+LDEFS = -DHANDLE_MAN_PAGES -DNAMED_FUNCTIONS=1 -DDEFAULT_INFOPATH='"$(DEFAULT_INFOPATH)"'
+
+TERMLIBS = @TERMLIBS@
+LIBS = $(TERMLIBS) -L../libtxi -ltxi @LIBS@
+LOADLIBES = $(LIBS)
+
+SHELL = /bin/sh
+
+CFLAGS = @CFLAGS@
+LDFLAGS = @LDFLAGS@
+
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+bindir = $(exec_prefix)/bin
+# Prefix for each installed program, normally empty or `g'.
+binprefix =
+# Prefix for each installed man page, normally empty or `g'.
+manprefix =
+mandir = $(prefix)/man/man1
+manext = 1
+infodir = $(prefix)/info
+DEFAULT_INFOPATH= $(infodir):.
+
+#### End of system configuration section. ####
+
+SRCS = dir.c display.c echo_area.c filesys.c \
+ info-utils.c info.c infodoc.c infomap.c \
+ m-x.c nodes.c search.c session.c \
+ signals.c terminal.c tilde.c window.c \
+ xmalloc.c indices.c makedoc.c nodemenu.c \
+ footnotes.c dribble.c variables.c gc.c man.c \
+ clib.c
+
+HDRS = display.h doc.h echo_area.h filesys.h \
+ general.h getopt.h info-utils.h info.h \
+ infomap.h nodes.h search.h session.h \
+ signals.h termdep.h terminal.h tilde.h \
+ indices.h window.h footnotes.h dribble.h \
+ variables.h gc.h clib.h
+
+OBJS = dir.o display.o doc.o echo_area.o filesys.o info-utils.o info.o \
+ infodoc.o infomap.o m-x.o nodes.o search.o session.o signals.o \
+ terminal.o tilde.o window.o indices.o xmalloc.o nodemenu.o \
+ footnotes.o dribble.o variables.o gc.o man.o clib.o
+
+# The names of files which declare info commands.
+CMDFILES = $(srcdir)/session.c $(srcdir)/echo_area.c $(srcdir)/infodoc.c \
+ $(srcdir)/m-x.c $(srcdir)/indices.c $(srcdir)/nodemenu.c \
+ $(srcdir)/footnotes.c $(srcdir)/variables.c
+
+# The name of the program which builds documentation structure from CMDFILES.
+MAKEDOC_OBJECTS = makedoc.o clib.o xmalloc.o
+MAKEDOC_SOURCE = makedoc.c clib.c xmalloc.c
+
+infofiles = info.info info-stnd.info
+
+.c.o:
+ $(CC) -c $(CPPFLAGS) $(LDEFS) $(DEFS) -I. -I$(srcdir) -I$(common) $(CFLAGS) $<
+
+all: info $(infofiles)
+sub-all: all
+
+install: all
+ $(INSTALL_PROGRAM) info $(bindir)/$(binprefix)info
+ -d=$(srcdir); test -f ./info.info && d=.; $(INSTALL_DATA) $$d/info.info $(infodir)/info.info
+ -d=$(srcdir); test -f ./info-stnd.info && d=.; $(INSTALL_DATA) $$d/info-stnd.info $(infodir)/info-stnd.info
+ -$(INSTALL_DATA) $(srcdir)/info.1 $(mandir)/$(manprefix)info.$(manext)
+ $(POST_INSTALL)
+ ../util/install-info --info-dir=$(infodir) $(infodir)/info.info
+ ../util/install-info --info-dir=$(infodir) $(infodir)/info-stnd.info
+
+uninstall:
+ $(RM) $(bindir)/info
+ $(RM) $(infodir)/info.info
+ $(RM) $(infodir)/info-stnd.info
+ $(RM) $(mandir)/$(manprefix)info.$(manext)
+
+info: $(OBJS) ../libtxi/libtxi.a
+ $(CC) $(LDFLAGS) -o info $(OBJS) $(LOADLIBES)
+
+all-info: info.info info-stnd.info
+
+info.info: info.texi
+ $(MAKEINFO) --no-split -I$(srcdir) info.texi
+
+info-stnd.info: info-stnd.texi
+ $(MAKEINFO) --no-split -I$(srcdir) info-stnd.texi
+
+dvi all-dvi: info.dvi info-stnd.dvi
+info.dvi: info.texi
+ PATH="$(util):$${PATH}" TEXINPUTS="$(srcdir):$(common):$${TEXINPUTS}" texi2dvi $(srcdir)/info.texi
+
+info-stnd.dvi: info-stnd.texi
+ PATH="$(util):$${PATH}" TEXINPUTS="$(srcdir):$(common):$${TEXINPUTS}" texi2dvi $(srcdir)/info-stnd.texi
+
+makedoc: $(MAKEDOC_OBJECTS) ../libtxi/libtxi.a
+ $(CC) $(LDFLAGS) -o makedoc $(MAKEDOC_OBJECTS) $(LOADLIBES)
+
+Makefile: $(srcdir)/Makefile.in ../config.status
+ cd ..; sh config.status
+
+clean:
+ $(RM) info funs.h doc.c makedoc $(OBJS) $(MAKEDOC_OBJECTS)
+
+distclean: clean texclean
+ $(RM) Makefile config.status config.cache *~ core core.* *.core
+ $(RM) *.BAK makedoc-TAGS TAGS \#* *.info*
+
+mostlyclean: clean
+
+realclean: distclean
+ $(RM) info.info info-stnd.info
+
+TAGS: $(SRCS) makedoc-TAGS
+ etags $(SRCS)
+ cat makedoc-TAGS >>TAGS && $(RM) makedoc-TAGS
+
+makedoc-TAGS: $(CMDFILES)
+ ./makedoc -tags $(CMDFILES) >makedoc-TAGS
+
+texclean:
+ $(RM) *.toc *.aux *.log *.cp *.fn *.tp *.vr *.pg *.ky *.cps
+ $(RM) *.tps *.fns *.kys *.pgs *.vrs
+
+check: info
+
+# The files `doc.c' and `funs.h' are created by ./makedoc run over the source
+# files which contain DECLARE_INFO_COMMAND. `funs.h' is a header file
+# listing the functions found. `doc.c' is a structure containing pointers
+# to those functions along with completable names and documentation strings.
+funs.h: makedoc $(CMDFILES)
+ -@if test -f funs.h; then mv -f funs.h old-funs.h; fi; :
+ -@if test -f doc.c; then mv -f doc.c old-doc.c; fi; :
+ ./makedoc $(CMDFILES)
+ -@if cmp -s old-funs.h funs.h; then mv old-funs.h funs.h; \
+ else $(RM) old-funs.h; fi; :
+ -@if cmp -s old-doc.c doc.c; then mv old-doc.c doc.c; \
+ else $(RM) old-doc.c; fi; :
+
+doc.c: funs.h
+dribble.o: dribble.c dribble.h
+display.o: display.c
+echo_area.o: echo_area.c
+filesys.o: filesys.c
+info-utils.o: info-utils.c
+info.o: info.c filesys.h
+infodoc.o: infodoc.c
+infomap.o: infomap.c
+m-x.o: m-x.c
+nodes.o: nodes.c
+search.o: search.c
+session.o: session.c
+signals.o: signals.c
+terminal.o: terminal.c
+tilde.o: tilde.c
+window.o: window.c
+xmalloc.o: xmalloc.c
+indices.o: indices.c
+makedoc.o: makedoc.c
+
+dir.o: dir.c
+display.o: nodes.h info-utils.h search.h
+display.o: terminal.h window.h display.h
+echo_area.o: info.h
+filesys.o: general.h tilde.h filesys.h
+footnotes.o: footnotes.h
+info-utils.o: info-utils.h nodes.h search.h
+info.o: info.h $(common)/getopt.h
+infodoc.o: info.h doc.h
+infomap.o: infomap.h funs.h
+gc.o: info.h
+m-x.o: info.h
+nodes.o: search.h filesys.h
+nodes.o: nodes.h info-utils.h
+search.o: general.h search.h nodes.h
+session.o: info.h
+signals.o: info.h signals.h
+terminal.o: terminal.h termdep.h
+tilde.o: tilde.h
+variables.c: variables.h
+window.o: nodes.h window.h display.h
+window.o: info-utils.h search.h infomap.h
+
+# Prevent GNU make v3 from overflowing arg limit on SysV.
+.NOEXPORT:
+
+# eof
diff --git a/contrib/texinfo/info/NEWS b/contrib/texinfo/info/NEWS
new file mode 100644
index 0000000..b13fb15
--- /dev/null
+++ b/contrib/texinfo/info/NEWS
@@ -0,0 +1,200 @@
+This release of Info is version 2.11. Please read the file README.
+
+Version 2.11, Sat Apr 1 09:15:21 1995
+
+Changes since 2.7 beta:
+
+Although the basic code remains the same, there are numerous nits
+fixed, including some display bugs, and a memory leak. Some changes
+that have taken place with larger impact include the way in which the
+(dir) node is built; I have added in support for "localdir"
+directories among other things. Info files may be stored in
+compressed formats, and in their own subdirectories; menu items which
+do not explicitly name the node to which they are attached have the
+menu item name looked up as an Info file if it is not found within the
+current document. This means that the menu item:
+
+* Info:: The Info documentation reader.
+
+in (dir) refers to the info node "(info)Top".
+
+Please see the ChangeLog and documentation for details on other
+changes.
+
+Version 2.7 beta, Wed Dec 30 02:02:38 1992
+Version 2.6 beta, Tue Dec 22 03:58:07 1992
+Version 2.5 beta, Tue Dec 8 14:50:35 1992
+Version 2.4 beta, Sat Nov 28 14:34:02 1992
+Version 2.3 beta, Fri Nov 27 01:04:13 1992
+Version 2.2 beta, Tue Nov 24 09:36:08 1992
+Version 2.1 beta, Tue Nov 17 23:29:36 1992
+
+Changes since 2.5 beta:
+
+Note that versions 2.6 and 2.7 Beta were only released to a select group.
+
+* "info-" removed from the front of M-x commands.
+
+* Automatic footnote display. When you enter a node which contains
+ footnotes, and the variable "automatic-footnotes" is "On", Info pops
+ up a window containing the footnotes. Likewise, when you leave that
+ node, the window containing the footnotes goes away.
+
+* Cleaner built in documentation, and documentation functions.
+
+ Use:
+ o `M-x describe-variable' to read a variable's documenation
+ o `M-x describe-key' to find out what a particular keystroke does.
+ o `M-x describe-function' to read a function's documentation.
+ o `M-x where-is' to find out what keys invoke a particular function.
+
+* Info can "tile" the displayed windows (via "M-x tile-windows"). If
+ the variable "automatic-tiling" is "On", then splitting a window or
+ deleting a window causes the remaining windows to be retiled.
+
+* You can save every keystroke you type in a "dribble file" by using the
+ `--dribble FILENAME' option. You can initially read keystrokes from an
+ alternate input stream with `--restore FILENAME', or by redirecting
+ input on the command line `info < old-dribble'.
+
+* New behaviour of menu items. If the label is the same as the
+ target node name, and the node couldn't be found in the current file,
+ treat the label as a file name. For example, a menu entry in "DIR"
+ might contain:
+
+ * Emacs:: Cool text-editor.
+
+ Info would not find the node "(dir)Emacs", so just plain "(emacs)"
+ would be tried.
+
+* New variable "ISO-Latin" allows you to use European machines with
+ 8-bit character sets.
+
+* Cleanups in echo area reading, and redisplay. Cleanups in handling the
+ window which shows possible completions.
+
+* Info can now read files that have been compressed. An array in filesys.c
+ maps extensions to programs that can decompress stdin, and write the results
+ to stdout. Currently, ".Z"/uncompress, ".z"/gunzip, and ".Y"/unyabba are
+ supported. The modeline for a compressed file shows "zz" in it.
+
+* There is a new variable "gc-compressed-files" which, if non-zero, says
+ it is okay to reclaim the file buffer space allocated to a file which
+ was compressed, if, and only if, that file's contents do not appear in
+ any history node.
+
+* New file `nodemenu.c' implements a few functions for manipulating
+ previously visited nodes. `C-x C-b' (list-visited-nodes) produces a
+ menu of the nodes that could be reached by info-history-node in some
+ window. `C-x b' (select-visited-node) is similar, but reads one of
+ the node names with completion.
+
+* Keystroke `M-r' (move_to_screen_line) allows the user to place the cursor at
+ the start of a specific screen line. Without a numeric argument, place the
+ cursor on the center line; with an arg, place the cursor on that line.
+
+* Interruptible display implemented. Basic display speedups and hacks.
+* The message "*** Tags Out of Date ***" now means what it says.
+* Index searching with `,' (info-index-next) has been improved.
+* When scrolling with C-v, C-M-v, or M-v, only "Page Only" scrolling
+ will happen.
+
+* Continous scrolling (along with `]' (info-global-next) and `['
+ (info-global-prev) works better. `]' and `[' accept numeric
+ arguments, moving that many nodes in that case.
+
+* `C-x w' (info-toggle-wrap) controls how lines wider than the width
+ of the screen are displayed. If a line is too long, a `$' is
+ displayed in the rightmost column of the window.
+
+* There are some new variables for controlling the behaviour of Info
+ interactively. The current list of variables is as follows:
+
+ Variable Name Default Value Description
+ ------------- ------------- -----------
+ `automatic-footnotes' On When "On", footnotes appear and
+ disappear automatically.
+
+ `automatic-tiling' Off When "On", creating of deleting a
+ window resizes other windows.
+
+ `visible-bell' Off If non-zero, try to use a visible bell.
+
+ `errors-ring-bell' On If non-zero, errors cause a ring.
+
+ `show-index-match' On If non-zero, the portion of the string
+ matched is highlighted by changing its
+ case.
+
+ `scroll-behaviour' Continuous One of "Continuous", "Next Only", or
+ "Page Only". "Page Only" prevents you from
+ scrolling past the bottom or top of a node.
+ "Next Only" causes the Next or Prev node to
+ be selected when you scroll past the bottom
+ or top of a node. "Continous" moves
+ linearly through the files hierchichal
+ structure.
+
+ `scroll-step' 0 Controls how scrolling is done for you when
+ the cursor moves out of the current window.
+ Non-zero means it is the number of lines
+ you would like the screen to shift. A
+ value of 0 means to center the line
+ containing the cursor in the window.
+
+ `gc-compressed-files' Off If non-zero means it is okay to reclaim the
+ file buffer space allocated to a file which
+ was compressed, if, and only if, that
+ file's contents do not appear in the node
+ list of any window.
+
+ `ISO-Latin' Off Non-zero means that you are using an ISO
+ Latin character set. By default, standard
+ ASCII characters are assumed.
+________________________________________
+This release of Info is version 2.5 beta.
+
+Changes since 2.4 beta:
+
+* Index (i) and (,) commands fully implemented.
+* "configure" script now shipped with Info.
+* New function "set-variable" allows users to set various variables.
+* User-settable behaviour on end or beginning of node scrolling. This
+ supercedes the SPC and DEL changes in 2.3 beta.
+
+________________________________________
+This release of Info is version 2.4 beta.
+
+Changes since 2.3 beta:
+
+* info-last-node now means move to the last node of this info file.
+* info-history-node means move backwards through this window's node history.
+* info-first-node moves to the first node in the Info file. This node is
+ not necessarily "Top"!
+* SPC and DEL can select the Next or Prev node after printing an informative
+ message when pressed at the end/beg of a node.
+
+----------------------------------------
+This release of Info is version 2.3 beta.
+
+Changes since 2.2 beta:
+
+* M-x command lines if NAMED_COMMANDS is #defined. Variable in Makefile.
+* Screen height changes made quite robust.
+* Interactive function "set-screen-height" implements user height changes.
+* Scrolling on some terminals is faster now.
+* C-l with numeric arguement is fixed.
+
+----------------------------------------
+This release of Info is version 2.2 beta.
+
+Changes since 2.0:
+
+* C-g can now interrupt multi-file searches.
+* Incremental search is fully implemented.
+* Loading large tag tables is much faster now.
+* makedoc.c replaces shell script, speeding incremental builds.
+* Scrolling in redisplay is implemented.
+* Recursive uses of the echo area made more robust.
+* Garbage collection of unreferenced nodes.
+
diff --git a/contrib/texinfo/info/README b/contrib/texinfo/info/README
new file mode 100644
index 0000000..d8f1ab6
--- /dev/null
+++ b/contrib/texinfo/info/README
@@ -0,0 +1,37 @@
+The file NEWS contains information about what has changed since the last
+release.
+
+The file ../INSTALL contains instructions on how to install Info.
+
+
+Info 2.0 is a complete rewrite of the original standalone Info I wrote in
+1987, the first program I wrote for rms. That program was something like
+my second Unix program ever, and my die-hard machine language coding habits
+tended to show through. I found the original Info hard to read and
+maintain, and thus decided to write this one.
+
+The rewrite consists of about 12,000 lines of code written in about 12
+days. I believe this version of Info to be in much better shape than the
+original Info, and the only reason it is in Beta test is because of its
+short life span.
+
+Info 2.0 is substantially different from its original standalone
+predecessor. It appears almost identical to the GNU Emacs version, but has
+the advantages of smaller size, ease of portability, and a built in library
+which can be used in other programs (to get or display documentation from
+Info files, for example).
+
+I eagerly await responses to this newer version of Info; comments on its
+portability, ease of use and user interface, code quality, and general
+usefulness are all of interest to me, and I will appreciate any comments
+that you would care to make.
+
+A full listing of the commands available in Info can be gotten by typing
+`?' while within an Info window. This produces a node in a window which
+can be viewed just like any Info node.
+
+Please send your comments, bug reports, and suggestions to
+
+ bug-texinfo@prep.ai.mit.edu
+
+--Brian Fox <bfox@ai.mit.edu>
diff --git a/contrib/texinfo/info/clib.c b/contrib/texinfo/info/clib.c
new file mode 100644
index 0000000..2cebde0
--- /dev/null
+++ b/contrib/texinfo/info/clib.c
@@ -0,0 +1,112 @@
+/* clib.c: Functions which we normally expect to find in the C library.
+ $Id: clib.c,v 1.2 1996/10/03 16:58:31 karl Exp $
+
+ This file is part of GNU Info, a program for reading online documentation
+ stored in Info format.
+
+ Copyright (C) 1995 Free Software Foundation, Inc.
+
+ 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Written by Brian Fox (bfox@ai.mit.edu). */
+
+#include <stdio.h>
+
+#if defined (HAVE_UNISTD_H)
+#include <unistd.h>
+#endif
+
+#if defined (HAVE_STDLIB_H)
+#include <stdlib.h>
+#endif
+
+#if defined (HAVE_STRING_H)
+#include <string.h>
+#endif
+
+#include <sys/errno.h>
+
+extern void *xmalloc (), *xrealloc ();
+#include "general.h"
+
+#if !defined (errno)
+extern int errno;
+#endif
+
+#if !defined (HAVE_STRERROR)
+extern char *sys_errlist[];
+extern int sys_nerr;
+
+char *
+strerror (num)
+ int num;
+{
+ if (num >= sys_nerr)
+ return ("");
+ else
+ return (sys_errlist[num]);
+}
+#endif /* !HAVE_STRERROR */
+
+#if !defined (HAVE_STRCASECMP)
+/* This Unix doesn't have the strcasecmp () function. */
+int
+strcasecmp (string1, string2)
+ char *string1, *string2;
+{
+ char ch1, ch2;
+
+ for (;;)
+ {
+ ch1 = *string1++;
+ ch2 = *string2++;
+
+ if (!(ch1 | ch2))
+ return (0);
+
+ ch1 = info_toupper (ch1);
+ ch2 = info_toupper (ch2);
+
+ if (ch1 != ch2)
+ return (ch1 - ch2);
+ }
+}
+
+/* Compare at most COUNT characters from string1 to string2. Case
+ doesn't matter. */
+int
+strncasecmp (string1, string2, count)
+ char *string1, *string2;
+ int count;
+{
+ register char ch1, ch2;
+
+ while (count)
+ {
+ ch1 = *string1++;
+ ch2 = *string2++;
+
+ ch1 = info_toupper (ch1);
+ ch2 = info_toupper (ch2);
+
+ if (ch1 == ch2)
+ count--;
+ else
+ break;
+ }
+ return (count);
+}
+#endif /* !STRCASECMP */
+
diff --git a/contrib/texinfo/info/clib.h b/contrib/texinfo/info/clib.h
new file mode 100644
index 0000000..c559fe5
--- /dev/null
+++ b/contrib/texinfo/info/clib.h
@@ -0,0 +1,42 @@
+/* clib.h: Declarations of functions which appear in clib.c (or libc.a). */
+
+/* This file is part of GNU Info, a program for reading online documentation
+ stored in Info format.
+
+ Copyright (C) 1995 Free Software Foundation, Inc.
+
+ 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Written by Brian Fox (bfox@ai.mit.edu). */
+
+#if !defined (_CLIB_H_)
+#define _CLIB_H_
+
+#if !defined (HAVE_STRDUP)
+extern char *strdup ();
+#endif
+
+#if !defined (HAVE_STRERROR)
+extern char *strerror ();
+#endif
+
+#if !defined (HAVE_STRCASECMP)
+extern int strcasecmp ();
+extern int strncasecmp ();
+#endif
+
+#endif /* !_CLIB_H_ */
+
+
diff --git a/contrib/texinfo/info/dir.c b/contrib/texinfo/info/dir.c
new file mode 100644
index 0000000..4ccf856
--- /dev/null
+++ b/contrib/texinfo/info/dir.c
@@ -0,0 +1,273 @@
+/* dir.c -- How to build a special "dir" node from "localdir" files. */
+
+/* This file is part of GNU Info, a program for reading online documentation
+ stored in Info format.
+
+ Copyright (C) 1993 Free Software Foundation, Inc.
+
+ 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Written by Brian Fox (bfox@ai.mit.edu). */
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#if defined (HAVE_SYS_FILE_H)
+#include <sys/file.h>
+#endif /* HAVE_SYS_FILE_H */
+#include <sys/errno.h>
+#include "info-utils.h"
+#include "filesys.h"
+#include "tilde.h"
+
+/* The "dir" node can be built from the contents of a file called "dir",
+ with the addition of the menus of every file named in the array
+ dirs_to_add which are found in INFOPATH. */
+
+static void add_menu_to_file_buffer (), insert_text_into_fb_at_binding ();
+static void build_dir_node_internal ();
+
+static char *dirs_to_add[] = {
+ "dir", "localdir", (char *)NULL
+};
+
+void
+maybe_build_dir_node (dirname)
+ char *dirname;
+{
+ FILE_BUFFER *dir_buffer;
+ int path_index, update_tags;
+ char *this_dir;
+
+ /* Check to see if the file has already been built. If so, then
+ do not build it again. */
+ dir_buffer = info_find_file (dirname);
+
+ /* If there is no "dir" in the current info path, we cannot build one
+ from nothing. */
+ if (!dir_buffer)
+ return;
+
+ /* If this directory has already been built, return now. */
+ if (dir_buffer->flags & N_CannotGC)
+ return;
+
+ path_index = update_tags = 0;
+
+ /* Using each element of the path, check for one of the files in
+ DIRS_TO_ADD. Do not check for "localdir.info.Z" or anything else.
+ Only files explictly named are eligible. This is a design decision.
+ There can be an info file name "localdir.info" which contains
+ information on the setting up of "localdir" files. */
+ while (this_dir = extract_colon_unit (infopath, &path_index))
+ {
+ register int da_index;
+ char *from_file;
+
+ /* Expand a leading tilde if one is present. */
+ if (*this_dir == '~')
+ {
+ char *tilde_expanded_dirname;
+
+ tilde_expanded_dirname = tilde_expand_word (this_dir);
+ if (tilde_expanded_dirname != this_dir)
+ {
+ free (this_dir);
+ this_dir = tilde_expanded_dirname;
+ }
+ }
+
+ /* For every file named in DIRS_TO_ADD found in the search path,
+ add the contents of that file's menu to our "dir" node. */
+ for (da_index = 0; from_file = dirs_to_add[da_index]; da_index++)
+ {
+ struct stat finfo;
+ char *fullpath;
+ int namelen, statable;
+
+ namelen = strlen (from_file);
+
+ fullpath = (char *)xmalloc (3 + strlen (this_dir) + namelen);
+ strcpy (fullpath, this_dir);
+ if (fullpath[strlen (fullpath) - 1] != '/')
+ strcat (fullpath, "/");
+ strcat (fullpath, from_file);
+
+ statable = (stat (fullpath, &finfo) == 0);
+
+ /* Only add the contents of this file if it is not identical to the
+ file of the DIR buffer. */
+ if ((statable && S_ISREG (finfo.st_mode)) &&
+ (strcmp (dir_buffer->fullpath, fullpath) != 0))
+ {
+ long filesize;
+ char *contents;
+
+ contents = filesys_read_info_file (fullpath, &filesize, &finfo);
+
+ if (contents)
+ {
+ update_tags++;
+ add_menu_to_file_buffer (contents, filesize, dir_buffer);
+ free (contents);
+ }
+ }
+
+ free (fullpath);
+ }
+ free (this_dir);
+ }
+
+ if (update_tags)
+ build_tags_and_nodes (dir_buffer);
+
+ /* Flag that the dir buffer has been built. */
+ dir_buffer->flags |= N_CannotGC;
+}
+
+/* Given CONTENTS and FB (a file buffer), add the menu found in CONTENTS
+ to the menu found in FB->contents. Second argument SIZE is the total
+ size of CONTENTS. */
+static void
+add_menu_to_file_buffer (contents, size, fb)
+ char *contents;
+ long size;
+ FILE_BUFFER *fb;
+{
+ SEARCH_BINDING contents_binding, fb_binding;
+ long contents_offset, fb_offset;
+
+ contents_binding.buffer = contents;
+ contents_binding.start = 0;
+ contents_binding.end = size;
+ contents_binding.flags = S_FoldCase | S_SkipDest;
+
+ fb_binding.buffer = fb->contents;
+ fb_binding.start = 0;
+ fb_binding.end = fb->filesize;
+ fb_binding.flags = S_FoldCase | S_SkipDest;
+
+ /* Move to the start of the menus in CONTENTS and FB. */
+ contents_offset = search_forward (INFO_MENU_LABEL, &contents_binding);
+ fb_offset = search_forward (INFO_MENU_LABEL, &fb_binding);
+
+ /* If there is no menu in CONTENTS, quit now. */
+ if (contents_offset == -1)
+ return;
+
+ /* There is a menu in CONTENTS, and contents_offset points to the first
+ character following the menu starter string. Skip all whitespace
+ and newline characters. */
+ contents_offset += skip_whitespace_and_newlines (contents + contents_offset);
+
+ /* If there is no menu in FB, make one. */
+ if (fb_offset == -1)
+ {
+ /* Find the start of the second node in this file buffer. If there
+ is only one node, we will be adding the contents to the end of
+ this node. */
+ fb_offset = find_node_separator (&fb_binding);
+
+ /* If not even a single node separator, give up. */
+ if (fb_offset == -1)
+ return;
+
+ fb_binding.start = fb_offset;
+ fb_binding.start +=
+ skip_node_separator (fb_binding.buffer + fb_binding.start);
+
+ /* Try to find the next node separator. */
+ fb_offset = find_node_separator (&fb_binding);
+
+ /* If found one, consider that the start of the menu. Otherwise, the
+ start of this menu is the end of the file buffer (i.e., fb->size). */
+ if (fb_offset != -1)
+ fb_binding.start = fb_offset;
+ else
+ fb_binding.start = fb_binding.end;
+
+ insert_text_into_fb_at_binding
+ (fb, &fb_binding, INFO_MENU_LABEL, strlen (INFO_MENU_LABEL));
+
+ fb_binding.buffer = fb->contents;
+ fb_binding.start = 0;
+ fb_binding.end = fb->filesize;
+ fb_offset = search_forward (INFO_MENU_LABEL, &fb_binding);
+ if (fb_offset == -1)
+ abort ();
+ }
+
+ /* CONTENTS_OFFSET and FB_OFFSET point to the starts of the menus that
+ appear in their respective buffers. Add the remainder of CONTENTS
+ to the end of FB's menu. */
+ fb_binding.start = fb_offset;
+ fb_offset = find_node_separator (&fb_binding);
+ if (fb_offset != -1)
+ fb_binding.start = fb_offset;
+ else
+ fb_binding.start = fb_binding.end;
+
+ /* Leave exactly one blank line between directory entries. */
+ {
+ int num_found = 0;
+
+ while ((fb_binding.start > 0) &&
+ (whitespace_or_newline (fb_binding.buffer[fb_binding.start - 1])))
+ {
+ num_found++;
+ fb_binding.start--;
+ }
+
+ /* Optimize if possible. */
+ if (num_found >= 2)
+ {
+ fb_binding.buffer[fb_binding.start++] = '\n';
+ fb_binding.buffer[fb_binding.start++] = '\n';
+ }
+ else
+ {
+ /* Do it the hard way. */
+ insert_text_into_fb_at_binding (fb, &fb_binding, "\n\n", 2);
+ fb_binding.start += 2;
+ }
+ }
+
+ /* Insert the new menu. */
+ insert_text_into_fb_at_binding
+ (fb, &fb_binding, contents + contents_offset, size - contents_offset);
+}
+
+static void
+insert_text_into_fb_at_binding (fb, binding, text, textlen)
+ FILE_BUFFER *fb;
+ SEARCH_BINDING *binding;
+ char *text;
+ int textlen;
+{
+ char *contents;
+ long start, end;
+
+ start = binding->start;
+ end = fb->filesize;
+
+ contents = (char *)xmalloc (fb->filesize + textlen + 1);
+ memcpy (contents, fb->contents, start);
+ memcpy (contents + start, text, textlen);
+ memcpy (contents + start + textlen, fb->contents + start, end - start);
+ free (fb->contents);
+ fb->contents = contents;
+ fb->filesize += textlen;
+ fb->finfo.st_size = fb->filesize;
+}
diff --git a/contrib/texinfo/info/display.c b/contrib/texinfo/info/display.c
new file mode 100644
index 0000000..0194afa
--- /dev/null
+++ b/contrib/texinfo/info/display.c
@@ -0,0 +1,561 @@
+/* display.c -- How to display Info windows. */
+
+/* This file is part of GNU Info, a program for reading online documentation
+ stored in Info format.
+
+ Copyright (C) 1993 Free Software Foundation, Inc.
+
+ 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Written by Brian Fox (bfox@ai.mit.edu). */
+
+#include <stdio.h>
+#include <ctype.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include "display.h"
+
+extern int info_any_buffered_input_p (); /* Found in session.c. */
+
+static void free_display ();
+static DISPLAY_LINE **make_display ();
+
+/* An array of display lines which tell us what is currently visible on
+ the display. */
+DISPLAY_LINE **the_display = (DISPLAY_LINE **)NULL;
+
+/* Non-zero means do no output. */
+int display_inhibited = 0;
+
+/* Initialize THE_DISPLAY to WIDTH and HEIGHT, with nothing in it. */
+void
+display_initialize_display (width, height)
+ int width, height;
+{
+ free_display (the_display);
+ the_display = make_display (width, height);
+ display_clear_display (the_display);
+}
+
+/* Clear all of the lines in DISPLAY making the screen blank. */
+void
+display_clear_display (display)
+ DISPLAY_LINE **display;
+{
+ register int i;
+ register DISPLAY_LINE *display_line;
+
+ for (i = 0; display_line = display[i]; i++)
+ {
+ display[i]->text[0] = '\0';
+ display[i]->textlen = 0;
+ display[i]->inverse = 0;
+ }
+}
+
+/* Non-zero if we didn't completely redisplay a window. */
+int display_was_interrupted_p = 0;
+
+/* Update the windows pointed to by WINDOW in the_display. This actually
+ writes the text on the screen. */
+void
+display_update_display (window)
+ WINDOW *window;
+{
+ register WINDOW *win;
+
+ display_was_interrupted_p = 0;
+
+ /* For every window in the list, check contents against the display. */
+ for (win = window; win; win = win->next)
+ {
+ /* Only re-display visible windows which need updating. */
+ if (((win->flags & W_WindowVisible) == 0) ||
+ ((win->flags & W_UpdateWindow) == 0) ||
+ (win->height == 0))
+ continue;
+
+ display_update_one_window (win);
+ if (display_was_interrupted_p)
+ break;
+ }
+
+ /* Always update the echo area. */
+ display_update_one_window (the_echo_area);
+}
+
+/* Display WIN on the_display. Unlike display_update_display (), this
+ function only does one window. */
+void
+display_update_one_window (win)
+ WINDOW *win;
+{
+ register char *nodetext; /* Current character to display. */
+ register char *last_node_char; /* Position of the last character in node. */
+ register int i; /* General use index. */
+ char *printed_line; /* Buffer for a printed line. */
+ int pl_index = 0; /* Index into PRINTED_LINE. */
+ int line_index = 0; /* Number of lines done so far. */
+ DISPLAY_LINE **display = the_display;
+
+ /* If display is inhibited, that counts as an interrupted display. */
+ if (display_inhibited)
+ display_was_interrupted_p = 1;
+
+ /* If the window has no height, or display is inhibited, quit now. */
+ if (!win->height || display_inhibited)
+ return;
+
+ /* If the window's first row doesn't appear in the_screen, then it
+ cannot be displayed. This can happen when the_echo_area is the
+ window to be displayed, and the screen has shrunk to less than one
+ line. */
+ if ((win->first_row < 0) || (win->first_row > the_screen->height))
+ return;
+
+ /* Print each line in the window into our local buffer, and then
+ check the contents of that buffer against the display. If they
+ differ, update the display. */
+ printed_line = (char *)xmalloc (1 + win->width);
+
+ if (!win->node || !win->line_starts)
+ goto done_with_node_display;
+
+ nodetext = win->line_starts[win->pagetop];
+ last_node_char = win->node->contents + win->node->nodelen;
+
+ for (; nodetext < last_node_char; nodetext++)
+ {
+ char *rep, *rep_carried_over, rep_temp[2];
+ int replen;
+
+ if (isprint (*nodetext))
+ {
+ rep_temp[0] = *nodetext;
+ replen = 1;
+ rep_temp[1] = '\0';
+ rep = rep_temp;
+ }
+ else
+ {
+ if (*nodetext == '\r' || *nodetext == '\n')
+ {
+ replen = win->width - pl_index;
+ }
+ else
+ {
+ rep = printed_representation (*nodetext, pl_index);
+ replen = strlen (rep);
+ }
+ }
+
+ /* If this character can be printed without passing the width of
+ the line, then stuff it into the line. */
+ if (replen + pl_index < win->width)
+ {
+ /* Optimize if possible. */
+ if (replen == 1)
+ {
+ printed_line[pl_index++] = *rep;
+ }
+ else
+ {
+ for (i = 0; i < replen; i++)
+ printed_line[pl_index++] = rep[i];
+ }
+ }
+ else
+ {
+ DISPLAY_LINE *entry;
+
+ /* If this character cannot be printed in this line, we have
+ found the end of this line as it would appear on the screen.
+ Carefully print the end of the line, and then compare. */
+ if (*nodetext == '\n' || *nodetext == '\r' || *nodetext == '\t')
+ {
+ printed_line[pl_index] = '\0';
+ rep_carried_over = (char *)NULL;
+ }
+ else
+ {
+ /* The printed representation of this character extends into
+ the next line. Remember the offset of the last character
+ printed out of REP so that we can carry the character over
+ to the next line. */
+ for (i = 0; pl_index < (win->width - 1);)
+ printed_line[pl_index++] = rep[i++];
+
+ rep_carried_over = rep + i;
+
+ /* If printing the last character in this window couldn't
+ possibly cause the screen to scroll, place a backslash
+ in the rightmost column. */
+ if (1 + line_index + win->first_row < the_screen->height)
+ {
+ if (win->flags & W_NoWrap)
+ printed_line[pl_index++] = '$';
+ else
+ printed_line[pl_index++] = '\\';
+ }
+ printed_line[pl_index] = '\0';
+ }
+
+ /* We have the exact line as it should appear on the screen.
+ Check to see if this line matches the one already appearing
+ on the screen. */
+ entry = display[line_index + win->first_row];
+
+ /* If the screen line is inversed, then we have to clear
+ the line from the screen first. Why, I don't know. */
+ if (entry->inverse)
+ {
+ terminal_goto_xy (0, line_index + win->first_row);
+ terminal_clear_to_eol ();
+ entry->inverse = 0;
+ entry->text[0] = '\0';
+ entry->textlen = 0;
+ }
+
+ /* Find the offset where these lines differ. */
+ for (i = 0; i < pl_index; i++)
+ if (printed_line[i] != entry->text[i])
+ break;
+
+ /* If the lines are not the same length, or if they differed
+ at all, we must do some redrawing. */
+ if ((i != pl_index) || (pl_index != entry->textlen))
+ {
+ /* Move to the proper point on the terminal. */
+ terminal_goto_xy (i, line_index + win->first_row);
+
+ /* If there is any text to print, print it. */
+ if (i != pl_index)
+ terminal_put_text (printed_line + i);
+
+ /* If the printed text didn't extend all the way to the edge
+ of the window, and text was appearing between here and the
+ edge of the window, clear from here to the end of the line. */
+ if ((pl_index < win->width && pl_index < entry->textlen) ||
+ (entry->inverse))
+ terminal_clear_to_eol ();
+
+ fflush (stdout);
+
+ /* Update the display text buffer. */
+ strcpy (entry->text + i, printed_line + i);
+ entry->textlen = pl_index;
+
+ /* Lines showing node text are not in inverse. Only modelines
+ have that distinction. */
+ entry->inverse = 0;
+ }
+
+ /* We have done at least one line. Increment our screen line
+ index, and check against the bottom of the window. */
+ if (++line_index == win->height)
+ break;
+
+ /* A line has been displayed, and the screen reflects that state.
+ If there is typeahead pending, then let that typeahead be read
+ now, instead of continuing with the display. */
+ if (info_any_buffered_input_p ())
+ {
+ free (printed_line);
+ display_was_interrupted_p = 1;
+ return;
+ }
+
+ /* Reset PL_INDEX to the start of the line. */
+ pl_index = 0;
+
+ /* If there are characters from REP left to print, stuff them
+ into the buffer now. */
+ if (rep_carried_over)
+ for (; rep[pl_index]; pl_index++)
+ printed_line[pl_index] = rep[pl_index];
+
+ /* If this window has chosen not to wrap lines, skip to the end
+ of the physical line in the buffer, and start a new line here. */
+ if (pl_index && (win->flags & W_NoWrap))
+ {
+ char *begin;
+
+ pl_index = 0;
+ printed_line[0] = '\0';
+
+ begin = nodetext;
+
+ while ((nodetext < last_node_char) && (*nodetext != '\n'))
+ nodetext++;
+ }
+ }
+ }
+
+ done_with_node_display:
+ /* We have reached the end of the node or the end of the window. If it
+ is the end of the node, then clear the lines of the window from here
+ to the end of the window. */
+ for (; line_index < win->height; line_index++)
+ {
+ DISPLAY_LINE *entry = display[line_index + win->first_row];
+
+ /* If this line has text on it then make it go away. */
+ if (entry && entry->textlen)
+ {
+ entry->textlen = 0;
+ entry->text[0] = '\0';
+
+ terminal_goto_xy (0, line_index + win->first_row);
+ terminal_clear_to_eol ();
+ }
+ }
+
+ /* Finally, if this window has a modeline it might need to be redisplayed.
+ Check the window's modeline against the one in the display, and update
+ if necessary. */
+ if ((win->flags & W_InhibitMode) == 0)
+ {
+ window_make_modeline (win);
+ line_index = win->first_row + win->height;
+
+ /* This display line must both be in inverse, and have the same
+ contents. */
+ if ((!display[line_index]->inverse) ||
+ (strcmp (display[line_index]->text, win->modeline) != 0))
+ {
+ terminal_goto_xy (0, line_index);
+ terminal_begin_inverse ();
+ terminal_put_text (win->modeline);
+ terminal_end_inverse ();
+ strcpy (display[line_index]->text, win->modeline);
+ display[line_index]->inverse = 1;
+ display[line_index]->textlen = strlen (win->modeline);
+ fflush (stdout);
+ }
+ }
+
+ /* Okay, this window doesn't need updating anymore. */
+ win->flags &= ~W_UpdateWindow;
+ free (printed_line);
+ fflush (stdout);
+}
+
+/* Scroll the region of the_display starting at START, ending at END, and
+ moving the lines AMOUNT lines. If AMOUNT is less than zero, the lines
+ are moved up in the screen, otherwise down. Actually, it is possible
+ for no scrolling to take place in the case that the terminal doesn't
+ support it. This doesn't matter to us. */
+void
+display_scroll_display (start, end, amount)
+ int start, end, amount;
+{
+ register int i, last;
+ DISPLAY_LINE *temp;
+
+ /* If this terminal cannot do scrolling, give up now. */
+ if (!terminal_can_scroll)
+ return;
+
+ /* If there isn't anything displayed on the screen because it is too
+ small, quit now. */
+ if (!the_display[0])
+ return;
+
+ /* If there is typeahead pending, then don't actually do any scrolling. */
+ if (info_any_buffered_input_p ())
+ return;
+
+ /* Do it on the screen. */
+ terminal_scroll_terminal (start, end, amount);
+
+ /* Now do it in the display buffer so our contents match the screen. */
+ if (amount > 0)
+ {
+ last = end + amount;
+
+ /* Shift the lines to scroll right into place. */
+ for (i = 0; i < (end - start); i++)
+ {
+ temp = the_display[last - i];
+ the_display[last - i] = the_display[end - i];
+ the_display[end - i] = temp;
+ }
+
+ /* The lines have been shifted down in the buffer. Clear all of the
+ lines that were vacated. */
+ for (i = start; i != (start + amount); i++)
+ {
+ the_display[i]->text[0] = '\0';
+ the_display[i]->textlen = 0;
+ the_display[i]->inverse = 0;
+ }
+ }
+
+ if (amount < 0)
+ {
+ last = start + amount;
+ for (i = 0; i < (end - start); i++)
+ {
+ temp = the_display[last + i];
+ the_display[last + i] = the_display[start + i];
+ the_display[start + i] = temp;
+ }
+
+ /* The lines have been shifted up in the buffer. Clear all of the
+ lines that are left over. */
+ for (i = end + amount; i != end; i++)
+ {
+ the_display[i]->text[0] = '\0';
+ the_display[i]->textlen = 0;
+ the_display[i]->inverse = 0;
+ }
+ }
+}
+
+/* Try to scroll lines in WINDOW. OLD_PAGETOP is the pagetop of WINDOW before
+ having had its line starts recalculated. OLD_STARTS is the list of line
+ starts that used to appear in this window. OLD_COUNT is the number of lines
+ that appear in the OLD_STARTS array. */
+void
+display_scroll_line_starts (window, old_pagetop, old_starts, old_count)
+ WINDOW *window;
+ int old_pagetop, old_count;
+ char **old_starts;
+{
+ register int i, old, new; /* Indices into the line starts arrays. */
+ int last_new, last_old; /* Index of the last visible line. */
+ int old_first, new_first; /* Index of the first changed line. */
+ int unchanged_at_top = 0;
+ int already_scrolled = 0;
+
+ /* Locate the first line which was displayed on the old window. */
+ old_first = old_pagetop;
+ new_first = window->pagetop;
+
+ /* Find the last line currently visible in this window. */
+ last_new = window->pagetop + (window->height - 1);
+ if (last_new > window->line_count)
+ last_new = window->line_count - 1;
+
+ /* Find the last line which used to be currently visible in this window. */
+ last_old = old_pagetop + (window->height - 1);
+ if (last_old > old_count)
+ last_old = old_count - 1;
+
+ for (old = old_first, new = new_first;
+ old < last_old && new < last_new;
+ old++, new++)
+ if (old_starts[old] != window->line_starts[new])
+ break;
+ else
+ unchanged_at_top++;
+
+ /* Loop through the old lines looking for a match in the new lines. */
+ for (old = old_first + unchanged_at_top; old < last_old; old++)
+ {
+ for (new = new_first; new < last_new; new++)
+ if (old_starts[old] == window->line_starts[new])
+ {
+ /* Find the extent of the matching lines. */
+ for (i = 0; (old + i) < last_old; i++)
+ if (old_starts[old + i] != window->line_starts[new + i])
+ break;
+
+ /* Scroll these lines if there are enough of them. */
+ {
+ int start, end, amount;
+
+ start = (window->first_row
+ + ((old + already_scrolled) - old_pagetop));
+ amount = new - (old + already_scrolled);
+ end = window->first_row + window->height;
+
+ /* If we are shifting the block of lines down, then the last
+ AMOUNT lines will become invisible. Thus, don't bother
+ scrolling them. */
+ if (amount > 0)
+ end -= amount;
+
+ if ((end - start) > 0)
+ {
+ display_scroll_display (start, end, amount);
+
+ /* Some lines have been scrolled. Simulate the scrolling
+ by offsetting the value of the old index. */
+ old += i;
+ already_scrolled += amount;
+ }
+ }
+ }
+ }
+}
+
+/* Move the screen cursor to directly over the current character in WINDOW. */
+void
+display_cursor_at_point (window)
+ WINDOW *window;
+{
+ int vpos, hpos;
+
+ vpos = window_line_of_point (window) - window->pagetop + window->first_row;
+ hpos = window_get_cursor_column (window);
+ terminal_goto_xy (hpos, vpos);
+}
+
+/* **************************************************************** */
+/* */
+/* Functions Static to this File */
+/* */
+/* **************************************************************** */
+
+/* Make a DISPLAY_LINE ** with width and height. */
+static DISPLAY_LINE **
+make_display (width, height)
+ int width, height;
+{
+ register int i;
+ DISPLAY_LINE **display;
+
+ display = (DISPLAY_LINE **)xmalloc ((1 + height) * sizeof (DISPLAY_LINE *));
+
+ for (i = 0; i < height; i++)
+ {
+ display[i] = (DISPLAY_LINE *)xmalloc (sizeof (DISPLAY_LINE));
+ display[i]->text = (char *)xmalloc (1 + width);
+ display[i]->textlen = 0;
+ display[i]->inverse = 0;
+ }
+ display[i] = (DISPLAY_LINE *)NULL;
+ return (display);
+}
+
+/* Free the storage allocated to DISPLAY. */
+static void
+free_display (display)
+ DISPLAY_LINE **display;
+{
+ register int i;
+ register DISPLAY_LINE *display_line;
+
+ if (!display)
+ return;
+
+ for (i = 0; display_line = display[i]; i++)
+ {
+ free (display_line->text);
+ free (display_line);
+ }
+ free (display);
+}
diff --git a/contrib/texinfo/info/display.h b/contrib/texinfo/info/display.h
new file mode 100644
index 0000000..d8bd5a1
--- /dev/null
+++ b/contrib/texinfo/info/display.h
@@ -0,0 +1,76 @@
+/* display.h -- How the display in Info is done. */
+
+/* This file is part of GNU Info, a program for reading online documentation
+ stored in Info format.
+
+ Copyright (C) 1993 Free Software Foundation, Inc.
+
+ 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Written by Brian Fox (bfox@ai.mit.edu). */
+
+#if !defined (_DISPLAY_H_)
+#define _DISPLAY_H_
+
+#include "info-utils.h"
+#include "terminal.h"
+
+typedef struct {
+ char *text; /* Text of the line as it appears. */
+ int textlen; /* Printable Length of TEXT. */
+ int inverse; /* Non-zero means this line is inverse. */
+} DISPLAY_LINE;
+
+/* An array of display lines which tell us what is currently visible on
+ the display. */
+extern DISPLAY_LINE **the_display;
+
+/* Non-zero means do no output. */
+extern int display_inhibited;
+
+/* Non-zero if we didn't completely redisplay a window. */
+extern int display_was_interrupted_p;
+
+/* Initialize THE_DISPLAY to WIDTH and HEIGHT, with nothing in it. */
+extern void display_initialize_display ();
+
+/* Clear all of the lines in DISPLAY making the screen blank. */
+extern void display_clear_display ();
+
+/* Update the windows pointed to by WINDOWS in THE_DISPLAY. This actually
+ writes the text on the screen. */
+extern void display_update_display ();
+
+/* Display WIN on THE_DISPLAY. Unlike display_update_display (), this
+ function only does one window. */
+extern void display_update_one_window ();
+
+/* Move the screen cursor to directly over the current character in WINDOW. */
+extern void display_cursor_at_point ();
+
+/* Scroll the region of the_display starting at START, ending at END, and
+ moving the lines AMOUNT lines. If AMOUNT is less than zero, the lines
+ are moved up in the screen, otherwise down. Actually, it is possible
+ for no scrolling to take place in the case that the terminal doesn't
+ support it. This doesn't matter to us. */
+extern void display_scroll_display ();
+
+/* Try to scroll lines in WINDOW. OLD_PAGETOP is the pagetop of WINDOW before
+ having had its line starts recalculated. OLD_STARTS is the list of line
+ starts that used to appear in this window. OLD_COUNT is the number of lines
+ that appear in the OLD_STARTS array. */
+extern void display_scroll_line_starts ();
+
+#endif /* !_DISPLAY_H_ */
diff --git a/contrib/texinfo/info/doc.h b/contrib/texinfo/info/doc.h
new file mode 100644
index 0000000..8afc28f
--- /dev/null
+++ b/contrib/texinfo/info/doc.h
@@ -0,0 +1,58 @@
+/* doc.h -- Structure associating function pointers with documentation. */
+
+/* This file is part of GNU Info, a program for reading online documentation
+ stored in Info format.
+
+ Copyright (C) 1993 Free Software Foundation, Inc.
+
+ 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Written by Brian Fox (bfox@ai.mit.edu). */
+
+#if !defined (_DOC_H_)
+#define _DOC_H_
+
+#if !defined (NULL)
+# define NULL 0x0
+#endif /* !NULL */
+
+#if !defined (__FUNCTION_DEF)
+# define __FUNCTION_DEF
+typedef int Function ();
+typedef void VFunction ();
+#endif /* _FUNCTION_DEF */
+
+typedef struct {
+ VFunction *func;
+#if defined (NAMED_FUNCTIONS)
+ char *func_name;
+#endif /* NAMED_FUNCTIONS */
+ char *doc;
+} FUNCTION_DOC;
+
+extern FUNCTION_DOC function_doc_array[];
+
+extern char *function_documentation ();
+extern char *key_documentation ();
+extern char *pretty_keyname ();
+extern char *replace_in_documentation ();
+extern void info_document_key ();
+extern void dump_map_to_message_buffer ();
+
+#if defined (NAMED_FUNCTIONS)
+extern char *function_name ();
+extern VFunction *named_function ();
+#endif /* NAMED_FUNCTIONS */
+#endif /* !_DOC_H_ */
diff --git a/contrib/texinfo/info/dribble b/contrib/texinfo/info/dribble
new file mode 100644
index 0000000..99d3a84
--- /dev/null
+++ b/contrib/texinfo/info/dribble
@@ -0,0 +1,5 @@
+mfoo
+em
+buffers
+
+ââ \ No newline at end of file
diff --git a/contrib/texinfo/info/dribble.c b/contrib/texinfo/info/dribble.c
new file mode 100644
index 0000000..8e16cea
--- /dev/null
+++ b/contrib/texinfo/info/dribble.c
@@ -0,0 +1,71 @@
+/* dribble.c -- Dribble files for Info. */
+
+/* This file is part of GNU Info, a program for reading online documentation
+ stored in Info format.
+
+ Copyright (C) 1993 Free Software Foundation, Inc.
+
+ 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Written by Brian Fox (bfox@ai.mit.edu). */
+
+#include <stdio.h>
+#include "dribble.h"
+
+/* When non-zero, it is a stream to write all input characters to for the
+ duration of this info session. */
+FILE *info_dribble_file = (FILE *)NULL;
+
+/* Open a dribble file named NAME, perhaps closing an already open one.
+ This sets the global variable INFO_DRIBBLE_FILE to the open stream. */
+void
+open_dribble_file (name)
+ char *name;
+{
+ /* Perhaps close existing dribble file. */
+ close_dribble_file ();
+
+ info_dribble_file = fopen (name, "w");
+
+#if defined (HAVE_SETVBUF)
+ if (info_dribble_file)
+# if defined (SETVBUF_REVERSED)
+ setvbuf (info_dribble_file, _IONBF, (char *)NULL, 1);
+# else
+ setvbuf (info_dribble_file, (char *)NULL, _IONBF, 1);
+# endif /* !SETVBUF_REVERSED */
+#endif /* HAVE_SETVBUF */
+}
+
+/* If there is a dribble file already open, close it. */
+void
+close_dribble_file ()
+{
+ if (info_dribble_file)
+ {
+ fflush (info_dribble_file);
+ fclose (info_dribble_file);
+ info_dribble_file = (FILE *)NULL;
+ }
+}
+
+/* Write some output to our existing dribble file. */
+void
+dribble (byte)
+ unsigned char byte;
+{
+ if (info_dribble_file)
+ fwrite (&byte, sizeof (unsigned char), 1, info_dribble_file);
+}
diff --git a/contrib/texinfo/info/dribble.h b/contrib/texinfo/info/dribble.h
new file mode 100644
index 0000000..5647b40
--- /dev/null
+++ b/contrib/texinfo/info/dribble.h
@@ -0,0 +1,41 @@
+/* dribble.h -- Functions and vars declared in dribble.c. */
+
+/* This file is part of GNU Info, a program for reading online documentation
+ stored in Info format.
+
+ Copyright (C) 1993 Free Software Foundation, Inc.
+
+ 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Written by Brian Fox (bfox@ai.mit.edu). */
+
+#if !defined (_DRIBBLE_H_)
+#define _DRIBBLE_H_
+
+/* When non-zero, it is a stream to write all input characters to for the
+ duration of this info session. */
+extern FILE *info_dribble_file;
+
+/* Open a dribble file named NAME, perhaps closing an already open one.
+ This sets the global variable INFO_DRIBBLE_FILE to the open stream. */
+extern void open_dribble_file ();
+
+/* If there is a dribble file already open, close it. */
+extern void close_dribble_file ();
+
+/* Write some output to our existing dribble file. */
+extern void dribble ();
+
+#endif /* !_DRIBBLE_H_ */
diff --git a/contrib/texinfo/info/echo_area.c b/contrib/texinfo/info/echo_area.c
new file mode 100644
index 0000000..265e988
--- /dev/null
+++ b/contrib/texinfo/info/echo_area.c
@@ -0,0 +1,1508 @@
+/* echo_area.c -- How to read a line in the echo area. */
+
+/* This file is part of GNU Info, a program for reading online documentation
+ stored in Info format.
+
+ Copyright (C) 1993 Free Software Foundation, Inc.
+
+ 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Written by Brian Fox (bfox@ai.mit.edu). */
+
+#include "info.h"
+
+#if defined (FD_SET)
+# if defined (hpux)
+# define fd_set_cast(x) (int *)(x)
+# else
+# define fd_set_cast(x) (fd_set *)(x)
+# endif /* !hpux */
+#endif /* FD_SET */
+
+/* Non-zero means that C-g was used to quit reading input. */
+int info_aborted_echo_area = 0;
+
+/* Non-zero means that the echo area is being used to read input. */
+int echo_area_is_active = 0;
+
+/* The address of the last command executed in the echo area. */
+VFunction *ea_last_executed_command = (VFunction *)NULL;
+
+/* Non-zero means that the last command executed while reading input
+ killed some text. */
+int echo_area_last_command_was_kill = 0;
+
+/* Variables which hold on to the current state of the input line. */
+static char input_line[1 + EA_MAX_INPUT];
+static char *input_line_prompt;
+static int input_line_point;
+static int input_line_beg;
+static int input_line_end;
+static NODE input_line_node = {
+ (char *)NULL, (char *)NULL, (char *)NULL, input_line, EA_MAX_INPUT, 0
+};
+
+static void echo_area_initialize_node ();
+static void push_echo_area (), pop_echo_area ();
+static int echo_area_stack_depth (), echo_area_stack_contains_completions_p ();
+
+static void ea_kill_text ();
+
+/* Non-zero means we force the user to complete. */
+static int echo_area_must_complete_p = 0;
+static int completions_window_p ();
+
+/* If non-null, this is a window which was specifically created to display
+ possible completions output. We remember it so we can delete it when
+ appropriate. */
+static WINDOW *echo_area_completions_window = (WINDOW *)NULL;
+
+/* Variables which keep track of the window which was active prior to
+ entering the echo area. */
+static WINDOW *calling_window = (WINDOW *)NULL;
+static NODE *calling_window_node = (NODE *)NULL;
+static long calling_window_point = 0;
+static long calling_window_pagetop = 0;
+
+/* Remember the node and pertinent variables of the calling window. */
+static void
+remember_calling_window (window)
+ WINDOW *window;
+{
+ /* Only do this if the calling window is not the completions window, or,
+ if it is the completions window and there is no other window. */
+ if (!completions_window_p (window) ||
+ ((window == windows) && !(window->next)))
+ {
+ calling_window = window;
+ calling_window_node = window->node;
+ calling_window_point = window->point;
+ calling_window_pagetop = window->pagetop;
+ }
+}
+
+/* Restore the caller's window so that it shows the node that it was showing
+ on entry to info_read_xxx_echo_area (). */
+static void
+restore_calling_window ()
+{
+ register WINDOW *win, *compwin = (WINDOW *)NULL;
+
+ /* If the calling window is still visible, and it is the window that
+ we used for completions output, then restore the calling window. */
+ for (win = windows; win; win = win->next)
+ {
+ if (completions_window_p (win))
+ compwin = win;
+
+ if (win == calling_window && win == compwin)
+ {
+ window_set_node_of_window (calling_window, calling_window_node);
+ calling_window->point = calling_window_point;
+ calling_window->pagetop = calling_window_pagetop;
+ compwin = (WINDOW *)NULL;
+ break;
+ }
+ }
+
+ /* Delete the completions window if it is still present, it isn't the
+ last window on the screen, and there aren't any prior echo area reads
+ pending which created a completions window. */
+ if (compwin)
+ {
+ if ((compwin != windows || windows->next) &&
+ !echo_area_stack_contains_completions_p ())
+ {
+ WINDOW *next;
+ int pagetop, start, end, amount;
+
+ next = compwin->next;
+ if (next)
+ {
+ start = next->first_row;
+ end = start + next->height;
+ amount = - (compwin->height + 1);
+ pagetop = next->pagetop;
+ }
+
+ info_delete_window_internal (compwin);
+
+ /* This is not necessary because info_delete_window_internal ()
+ calls echo_area_inform_of_deleted_window (), which does the
+ right thing. */
+#if defined (UNNECESSARY)
+ echo_area_completions_window = (WINDOW *)NULL;
+#endif /* UNNECESSARY */
+
+ if (next)
+ {
+ display_scroll_display (start, end, amount);
+ next->pagetop = pagetop;
+ display_update_display (windows);
+ }
+ }
+ }
+}
+
+/* Set up a new input line with PROMPT. */
+static void
+initialize_input_line (prompt)
+ char *prompt;
+{
+ input_line_prompt = prompt;
+ if (prompt)
+ strcpy (input_line, prompt);
+ else
+ input_line[0] = '\0';
+
+ input_line_beg = input_line_end = input_line_point = strlen (prompt);
+}
+
+static char *
+echo_area_after_read ()
+{
+ char *return_value;
+
+ if (info_aborted_echo_area)
+ {
+ info_aborted_echo_area = 0;
+ return_value = (char *)NULL;
+ }
+ else
+ {
+ if (input_line_beg == input_line_end)
+ return_value = strdup ("");
+ else
+ {
+ int line_len = input_line_end - input_line_beg;
+ return_value = (char *) xmalloc (1 + line_len);
+ strncpy (return_value, &input_line[input_line_beg], line_len);
+ return_value[line_len] = '\0';
+ }
+ }
+ return (return_value);
+}
+
+/* Read a line of text in the echo area. Return a malloc ()'ed string,
+ or NULL if the user aborted out of this read. WINDOW is the currently
+ active window, so that we can restore it when we need to. PROMPT, if
+ non-null, is a prompt to print before reading the line. */
+char *
+info_read_in_echo_area (window, prompt)
+ WINDOW *window;
+ char *prompt;
+{
+ char *line;
+
+ /* If the echo area is already active, remember the current state. */
+ if (echo_area_is_active)
+ push_echo_area ();
+
+ /* Initialize our local variables. */
+ initialize_input_line (prompt);
+
+ /* Initialize the echo area for the first (but maybe not the last) time. */
+ echo_area_initialize_node ();
+
+ /* Save away the original node of this window, and the window itself,
+ so echo area commands can temporarily use this window. */
+ remember_calling_window (window);
+
+ /* Let the rest of Info know that the echo area is active. */
+ echo_area_is_active++;
+ active_window = the_echo_area;
+
+ /* Read characters in the echo area. */
+ info_read_and_dispatch ();
+
+ echo_area_is_active--;
+
+ /* Restore the original active window and show point in it. */
+ active_window = calling_window;
+ restore_calling_window ();
+ display_cursor_at_point (active_window);
+ fflush (stdout);
+
+ /* Get the value of the line. */
+ line = echo_area_after_read ();
+
+ /* If there is a previous loop waiting for us, restore it now. */
+ if (echo_area_is_active)
+ pop_echo_area ();
+
+ /* Return the results to the caller. */
+ return (line);
+}
+
+/* (re) Initialize the echo area node. */
+static void
+echo_area_initialize_node ()
+{
+ register int i;
+
+ for (i = input_line_end; i < sizeof (input_line); i++)
+ input_line[i] = ' ';
+
+ input_line[i - 1] = '\n';
+ window_set_node_of_window (the_echo_area, &input_line_node);
+ input_line[input_line_end] = '\n';
+}
+
+/* Prepare to read characters in the echo area. This can initialize the
+ echo area node, but its primary purpose is to side effect the input
+ line buffer contents. */
+void
+echo_area_prep_read ()
+{
+ if (the_echo_area->node != &input_line_node)
+ echo_area_initialize_node ();
+
+ the_echo_area->point = input_line_point;
+ input_line[input_line_end] = '\n';
+ display_update_one_window (the_echo_area);
+ display_cursor_at_point (active_window);
+}
+
+
+/* **************************************************************** */
+/* */
+/* Echo Area Movement Commands */
+/* */
+/* **************************************************************** */
+
+DECLARE_INFO_COMMAND (ea_forward, "Move forward a character")
+{
+ if (count < 0)
+ ea_backward (window, -count, key);
+ else
+ {
+ input_line_point += count;
+ if (input_line_point > input_line_end)
+ input_line_point = input_line_end;
+ }
+}
+
+DECLARE_INFO_COMMAND (ea_backward, "Move backward a character")
+{
+ if (count < 0)
+ ea_forward (window, -count, key);
+ else
+ {
+ input_line_point -= count;
+ if (input_line_point < input_line_beg)
+ input_line_point = input_line_beg;
+ }
+}
+
+DECLARE_INFO_COMMAND (ea_beg_of_line, "Move to the start of this line")
+{
+ input_line_point = input_line_beg;
+}
+
+DECLARE_INFO_COMMAND (ea_end_of_line, "Move to the end of this line")
+{
+ input_line_point = input_line_end;
+}
+
+#define alphabetic(c) (islower (c) || isupper (c) || isdigit (c))
+
+/* Move forward a word in the input line. */
+DECLARE_INFO_COMMAND (ea_forward_word, "Move forward a word")
+{
+ int c;
+
+ if (count < 0)
+ ea_backward_word (window, -count, key);
+ else
+ {
+ while (count--)
+ {
+ if (input_line_point == input_line_end)
+ return;
+
+ /* If we are not in a word, move forward until we are in one.
+ Then, move forward until we hit a non-alphabetic character. */
+ c = input_line[input_line_point];
+
+ if (!alphabetic (c))
+ {
+ while (++input_line_point < input_line_end)
+ {
+ c = input_line[input_line_point];
+ if (alphabetic (c))
+ break;
+ }
+ }
+
+ if (input_line_point == input_line_end)
+ return;
+
+ while (++input_line_point < input_line_end)
+ {
+ c = input_line[input_line_point];
+ if (!alphabetic (c))
+ break;
+ }
+ }
+ }
+}
+
+DECLARE_INFO_COMMAND (ea_backward_word, "Move backward a word")
+{
+ int c;
+
+ if (count < 0)
+ ea_forward_word (window, -count, key);
+ else
+ {
+ while (count--)
+ {
+ if (input_line_point == input_line_beg)
+ return;
+
+ /* Like ea_forward_word (), except that we look at the
+ characters just before point. */
+
+ c = input_line[input_line_point - 1];
+
+ if (!alphabetic (c))
+ {
+ while ((--input_line_point) != input_line_beg)
+ {
+ c = input_line[input_line_point - 1];
+ if (alphabetic (c))
+ break;
+ }
+ }
+
+ while (input_line_point != input_line_beg)
+ {
+ c = input_line[input_line_point - 1];
+ if (!alphabetic (c))
+ break;
+ else
+ --input_line_point;
+ }
+ }
+ }
+}
+
+DECLARE_INFO_COMMAND (ea_delete, "Delete the character under the cursor")
+{
+ register int i;
+
+ if (count < 0)
+ ea_rubout (window, -count, key);
+ else
+ {
+ if (input_line_point == input_line_end)
+ return;
+
+ if (info_explicit_arg || count > 1)
+ {
+ int orig_point;
+
+ orig_point = input_line_point;
+ ea_forward (window, count, key);
+ ea_kill_text (orig_point, input_line_point);
+ input_line_point = orig_point;
+ }
+ else
+ {
+ for (i = input_line_point; i < input_line_end; i++)
+ input_line[i] = input_line[i + 1];
+
+ input_line_end--;
+ }
+ }
+}
+
+DECLARE_INFO_COMMAND (ea_rubout, "Delete the character behind the cursor")
+{
+ if (count < 0)
+ ea_delete (window, -count, key);
+ else
+ {
+ int start;
+
+ if (input_line_point == input_line_beg)
+ return;
+
+ start = input_line_point;
+ ea_backward (window, count, key);
+
+ if (info_explicit_arg || count > 1)
+ ea_kill_text (start, input_line_point);
+ else
+ ea_delete (window, count, key);
+ }
+}
+
+DECLARE_INFO_COMMAND (ea_abort, "Cancel or quit operation")
+{
+ /* If any text, just discard it, and restore the calling window's node.
+ If no text, quit. */
+ if (input_line_end != input_line_beg)
+ {
+ terminal_ring_bell ();
+ input_line_end = input_line_point = input_line_beg;
+ if (calling_window->node != calling_window_node)
+ restore_calling_window ();
+ }
+ else
+ info_aborted_echo_area = 1;
+}
+
+DECLARE_INFO_COMMAND (ea_newline, "Accept (or force completion of) this line")
+{
+ /* Stub does nothing. Simply here to see if it has been executed. */
+}
+
+DECLARE_INFO_COMMAND (ea_quoted_insert, "Insert next character verbatim")
+{
+ unsigned char character;
+
+ character = info_get_another_input_char ();
+ ea_insert (window, count, character);
+}
+
+DECLARE_INFO_COMMAND (ea_insert, "Insert this character")
+{
+ register int i;
+
+ if ((input_line_end + 1) == EA_MAX_INPUT)
+ {
+ terminal_ring_bell ();
+ return;
+ }
+
+ for (i = input_line_end + 1; i != input_line_point; i--)
+ input_line[i] = input_line[i - 1];
+
+ input_line[input_line_point] = key;
+ input_line_point++;
+ input_line_end++;
+}
+
+DECLARE_INFO_COMMAND (ea_tab_insert, "Insert a TAB character")
+{
+ ea_insert (window, count, '\t');
+}
+
+/* Transpose the characters at point. If point is at the end of the line,
+ then transpose the characters before point. */
+DECLARE_INFO_COMMAND (ea_transpose_chars, "Transpose characters at point")
+{
+ /* Handle conditions that would make it impossible to transpose
+ characters. */
+ if (!count || !input_line_point || (input_line_end - input_line_beg) < 2)
+ return;
+
+ while (count)
+ {
+ int t;
+ if (input_line_point == input_line_end)
+ {
+ t = input_line[input_line_point - 1];
+
+ input_line[input_line_point - 1] = input_line[input_line_point - 2];
+ input_line[input_line_point - 2] = t;
+ }
+ else
+ {
+ t = input_line[input_line_point];
+
+ input_line[input_line_point] = input_line[input_line_point - 1];
+ input_line[input_line_point - 1] = t;
+
+ if (count < 0 && input_line_point != input_line_beg)
+ input_line_point--;
+ else
+ input_line_point++;
+ }
+
+ if (count < 0)
+ count++;
+ else
+ count--;
+ }
+}
+
+/* **************************************************************** */
+/* */
+/* Echo Area Killing and Yanking */
+/* */
+/* **************************************************************** */
+
+static char **kill_ring = (char **)NULL;
+static int kill_ring_index = 0; /* Number of kills appearing in KILL_RING. */
+static int kill_ring_slots = 0; /* Number of slots allocated to KILL_RING. */
+static int kill_ring_loc = 0; /* Location of current yank pointer. */
+
+/* The largest number of kills that we remember at one time. */
+static int max_retained_kills = 15;
+
+DECLARE_INFO_COMMAND (ea_yank, "Yank back the contents of the last kill")
+{
+ register int i;
+ register char *text;
+
+ if (!kill_ring_index)
+ {
+ inform_in_echo_area ("Kill ring is empty");
+ return;
+ }
+
+ text = kill_ring[kill_ring_loc];
+
+ for (i = 0; text[i]; i++)
+ ea_insert (window, 1, text[i]);
+}
+
+/* If the last command was yank, or yank_pop, and the text just before
+ point is identical to the current kill item, then delete that text
+ from the line, rotate the index down, and yank back some other text. */
+DECLARE_INFO_COMMAND (ea_yank_pop, "Yank back a previous kill")
+{
+ register int len;
+
+ if (((ea_last_executed_command != ea_yank) &&
+ (ea_last_executed_command != ea_yank_pop)) ||
+ (kill_ring_index == 0))
+ return;
+
+ len = strlen (kill_ring[kill_ring_loc]);
+
+ /* Delete the last yanked item from the line. */
+ {
+ register int i, counter;
+
+ counter = input_line_end - input_line_point;
+
+ for (i = input_line_point - len; counter; i++, counter--)
+ input_line[i] = input_line[i + len];
+
+ input_line_end -= len;
+ input_line_point -= len;
+ }
+
+ /* Get a previous kill, and yank that. */
+ kill_ring_loc--;
+ if (kill_ring_loc < 0)
+ kill_ring_loc = kill_ring_index - 1;
+
+ ea_yank (window, count, key);
+}
+
+/* Delete the text from point to end of line. */
+DECLARE_INFO_COMMAND (ea_kill_line, "Kill to the end of the line")
+{
+ if (count < 0)
+ {
+ ea_kill_text (input_line_point, input_line_beg);
+ input_line_point = input_line_beg;
+ }
+ else
+ ea_kill_text (input_line_point, input_line_end);
+}
+
+/* Delete the text from point to beg of line. */
+DECLARE_INFO_COMMAND (ea_backward_kill_line,
+ "Kill to the beginning of the line")
+{
+ if (count < 0)
+ ea_kill_text (input_line_point, input_line_end);
+ else
+ {
+ ea_kill_text (input_line_point, input_line_beg);
+ input_line_point = input_line_beg;
+ }
+}
+
+/* Delete from point to the end of the current word. */
+DECLARE_INFO_COMMAND (ea_kill_word, "Kill the word following the cursor")
+{
+ int orig_point = input_line_point;
+
+ if (count < 0)
+ ea_backward_kill_word (window, -count, key);
+ else
+ {
+ ea_forward_word (window, count, key);
+
+ if (input_line_point != orig_point)
+ ea_kill_text (orig_point, input_line_point);
+
+ input_line_point = orig_point;
+ }
+}
+
+/* Delete from point to the start of the current word. */
+DECLARE_INFO_COMMAND (ea_backward_kill_word,
+ "Kill the word preceding the cursor")
+{
+ int orig_point = input_line_point;
+
+ if (count < 0)
+ ea_kill_word (window, -count, key);
+ else
+ {
+ ea_backward_word (window, count, key);
+
+ if (input_line_point != orig_point)
+ ea_kill_text (orig_point, input_line_point);
+ }
+}
+
+/* The way to kill something. This appends or prepends to the last
+ kill, if the last command was a kill command. If FROM is less
+ than TO, then the killed text is appended to the most recent kill,
+ otherwise it is prepended. If the last command was not a kill command,
+ then a new slot is made for this kill. */
+static void
+ea_kill_text (from, to)
+ int from, to;
+{
+ register int i, counter, distance;
+ int killing_backwards, slot;
+ char *killed_text;
+
+ killing_backwards = (from > to);
+
+ /* If killing backwards, reverse the values of FROM and TO. */
+ if (killing_backwards)
+ {
+ int temp = from;
+ from = to;
+ to = temp;
+ }
+
+ /* Remember the text that we are about to delete. */
+ distance = to - from;
+ killed_text = (char *)xmalloc (1 + distance);
+ strncpy (killed_text, &input_line[from], distance);
+ killed_text[distance] = '\0';
+
+ /* Actually delete the text from the line. */
+ counter = input_line_end - to;
+
+ for (i = from; counter; i++, counter--)
+ input_line[i] = input_line[i + distance];
+
+ input_line_end -= distance;
+
+ /* If the last command was a kill, append or prepend the killed text to
+ the last command's killed text. */
+ if (echo_area_last_command_was_kill)
+ {
+ char *old, *new;
+
+ slot = kill_ring_loc;
+ old = kill_ring[slot];
+ new = (char *)xmalloc (1 + strlen (old) + strlen (killed_text));
+
+ if (killing_backwards)
+ {
+ /* Prepend TEXT to current kill. */
+ strcpy (new, killed_text);
+ strcat (new, old);
+ }
+ else
+ {
+ /* Append TEXT to current kill. */
+ strcpy (new, old);
+ strcat (new, killed_text);
+ }
+
+ free (old);
+ free (killed_text);
+ kill_ring[slot] = new;
+ }
+ else
+ {
+ /* Try to store the kill in a new slot, unless that would cause there
+ to be too many remembered kills. */
+ slot = kill_ring_index;
+
+ if (slot == max_retained_kills)
+ slot = 0;
+
+ if (slot + 1 > kill_ring_slots)
+ kill_ring = (char **) xrealloc
+ (kill_ring,
+ (kill_ring_slots += max_retained_kills) * sizeof (char *));
+
+ if (slot != kill_ring_index)
+ free (kill_ring[slot]);
+ else
+ kill_ring_index++;
+
+ kill_ring[slot] = killed_text;
+
+ kill_ring_loc = slot;
+ }
+
+ /* Notice that the last command was a kill. */
+ echo_area_last_command_was_kill++;
+}
+
+/* **************************************************************** */
+/* */
+/* Echo Area Completion */
+/* */
+/* **************************************************************** */
+
+/* Pointer to an array of REFERENCE to complete over. */
+static REFERENCE **echo_area_completion_items = (REFERENCE **)NULL;
+
+/* Sorted array of REFERENCE * which is the possible completions found in
+ the variable echo_area_completion_items. If there is only one element,
+ it is the only possible completion. */
+static REFERENCE **completions_found = (REFERENCE **)NULL;
+static int completions_found_index = 0;
+static int completions_found_slots = 0;
+
+/* The lowest common denominator found while completing. */
+static REFERENCE *LCD_completion;
+
+/* Internal functions used by the user calls. */
+static void build_completions (), completions_must_be_rebuilt ();
+
+/* Variable which holds the output of completions. */
+static NODE *possible_completions_output_node = (NODE *)NULL;
+
+static char *compwin_name = "*Completions*";
+
+/* Return non-zero if WINDOW is a window used for completions output. */
+static int
+completions_window_p (window)
+ WINDOW *window;
+{
+ int result = 0;
+
+ if (internal_info_node_p (window->node) &&
+ (strcmp (window->node->nodename, compwin_name) == 0))
+ result = 1;
+
+ return (result);
+}
+
+/* Workhorse for completion readers. If FORCE is non-zero, the user cannot
+ exit unless the line read completes, or is empty. */
+char *
+info_read_completing_internal (window, prompt, completions, force)
+ WINDOW *window;
+ char *prompt;
+ REFERENCE **completions;
+ int force;
+{
+ char *line;
+
+ /* If the echo area is already active, remember the current state. */
+ if (echo_area_is_active)
+ push_echo_area ();
+
+ echo_area_must_complete_p = force;
+
+ /* Initialize our local variables. */
+ initialize_input_line (prompt);
+
+ /* Initialize the echo area for the first (but maybe not the last) time. */
+ echo_area_initialize_node ();
+
+ /* Save away the original node of this window, and the window itself,
+ so echo area commands can temporarily use this window. */
+ remember_calling_window (window);
+
+ /* Save away the list of items to complete over. */
+ echo_area_completion_items = completions;
+ completions_must_be_rebuilt ();
+
+ active_window = the_echo_area;
+ echo_area_is_active++;
+
+ /* Read characters in the echo area. */
+ while (1)
+ {
+ info_read_and_dispatch ();
+
+ line = echo_area_after_read ();
+
+ /* Force the completion to take place if the user hasn't accepted
+ a default or aborted, and if FORCE is active. */
+ if (force && line && *line && completions)
+ {
+ register int i;
+
+ build_completions ();
+
+ /* If there is only one completion, then make the line be that
+ completion. */
+ if (completions_found_index == 1)
+ {
+ free (line);
+ line = strdup (completions_found[0]->label);
+ break;
+ }
+
+ /* If one of the completions matches exactly, then that is okay, so
+ return the current line. */
+ for (i = 0; i < completions_found_index; i++)
+ if (strcasecmp (completions_found[i]->label, line) == 0)
+ {
+ free (line);
+ line = strdup (completions_found[i]->label);
+ break;
+ }
+
+ /* If no match, go back and try again. */
+ if (i == completions_found_index)
+ {
+ inform_in_echo_area ("Not complete");
+ continue;
+ }
+ }
+ break;
+ }
+ echo_area_is_active--;
+
+ /* Restore the original active window and show point in it. */
+ active_window = calling_window;
+ restore_calling_window ();
+ display_cursor_at_point (active_window);
+ fflush (stdout);
+
+ echo_area_completion_items = (REFERENCE **)NULL;
+ completions_must_be_rebuilt ();
+
+ /* If there is a previous loop waiting for us, restore it now. */
+ if (echo_area_is_active)
+ pop_echo_area ();
+
+ return (line);
+}
+
+/* Read a line in the echo area with completion over COMPLETIONS. */
+char *
+info_read_completing_in_echo_area (window, prompt, completions)
+ WINDOW *window;
+ char *prompt;
+ REFERENCE **completions;
+{
+ return (info_read_completing_internal (window, prompt, completions, 1));
+}
+
+/* Read a line in the echo area allowing completion over COMPLETIONS, but
+ not requiring it. */
+char *
+info_read_maybe_completing (window, prompt, completions)
+ WINDOW *window;
+ char *prompt;
+ REFERENCE **completions;
+{
+ return (info_read_completing_internal (window, prompt, completions, 0));
+}
+
+DECLARE_INFO_COMMAND (ea_possible_completions, "List possible completions")
+{
+ if (!echo_area_completion_items)
+ {
+ ea_insert (window, count, key);
+ return;
+ }
+
+ build_completions ();
+
+ if (!completions_found_index)
+ {
+ terminal_ring_bell ();
+ inform_in_echo_area ("No completions");
+ }
+ else if ((completions_found_index == 1) && (key != '?'))
+ {
+ inform_in_echo_area ("Sole completion");
+ }
+ else
+ {
+ register int i, l;
+ int limit, count, max_label = 0;
+
+ initialize_message_buffer ();
+ printf_to_message_buffer
+ ("There %s %d ", completions_found_index == 1 ? "is" : "are",
+ completions_found_index);
+ printf_to_message_buffer
+ ("completion%s:\n", completions_found_index == 1 ? "" : "s");
+
+ /* Find the maximum length of a label. */
+ for (i = 0; i < completions_found_index; i++)
+ {
+ int len = strlen (completions_found[i]->label);
+ if (len > max_label)
+ max_label = len;
+ }
+
+ max_label += 4;
+
+ /* Find out how many columns we should print in. */
+ limit = calling_window->width / max_label;
+ if (limit != 1 && (limit * max_label == calling_window->width))
+ limit--;
+
+ /* Avoid a possible floating exception. If max_label > width then
+ the limit will be 0 and a divide-by-zero fault will result. */
+ if (limit == 0)
+ limit = 1;
+
+ /* How many iterations of the printing loop? */
+ count = (completions_found_index + (limit - 1)) / limit;
+
+ /* Watch out for special case. If the number of completions is less
+ than LIMIT, then just do the inner printing loop. */
+ if (completions_found_index < limit)
+ count = 1;
+
+ /* Print the sorted items, up-and-down alphabetically. */
+ for (i = 0; i < count; i++)
+ {
+ register int j;
+
+ for (j = 0, l = i; j < limit; j++)
+ {
+ if (l >= completions_found_index)
+ break;
+ else
+ {
+ char *label;
+ int printed_length, k;
+
+ label = completions_found[l]->label;
+ printed_length = strlen (label);
+ printf_to_message_buffer ("%s", label);
+
+ if (j + 1 < limit)
+ {
+ for (k = 0; k < max_label - printed_length; k++)
+ printf_to_message_buffer (" ");
+ }
+ }
+ l += count;
+ }
+ printf_to_message_buffer ("\n");
+ }
+
+ /* Make a new node to hold onto possible completions. Don't destroy
+ dangling pointers. */
+ {
+ NODE *temp;
+
+ temp = message_buffer_to_node ();
+ add_gcable_pointer (temp->contents);
+ name_internal_node (temp, compwin_name);
+ possible_completions_output_node = temp;
+ }
+
+ /* Find a suitable window for displaying the completions output.
+ First choice is an existing window showing completions output.
+ If there is only one window, and it is large, make another
+ (smaller) window, and use that one. Otherwise, use the caller's
+ window. */
+ {
+ WINDOW *compwin;
+
+ compwin = get_internal_info_window (compwin_name);
+
+ if (!compwin)
+ {
+ /* If we can split the window to display most of the completion
+ items, then do so. */
+ if (calling_window->height > (count * 2))
+ {
+ int start, end, pagetop;
+
+ active_window = calling_window;
+
+ /* Perhaps we can scroll this window on redisplay. */
+ start = calling_window->first_row;
+ pagetop = calling_window->pagetop;
+
+ compwin =
+ window_make_window (possible_completions_output_node);
+ active_window = the_echo_area;
+ window_change_window_height
+ (compwin, -(compwin->height - (count + 2)));
+
+ window_adjust_pagetop (calling_window);
+ remember_calling_window (calling_window);
+
+#if defined (SPLIT_BEFORE_ACTIVE)
+ /* If the pagetop hasn't changed, scrolling the calling
+ window is a reasonable thing to do. */
+ if (pagetop == calling_window->pagetop)
+ {
+ end = start + calling_window->height;
+ display_scroll_display
+ (start, end, calling_window->prev->height + 1);
+ }
+#else /* !SPLIT_BEFORE_ACTIVE */
+ /* If the pagetop has changed, set the new pagetop here. */
+ if (pagetop != calling_window->pagetop)
+ {
+ int newtop = calling_window->pagetop;
+ calling_window->pagetop = pagetop;
+ set_window_pagetop (calling_window, newtop);
+ }
+#endif /* !SPLIT_BEFORE_ACTIVE */
+
+ echo_area_completions_window = compwin;
+ remember_window_and_node (compwin, compwin->node);
+ }
+ else
+ compwin = calling_window;
+ }
+
+ if (compwin->node != possible_completions_output_node)
+ {
+ window_set_node_of_window
+ (compwin, possible_completions_output_node);
+ remember_window_and_node (compwin, compwin->node);
+ }
+
+ display_update_display (windows);
+ }
+ }
+}
+
+DECLARE_INFO_COMMAND (ea_complete, "Insert completion")
+{
+ if (!echo_area_completion_items)
+ {
+ ea_insert (window, count, key);
+ return;
+ }
+
+ /* If KEY is SPC, and we are not forcing completion to take place, simply
+ insert the key. */
+ if (!echo_area_must_complete_p && key == SPC)
+ {
+ ea_insert (window, count, key);
+ return;
+ }
+
+ if (ea_last_executed_command == ea_complete)
+ {
+ /* If the keypress is a SPC character, and we have already tried
+ completing once, and there are several completions, then check
+ the batch of completions to see if any continue with a space.
+ If there are some, insert the space character and continue. */
+ if (key == SPC && completions_found_index > 1)
+ {
+ register int i, offset;
+
+ offset = input_line_end - input_line_beg;
+
+ for (i = 0; i < completions_found_index; i++)
+ if (completions_found[i]->label[offset] == ' ')
+ break;
+
+ if (completions_found[i])
+ ea_insert (window, 1, ' ');
+ else
+ {
+ ea_possible_completions (window, count, key);
+ return;
+ }
+ }
+ else
+ {
+ ea_possible_completions (window, count, key);
+ return;
+ }
+ }
+
+ input_line_point = input_line_end;
+ build_completions ();
+
+ if (!completions_found_index)
+ terminal_ring_bell ();
+ else if (LCD_completion->label[0] == '\0')
+ ea_possible_completions (window, count, key);
+ else
+ {
+ register int i;
+ input_line_point = input_line_end = input_line_beg;
+ for (i = 0; LCD_completion->label[i]; i++)
+ ea_insert (window, 1, LCD_completion->label[i]);
+ }
+}
+
+/* Utility REFERENCE used to store possible LCD. */
+static REFERENCE LCD_reference = { (char *)NULL, (char *)NULL, (char *)NULL };
+
+static void remove_completion_duplicates ();
+
+/* Variables which remember the state of the most recent call
+ to build_completions (). */
+static char *last_completion_request = (char *)NULL;
+static REFERENCE **last_completion_items = (REFERENCE **)NULL;
+
+/* How to tell the completion builder to reset internal state. */
+static void
+completions_must_be_rebuilt ()
+{
+ maybe_free (last_completion_request);
+ last_completion_request = (char *)NULL;
+ last_completion_items = (REFERENCE **)NULL;
+}
+
+/* Build a list of possible completions from echo_area_completion_items,
+ and the contents of input_line. */
+static void
+build_completions ()
+{
+ register int i, len;
+ register REFERENCE *entry;
+ char *request;
+ int informed_of_lengthy_job = 0;
+
+ /* If there are no items to complete over, exit immediately. */
+ if (!echo_area_completion_items)
+ {
+ completions_found_index = 0;
+ LCD_completion = (REFERENCE *)NULL;
+ return;
+ }
+
+ /* Check to see if this call to build completions is the same as the last
+ call to build completions. */
+ len = input_line_end - input_line_beg;
+ request = (char *)xmalloc (1 + len);
+ strncpy (request, &input_line[input_line_beg], len);
+ request[len] = '\0';
+
+ if (last_completion_request && last_completion_items &&
+ last_completion_items == echo_area_completion_items &&
+ (strcmp (last_completion_request, request) == 0))
+ {
+ free (request);
+ return;
+ }
+
+ maybe_free (last_completion_request);
+ last_completion_request = request;
+ last_completion_items = echo_area_completion_items;
+
+ /* Always start at the beginning of the list. */
+ completions_found_index = 0;
+ LCD_completion = (REFERENCE *)NULL;
+
+ for (i = 0; entry = echo_area_completion_items[i]; i++)
+ {
+ if (strncasecmp (request, entry->label, len) == 0)
+ add_pointer_to_array (entry, completions_found_index,
+ completions_found, completions_found_slots,
+ 20, REFERENCE *);
+
+ if (!informed_of_lengthy_job && completions_found_index > 100)
+ {
+ informed_of_lengthy_job = 1;
+ window_message_in_echo_area ("Building completions...");
+ }
+ }
+
+ if (!completions_found_index)
+ return;
+
+ /* Sort and prune duplicate entries from the completions array. */
+ remove_completion_duplicates ();
+
+ /* If there is only one completion, just return that. */
+ if (completions_found_index == 1)
+ {
+ LCD_completion = completions_found[0];
+ return;
+ }
+
+ /* Find the least common denominator. */
+ {
+ long shortest = 100000;
+
+ for (i = 1; i < completions_found_index; i++)
+ {
+ register int j;
+ int c1, c2;
+
+ for (j = 0;
+ (c1 = info_tolower (completions_found[i - 1]->label[j])) &&
+ (c2 = info_tolower (completions_found[i]->label[j]));
+ j++)
+ if (c1 != c2)
+ break;
+
+ if (shortest > j)
+ shortest = j;
+ }
+
+ maybe_free (LCD_reference.label);
+ LCD_reference.label = (char *)xmalloc (1 + shortest);
+ strncpy (LCD_reference.label, completions_found[0]->label, shortest);
+ LCD_reference.label[shortest] = '\0';
+ LCD_completion = &LCD_reference;
+ }
+
+ if (informed_of_lengthy_job)
+ echo_area_initialize_node ();
+}
+
+/* Function called by qsort. */
+static int
+compare_references (entry1, entry2)
+ REFERENCE **entry1, **entry2;
+{
+ return (strcasecmp ((*entry1)->label, (*entry2)->label));
+}
+
+/* Prune duplicate entries from COMPLETIONS_FOUND. */
+static void
+remove_completion_duplicates ()
+{
+ register int i, j;
+ REFERENCE **temp;
+ int newlen;
+
+ if (!completions_found_index)
+ return;
+
+ /* Sort the items. */
+ qsort (completions_found, completions_found_index, sizeof (REFERENCE *),
+ compare_references);
+
+ for (i = 0, newlen = 1; i < completions_found_index - 1; i++)
+ {
+ if (strcmp (completions_found[i]->label,
+ completions_found[i + 1]->label) == 0)
+ completions_found[i] = (REFERENCE *)NULL;
+ else
+ newlen++;
+ }
+
+ /* We have marked all the dead slots. It is faster to copy the live slots
+ twice than to prune the dead slots one by one. */
+ temp = (REFERENCE **)xmalloc ((1 + newlen) * sizeof (REFERENCE *));
+ for (i = 0, j = 0; i < completions_found_index; i++)
+ if (completions_found[i])
+ temp[j++] = completions_found[i];
+
+ for (i = 0; i < newlen; i++)
+ completions_found[i] = temp[i];
+
+ completions_found[i] = (REFERENCE *)NULL;
+ completions_found_index = newlen;
+ free (temp);
+}
+
+/* Scroll the "other" window. If there is a window showing completions, scroll
+ that one, otherwise scroll the window which was active on entering the read
+ function. */
+DECLARE_INFO_COMMAND (ea_scroll_completions_window, "Scroll the completions window")
+{
+ WINDOW *compwin;
+ int old_pagetop;
+
+ compwin = get_internal_info_window (compwin_name);
+
+ if (!compwin)
+ compwin = calling_window;
+
+ old_pagetop = compwin->pagetop;
+
+ /* Let info_scroll_forward () do the work, and print any messages that
+ need to be displayed. */
+ info_scroll_forward (compwin, count, key);
+}
+
+/* Function which gets called when an Info window is deleted while the
+ echo area is active. WINDOW is the window which has just been deleted. */
+void
+echo_area_inform_of_deleted_window (window)
+ WINDOW *window;
+{
+ /* If this is the calling_window, forget what we remembered about it. */
+ if (window == calling_window)
+ {
+ if (active_window != the_echo_area)
+ remember_calling_window (active_window);
+ else
+ remember_calling_window (windows);
+ }
+
+ /* If this window was the echo_area_completions_window, then notice that
+ the window has been deleted. */
+ if (window == echo_area_completions_window)
+ echo_area_completions_window = (WINDOW *)NULL;
+}
+
+/* **************************************************************** */
+/* */
+/* Pushing and Popping the Echo Area */
+/* */
+/* **************************************************************** */
+
+/* Push and Pop the echo area. */
+typedef struct {
+ char *line;
+ char *prompt;
+ REFERENCE **comp_items;
+ int point, beg, end;
+ int must_complete;
+ NODE node;
+ WINDOW *compwin;
+} PUSHED_EA;
+
+static PUSHED_EA **pushed_echo_areas = (PUSHED_EA **)NULL;
+static int pushed_echo_areas_index = 0;
+static int pushed_echo_areas_slots = 0;
+
+/* Pushing the echo_area has a side effect of zeroing the completion_items. */
+static void
+push_echo_area ()
+{
+ PUSHED_EA *pushed;
+
+ pushed = (PUSHED_EA *)xmalloc (sizeof (PUSHED_EA));
+ pushed->line = strdup (input_line);
+ pushed->prompt = input_line_prompt;
+ pushed->point = input_line_point;
+ pushed->beg = input_line_beg;
+ pushed->end = input_line_end;
+ pushed->node = input_line_node;
+ pushed->comp_items = echo_area_completion_items;
+ pushed->must_complete = echo_area_must_complete_p;
+ pushed->compwin = echo_area_completions_window;
+
+ add_pointer_to_array (pushed, pushed_echo_areas_index, pushed_echo_areas,
+ pushed_echo_areas_slots, 4, PUSHED_EA *);
+
+ echo_area_completion_items = (REFERENCE **)NULL;
+}
+
+static void
+pop_echo_area ()
+{
+ PUSHED_EA *popped;
+
+ popped = pushed_echo_areas[--pushed_echo_areas_index];
+
+ strcpy (input_line, popped->line);
+ free (popped->line);
+ input_line_prompt = popped->prompt;
+ input_line_point = popped->point;
+ input_line_beg = popped->beg;
+ input_line_end = popped->end;
+ input_line_node = popped->node;
+ echo_area_completion_items = popped->comp_items;
+ echo_area_must_complete_p = popped->must_complete;
+ echo_area_completions_window = popped->compwin;
+ completions_must_be_rebuilt ();
+
+ /* If the completion window no longer exists, forget about it. */
+ if (echo_area_completions_window)
+ {
+ register WINDOW *win;
+
+ for (win = windows; win; win = win->next)
+ if (echo_area_completions_window == win)
+ break;
+
+ /* If the window wasn't found, then it has already been deleted. */
+ if (!win)
+ echo_area_completions_window = (WINDOW *)NULL;
+ }
+
+ free (popped);
+}
+
+static int
+echo_area_stack_depth ()
+{
+ return (pushed_echo_areas_index);
+}
+
+/* Returns non-zero if any of the prior stacked calls to read in the echo
+ area produced a completions window. */
+static int
+echo_area_stack_contains_completions_p ()
+{
+ register int i;
+
+ for (i = 0; i < pushed_echo_areas_index; i++)
+ if (pushed_echo_areas[i]->compwin)
+ return (1);
+
+ return (0);
+}
+
+/* **************************************************************** */
+/* */
+/* Error Messages While Reading in Echo Area */
+/* */
+/* **************************************************************** */
+
+#if defined (HAVE_SYS_TIME_H)
+# include <sys/time.h>
+# define HAVE_STRUCT_TIMEVAL
+#endif /* HAVE_SYS_TIME_H */
+
+static void
+pause_or_input ()
+{
+#if defined (FD_SET)
+ struct timeval timer;
+ fd_set readfds;
+ int ready;
+
+ FD_ZERO (&readfds);
+ FD_SET (fileno (stdin), &readfds);
+ timer.tv_sec = 2;
+ timer.tv_usec = 750;
+ ready = select (1, &readfds, (fd_set *)NULL, (fd_set *)NULL, &timer);
+#endif /* FD_SET */
+}
+
+/* Print MESSAGE right after the end of the current line, and wait
+ for input or 2.75 seconds, whichever comes first. Then flush the
+ informational message that was printed. */
+void
+inform_in_echo_area (message)
+ char *message;
+{
+ register int i;
+ char *text;
+
+ text = strdup (message);
+ for (i = 0; text[i] && text[i] != '\n'; i++);
+ text[i] = '\0';
+
+ echo_area_initialize_node ();
+ sprintf (&input_line[input_line_end], "%s[%s]\n",
+ echo_area_is_active ? " ": "", text);
+ free (text);
+ the_echo_area->point = input_line_point;
+ display_update_one_window (the_echo_area);
+ display_cursor_at_point (active_window);
+ fflush (stdout);
+ pause_or_input ();
+ echo_area_initialize_node ();
+}
diff --git a/contrib/texinfo/info/echo_area.h b/contrib/texinfo/info/echo_area.h
new file mode 100644
index 0000000..09c2bc7
--- /dev/null
+++ b/contrib/texinfo/info/echo_area.h
@@ -0,0 +1,63 @@
+/* echo_area.h -- Functions used in reading information from the echo area. */
+
+/* This file is part of GNU Info, a program for reading online documentation
+ stored in Info format.
+
+ Copyright (C) 1993 Free Software Foundation, Inc.
+
+ 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Written by Brian Fox (bfox@ai.mit.edu). */
+
+#if !defined (_ECHO_AREA_H_)
+#define _ECHO_AREA_H_
+
+#define EA_MAX_INPUT 256
+
+extern int echo_area_is_active, info_aborted_echo_area;
+
+/* Non-zero means that the last command executed while reading input
+ killed some text. */
+extern int echo_area_last_command_was_kill;
+
+extern void inform_in_echo_area (), echo_area_inform_of_deleted_window ();
+extern void echo_area_prep_read ();
+extern VFunction *ea_last_executed_command;
+
+/* Read a line of text in the echo area. Return a malloc ()'ed string,
+ or NULL if the user aborted out of this read. WINDOW is the currently
+ active window, so that we can restore it when we need to. PROMPT, if
+ non-null, is a prompt to print before reading the line. */
+extern char *info_read_in_echo_area ();
+
+/* Read a line in the echo area with completion over COMPLETIONS.
+ Takes arguments of WINDOW, PROMPT, and COMPLETIONS, a REFERENCE **. */
+char *info_read_completing_in_echo_area ();
+
+/* Read a line in the echo area allowing completion over COMPLETIONS, but
+ not requiring it. Takes arguments of WINDOW, PROMPT, and COMPLETIONS,
+ a REFERENCE **. */
+extern char *info_read_maybe_completing ();
+
+extern void ea_insert (), ea_quoted_insert ();
+extern void ea_beg_of_line (), ea_backward (), ea_delete (), ea_end_of_line ();
+extern void ea_forward (), ea_abort (), ea_rubout (), ea_complete ();
+extern void ea_newline (), ea_kill_line (), ea_transpose_chars ();
+extern void ea_yank (), ea_tab_insert (), ea_possible_completions ();
+extern void ea_backward_word (), ea_kill_word (), ea_forward_word ();
+extern void ea_yank_pop (), ea_backward_kill_word ();
+extern void ea_scroll_completions_window ();
+
+#endif /* _ECHO_AREA_H_ */
diff --git a/contrib/texinfo/info/filesys.c b/contrib/texinfo/info/filesys.c
new file mode 100644
index 0000000..e684bf8
--- /dev/null
+++ b/contrib/texinfo/info/filesys.c
@@ -0,0 +1,617 @@
+/* filesys.c -- File system specific functions for hacking this system. */
+
+/* This file is part of GNU Info, a program for reading online documentation
+ stored in Info format.
+
+ Copyright (C) 1993 Free Software Foundation, Inc.
+
+ 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Written by Brian Fox (bfox@ai.mit.edu). */
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#if defined (HAVE_SYS_FILE_H)
+#include <sys/file.h>
+#endif /* HAVE_SYS_FILE_H */
+#include <sys/errno.h>
+#include "general.h"
+#include "tilde.h"
+#include "filesys.h"
+
+#if !defined (O_RDONLY)
+#if defined (HAVE_SYS_FCNTL_H)
+#include <sys/fcntl.h>
+#else /* !HAVE_SYS_FCNTL_H */
+#include <fcntl.h>
+#endif /* !HAVE_SYS_FCNTL_H */
+#endif /* !O_RDONLY */
+
+#if !defined (errno)
+extern int errno;
+#endif /* !errno */
+
+/* Found in info-utils.c. */
+extern char *filename_non_directory ();
+
+#if !defined (BUILDING_LIBRARY)
+/* Found in session.c */
+extern int info_windows_initialized_p;
+
+/* Found in window.c. */
+extern void message_in_echo_area (), unmessage_in_echo_area ();
+#endif /* !BUILDING_LIBRARY */
+
+/* Local to this file. */
+static char *info_file_in_path (), *lookup_info_filename ();
+static void remember_info_filename (), maybe_initialize_infopath ();
+
+#if !defined (NULL)
+# define NULL 0x0
+#endif /* !NULL */
+
+typedef struct {
+ char *suffix;
+ char *decompressor;
+} COMPRESSION_ALIST;
+
+static char *info_suffixes[] = {
+ "",
+ ".info",
+ "-info",
+ (char *)NULL
+};
+
+static COMPRESSION_ALIST compress_suffixes[] = {
+ { ".Z", "uncompress" },
+ { ".Y", "unyabba" },
+ { ".z", "gunzip" },
+ { ".gz", "gunzip" },
+ { (char *)NULL, (char *)NULL }
+};
+
+/* The path on which we look for info files. You can initialize this
+ from the environment variable INFOPATH if there is one, or you can
+ call info_add_path () to add paths to the beginning or end of it.
+ You can call zap_infopath () to make the path go away. */
+char *infopath = (char *)NULL;
+static int infopath_size = 0;
+
+/* Expand the filename in PARTIAL to make a real name for this operating
+ system. This looks in INFO_PATHS in order to find the correct file.
+ If it can't find the file, it returns NULL. */
+static char *local_temp_filename = (char *)NULL;
+static int local_temp_filename_size = 0;
+
+char *
+info_find_fullpath (partial)
+ char *partial;
+{
+ int initial_character;
+ char *temp;
+
+ filesys_error_number = 0;
+
+ maybe_initialize_infopath ();
+
+ if (partial && (initial_character = *partial))
+ {
+ char *expansion;
+
+ expansion = lookup_info_filename (partial);
+
+ if (expansion)
+ return (expansion);
+
+ /* If we have the full path to this file, we still may have to add
+ various extensions to it. I guess we have to stat this file
+ after all. */
+ if (initial_character == '/')
+ temp = info_file_in_path (partial + 1, "/");
+ else if (initial_character == '~')
+ {
+ expansion = tilde_expand_word (partial);
+ if (*expansion == '/')
+ {
+ temp = info_file_in_path (expansion + 1, "/");
+ free (expansion);
+ }
+ else
+ temp = expansion;
+ }
+ else if (initial_character == '.' &&
+ (partial[1] == '/' || (partial[1] == '.' && partial[2] == '/')))
+ {
+ if (local_temp_filename_size < 1024)
+ local_temp_filename = (char *)xrealloc
+ (local_temp_filename, (local_temp_filename_size = 1024));
+#if defined (HAVE_GETCWD)
+ if (!getcwd (local_temp_filename, local_temp_filename_size))
+#else /* !HAVE_GETCWD */
+ if (!getwd (local_temp_filename))
+#endif /* !HAVE_GETCWD */
+ {
+ filesys_error_number = errno;
+ return (partial);
+ }
+
+ strcat (local_temp_filename, "/");
+ strcat (local_temp_filename, partial);
+ return (local_temp_filename);
+ }
+ else
+ temp = info_file_in_path (partial, infopath);
+
+ if (temp)
+ {
+ remember_info_filename (partial, temp);
+ if (strlen (temp) > local_temp_filename_size)
+ local_temp_filename = (char *) xrealloc
+ (local_temp_filename,
+ (local_temp_filename_size = (50 + strlen (temp))));
+ strcpy (local_temp_filename, temp);
+ free (temp);
+ return (local_temp_filename);
+ }
+ }
+ return (partial);
+}
+
+/* Scan the list of directories in PATH looking for FILENAME. If we find
+ one that is a regular file, return it as a new string. Otherwise, return
+ a NULL pointer. */
+static char *
+info_file_in_path (filename, path)
+ char *filename, *path;
+{
+ struct stat finfo;
+ char *temp_dirname;
+ int statable, dirname_index;
+
+ dirname_index = 0;
+
+ while (temp_dirname = extract_colon_unit (path, &dirname_index))
+ {
+ register int i, pre_suffix_length;
+ char *temp;
+
+ /* Expand a leading tilde if one is present. */
+ if (*temp_dirname == '~')
+ {
+ char *expanded_dirname;
+
+ expanded_dirname = tilde_expand_word (temp_dirname);
+ free (temp_dirname);
+ temp_dirname = expanded_dirname;
+ }
+
+ temp = (char *)xmalloc (30 + strlen (temp_dirname) + strlen (filename));
+ strcpy (temp, temp_dirname);
+ if (temp[(strlen (temp)) - 1] != '/')
+ strcat (temp, "/");
+ strcat (temp, filename);
+
+ pre_suffix_length = strlen (temp);
+
+ free (temp_dirname);
+
+ for (i = 0; info_suffixes[i]; i++)
+ {
+ strcpy (temp + pre_suffix_length, info_suffixes[i]);
+
+ statable = (stat (temp, &finfo) == 0);
+
+ /* If we have found a regular file, then use that. Else, if we
+ have found a directory, look in that directory for this file. */
+ if (statable)
+ {
+ if (S_ISREG (finfo.st_mode))
+ {
+ return (temp);
+ }
+ else if (S_ISDIR (finfo.st_mode))
+ {
+ char *newpath, *filename_only, *newtemp;
+
+ newpath = strdup (temp);
+ filename_only = filename_non_directory (filename);
+ newtemp = info_file_in_path (filename_only, newpath);
+
+ free (newpath);
+ if (newtemp)
+ {
+ free (temp);
+ return (newtemp);
+ }
+ }
+ }
+ else
+ {
+ /* Add various compression suffixes to the name to see if
+ the file is present in compressed format. */
+ register int j, pre_compress_suffix_length;
+
+ pre_compress_suffix_length = strlen (temp);
+
+ for (j = 0; compress_suffixes[j].suffix; j++)
+ {
+ strcpy (temp + pre_compress_suffix_length,
+ compress_suffixes[j].suffix);
+
+ statable = (stat (temp, &finfo) == 0);
+ if (statable && (S_ISREG (finfo.st_mode)))
+ return (temp);
+ }
+ }
+ }
+ free (temp);
+ }
+ return ((char *)NULL);
+}
+
+/* Given a string containing units of information separated by colons,
+ return the next one pointed to by IDX, or NULL if there are no more.
+ Advance IDX to the character after the colon. */
+char *
+extract_colon_unit (string, idx)
+ char *string;
+ int *idx;
+{
+ register int i, start;
+
+ i = start = *idx;
+ if ((i >= strlen (string)) || !string)
+ return ((char *) NULL);
+
+ while (string[i] && string[i] != ':')
+ i++;
+ if (i == start)
+ {
+ return ((char *) NULL);
+ }
+ else
+ {
+ char *value;
+
+ value = (char *) xmalloc (1 + (i - start));
+ strncpy (value, &string[start], (i - start));
+ value[i - start] = '\0';
+ if (string[i])
+ ++i;
+ *idx = i;
+ return (value);
+ }
+}
+
+/* A structure which associates a filename with its expansion. */
+typedef struct {
+ char *filename;
+ char *expansion;
+} FILENAME_LIST;
+
+/* An array of remembered arguments and results. */
+static FILENAME_LIST **names_and_files = (FILENAME_LIST **)NULL;
+static int names_and_files_index = 0;
+static int names_and_files_slots = 0;
+
+/* Find the result for having already called info_find_fullpath () with
+ FILENAME. */
+static char *
+lookup_info_filename (filename)
+ char *filename;
+{
+ if (filename && names_and_files)
+ {
+ register int i;
+ for (i = 0; names_and_files[i]; i++)
+ {
+ if (strcmp (names_and_files[i]->filename, filename) == 0)
+ return (names_and_files[i]->expansion);
+ }
+ }
+ return (char *)NULL;;
+}
+
+/* Add a filename and its expansion to our list. */
+static void
+remember_info_filename (filename, expansion)
+ char *filename, *expansion;
+{
+ FILENAME_LIST *new;
+
+ if (names_and_files_index + 2 > names_and_files_slots)
+ {
+ int alloc_size;
+ names_and_files_slots += 10;
+
+ alloc_size = names_and_files_slots * sizeof (FILENAME_LIST *);
+
+ names_and_files =
+ (FILENAME_LIST **) xrealloc (names_and_files, alloc_size);
+ }
+
+ new = (FILENAME_LIST *)xmalloc (sizeof (FILENAME_LIST));
+ new->filename = strdup (filename);
+ new->expansion = expansion ? strdup (expansion) : (char *)NULL;
+
+ names_and_files[names_and_files_index++] = new;
+ names_and_files[names_and_files_index] = (FILENAME_LIST *)NULL;
+}
+
+static void
+maybe_initialize_infopath ()
+{
+ if (!infopath_size)
+ {
+ infopath = (char *)
+ xmalloc (infopath_size = (1 + strlen (DEFAULT_INFOPATH)));
+
+ strcpy (infopath, DEFAULT_INFOPATH);
+ }
+}
+
+/* Add PATH to the list of paths found in INFOPATH. 2nd argument says
+ whether to put PATH at the front or end of INFOPATH. */
+void
+info_add_path (path, where)
+ char *path;
+ int where;
+{
+ int len;
+
+ if (!infopath)
+ {
+ infopath = (char *)xmalloc (infopath_size = 200 + strlen (path));
+ infopath[0] = '\0';
+ }
+
+ len = strlen (path) + strlen (infopath);
+
+ if (len + 2 >= infopath_size)
+ infopath = (char *)xrealloc (infopath, (infopath_size += (2 * len) + 2));
+
+ if (!*infopath)
+ strcpy (infopath, path);
+ else if (where == INFOPATH_APPEND)
+ {
+ strcat (infopath, ":");
+ strcat (infopath, path);
+ }
+ else if (where == INFOPATH_PREPEND)
+ {
+ char *temp = strdup (infopath);
+ strcpy (infopath, path);
+ strcat (infopath, ":");
+ strcat (infopath, temp);
+ free (temp);
+ }
+}
+
+/* Make INFOPATH have absolutely nothing in it. */
+void
+zap_infopath ()
+{
+ if (infopath)
+ free (infopath);
+
+ infopath = (char *)NULL;
+ infopath_size = 0;
+}
+
+/* Read the contents of PATHNAME, returning a buffer with the contents of
+ that file in it, and returning the size of that buffer in FILESIZE.
+ FINFO is a stat struct which has already been filled in by the caller.
+ If the file cannot be read, return a NULL pointer. */
+char *
+filesys_read_info_file (pathname, filesize, finfo)
+ char *pathname;
+ long *filesize;
+ struct stat *finfo;
+{
+ long st_size;
+
+ *filesize = filesys_error_number = 0;
+
+ if (compressed_filename_p (pathname))
+ return (filesys_read_compressed (pathname, filesize, finfo));
+ else
+ {
+ int descriptor;
+ char *contents;
+
+ descriptor = open (pathname, O_RDONLY, 0666);
+
+ /* If the file couldn't be opened, give up. */
+ if (descriptor < 0)
+ {
+ filesys_error_number = errno;
+ return ((char *)NULL);
+ }
+
+ /* Try to read the contents of this file. */
+ st_size = (long) finfo->st_size;
+ contents = (char *)xmalloc (1 + st_size);
+ if ((read (descriptor, contents, st_size)) != st_size)
+ {
+ filesys_error_number = errno;
+ close (descriptor);
+ free (contents);
+ return ((char *)NULL);
+ }
+
+ close (descriptor);
+
+ *filesize = st_size;
+ return (contents);
+ }
+}
+
+/* Typically, pipe buffers are 4k. */
+#define BASIC_PIPE_BUFFER (4 * 1024)
+
+/* We use some large multiple of that. */
+#define FILESYS_PIPE_BUFFER_SIZE (16 * BASIC_PIPE_BUFFER)
+
+char *
+filesys_read_compressed (pathname, filesize, finfo)
+ char *pathname;
+ long *filesize;
+ struct stat *finfo;
+{
+ FILE *stream;
+ char *command, *decompressor;
+ char *contents = (char *)NULL;
+
+ *filesize = filesys_error_number = 0;
+
+ decompressor = filesys_decompressor_for_file (pathname);
+
+ if (!decompressor)
+ return ((char *)NULL);
+
+ command = (char *)xmalloc (10 + strlen (pathname) + strlen (decompressor));
+ sprintf (command, "%s < %s", decompressor, pathname);
+
+#if !defined (BUILDING_LIBRARY)
+ if (info_windows_initialized_p)
+ {
+ char *temp;
+
+ temp = (char *)xmalloc (5 + strlen (command));
+ sprintf (temp, "%s...", command);
+ message_in_echo_area ("%s", temp);
+ free (temp);
+ }
+#endif /* !BUILDING_LIBRARY */
+
+ stream = popen (command, "r");
+ free (command);
+
+ /* Read chunks from this file until there are none left to read. */
+ if (stream)
+ {
+ int offset, size;
+ char *chunk;
+
+ offset = size = 0;
+ chunk = (char *)xmalloc (FILESYS_PIPE_BUFFER_SIZE);
+
+ while (1)
+ {
+ int bytes_read;
+
+ bytes_read = fread (chunk, 1, FILESYS_PIPE_BUFFER_SIZE, stream);
+
+ if (bytes_read + offset >= size)
+ contents = (char *)xrealloc
+ (contents, size += (2 * FILESYS_PIPE_BUFFER_SIZE));
+
+ memcpy (contents + offset, chunk, bytes_read);
+ offset += bytes_read;
+ if (bytes_read != FILESYS_PIPE_BUFFER_SIZE)
+ break;
+ }
+
+ free (chunk);
+ pclose (stream);
+ contents = (char *)xrealloc (contents, offset + 1);
+ *filesize = offset;
+ }
+ else
+ {
+ filesys_error_number = errno;
+ }
+
+#if !defined (BUILDING_LIBARARY)
+ if (info_windows_initialized_p)
+ unmessage_in_echo_area ();
+#endif /* !BUILDING_LIBRARY */
+ return (contents);
+}
+
+/* Return non-zero if FILENAME belongs to a compressed file. */
+int
+compressed_filename_p (filename)
+ char *filename;
+{
+ char *decompressor;
+
+ /* Find the final extension of this filename, and see if it matches one
+ of our known ones. */
+ decompressor = filesys_decompressor_for_file (filename);
+
+ if (decompressor)
+ return (1);
+ else
+ return (0);
+}
+
+/* Return the command string that would be used to decompress FILENAME. */
+char *
+filesys_decompressor_for_file (filename)
+ char *filename;
+{
+ register int i;
+ char *extension = (char *)NULL;
+
+ /* Find the final extension of FILENAME, and see if it appears in our
+ list of known compression extensions. */
+ for (i = strlen (filename) - 1; i > 0; i--)
+ if (filename[i] == '.')
+ {
+ extension = filename + i;
+ break;
+ }
+
+ if (!extension)
+ return ((char *)NULL);
+
+ for (i = 0; compress_suffixes[i].suffix; i++)
+ if (strcmp (extension, compress_suffixes[i].suffix) == 0)
+ return (compress_suffixes[i].decompressor);
+
+ return ((char *)NULL);
+}
+
+/* The number of the most recent file system error. */
+int filesys_error_number = 0;
+
+/* A function which returns a pointer to a static buffer containing
+ an error message for FILENAME and ERROR_NUM. */
+static char *errmsg_buf = (char *)NULL;
+static int errmsg_buf_size = 0;
+
+char *
+filesys_error_string (filename, error_num)
+ char *filename;
+ int error_num;
+{
+ int len;
+ char *result;
+
+ if (error_num == 0)
+ return ((char *)NULL);
+
+ result = strerror (error_num);
+
+ len = 4 + strlen (filename) + strlen (result);
+ if (len >= errmsg_buf_size)
+ errmsg_buf = (char *)xrealloc (errmsg_buf, (errmsg_buf_size = 2 + len));
+
+ sprintf (errmsg_buf, "%s: %s", filename, result);
+ return (errmsg_buf);
+}
+
diff --git a/contrib/texinfo/info/filesys.h b/contrib/texinfo/info/filesys.h
new file mode 100644
index 0000000..130a52a
--- /dev/null
+++ b/contrib/texinfo/info/filesys.h
@@ -0,0 +1,84 @@
+/* filesys.h -- External declarations of functions and vars in filesys.c. */
+
+/* This file is part of GNU Info, a program for reading online documentation
+ stored in Info format.
+
+ Copyright (C) 1993 Free Software Foundation, Inc.
+
+ 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Written by Brian Fox (bfox@ai.mit.edu). */
+
+#if !defined (_FILESYS_H_)
+#define _FILESYS_H_
+
+/* The path on which we look for info files. You can initialize this
+ from the environment variable INFOPATH if there is one, or you can
+ call info_add_path () to add paths to the beginning or end of it. */
+extern char *infopath;
+
+/* Make INFOPATH have absolutely nothing in it. */
+extern void zap_infopath ();
+
+/* Add PATH to the list of paths found in INFOPATH. 2nd argument says
+ whether to put PATH at the front or end of INFOPATH. */
+extern void info_add_path ();
+
+/* Defines that are passed along with the pathname to info_add_path (). */
+#define INFOPATH_PREPEND 0
+#define INFOPATH_APPEND 1
+
+/* Expand the filename in PARTIAL to make a real name for this operating
+ system. This looks in INFO_PATHS in order to find the correct file.
+ If it can't find the file, it returns NULL. */
+extern char *info_find_fullpath ();
+
+/* Read the contents of PATHNAME, returning a buffer with the contents of
+ that file in it, and returning the size of that buffer in FILESIZE.
+ FINFO is a stat struct which has already been filled in by the caller.
+ If the file cannot be read, return a NULL pointer. */
+extern char *filesys_read_info_file ();
+extern char *filesys_read_compressed ();
+
+/* Return the command string that would be used to decompress FILENAME. */
+extern char *filesys_decompressor_for_file ();
+extern int compressed_filename_p ();
+
+/* A function which returns a pointer to a static buffer containing
+ an error message for FILENAME and ERROR_NUM. */
+extern char *filesys_error_string ();
+
+/* The number of the most recent file system error. */
+extern int filesys_error_number;
+
+/* Given a string containing units of information separated by colons,
+ return the next one pointed to by IDX, or NULL if there are no more.
+ Advance IDX to the character after the colon. */
+extern char *extract_colon_unit ();
+
+/* The default value of INFOPATH. */
+#if !defined (DEFAULT_INFOPATH)
+! # define DEFAULT_INFOPATH "/usr/local/info:/usr/info:/usr/local/lib/info:/usr/lib/info:/usr/local/gnu/info:/usr/local/gnu/lib/info:/usr/gnu/info:/usr/gnu/lib/info:/opt/gnu/info:/usr/share/info:/usr/share/lib/info:/usr/local/share/info:/usr/local/share/lib/info:/usr/gnu/lib/emacs/info:/usr/local/gnu/lib/emacs/info:/usr/local/lib/emacs/info:/usr/local/emacs/info:."
+#endif /* !DEFAULT_INFOPATH */
+
+#if !defined (S_ISREG) && defined (S_IFREG)
+# define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
+#endif /* !S_ISREG && S_IFREG */
+
+#if !defined (S_ISDIR) && defined (S_IFDIR)
+# define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
+#endif /* !S_ISDIR && S_IFDIR */
+
+#endif /* !_FILESYS_H_ */
diff --git a/contrib/texinfo/info/footnotes.c b/contrib/texinfo/info/footnotes.c
new file mode 100644
index 0000000..35a0f35
--- /dev/null
+++ b/contrib/texinfo/info/footnotes.c
@@ -0,0 +1,265 @@
+/* footnotes.c -- Some functions for manipulating footnotes. */
+
+/* This file is part of GNU Info, a program for reading online documentation
+ stored in Info format.
+
+ Copyright (C) 1993 Free Software Foundation, Inc.
+
+ 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Written by Brian Fox (bfox@ai.mit.edu). */
+
+#include "info.h"
+
+/* Non-zero means attempt to show footnotes when displaying a new window. */
+int auto_footnotes_p = 1;
+
+static char *footnote_nodename = "*Footnotes*";
+
+#define FOOTNOTE_HEADER_FORMAT \
+ "*** Footnotes appearing in the node \"%s\" ***\n"
+
+/* Find the window currently showing footnotes. */
+static WINDOW *
+find_footnotes_window ()
+{
+ WINDOW *win;
+
+ /* Try to find an existing window first. */
+ for (win = windows; win; win = win->next)
+ if (internal_info_node_p (win->node) &&
+ (strcmp (win->node->nodename, footnote_nodename) == 0))
+ break;
+
+ return (win);
+}
+
+/* Manufacture a node containing the footnotes of this node, and
+ return the manufactured node. If NODE has no footnotes, return a
+ NULL pointer. */
+NODE *
+make_footnotes_node (node)
+ NODE *node;
+{
+ NODE *fn_node, *result = (NODE *)NULL;
+ long fn_start;
+
+ /* Make the initial assumption that the footnotes appear as simple
+ text within this windows node. */
+ fn_node = node;
+
+ /* See if this node contains the magic footnote label. */
+ fn_start =
+ info_search_in_node (FOOTNOTE_LABEL, node, 0, (WINDOW *)NULL, 1);
+
+ /* If it doesn't, check to see if it has an associated footnotes node. */
+ if (fn_start == -1)
+ {
+ REFERENCE **refs;
+
+ refs = info_xrefs_of_node (node);
+
+ if (refs)
+ {
+ register int i;
+ char *refname;
+
+ refname = (char *)xmalloc
+ (1 + strlen ("-Footnotes") + strlen (node->nodename));
+
+ strcpy (refname, node->nodename);
+ strcat (refname, "-Footnotes");
+
+ for (i = 0; refs[i]; i++)
+ if ((refs[i]->nodename != (char *)NULL) &&
+ (strcmp (refs[i]->nodename, refname) == 0))
+ {
+ char *filename;
+
+ filename = node->parent;
+ if (!filename)
+ filename = node->filename;
+
+ fn_node = info_get_node (filename, refname);
+
+ if (fn_node)
+ fn_start = 0;
+
+ break;
+ }
+
+ free (refname);
+ info_free_references (refs);
+ }
+ }
+
+ /* If we never found the start of a footnotes area, quit now. */
+ if (fn_start == -1)
+ return ((NODE *)NULL);
+
+ /* Make the new node. */
+ result = (NODE *)xmalloc (sizeof (NODE));
+ result->flags = 0;
+
+ /* Get the size of the footnotes appearing within this node. */
+ {
+ char *header;
+ long text_start = fn_start;
+
+ header = (char *)xmalloc
+ (1 + strlen (node->nodename) + strlen (FOOTNOTE_HEADER_FORMAT));
+ sprintf (header, FOOTNOTE_HEADER_FORMAT, node->nodename);
+
+ /* Move the start of the displayed text to right after the first line.
+ This effectively skips either "---- footno...", or "File: foo...". */
+ while (text_start < fn_node->nodelen)
+ if (fn_node->contents[text_start++] == '\n')
+ break;
+
+ result->nodelen = strlen (header) + fn_node->nodelen - text_start;
+
+ /* Set the contents of this node. */
+ result->contents = (char *)xmalloc (1 + result->nodelen);
+ sprintf (result->contents, "%s", header);
+ memcpy (result->contents + strlen (header),
+ fn_node->contents + text_start, fn_node->nodelen - text_start);
+
+ name_internal_node (result, footnote_nodename);
+ free (header);
+ }
+
+#if defined (NOTDEF)
+ /* If the footnotes were gleaned from the node that we were called with,
+ shorten the calling node's display length. */
+ if (fn_node == node)
+ narrow_node (node, 0, fn_start);
+#endif /* NOTDEF */
+
+ return (result);
+}
+
+/* Create or delete the footnotes window depending on whether footnotes
+ exist in WINDOW's node or not. Returns FN_FOUND if footnotes were found
+ and displayed. Returns FN_UNFOUND if there were no footnotes found
+ in WINDOW's node. Returns FN_UNABLE if there were footnotes, but the
+ window to show them couldn't be made. */
+int
+info_get_or_remove_footnotes (window)
+ WINDOW *window;
+{
+ WINDOW *fn_win;
+ NODE *new_footnotes;
+
+ fn_win = find_footnotes_window ();
+
+ /* If we are in the footnotes window, change nothing. */
+ if (fn_win == window)
+ return (FN_FOUND);
+
+ /* Try to find footnotes for this window's node. */
+ new_footnotes = make_footnotes_node (window->node);
+
+ /* If there was a window showing footnotes, and there are no footnotes
+ for the current window, delete the old footnote window. */
+ if (fn_win && !new_footnotes)
+ {
+ if (windows->next)
+ info_delete_window_internal (fn_win);
+ }
+
+ /* If there are footnotes for this window's node, but no window around
+ showing footnotes, try to make a new window. */
+ if (new_footnotes && !fn_win)
+ {
+ WINDOW *old_active;
+ WINDOW *last, *win;
+
+ /* Always make this window be the last one appearing in the list. Find
+ the last window in the chain. */
+ for (win = windows, last = windows; win; last = win, win = win->next);
+
+ /* Try to split this window, and make the split window the one to
+ contain the footnotes. */
+ old_active = active_window;
+ active_window = last;
+ fn_win = window_make_window (new_footnotes);
+ active_window = old_active;
+
+ if (!fn_win)
+ {
+ free (new_footnotes->contents);
+ free (new_footnotes);
+
+ /* If we are hacking automatic footnotes, and there are footnotes
+ but we couldn't display them, print a message to that effect. */
+ if (auto_footnotes_p)
+ inform_in_echo_area ("Footnotes could not be displayed");
+ return (FN_UNABLE);
+ }
+ }
+
+ /* If there are footnotes, and there is a window to display them,
+ make that window be the number of lines appearing in the footnotes. */
+ if (new_footnotes && fn_win)
+ {
+ window_set_node_of_window (fn_win, new_footnotes);
+
+ window_change_window_height
+ (fn_win, fn_win->line_count - fn_win->height);
+
+ remember_window_and_node (fn_win, new_footnotes);
+ add_gcable_pointer (new_footnotes->contents);
+ }
+
+ if (!new_footnotes)
+ return (FN_UNFOUND);
+ else
+ return (FN_FOUND);
+}
+
+/* Show the footnotes associated with this node in another window. */
+DECLARE_INFO_COMMAND (info_show_footnotes,
+ "Show the footnotes associated with this node in another window")
+{
+ int result;
+
+ /* A negative argument means just make the window go away. */
+ if (count < 0)
+ {
+ WINDOW *fn_win = find_footnotes_window ();
+
+ /* If there is an old footnotes window, and it isn't the only window
+ on the screen, delete it. */
+ if (fn_win && windows->next)
+ info_delete_window_internal (fn_win);
+ }
+ else
+ {
+ int result;
+
+ result = info_get_or_remove_footnotes (window);
+
+ switch (result)
+ {
+ case FN_UNFOUND:
+ info_error (NO_FOOT_NODE);
+ break;
+
+ case FN_UNABLE:
+ info_error (WIN_TOO_SMALL);
+ break;
+ }
+ }
+}
diff --git a/contrib/texinfo/info/footnotes.h b/contrib/texinfo/info/footnotes.h
new file mode 100644
index 0000000..89b1b35
--- /dev/null
+++ b/contrib/texinfo/info/footnotes.h
@@ -0,0 +1,46 @@
+/* footnotes.h -- Some functions for manipulating footnotes. */
+
+/* This file is part of GNU Info, a program for reading online documentation
+ stored in Info format.
+
+ Copyright (C) 1993 Free Software Foundation, Inc.
+
+ 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Written by Brian Fox (bfox@ai.mit.edu). */
+
+#if !defined (_FOOTNOTES_H_)
+#define _FOOTNOTES_H_
+
+/* Magic string which indicates following text is footnotes. */
+#define FOOTNOTE_LABEL "---------- Footnotes ----------"
+
+#define FN_FOUND 0
+#define FN_UNFOUND 1
+#define FN_UNABLE 2
+
+
+/* Create or delete the footnotes window depending on whether footnotes
+ exist in WINDOW's node or not. Returns FN_FOUND if footnotes were found
+ and displayed. Returns FN_UNFOUND if there were no footnotes found
+ in WINDOW's node. Returns FN_UNABLE if there were footnotes, but the
+ window to show them couldn't be made. */
+extern int info_get_or_remove_footnotes ();
+
+/* Non-zero means attempt to show footnotes when displaying a new window. */
+extern int auto_footnotes_p;
+
+#endif /* !_FOOTNOTES_H_ */
+
diff --git a/contrib/texinfo/info/gc.c b/contrib/texinfo/info/gc.c
new file mode 100644
index 0000000..3b9b090
--- /dev/null
+++ b/contrib/texinfo/info/gc.c
@@ -0,0 +1,95 @@
+/* gc.c -- Functions to remember and garbage collect unused node contents. */
+
+/* This file is part of GNU Info, a program for reading online documentation
+ stored in Info format.
+
+ Copyright (C) 1993 Free Software Foundation, Inc.
+
+ 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Written by Brian Fox (bfox@ai.mit.edu). */
+
+#include "info.h"
+
+/* Array of pointers to the contents of gc-able nodes. A pointer on this
+ list can be garbage collected when no info window contains a node whose
+ contents member match the pointer. */
+static char **gcable_pointers = (char **)NULL;
+static int gcable_pointers_index = 0;
+static int gcable_pointers_slots = 0;
+
+/* Add POINTER to the list of garbage collectible pointers. A pointer
+ is not actually garbage collected until no info window contains a node
+ whose contents member is equal to the pointer. */
+void
+add_gcable_pointer (pointer)
+ char *pointer;
+{
+ gc_pointers ();
+ add_pointer_to_array (pointer, gcable_pointers_index, gcable_pointers,
+ gcable_pointers_slots, 10, char *);
+}
+
+/* Grovel the list of info windows and gc-able pointers finding those
+ node->contents which are collectible, and free them. */
+void
+gc_pointers ()
+{
+ register int i, j, k;
+ INFO_WINDOW *iw;
+ char **new = (char **)NULL;
+ int new_index = 0;
+ int new_slots = 0;
+
+ if (!info_windows || !gcable_pointers_index)
+ return;
+
+ for (i = 0; iw = info_windows[i]; i++)
+ {
+ for (j = 0; j < iw->nodes_index; j++)
+ {
+ NODE *node = iw->nodes[j];
+
+ /* If this node->contents appears in our list of gcable_pointers,
+ it is not gc-able, so save it. */
+ for (k = 0; k < gcable_pointers_index; k++)
+ if (gcable_pointers[k] == node->contents)
+ {
+ add_pointer_to_array
+ (node->contents, new_index, new, new_slots, 10, char *);
+ break;
+ }
+ }
+ }
+
+ /* We have gathered all of the pointers which need to be saved. Free any
+ of the original pointers which do not appear in the new list. */
+ for (i = 0; i < gcable_pointers_index; i++)
+ {
+ for (j = 0; j < new_index; j++)
+ if (gcable_pointers[i] == new[j])
+ break;
+
+ /* If we got all the way through the new list, then the old pointer
+ can be garbage collected. */
+ if (new && !new[j])
+ free (gcable_pointers[i]);
+ }
+
+ free (gcable_pointers);
+ gcable_pointers = new;
+ gcable_pointers_slots = new_slots;
+ gcable_pointers_index = new_index;
+}
diff --git a/contrib/texinfo/info/gc.h b/contrib/texinfo/info/gc.h
new file mode 100644
index 0000000..876062a
--- /dev/null
+++ b/contrib/texinfo/info/gc.h
@@ -0,0 +1,36 @@
+/* gc.h -- Functions for garbage collecting unused node contents. */
+
+/* This file is part of GNU Info, a program for reading online documentation
+ stored in Info format.
+
+ Copyright (C) 1993 Free Software Foundation, Inc.
+
+ 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Written by Brian Fox (bfox@ai.mit.edu). */
+
+#if !defined (_GC_H_)
+#define _GC_H_
+
+/* Add POINTER to the list of garbage collectible pointers. A pointer
+ is not actually garbage collected until no info window contains a node
+ whose contents member is equal to the pointer. */
+extern void add_gcable_pointer ();
+
+/* Grovel the list of info windows and gc-able pointers finding those
+ node->contents which are collectible, and free them. */
+extern void gc_pointers ();
+
+#endif /* !_GC_H_ */
diff --git a/contrib/texinfo/info/general.h b/contrib/texinfo/info/general.h
new file mode 100644
index 0000000..4b97dc8
--- /dev/null
+++ b/contrib/texinfo/info/general.h
@@ -0,0 +1,94 @@
+/* general.h -- Some generally useful defines. */
+
+/* This file is part of GNU Info, a program for reading online documentation
+ stored in Info format.
+
+ Copyright (C) 1993 Free Software Foundation, Inc.
+
+ 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Written by Brian Fox (bfox@ai.mit.edu). */
+
+#if !defined (_GENERAL_H_)
+#define _GENERAL_H_
+
+extern void *xmalloc (), *xrealloc ();
+
+#if defined (HAVE_UNISTD_H)
+# include <unistd.h>
+#endif /* HAVE_UNISTD_H */
+
+#if defined (HAVE_STRING_H)
+# include <string.h>
+#else
+# include <strings.h>
+#endif /* !HAVE_STRING_H */
+
+#include "clib.h"
+
+#define info_toupper(x) (islower (x) ? toupper (x) : x)
+#define info_tolower(x) (isupper (x) ? tolower (x) : x)
+
+#if !defined (whitespace)
+# define whitespace(c) ((c == ' ') || (c == '\t'))
+#endif /* !whitespace */
+
+#if !defined (whitespace_or_newline)
+# define whitespace_or_newline(c) (whitespace (c) || (c == '\n'))
+#endif /* !whitespace_or_newline */
+
+#if !defined (__FUNCTION_DEF)
+# define __FUNCTION_DEF
+typedef int Function ();
+typedef void VFunction ();
+typedef char *CFunction ();
+#endif /* _FUNCTION_DEF */
+
+/* Add POINTER to the list of pointers found in ARRAY. SLOTS is the number
+ of slots that have already been allocated. INDEX is the index into the
+ array where POINTER should be added. GROW is the number of slots to grow
+ ARRAY by, in the case that it needs growing. TYPE is a cast of the type
+ of object stored in ARRAY (e.g., NODE_ENTRY *. */
+#define add_pointer_to_array(pointer, idx, array, slots, grow, type) \
+ do { \
+ if (idx + 2 >= slots) \
+ array = (type *)(xrealloc (array, (slots += grow) * sizeof (type))); \
+ array[idx++] = (type)pointer; \
+ array[idx] = (type)NULL; \
+ } while (0)
+
+#define maybe_free(x) do { if (x) free (x); } while (0)
+
+#if !defined (zero_mem) && defined (HAVE_MEMSET)
+# define zero_mem(mem, length) memset (mem, 0, length)
+#endif /* !zero_mem && HAVE_MEMSET */
+
+#if !defined (zero_mem) && defined (HAVE_BZERO)
+# define zero_mem(mem, length) bzero (mem, length)
+#endif /* !zero_mem && HAVE_BZERO */
+
+#if !defined (zero_mem)
+# define zero_mem(mem, length) \
+ do { \
+ register int zi; \
+ register unsigned char *place; \
+ \
+ place = (unsigned char *)mem; \
+ for (zi = 0; zi < length; zi++) \
+ place[zi] = 0; \
+ } while (0)
+#endif /* !zero_mem */
+
+#endif /* !_GENERAL_H_ */
diff --git a/contrib/texinfo/info/indices.c b/contrib/texinfo/info/indices.c
new file mode 100644
index 0000000..6848884
--- /dev/null
+++ b/contrib/texinfo/info/indices.c
@@ -0,0 +1,667 @@
+/* indices.c -- Commands for dealing with an Info file Index. */
+
+/* This file is part of GNU Info, a program for reading online documentation
+ stored in Info format.
+
+ Copyright (C) 1993 Free Software Foundation, Inc.
+
+ 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Written by Brian Fox (bfox@ai.mit.edu). */
+
+#include "info.h"
+#include "indices.h"
+
+/* User-visible variable controls the output of info-index-next. */
+int show_index_match = 1;
+
+/* In the Info sense, an index is a menu. This variable holds the last
+ parsed index. */
+static REFERENCE **index_index = (REFERENCE **)NULL;
+
+/* The offset of the most recently selected index element. */
+static int index_offset = 0;
+
+/* Variable which holds the last string searched for. */
+static char *index_search = (char *)NULL;
+
+/* A couple of "globals" describing where the initial index was found. */
+static char *initial_index_filename = (char *)NULL;
+static char *initial_index_nodename = (char *)NULL;
+
+/* A structure associating index names with index offset ranges. */
+typedef struct {
+ char *name; /* The nodename of this index. */
+ int first; /* The index in our list of the first entry. */
+ int last; /* The index in our list of the last entry. */
+} INDEX_NAME_ASSOC;
+
+/* An array associating index nodenames with index offset ranges. */
+static INDEX_NAME_ASSOC **index_nodenames = (INDEX_NAME_ASSOC **)NULL;
+static int index_nodenames_index = 0;
+static int index_nodenames_slots = 0;
+
+/* Add the name of NODE, and the range of the associated index elements
+ (passed in ARRAY) to index_nodenames. */
+static void
+add_index_to_index_nodenames (array, node)
+ REFERENCE **array;
+ NODE *node;
+{
+ register int i, last;
+ INDEX_NAME_ASSOC *assoc;
+
+ for (last = 0; array[last]; last++);
+ assoc = (INDEX_NAME_ASSOC *)xmalloc (sizeof (INDEX_NAME_ASSOC));
+ assoc->name = strdup (node->nodename);
+
+ if (!index_nodenames_index)
+ {
+ assoc->first = 0;
+ assoc->last = last;
+ }
+ else
+ {
+ for (i = 0; index_nodenames[i + 1]; i++);
+ assoc->first = 1 + index_nodenames[i]->last;
+ assoc->last = assoc->first + last;
+ }
+ add_pointer_to_array
+ (assoc, index_nodenames_index, index_nodenames, index_nodenames_slots,
+ 10, INDEX_NAME_ASSOC *);
+}
+
+/* Find and return the indices of WINDOW's file. The indices are defined
+ as the first node in the file containing the word "Index" and any
+ immediately following nodes whose names also contain "Index". All such
+ indices are concatenated and the result returned. If WINDOW's info file
+ doesn't have any indices, a NULL pointer is returned. */
+REFERENCE **
+info_indices_of_window (window)
+ WINDOW *window;
+{
+ FILE_BUFFER *fb;
+
+ fb = file_buffer_of_window (window);
+
+ return (info_indices_of_file_buffer (fb));
+}
+
+REFERENCE **
+info_indices_of_file_buffer (file_buffer)
+ FILE_BUFFER *file_buffer;
+{
+ register int i;
+ REFERENCE **result = (REFERENCE **)NULL;
+
+ /* No file buffer, no indices. */
+ if (!file_buffer)
+ return ((REFERENCE **)NULL);
+
+ /* Reset globals describing where the index was found. */
+ maybe_free (initial_index_filename);
+ maybe_free (initial_index_nodename);
+ initial_index_filename = (char *)NULL;
+ initial_index_nodename = (char *)NULL;
+
+ if (index_nodenames)
+ {
+ for (i = 0; index_nodenames[i]; i++)
+ {
+ free (index_nodenames[i]->name);
+ free (index_nodenames[i]);
+ }
+
+ index_nodenames_index = 0;
+ index_nodenames[0] = (INDEX_NAME_ASSOC *)NULL;
+ }
+
+ /* Grovel the names of the nodes found in this file. */
+ if (file_buffer->tags)
+ {
+ TAG *tag;
+
+ for (i = 0; tag = file_buffer->tags[i]; i++)
+ {
+ if (string_in_line ("Index", tag->nodename) != -1)
+ {
+ NODE *node;
+ REFERENCE **menu;
+
+ /* Found one. Get its menu. */
+ node = info_get_node (tag->filename, tag->nodename);
+ if (!node)
+ continue;
+
+ /* Remember the filename and nodename of this index. */
+ initial_index_filename = strdup (file_buffer->filename);
+ initial_index_nodename = strdup (tag->nodename);
+
+ menu = info_menu_of_node (node);
+
+ /* If we have a menu, add this index's nodename and range
+ to our list of index_nodenames. */
+ if (menu)
+ {
+ add_index_to_index_nodenames (menu, node);
+
+ /* Concatenate the references found so far. */
+ result = info_concatenate_references (result, menu);
+ }
+ free (node);
+ }
+ }
+ }
+
+ /* If there is a result, clean it up so that every entry has a filename. */
+ for (i = 0; result && result[i]; i++)
+ if (!result[i]->filename)
+ result[i]->filename = strdup (file_buffer->filename);
+
+ return (result);
+}
+
+DECLARE_INFO_COMMAND (info_index_search,
+ "Look up a string in the index for this file")
+{
+ FILE_BUFFER *fb;
+ char *line;
+
+ /* Reset the index offset, since this is not the info-index-next command. */
+ index_offset = 0;
+
+ /* The user is selecting a new search string, so flush the old one. */
+ maybe_free (index_search);
+ index_search = (char *)NULL;
+
+ /* If this window's file is not the same as the one that we last built an
+ index for, build and remember an index now. */
+ fb = file_buffer_of_window (window);
+ if (!initial_index_filename ||
+ (strcmp (initial_index_filename, fb->filename) != 0))
+ {
+ info_free_references (index_index);
+ window_message_in_echo_area ("Finding index entries...");
+ index_index = info_indices_of_file_buffer (fb);
+ }
+
+ /* If there is no index, quit now. */
+ if (!index_index)
+ {
+ info_error ("No indices found.");
+ return;
+ }
+
+ /* Okay, there is an index. Let the user select one of the members of it. */
+ line =
+ info_read_maybe_completing (window, "Index entry: ", index_index);
+
+ window = active_window;
+
+ /* User aborted? */
+ if (!line)
+ {
+ info_abort_key (active_window, 1, 0);
+ return;
+ }
+
+ /* Empty line means move to the Index node. */
+ if (!*line)
+ {
+ free (line);
+
+ if (initial_index_filename && initial_index_nodename)
+ {
+ NODE *node;
+
+ node =
+ info_get_node (initial_index_filename, initial_index_nodename);
+ set_remembered_pagetop_and_point (window);
+ window_set_node_of_window (window, node);
+ remember_window_and_node (window, node);
+ window_clear_echo_area ();
+ return;
+ }
+ }
+
+ /* The user typed either a completed index label, or a partial string.
+ Find an exact match, or, failing that, the first index entry containing
+ the partial string. So, we just call info_next_index_match () with minor
+ manipulation of INDEX_OFFSET. */
+ {
+ int old_offset;
+
+ /* Start the search right after/before this index. */
+ if (count < 0)
+ {
+ register int i;
+ for (i = 0; index_index[i]; i++);
+ index_offset = i;
+ }
+ else
+ index_offset = -1;
+
+ old_offset = index_offset;
+
+ /* The "last" string searched for is this one. */
+ index_search = line;
+
+ /* Find it, or error. */
+ info_next_index_match (window, count, 0);
+
+ /* If the search failed, return the index offset to where it belongs. */
+ if (index_offset == old_offset)
+ index_offset = 0;
+ }
+}
+
+DECLARE_INFO_COMMAND (info_next_index_match,
+ "Go to the next matching index item from the last `\\[index-search]' command")
+{
+ register int i;
+ int partial, dir;
+ NODE *node;
+
+ /* If there is no previous search string, the user hasn't built an index
+ yet. */
+ if (!index_search)
+ {
+ info_error ("No previous index search string.");
+ return;
+ }
+
+ /* If there is no index, that is an error. */
+ if (!index_index)
+ {
+ info_error ("No index entries.");
+ return;
+ }
+
+ /* The direction of this search is controlled by the value of the
+ numeric argument. */
+ if (count < 0)
+ dir = -1;
+ else
+ dir = 1;
+
+ /* Search for the next occurence of index_search. First try to find
+ an exact match. */
+ partial = 0;
+
+ for (i = index_offset + dir; (i > -1) && (index_index[i]); i += dir)
+ if (strcmp (index_search, index_index[i]->label) == 0)
+ break;
+
+ /* If that failed, look for the next substring match. */
+ if ((i < 0) || (!index_index[i]))
+ {
+ for (i = index_offset + dir; (i > -1) && (index_index[i]); i += dir)
+ if (string_in_line (index_search, index_index[i]->label) != -1)
+ break;
+
+ if ((i > -1) && (index_index[i]))
+ partial = string_in_line (index_search, index_index[i]->label);
+ }
+
+ /* If that failed, print an error. */
+ if ((i < 0) || (!index_index[i]))
+ {
+ info_error ("No %sindex entries containing \"%s\".",
+ index_offset > 0 ? "more " : "", index_search);
+ return;
+ }
+
+ /* Okay, we found the next one. Move the offset to the current entry. */
+ index_offset = i;
+
+ /* Report to the user on what we have found. */
+ {
+ register int j;
+ char *name = "CAN'T SEE THIS";
+ char *match;
+
+ for (j = 0; index_nodenames[j]; j++)
+ {
+ if ((i >= index_nodenames[j]->first) &&
+ (i <= index_nodenames[j]->last))
+ {
+ name = index_nodenames[j]->name;
+ break;
+ }
+ }
+
+ /* If we had a partial match, indicate to the user which part of the
+ string matched. */
+ match = strdup (index_index[i]->label);
+
+ if (partial && show_index_match)
+ {
+ int j, ls, start, upper;
+
+ ls = strlen (index_search);
+ start = partial - ls;
+ upper = isupper (match[start]) ? 1 : 0;
+
+ for (j = 0; j < ls; j++)
+ if (upper)
+ match[j + start] = info_tolower (match[j + start]);
+ else
+ match[j + start] = info_toupper (match[j + start]);
+ }
+
+ {
+ char *format;
+
+ format = replace_in_documentation
+ ("Found \"%s\" in %s. (`\\[next-index-match]' tries to find next.)");
+
+ window_message_in_echo_area (format, match, name);
+ }
+
+ free (match);
+ }
+
+ /* Select the node corresponding to this index entry. */
+ node = info_get_node (index_index[i]->filename, index_index[i]->nodename);
+
+ if (!node)
+ {
+ info_error (CANT_FILE_NODE,
+ index_index[i]->filename, index_index[i]->nodename);
+ return;
+ }
+
+ set_remembered_pagetop_and_point (window);
+ window_set_node_of_window (window, node);
+ remember_window_and_node (window, node);
+
+
+ /* Try to find an occurence of LABEL in this node. */
+ {
+ long start, loc;
+
+ start = window->line_starts[1] - window->node->contents;
+ loc = info_target_search_node (node, index_index[i]->label, start);
+
+ if (loc != -1)
+ {
+ window->point = loc;
+ window_adjust_pagetop (window);
+ }
+ }
+}
+
+/* **************************************************************** */
+/* */
+/* Info APROPOS: Search every known index. */
+/* */
+/* **************************************************************** */
+
+/* For every menu item in DIR, search the indices of that file for
+ SEARCH_STRING. */
+REFERENCE **
+apropos_in_all_indices (search_string, inform)
+ char *search_string;
+ int inform;
+{
+ register int i, dir_index;
+ REFERENCE **all_indices = (REFERENCE **)NULL;
+ REFERENCE **dir_menu = (REFERENCE **)NULL;
+ NODE *dir_node;
+ int printed = 0;
+
+ dir_node = info_get_node ("dir", "Top");
+ if (dir_node)
+ dir_menu = info_menu_of_node (dir_node);
+
+ if (!dir_menu)
+ return;
+
+ /* For every menu item in DIR, get the associated node's file buffer and
+ read the indices of that file buffer. Gather all of the indices into
+ one large one. */
+ for (dir_index = 0; dir_menu[dir_index]; dir_index++)
+ {
+ REFERENCE **this_index, *this_item;
+ NODE *this_node;
+ FILE_BUFFER *this_fb;
+
+ this_item = dir_menu[dir_index];
+
+ if (!this_item->filename)
+ {
+ if (dir_node->parent)
+ this_item->filename = strdup (dir_node->parent);
+ else
+ this_item->filename = strdup (dir_node->filename);
+ }
+
+ /* Find this node. If we cannot find it, try using the label of the
+ entry as a file (i.e., "(LABEL)Top"). */
+ this_node = info_get_node (this_item->filename, this_item->nodename);
+
+ if (!this_node && this_item->nodename &&
+ (strcmp (this_item->label, this_item->nodename) == 0))
+ this_node = info_get_node (this_item->label, "Top");
+
+ if (!this_node)
+ continue;
+
+ /* Get the file buffer associated with this node. */
+ {
+ char *files_name;
+
+ files_name = this_node->parent;
+ if (!files_name)
+ files_name = this_node->filename;
+
+ this_fb = info_find_file (files_name);
+
+ if (this_fb && inform)
+ message_in_echo_area ("Scanning indices of \"%s\"...", files_name);
+
+ this_index = info_indices_of_file_buffer (this_fb);
+ free (this_node);
+
+ if (this_fb && inform)
+ unmessage_in_echo_area ();
+ }
+
+ if (this_index)
+ {
+ /* Remember the filename which contains this set of references. */
+ for (i = 0; this_index && this_index[i]; i++)
+ if (!this_index[i]->filename)
+ this_index[i]->filename = strdup (this_fb->filename);
+
+ /* Concatenate with the other indices. */
+ all_indices = info_concatenate_references (all_indices, this_index);
+ }
+ }
+
+ info_free_references (dir_menu);
+
+ /* Build a list of the references which contain SEARCH_STRING. */
+ if (all_indices)
+ {
+ REFERENCE *entry, **apropos_list = (REFERENCE **)NULL;
+ int apropos_list_index = 0;
+ int apropos_list_slots = 0;
+
+ for (i = 0; (entry = all_indices[i]); i++)
+ {
+ if (string_in_line (search_string, entry->label) != -1)
+ {
+ add_pointer_to_array
+ (entry, apropos_list_index, apropos_list, apropos_list_slots,
+ 100, REFERENCE *);
+ }
+ else
+ {
+ maybe_free (entry->label);
+ maybe_free (entry->filename);
+ maybe_free (entry->nodename);
+ free (entry);
+ }
+ }
+
+ free (all_indices);
+ all_indices = apropos_list;
+ }
+ return (all_indices);
+}
+
+#define APROPOS_NONE \
+ "No available info files reference \"%s\" in their indices."
+
+void
+info_apropos (string)
+ char *string;
+{
+ REFERENCE **apropos_list;
+
+ apropos_list = apropos_in_all_indices (string, 0);
+
+ if (!apropos_list)
+ {
+ info_error (APROPOS_NONE, string);
+ }
+ else
+ {
+ register int i;
+ REFERENCE *entry;
+
+ for (i = 0; (entry = apropos_list[i]); i++)
+ fprintf (stderr, "\"(%s)%s\" -- %s\n",
+ entry->filename, entry->nodename, entry->label);
+ }
+ info_free_references (apropos_list);
+}
+
+static char *apropos_list_nodename = "*Apropos*";
+
+DECLARE_INFO_COMMAND (info_index_apropos,
+ "Grovel all known info file's indices for a string and build a menu")
+{
+ char *line;
+
+ line = info_read_in_echo_area (window, "Index apropos: ");
+
+ window = active_window;
+
+ /* User aborted? */
+ if (!line)
+ {
+ info_abort_key (window, 1, 1);
+ return;
+ }
+
+ /* User typed something? */
+ if (*line)
+ {
+ REFERENCE **apropos_list;
+ NODE *apropos_node;
+
+ apropos_list = apropos_in_all_indices (line, 1);
+
+ if (!apropos_list)
+ {
+ info_error (APROPOS_NONE, line);
+ }
+ else
+ {
+ register int i;
+ char *line_buffer;
+
+ initialize_message_buffer ();
+ printf_to_message_buffer
+ ("\n* Menu: Nodes whoses indices contain \"%s\":\n", line);
+ line_buffer = (char *)xmalloc (500);
+
+ for (i = 0; apropos_list[i]; i++)
+ {
+ int len;
+ sprintf (line_buffer, "* (%s)%s::",
+ apropos_list[i]->filename, apropos_list[i]->nodename);
+ len = pad_to (36, line_buffer);
+ sprintf (line_buffer + len, "%s", apropos_list[i]->label);
+ printf_to_message_buffer ("%s\n", line_buffer);
+ }
+ free (line_buffer);
+ }
+
+ apropos_node = message_buffer_to_node ();
+ add_gcable_pointer (apropos_node->contents);
+ name_internal_node (apropos_node, apropos_list_nodename);
+
+ /* Even though this is an internal node, we don't want the window
+ system to treat it specially. So we turn off the internalness
+ of it here. */
+ apropos_node->flags &= ~N_IsInternal;
+
+ /* Find/Create a window to contain this node. */
+ {
+ WINDOW *new;
+ NODE *node;
+
+ set_remembered_pagetop_and_point (window);
+
+ /* If a window is visible and showing an apropos list already,
+ re-use it. */
+ for (new = windows; new; new = new->next)
+ {
+ node = new->node;
+
+ if (internal_info_node_p (node) &&
+ (strcmp (node->nodename, apropos_list_nodename) == 0))
+ break;
+ }
+
+ /* If we couldn't find an existing window, try to use the next window
+ in the chain. */
+ if (!new && window->next)
+ new = window->next;
+
+ /* If we still don't have a window, make a new one to contain
+ the list. */
+ if (!new)
+ {
+ WINDOW *old_active;
+
+ old_active = active_window;
+ active_window = window;
+ new = window_make_window ((NODE *)NULL);
+ active_window = old_active;
+ }
+
+ /* If we couldn't make a new window, use this one. */
+ if (!new)
+ new = window;
+
+ /* Lines do not wrap in this window. */
+ new->flags |= W_NoWrap;
+
+ window_set_node_of_window (new, apropos_node);
+ remember_window_and_node (new, apropos_node);
+ active_window = new;
+ }
+ info_free_references (apropos_list);
+ }
+ free (line);
+
+ if (!info_error_was_printed)
+ window_clear_echo_area ();
+}
+
diff --git a/contrib/texinfo/info/indices.h b/contrib/texinfo/info/indices.h
new file mode 100644
index 0000000..265b147
--- /dev/null
+++ b/contrib/texinfo/info/indices.h
@@ -0,0 +1,39 @@
+/* indices.h -- Functions defined in indices.c. */
+
+/* This file is part of GNU Info, a program for reading online documentation
+ stored in Info format.
+
+ Copyright (C) 1993 Free Software Foundation, Inc.
+
+ 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Written by Brian Fox (bfox@ai.mit.edu). */
+
+#if !defined (_INDICES_H_)
+#define _INDICES_H_
+
+/* User-visible variable controls the output of info-index-next. */
+extern int show_index_match;
+
+extern REFERENCE **info_indices_of_window (), **info_indices_of_file_buffer ();
+extern void info_apropos ();
+
+/* For every menu item in DIR, search the indices of that file for STRING. */
+REFERENCE **apropos_in_all_indices ();
+
+/* User visible functions declared in indices.c. */
+extern void info_index_search (), info_next_index_match ();
+
+#endif /* !_INDICES_H_ */
diff --git a/contrib/texinfo/info/info-stnd.texi b/contrib/texinfo/info/info-stnd.texi
new file mode 100644
index 0000000..e0fdb20
--- /dev/null
+++ b/contrib/texinfo/info/info-stnd.texi
@@ -0,0 +1,1365 @@
+\input texinfo @c -*-texinfo-*-
+@comment %**start of header
+@setfilename info-stnd.info
+@settitle GNU Info
+@set InfoProgVer 2.11
+@paragraphindent none
+@footnotestyle end
+@synindex vr cp
+@synindex fn cp
+@synindex ky cp
+@comment %**end of header
+@comment $Id: info-stnd.texi,v 1.3 1996/09/30 15:34:02 karl Exp $
+
+@dircategory Texinfo documentation system
+@direntry
+* info program: (info-stnd). Standalone Info-reading program.
+@end direntry
+
+@ifinfo
+This file documents GNU Info, a program for viewing the on-line formatted
+versions of Texinfo files. This documentation is different from the
+documentation for the Info reader that is part of GNU Emacs. If you do
+not know how to use Info, but have a working Info reader, you should
+read that documentation first.
+
+Copyright @copyright{} 1992, 93, 96 Free Software Foundation, Inc.
+
+Permission is granted to make and distribute verbatim copies of this
+manual provided the copyright notice and this permission notice are
+preserved on all copies.
+
+@ignore
+Permission is granted to process this file through TeX and print the
+results, provided the printed document carries a copying permission
+notice identical to this one except for the removal of this paragraph
+(this paragraph not being relevant to the printed manual).
+@end ignore
+
+Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, provided also that the
+sections entitled ``Copying'' and ``GNU General Public License'' are
+included exactly as in the original, and provided that the entire
+resulting derived work is distributed under the terms of a permission
+notice identical to this one.
+
+Permission is granted to copy and distribute translations of this manual
+into another language, under the above conditions for modified versions,
+except that this permission notice may be stated in a translation
+approved by the Free Software Foundation.
+@end ifinfo
+
+@titlepage
+@title GNU Info User's Guide
+@subtitle For GNU Info version @value{InfoProgVer}
+@author Brian J. Fox (bfox@@ai.mit.edu)
+@page
+@vskip 0pt plus 1filll
+Copyright @copyright{} 1992, 1993 Free Software Foundation
+
+Permission is granted to make and distribute verbatim copies of this
+manual provided the copyright notice and this permission notice are
+preserved on all copies.
+
+Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, provided also that the
+sections entitled ``Copying'' and ``GNU General Public License'' are
+included exactly as in the original, and provided that the entire
+resulting derived work is distributed under the terms of a permission
+notice identical to this one.
+
+Permission is granted to copy and distribute translations of this manual
+into another language, under the above conditions for modified versions,
+except that this permission notice may be stated in a translation
+approved by the Free Software Foundation.
+@end titlepage
+
+@ifinfo
+@node Top, What is Info, (dir), (dir)
+@top The GNU Info Program
+
+This file documents GNU Info, a program for viewing the on-line
+formatted versions of Texinfo files, version @value{InfoProgVer}. This
+documentation is different from the documentation for the Info reader
+that is part of GNU Emacs.
+@end ifinfo
+
+@menu
+* What is Info::
+* Options:: Options you can pass on the command line.
+* Cursor Commands:: Commands which move the cursor within a node.
+* Scrolling Commands:: Commands for moving the node around
+ in a window.
+* Node Commands:: Commands for selecting a new node.
+* Searching Commands:: Commands for searching an Info file.
+* Xref Commands:: Commands for selecting cross references.
+* Window Commands:: Commands which manipulate multiple windows.
+* Printing Nodes:: How to print out the contents of a node.
+* Miscellaneous Commands:: A few commands that defy categories.
+* Variables:: How to change the default behavior of Info.
+* GNU Info Global Index:: Global index containing keystrokes,
+ command names, variable names,
+ and general concepts.
+@end menu
+
+@node What is Info, Options, Top, Top
+@chapter What is Info?
+
+@iftex
+This file documents GNU Info, a program for viewing the on-line formatted
+versions of Texinfo files, version @value{InfoProgVer}.
+@end iftex
+
+@dfn{Info} is a program which is used to view Info files on an ASCII
+terminal. @dfn{Info files} are the result of processing Texinfo files
+with the program @code{makeinfo} or with one of the Emacs commands, such
+as @code{M-x texinfo-format-buffer}. Texinfo itself is a documentation
+system that uses a single source file to produce both on-line
+information and printed output. You can typeset and print the
+files that you read in Info.@refill
+
+@node Options, Cursor Commands, What is Info, Top
+@chapter Command Line Options
+@cindex command line options
+@cindex arguments, command line
+
+GNU Info accepts several options to control the initial node being
+viewed, and to specify which directories to search for Info files. Here
+is a template showing an invocation of GNU Info from the shell:
+
+@example
+info [--@var{option-name} @var{option-value}] @var{menu-item}@dots{}
+@end example
+
+The following @var{option-names} are available when invoking Info from
+the shell:
+
+@table @code
+@cindex directory path
+@item --directory @var{directory-path}
+@itemx -d @var{directory-path}
+Add @var{directory-path} to the list of directory paths searched when
+Info needs to find a file. You may issue @code{--directory} multiple
+times; once for each directory which contains Info files.
+Alternatively, you may specify a value for the environment variable
+@code{INFOPATH}; if @code{--directory} is not given, the value of
+@code{INFOPATH} is used. The value of @code{INFOPATH} is a colon
+separated list of directory names. If you do not supply @code{INFOPATH}
+or @code{--directory-path}, Info uses a default path.
+
+@item --file @var{filename}
+@itemx -f @var{filename}
+@cindex Info file, selecting
+Specify a particular Info file to visit. By default, Info visits
+the file @code{dir}; if you use this option, Info will start with
+@code{(@var{filename})Top} as the first file and node.
+
+@item --node @var{nodename}
+@itemx -n @var{nodename}
+@cindex node, selecting
+Specify a particular node to visit in the initial file that Info
+loads. This is especially useful in conjunction with
+@code{--file}@footnote{Of course, you can specify both the file and node
+in a @code{--node} command; but don't forget to escape the open and
+close parentheses from the shell as in: @code{info --node
+"(emacs)Buffers"}}. You may specify @code{--node} multiple times; for
+an interactive Info, each @var{nodename} is visited in its own window,
+for a non-interactive Info (such as when @code{--output} is given) each
+@var{nodename} is processed sequentially.
+
+@item --output @var{filename}
+@itemx -o @var{filename}
+@cindex file, outputting to
+@cindex outputting to a file
+Specify @var{filename} as the name of a file to which to direct output.
+Each node that Info visits will be output to @var{filename} instead of
+interactively viewed. A value of @code{-} for @var{filename} specifies
+the standard output.
+
+@item --subnodes
+@cindex @code{--subnodes}, command line option
+This option only has meaning when given in conjunction with
+@code{--output}. It means to recursively output the nodes appearing in
+the menus of each node being output. Menu items which resolve to
+external Info files are not output, and neither are menu items which are
+members of an index. Each node is only output once.
+
+@item --help
+@itemx -h
+Produces a relatively brief description of the available Info options.
+
+@item --version
+@cindex version information
+Prints the version information of Info and exits.
+
+@item @var{menu-item}
+@cindex menu, following
+Info treats its remaining arguments as the names of menu items. The
+first argument is a menu item in the initial node visited, while
+the second argument is a menu item in the first argument's node.
+You can easily move to the node of your choice by specifying the menu
+names which describe the path to that node. For example,
+
+@example
+info emacs buffers
+@end example
+
+@noindent
+first selects the menu item @samp{Emacs} in the node @samp{(dir)Top},
+and then selects the menu item @samp{Buffers} in the node
+@samp{(emacs)Top}.
+@end table
+
+@node Cursor Commands, Scrolling Commands, Options, Top
+@chapter Moving the Cursor
+@cindex cursor, moving
+
+Many people find that reading screens of text page by page is made
+easier when one is able to indicate particular pieces of text with some
+kind of pointing device. Since this is the case, GNU Info (both the
+Emacs and standalone versions) have several commands which allow you to
+move the cursor about the screen. The notation used in this manual to
+describe keystrokes is identical to the notation used within the Emacs
+manual, and the GNU Readline manual. @xref{Characters, , Character
+Conventions, emacs, the GNU Emacs Manual}, if you are unfamiliar with the
+notation.
+
+The following table lists the basic cursor movement commands in Info.
+Each entry consists of the key sequence you should type to execute the
+cursor movement, the @code{M-x}@footnote{@code{M-x} is also a command; it
+invokes @code{execute-extended-command}. @xref{M-x, , Executing an
+extended command, emacs, the GNU Emacs Manual}, for more detailed
+information.} command name (displayed in parentheses), and a short
+description of what the command does. All of the cursor motion commands
+can take an @dfn{numeric} argument (@pxref{Miscellaneous Commands,
+@code{universal-argument}}), to find out how to supply them. With a
+numeric argument, the motion commands are simply executed that
+many times; for example, a numeric argument of 4 given to
+@code{next-line} causes the cursor to move down 4 lines. With a
+negative numeric argument, the motion is reversed; an argument of -4
+given to the @code{next-line} command would cause the cursor to move
+@emph{up} 4 lines.
+
+@table @asis
+@item @code{C-n} (@code{next-line})
+@kindex C-n
+@findex next-line
+Move the cursor down to the next line.
+
+@item @code{C-p} (@code{prev-line})
+@kindex C-p
+@findex prev-line
+Move the cursor up to the previous line.
+
+@item @code{C-a} (@code{beginning-of-line})
+@kindex C-a, in Info windows
+@findex beginning-of-line
+Move the cursor to the start of the current line.
+
+@item @code{C-e} (@code{end-of-line})
+@kindex C-e, in Info windows
+@findex end-of-line
+Move the cursor to the end of the current line.
+
+@item @code{C-f} (@code{forward-char})
+@kindex C-f, in Info windows
+@findex forward-char
+Move the cursor forward a character.
+
+@item @code{C-b} (@code{backward-char})
+@kindex C-b, in Info windows
+@findex backward-char
+Move the cursor backward a character.
+
+@item @code{M-f} (@code{forward-word})
+@kindex M-f, in Info windows
+@findex forward-word
+Move the cursor forward a word.
+
+@item @code{M-b} (@code{backward-word})
+@kindex M-b, in Info windows
+@findex backward-word
+Move the cursor backward a word.
+
+@item @code{M-<} (@code{beginning-of-node})
+@itemx @code{b}
+@kindex b, in Info windows
+@kindex M-<
+@findex beginning-of-node
+Move the cursor to the start of the current node.
+
+@item @code{M->} (@code{end-of-node})
+@kindex M->
+@findex end-of-node
+Move the cursor to the end of the current node.
+
+@item @code{M-r} (@code{move-to-window-line})
+@kindex M-r
+@findex move-to-window-line
+Move the cursor to a specific line of the window. Without a numeric
+argument, @code{M-r} moves the cursor to the start of the line in the
+center of the window. With a numeric argument of @var{n}, @code{M-r}
+moves the cursor to the start of the @var{n}th line in the window.
+@end table
+
+@node Scrolling Commands, Node Commands, Cursor Commands, Top
+@chapter Moving Text Within a Window
+@cindex scrolling
+
+Sometimes you are looking at a screenful of text, and only part of the
+current paragraph you are reading is visible on the screen. The
+commands detailed in this section are used to shift which part of the
+current node is visible on the screen.
+
+@table @asis
+@item @code{SPC} (@code{scroll-forward})
+@itemx @code{C-v}
+@kindex SPC, in Info windows
+@kindex C-v
+@findex scroll-forward
+Shift the text in this window up. That is, show more of the node which
+is currently below the bottom of the window. With a numeric argument,
+show that many more lines at the bottom of the window; a numeric
+argument of 4 would shift all of the text in the window up 4 lines
+(discarding the top 4 lines), and show you four new lines at the bottom
+of the window. Without a numeric argument, @key{SPC} takes the bottom
+two lines of the window and places them at the top of the window,
+redisplaying almost a completely new screenful of lines.
+
+@item @code{DEL} (@code{scroll-backward})
+@itemx @code{M-v}
+@kindex DEL, in Info windows
+@kindex M-v
+@findex scroll-backward
+Shift the text in this window down. The inverse of
+@code{scroll-forward}.
+@end table
+
+@cindex scrolling through node structure
+The @code{scroll-forward} and @code{scroll-backward} commands can also
+move forward and backward through the node structure of the file. If
+you press @key{SPC} while viewing the end of a node, or @key{DEL} while
+viewing the beginning of a node, what happens is controlled by the
+variable @code{scroll-behavior}. @xref{Variables,
+@code{scroll-behavior}}, for more information.
+
+@table @asis
+@item @code{C-l} (@code{redraw-display})
+@kindex C-l
+@findex redraw-display
+Redraw the display from scratch, or shift the line containing the cursor
+to a specified location. With no numeric argument, @samp{C-l} clears
+the screen, and then redraws its entire contents. Given a numeric
+argument of @var{n}, the line containing the cursor is shifted so that
+it is on the @var{n}th line of the window.
+
+@item @code{C-x w} (@code{toggle-wrap})
+@kindex C-w
+@findex toggle-wrap
+Toggles the state of line wrapping in the current window. Normally,
+lines which are longer than the screen width @dfn{wrap}, i.e., they are
+continued on the next line. Lines which wrap have a @samp{\} appearing
+in the rightmost column of the screen. You can cause such lines to be
+terminated at the rightmost column by changing the state of line
+wrapping in the window with @code{C-x w}. When a line which needs more
+space than one screen width to display is displayed, a @samp{$} appears
+in the rightmost column of the screen, and the remainder of the line is
+invisible.
+@end table
+
+@node Node Commands, Searching Commands, Scrolling Commands, Top
+@chapter Selecting a New Node
+@cindex nodes, selection of
+
+This section details the numerous Info commands which select a new node
+to view in the current window.
+
+The most basic node commands are @samp{n}, @samp{p}, @samp{u}, and
+@samp{l}.
+
+When you are viewing a node, the top line of the node contains some Info
+@dfn{pointers} which describe where the next, previous, and up nodes
+are. Info uses this line to move about the node structure of the file
+when you use the following commands:
+
+@table @asis
+@item @code{n} (@code{next-node})
+@kindex n
+@findex next-node
+Select the `Next' node.
+
+@item @code{p} (@code{prev-node})
+@kindex p
+@findex prev-node
+Select the `Prev' node.
+
+@item @code{u} (@code{up-node})
+@kindex u
+@findex up-node
+Select the `Up' node.
+@end table
+
+You can easily select a node that you have already viewed in this window
+by using the @samp{l} command -- this name stands for "last", and
+actually moves through the list of already visited nodes for this
+window. @samp{l} with a negative numeric argument moves forward through
+the history of nodes for this window, so you can quickly step between
+two adjacent (in viewing history) nodes.
+
+@table @asis
+@item @code{l} (@code{history-node})
+@kindex l
+@findex history-node
+Select the most recently selected node in this window.
+@end table
+
+Two additional commands make it easy to select the most commonly
+selected nodes; they are @samp{t} and @samp{d}.
+
+@table @asis
+@item @code{t} (@code{top-node})
+@kindex t
+@findex top-node
+Select the node @samp{Top} in the current Info file.
+
+@item @code{d} (@code{dir-node})
+@kindex d
+@findex dir-node
+Select the directory node (i.e., the node @samp{(dir)}).
+@end table
+
+Here are some other commands which immediately result in the selection
+of a different node in the current window:
+
+@table @asis
+@item @code{<} (@code{first-node})
+@kindex <
+@findex first-node
+Selects the first node which appears in this file. This node is most
+often @samp{Top}, but it does not have to be.
+
+@item @code{>} (@code{last-node})
+@kindex >
+@findex last-node
+Select the last node which appears in this file.
+
+@item @code{]} (@code{global-next-node})
+@kindex ]
+@findex global-next-node
+Move forward or down through node structure. If the node that you are
+currently viewing has a @samp{Next} pointer, that node is selected.
+Otherwise, if this node has a menu, the first menu item is selected. If
+there is no @samp{Next} and no menu, the same process is tried with the
+@samp{Up} node of this node.
+
+@item @code{[} (@code{global-prev-node})
+@kindex [
+@findex global-prev-node
+Move backward or up through node structure. If the node that you are
+currently viewing has a @samp{Prev} pointer, that node is selected.
+Otherwise, if the node has an @samp{Up} pointer, that node is selected,
+and if it has a menu, the last item in the menu is selected.
+@end table
+
+You can get the same behavior as @code{global-next-node} and
+@code{global-prev-node} while simply scrolling through the file with
+@key{SPC} and @key{DEL}; @xref{Variables, @code{scroll-behavior}}, for
+more information.
+
+@table @asis
+@item @code{g} (@code{goto-node})
+@kindex g
+@findex goto-node
+Read the name of a node and select it. No completion is done while
+reading the node name, since the desired node may reside in a separate
+file. The node must be typed exactly as it appears in the Info file. A
+file name may be included as with any node specification, for example
+
+@example
+@code{g(emacs)Buffers}
+@end example
+
+finds the node @samp{Buffers} in the Info file @file{emacs}.
+
+@item @code{C-x k} (@code{kill-node})
+@kindex C-x k
+@findex kill-node
+Kill a node. The node name is prompted for in the echo area, with a
+default of the current node. @dfn{Killing} a node means that Info tries
+hard to forget about it, removing it from the list of history nodes kept
+for the window where that node is found. Another node is selected in
+the window which contained the killed node.
+
+@item @code{C-x C-f} (@code{view-file})
+@kindex C-x C-f
+@findex view-file
+Read the name of a file and selects the entire file. The command
+@example
+@code{C-x C-f @var{filename}}
+@end example
+is equivalent to typing
+@example
+@code{g(@var{filename})*}
+@end example
+
+@item @code{C-x C-b} (@code{list-visited-nodes})
+@kindex C-x C-b
+@findex list-visited-nodes
+Make a window containing a menu of all of the currently visited nodes.
+This window becomes the selected window, and you may use the standard
+Info commands within it.
+
+@item @code{C-x b} (@code{select-visited-node})
+@kindex C-x b
+@findex select-visited-node
+Select a node which has been previously visited in a visible window.
+This is similar to @samp{C-x C-b} followed by @samp{m}, but no window is
+created.
+@end table
+
+@node Searching Commands, Xref Commands, Node Commands, Top
+@chapter Searching an Info File
+@cindex searching
+
+GNU Info allows you to search for a sequence of characters throughout an
+entire Info file, search through the indices of an Info file, or find
+areas within an Info file which discuss a particular topic.
+
+@table @asis
+@item @code{s} (@code{search})
+@kindex s
+@findex search
+Read a string in the echo area and search for it.
+
+@item @code{C-s} (@code{isearch-forward})
+@kindex C-s
+@findex isearch-forward
+Interactively search forward through the Info file for a string as you
+type it.
+
+@item @code{C-r} (@code{isearch-backward})
+@kindex C-r
+@findex isearch-backward
+Interactively search backward through the Info file for a string as
+you type it.
+
+@item @code{i} (@code{index-search})
+@kindex i
+@findex index-search
+Look up a string in the indices for this Info file, and select a node
+where the found index entry points to.
+
+@item @code{,} (@code{next-index-match})
+@kindex ,
+@findex next-index-match
+Move to the node containing the next matching index item from the last
+@samp{i} command.
+@end table
+
+The most basic searching command is @samp{s} (@code{search}). The
+@samp{s} command prompts you for a string in the echo area, and then
+searches the remainder of the Info file for an occurrence of that string.
+If the string is found, the node containing it is selected, and the
+cursor is left positioned at the start of the found string. Subsequent
+@samp{s} commands show you the default search string within @samp{[} and
+@samp{]}; pressing @key{RET} instead of typing a new string will use the
+default search string.
+
+@dfn{Incremental searching} is similar to basic searching, but the
+string is looked up while you are typing it, instead of waiting until
+the entire search string has been specified.
+
+@node Xref Commands, Window Commands, Searching Commands, Top
+@chapter Selecting Cross References
+
+We have already discussed the @samp{Next}, @samp{Prev}, and @samp{Up}
+pointers which appear at the top of a node. In addition to these
+pointers, a node may contain other pointers which refer you to a
+different node, perhaps in another Info file. Such pointers are called
+@dfn{cross references}, or @dfn{xrefs} for short.
+
+@menu
+* Parts of an Xref:: What a cross reference is made of.
+* Selecting Xrefs:: Commands for selecting menu or note items.
+@end menu
+
+@node Parts of an Xref, Selecting Xrefs, , Xref Commands
+@section Parts of an Xref
+
+Cross references have two major parts: the first part is called the
+@dfn{label}; it is the name that you can use to refer to the cross
+reference, and the second is the @dfn{target}; it is the full name of
+the node that the cross reference points to.
+
+The target is separated from the label by a colon @samp{:}; first the
+label appears, and then the target. For example, in the sample menu
+cross reference below, the single colon separates the label from the
+target.
+
+@example
+* Foo Label: Foo Target. More information about Foo.
+@end example
+
+Note the @samp{.} which ends the name of the target. The @samp{.} is
+not part of the target; it serves only to let Info know where the target
+name ends.
+
+A shorthand way of specifying references allows two adjacent colons to
+stand for a target name which is the same as the label name:
+
+@example
+* Foo Commands:: Commands pertaining to Foo.
+@end example
+
+In the above example, the name of the target is the same as the name of
+the label, in this case @code{Foo Commands}.
+
+You will normally see two types of cross reference while viewing nodes:
+@dfn{menu} references, and @dfn{note} references. Menu references
+appear within a node's menu; they begin with a @samp{*} at the beginning
+of a line, and continue with a label, a target, and a comment which
+describes what the contents of the node pointed to contains.
+
+Note references appear within the body of the node text; they begin with
+@code{*Note}, and continue with a label and a target.
+
+Like @samp{Next}, @samp{Prev}, and @samp{Up} pointers, cross references
+can point to any valid node. They are used to refer you to a place
+where more detailed information can be found on a particular subject.
+Here is a cross reference which points to a node within the Texinfo
+documentation: @xref{xref, , Writing an Xref, texinfo, the Texinfo
+Manual}, for more information on creating your own texinfo cross
+references.
+
+@node Selecting Xrefs, , Parts of an Xref, Xref Commands
+@section Selecting Xrefs
+
+The following table lists the Info commands which operate on menu items.
+
+@table @asis
+@item @code{1} (@code{menu-digit})
+@itemx @code{2} @dots{} @code{9}
+@cindex 1 @dots{} 9, in Info windows
+@kindex 1 @dots{} 9, in Info windows
+@findex menu-digit
+Within an Info window, pressing a single digit, (such as @samp{1}),
+selects that menu item, and places its node in the current window.
+For convenience, there is one exception; pressing @samp{0} selects the
+@emph{last} item in the node's menu.
+
+@item @code{0} (@code{last-menu-item})
+@kindex 0, in Info windows
+@findex last-menu-item
+Select the last item in the current node's menu.
+
+@item @code{m} (@code{menu-item})
+@kindex m
+@findex menu-item
+Reads the name of a menu item in the echo area and selects its node.
+Completion is available while reading the menu label.
+
+@item @code{M-x find-menu}
+@findex find-menu
+Move the cursor to the start of this node's menu.
+@end table
+
+This table lists the Info commands which operate on note cross references.
+
+@table @asis
+@item @code{f} (@code{xref-item})
+@itemx @code{r}
+@kindex f
+@kindex r
+@findex xref-item
+Reads the name of a note cross reference in the echo area and selects
+its node. Completion is available while reading the cross reference
+label.
+@end table
+
+Finally, the next few commands operate on menu or note references alike:
+
+@table @asis
+@item @code{TAB} (@code{move-to-next-xref})
+@kindex TAB, in Info windows
+@findex move-to-next-xref
+Move the cursor to the start of the next nearest menu item or note
+reference in this node. You can then use @key{RET}
+(@code{select-reference-this-line}) to select the menu or note reference.
+
+@item @code{M-TAB} (@code{move-to-prev-xref})
+@kindex M-TAB, in Info windows
+@findex move-to-prev-xref
+Move the cursor the start of the nearest previous menu item or note
+reference in this node.
+
+@item @code{RET} (@code{select-reference-this-line})
+@kindex RET, in Info windows
+@findex select-reference-this-line
+Select the menu item or note reference appearing on this line.
+@end table
+
+@node Window Commands, Printing Nodes, Xref Commands, Top
+@chapter Manipulating Multiple Windows
+@cindex windows, manipulating
+
+A @dfn{window} is a place to show the text of a node. Windows have a
+view area where the text of the node is displayed, and an associated
+@dfn{mode line}, which briefly describes the node being viewed.
+
+GNU Info supports multiple windows appearing in a single screen; each
+window is separated from the next by its modeline. At any time, there
+is only one @dfn{active} window, that is, the window in which the cursor
+appears. There are commands available for creating windows, changing
+the size of windows, selecting which window is active, and for deleting
+windows.
+
+@menu
+* The Mode Line:: What appears in the mode line?
+* Basic Windows:: Manipulating windows in Info.
+* The Echo Area:: Used for displaying errors and reading input.
+@end menu
+
+@node The Mode Line, Basic Windows, , Window Commands
+@section The Mode Line
+
+A @dfn{mode line} is a line of inverse video which appears at the bottom
+of an Info window. It describes the contents of the window just above
+it; this information includes the name of the file and node appearing in
+that window, the number of screen lines it takes to display the node,
+and the percentage of text that is above the top of the window. It can
+also tell you if the indirect tags table for this Info file needs to be
+updated, and whether or not the Info file was compressed when stored on
+disk.
+
+Here is a sample mode line for a window containing an uncompressed file
+named @file{dir}, showing the node @samp{Top}.
+
+@example
+@group
+-----Info: (dir)Top, 40 lines --Top---------------------------------------
+ ^^ ^ ^^^ ^^
+ (file)Node #lines where
+@end group
+@end example
+
+When a node comes from a file which is compressed on disk, this is
+indicated in the mode line with two small @samp{z}'s. In addition, if
+the Info file containing the node has been split into subfiles, the name
+of the subfile containing the node appears in the modeline as well:
+
+@example
+--zz-Info: (emacs)Top, 291 lines --Top-- Subfile: emacs-1.Z---------------
+@end example
+
+When Info makes a node internally, such that there is no corresponding
+info file on disk, the name of the node is surrounded by asterisks
+(@samp{*}). The name itself tells you what the contents of the window
+are; the sample mode line below shows an internally constructed node
+showing possible completions:
+
+@example
+-----Info: *Completions*, 7 lines --All-----------------------------------
+@end example
+
+@node Basic Windows, The Echo Area, The Mode Line, Window Commands
+@section Window Commands
+
+It can be convenient to view more than one node at a time. To allow
+this, Info can display more than one @dfn{window}. Each window has its
+own mode line (@pxref{The Mode Line}) and history of nodes viewed in that
+window (@pxref{Node Commands, , @code{history-node}}).
+
+@table @asis
+@item @code{C-x o} (@code{next-window})
+@cindex windows, selecting
+@kindex C-x o
+@findex next-window
+Select the next window on the screen. Note that the echo area can only be
+selected if it is already in use, and you have left it temporarily.
+Normally, @samp{C-x o} simply moves the cursor into the next window on
+the screen, or if you are already within the last window, into the first
+window on the screen. Given a numeric argument, @samp{C-x o} moves over
+that many windows. A negative argument causes @samp{C-x o} to select
+the previous window on the screen.
+
+@item @code{M-x prev-window}
+@findex prev-window
+Select the previous window on the screen. This is identical to
+@samp{C-x o} with a negative argument.
+
+@item @code{C-x 2} (@code{split-window})
+@cindex windows, creating
+@kindex C-x 2
+@findex split-window
+Split the current window into two windows, both showing the same node.
+Each window is one half the size of the original window, and the cursor
+remains in the original window. The variable @code{automatic-tiling}
+can cause all of the windows on the screen to be resized for you
+automatically, please @pxref{Variables, , automatic-tiling} for more
+information.
+
+@item @code{C-x 0} (@code{delete-window})
+@cindex windows, deleting
+@kindex C-x 0
+@findex delete-window
+Delete the current window from the screen. If you have made too many
+windows and your screen appears cluttered, this is the way to get rid of
+some of them.
+
+@item @code{C-x 1} (@code{keep-one-window})
+@kindex C-x 1
+@findex keep-one-window
+Delete all of the windows excepting the current one.
+
+@item @code{ESC C-v} (@code{scroll-other-window})
+@kindex ESC C-v, in Info windows
+@findex scroll-other-window
+Scroll the other window, in the same fashion that @samp{C-v} might
+scroll the current window. Given a negative argument, scroll the
+"other" window backward.
+
+@item @code{C-x ^} (@code{grow-window})
+@kindex C-x ^
+@findex grow-window
+Grow (or shrink) the current window. Given a numeric argument, grow
+the current window that many lines; with a negative numeric argument,
+shrink the window instead.
+
+@item @code{C-x t} (@code{tile-windows})
+@cindex tiling
+@kindex C-x t
+@findex tile-windows
+Divide the available screen space among all of the visible windows.
+Each window is given an equal portion of the screen in which to display
+its contents. The variable @code{automatic-tiling} can cause
+@code{tile-windows} to be called when a window is created or deleted.
+@xref{Variables, , @code{automatic-tiling}}.
+@end table
+
+@node The Echo Area, , Basic Windows, Window Commands
+@section The Echo Area
+@cindex echo area
+
+The @dfn{echo area} is a one line window which appears at the bottom of
+the screen. It is used to display informative or error messages, and to
+read lines of input from you when that is necessary. Almost all of the
+commands available in the echo area are identical to their Emacs
+counterparts, so please refer to that documentation for greater depth of
+discussion on the concepts of editing a line of text. The following
+table briefly lists the commands that are available while input is being
+read in the echo area:
+
+@table @asis
+@item @code{C-f} (@code{echo-area-forward})
+@kindex C-f, in the echo area
+@findex echo-area-forward
+Move forward a character.
+
+@item @code{C-b} (@code{echo-area-backward})
+@kindex C-b, in the echo area
+@findex echo-area-backward
+Move backward a character.
+
+@item @code{C-a} (@code{echo-area-beg-of-line})
+@kindex C-a, in the echo area
+@findex echo-area-beg-of-line
+Move to the start of the input line.
+
+@item @code{C-e} (@code{echo-area-end-of-line})
+@kindex C-e, in the echo area
+@findex echo-area-end-of-line
+Move to the end of the input line.
+
+@item @code{M-f} (@code{echo-area-forward-word})
+@kindex M-f, in the echo area
+@findex echo-area-forward-word
+Move forward a word.
+
+@item @code{M-b} (@code{echo-area-backward-word})
+@kindex M-b, in the echo area
+@findex echo-area-backward-word
+Move backward a word.
+
+@item @code{C-d} (@code{echo-area-delete})
+@kindex C-d, in the echo area
+@findex echo-area-delete
+Delete the character under the cursor.
+
+@item @code{DEL} (@code{echo-area-rubout})
+@kindex DEL, in the echo area
+@findex echo-area-rubout
+Delete the character behind the cursor.
+
+@item @code{C-g} (@code{echo-area-abort})
+@kindex C-g, in the echo area
+@findex echo-area-abort
+Cancel or quit the current operation. If completion is being read,
+@samp{C-g} discards the text of the input line which does not match any
+completion. If the input line is empty, @samp{C-g} aborts the calling
+function.
+
+@item @code{RET} (@code{echo-area-newline})
+@kindex RET, in the echo area
+@findex echo-area-newline
+Accept (or forces completion of) the current input line.
+
+@item @code{C-q} (@code{echo-area-quoted-insert})
+@kindex C-q, in the echo area
+@findex echo-area-quoted-insert
+Insert the next character verbatim. This is how you can insert control
+characters into a search string, for example.
+
+@item @var{printing character} (@code{echo-area-insert})
+@kindex printing characters, in the echo area
+@findex echo-area-insert
+Insert the character.
+
+@item @code{M-TAB} (@code{echo-area-tab-insert})
+@kindex M-TAB, in the echo area
+@findex echo-area-tab-insert
+Insert a TAB character.
+
+@item @code{C-t} (@code{echo-area-transpose-chars})
+@kindex C-t, in the echo area
+@findex echo-area-transpose-chars
+Transpose the characters at the cursor.
+@end table
+
+The next group of commands deal with @dfn{killing}, and @dfn{yanking}
+text. For an in depth discussion of killing and yanking,
+@pxref{Killing, , Killing and Deleting, emacs, the GNU Emacs Manual}
+
+@table @asis
+@item @code{M-d} (@code{echo-area-kill-word})
+@kindex M-d, in the echo area
+@findex echo-area-kill-word
+Kill the word following the cursor.
+
+@item @code{M-DEL} (@code{echo-area-backward-kill-word})
+@kindex M-DEL, in the echo area
+@findex echo-area-backward-kill-word
+Kill the word preceding the cursor.
+
+@item @code{C-k} (@code{echo-area-kill-line})
+@kindex C-k, in the echo area
+@findex echo-area-kill-line
+Kill the text from the cursor to the end of the line.
+
+@item @code{C-x DEL} (@code{echo-area-backward-kill-line})
+@kindex C-x DEL, in the echo area
+@findex echo-area-backward-kill-line
+Kill the text from the cursor to the beginning of the line.
+
+@item @code{C-y} (@code{echo-area-yank})
+@kindex C-y, in the echo area
+@findex echo-area-yank
+Yank back the contents of the last kill.
+
+@item @code{M-y} (@code{echo-area-yank-pop})
+@kindex M-y, in the echo area
+@findex echo-area-yank-pop
+Yank back a previous kill, removing the last yanked text first.
+@end table
+
+Sometimes when reading input in the echo area, the command that needed
+input will only accept one of a list of several choices. The choices
+represent the @dfn{possible completions}, and you must respond with one
+of them. Since there are a limited number of responses you can make,
+Info allows you to abbreviate what you type, only typing as much of the
+response as is necessary to uniquely identify it. In addition, you can
+request Info to fill in as much of the response as is possible; this
+is called @dfn{completion}.
+
+The following commands are available when completing in the echo area:
+
+@table @asis
+@item @code{TAB} (@code{echo-area-complete})
+@itemx @code{SPC}
+@kindex TAB, in the echo area
+@kindex SPC, in the echo area
+@findex echo-area-complete
+Insert as much of a completion as is possible.
+
+@item @code{?} (@code{echo-area-possible-completions})
+@kindex ?, in the echo area
+@findex echo-area-possible-completions
+Display a window containing a list of the possible completions of what
+you have typed so far. For example, if the available choices are:
+
+@example
+@group
+bar
+foliate
+food
+forget
+@end group
+@end example
+
+@noindent
+and you have typed an @samp{f}, followed by @samp{?}, the possible
+completions would contain:
+
+@example
+@group
+foliate
+food
+forget
+@end group
+@end example
+
+@noindent
+i.e., all of the choices which begin with @samp{f}. Pressing @key{SPC}
+or @key{TAB} would result in @samp{fo} appearing in the echo area, since
+all of the choices which begin with @samp{f} continue with @samp{o}.
+Now, typing @samp{l} followed by @samp{TAB} results in @samp{foliate}
+appearing in the echo area, since that is the only choice which begins
+with @samp{fol}.
+
+@item @code{ESC C-v} (@code{echo-area-scroll-completions-window})
+@kindex ESC C-v, in the echo area
+@findex echo-area-scroll-completions-window
+Scroll the completions window, if that is visible, or the "other"
+window if not.
+@end table
+
+@node Printing Nodes, Miscellaneous Commands, Window Commands, Top
+@chapter Printing Out Nodes
+@cindex printing
+
+You may wish to print out the contents of a node as a quick reference
+document for later use. Info provides you with a command for doing
+this. In general, we recommend that you use @TeX{} to format the
+document and print sections of it, by running @code{tex} on the Texinfo
+source file.
+
+@table @asis
+@item @code{M-x print-node}
+@findex print-node
+@cindex INFO_PRINT_COMMAND, environment variable
+Pipe the contents of the current node through the command in the
+environment variable @code{INFO_PRINT_COMMAND}. If the variable does not
+exist, the node is simply piped to @code{lpr}.
+@end table
+
+@node Miscellaneous Commands, Variables, Printing Nodes, Top
+@chapter Miscellaneous Commands
+
+GNU Info contains several commands which self-document GNU Info:
+
+@table @asis
+@item @code{M-x describe-command}
+@cindex functions, describing
+@cindex commands, describing
+@findex describe-command
+Read the name of an Info command in the echo area and then display a
+brief description of what that command does.
+
+@item @code{M-x describe-key}
+@cindex keys, describing
+@findex describe-key
+Read a key sequence in the echo area, and then display the name and
+documentation of the Info command that the key sequence invokes.
+
+@item @code{M-x describe-variable}
+Read the name of a variable in the echo area and then display a brief
+description of what the variable affects.
+
+@item @code{M-x where-is}
+@findex where-is
+Read the name of an Info command in the echo area, and then display
+a key sequence which can be typed in order to invoke that command.
+
+@item @code{C-h} (@code{get-help-window})
+@itemx @code{?}
+@kindex C-h
+@kindex ?, in Info windows
+@findex get-help-window
+Create (or Move into) the window displaying @code{*Help*}, and place
+a node containing a quick reference card into it. This window displays
+the most concise information about GNU Info available.
+
+@item @code{h} (@code{get-info-help-node})
+@kindex h
+@findex get-info-help-node
+Try hard to visit the node @code{(info)Help}. The Info file
+@file{info.texi} distributed with GNU Info contains this node. Of
+course, the file must first be processed with @code{makeinfo}, and then
+placed into the location of your Info directory.
+@end table
+
+Here are the commands for creating a numeric argument:
+
+@table @asis
+@item @code{C-u} (@code{universal-argument})
+@cindex numeric arguments
+@kindex C-u
+@findex universal-argument
+Start (or multiply by 4) the current numeric argument. @samp{C-u} is
+a good way to give a small numeric argument to cursor movement or
+scrolling commands; @samp{C-u C-v} scrolls the screen 4 lines, while
+@samp{C-u C-u C-n} moves the cursor down 16 lines.
+
+@item @code{M-1} (@code{add-digit-to-numeric-arg})
+@itemx @code{M-2} @dots{} @code{M-9}
+@kindex M-1 @dots{} M-9
+@findex add-digit-to-numeric-arg
+Add the digit value of the invoking key to the current numeric
+argument. Once Info is reading a numeric argument, you may just type
+the digits of the argument, without the Meta prefix. For example, you
+might give @samp{C-l} a numeric argument of 32 by typing:
+
+@example
+@kbd{C-u 3 2 C-l}
+@end example
+
+@noindent
+or
+
+@example
+@kbd{M-3 2 C-l}
+@end example
+@end table
+
+@samp{C-g} is used to abort the reading of a multi-character key
+sequence, to cancel lengthy operations (such as multi-file searches) and
+to cancel reading input in the echo area.
+
+@table @asis
+@item @code{C-g} (@code{abort-key})
+@cindex cancelling typeahead
+@cindex cancelling the current operation
+@kindex C-g, in Info windows
+@findex abort-key
+Cancel current operation.
+@end table
+
+The @samp{q} command of Info simply quits running Info.
+
+@table @asis
+@item @code{q} (@code{quit})
+@cindex quitting
+@kindex q
+@findex quit
+Exit GNU Info.
+@end table
+
+If the operating system tells GNU Info that the screen is 60 lines tall,
+and it is actually only 40 lines tall, here is a way to tell Info that
+the operating system is correct.
+
+@table @asis
+@item @code{M-x set-screen-height}
+@findex set-screen-height
+@cindex screen, changing the height of
+Read a height value in the echo area and set the height of the
+displayed screen to that value.
+@end table
+
+Finally, Info provides a convenient way to display footnotes which might
+be associated with the current node that you are viewing:
+
+@table @asis
+@item @code{ESC C-f} (@code{show-footnotes})
+@kindex ESC C-f
+@findex show-footnotes
+@cindex footnotes, displaying
+Show the footnotes (if any) associated with the current node in another
+window. You can have Info automatically display the footnotes
+associated with a node when the node is selected by setting the variable
+@code{automatic-footnotes}. @xref{Variables, , @code{automatic-footnotes}}.
+@end table
+
+@node Variables, GNU Info Global Index, Miscellaneous Commands, Top
+@chapter Manipulating Variables
+
+GNU Info contains several @dfn{variables} whose values are looked at by
+various Info commands. You can change the values of these variables,
+and thus change the behavior of Info to more closely match your
+environment and Info file reading manner.
+
+@table @asis
+@item @code{M-x set-variable}
+@cindex variables, setting
+@findex set-variable
+Read the name of a variable, and the value for it, in the echo area and
+then set the variable to that value. Completion is available when
+reading the variable name; often, completion is available when reading
+the value to give to the variable, but that depends on the variable
+itself. If a variable does @emph{not} supply multiple choices to
+complete over, it expects a numeric value.
+
+@item @code{M-x describe-variable}
+@cindex variables, describing
+@findex describe-variable
+Read the name of a variable in the echo area and then display a brief
+description of what the variable affects.
+@end table
+
+Here is a list of the variables that you can set in Info.
+
+@table @code
+@item automatic-footnotes
+@vindex automatic-footnotes
+When set to @code{On}, footnotes appear and disappear automatically.
+This variable is @code{On} by default. When a node is selected, a
+window containing the footnotes which appear in that node is created,
+and the footnotes are displayed within the new window. The window that
+Info creates to contain the footnotes is called @samp{*Footnotes*}. If
+a node is selected which contains no footnotes, and a @samp{*Footnotes*}
+window is on the screen, the @samp{*Footnotes*} window is deleted.
+Footnote windows created in this fashion are not automatically tiled so
+that they can use as little of the display as is possible.
+
+@item automatic-tiling
+@vindex automatic-tiling
+When set to @code{On}, creating or deleting a window resizes other
+windows. This variable is @code{Off} by default. Normally, typing
+@samp{C-x 2} divides the current window into two equal parts. When
+@code{automatic-tiling} is set to @code{On}, all of the windows are
+resized automatically, keeping an equal number of lines visible in each
+window. There are exceptions to the automatic tiling; specifically, the
+windows @samp{*Completions*} and @samp{*Footnotes*} are @emph{not}
+resized through automatic tiling; they remain their original size.
+
+@item visible-bell
+@vindex visible-bell
+When set to @code{On}, GNU Info attempts to flash the screen instead of
+ringing the bell. This variable is @code{Off} by default. Of course,
+Info can only flash the screen if the terminal allows it; in the case
+that the terminal does not allow it, the setting of this variable has no
+effect. However, you can make Info perform quietly by setting the
+@code{errors-ring-bell} variable to @code{Off}.
+
+@item errors-ring-bell
+@vindex errors-ring-bell
+When set to @code{On}, errors cause the bell to ring. The default
+setting of this variable is @code{On}.
+
+@item gc-compressed-files
+@vindex gc-compressed-files
+When set to @code{On}, Info garbage collects files which had to be
+uncompressed. The default value of this variable is @code{Off}.
+Whenever a node is visited in Info, the Info file containing that node
+is read into core, and Info reads information about the tags and nodes
+contained in that file. Once the tags information is read by Info, it
+is never forgotten. However, the actual text of the nodes does not need
+to remain in core unless a particular Info window needs it. For
+non-compressed files, the text of the nodes does not remain in core when
+it is no longer in use. But de-compressing a file can be a time
+consuming operation, and so Info tries hard not to do it twice.
+@code{gc-compressed-files} tells Info it is okay to garbage collect the
+text of the nodes of a file which was compressed on disk.
+
+@item show-index-match
+@vindex show-index-match
+When set to @code{On}, the portion of the matched search string is
+highlighted in the message which explains where the matched search
+string was found. The default value of this variable is @code{On}.
+When Info displays the location where an index match was found,
+(@pxref{Searching Commands, , @code{next-index-match}}), the portion of the
+string that you had typed is highlighted by displaying it in the inverse
+case from its surrounding characters.
+
+@item scroll-behavior
+@vindex scroll-behavior
+Control what happens when forward scrolling is requested at the end of
+a node, or when backward scrolling is requested at the beginning of a
+node. The default value for this variable is @code{Continuous}. There
+are three possible values for this variable:
+
+@table @code
+@item Continuous
+Try to get the first item in this node's menu, or failing that, the
+@samp{Next} node, or failing that, the @samp{Next} of the @samp{Up}.
+This behavior is identical to using the @samp{]}
+(@code{global-next-node}) and @samp{[} (@code{global-prev-node})
+commands.
+
+@item Next Only
+Only try to get the @samp{Next} node.
+
+@item Page Only
+Simply give up, changing nothing. If @code{scroll-behavior} is
+@code{Page Only}, no scrolling command can change the node that is being
+viewed.
+@end table
+
+@item scroll-step
+@vindex scroll-step
+The number of lines to scroll when the cursor moves out of the window.
+Scrolling happens automatically if the cursor has moved out of the
+visible portion of the node text when it is time to display. Usually
+the scrolling is done so as to put the cursor on the center line of the
+current window. However, if the variable @code{scroll-step} has a
+nonzero value, Info attempts to scroll the node text by that many lines;
+if that is enough to bring the cursor back into the window, that is what
+is done. The default value of this variable is 0, thus placing the
+cursor (and the text it is attached to) in the center of the window.
+Setting this variable to 1 causes a kind of "smooth scrolling" which
+some people prefer.
+
+@item ISO-Latin
+@cindex ISO Latin characters
+@vindex ISO-Latin
+When set to @code{On}, Info accepts and displays ISO Latin characters.
+By default, Info assumes an ASCII character set. @code{ISO-Latin} tells
+Info that it is running in an environment where the European standard
+character set is in use, and allows you to input such characters to
+Info, as well as display them.
+@end table
+
+
+
+@c the following is incomplete
+@ignore
+@c node Info for Sys Admins
+@c chapter Info for System Administrators
+
+This text describes some common ways of setting up an Info hierarchy
+from scratch, and details the various options that are available when
+installing Info. This text is designed for the person who is installing
+GNU Info on the system; although users may find the information present
+in this section interesting, none of it is vital to understanding how to
+use GNU Info.
+
+@menu
+* Setting the INFOPATH:: Where are my Info files kept?
+* Editing the DIR node:: What goes in `DIR', and why?
+* Storing Info files:: Alternate formats allow flexibility in setups.
+* Using `localdir':: Building DIR on the fly.
+* Example setups:: Some common ways to organize Info files.
+@end menu
+
+@c node Setting the INFOPATH
+@c section Setting the INFOPATH
+
+Where are my Info files kept?
+
+@c node Editing the DIR node
+@c section Editing the DIR node
+
+What goes in `DIR', and why?
+
+@c node Storing Info files
+@c section Storing Info files
+
+Alternate formats allow flexibility in setups.
+
+@c node Using `localdir'
+@c section Using `localdir'
+
+Building DIR on the fly.
+
+@c node Example setups
+@c section Example setups
+
+Some common ways to organize Info files.
+@end ignore
+
+@node GNU Info Global Index, , Variables, Top
+@appendix Global Index
+
+@printindex cp
+
+@contents
+@bye
diff --git a/contrib/texinfo/info/info-utils.c b/contrib/texinfo/info/info-utils.c
new file mode 100644
index 0000000..6af3dd0
--- /dev/null
+++ b/contrib/texinfo/info/info-utils.c
@@ -0,0 +1,672 @@
+/* info-utils.c -- Useful functions for manipulating Info file quirks. */
+
+/* This file is part of GNU Info, a program for reading online documentation
+ stored in Info format.
+
+ Copyright (C) 1993 Free Software Foundation, Inc.
+
+ 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Written by Brian Fox (bfox@ai.mit.edu). */
+
+#include <stdio.h> /* For "NULL". Yechhh! */
+#include <ctype.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#if defined (HAVE_STRING_H)
+# include <string.h>
+#endif /* HAVE_STRING_H */
+#include "info-utils.h"
+
+#if defined (HANDLE_MAN_PAGES)
+# include "man.h"
+#endif /* HANDLE_MAN_PAGES */
+
+/* When non-zero, various display and input functions handle ISO Latin
+ character sets correctly. */
+int ISO_Latin_p = 0;
+
+/* Variable which holds the most recent filename parsed as a result of
+ calling info_parse_xxx (). */
+char *info_parsed_filename = (char *)NULL;
+
+/* Variable which holds the most recent nodename parsed as a result of
+ calling info_parse_xxx (). */
+char *info_parsed_nodename = (char *)NULL;
+
+/* Functions to remember a filename or nodename for later return. */
+static void save_filename (), saven_filename ();
+static void save_nodename (), saven_nodename ();
+
+/* How to get a reference (either menu or cross). */
+static REFERENCE **info_references_internal ();
+
+/* Parse the filename and nodename out of STRING. If STRING doesn't
+ contain a filename (i.e., it is NOT (FILENAME)NODENAME) then set
+ INFO_PARSED_FILENAME to NULL. If second argument NEWLINES_OKAY is
+ non-zero, it says to allow the nodename specification to cross a
+ newline boundary (i.e., only `,', `.', or `TAB' can end the spec). */
+void
+info_parse_node (string, newlines_okay)
+ char *string;
+ int newlines_okay;
+{
+ register int i = 0;
+
+ /* Default the answer. */
+ save_filename ((char *)NULL);
+ save_nodename ((char *)NULL);
+
+ /* Special case of nothing passed. Return nothing. */
+ if (!string || !*string)
+ return;
+
+ string += skip_whitespace (string);
+
+ /* Check for (FILENAME)NODENAME. */
+ if (*string == '(')
+ {
+ i = 0;
+ /* Advance past the opening paren. */
+ string++;
+
+ /* Find the closing paren. */
+ while (string[i] && string[i] != ')')
+ i++;
+
+ /* Remember parsed filename. */
+ saven_filename (string, i);
+
+ /* Point directly at the nodename. */
+ string += i;
+
+ if (*string)
+ string++;
+ }
+
+ /* Parse out nodename. */
+ i = skip_node_characters (string, newlines_okay);
+ saven_nodename (string, i);
+ canonicalize_whitespace (info_parsed_nodename);
+ if (info_parsed_nodename && !*info_parsed_nodename)
+ {
+ free (info_parsed_nodename);
+ info_parsed_nodename = (char *)NULL;
+ }
+}
+
+/* Return the node addressed by LABEL in NODE (usually one of "Prev:",
+ "Next:", "Up:", "File:", or "Node:". After a call to this function,
+ the global INFO_PARSED_NODENAME and INFO_PARSED_FILENAME contain
+ the information. */
+void
+info_parse_label (label, node)
+ char *label;
+ NODE *node;
+{
+ register int i;
+ char *nodeline;
+
+ /* Default answer to failure. */
+ save_nodename ((char *)NULL);
+ save_filename ((char *)NULL);
+
+ /* Find the label in the first line of this node. */
+ nodeline = node->contents;
+ i = string_in_line (label, nodeline);
+
+ if (i == -1)
+ return;
+
+ nodeline += i;
+ nodeline += skip_whitespace (nodeline);
+ info_parse_node (nodeline, DONT_SKIP_NEWLINES);
+}
+
+/* **************************************************************** */
+/* */
+/* Finding and Building Menus */
+/* */
+/* **************************************************************** */
+
+/* Return a NULL terminated array of REFERENCE * which represents the menu
+ found in NODE. If there is no menu in NODE, just return a NULL pointer. */
+REFERENCE **
+info_menu_of_node (node)
+ NODE *node;
+{
+ long position;
+ SEARCH_BINDING search;
+ REFERENCE **menu = (REFERENCE **)NULL;
+
+ search.buffer = node->contents;
+ search.start = 0;
+ search.end = node->nodelen;
+ search.flags = S_FoldCase;
+
+ /* Find the start of the menu. */
+ position = search_forward (INFO_MENU_LABEL, &search);
+
+ if (position == -1)
+ return ((REFERENCE **) NULL);
+
+ /* We have the start of the menu now. Glean menu items from the rest
+ of the node. */
+ search.start = position + strlen (INFO_MENU_LABEL);
+ search.start += skip_line (search.buffer + search.start);
+ search.start--;
+ menu = info_menu_items (&search);
+ return (menu);
+}
+
+/* Return a NULL terminated array of REFERENCE * which represents the cross
+ refrences found in NODE. If there are no cross references in NODE, just
+ return a NULL pointer. */
+REFERENCE **
+info_xrefs_of_node (node)
+ NODE *node;
+{
+ SEARCH_BINDING search;
+
+#if defined (HANDLE_MAN_PAGES)
+ if (node->flags & N_IsManPage)
+ return (xrefs_of_manpage (node));
+#endif
+
+ search.buffer = node->contents;
+ search.start = 0;
+ search.end = node->nodelen;
+ search.flags = S_FoldCase;
+
+ return (info_xrefs (&search));
+}
+
+/* Glean menu entries from BINDING->buffer + BINDING->start until we
+ have looked at the entire contents of BINDING. Return an array
+ of REFERENCE * that represents each menu item in this range. */
+REFERENCE **
+info_menu_items (binding)
+ SEARCH_BINDING *binding;
+{
+ return (info_references_internal (INFO_MENU_ENTRY_LABEL, binding));
+}
+
+/* Glean cross references from BINDING->buffer + BINDING->start until
+ BINDING->end. Return an array of REFERENCE * that represents each
+ cross reference in this range. */
+REFERENCE **
+info_xrefs (binding)
+ SEARCH_BINDING *binding;
+{
+ return (info_references_internal (INFO_XREF_LABEL, binding));
+}
+
+/* Glean cross references or menu items from BINDING. Return an array
+ of REFERENCE * that represents the items found. */
+static REFERENCE **
+info_references_internal (label, binding)
+ char *label;
+ SEARCH_BINDING *binding;
+{
+ SEARCH_BINDING search;
+ REFERENCE **refs = (REFERENCE **)NULL;
+ int refs_index = 0, refs_slots = 0;
+ int searching_for_menu_items = 0;
+ long position;
+
+ search.buffer = binding->buffer;
+ search.start = binding->start;
+ search.end = binding->end;
+ search.flags = S_FoldCase | S_SkipDest;
+
+ searching_for_menu_items = (strcasecmp (label, INFO_MENU_ENTRY_LABEL) == 0);
+
+ while ((position = search_forward (label, &search)) != -1)
+ {
+ int offset, start;
+ char *refdef;
+ REFERENCE *entry;
+
+ search.start = position;
+ search.start += skip_whitespace (search.buffer + search.start);
+ start = search.start - binding->start;
+ refdef = search.buffer + search.start;
+ offset = string_in_line (":", refdef);
+
+ /* When searching for menu items, if no colon, there is no
+ menu item on this line. */
+ if (offset == -1)
+ {
+ if (searching_for_menu_items)
+ continue;
+ else
+ {
+ int temp;
+
+ temp = skip_line (refdef);
+ offset = string_in_line (":", refdef + temp);
+ if (offset == -1)
+ continue; /* Give up? */
+ else
+ offset += temp;
+ }
+ }
+
+ entry = (REFERENCE *)xmalloc (sizeof (REFERENCE));
+ entry->filename = (char *)NULL;
+ entry->nodename = (char *)NULL;
+ entry->label = (char *)xmalloc (offset);
+ strncpy (entry->label, refdef, offset - 1);
+ entry->label[offset - 1] = '\0';
+ canonicalize_whitespace (entry->label);
+
+ refdef += offset;
+ entry->start = start;
+ entry->end = refdef - binding->buffer;
+
+ /* If this reference entry continues with another ':' then the
+ nodename is the same as the label. */
+ if (*refdef == ':')
+ {
+ entry->nodename = strdup (entry->label);
+ }
+ else
+ {
+ /* This entry continues with a specific nodename. Parse the
+ nodename from the specification. */
+
+ refdef += skip_whitespace_and_newlines (refdef);
+
+ if (searching_for_menu_items)
+ info_parse_node (refdef, DONT_SKIP_NEWLINES);
+ else
+ info_parse_node (refdef, SKIP_NEWLINES);
+
+ if (info_parsed_filename)
+ entry->filename = strdup (info_parsed_filename);
+
+ if (info_parsed_nodename)
+ entry->nodename = strdup (info_parsed_nodename);
+ }
+
+ add_pointer_to_array
+ (entry, refs_index, refs, refs_slots, 50, REFERENCE *);
+ }
+ return (refs);
+}
+
+/* Get the entry associated with LABEL in MENU. Return a pointer to the
+ REFERENCE if found, or NULL. */
+REFERENCE *
+info_get_labeled_reference (label, references)
+ char *label;
+ REFERENCE **references;
+{
+ register int i;
+ REFERENCE *entry;
+
+ for (i = 0; references && (entry = references[i]); i++)
+ {
+ if (strcmp (label, entry->label) == 0)
+ return (entry);
+ }
+ return ((REFERENCE *)NULL);
+}
+
+/* A utility function for concatenating REFERENCE **. Returns a new
+ REFERENCE ** which is the concatenation of REF1 and REF2. The REF1
+ and REF2 arrays are freed, but their contents are not. */
+REFERENCE **
+info_concatenate_references (ref1, ref2)
+ REFERENCE **ref1, **ref2;
+{
+ register int i, j;
+ REFERENCE **result;
+ int size;
+
+ /* With one argument passed as NULL, simply return the other arg. */
+ if (!ref1)
+ return (ref2);
+ else if (!ref2)
+ return (ref1);
+
+ /* Get the total size of the slots that we will need. */
+ for (i = 0; ref1[i]; i++);
+ size = i;
+ for (i = 0; ref2[i]; i++);
+ size += i;
+
+ result = (REFERENCE **)xmalloc ((1 + size) * sizeof (REFERENCE *));
+
+ /* Copy the contents over. */
+ for (i = 0; ref1[i]; i++)
+ result[i] = ref1[i];
+
+ j = i;
+ for (i = 0; ref2[i]; i++)
+ result[j++] = ref2[i];
+
+ result[j] = (REFERENCE *)NULL;
+ free (ref1);
+ free (ref2);
+ return (result);
+}
+
+/* Free the data associated with REFERENCES. */
+void
+info_free_references (references)
+ REFERENCE **references;
+{
+ register int i;
+ REFERENCE *entry;
+
+ if (references)
+ {
+ for (i = 0; references && (entry = references[i]); i++)
+ {
+ maybe_free (entry->label);
+ maybe_free (entry->filename);
+ maybe_free (entry->nodename);
+
+ free (entry);
+ }
+
+ free (references);
+ }
+}
+
+/* Search for sequences of whitespace or newlines in STRING, replacing
+ all such sequences with just a single space. Remove whitespace from
+ start and end of string. */
+void
+canonicalize_whitespace (string)
+ char *string;
+{
+ register int i, j;
+ int len, whitespace_found, whitespace_loc;
+ char *temp;
+
+ if (!string)
+ return;
+
+ len = strlen (string);
+ temp = (char *)xmalloc (1 + len);
+
+ /* Search for sequences of whitespace or newlines. Replace all such
+ sequences in the string with just a single space. */
+
+ whitespace_found = 0;
+ for (i = 0, j = 0; string[i]; i++)
+ {
+ if (whitespace_or_newline (string[i]))
+ {
+ whitespace_found++;
+ whitespace_loc = i;
+ continue;
+ }
+ else
+ {
+ if (whitespace_found && whitespace_loc)
+ {
+ whitespace_found = 0;
+
+ /* Suppress whitespace at start of string. */
+ if (j)
+ temp[j++] = ' ';
+ }
+
+ temp[j++] = string[i];
+ }
+ }
+
+ /* Kill trailing whitespace. */
+ if (j && whitespace (temp[j - 1]))
+ j--;
+
+ temp[j] = '\0';
+ strcpy (string, temp);
+ free (temp);
+}
+
+/* String representation of a char returned by printed_representation (). */
+static char the_rep[10];
+
+/* Return a pointer to a string which is the printed representation
+ of CHARACTER if it were printed at HPOS. */
+char *
+printed_representation (character, hpos)
+ unsigned char character;
+ int hpos;
+{
+ register int i = 0;
+ int printable_limit;
+
+ if (ISO_Latin_p)
+ printable_limit = 160;
+ else
+ printable_limit = 127;
+
+ if (character == '\177')
+ {
+ the_rep[i++] = '^';
+ the_rep[i++] = '?';
+ }
+ else if (iscntrl (character))
+ {
+ switch (character)
+ {
+ case '\r':
+ case '\n':
+ the_rep[i++] = character;
+ break;
+
+ case '\t':
+ {
+ int tw;
+
+ tw = ((hpos + 8) & 0xf8) - hpos;
+ while (i < tw)
+ the_rep[i++] = ' ';
+ }
+ break;
+
+ default:
+ the_rep[i++] = '^';
+ the_rep[i++] = (character | 0x40);
+ }
+ }
+ else if (character > printable_limit)
+ {
+ sprintf (the_rep + i, "\\%0o", character);
+ i = strlen (the_rep);
+ }
+ else
+ the_rep[i++] = character;
+
+ the_rep[i] = '\0';
+
+ return (the_rep);
+}
+
+
+/* **************************************************************** */
+/* */
+/* Functions Static To This File */
+/* */
+/* **************************************************************** */
+
+/* Amount of space allocated to INFO_PARSED_FILENAME via xmalloc (). */
+static int parsed_filename_size = 0;
+
+/* Amount of space allocated to INFO_PARSED_NODENAME via xmalloc (). */
+static int parsed_nodename_size = 0;
+
+static void save_string (), saven_string ();
+
+/* Remember FILENAME in PARSED_FILENAME. An empty FILENAME is translated
+ to a NULL pointer in PARSED_FILENAME. */
+static void
+save_filename (filename)
+ char *filename;
+{
+ save_string (filename, &info_parsed_filename, &parsed_filename_size);
+}
+
+/* Just like save_filename (), but you pass the length of the string. */
+static void
+saven_filename (filename, len)
+ char *filename;
+ int len;
+{
+ saven_string (filename, len,
+ &info_parsed_filename, &parsed_filename_size);
+}
+
+/* Remember NODENAME in PARSED_NODENAME. An empty NODENAME is translated
+ to a NULL pointer in PARSED_NODENAME. */
+static void
+save_nodename (nodename)
+ char *nodename;
+{
+ save_string (nodename, &info_parsed_nodename, &parsed_nodename_size);
+}
+
+/* Just like save_nodename (), but you pass the length of the string. */
+static void
+saven_nodename (nodename, len)
+ char *nodename;
+ int len;
+{
+ saven_string (nodename, len,
+ &info_parsed_nodename, &parsed_nodename_size);
+}
+
+/* Remember STRING in STRING_P. STRING_P should currently have STRING_SIZE_P
+ bytes allocated to it. An empty STRING is translated to a NULL pointer
+ in STRING_P. */
+static void
+save_string (string, string_p, string_size_p)
+ char *string;
+ char **string_p;
+ int *string_size_p;
+{
+ if (!string || !*string)
+ {
+ if (*string_p)
+ free (*string_p);
+
+ *string_p = (char *)NULL;
+ *string_size_p = 0;
+ }
+ else
+ {
+ if (strlen (string) >= *string_size_p)
+ *string_p = (char *)xrealloc
+ (*string_p, (*string_size_p = 1 + strlen (string)));
+
+ strcpy (*string_p, string);
+ }
+}
+
+/* Just like save_string (), but you also pass the length of STRING. */
+static void
+saven_string (string, len, string_p, string_size_p)
+ char *string;
+ int len;
+ char **string_p;
+ int *string_size_p;
+{
+ if (!string)
+ {
+ if (*string_p)
+ free (*string_p);
+
+ *string_p = (char *)NULL;
+ *string_size_p = 0;
+ }
+ else
+ {
+ if (len >= *string_size_p)
+ *string_p = (char *)xrealloc (*string_p, (*string_size_p = 1 + len));
+
+ strncpy (*string_p, string, len);
+ (*string_p)[len] = '\0';
+ }
+}
+
+/* Return a pointer to the part of PATHNAME that simply defines the file. */
+char *
+filename_non_directory (pathname)
+ char *pathname;
+{
+ char *filename;
+
+ filename = (char *) strrchr (pathname, '/');
+
+ if (filename)
+ filename++;
+ else
+ filename = pathname;
+
+ return (filename);
+}
+
+/* Return non-zero if NODE is one especially created by Info. */
+int
+internal_info_node_p (node)
+ NODE *node;
+{
+#if defined (NEVER)
+ if (node &&
+ (node->filename && !*node->filename) &&
+ !node->parent && node->nodename)
+ return (1);
+ else
+ return (0);
+#else
+ return ((node != (NODE *)NULL) && ((node->flags & N_IsInternal) != 0));
+#endif /* !NEVER */
+}
+
+/* Make NODE appear to be one especially created by Info. */
+void
+name_internal_node (node, name)
+ NODE *node;
+ char *name;
+{
+ if (!node)
+ return;
+
+ node->filename = "";
+ node->parent = (char *)NULL;
+ node->nodename = name;
+ node->flags |= N_IsInternal;
+}
+
+/* Return the window displaying NAME, the name of an internally created
+ Info window. */
+WINDOW *
+get_internal_info_window (name)
+ char *name;
+{
+ WINDOW *win;
+
+ for (win = windows; win; win = win->next)
+ if (internal_info_node_p (win->node) &&
+ (strcmp (win->node->nodename, name) == 0))
+ break;
+
+ return (win);
+}
diff --git a/contrib/texinfo/info/info-utils.h b/contrib/texinfo/info/info-utils.h
new file mode 100644
index 0000000..e2627e1
--- /dev/null
+++ b/contrib/texinfo/info/info-utils.h
@@ -0,0 +1,140 @@
+/* info-utils.h -- Exported functions and variables from info-util.c.
+ $Id: info-utils.h,v 1.2 1996/10/02 22:24:11 karl Exp $
+
+ This file is part of GNU Info, a program for reading online documentation
+ stored in Info format.
+
+ Copyright (C) 1993, 96 Free Software Foundation, Inc.
+
+ 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Written by Brian Fox (bfox@ai.mit.edu). */
+
+#if !defined (_INFO_UTILS_H_)
+#define _INFO_UTILS_H_
+
+#if !defined (HAVE_STRCHR)
+# undef strchr
+# undef strrchr
+# define strchr index
+# define strrchr rindex
+#endif /* !HAVE_STRCHR */
+
+#include "nodes.h"
+#include "window.h"
+#include "search.h"
+
+/* Structure which describes a node reference, such as a menu entry or
+ cross reference. Arrays of such references can be built by calling
+ info_menus_of_node () or info_xrefs_of_node (). */
+typedef struct {
+ char *label; /* User Label. */
+ char *filename; /* File where this node can be found. */
+ char *nodename; /* Name of the node. */
+ int start, end; /* Offsets within the containing node of LABEL. */
+} REFERENCE;
+
+/* When non-zero, various display and input functions handle ISO Latin
+ character sets correctly. */
+extern int ISO_Latin_p;
+
+/* Variable which holds the most recent filename parsed as a result of
+ calling info_parse_xxx (). */
+extern char *info_parsed_filename;
+
+/* Variable which holds the most recent nodename parsed as a result of
+ calling info_parse_xxx (). */
+extern char *info_parsed_nodename;
+
+/* Parse the filename and nodename out of STRING. If STRING doesn't
+ contain a filename (i.e., it is NOT (FILENAME)NODENAME) then set
+ INFO_PARSED_FILENAME to NULL. If second argument NEWLINES_OKAY is
+ non-zero, it says to allow the nodename specification to cross a
+ newline boundary (i.e., only `,', `.', or `TAB' can end the spec). */
+void info_parse_node ();
+
+/* Return a NULL terminated array of REFERENCE * which represents the menu
+ found in NODE. If there is no menu in NODE, just return a NULL pointer. */
+extern REFERENCE **info_menu_of_node ();
+
+/* Return a NULL terminated array of REFERENCE * which represents the cross
+ refrences found in NODE. If there are no cross references in NODE, just
+ return a NULL pointer. */
+extern REFERENCE **info_xrefs_of_node ();
+
+/* Glean cross references from BINDING->buffer + BINDING->start until
+ BINDING->end. Return an array of REFERENCE * that represents each
+ cross reference in this range. */
+extern REFERENCE **info_xrefs ();
+
+/* Get the entry associated with LABEL in REFERENCES. Return a pointer to
+ the reference if found, or NULL. */
+extern REFERENCE *info_get_labeled_reference ();
+
+/* Glean menu entries from BINDING->buffer + BINDING->start until we
+ have looked at the entire contents of BINDING. Return an array
+ of REFERENCE * that represents each menu item in this range. */
+extern REFERENCE **info_menu_items ();
+
+/* A utility function for concatenating REFERENCE **. Returns a new
+ REFERENCE ** which is the concatenation of REF1 and REF2. The REF1
+ and REF2 arrays are freed, but their contents are not. */
+REFERENCE **info_concatenate_references ();
+
+/* Free the data associated with REFERENCES. */
+extern void info_free_references ();
+
+/* Search for sequences of whitespace or newlines in STRING, replacing
+ all such sequences with just a single space. Remove whitespace from
+ start and end of string. */
+void canonicalize_whitespace ();
+
+/* Return a pointer to a string which is the printed representation
+ of CHARACTER if it were printed at HPOS. */
+extern char *printed_representation ();
+
+/* Return a pointer to the part of PATHNAME that simply defines the file. */
+extern char *filename_non_directory ();
+
+/* Return non-zero if NODE is one especially created by Info. */
+extern int internal_info_node_p ();
+
+/* Make NODE appear to be one especially created by Info, and give it NAME. */
+extern void name_internal_node ();
+
+/* Return the window displaying NAME, the name of an internally created
+ Info window. */
+extern WINDOW *get_internal_info_window ();
+
+/* Return the node addressed by LABEL in NODE (usually one of "Prev:",
+ "Next:", "Up:", "File:", or "Node:". After a call to this function,
+ the global INFO_PARSED_NODENAME and INFO_PARSED_FILENAME contain
+ the information. */
+extern void info_parse_label (/* label, node */);
+
+#define info_label_was_found \
+ (info_parsed_nodename != NULL || info_parsed_filename != NULL)
+
+#define info_file_label_of_node(n) info_parse_label (INFO_FILE_LABEL, n)
+#define info_next_label_of_node(n) info_parse_label (INFO_NEXT_LABEL, n)
+#define info_up_label_of_node(n) info_parse_label (INFO_UP_LABEL, n)
+#define info_prev_label_of_node(n) \
+ do { \
+ info_parse_label (INFO_PREV_LABEL, n); \
+ if (!info_label_was_found) \
+ info_parse_label (INFO_ALTPREV_LABEL, n); \
+ } while (0)
+
+#endif /* !_INFO_UTILS_H_ */
diff --git a/contrib/texinfo/info/info.1 b/contrib/texinfo/info/info.1
new file mode 100644
index 0000000..f956873
--- /dev/null
+++ b/contrib/texinfo/info/info.1
@@ -0,0 +1,229 @@
+.TH info 1 "7th December 1990"
+.SH NAME
+info \- GNU's hypertext system
+.SH SYNOPSIS
+.B info
+[
+.B \-\-option-name option-value
+]
+.B \menu-item...
+.SH COPYRIGHT
+.if n Copyright (C) 1989, 1993 Free Software Foundation, Inc.
+.if t Copyright \(co 1989, 1993 Free Software Foundation, Inc.
+.SH DESCRIPTION
+.LP
+The GNU project has a hypertext system called
+.I Info
+which allows the same source file to be either printed as a
+paper manual, or viewed using
+.B info.
+It is possible to use the
+.B info
+program from inside Emacs, or to use the stand-alone version described here.
+This manual page gives a brief summary of its capabilities.
+
+.SH OPTIONS
+.TP
+.B \-\-directory directory-path
+Add
+.B directory-path
+to the list of directory paths searched when
+.B info
+needs to find a file. You may issue
+.B \-\-directory
+multiple times.
+Alternatively, you may specify a value for the environment variable
+.B INFOPATH;
+if
+.B \-\-directory
+is not given, the value of
+.B INFOPATH
+is used. The value of
+.B INFOPATH
+is a colon separated list of directory names. If you do not supply either
+.B INFOPATH
+or
+.B \-\-directory-path,
+.B info
+uses a default path.
+.TP
+.B \-f filename
+Specify a particular
+.B info
+file to visit. By default,
+.B info
+visits
+the file
+.B dir;
+if you use this option,
+.B info
+will start with
+.B (FILENAME)Top
+as the first file and node.
+.TP
+.B \-n nodename
+Specify a particular node to visit in the initial file that
+.B info
+loads. This is especially useful in conjunction with
+.B \-\-file.
+You may specify
+.B \-\-node
+multiple times.
+.TP
+.B -o file
+Direct output to
+.B file
+instead of starting an interactive
+.B info
+session.
+.TP
+.B \-h
+Produce a relatively brief description of the available
+.B info
+options.
+.TP
+.B \-\-version
+Print the version information of
+.B info
+and exit.
+.TP
+.B menu-item
+.B info
+treats its remaining arguments as the names of menu items.
+The first argument is a menu item in the initial node visited,
+while the second argument is a menu item in the first argument's
+node. You can easily move to the node of your choice by
+specifying the menu names which describe the path to that node.
+For example,
+
+.B info emacs buffers
+
+first selects the menu item
+.B emacs
+in the node
+.B (dir)Top,
+and then selects the menu item
+.B buffers
+in the node
+.B (emacs)Top.
+.SH COMMANDS
+When in
+.B info
+the following commands are available:
+.TP
+.B h
+Invoke the Info tutorial.
+.TP
+.B ?
+Get a short summary of
+.B info
+commands.
+.TP
+.B h
+Select the
+.B info
+node from the main directory; this is much more complete than just
+using
+.B ?.
+.TP
+.B Ctrl-g
+Abort whatever you are doing.
+.TP
+.B Ctrl-l
+Redraw the screen.
+.PP
+Selecting other nodes:
+.TP
+.B n
+Move to the "next" node of this node.
+.TP
+.B p
+Move to the "previous" node of this node.
+.TP
+.B u
+Move to this node's "up" node.
+.TP
+.B m
+Pick a menu item specified by name. Picking a menu item causes another
+node to be selected. You do not need to type a complete nodename; if
+you type a few letters and then a space or tab
+.B info
+will will try to fill in the rest of the nodename. If you ask for further
+completion without typing any more characters you'll be given a list
+of possibilities; you can also get the list with
+.B ?.
+If you type a few characters and then hit return
+.B info
+will try to do a completion, and if it is ambigous use the first possibility.
+.TP
+.B f
+Follow a cross reference. You are asked for the name of the reference,
+using command completion as for
+.B m.
+.TP
+.B l
+Move to the last node you were at.
+.PP
+Moving within a node:
+.TP
+.B Space
+Scroll forward a page.
+.TP
+.B DEL
+Scroll backward a page.
+.TP
+.B b
+Go to the beginning of this node.
+.PP
+Advanced commands:
+.TP
+.B q
+Quit
+.B info.
+.TP
+.B 1
+Pick first item in node's menu.
+.TP
+.B 2 \-\- 5
+Pick second ... fifth item in node's menu.
+.TP
+.B g
+Move to node specified by name. You may include a filename as well,
+as
+.B (FILENAME)NODENAME.
+.TP
+.B s
+Search through this
+.B info
+file for a specified string, and select the node in which
+the next occurrence is found.
+.TP
+.B M-x print-node
+Pipe the contents of the current node through the command in the
+environment variable
+.B INFO_PRINT_COMMAND.
+If the variable does not exist, the node is simply piped to
+.B lpr.
+.SH ENVIRONMENT
+.TP
+.B INFOPATH
+A colon-separated list of directories to search for
+.B info
+files. Used if
+.B \-\-directory
+is not given.
+.TP
+.B INFO_PRINT_COMMAND
+The command used for printing.
+.SH SEE ALSO
+.BR emacs (1)
+.SH AUTHOR
+.RS
+Brian Fox, Free Software Foundation
+.br
+bfox@ai.mit.edu
+.SH MANUAL AUTHOR
+.RS
+Robert Lupton; updated by Robert J. Chassell.
+.br
+rhl@astro.princeton.edu; bob@gnu.ai.mit.edu
diff --git a/contrib/texinfo/info/info.c b/contrib/texinfo/info/info.c
new file mode 100644
index 0000000..223df55
--- /dev/null
+++ b/contrib/texinfo/info/info.c
@@ -0,0 +1,565 @@
+/* info.c -- Display nodes of Info files in multiple windows. */
+
+/* This file is part of GNU Info, a program for reading online documentation
+ stored in Info format.
+
+ Copyright (C) 1993, 96 Free Software Foundation, Inc.
+
+ 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Written by Brian Fox (bfox@ai.mit.edu). */
+
+#include "info.h"
+#include "dribble.h"
+#include "getopt.h"
+#if defined (HANDLE_MAN_PAGES)
+# include "man.h"
+#endif /* HANDLE_MAN_PAGES */
+
+/* The version numbers of this version of Info. */
+int info_major_version = 2;
+int info_minor_version = 16;
+int info_patch_level = 0;
+
+/* Non-zero means search all indices for APROPOS_SEARCH_STRING. */
+static int apropos_p = 0;
+
+/* Variable containing the string to search for when apropos_p is non-zero. */
+static char *apropos_search_string = (char *)NULL;
+
+/* Non-zero means print version info only. */
+static int print_version_p = 0;
+
+/* Non-zero means print a short description of the options. */
+static int print_help_p = 0;
+
+/* Array of the names of nodes that the user specified with "--node" on the
+ command line. */
+static char **user_nodenames = (char **)NULL;
+static int user_nodenames_index = 0;
+static int user_nodenames_slots = 0;
+
+/* String specifying the first file to load. This string can only be set
+ by the user specifying "--file" on the command line. */
+static char *user_filename = (char *)NULL;
+
+/* String specifying the name of the file to dump nodes to. This value is
+ filled if the user speficies "--output" on the command line. */
+static char *user_output_filename = (char *)NULL;
+
+/* Non-zero indicates that when "--output" is specified, all of the menu
+ items of the specified nodes (and their subnodes as well) should be
+ dumped in the order encountered. This basically can print a book. */
+int dump_subnodes = 0;
+
+/* Structure describing the options that Info accepts. We pass this structure
+ to getopt_long (). If you add or otherwise change this structure, you must
+ also change the string which follows it. */
+#define APROPOS_OPTION 1
+#define DRIBBLE_OPTION 2
+#define RESTORE_OPTION 3
+static struct option long_options[] = {
+ { "apropos", 1, 0, APROPOS_OPTION },
+ { "directory", 1, 0, 'd' },
+ { "node", 1, 0, 'n' },
+ { "file", 1, 0, 'f' },
+ { "subnodes", 0, &dump_subnodes, 1 },
+ { "output", 1, 0, 'o' },
+ { "help", 0, &print_help_p, 1 },
+ { "version", 0, &print_version_p, 1 },
+ { "dribble", 1, 0, DRIBBLE_OPTION },
+ { "restore", 1, 0, RESTORE_OPTION },
+ {NULL, 0, NULL, 0}
+};
+
+/* String describing the shorthand versions of the long options found above. */
+static char *short_options = "d:n:f:o:s";
+
+/* When non-zero, the Info window system has been initialized. */
+int info_windows_initialized_p = 0;
+
+/* Some "forward" declarations. */
+static void usage (), info_short_help (), remember_info_program_name ();
+
+
+/* **************************************************************** */
+/* */
+/* Main Entry Point to the Info Program */
+/* */
+/* **************************************************************** */
+
+int
+main (argc, argv)
+ int argc;
+ char **argv;
+{
+ int getopt_long_index; /* Index returned by getopt_long (). */
+ NODE *initial_node; /* First node loaded by Info. */
+
+ remember_info_program_name (argv[0]);
+
+ while (1)
+ {
+ int option_character;
+
+ option_character = getopt_long
+ (argc, argv, short_options, long_options, &getopt_long_index);
+
+ /* getopt_long () returns EOF when there are no more long options. */
+ if (option_character == EOF)
+ break;
+
+ /* If this is a long option, then get the short version of it. */
+ if (option_character == 0 && long_options[getopt_long_index].flag == 0)
+ option_character = long_options[getopt_long_index].val;
+
+ /* Case on the option that we have received. */
+ switch (option_character)
+ {
+ case 0:
+ break;
+
+ /* User wants to add a directory. */
+ case 'd':
+ info_add_path (optarg, INFOPATH_PREPEND);
+ break;
+
+ /* User is specifying a particular node. */
+ case 'n':
+ add_pointer_to_array (optarg, user_nodenames_index, user_nodenames,
+ user_nodenames_slots, 10, char *);
+ break;
+
+ /* User is specifying a particular Info file. */
+ case 'f':
+ if (user_filename)
+ free (user_filename);
+
+ user_filename = strdup (optarg);
+ break;
+
+ /* User is specifying the name of a file to output to. */
+ case 'o':
+ if (user_output_filename)
+ free (user_output_filename);
+ user_output_filename = strdup (optarg);
+ break;
+
+ /* User is specifying that she wishes to dump the subnodes of
+ the node that she is dumping. */
+ case 's':
+ dump_subnodes = 1;
+ break;
+
+ /* User has specified a string to search all indices for. */
+ case APROPOS_OPTION:
+ apropos_p = 1;
+ maybe_free (apropos_search_string);
+ apropos_search_string = strdup (optarg);
+ break;
+
+ /* User has specified a dribble file to receive keystrokes. */
+ case DRIBBLE_OPTION:
+ close_dribble_file ();
+ open_dribble_file (optarg);
+ break;
+
+ /* User has specified an alternate input stream. */
+ case RESTORE_OPTION:
+ info_set_input_from_file (optarg);
+ break;
+
+ default:
+ usage ();
+ }
+ }
+
+ /* If the output device is not a terminal, and no output filename has been
+ specified, make user_output_filename be "-", so that the info is written
+ to stdout, and turn on the dumping of subnodes. */
+ if ((!isatty (fileno (stdout))) && (user_output_filename == (char *)NULL))
+ {
+ user_output_filename = strdup ("-");
+ dump_subnodes = 1;
+ }
+
+ /* If the user specified --version, then show the version and exit. */
+ if (print_version_p)
+ {
+ printf ("GNU Info (Texinfo 3.9) %s\n", version_string ());
+ puts ("Copyright (C) 1996 Free Software Foundation, Inc.\n\
+There is NO warranty. You may redistribute this software\n\
+under the terms of the GNU General Public License.\n\
+For more information about these matters, see the files named COPYING.");
+ exit (0);
+ }
+
+ /* If the `--help' option was present, show the help and exit. */
+ if (print_help_p)
+ {
+ info_short_help ();
+ exit (0);
+ }
+
+ /* If the user hasn't specified a path for Info files, default that path
+ now. */
+ if (!infopath)
+ {
+ char *path_from_env, *getenv ();
+
+ path_from_env = getenv ("INFOPATH");
+
+ if (path_from_env)
+ info_add_path (path_from_env, INFOPATH_PREPEND);
+ else
+ info_add_path (DEFAULT_INFOPATH, INFOPATH_PREPEND);
+ }
+
+ /* If the user specified a particular filename, add the path of that
+ file to the contents of INFOPATH. */
+ if (user_filename)
+ {
+ char *directory_name, *temp;
+
+ directory_name = strdup (user_filename);
+ temp = filename_non_directory (directory_name);
+
+ if (temp != directory_name)
+ {
+ *temp = 0;
+ info_add_path (directory_name, INFOPATH_PREPEND);
+ }
+
+ free (directory_name);
+ }
+
+ /* If the user wants to search every known index for a given string,
+ do that now, and report the results. */
+ if (apropos_p)
+ {
+ info_apropos (apropos_search_string);
+ exit (0);
+ }
+
+ /* Get the initial Info node. It is either "(dir)Top", or what the user
+ specifed with values in user_filename and user_nodenames. */
+ if (user_nodenames)
+ initial_node = info_get_node (user_filename, user_nodenames[0]);
+ else
+ initial_node = info_get_node (user_filename, (char *)NULL);
+
+ /* If we couldn't get the initial node, this user is in trouble. */
+ if (!initial_node)
+ {
+ if (info_recent_file_error)
+ info_error (info_recent_file_error);
+ else
+ info_error
+ (CANT_FIND_NODE, user_nodenames ? user_nodenames[0] : "Top");
+ exit (1);
+ }
+
+ /* Special cases for when the user specifies multiple nodes. If we are
+ dumping to an output file, dump all of the nodes specified. Otherwise,
+ attempt to create enough windows to handle the nodes that this user wants
+ displayed. */
+ if (user_nodenames_index > 1)
+ {
+ free (initial_node);
+
+ if (user_output_filename)
+ dump_nodes_to_file
+ (user_filename, user_nodenames, user_output_filename, dump_subnodes);
+ else
+ begin_multiple_window_info_session (user_filename, user_nodenames);
+
+ exit (0);
+ }
+
+ /* If there are arguments remaining, they are the names of menu items
+ in sequential info files starting from the first one loaded. That
+ file name is either "dir", or the contents of user_filename if one
+ was specified. */
+ while (optind != argc)
+ {
+ REFERENCE **menu;
+ REFERENCE *entry;
+ NODE *node;
+ char *arg;
+ static char *first_arg = (char *)NULL;
+
+ /* Remember the name of the menu entry we want. */
+ arg = argv[optind++];
+
+ if (first_arg == (char *)NULL)
+ first_arg = arg;
+
+ /* Build and return a list of the menu items in this node. */
+ menu = info_menu_of_node (initial_node);
+
+ /* If there wasn't a menu item in this node, stop here, but let
+ the user continue to use Info. Perhaps they wanted this node
+ and didn't realize it. */
+ if (!menu)
+ {
+#if defined (HANDLE_MAN_PAGES)
+ if (first_arg == arg)
+ {
+ node = make_manpage_node (first_arg);
+ if (node)
+ goto maybe_got_node;
+ }
+#endif /* HANDLE_MAN_PAGES */
+ begin_info_session_with_error
+ (initial_node, "There is no menu in this node.");
+ exit (0);
+ }
+
+ /* Find the specified menu item. */
+ entry = info_get_labeled_reference (arg, menu);
+
+ /* If the item wasn't found, search the list sloppily. Perhaps this
+ user typed "buffer" when they really meant "Buffers". */
+ if (!entry)
+ {
+ register int i;
+ int best_guess = -1;
+
+ for (i = 0; entry = menu[i]; i++)
+ {
+ if (strcasecmp (entry->label, arg) == 0)
+ break;
+ else
+ if (strncasecmp (entry->label, arg, strlen (arg)) == 0)
+ best_guess = i;
+ }
+
+ if (!entry && best_guess != -1)
+ entry = menu[best_guess];
+ }
+
+ /* If we failed to find the reference, start Info with the current
+ node anyway. It is probably a misspelling. */
+ if (!entry)
+ {
+ char *error_message = "There is no menu item \"%s\" in this node.";
+
+#if defined (HANDLE_MAN_PAGES)
+ if (first_arg == arg)
+ {
+ node = make_manpage_node (first_arg);
+ if (node)
+ goto maybe_got_node;
+ }
+#endif /* HANDLE_MAN_PAGES */
+
+ info_free_references (menu);
+
+ /* If we were supposed to dump this node, complain. */
+ if (user_output_filename)
+ info_error (error_message, arg);
+ else
+ begin_info_session_with_error (initial_node, error_message, arg);
+
+ exit (0);
+ }
+
+ /* We have found the reference that the user specified. Clean it
+ up a little bit. */
+ if (!entry->filename)
+ {
+ if (initial_node->parent)
+ entry->filename = strdup (initial_node->parent);
+ else
+ entry->filename = strdup (initial_node->filename);
+ }
+
+ /* Find this node. If we can find it, then turn the initial_node
+ into this one. If we cannot find it, try using the label of the
+ entry as a file (i.e., "(LABEL)Top"). Otherwise the Info file is
+ malformed in some way, and we will just use the current value of
+ initial node. */
+ node = info_get_node (entry->filename, entry->nodename);
+
+#if defined (HANDLE_MAN_PAGES)
+ if ((first_arg == arg) && !node)
+ {
+ node = make_manpage_node (first_arg);
+ if (node)
+ goto maybe_got_node;
+ }
+#endif /* HANDLE_MAN_PAGES */
+
+ if (!node && entry->nodename &&
+ (strcmp (entry->label, entry->nodename) == 0))
+ node = info_get_node (entry->label, "Top");
+
+ maybe_got_node:
+ if (node)
+ {
+ free (initial_node);
+ initial_node = node;
+ info_free_references (menu);
+ }
+ else
+ {
+ char *temp = strdup (entry->label);
+ char *error_message;
+
+ error_message = "Unable to find the node referenced by \"%s\".";
+
+ info_free_references (menu);
+
+ /* If we were trying to dump the node, then give up. Otherwise,
+ start the session with an error message. */
+ if (user_output_filename)
+ info_error (error_message, temp);
+ else
+ begin_info_session_with_error (initial_node, error_message, temp);
+
+ exit (0);
+ }
+ }
+
+ /* If the user specified that this node should be output, then do that
+ now. Otherwise, start the Info session with this node. */
+ if (user_output_filename)
+ dump_node_to_file (initial_node, user_output_filename, dump_subnodes);
+ else
+ begin_info_session (initial_node);
+
+ exit (0);
+}
+
+/* Return a string describing the current version of Info. */
+char *
+version_string ()
+{
+ static char *vstring = (char *)NULL;
+
+ if (!vstring)
+ {
+ vstring = (char *)xmalloc (50);
+ sprintf (vstring, "%d.%d", info_major_version, info_minor_version);
+ if (info_patch_level)
+ sprintf (vstring + strlen (vstring), "-p%d", info_patch_level);
+ }
+ return (vstring);
+}
+
+/* **************************************************************** */
+/* */
+/* Error Handling for Info */
+/* */
+/* **************************************************************** */
+
+static char *program_name = (char *)NULL;
+
+static void
+remember_info_program_name (fullpath)
+ char *fullpath;
+{
+ char *filename;
+
+ filename = filename_non_directory (fullpath);
+ program_name = strdup (filename);
+}
+
+/* Non-zero if an error has been signalled. */
+int info_error_was_printed = 0;
+
+/* Non-zero means ring terminal bell on errors. */
+int info_error_rings_bell_p = 1;
+
+/* Print FORMAT with ARG1 and ARG2. If the window system was initialized,
+ then the message is printed in the echo area. Otherwise, a message is
+ output to stderr. */
+void
+info_error (format, arg1, arg2)
+ char *format;
+ void *arg1, *arg2;
+{
+ info_error_was_printed = 1;
+
+ if (!info_windows_initialized_p || display_inhibited)
+ {
+ fprintf (stderr, "%s: ", program_name);
+ fprintf (stderr, format, arg1, arg2);
+ fprintf (stderr, "\n");
+ fflush (stderr);
+ }
+ else
+ {
+ if (!echo_area_is_active)
+ {
+ if (info_error_rings_bell_p)
+ terminal_ring_bell ();
+ window_message_in_echo_area (format, arg1, arg2);
+ }
+ else
+ {
+ NODE *temp;
+
+ temp = build_message_node (format, arg1, arg2);
+ if (info_error_rings_bell_p)
+ terminal_ring_bell ();
+ inform_in_echo_area (temp->contents);
+ free (temp->contents);
+ free (temp);
+ }
+ }
+}
+
+/* Produce a very brief descripton of the available options and exit with
+ an error. */
+static void
+usage ()
+{
+ fprintf (stderr,"%s\n%s\n%s\n%s\n%s\n",
+"Usage: info [-d dir-path] [-f info-file] [-o output-file] [-n node-name]...",
+" [--directory dir-path] [--file info-file] [--node node-name]...",
+" [--help] [--output output-file] [--subnodes] [--version]",
+" [--dribble dribble-file] [--restore from-file]",
+" [menu-selection ...]");
+ exit (1);
+}
+
+/* Produce a scaled down description of the available options to Info. */
+static void
+info_short_help ()
+{
+ puts ("\
+Here is a quick description of Info's options. For a more complete\n\
+description of how to use Info, type `info info options'.\n\
+\n\
+ --directory DIR Add DIR to INFOPATH.\n\
+ --dribble FILENAME Remember user keystrokes in FILENAME.\n\
+ --file FILENAME Specify Info file to visit.\n\
+ --node NODENAME Specify nodes in first visited Info file.\n\
+ --output FILENAME Output selected nodes to FILENAME.\n\
+ --restore FILENAME Read initial keystrokes from FILENAME.\n\
+ --subnodes Recursively output menu items.\n\
+ --help Get this help message.\n\
+ --version Display Info's version information.\n\
+\n\
+Remaining arguments to Info are treated as the names of menu\n\
+items in the initial node visited. You can easily move to the\n\
+node of your choice by specifying the menu names which describe\n\
+the path to that node. For example, `info emacs buffers'.\n\
+\n\
+Email bug reports to bug-texinfo@prep.ai.mit.edu.");
+
+ exit (0);
+}
diff --git a/contrib/texinfo/info/info.h b/contrib/texinfo/info/info.h
new file mode 100644
index 0000000..a875922
--- /dev/null
+++ b/contrib/texinfo/info/info.h
@@ -0,0 +1,100 @@
+/* info.h -- Header file which includes all of the other headers. */
+
+/* This file is part of GNU Info, a program for reading online documentation
+ stored in Info format.
+
+ Copyright (C) 1993 Free Software Foundation, Inc.
+
+ 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Written by Brian Fox (bfox@ai.mit.edu). */
+
+#if !defined (_INFO_H_)
+#define _INFO_H_
+
+#include <stdio.h>
+#include <ctype.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#if defined (HAVE_STRING_H)
+#include <string.h>
+#endif /* HAVE_STRING_H */
+#include "filesys.h"
+#include "display.h"
+#include "session.h"
+#include "echo_area.h"
+#include "doc.h"
+#include "footnotes.h"
+#include "gc.h"
+
+/* A structure associating the nodes visited in a particular window. */
+typedef struct {
+ WINDOW *window; /* The window that this list is attached to. */
+ NODE **nodes; /* Array of nodes visited in this window. */
+ int *pagetops; /* For each node in NODES, the pagetop. */
+ long *points; /* For each node in NODES, the point. */
+ int current; /* Index in NODES of the current node. */
+ int nodes_index; /* Index where to add the next node. */
+ int nodes_slots; /* Number of slots allocated to NODES. */
+} INFO_WINDOW;
+
+/* Array of structures describing for each window which nodes have been
+ visited in that window. */
+extern INFO_WINDOW **info_windows;
+
+/* For handling errors. If you initialize the window system, you should
+ also set info_windows_initialized_p to non-zero. It is used by the
+ info_error () function to determine how to format and output errors. */
+extern int info_windows_initialized_p;
+
+/* Non-zero if an error message has been printed. */
+extern int info_error_was_printed;
+
+/* Non-zero means ring terminal bell on errors. */
+extern int info_error_rings_bell_p;
+
+/* Print FORMAT with ARG1 and ARG2. If the window system was initialized,
+ then the message is printed in the echo area. Otherwise, a message is
+ output to stderr. */
+extern void info_error ();
+
+/* The version numbers of Info. */
+extern int info_major_version, info_minor_version, info_patch_level;
+
+/* How to get the version string for this version of Info. Returns
+ something similar to "2.11". */
+extern char *version_string ();
+
+/* Error message defines. */
+#define CANT_FIND_NODE "Cannot find the node \"%s\"."
+#define CANT_FILE_NODE "Cannot find the node \"(%s)%s\"."
+#define CANT_FIND_WIND "Cannot find a window!"
+#define CANT_FIND_POINT "Point doesn't appear within this window's node!"
+#define CANT_KILL_LAST "Cannot delete the last window."
+#define NO_MENU_NODE "No menu in this node."
+#define NO_FOOT_NODE "No footnotes in this node."
+#define NO_XREF_NODE "No cross references in this node."
+#define NO_POINTER "No \"%s\" pointer for this node."
+#define UNKNOWN_COMMAND "Unknown Info command `%c'. `?' for help."
+#define TERM_TOO_DUMB "Terminal type \"%s\" is not smart enough to run Info."
+#define AT_NODE_BOTTOM "You are already at the last page of this node."
+#define AT_NODE_TOP "You are already at the first page of this node."
+#define ONE_WINDOW "Only one window."
+#define WIN_TOO_SMALL "Resulting window would be too small."
+#define CANT_MAKE_HELP \
+"There isn't enough room to make a help window. Please delete a window."
+
+#endif /* !_INFO_H_ */
+
diff --git a/contrib/texinfo/info/info.texi b/contrib/texinfo/info/info.texi
new file mode 100644
index 0000000..cfdf782
--- /dev/null
+++ b/contrib/texinfo/info/info.texi
@@ -0,0 +1,916 @@
+\input texinfo @c -*-texinfo-*-
+@comment %**start of header
+@setfilename info.info
+@settitle Info 1.0
+@comment %**end of header
+@comment $Id: info.texi,v 1.5 1996/09/29 16:58:42 karl Exp $
+
+@dircategory Texinfo documentation system
+@direntry
+* Info: (info). Documentation browsing system.
+@end direntry
+
+@ifinfo
+This file describes how to use Info,
+the on-line, menu-driven GNU documentation system.
+
+Copyright (C) 1989, 92, 96 Free Software Foundation, Inc.
+
+Permission is granted to make and distribute verbatim copies of
+this manual provided the copyright notice and this permission notice
+are preserved on all copies.
+
+@ignore
+Permission is granted to process this file through TeX and print the
+results, provided the printed document carries copying permission
+notice identical to this one except for the removal of this paragraph
+(this paragraph not being relevant to the printed manual).
+
+@end ignore
+Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, provided that the entire
+resulting derived work is distributed under the terms of a permission
+notice identical to this one.
+
+Permission is granted to copy and distribute translations of this manual
+into another language, under the above conditions for modified versions,
+except that this permission notice may be stated in a translation approved
+by the Free Software Foundation.
+@end ifinfo
+
+@titlepage
+@sp 11
+@center @titlefont{Info}
+@sp 2
+@center The
+@sp 2
+@center On-line, Menu-driven
+@sp 2
+@center GNU Documentation System
+
+@page
+@vskip 0pt plus 1filll
+Copyright @copyright{} 1989, 1992, 1993 Free Software Foundation, Inc.
+@sp 2
+
+Published by the Free Software Foundation @*
+59 Temple Place - Suite 330 @*
+Boston, MA 02111-1307, USA.
+
+Permission is granted to make and distribute verbatim copies of
+this manual provided the copyright notice and this permission notice
+are preserved on all copies.
+
+Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, provided that the entire
+resulting derived work is distributed under the terms of a permission
+notice identical to this one.
+
+Permission is granted to copy and distribute translations of this manual
+into another language, under the above conditions for modified versions,
+except that this permission notice may be stated in a translation approved
+by the Free Software Foundation.
+@end titlepage
+
+@ifinfo
+@node Top, Getting Started, (dir), (dir)
+@top Info: An Introduction
+
+Info is a program for reading documentation, which you are using now.
+
+To learn how to use Info, type the command @kbd{h}. It brings you
+to a programmed instruction sequence.
+
+@c Need to make sure that `Info-help' goes to the right node,
+@c which is the first node of the first chapter. (It should.)
+@c (Info-find-node "info"
+@c (if (< (window-height) 23)
+@c "Help-Small-Screen"
+@c "Help")))
+
+To learn advanced Info commands, type @kbd{n} twice. This brings you to
+@cite{Info for Experts}, skipping over the `Getting Started' chapter.
+@end ifinfo
+
+@menu
+* Getting Started:: Getting started using an Info reader.
+* Advanced Info:: Advanced commands within Info.
+* Create an Info File:: How to make your own Info file.
+* The Standalone Info Program: (info-stnd.info).
+@end menu
+
+@node Getting Started, Advanced Info, Top, Top
+@comment node-name, next, previous, up
+@chapter Getting Started
+
+This first part of the Info manual describes how to get around inside
+of Info. The second part of the manual describes various advanced
+Info commands, and how to write an Info as distinct from a Texinfo
+file. The third part is about how to generate Info files from
+Texinfo files.
+
+@iftex
+This manual is primarily designed for use on a computer, so that you can
+try Info commands while reading about them. Reading it on paper is less
+effective, since you must take it on faith that the commands described
+really do what the manual says. By all means go through this manual now
+that you have it; but please try going through the on-line version as
+well.
+
+There are two ways of looking at the online version of this manual:
+
+@enumerate
+@item
+Type @code{info} at your shell's command line. This approach uses a
+small stand-alone program designed just to read Info files.
+
+@item
+Type @code{emacs} at the command line; then type @kbd{C-h i} (Control
+@kbd{h}, followed by @kbd{i}). This approach uses the Info mode of the
+Emacs program, an editor with many other capabilities.
+@end enumerate
+
+In either case, then type @kbd{mInfo} (just the letters), followed by
+@key{RET}---the ``Return'' or ``Enter'' key. At this point, you should
+be ready to follow the instructions in this manual as you read them on
+the screen.
+@c FIXME! (pesch@cygnus.com, 14 dec 1992)
+@c Is it worth worrying about what-if the beginner goes to somebody
+@c else's Emacs session, which already has an Info running in the middle
+@c of something---in which case these simple instructions won't work?
+@end iftex
+
+@menu
+* Help-Small-Screen:: Starting Info on a Small Screen
+* Help:: How to use Info
+* Help-P:: Returning to the Previous node
+* Help-^L:: The Space, Rubout, B and ^L commands.
+* Help-M:: Menus
+* Help-Adv:: Some advanced Info commands
+* Help-Q:: Quitting Info
+@end menu
+
+@node Help-Small-Screen, Help, , Getting Started
+@comment node-name, next, previous, up
+@section Starting Info on a Small Screen
+
+@iftex
+(In Info, you only see this section if your terminal has a small
+number of lines; most readers pass by it without seeing it.)
+@end iftex
+
+Since your terminal has an unusually small number of lines on its
+screen, it is necessary to give you special advice at the beginning.
+
+If you see the text @samp{--All----} at near the bottom right corner
+of the screen, it means the entire text you are looking at fits on the
+screen. If you see @samp{--Top----} instead, it means that there is
+more text below that does not fit. To move forward through the text
+and see another screen full, press the Space bar, @key{SPC}. To move
+back up, press the key labeled @samp{Backspace} or @key{Delete}.
+
+@ifinfo
+Here are 40 lines of junk, so you can try Spaces and Deletes and
+see what they do. At the end are instructions of what you should do
+next.
+
+This is line 17 @*
+This is line 18 @*
+This is line 19 @*
+This is line 20 @*
+This is line 21 @*
+This is line 22 @*
+This is line 23 @*
+This is line 24 @*
+This is line 25 @*
+This is line 26 @*
+This is line 27 @*
+This is line 28 @*
+This is line 29 @*
+This is line 30 @*
+This is line 31 @*
+This is line 32 @*
+This is line 33 @*
+This is line 34 @*
+This is line 35 @*
+This is line 36 @*
+This is line 37 @*
+This is line 38 @*
+This is line 39 @*
+This is line 40 @*
+This is line 41 @*
+This is line 42 @*
+This is line 43 @*
+This is line 44 @*
+This is line 45 @*
+This is line 46 @*
+This is line 47 @*
+This is line 48 @*
+This is line 49 @*
+This is line 50 @*
+This is line 51 @*
+This is line 52 @*
+This is line 53 @*
+This is line 54 @*
+This is line 55 @*
+This is line 56 @*
+
+If you have managed to get here, go back to the beginning with
+Delete, and come back here again, then you understand Space and
+Delete. So now type an @kbd{n} ---just one character; don't type
+the quotes and don't type the Return key afterward--- to
+get to the normal start of the course.
+@end ifinfo
+
+@node Help, Help-P, Help-Small-Screen, Getting Started
+@comment node-name, next, previous, up
+@section How to use Info
+
+You are talking to the program Info, for reading documentation.
+
+ Right now you are looking at one @dfn{Node} of Information.
+A node contains text describing a specific topic at a specific
+level of detail. This node's topic is ``how to use Info''.
+
+ The top line of a node is its @dfn{header}. This node's header (look at
+it now) says that it is the node named @samp{Help} in the file
+@file{info}. It says that the @samp{Next} node after this one is the node
+called @samp{Help-P}. An advanced Info command lets you go to any node
+whose name you know.
+
+ Besides a @samp{Next}, a node can have a @samp{Previous} or an @samp{Up}.
+This node has a @samp{Previous} but no @samp{Up}, as you can see.
+
+ Now it is time to move on to the @samp{Next} node, named @samp{Help-P}.
+
+>> Type @samp{n} to move there. Type just one character;
+ do not type the quotes and do not type a @key{RET} afterward.
+
+@samp{>>} in the margin means it is really time to try a command.
+
+@node Help-P, Help-^L, Help, Getting Started
+@comment node-name, next, previous, up
+@section Returning to the Previous node
+
+This node is called @samp{Help-P}. The @samp{Previous} node, as you see,
+is @samp{Help}, which is the one you just came from using the @kbd{n}
+command. Another @kbd{n} command now would take you to the next
+node, @samp{Help-^L}.
+
+>> But do not do that yet. First, try the @kbd{p} command, which takes
+ you to the @samp{Previous} node. When you get there, you can do an
+ @kbd{n} again to return here.
+
+ This all probably seems insultingly simple so far, but @emph{do not} be
+led into skimming. Things will get more complicated soon. Also,
+do not try a new command until you are told it is time to. Otherwise,
+you may make Info skip past an important warning that was coming up.
+
+>> Now do an @kbd{n} to get to the node @samp{Help-^L} and learn more.
+
+@node Help-^L, Help-M, Help-P, Getting Started
+@comment node-name, next, previous, up
+@section The Space, Delete, B and ^L commands.
+
+ This node's header tells you that you are now at node @samp{Help-^L}, and
+that @kbd{p} would get you back to @samp{Help-P}. The node's title is
+underlined; it says what the node is about (most nodes have titles).
+
+ This is a big node and it does not all fit on your display screen.
+You can tell that there is more that is not visible because you
+can see the string @samp{--Top-----} rather than @samp{--All----} near
+the bottom right corner of the screen.
+
+ The Space, Delete and @kbd{B} commands exist to allow you to ``move
+around'' in a node that does not all fit on the screen at once.
+Space moves forward, to show what was below the bottom of the screen.
+Delete moves backward, to show what was above the top of the screen
+(there is not anything above the top until you have typed some spaces).
+
+>> Now try typing a Space (afterward, type a Delete to return here).
+
+ When you type the space, the two lines that were at the bottom of
+the screen appear at the top, followed by more lines. Delete takes
+the two lines from the top and moves them to the bottom,
+@emph{usually}, but if there are not a full screen's worth of lines
+above them they may not make it all the way to the bottom.
+
+ If you type Space when there is no more to see, it rings the
+bell and otherwise does nothing. The same goes for Delete when
+the header of the node is visible.
+
+ If your screen is ever garbaged, you can tell Info to print it out
+again by typing @kbd{C-l} (@kbd{Control-L}, that is---hold down ``Control'' and
+type an @key{L} or @kbd{l}).
+
+>> Type @kbd{C-l} now.
+
+ To move back to the beginning of the node you are on, you can type
+a lot of Deletes. You can also type simply @kbd{b} for beginning.
+>> Try that now. (We have put in enough verbiage to push this past
+the first screenful, but screens are so big nowadays that perhaps it
+isn't enough. You may need to shrink your Emacs or Info window.)
+Then come back, with Spaces.
+
+ If your screen is very tall, all of this node might fit at once.
+In that case, "b" won't do anything. Sorry; what can we do?
+
+ You have just learned a considerable number of commands. If you
+want to use one but have trouble remembering which, you should type
+a @key{?} which prints out a brief list of commands. When you are
+finished looking at the list, make it go away by typing a @key{SPC}.
+
+>> Type a @key{?} now. After it finishes, type a @key{SPC}.
+
+ (If you are using the standalone Info reader, type `l' to return here.)
+
+ From now on, you will encounter large nodes without warning, and
+will be expected to know how to use Space and Delete to move
+around in them without being told. Since not all terminals have
+the same size screen, it would be impossible to warn you anyway.
+
+>> Now type @kbd{n} to see the description of the @kbd{m} command.
+
+@node Help-M, Help-Adv, Help-^L, Getting Started
+@comment node-name, next, previous, up
+@section Menus
+
+Menus and the @kbd{m} command
+
+ With only the @kbd{n} and @kbd{p} commands for moving between nodes, nodes
+are restricted to a linear sequence. Menus allow a branching
+structure. A menu is a list of other nodes you can move to. It is
+actually just part of the text of the node formatted specially so that
+Info can interpret it. The beginning of a menu is always identified
+by a line which starts with @samp{* Menu:}. A node contains a menu if and
+only if it has a line in it which starts that way. The only menu you
+can use at any moment is the one in the node you are in. To use a
+menu in any other node, you must move to that node first.
+
+ After the start of the menu, each line that starts with a @samp{*}
+identifies one subtopic. The line usually contains a brief name
+for the subtopic (followed by a @samp{:}), the name of the node that talks
+about that subtopic, and optionally some further description of the
+subtopic. Lines in the menu that do not start with a @samp{*} have no
+special meaning---they are only for the human reader's benefit and do
+not define additional subtopics. Here is an example:
+
+@example
+* Foo: FOO's Node This tells about FOO
+@end example
+
+The subtopic name is Foo, and the node describing it is @samp{FOO's Node}.
+The rest of the line is just for the reader's Information.
+[[ But this line is not a real menu item, simply because there is
+no line above it which starts with @samp{* Menu:}.]]
+
+ When you use a menu to go to another node (in a way that will be
+described soon), what you specify is the subtopic name, the first
+thing in the menu line. Info uses it to find the menu line, extracts
+the node name from it, and goes to that node. The reason that there
+is both a subtopic name and a node name is that the node name must be
+meaningful to the computer and may therefore have to be ugly looking.
+The subtopic name can be chosen just to be convenient for the user to
+specify. Often the node name is convenient for the user to specify
+and so both it and the subtopic name are the same. There is an
+abbreviation for this:
+
+@example
+* Foo:: This tells about FOO
+@end example
+
+@noindent
+This means that the subtopic name and node name are the same; they are
+both @samp{Foo}.
+
+>> Now use Spaces to find the menu in this node, then come back to
+ the front with a @kbd{b} and some Spaces. As you see, a menu is
+ actually visible in its node. If you cannot find a menu in a node
+ by looking at it, then the node does not have a menu and the
+ @kbd{m} command is not available.
+
+ The command to go to one of the subnodes is @kbd{m}---but @emph{do
+not do it yet!} Before you use @kbd{m}, you must understand the
+difference between commands and arguments. So far, you have learned
+several commands that do not need arguments. When you type one, Info
+processes it and is instantly ready for another command. The @kbd{m}
+command is different: it is incomplete without the @dfn{name of the
+subtopic}. Once you have typed @kbd{m}, Info tries to read the
+subtopic name.
+
+ Now look for the line containing many dashes near the bottom of the
+screen. There is one more line beneath that one, but usually it is
+blank. If it is empty, Info is ready for a command, such as @kbd{n}
+or @kbd{b} or Space or @kbd{m}. If that line contains text ending
+in a colon, it mean Info is trying to read the @dfn{argument} to a
+command. At such times, commands do not work, because Info tries to
+use them as the argument. You must either type the argument and
+finish the command you started, or type @kbd{Control-g} to cancel the
+command. When you have done one of those things, the line becomes
+blank again.
+
+ The command to go to a subnode via a menu is @kbd{m}. After you type
+the @kbd{m}, the line at the bottom of the screen says @samp{Menu item: }.
+You must then type the name of the subtopic you want, and end it with
+a @key{RET}.
+
+ You can abbreviate the subtopic name. If the abbreviation is not
+unique, the first matching subtopic is chosen. Some menus put
+the shortest possible abbreviation for each subtopic name in capital
+letters, so you can see how much you need to type. It does not
+matter whether you use upper case or lower case when you type the
+subtopic. You should not put any spaces at the end, or inside of the
+item name, except for one space where a space appears in the item in
+the menu.
+
+ You can also use the @dfn{completion} feature to help enter the subtopic
+name. If you type the Tab key after entering part of a name, it will
+magically fill in more of the name---as much as follows uniquely from
+what you have entered.
+
+ If you move the cursor to one of the menu subtopic lines, then you do
+not need to type the argument: you just type a Return, and it stands for
+the subtopic of the line you are on.
+
+Here is a menu to give you a chance to practice.
+
+* Menu: The menu starts here.
+
+This menu gives you three ways of going to one place, Help-FOO.
+
+* Foo: Help-FOO. A node you can visit for fun.@*
+* Bar: Help-FOO. Strange! two ways to get to the same place.@*
+* Help-FOO:: And yet another!@*
+
+
+>> Now type just an @kbd{m} and see what happens:
+
+ Now you are ``inside'' an @kbd{m} command. Commands cannot be used
+now; the next thing you will type must be the name of a subtopic.
+
+ You can change your mind about doing the @kbd{m} by typing Control-g.
+
+>> Try that now; notice the bottom line clear.
+
+>> Then type another @kbd{m}.
+
+>> Now type @samp{BAR} item name. Do not type Return yet.
+
+ While you are typing the item name, you can use the Delete key to
+cancel one character at a time if you make a mistake.
+
+>> Type one to cancel the @samp{R}. You could type another @samp{R} to
+ replace it. You do not have to, since @samp{BA} is a valid abbreviation.
+
+>> Now you are ready to go. Type a @key{RET}.
+
+ After visiting Help-FOO, you should return here.
+
+>> Type @kbd{n} to see more commands.
+
+@c If a menu appears at the end of this node, remove it.
+@c It is an accident of the menu updating command.
+
+Here is another way to get to Help-FOO, a menu. You can ignore this
+if you want, or else try it (but then please come back to here).
+
+@menu
+* Help-FOO::
+@end menu
+
+@node Help-FOO, , , Help-M
+@comment node-name, next, previous, up
+@subsection The @kbd{u} command
+
+ Congratulations! This is the node @samp{Help-FOO}. Unlike the other
+nodes you have seen, this one has an @samp{Up}: @samp{Help-M}, the node you
+just came from via the @kbd{m} command. This is the usual
+convention---the nodes you reach from a menu have @samp{Up} nodes that lead
+back to the menu. Menus move Down in the tree, and @samp{Up} moves Up.
+@samp{Previous}, on the other hand, is usually used to ``stay on the same
+level but go backwards''
+
+ You can go back to the node @samp{Help-M} by typing the command
+@kbd{u} for ``Up''. That puts you at the @emph{front} of the
+node---to get back to where you were reading you have to type
+some @key{SPC}s.
+
+>> Now type @kbd{u} to move back up to @samp{Help-M}.
+
+@node Help-Adv, Help-Q, Help-M, Getting Started
+@comment node-name, next, previous, up
+@section Some advanced Info commands
+
+ The course is almost over, so please stick with it to the end.
+
+ If you have been moving around to different nodes and wish to
+retrace your steps, the @kbd{l} command (@kbd{l} for @dfn{last}) will
+do that, one node-step at a time. As you move from node to node, Info
+records the nodes where you have been in a special history list. The
+@kbd{l} command revisits nodes in the history list; each successive
+@kbd{l} command moves one step back through the history.
+
+ If you have been following directions, ad @kbd{l} command now will get
+you back to @samp{Help-M}. Another @kbd{l} command would undo the
+@kbd{u} and get you back to @samp{Help-FOO}. Another @kbd{l} would undo
+the @kbd{m} and get you back to @samp{Help-M}.
+
+>> Try typing three @kbd{l}'s, pausing in between to see what each
+ @kbd{l} does.
+
+Then follow directions again and you will end up back here.
+
+ Note the difference between @kbd{l} and @kbd{p}: @kbd{l} moves to
+where @emph{you} last were, whereas @kbd{p} always moves to the node
+which the header says is the @samp{Previous} node (from this node, to
+@samp{Help-M}).
+
+ The @samp{d} command gets you instantly to the Directory node.
+This node, which is the first one you saw when you entered Info,
+has a menu which leads (directly, or indirectly through other menus),
+to all the nodes that exist.
+
+>> Try doing a @samp{d}, then do an @kbd{l} to return here (yes,
+ @emph{do} return).
+
+ Sometimes, in Info documentation, you will see a cross reference.
+Cross references look like this: @xref{Help-Cross, Cross}. That is a
+real, live cross reference which is named @samp{Cross} and points at
+the node named @samp{Help-Cross}.
+
+ If you wish to follow a cross reference, you must use the @samp{f}
+command. The @samp{f} must be followed by the cross reference name
+(in this case, @samp{Cross}). While you enter the name, you can use the
+Delete key to edit your input. If you change your mind about following
+any reference, you can use @kbd{Control-g} to cancel the command.
+
+ Completion is available in the @samp{f} command; you can complete among
+all the cross reference names in the current node by typing a Tab.
+
+>> Type @samp{f}, followed by @samp{Cross}, and a @key{RET}.
+
+ To get a list of all the cross references in the current node, you can
+type @kbd{?} after an @samp{f}. The @samp{f} continues to await a
+cross reference name even after printing the list, so if you don't
+actually want to follow a reference, you should type a @kbd{Control-g}
+to cancel the @samp{f}.
+
+>> Type "f?" to get a list of the cross references in this node. Then
+ type a @kbd{Control-g} and see how the @samp{f} gives up.
+
+>> Now type @kbd{n} to see the last node of the course.
+
+@c If a menu appears at the end of this node, remove it.
+@c It is an accident of the menu updating command.
+
+@node Help-Cross, , , Help-Adv
+@comment node-name, next, previous, up
+@unnumberedsubsec The node reached by the cross reference in Info
+
+ This is the node reached by the cross reference named @samp{Cross}.
+
+ While this node is specifically intended to be reached by a cross
+reference, most cross references lead to nodes that ``belong''
+someplace else far away in the structure of Info. So you cannot expect
+the footnote to have a @samp{Next}, @samp{Previous} or @samp{Up} pointing back to
+where you came from. In general, the @kbd{l} (el) command is the only
+way to get back there.
+
+>> Type @kbd{l} to return to the node where the cross reference was.
+
+@node Help-Q, , Help-Adv, Getting Started
+@comment node-name, next, previous, up
+@section Quitting Info
+
+ To get out of Info, back to what you were doing before, type @kbd{q}
+for @dfn{Quit}.
+
+ This is the end of the course on using Info. There are some other
+commands that are meant for experienced users; they are useful, and you
+can find them by looking in the directory node for documentation on
+Info. Finding them will be a good exercise in using Info in the usual
+manner.
+
+>> Type @samp{d} to go to the Info directory node; then type
+ @samp{mInfo} and Return, to get to the node about Info and
+ see what other help is available.
+
+@node Advanced Info, Create an Info File, Getting Started, Top
+@comment node-name, next, previous, up
+@chapter Info for Experts
+
+This chapter describes various advanced Info commands, and how to write
+an Info as distinct from a Texinfo file. (However, in most cases, writing a
+Texinfo file is better, since you can use it @emph{both} to generate an
+Info file and to make a printed manual. @xref{Top,, Overview of
+Texinfo, texinfo, Texinfo: The GNU Documentation Format}.)
+
+@menu
+* Expert:: Advanced Info commands: g, s, e, and 1 - 5.
+* Add:: Describes how to add new nodes to the hierarchy.
+ Also tells what nodes look like.
+* Menus:: How to add to or create menus in Info nodes.
+* Cross-refs:: How to add cross-references to Info nodes.
+* Tags:: How to make tag tables for Info files.
+* Checking:: Checking an Info File
+* Emacs Info Variables:: Variables modifying the behavior of Emacs Info.
+@end menu
+
+@node Expert, Add, , Advanced Info
+@comment node-name, next, previous, up
+@section Advanced Info Commands
+
+@kbd{g}, @kbd{s}, @kbd{1}, -- @kbd{9}, and @kbd{e}
+
+If you know a node's name, you can go there by typing @kbd{g}, the
+name, and @key{RET}. Thus, @kbd{gTop@key{RET}} would go to the node
+called @samp{Top} in this file (its directory node).
+@kbd{gExpert@key{RET}} would come back here.
+
+Unlike @kbd{m}, @kbd{g} does not allow the use of abbreviations.
+
+To go to a node in another file, you can include the filename in the
+node name by putting it at the front, in parentheses. Thus,
+@kbd{g(dir)Top@key{RET}} would go to the Info Directory node, which is
+node @samp{Top} in the file @file{dir}.
+
+The node name @samp{*} specifies the whole file. So you can look at
+all of the current file by typing @kbd{g*@key{RET}} or all of any
+other file with @kbd{g(FILENAME)@key{RET}}.
+
+The @kbd{s} command allows you to search a whole file for a string.
+It switches to the next node if and when that is necessary. You
+type @kbd{s} followed by the string to search for, terminated by
+@key{RET}. To search for the same string again, just @kbd{s} followed
+by @key{RET} will do. The file's nodes are scanned in the order
+they are in in the file, which has no necessary relationship to the
+order that they may be in in the tree structure of menus and @samp{next} pointers.
+But normally the two orders are not very different. In any case,
+you can always do a @kbd{b} to find out what node you have reached, if
+the header is not visible (this can happen, because @kbd{s} puts your
+cursor at the occurrence of the string, not at the beginning of the
+node).
+
+If you grudge the system each character of type-in it requires, you
+might like to use the commands @kbd{1}, @kbd{2}, @kbd{3}, @kbd{4}, ...
+@kbd{9}. They are short for the @kbd{m} command together with an
+argument. @kbd{1} goes through the first item in the current node's
+menu; @kbd{2} goes through the second item, etc.
+
+If you display supports multiple fonts, and you are using Emacs' Info
+mode to read Info files, the @samp{*} for the fifth menu item is
+underlines, and so is the @samp{*} for the ninth item; these underlines
+make it easy to see at a glance which number to use for an item.
+
+On ordinary terminals, you won't have underlining. If you need to
+actually count items, it is better to use @kbd{m} instead, and specify
+the name.
+
+The Info command @kbd{e} changes from Info mode to an ordinary
+Emacs editing mode, so that you can edit the text of the current node.
+Type @kbd{C-c C-c} to switch back to Info. The @kbd{e} command is allowed
+only if the variable @code{Info-enable-edit} is non-@code{nil}.
+
+@node Add, Menus, Expert, Advanced Info
+@comment node-name, next, previous, up
+@section Adding a new node to Info
+
+To add a new topic to the list in the Info directory, you must:
+@enumerate
+@item
+Create some nodes, in some file, to document that topic.
+@item
+Put that topic in the menu in the directory. @xref{Menus, Menu}.
+@end enumerate
+
+Usually, the way to create the nodes is with Texinfo @pxref{Top,, Overview of
+Texinfo, texinfo, Texinfo: The GNU Documentation Format}); this has the
+advantage that you can also make a printed manual from them. However,
+if hyou want to edit an Info file, here is how.
+
+ The new node can live in an existing documentation file, or in a new
+one. It must have a @key{^_} character before it (invisible to the
+user; this node has one but you cannot see it), and it ends with either
+a @key{^_}, a @key{^L}, or the end of file. Note: If you put in a
+@key{^L} to end a new node, be sure that there is a @key{^_} after it
+to start the next one, since @key{^L} cannot @emph{start} a node.
+Also, a nicer way to make a node boundary be a page boundary as well
+is to put a @key{^L} @emph{right after} the @key{^_}.
+
+ The @key{^_} starting a node must be followed by a newline or a
+@key{^L} newline, after which comes the node's header line. The
+header line must give the node's name (by which Info finds it),
+and state the names of the @samp{Next}, @samp{Previous}, and @samp{Up} nodes (if
+there are any). As you can see, this node's @samp{Up} node is the node
+@samp{Top}, which points at all the documentation for Info. The @samp{Next}
+node is @samp{Menus}.
+
+ The keywords @dfn{Node}, @dfn{Previous}, @dfn{Up}, and @dfn{Next},
+may appear in any order, anywhere in the header line, but the
+recommended order is the one in this sentence. Each keyword must be
+followed by a colon, spaces and tabs, and then the appropriate name.
+The name may be terminated with a tab, a comma, or a newline. A space
+does not end it; node names may contain spaces. The case of letters
+in the names is insignificant.
+
+ A node name has two forms. A node in the current file is named by
+what appears after the @samp{Node: } in that node's first line. For
+example, this node's name is @samp{Add}. A node in another file is
+named by @samp{(@var{filename})@var{node-within-file}}, as in
+@samp{(info)Add} for this node. If the file name starts with ``./'',
+then it is relative to the current directory; otherwise, it is relative
+starting from the standard Info file directory of your site.
+The name @samp{(@var{filename})Top} can be abbreviated to just
+@samp{(@var{filename})}. By convention, the name @samp{Top} is used for
+the ``highest'' node in any single file---the node whose @samp{Up} points
+out of the file. The Directory node is @file{(dir)}. The @samp{Top} node
+of a document file listed in the Directory should have an @samp{Up:
+(dir)} in it.
+
+ The node name @kbd{*} is special: it refers to the entire file.
+Thus, @kbd{g*} shows you the whole current file. The use of the
+node @kbd{*} is to make it possible to make old-fashioned,
+unstructured files into nodes of the tree.
+
+ The @samp{Node:} name, in which a node states its own name, must not
+contain a filename, since Info when searching for a node does not
+expect one to be there. The @samp{Next}, @samp{Previous} and @samp{Up} names may
+contain them. In this node, since the @samp{Up} node is in the same file,
+it was not necessary to use one.
+
+ Note that the nodes in this file have a file name in the header
+line. The file names are ignored by Info, but they serve as comments
+to help identify the node for the user.
+
+@node Menus, Cross-refs, Add, Advanced Info
+@comment node-name, next, previous, up
+@section How to Create Menus
+
+ Any node in the Info hierarchy may have a @dfn{menu}---a list of subnodes.
+The @kbd{m} command searches the current node's menu for the topic which it
+reads from the terminal.
+
+ A menu begins with a line starting with @samp{* Menu:}. The rest of the
+line is a comment. After the starting line, every line that begins
+with a @samp{* } lists a single topic. The name of the topic--the
+argument that the user must give to the @kbd{m} command to select this
+topic---comes right after the star and space, and is followed by a
+colon, spaces and tabs, and the name of the node which discusses that
+topic. The node name, like node names following @samp{Next}, @samp{Previous}
+and @samp{Up}, may be terminated with a tab, comma, or newline; it may also
+be terminated with a period.
+
+ If the node name and topic name are the same, then rather than
+giving the name twice, the abbreviation @samp{* NAME::} may be used
+(and should be used, whenever possible, as it reduces the visual
+clutter in the menu).
+
+ It is considerate to choose the topic names so that they differ
+from each other very near the beginning---this allows the user to type
+short abbreviations. In a long menu, it is a good idea to capitalize
+the beginning of each item name which is the minimum acceptable
+abbreviation for it (a long menu is more than 5 or so entries).
+
+ The nodes listed in a node's menu are called its ``subnodes'', and
+it is their ``superior''. They should each have an @samp{Up:} pointing at
+the superior. It is often useful to arrange all or most of the
+subnodes in a sequence of @samp{Next} and @samp{Previous} pointers so that someone who
+wants to see them all need not keep revisiting the Menu.
+
+ The Info Directory is simply the menu of the node @samp{(dir)Top}---that
+is, node @samp{Top} in file @file{.../info/dir}. You can put new entries
+in that menu just like any other menu. The Info Directory is @emph{not} the
+same as the file directory called @file{info}. It happens that many of
+Info's files live on that file directory, but they do not have to; and
+files on that directory are not automatically listed in the Info
+Directory node.
+
+ Also, although the Info node graph is claimed to be a ``hierarchy'',
+in fact it can be @emph{any} directed graph. Shared structures and
+pointer cycles are perfectly possible, and can be used if they are
+appropriate to the meaning to be expressed. There is no need for all
+the nodes in a file to form a connected structure. In fact, this file
+has two connected components. You are in one of them, which is under
+the node @samp{Top}; the other contains the node @samp{Help} which the
+@kbd{h} command goes to. In fact, since there is no garbage
+collector, nothing terrible happens if a substructure is not pointed
+to, but such a substructure is rather useless since nobody can
+ever find out that it exists.
+
+@node Cross-refs, Tags, Menus, Advanced Info
+@comment node-name, next, previous, up
+@section Creating Cross References
+
+ A cross reference can be placed anywhere in the text, unlike a menu
+item which must go at the front of a line. A cross reference looks
+like a menu item except that it has @samp{*note} instead of @kbd{*}.
+It @emph{cannot} be terminated by a @samp{)}, because @samp{)}'s are
+so often part of node names. If you wish to enclose a cross reference
+in parentheses, terminate it with a period first. Here are two
+examples of cross references pointers:
+
+@example
+*Note details: commands. (See *note 3: Full Proof.)
+@end example
+
+They are just examples. The places they ``lead to'' do not really exist!
+
+@node Tags, Checking, Cross-refs, Advanced Info
+@comment node-name, next, previous, up
+@section Tag Tables for Info Files
+
+ You can speed up the access to nodes of a large Info file by giving
+it a tag table. Unlike the tag table for a program, the tag table for
+an Info file lives inside the file itself and is used
+automatically whenever Info reads in the file.
+
+ To make a tag table, go to a node in the file using Emacs Info mode and type
+@kbd{M-x Info-tagify}. Then you must use @kbd{C-x C-s} to save the
+file.
+
+ Once the Info file has a tag table, you must make certain it is up
+to date. If, as a result of deletion of text, any node moves back
+more than a thousand characters in the file from the position
+recorded in the tag table, Info will no longer be able to find that
+node. To update the tag table, use the @code{Info-tagify} command again.
+
+ An Info file tag table appears at the end of the file and looks like
+this:
+
+@example
+^_
+Tag Table:
+File: info, Node: Cross-refs^?21419
+File: info, Node: Tags^?22145
+^_
+End Tag Table
+@end example
+
+@noindent
+Note that it contains one line per node, and this line contains
+the beginning of the node's header (ending just after the node name),
+a Delete character, and the character position in the file of the
+beginning of the node.
+
+@node Checking, Emacs Info Variables, Tags, Advanced Info
+@comment node-name, next, previous, up
+@section Checking an Info File
+
+ When creating an Info file, it is easy to forget the name of a node
+when you are making a pointer to it from another node. If you put in
+the wrong name for a node, this is not detected until someone
+tries to go through the pointer using Info. Verification of the Info
+file is an automatic process which checks all pointers to nodes and
+reports any pointers which are invalid. Every @samp{Next}, @samp{Previous}, and
+@samp{Up} is checked, as is every menu item and every cross reference. In
+addition, any @samp{Next} which does not have a @samp{Previous} pointing back is
+reported. Only pointers within the file are checked, because checking
+pointers to other files would be terribly slow. But those are usually
+few.
+
+ To check an Info file, do @kbd{M-x Info-validate} while looking at
+any node of the file with Emacs Info mode.
+
+@node Emacs Info Variables, , Checking, Advanced Info
+@section Emacs Info-mode Variables
+
+The following variables may modify the behaviour of Info-mode in Emacs;
+you may wish to set one or several of these variables interactively, or
+in your @file{~/.emacs} init file. @xref{Examining, Examining and Setting
+Variables, Examining and Setting Variables, emacs, The GNU Emacs
+Manual}.
+
+@vtable @code
+@item Info-enable-edit
+Set to @code{nil}, disables the @samp{e} (@code{Info-edit}) command. A
+non-@code{nil} value enables it. @xref{Add, Edit}.
+
+@item Info-enable-active-nodes
+When set to a non-@code{nil} value, allows Info to execute Lisp code
+associated with nodes. The Lisp code is executed when the node is
+selected.
+
+@item Info-directory-list
+The list of directories to search for Info files. Each element is a
+string (directory name) or @code{nil} (try default directory).
+
+@item Info-directory
+The standard directory for Info documentation files. Only used when the
+function @code{Info-directory} is called.
+@end vtable
+
+@node Create an Info File, , Advanced Info, Top
+@comment node-name, next, previous, up
+@chapter Creating an Info File from a Makeinfo file
+
+@code{makeinfo} is a utility that converts a Texinfo file into an Info
+file; @code{texinfo-format-region} and @code{texinfo-format-buffer} are
+GNU Emacs functions that do the same.
+
+@xref{Create an Info File, , Creating an Info File, texinfo, the Texinfo
+Manual}, to learn how to create an Info file from a Texinfo file.
+
+@xref{Top,, Overview of Texinfo, texinfo, Texinfo: The GNU Documentation
+Format}, to learn how to write a Texinfo file.
+
+@bye
diff --git a/contrib/texinfo/info/infodoc.c b/contrib/texinfo/info/infodoc.c
new file mode 100644
index 0000000..3567509
--- /dev/null
+++ b/contrib/texinfo/info/infodoc.c
@@ -0,0 +1,771 @@
+/* infodoc.c -- Functions which build documentation nodes. */
+
+/* This file is part of GNU Info, a program for reading online documentation
+ stored in Info format.
+
+ Copyright (C) 1993 Free Software Foundation, Inc.
+
+ 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Written by Brian Fox (bfox@ai.mit.edu). */
+
+#include "info.h"
+
+/* Normally we do not define HELP_NODE_GETS_REGENERATED because the
+ contents of the help node currently can never change once an info
+ session has been started. You should consider defining this in
+ the case that you place information about dynamic variables in the
+ help text. When that happens, the contents of the help node will
+ change dependent on the value of those variables, and the user will
+ expect to see those changes. */
+/* #define HELP_NODE_GETS_REGENERATED 1 */
+
+/* **************************************************************** */
+/* */
+/* Info Help Windows */
+/* */
+/* **************************************************************** */
+
+/* The name of the node used in the help window. */
+static char *info_help_nodename = "*Info Help*";
+
+/* A node containing printed key bindings and their documentation. */
+static NODE *internal_info_help_node = (NODE *)NULL;
+
+/* A pointer to the contents of the help node. */
+static char *internal_info_help_node_contents = (char *)NULL;
+
+/* The static text which appears in the internal info help node. */
+static char *info_internal_help_text[] = {
+ "Basic Commands in Info Windows",
+ "******************************",
+ "",
+ " h Invoke the Info tutorial.",
+ "",
+ "Selecting other nodes:",
+ "----------------------",
+ " n Move to the \"next\" node of this node.",
+ " p Move to the \"previous\" node of this node.",
+ " u Move \"up\" from this node.",
+ " m Pick menu item specified by name.",
+ " Picking a menu item causes another node to be selected.",
+ " f Follow a cross reference. Reads name of reference.",
+ " l Move to the last node seen in this window.",
+ " d Move to the `directory' node. Equivalent to `g(DIR)'.",
+ "",
+ "Moving within a node:",
+ "---------------------",
+ " SPC Scroll forward a page.",
+ " DEL Scroll backward a page.",
+ " b Go to the beginning of this node.",
+ " e Go to the end of this node.",
+ "",
+ "\"Advanced\" commands:",
+ "--------------------",
+ " q Quit Info.",
+ " 1 Pick first item in node's menu.",
+ " 2-9 Pick second ... ninth item in node's menu.",
+ " 0 Pick last item in node's menu.",
+ " g Move to node specified by name.",
+ " You may include a filename as well, as in (FILENAME)NODENAME.",
+ " s Search through this Info file for a specified string,",
+ " and select the node in which the next occurrence is found.",
+ (char *)NULL
+};
+
+static char *where_is (), *where_is_internal ();
+
+void
+dump_map_to_message_buffer (prefix, map)
+ char *prefix;
+ Keymap map;
+{
+ register int i;
+
+ for (i = 0; i < 256; i++)
+ {
+ if (map[i].type == ISKMAP)
+ {
+ char *new_prefix, *keyname;
+
+ keyname = pretty_keyname (i);
+ new_prefix = (char *)
+ xmalloc (3 + strlen (prefix) + strlen (keyname));
+ sprintf (new_prefix, "%s%s%s ", prefix, *prefix ? " " : "", keyname);
+
+ dump_map_to_message_buffer (new_prefix, (Keymap)map[i].function);
+ free (new_prefix);
+ }
+ else if (map[i].function)
+ {
+ register int last;
+ char *doc, *name;
+
+ doc = function_documentation (map[i].function);
+ name = function_name (map[i].function);
+
+ if (!*doc)
+ continue;
+
+ /* Find out if there is a series of identical functions, as in
+ ea_insert (). */
+ for (last = i + 1; last < 256; last++)
+ if ((map[last].type != ISFUNC) ||
+ (map[last].function != map[i].function))
+ break;
+
+ if (last - 1 != i)
+ {
+ printf_to_message_buffer
+ ("%s%s .. ", prefix, pretty_keyname (i));
+ printf_to_message_buffer
+ ("%s%s\t", prefix, pretty_keyname (last - 1));
+ i = last - 1;
+ }
+ else
+ printf_to_message_buffer ("%s%s\t", prefix, pretty_keyname (i));
+
+#if defined (NAMED_FUNCTIONS)
+ /* Print the name of the function, and some padding before the
+ documentation string is printed. */
+ {
+ int length_so_far;
+ int desired_doc_start = 40; /* Must be multiple of 8. */
+
+ printf_to_message_buffer ("(%s)", name);
+ length_so_far = message_buffer_length_this_line ();
+
+ if ((desired_doc_start + strlen (doc)) >= the_screen->width)
+ printf_to_message_buffer ("\n ");
+ else
+ {
+ while (length_so_far < desired_doc_start)
+ {
+ printf_to_message_buffer ("\t");
+ length_so_far += character_width ('\t', length_so_far);
+ }
+ }
+ }
+#endif /* NAMED_FUNCTIONS */
+ printf_to_message_buffer ("%s\n", doc);
+ }
+ }
+}
+
+/* How to create internal_info_help_node. */
+static void
+create_internal_info_help_node ()
+{
+ register int i;
+ char *contents = (char *)NULL;
+ NODE *node;
+
+#if !defined (HELP_NODE_GETS_REGENERATED)
+ if (internal_info_help_node_contents)
+ contents = internal_info_help_node_contents;
+#endif /* !HELP_NODE_GETS_REGENERATED */
+
+ if (!contents)
+ {
+ int printed_one_mx = 0;
+
+ initialize_message_buffer ();
+
+ for (i = 0; info_internal_help_text[i]; i++)
+ printf_to_message_buffer ("%s\n", info_internal_help_text[i]);
+
+ printf_to_message_buffer ("---------------------\n\n");
+ printf_to_message_buffer ("The current search path is:\n");
+ printf_to_message_buffer (" \"%s\"\n", infopath);
+ printf_to_message_buffer ("---------------------\n\n");
+ printf_to_message_buffer ("Commands available in Info windows:\n\n");
+ dump_map_to_message_buffer ("", info_keymap);
+ printf_to_message_buffer ("---------------------\n\n");
+ printf_to_message_buffer ("Commands available in the echo area:\n\n");
+ dump_map_to_message_buffer ("", echo_area_keymap);
+
+#if defined (NAMED_FUNCTIONS)
+ /* Get a list of the M-x commands which have no keystroke equivs. */
+ for (i = 0; function_doc_array[i].func; i++)
+ {
+ VFunction *func = function_doc_array[i].func;
+
+ if ((!where_is_internal (info_keymap, func)) &&
+ (!where_is_internal (echo_area_keymap, func)))
+ {
+ if (!printed_one_mx)
+ {
+ printf_to_message_buffer ("---------------------\n\n");
+ printf_to_message_buffer
+ ("The following commands can only be invoked via M-x:\n\n");
+ printed_one_mx = 1;
+ }
+
+ printf_to_message_buffer
+ ("M-x %s\n %s\n",
+ function_doc_array[i].func_name,
+ replace_in_documentation (function_doc_array[i].doc));
+ }
+ }
+
+ if (printed_one_mx)
+ printf_to_message_buffer ("\n");
+#endif /* NAMED_FUNCTIONS */
+
+ printf_to_message_buffer
+ ("%s", replace_in_documentation
+ ("--- Use `\\[history-node]' or `\\[kill-node]' to exit ---\n"));
+ node = message_buffer_to_node ();
+ internal_info_help_node_contents = node->contents;
+ }
+ else
+ {
+ /* We already had the right contents, so simply use them. */
+ node = build_message_node ("", 0, 0);
+ free (node->contents);
+ node->contents = contents;
+ node->nodelen = 1 + strlen (contents);
+ }
+
+ internal_info_help_node = node;
+
+ /* Do not GC this node's contents. It never changes, and we never need
+ to delete it once it is made. If you change some things (such as
+ placing information about dynamic variables in the help text) then
+ you will need to allow the contents to be gc'd, and you will have to
+ arrange to always regenerate the help node. */
+#if defined (HELP_NODE_GETS_REGENERATED)
+ add_gcable_pointer (internal_info_help_node->contents);
+#endif
+
+ name_internal_node (internal_info_help_node, info_help_nodename);
+
+ /* Even though this is an internal node, we don't want the window
+ system to treat it specially. So we turn off the internalness
+ of it here. */
+ internal_info_help_node->flags &= ~N_IsInternal;
+}
+
+/* Return a window which is the window showing help in this Info. */
+static WINDOW *
+info_find_or_create_help_window ()
+{
+ WINDOW *help_window, *eligible, *window;
+
+ eligible = (WINDOW *)NULL;
+ help_window = get_internal_info_window (info_help_nodename);
+
+ /* If we couldn't find the help window, then make it. */
+ if (!help_window)
+ {
+ int max = 0;
+
+ for (window = windows; window; window = window->next)
+ {
+ if (window->height > max)
+ {
+ max = window->height;
+ eligible = window;
+ }
+ }
+
+ if (!eligible)
+ return ((WINDOW *)NULL);
+ }
+#if !defined (HELP_NODE_GETS_REGENERATED)
+ else
+ return (help_window);
+#endif /* !HELP_NODE_GETS_REGENERATED */
+
+ /* Make sure that we have a node containing the help text. */
+ create_internal_info_help_node ();
+
+ /* Either use the existing window to display the help node, or create
+ a new window if there was no existing help window. */
+ if (!help_window)
+ {
+ /* Split the largest window into 2 windows, and show the help text
+ in that window. */
+ if (eligible->height > 30)
+ {
+ active_window = eligible;
+ help_window = window_make_window (internal_info_help_node);
+ }
+ else
+ {
+ set_remembered_pagetop_and_point (active_window);
+ window_set_node_of_window (active_window, internal_info_help_node);
+ help_window = active_window;
+ }
+ }
+ else
+ {
+ /* Case where help node always gets regenerated, and we have an
+ existing window in which to place the node. */
+ if (active_window != help_window)
+ {
+ set_remembered_pagetop_and_point (active_window);
+ active_window = help_window;
+ }
+ window_set_node_of_window (active_window, internal_info_help_node);
+ }
+ remember_window_and_node (help_window, help_window->node);
+ return (help_window);
+}
+
+/* Create or move to the help window. */
+DECLARE_INFO_COMMAND (info_get_help_window, "Display help message")
+{
+ WINDOW *help_window;
+
+ help_window = info_find_or_create_help_window ();
+ if (help_window)
+ {
+ active_window = help_window;
+ active_window->flags |= W_UpdateWindow;
+ }
+ else
+ {
+ info_error (CANT_MAKE_HELP);
+ }
+}
+
+/* Show the Info help node. This means that the "info" file is installed
+ where it can easily be found on your system. */
+DECLARE_INFO_COMMAND (info_get_info_help_node, "Visit Info node `(info)Help'")
+{
+ NODE *node;
+ char *nodename;
+
+ /* If there is a window on the screen showing the node "(info)Help" or
+ the node "(info)Help-Small-Screen", simply select that window. */
+ {
+ WINDOW *win;
+
+ for (win = windows; win; win = win->next)
+ {
+ if (win->node && win->node->filename &&
+ (strcasecmp
+ (filename_non_directory (win->node->filename), "info") == 0) &&
+ ((strcmp (win->node->nodename, "Help") == 0) ||
+ (strcmp (win->node->nodename, "Help-Small-Screen") == 0)))
+ {
+ active_window = win;
+ return;
+ }
+ }
+ }
+
+ /* If the current window is small, show the small screen help. */
+ if (active_window->height < 24)
+ nodename = "Help-Small-Screen";
+ else
+ nodename = "Help";
+
+ /* Try to get the info file for Info. */
+ node = info_get_node ("Info", nodename);
+
+ if (!node)
+ {
+ if (info_recent_file_error)
+ info_error (info_recent_file_error);
+ else
+ info_error (CANT_FILE_NODE, "Info", nodename);
+ }
+ else
+ {
+ /* If the current window is very large (greater than 45 lines),
+ then split it and show the help node in another window.
+ Otherwise, use the current window. */
+
+ if (active_window->height > 45)
+ active_window = window_make_window (node);
+ else
+ {
+ set_remembered_pagetop_and_point (active_window);
+ window_set_node_of_window (active_window, node);
+ }
+
+ remember_window_and_node (active_window, node);
+ }
+}
+
+/* **************************************************************** */
+/* */
+/* Groveling Info Keymaps and Docs */
+/* */
+/* **************************************************************** */
+
+/* Return the documentation associated with the Info command FUNCTION. */
+char *
+function_documentation (function)
+ VFunction *function;
+{
+ register int i;
+
+ for (i = 0; function_doc_array[i].func; i++)
+ if (function == function_doc_array[i].func)
+ break;
+
+ return (replace_in_documentation (function_doc_array[i].doc));
+}
+
+#if defined (NAMED_FUNCTIONS)
+/* Return the user-visible name of the function associated with the
+ Info command FUNCTION. */
+char *
+function_name (function)
+
+ VFunction *function;
+{
+ register int i;
+
+ for (i = 0; function_doc_array[i].func; i++)
+ if (function == function_doc_array[i].func)
+ break;
+
+ return (function_doc_array[i].func_name);
+}
+
+/* Return a pointer to the function named NAME. */
+VFunction *
+named_function (name)
+ char *name;
+{
+ register int i;
+
+ for (i = 0; function_doc_array[i].func; i++)
+ if (strcmp (function_doc_array[i].func_name, name) == 0)
+ break;
+
+ return (function_doc_array[i].func);
+}
+#endif /* NAMED_FUNCTIONS */
+
+/* Return the documentation associated with KEY in MAP. */
+char *
+key_documentation (key, map)
+ char key;
+ Keymap map;
+{
+ VFunction *function = map[key].function;
+
+ if (function)
+ return (function_documentation (function));
+ else
+ return ((char *)NULL);
+}
+
+DECLARE_INFO_COMMAND (describe_key, "Print documentation for KEY")
+{
+ char keyname[50];
+ int keyname_index = 0;
+ unsigned char keystroke;
+ char *rep;
+ Keymap map;
+
+ keyname[0] = '\0';
+ map = window->keymap;
+
+ while (1)
+ {
+ message_in_echo_area ("Describe key: %s", keyname);
+ keystroke = info_get_input_char ();
+ unmessage_in_echo_area ();
+
+ if (Meta_p (keystroke) && (!ISO_Latin_p || key < 160))
+ {
+ if (map[ESC].type != ISKMAP)
+ {
+ window_message_in_echo_area
+ ("ESC %s is undefined.", pretty_keyname (UnMeta (keystroke)));
+ return;
+ }
+
+ strcpy (keyname + keyname_index, "ESC ");
+ keyname_index = strlen (keyname);
+ keystroke = UnMeta (keystroke);
+ map = (Keymap)map[ESC].function;
+ }
+
+ /* Add the printed representation of KEYSTROKE to our keyname. */
+ rep = pretty_keyname (keystroke);
+ strcpy (keyname + keyname_index, rep);
+ keyname_index = strlen (keyname);
+
+ if (map[keystroke].function == (VFunction *)NULL)
+ {
+ message_in_echo_area ("%s is undefined.", keyname);
+ return;
+ }
+ else if (map[keystroke].type == ISKMAP)
+ {
+ map = (Keymap)map[keystroke].function;
+ strcat (keyname, " ");
+ keyname_index = strlen (keyname);
+ continue;
+ }
+ else
+ {
+ char *message, *fundoc, *funname = "";
+
+#if defined (NAMED_FUNCTIONS)
+ funname = function_name (map[keystroke].function);
+#endif /* NAMED_FUNCTIONS */
+
+ fundoc = function_documentation (map[keystroke].function);
+
+ message = (char *)xmalloc
+ (10 + strlen (keyname) + strlen (fundoc) + strlen (funname));
+
+#if defined (NAMED_FUNCTIONS)
+ sprintf (message, "%s (%s): %s.", keyname, funname, fundoc);
+#else
+ sprintf (message, "%s is defined to %s.", keyname, fundoc);
+#endif /* !NAMED_FUNCTIONS */
+
+ window_message_in_echo_area ("%s", message);
+ free (message);
+ break;
+ }
+ }
+}
+
+/* How to get the pretty printable name of a character. */
+static char rep_buffer[30];
+
+char *
+pretty_keyname (key)
+ unsigned char key;
+{
+ char *rep;
+
+ if (Meta_p (key))
+ {
+ char temp[20];
+
+ rep = pretty_keyname (UnMeta (key));
+
+ sprintf (temp, "ESC %s", rep);
+ strcpy (rep_buffer, temp);
+ rep = rep_buffer;
+ }
+ else if (Control_p (key))
+ {
+ switch (key)
+ {
+ case '\n': rep = "LFD"; break;
+ case '\t': rep = "TAB"; break;
+ case '\r': rep = "RET"; break;
+ case ESC: rep = "ESC"; break;
+
+ default:
+ sprintf (rep_buffer, "C-%c", UnControl (key));
+ rep = rep_buffer;
+ }
+ }
+ else
+ {
+ switch (key)
+ {
+ case ' ': rep = "SPC"; break;
+ case DEL: rep = "DEL"; break;
+ default:
+ rep_buffer[0] = key;
+ rep_buffer[1] = '\0';
+ rep = rep_buffer;
+ }
+ }
+ return (rep);
+}
+
+/* Replace the names of functions with the key that invokes them. */
+char *
+replace_in_documentation (string)
+ char *string;
+{
+ register int i, start, next;
+ static char *result = (char *)NULL;
+
+ maybe_free (result);
+ result = (char *)xmalloc (1 + strlen (string));
+
+ i = next = start = 0;
+
+ /* Skip to the beginning of a replaceable function. */
+ for (i = start; string[i]; i++)
+ {
+ /* Is this the start of a replaceable function name? */
+ if (string[i] == '\\' && string[i + 1] == '[')
+ {
+ char *fun_name, *rep;
+ VFunction *function;
+
+ /* Copy in the old text. */
+ strncpy (result + next, string + start, i - start);
+ next += (i - start);
+ start = i + 2;
+
+ /* Move to the end of the function name. */
+ for (i = start; string[i] && (string[i] != ']'); i++);
+
+ fun_name = (char *)xmalloc (1 + i - start);
+ strncpy (fun_name, string + start, i - start);
+ fun_name[i - start] = '\0';
+
+ /* Find a key which invokes this function in the info_keymap. */
+ function = named_function (fun_name);
+
+ /* If the internal documentation string fails, there is a
+ serious problem with the associated command's documentation.
+ We croak so that it can be fixed immediately. */
+ if (!function)
+ abort ();
+
+ rep = where_is (info_keymap, function);
+ strcpy (result + next, rep);
+ next = strlen (result);
+
+ start = i;
+ if (string[i])
+ start++;
+ }
+ }
+ strcpy (result + next, string + start);
+ return (result);
+}
+
+/* Return a string of characters which could be typed from the keymap
+ MAP to invoke FUNCTION. */
+static char *where_is_rep = (char *)NULL;
+static int where_is_rep_index = 0;
+static int where_is_rep_size = 0;
+
+static char *
+where_is (map, function)
+ Keymap map;
+ VFunction *function;
+{
+ char *rep;
+
+ if (!where_is_rep_size)
+ where_is_rep = (char *)xmalloc (where_is_rep_size = 100);
+ where_is_rep_index = 0;
+
+ rep = where_is_internal (map, function);
+
+ /* If it couldn't be found, return "M-x Foo". */
+ if (!rep)
+ {
+ char *name;
+
+ name = function_name (function);
+
+ if (name)
+ sprintf (where_is_rep, "M-x %s", name);
+
+ rep = where_is_rep;
+ }
+ return (rep);
+}
+
+/* Return the printed rep of FUNCTION as found in MAP, or NULL. */
+static char *
+where_is_internal (map, function)
+ Keymap map;
+ VFunction *function;
+{
+ register int i;
+
+ /* If the function is directly invokable in MAP, return the representation
+ of that keystroke. */
+ for (i = 0; i < 256; i++)
+ if ((map[i].type == ISFUNC) && map[i].function == function)
+ {
+ sprintf (where_is_rep + where_is_rep_index, "%s", pretty_keyname (i));
+ return (where_is_rep);
+ }
+
+ /* Okay, search subsequent maps for this function. */
+ for (i = 0; i < 256; i++)
+ {
+ if (map[i].type == ISKMAP)
+ {
+ int saved_index = where_is_rep_index;
+ char *rep;
+
+ sprintf (where_is_rep + where_is_rep_index, "%s ",
+ pretty_keyname (i));
+
+ where_is_rep_index = strlen (where_is_rep);
+ rep = where_is_internal ((Keymap)map[i].function, function);
+
+ if (rep)
+ return (where_is_rep);
+
+ where_is_rep_index = saved_index;
+ }
+ }
+
+ return ((char *)NULL);
+}
+
+extern char *read_function_name ();
+
+DECLARE_INFO_COMMAND (info_where_is,
+ "Show what to type to execute a given command")
+{
+ char *command_name;
+
+ command_name = read_function_name ("Where is command: ", window);
+
+ if (!command_name)
+ {
+ info_abort_key (active_window, count, key);
+ return;
+ }
+
+ if (*command_name)
+ {
+ VFunction *function;
+
+ function = named_function (command_name);
+
+ if (function)
+ {
+ char *location;
+
+ location = where_is (active_window->keymap, function);
+
+ if (!location)
+ {
+ info_error ("`%s' is not on any keys", command_name);
+ }
+ else
+ {
+ if (strncmp (location, "M-x ", 4) == 0)
+ window_message_in_echo_area
+ ("%s can only be invoked via %s.", command_name, location);
+ else
+ window_message_in_echo_area
+ ("%s can be invoked via %s.", command_name, location);
+ }
+ }
+ else
+ info_error ("There is no function named `%s'", command_name);
+ }
+
+ free (command_name);
+}
diff --git a/contrib/texinfo/info/infomap.c b/contrib/texinfo/info/infomap.c
new file mode 100644
index 0000000..3f24f1f
--- /dev/null
+++ b/contrib/texinfo/info/infomap.c
@@ -0,0 +1,274 @@
+/* infomap.c -- Keymaps for Info. */
+
+/* This file is part of GNU Info, a program for reading online documentation
+ stored in Info format.
+
+ Copyright (C) 1993 Free Software Foundation, Inc.
+
+ 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Written by Brian Fox (bfox@ai.mit.edu). */
+
+#include "stdio.h"
+#include "ctype.h"
+#include "infomap.h"
+#include "funs.h"
+
+/* Return a new keymap which has all the uppercase letters mapped to run
+ the function info_do_lowercase_version (). */
+Keymap
+keymap_make_keymap ()
+{
+ register int i;
+ Keymap keymap;
+
+ keymap = (Keymap)xmalloc (256 * sizeof (KEYMAP_ENTRY));
+
+ for (i = 0; i < 256; i++)
+ {
+ keymap[i].type = ISFUNC;
+ keymap[i].function = (VFunction *)NULL;
+ }
+
+ for (i = 'A'; i < ('Z' + 1); i++)
+ {
+ keymap[i].type = ISFUNC;
+ keymap[i].function = info_do_lowercase_version;
+ }
+
+ return (keymap);
+}
+
+/* Return a new keymap which is a copy of MAP. */
+Keymap
+keymap_copy_keymap (map)
+ Keymap map;
+{
+ register int i;
+ Keymap keymap;
+
+ keymap = keymap_make_keymap ();
+
+ for (i = 0; i < 256; i++)
+ {
+ keymap[i].type = map[i].type;
+ keymap[i].function = map[i].function;
+ }
+ return (keymap);
+}
+
+/* Free the keymap and it's descendents. */
+void
+keymap_discard_keymap (map)
+ Keymap (map);
+{
+ register int i;
+
+ if (!map)
+ return;
+
+ for (i = 0; i < 256; i++)
+ {
+ switch (map[i].type)
+ {
+ case ISFUNC:
+ break;
+
+ case ISKMAP:
+ keymap_discard_keymap ((Keymap)map[i].function);
+ break;
+
+ }
+ }
+}
+
+/* Initialize the standard info keymaps. */
+
+Keymap info_keymap = (Keymap)NULL;
+Keymap echo_area_keymap = (Keymap)NULL;
+
+void
+initialize_info_keymaps ()
+{
+ register int i;
+ Keymap map;
+
+ if (!info_keymap)
+ {
+ info_keymap = keymap_make_keymap ();
+ info_keymap[ESC].type = ISKMAP;
+ info_keymap[ESC].function = (VFunction *)keymap_make_keymap ();
+ info_keymap[Control ('x')].type = ISKMAP;
+ info_keymap[Control ('x')].function = (VFunction *)keymap_make_keymap ();
+ echo_area_keymap = keymap_make_keymap ();
+ echo_area_keymap[ESC].type = ISKMAP;
+ echo_area_keymap[ESC].function = (VFunction *)keymap_make_keymap ();
+ echo_area_keymap[Control ('x')].type = ISKMAP;
+ echo_area_keymap[Control ('x')].function =
+ (VFunction *)keymap_make_keymap ();
+ }
+
+ /* Bind numeric arg functions for both echo area and info window maps. */
+ for (i = '0'; i < '9' + 1; i++)
+ {
+ ((Keymap) info_keymap[ESC].function)[i].function =
+ ((Keymap) echo_area_keymap[ESC].function)[i].function =
+ info_add_digit_to_numeric_arg;
+ }
+ ((Keymap) info_keymap[ESC].function)['-'].function =
+ ((Keymap) echo_area_keymap[ESC].function)['-'].function =
+ info_add_digit_to_numeric_arg;
+
+ /* Bind the echo area routines. */
+ map = echo_area_keymap;
+
+ /* Bind the echo area insert routines. */
+ for (i = 0; i < 160; i++)
+ if (isprint (i))
+ map[i].function = ea_insert;
+
+ map[Control ('a')].function = ea_beg_of_line;
+ map[Control ('b')].function = ea_backward;
+ map[Control ('d')].function = ea_delete;
+ map[Control ('e')].function = ea_end_of_line;
+ map[Control ('f')].function = ea_forward;
+ map[Control ('g')].function = ea_abort;
+ map[Control ('h')].function = ea_rubout;
+ map[Control ('k')].function = ea_kill_line;
+ map[Control ('l')].function = info_redraw_display;
+ map[Control ('q')].function = ea_quoted_insert;
+ map[Control ('t')].function = ea_transpose_chars;
+ map[Control ('u')].function = info_universal_argument;
+ map[Control ('y')].function = ea_yank;
+
+ map[LFD].function = ea_newline;
+ map[RET].function = ea_newline;
+ map[SPC].function = ea_complete;
+ map[TAB].function = ea_complete;
+ map['?'].function = ea_possible_completions;
+ map[DEL].function = ea_rubout;
+
+ /* Bind the echo area ESC keymap. */
+ map = (Keymap)echo_area_keymap[ESC].function;
+
+ map[Control ('g')].function = ea_abort;
+ map[Control ('v')].function = ea_scroll_completions_window;
+ map['b'].function = ea_backward_word;
+ map['d'].function = ea_kill_word;
+ map['f'].function = ea_forward_word;
+#if defined (NAMED_FUNCTIONS)
+ /* map['x'].function = info_execute_command; */
+#endif /* NAMED_FUNCTIONS */
+ map['y'].function = ea_yank_pop;
+ map['?'].function = ea_possible_completions;
+ map[TAB].function = ea_tab_insert;
+ map[DEL].function = ea_backward_kill_word;
+
+ /* Bind the echo area Control-x keymap. */
+ map = (Keymap)echo_area_keymap[Control ('x')].function;
+
+ map['o'].function = info_next_window;
+ map[DEL].function = ea_backward_kill_line;
+
+ /* Bind commands for Info window keymaps. */
+ map = info_keymap;
+ map[TAB].function = info_move_to_next_xref;
+ map[LFD].function = info_select_reference_this_line;
+ map[RET].function = info_select_reference_this_line;
+ map[SPC].function = info_scroll_forward;
+ map[Control ('a')].function = info_beginning_of_line;
+ map[Control ('b')].function = info_backward_char;
+ map[Control ('e')].function = info_end_of_line;
+ map[Control ('f')].function = info_forward_char;
+ map[Control ('g')].function = info_abort_key;
+ map[Control ('h')].function = info_get_help_window;
+ map[Control ('l')].function = info_redraw_display;
+ map[Control ('n')].function = info_next_line;
+ map[Control ('p')].function = info_prev_line;
+ map[Control ('r')].function = isearch_backward;
+ map[Control ('s')].function = isearch_forward;
+ map[Control ('u')].function = info_universal_argument;
+ map[Control ('v')].function = info_scroll_forward;
+ map[','].function = info_next_index_match;
+
+ for (i = '1'; i < '9' + 1; i++)
+ map[i].function = info_menu_digit;
+ map['0'].function = info_last_menu_item;
+
+ map['<'].function = info_first_node;
+ map['>'].function = info_last_node;
+ map['?'].function = info_get_help_window;
+ map['['].function = info_global_prev_node;
+ map[']'].function = info_global_next_node;
+
+ map['b'].function = info_beginning_of_node;
+ map['d'].function = info_dir_node;
+ map['e'].function = info_end_of_node;
+ map['f'].function = info_xref_item;
+ map['g'].function = info_goto_node;
+ map['h'].function = info_get_info_help_node;
+ map['i'].function = info_index_search;
+ map['l'].function = info_history_node;
+ map['m'].function = info_menu_item;
+ map['n'].function = info_next_node;
+ map['p'].function = info_prev_node;
+ map['q'].function = info_quit;
+ map['r'].function = info_xref_item;
+ map['s'].function = info_search;
+ map['t'].function = info_top_node;
+ map['u'].function = info_up_node;
+ map[DEL].function = info_scroll_backward;
+
+ /* Bind members in the ESC map for Info windows. */
+ map = (Keymap)info_keymap[ESC].function;
+ map[Control ('f')].function = info_show_footnotes;
+ map[Control ('g')].function = info_abort_key;
+ map[TAB].function = info_move_to_prev_xref;
+ map[Control ('v')].function = info_scroll_other_window;
+ map['<'].function = info_beginning_of_node;
+ map['>'].function = info_end_of_node;
+ map['b'].function = info_backward_word;
+ map['f'].function = info_forward_word;
+ map['r'].function = info_move_to_window_line;
+ map['v'].function = info_scroll_backward;
+#if defined (NAMED_FUNCTIONS)
+ map['x'].function = info_execute_command;
+#endif /* NAMED_FUNCTIONS */
+
+ /* Bind members in the Control-X map for Info windows. */
+ map = (Keymap)info_keymap[Control ('x')].function;
+
+ map[Control ('b')].function = list_visited_nodes;
+ map[Control ('c')].function = info_quit;
+ map[Control ('f')].function = info_view_file;
+ map[Control ('g')].function = info_abort_key;
+ map[Control ('v')].function = info_view_file;
+ map['0'].function = info_delete_window;
+ map['1'].function = info_keep_one_window;
+ map['2'].function = info_split_window;
+ map['^'].function = info_grow_window;
+ map['b'].function = select_visited_node;
+ map['k'].function = info_kill_node;
+ map['o'].function = info_next_window;
+ map['t'].function = info_tile_windows;
+ map['w'].function = info_toggle_wrap;
+}
+
+/* Strings which represent the sequence of characters that the arrow keys
+ produce. If these keys begin with ESC, and the second character of the
+ sequence does not conflict with an existing binding in the Meta keymap,
+ then bind the keys to do what C-p, C-n, C-f, and C-b do. */
+extern char *term_ku, *term_kd, *term_kr, *term_kl;
+
diff --git a/contrib/texinfo/info/infomap.h b/contrib/texinfo/info/infomap.h
new file mode 100644
index 0000000..faf9388
--- /dev/null
+++ b/contrib/texinfo/info/infomap.h
@@ -0,0 +1,82 @@
+/* infomap.h -- Description of a keymap in Info and related functions. */
+
+/* This file is part of GNU Info, a program for reading online documentation
+ stored in Info format.
+
+ Copyright (C) 1993 Free Software Foundation, Inc.
+
+ 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Written by Brian Fox (bfox@ai.mit.edu). */
+
+#if !defined (_INFOMAP_H_)
+#define _INFOMAP_H_
+
+#include "general.h"
+
+#define ESC '\033'
+#define DEL '\177'
+#define TAB '\011'
+#define RET '\r'
+#define LFD '\n'
+#define SPC ' '
+
+#define meta_character_threshold (DEL + 1)
+#define control_character_threshold (SPC)
+
+#define meta_character_bit 0x80
+#define control_character_bit 0x40
+
+#define Meta_p(c) (((c) > meta_character_threshold))
+#define Control_p(c) ((c) < control_character_threshold)
+
+#define Meta(c) ((c) | (meta_character_bit))
+#define UnMeta(c) ((c) & (~meta_character_bit))
+#define Control(c) ((toupper (c)) & (~control_character_bit))
+#define UnControl(c) (tolower ((c) | control_character_bit))
+
+/* A keymap contains one entry for each key in the ASCII set.
+ Each entry consists of a type and a pointer.
+ FUNCTION is the address of a function to run, or the
+ address of a keymap to indirect through.
+ TYPE says which kind of thing FUNCTION is. */
+typedef struct {
+ char type;
+ VFunction *function;
+} KEYMAP_ENTRY;
+
+typedef KEYMAP_ENTRY *Keymap;
+
+/* The values that TYPE can have in a keymap entry. */
+#define ISFUNC 0
+#define ISKMAP 1
+
+extern Keymap info_keymap;
+extern Keymap echo_area_keymap;
+
+/* Return a new keymap which has all the uppercase letters mapped to run
+ the function info_do_lowercase_version (). */
+extern Keymap keymap_make_keymap ();
+
+/* Return a new keymap which is a copy of MAP. */
+extern Keymap keymap_copy_keymap ();
+
+/* Free MAP and it's descendents. */
+extern void keymap_discard_keymap ();
+
+/* Initialize the info keymaps. */
+extern void initialize_info_keymaps ();
+
+#endif /* !_INFOMAP_H_ */
diff --git a/contrib/texinfo/info/m-x.c b/contrib/texinfo/info/m-x.c
new file mode 100644
index 0000000..03ac1a5
--- /dev/null
+++ b/contrib/texinfo/info/m-x.c
@@ -0,0 +1,195 @@
+/* m-x.c -- Meta-X minibuffer reader. */
+
+/* This file is part of GNU Info, a program for reading online documentation
+ stored in Info format.
+
+ Copyright (C) 1993 Free Software Foundation, Inc.
+
+ 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Written by Brian Fox (bfox@ai.mit.edu). */
+
+#include "info.h"
+
+/* **************************************************************** */
+/* */
+/* Reading Named Commands */
+/* */
+/* **************************************************************** */
+
+/* Read the name of an Info function in the echo area and return the
+ name. A return value of NULL indicates that no function name could
+ be read. */
+char *
+read_function_name (prompt, window)
+ char *prompt;
+ WINDOW *window;
+{
+ register int i;
+ char *line;
+ REFERENCE **array = (REFERENCE **)NULL;
+ int array_index = 0, array_slots = 0;
+
+ /* Make an array of REFERENCE which actually contains the names of
+ the functions available in Info. */
+ for (i = 0; function_doc_array[i].func; i++)
+ {
+ REFERENCE *entry;
+
+ entry = (REFERENCE *)xmalloc (sizeof (REFERENCE));
+ entry->label = strdup (function_doc_array[i].func_name);
+ entry->nodename = (char *)NULL;
+ entry->filename = (char *)NULL;
+
+ add_pointer_to_array
+ (entry, array_index, array, array_slots, 200, REFERENCE *);
+ }
+
+ line = info_read_completing_in_echo_area (window, prompt, array);
+
+ info_free_references (array);
+
+ if (!echo_area_is_active)
+ window_clear_echo_area ();
+
+ return (line);
+}
+
+DECLARE_INFO_COMMAND (describe_command,
+ "Read the name of an Info command and describe it")
+{
+ char *line;
+
+ line = read_function_name ("Describe command: ", window);
+
+ if (!line)
+ {
+ info_abort_key (active_window, count, key);
+ return;
+ }
+
+ /* Describe the function named in "LINE". */
+ if (*line)
+ {
+ char *fundoc;
+ VFunction *fun;
+
+ fun = named_function (line);
+
+ if (!fun)
+ return;
+
+ window_message_in_echo_area ("%s: %s.",
+ line, function_documentation (fun));
+ }
+ free (line);
+}
+
+DECLARE_INFO_COMMAND (info_execute_command,
+ "Read a command name in the echo area and execute it")
+{
+ char *line;
+
+ /* Ask the completer to read a reference for us. */
+ if (info_explicit_arg || count != 1)
+ {
+ char *prompt;
+
+ prompt = (char *)xmalloc (20);
+ sprintf (prompt, "%d M-x ", count);
+ line = read_function_name (prompt, window);
+ }
+ else
+ line = read_function_name ("M-x ", window);
+
+ /* User aborted? */
+ if (!line)
+ {
+ info_abort_key (active_window, count, key);
+ return;
+ }
+
+ /* User accepted "default"? (There is none.) */
+ if (!*line)
+ {
+ free (line);
+ return;
+ }
+
+ /* User wants to execute a named command. Do it. */
+ {
+ VFunction *function;
+
+ if ((active_window != the_echo_area) &&
+ (strncmp (line, "echo-area-", 10) == 0))
+ {
+ free (line);
+ info_error ("Cannot execute an `echo-area' command here.");
+ return;
+ }
+
+ function = named_function (line);
+ free (line);
+
+ if (!function)
+ return;
+
+ (*function) (active_window, count, 0);
+ }
+}
+
+/* Okay, now that we have M-x, let the user set the screen height. */
+DECLARE_INFO_COMMAND (set_screen_height,
+ "Set the height of the displayed window")
+{
+ int new_height;
+
+ if (info_explicit_arg || count != 1)
+ new_height = count;
+ else
+ {
+ char prompt[80];
+ char *line;
+
+ new_height = screenheight;
+
+ sprintf (prompt, "Set screen height to (%d): ", new_height);
+
+ line = info_read_in_echo_area (window, prompt);
+
+ /* If the user aborted, do that now. */
+ if (!line)
+ {
+ info_abort_key (active_window, count, 0);
+ return;
+ }
+
+ /* Find out what the new height is supposed to be. */
+ if (*line)
+ new_height = atoi (line);
+
+ /* Clear the echo area if it isn't active. */
+ if (!echo_area_is_active)
+ window_clear_echo_area ();
+
+ free (line);
+ }
+
+ terminal_clear_screen ();
+ display_clear_display (the_display);
+ screenheight = new_height;
+ display_initialize_display (screenwidth, screenheight);
+ window_new_screen_size (screenwidth, screenheight);
+}
diff --git a/contrib/texinfo/info/makedoc.c b/contrib/texinfo/info/makedoc.c
new file mode 100644
index 0000000..c0c4587
--- /dev/null
+++ b/contrib/texinfo/info/makedoc.c
@@ -0,0 +1,481 @@
+/* makedoc.c -- Make DOC.C and FUNS.H from input files. */
+
+/* This file is part of GNU Info, a program for reading online documentation
+ stored in Info format.
+
+ Copyright (C) 1993 Free Software Foundation, Inc.
+
+ 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Written by Brian Fox (bfox@ai.mit.edu). */
+
+/* This program grovels the contents of the source files passed as arguments
+ and writes out a file of function pointers and documentation strings, and
+ a header file which describes the contents. This only does the functions
+ declared with DECLARE_INFO_COMMAND. */
+
+#include <stdio.h>
+#include <ctype.h>
+#include <sys/types.h>
+#if defined (HAVE_SYS_FILE_H)
+#include <sys/file.h>
+#endif /* HAVE_SYS_FILE_H */
+#include <sys/stat.h>
+#include "general.h"
+
+#if !defined (O_RDONLY)
+#if defined (HAVE_SYS_FCNTL_H)
+#include <sys/fcntl.h>
+#else /* !HAVE_SYS_FCNTL_H */
+#include <fcntl.h>
+#endif /* !HAVE_SYS_FCNTL_H */
+#endif /* !O_RDONLY */
+
+extern void *xmalloc (), *xrealloc ();
+static void fatal_file_error ();
+
+/* Name of the header file which receives the declarations of functions. */
+static char *funs_filename = "funs.h";
+
+/* Name of the documentation to function pointer file. */
+static char *doc_filename = "doc.c";
+
+static char *doc_header[] = {
+ "/* doc.c -- Generated structure containing function names and doc strings.",
+ "",
+ " This file was automatically made from various source files with the",
+ " command \"%s\". DO NOT EDIT THIS FILE, only \"%s.c\".",
+ (char *)NULL
+};
+
+static char *doc_header_1[] = {
+ " An entry in the array FUNCTION_DOC_ARRAY is made for each command",
+ " found in the above files; each entry consists of a function pointer,",
+#if defined (NAMED_FUNCTIONS)
+ " a string which is the user-visible name of the function,",
+#endif /* NAMED_FUNCTIONS */
+ " and a string which documents its purpose. */",
+ "",
+ "#include \"doc.h\"",
+ "#include \"funs.h\"",
+ "",
+ "FUNCTION_DOC function_doc_array[] = {",
+ "",
+ (char *)NULL
+};
+
+/* How to remember the locations of the functions found so that Emacs
+ can use the information in a tag table. */
+typedef struct {
+ char *name; /* Name of the tag. */
+ int line; /* Line number at which it appears. */
+ long char_offset; /* Character offset at which it appears. */
+} EMACS_TAG;
+
+typedef struct {
+ char *filename; /* Name of the file containing entries. */
+ long entrylen; /* Total number of characters in tag block. */
+ EMACS_TAG **entries; /* Entries found in FILENAME. */
+ int entries_index;
+ int entries_slots;
+} EMACS_TAG_BLOCK;
+
+EMACS_TAG_BLOCK **emacs_tags = (EMACS_TAG_BLOCK **)NULL;
+int emacs_tags_index = 0;
+int emacs_tags_slots = 0;
+
+#define DECLARATION_STRING "\nDECLARE_INFO_COMMAND"
+
+static void process_one_file ();
+static void maybe_dump_tags ();
+static FILE *must_fopen ();
+
+int
+main (argc, argv)
+ int argc;
+ char **argv;
+{
+ register int i;
+ int tags_only = 0;
+ FILE *funs_stream, *doc_stream;
+
+ for (i = 1; i < argc; i++)
+ if (strcmp (argv[i], "-tags") == 0)
+ {
+ tags_only++;
+ break;
+ }
+
+ if (tags_only)
+ {
+ funs_filename = "/dev/null";
+ doc_filename = "/dev/null";
+ }
+
+ funs_stream = must_fopen (funs_filename, "w");
+ doc_stream = must_fopen (doc_filename, "w");
+
+ fprintf (funs_stream,
+ "/* %s -- Generated declarations for Info commands. */\n",
+ funs_filename);
+
+ for (i = 0; doc_header[i]; i++)
+ {
+ fprintf (doc_stream, doc_header[i], argv[0], argv[0]);
+ fprintf (doc_stream, "\n");
+ }
+
+ fprintf (doc_stream,
+ " Source files groveled to make this file include:\n\n");
+
+ for (i = 1; i < argc; i++)
+ fprintf (doc_stream, "\t%s\n", argv[i]);
+
+ fprintf (doc_stream, "\n");
+
+ for (i = 0; doc_header_1[i]; i++)
+ fprintf (doc_stream, "%s\n", doc_header_1[i]);
+
+
+ for (i = 1; i < argc; i++)
+ {
+ char *curfile;
+ curfile = argv[i];
+
+ if (*curfile == '-')
+ continue;
+
+ fprintf (doc_stream, "/* Commands found in \"%s\". */\n", curfile);
+ fprintf (funs_stream, "\n/* Functions declared in \"%s\". */\n",
+ curfile);
+
+ process_one_file (curfile, doc_stream, funs_stream);
+ }
+
+ fprintf (doc_stream,
+ " { (VFunction *)NULL, (char *)NULL, (char *)NULL }\n};\n");
+
+ fclose (funs_stream);
+ fclose (doc_stream);
+
+ if (tags_only)
+ maybe_dump_tags (stdout);
+ exit (0);
+}
+
+/* Dumping out the contents of an Emacs tags table. */
+static void
+maybe_dump_tags (stream)
+ FILE *stream;
+{
+ register int i;
+
+ /* Print out the information for each block. */
+ for (i = 0; i < emacs_tags_index; i++)
+ {
+ register int j;
+ register EMACS_TAG_BLOCK *block;
+ register EMACS_TAG *etag;
+ long block_len;
+
+ block_len = 0;
+ block = emacs_tags[i];
+
+ /* Calculate the length of the dumped block first. */
+ for (j = 0; j < block->entries_index; j++)
+ {
+ char digits[30];
+ etag = block->entries[j];
+ block_len += 3 + strlen (etag->name);
+ sprintf (digits, "%d,%d", etag->line, etag->char_offset);
+ block_len += strlen (digits);
+ }
+
+ /* Print out the defining line. */
+ fprintf (stream, "\f\n%s,%d\n", block->filename, block_len);
+
+ /* Print out the individual tags. */
+ for (j = 0; j < block->entries_index; j++)
+ {
+ etag = block->entries[j];
+
+ fprintf (stream, "%s,\177%d,%d\n",
+ etag->name, etag->line, etag->char_offset);
+ }
+ }
+}
+
+/* Keeping track of names, line numbers and character offsets of functions
+ found in source files. */
+static EMACS_TAG_BLOCK *
+make_emacs_tag_block (filename)
+ char *filename;
+{
+ EMACS_TAG_BLOCK *block;
+
+ block = (EMACS_TAG_BLOCK *)xmalloc (sizeof (EMACS_TAG_BLOCK));
+ block->filename = strdup (filename);
+ block->entrylen = 0;
+ block->entries = (EMACS_TAG **)NULL;
+ block->entries_index = 0;
+ block->entries_slots = 0;
+ return (block);
+}
+
+static void
+add_tag_to_block (block, name, line, char_offset)
+ EMACS_TAG_BLOCK *block;
+ char *name;
+ int line;
+ long char_offset;
+{
+ EMACS_TAG *tag;
+
+ tag = (EMACS_TAG *)xmalloc (sizeof (EMACS_TAG));
+ tag->name = name;
+ tag->line = line;
+ tag->char_offset = char_offset;
+ add_pointer_to_array (tag, block->entries_index, block->entries,
+ block->entries_slots, 50, EMACS_TAG *);
+}
+
+/* Read the file represented by FILENAME into core, and search it for Info
+ function declarations. Output the declarations in various forms to the
+ DOC_STREAM and FUNS_STREAM. */
+static void
+process_one_file (filename, doc_stream, funs_stream)
+ char *filename;
+ FILE *doc_stream, *funs_stream;
+{
+ int descriptor, decl_len;
+ char *buffer, *decl_str;
+ struct stat finfo;
+ long offset;
+ long file_size;
+ EMACS_TAG_BLOCK *block;
+
+ if (stat (filename, &finfo) == -1)
+ fatal_file_error (filename);
+
+ descriptor = open (filename, O_RDONLY, 0666);
+
+ if (descriptor == -1)
+ fatal_file_error (filename);
+
+ file_size = (long) finfo.st_size;
+ buffer = (char *)xmalloc (1 + file_size);
+ read (descriptor, buffer, file_size);
+ close (descriptor);
+
+ offset = 0;
+ decl_str = DECLARATION_STRING;
+ decl_len = strlen (decl_str);
+
+ block = make_emacs_tag_block (filename);
+
+ while (1)
+ {
+ long point = 0;
+ long line_start = 0;
+ int line_number = 0;
+
+ char *func, *doc;
+#if defined (NAMED_FUNCTIONS)
+ char *func_name;
+#endif /* NAMED_FUNCTIONS */
+
+ for (; offset < (file_size - decl_len); offset++)
+ {
+ if (buffer[offset] == '\n')
+ {
+ line_number++;
+ line_start = offset + 1;
+ }
+
+ if (strncmp (buffer + offset, decl_str, decl_len) == 0)
+ {
+ offset += decl_len;
+ point = offset;
+ break;
+ }
+ }
+
+ if (!point)
+ break;
+
+ /* Skip forward until we find the open paren. */
+ while (point < file_size)
+ {
+ if (buffer[point] == '\n')
+ {
+ line_number++;
+ line_start = point + 1;
+ }
+ else if (buffer[point] == '(')
+ break;
+
+ point++;
+ }
+
+ while (point++ < file_size)
+ {
+ if (!whitespace_or_newline (buffer[point]))
+ break;
+ else if (buffer[point] == '\n')
+ {
+ line_number++;
+ line_start = point + 1;
+ }
+ }
+
+ if (point >= file_size)
+ break;
+
+ /* Now looking at name of function. Get it. */
+ for (offset = point; buffer[offset] != ','; offset++);
+ func = (char *)xmalloc (1 + (offset - point));
+ strncpy (func, buffer + point, offset - point);
+ func[offset - point] = '\0';
+
+ /* Remember this tag in the current block. */
+ {
+ char *tag_name;
+
+ tag_name = (char *)xmalloc (1 + (offset - line_start));
+ strncpy (tag_name, buffer + line_start, offset - line_start);
+ tag_name[offset - line_start] = '\0';
+ add_tag_to_block (block, tag_name, line_number, point);
+ }
+
+#if defined (NAMED_FUNCTIONS)
+ /* Generate the user-visible function name from the function's name. */
+ {
+ register int i;
+ char *name_start;
+
+ name_start = func;
+
+ if (strncmp (name_start, "info_", 5) == 0)
+ name_start += 5;
+
+ func_name = strdup (name_start);
+
+ /* Fix up "ea" commands. */
+ if (strncmp (func_name, "ea_", 3) == 0)
+ {
+ char *temp_func_name;
+
+ temp_func_name = (char *)xmalloc (10 + strlen (func_name));
+ strcpy (temp_func_name, "echo_area_");
+ strcat (temp_func_name, func_name + 3);
+ free (func_name);
+ func_name = temp_func_name;
+ }
+
+ for (i = 0; func_name[i]; i++)
+ if (func_name[i] == '_')
+ func_name[i] = '-';
+ }
+#endif /* NAMED_FUNCTIONS */
+
+ /* Find doc string. */
+ point = offset + 1;
+
+ while (point < file_size)
+ {
+ if (buffer[point] == '\n')
+ {
+ line_number++;
+ line_start = point + 1;
+ }
+
+ if (buffer[point] == '"')
+ break;
+ else
+ point++;
+ }
+
+ offset = point + 1;
+
+ while (offset < file_size)
+ {
+ if (buffer[offset] == '\n')
+ {
+ line_number++;
+ line_start = offset + 1;
+ }
+
+ if (buffer[offset] == '\\')
+ offset += 2;
+ else if (buffer[offset] == '"')
+ break;
+ else
+ offset++;
+ }
+
+ offset++;
+ if (offset >= file_size)
+ break;
+
+ doc = (char *)xmalloc (1 + (offset - point));
+ strncpy (doc, buffer + point, offset - point);
+ doc[offset - point] = '\0';
+
+#if defined (NAMED_FUNCTIONS)
+ fprintf (doc_stream, " { %s, \"%s\", %s },\n", func, func_name, doc);
+ free (func_name);
+#else /* !NAMED_FUNCTIONS */
+ fprintf (doc_stream, " { %s, %s },\n", func, doc);
+#endif /* !NAMED_FUNCTIONS */
+
+ fprintf (funs_stream, "extern void %s ();\n", func);
+ free (func);
+ free (doc);
+ }
+ free (buffer);
+
+ /* If we created any tags, remember this file on our global list. Otherwise,
+ free the memory already allocated to it. */
+ if (block->entries)
+ add_pointer_to_array (block, emacs_tags_index, emacs_tags,
+ emacs_tags_slots, 10, EMACS_TAG_BLOCK *);
+ else
+ {
+ free (block->filename);
+ free (block);
+ }
+}
+
+static void
+fatal_file_error (filename)
+ char *filename;
+{
+ fprintf (stderr, "Couldn't manipulate the file %s.\n", filename);
+ exit (2);
+}
+
+static FILE *
+must_fopen (filename, mode)
+ char *filename, *mode;
+{
+ FILE *stream;
+
+ stream = fopen (filename, mode);
+ if (!stream)
+ fatal_file_error (filename);
+
+ return (stream);
+}
+
diff --git a/contrib/texinfo/info/man.c b/contrib/texinfo/info/man.c
new file mode 100644
index 0000000..b899ec1
--- /dev/null
+++ b/contrib/texinfo/info/man.c
@@ -0,0 +1,643 @@
+/* man.c: How to read and format man files. */
+
+/* This file is part of GNU Info, a program for reading online documentation
+ stored in Info format.
+
+ Copyright (C) 1995 Free Software Foundation, Inc.
+
+ 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Written by Brian Fox Thu May 4 09:17:52 1995 (bfox@ai.mit.edu). */
+
+#include "info.h"
+#include <sys/ioctl.h>
+#include <sys/file.h>
+#include "signals.h"
+#if defined (HAVE_SYS_TIME_H)
+#include <sys/time.h>
+#endif
+#if defined (HAVE_SYS_WAIT_H)
+#include <sys/wait.h>
+#endif
+#include "tilde.h"
+
+#include "man.h"
+
+#if !defined (_POSIX_VERSION)
+#define pid_t int
+#endif
+
+#if defined (FD_SET)
+# if defined (hpux)
+# define fd_set_cast(x) (int *)(x)
+# else
+# define fd_set_cast(x) (fd_set *)(x)
+# endif /* !hpux */
+#endif /* FD_SET */
+
+static char *read_from_fd ();
+static void clean_manpage ();
+static NODE *manpage_node_of_file_buffer ();
+static char *get_manpage_contents ();
+
+NODE *
+make_manpage_node (pagename)
+ char *pagename;
+{
+ return (info_get_node (MANPAGE_FILE_BUFFER_NAME, pagename));
+}
+
+NODE *
+get_manpage_node (file_buffer, pagename)
+ FILE_BUFFER *file_buffer;
+ char *pagename;
+{
+ NODE *node;
+
+ node = manpage_node_of_file_buffer (file_buffer, pagename);
+
+ if (!node)
+ {
+ char *page;
+
+ page = get_manpage_contents (pagename);
+
+ if (page)
+ {
+ char header[1024];
+ long oldsize, newsize;
+ int hlen, plen;
+
+ sprintf (header, "\n\n%c\n%s %s, %s %s, %s (dir)\n\n",
+ INFO_COOKIE,
+ INFO_FILE_LABEL, file_buffer->filename,
+ INFO_NODE_LABEL, pagename,
+ INFO_UP_LABEL);
+ oldsize = file_buffer->filesize;
+ hlen = strlen (header);
+ plen = strlen (page);
+ newsize = (oldsize + hlen + plen);
+ file_buffer->contents =
+ (char *)xrealloc (file_buffer->contents, 1 + newsize);
+ memcpy (file_buffer->contents + oldsize, header, hlen);
+ oldsize += hlen;
+ memcpy (file_buffer->contents + oldsize, page, plen);
+ file_buffer->contents[newsize] = '\0';
+ file_buffer->filesize = newsize;
+ file_buffer->finfo.st_size = newsize;
+ build_tags_and_nodes (file_buffer);
+ free (page);
+ }
+
+ node = manpage_node_of_file_buffer (file_buffer, pagename);
+ }
+
+ return (node);
+}
+
+FILE_BUFFER *
+create_manpage_file_buffer ()
+{
+ FILE_BUFFER *file_buffer;
+ struct stat *finfo;
+
+ file_buffer = make_file_buffer ();
+ file_buffer->filename = strdup (MANPAGE_FILE_BUFFER_NAME);
+ file_buffer->fullpath = strdup (MANPAGE_FILE_BUFFER_NAME);
+ file_buffer->finfo.st_size = 0;
+ file_buffer->filesize = 0;
+ file_buffer->contents = (char *)NULL;
+ file_buffer->flags = (N_IsInternal | N_CannotGC | N_IsManPage);
+
+ return (file_buffer);
+}
+
+/* Scan the list of directories in PATH looking for FILENAME. If we find
+ one that is an executable file, return it as a new string. Otherwise,
+ return a NULL pointer. */
+static char *
+executable_file_in_path (filename, path)
+ char *filename, *path;
+{
+ struct stat finfo;
+ char *temp_dirname;
+ int statable, dirname_index;
+
+ dirname_index = 0;
+
+ while (temp_dirname = extract_colon_unit (path, &dirname_index))
+ {
+ register int i;
+ char *temp;
+
+ /* Expand a leading tilde if one is present. */
+ if (*temp_dirname == '~')
+ {
+ char *expanded_dirname;
+
+ expanded_dirname = tilde_expand_word (temp_dirname);
+ free (temp_dirname);
+ temp_dirname = expanded_dirname;
+ }
+
+ temp = (char *)xmalloc (30 + strlen (temp_dirname) + strlen (filename));
+ strcpy (temp, temp_dirname);
+ if (temp[(strlen (temp)) - 1] != '/')
+ strcat (temp, "/");
+ strcat (temp, filename);
+
+ free (temp_dirname);
+
+ statable = (stat (temp, &finfo) == 0);
+
+ /* If we have found a regular executable file, then use it. */
+ if ((statable) && (S_ISREG (finfo.st_mode)) &&
+ (access (temp, X_OK) == 0))
+ return (temp);
+ else
+ free (temp);
+ }
+ return ((char *)NULL);
+}
+
+/* Return the full pathname of the system man page formatter. */
+static char *
+find_man_formatter ()
+{
+ return (executable_file_in_path ("man", (char *)getenv ("PATH")));
+}
+
+static char *manpage_pagename = (char *)NULL;
+static char *manpage_section = (char *)NULL;
+
+static void
+get_page_and_section (pagename)
+ char *pagename;
+{
+ register int i;
+
+ if (manpage_pagename)
+ free (manpage_pagename);
+
+ if (manpage_section)
+ free (manpage_section);
+
+ manpage_pagename = (char *)NULL;
+ manpage_section = (char *)NULL;
+
+ for (i = 0; pagename[i] != '\0' && pagename[i] != '('; i++);
+
+ manpage_pagename = (char *)xmalloc (1 + i);
+ strncpy (manpage_pagename, pagename, i);
+ manpage_pagename[i] = '\0';
+
+ if (pagename[i] == '(')
+ {
+ int start;
+
+ start = i + 1;
+
+ for (i = start; pagename[i] != '\0' && pagename[i] != ')'; i++);
+
+ manpage_section = (char *)xmalloc (1 + (i - start));
+ strncpy (manpage_section, pagename + start, (i - start));
+ manpage_section[i - start] = '\0';
+ }
+}
+
+static void
+reap_children (sig)
+ int sig;
+{
+ unsigned int status;
+ wait (&status);
+}
+
+static char *
+get_manpage_contents (pagename)
+ char *pagename;
+{
+ static char *formatter_args[4] = { (char *)NULL };
+ int pipes[2];
+ pid_t child;
+ char *formatted_page = (char *)NULL;
+ char *section = (char *)NULL;
+ int arg_index = 1;
+
+ if (formatter_args[0] == (char *)NULL)
+ formatter_args[0] = find_man_formatter ();
+
+ if (formatter_args[0] == (char *)NULL)
+ return ((char *)NULL);
+
+ get_page_and_section (pagename);
+
+ if (manpage_section != (char *)NULL)
+ formatter_args[arg_index++] = manpage_section;
+
+ formatter_args[arg_index++] = manpage_pagename;
+ formatter_args[arg_index] = (char *)NULL;
+
+ /* Open a pipe to this program, read the output, and save it away
+ in FORMATTED_PAGE. The reader end of the pipe is pipes[0]; the
+ writer end is pipes[1]. */
+ pipe (pipes);
+
+ signal (SIGCHLD, reap_children);
+
+ child = fork ();
+
+ if (child == -1)
+ return ((char *)NULL);
+
+ if (child != 0)
+ {
+ /* In the parent, close the writing end of the pipe, and read from
+ the exec'd child. */
+ close (pipes[1]);
+ formatted_page = read_from_fd (pipes[0]);
+ close (pipes[0]);
+ }
+ else
+ {
+ /* In the child, close the read end of the pipe, make the write end
+ of the pipe be stdout, and execute the man page formatter. */
+ close (pipes[0]);
+ close (fileno (stderr));
+ close (fileno (stdin)); /* Don't print errors. */
+ dup2 (pipes[1], fileno (stdout));
+
+ execv (formatter_args[0], formatter_args);
+
+ /* If we get here, we couldn't exec, so close out the pipe and
+ exit. */
+ close (pipes[1]);
+ exit (0);
+ }
+
+ /* If we have the page, then clean it up. */
+ if (formatted_page)
+ clean_manpage (formatted_page);
+
+ return (formatted_page);
+}
+
+static void
+clean_manpage (manpage)
+ char *manpage;
+{
+ register int i, j;
+ int newline_count = 0;
+ char *newpage;
+
+ newpage = (char *)xmalloc (1 + strlen (manpage));
+
+ for (i = 0, j = 0; newpage[j] = manpage[i]; i++, j++)
+ {
+ if (manpage[i] == '\n')
+ newline_count++;
+ else
+ newline_count = 0;
+
+ if (newline_count == 3)
+ {
+ j--;
+ newline_count--;
+ }
+
+ if (manpage[i] == '\b' || manpage[i] == '\f')
+ j -= 2;
+ }
+
+ newpage[j++] = '\0';
+
+ strcpy (manpage, newpage);
+ free (newpage);
+}
+
+static NODE *
+manpage_node_of_file_buffer (file_buffer, pagename)
+ FILE_BUFFER *file_buffer;
+ char *pagename;
+{
+ NODE *node = (NODE *)NULL;
+ TAG *tag = (TAG *)NULL;
+
+ if (file_buffer->contents)
+ {
+ register int i;
+
+ for (i = 0; tag = file_buffer->tags[i]; i++)
+ {
+ if (strcasecmp (pagename, tag->nodename) == 0)
+ break;
+ }
+ }
+
+ if (tag)
+ {
+ node = (NODE *)xmalloc (sizeof (NODE));
+ node->filename = file_buffer->filename;
+ node->nodename = tag->nodename;
+ node->contents = file_buffer->contents + tag->nodestart;
+ node->nodelen = tag->nodelen;
+ node->flags = 0;
+ node->parent = (char *)NULL;
+ node->flags = (N_HasTagsTable | N_IsManPage);
+ node->contents += skip_node_separator (node->contents);
+ }
+
+ return (node);
+}
+
+static char *
+read_from_fd (fd)
+ int fd;
+{
+ struct timeval timeout;
+ char *buffer = (char *)NULL;
+ int bsize = 0;
+ int bindex = 0;
+ int select_result;
+#if defined (FD_SET)
+ fd_set read_fds;
+
+ timeout.tv_sec = 15;
+ timeout.tv_usec = 0;
+
+ FD_ZERO (&read_fds);
+ FD_SET (fd, &read_fds);
+
+ select_result = select (fd + 1, fd_set_cast (&read_fds), 0, 0, &timeout);
+#else /* !FD_SET */
+ select_result = 1;
+#endif /* !FD_SET */
+
+ switch (select_result)
+ {
+ case 0:
+ case -1:
+ break;
+
+ default:
+ {
+ int amount_read;
+ int done = 0;
+
+ while (!done)
+ {
+ while ((bindex + 1024) > (bsize))
+ buffer = (char *)xrealloc (buffer, (bsize += 1024));
+ buffer[bindex] = '\0';
+
+ amount_read = read (fd, buffer + bindex, 1023);
+
+ if (amount_read < 0)
+ {
+ done = 1;
+ }
+ else
+ {
+ bindex += amount_read;
+ buffer[bindex] = '\0';
+ if (amount_read == 0)
+ done = 1;
+ }
+ }
+ }
+ }
+
+ if ((buffer != (char *)NULL) && (*buffer == '\0'))
+ {
+ free (buffer);
+ buffer = (char *)NULL;
+ }
+
+ return (buffer);
+}
+
+static char *reference_section_starters[] =
+{
+ "\nRELATED INFORMATION",
+ "\nRELATED\tINFORMATION",
+ "RELATED INFORMATION\n",
+ "RELATED\tINFORMATION\n",
+ "\nSEE ALSO",
+ "\nSEE\tALSO",
+ "SEE ALSO\n",
+ "SEE\tALSO\n",
+ (char *)NULL
+};
+
+static SEARCH_BINDING frs_binding;
+
+static SEARCH_BINDING *
+find_reference_section (node)
+ NODE *node;
+{
+ register int i;
+ long position = -1;
+
+ frs_binding.buffer = node->contents;
+ frs_binding.start = 0;
+ frs_binding.end = node->nodelen;
+ frs_binding.flags = S_SkipDest;
+
+ for (i = 0; reference_section_starters[i] != (char *)NULL; i++)
+ {
+ position = search_forward (reference_section_starters[i], &frs_binding);
+ if (position != -1)
+ break;
+ }
+
+ if (position == -1)
+ return ((SEARCH_BINDING *)NULL);
+
+ /* We found the start of the reference section, and point is right after
+ the string which starts it. The text from here to the next header
+ (or end of buffer) contains the only references in this manpage. */
+ frs_binding.start = position;
+
+ for (i = frs_binding.start; i < frs_binding.end - 2; i++)
+ {
+ if ((frs_binding.buffer[i] == '\n') &&
+ (!whitespace (frs_binding.buffer[i + 1])))
+ {
+ frs_binding.end = i;
+ break;
+ }
+ }
+
+ return (&frs_binding);
+}
+
+REFERENCE **
+xrefs_of_manpage (node)
+ NODE *node;
+{
+ SEARCH_BINDING *reference_section;
+ REFERENCE **refs = (REFERENCE **)NULL;
+ int refs_index = 0;
+ int refs_slots = 0;
+ long position;
+
+ reference_section = find_reference_section (node);
+
+ if (reference_section == (SEARCH_BINDING *)NULL)
+ return ((REFERENCE **)NULL);
+
+ /* Grovel the reference section building a list of references found there.
+ A reference is alphabetic characters followed by non-whitespace text
+ within parenthesis. */
+ reference_section->flags = 0;
+
+ while ((position = search_forward ("(", reference_section)) != -1)
+ {
+ register int start, end;
+
+ for (start = position; start > reference_section->start; start--)
+ if (whitespace (reference_section->buffer[start]))
+ break;
+
+ start++;
+
+ for (end = position; end < reference_section->end; end++)
+ {
+ if (whitespace (reference_section->buffer[end]))
+ {
+ end = start;
+ break;
+ }
+
+ if (reference_section->buffer[end] == ')')
+ {
+ end++;
+ break;
+ }
+ }
+
+ if (end != start)
+ {
+ REFERENCE *entry;
+ int len = end - start;
+
+ entry = (REFERENCE *)xmalloc (sizeof (REFERENCE));
+ entry->label = (char *)xmalloc (1 + len);
+ strncpy (entry->label, (reference_section->buffer) + start, len);
+ entry->label[len] = '\0';
+ entry->filename = strdup (node->filename);
+ entry->nodename = strdup (entry->label);
+ entry->start = start;
+ entry->end = end;
+
+ add_pointer_to_array
+ (entry, refs_index, refs, refs_slots, 10, REFERENCE *);
+ }
+
+ reference_section->start = position + 1;
+ }
+
+ return (refs);
+}
+
+long
+locate_manpage_xref (node, start, dir)
+ NODE *node;
+ long start;
+ int dir;
+{
+ register int i, count;
+ REFERENCE **refs;
+ long position = -1;
+
+ refs = xrefs_of_manpage (node);
+
+ if (refs)
+ {
+ register int i, count;
+ REFERENCE *entry;
+
+ for (i = 0; refs[i]; i++);
+ count = i;
+
+ if (dir > 0)
+ {
+ for (i = 0; entry = refs[i]; i++)
+ if (entry->start > start)
+ {
+ position = entry->start;
+ break;
+ }
+ }
+ else
+ {
+ for (i = count - 1; i > -1; i--)
+ {
+ entry = refs[i];
+
+ if (entry->start < start)
+ {
+ position = entry->start;
+ break;
+ }
+ }
+ }
+
+ info_free_references (refs);
+ }
+ return (position);
+}
+
+/* This one was a little tricky. The binding buffer that is passed in has
+ a START and END value of 0 -- strlen (window-line-containing-point).
+ The BUFFER is a pointer to the start of that line. */
+REFERENCE **
+manpage_xrefs_in_binding (node, binding)
+ NODE *node;
+ SEARCH_BINDING *binding;
+{
+ register int i;
+ REFERENCE **all_refs = xrefs_of_manpage (node);
+ REFERENCE **brefs = (REFERENCE **)NULL;
+ REFERENCE *entry;
+ int brefs_index = 0;
+ int brefs_slots = 0;
+ int start, end;
+
+ if (!all_refs)
+ return ((REFERENCE **)NULL);
+
+ start = binding->start + (binding->buffer - node->contents);
+ end = binding->end + (binding->buffer - node->contents);
+
+ for (i = 0; entry = all_refs[i]; i++)
+ {
+ if ((entry->start > start) && (entry->end < end))
+ {
+ add_pointer_to_array
+ (entry, brefs_index, brefs, brefs_slots, 10, REFERENCE *);
+ }
+ else
+ {
+ maybe_free (entry->label);
+ maybe_free (entry->filename);
+ maybe_free (entry->nodename);
+ free (entry);
+ }
+ }
+
+ free (all_refs);
+ return (brefs);
+}
diff --git a/contrib/texinfo/info/man.h b/contrib/texinfo/info/man.h
new file mode 100644
index 0000000..1584e26
--- /dev/null
+++ b/contrib/texinfo/info/man.h
@@ -0,0 +1,36 @@
+/* man.h: Defines and external function declarations for man.c */
+
+/* This file is part of GNU Info, a program for reading online documentation
+ stored in Info format.
+
+ Copyright (C) 1993 Free Software Foundation, Inc.
+
+ 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Author: Brian J. Fox (bfox@ai.mit.edu) Sat May 6 16:19:13 1995. */
+
+#if !defined (_MAN_H_)
+#define _MAN_H_
+
+#define MANPAGE_FILE_BUFFER_NAME "*manpages*"
+
+extern NODE *make_manpage_node (/* char *pagename */);
+extern NODE *get_manpage_node (/* FILE_BUFFER *file_buffer, char *pagename */);
+extern FILE_BUFFER *create_manpage_file_buffer (/* void */);
+extern long locate_manpage_xref (/* NODE *node, long start, int dir */);
+extern REFERENCE **xrefs_of_manpage (/* NODE *node */);
+extern REFERENCE **manpage_xrefs_in_binding (/* NODE *node, SEARCH_BINDING *binding */);
+
+#endif /* !_MAN_H_ */
diff --git a/contrib/texinfo/info/nodemenu.c b/contrib/texinfo/info/nodemenu.c
new file mode 100644
index 0000000..3304415
--- /dev/null
+++ b/contrib/texinfo/info/nodemenu.c
@@ -0,0 +1,329 @@
+/* nodemenu.c -- Produce a menu of all visited nodes. */
+
+/* This file is part of GNU Info, a program for reading online documentation
+ stored in Info format.
+
+ Copyright (C) 1993 Free Software Foundation, Inc.
+
+ 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Written by Brian Fox (bfox@ai.mit.edu). */
+
+#include "info.h"
+
+/* Return a line describing the format of a node information line. */
+static char *
+nodemenu_format_info ()
+{
+ return ("\n\
+* Menu:\n\
+ (File)Node Lines Size Containing File\n\
+ ---------- ----- ---- ---------------");
+}
+
+/* Produce a formatted line of information about NODE. Here is what we want
+ the output listing to look like:
+
+* Menu:
+ (File)Node Lines Size Containing File
+ ---------- ----- ---- ---------------
+* (emacs)Buffers:: 48 2230 /usr/gnu/info/emacs/emacs-1
+* (autoconf)Writing configure.in:: 123 58789 /usr/gnu/info/autoconf/autoconf-1
+* (dir)Top:: 40 589 /usr/gnu/info/dir
+*/
+static char *
+format_node_info (node)
+ NODE *node;
+{
+ register int i, len;
+ char *parent, *containing_file;
+ static char *line_buffer = (char *)NULL;
+
+ if (!line_buffer)
+ line_buffer = (char *)xmalloc (1000);
+
+ if (node->parent)
+ {
+ parent = filename_non_directory (node->parent);
+ if (!parent)
+ parent = node->parent;
+ }
+ else
+ parent = (char *)NULL;
+
+ containing_file = node->filename;
+
+ if (!parent && !*containing_file)
+ sprintf (line_buffer, "* %s::", node->nodename);
+ else
+ {
+ char *file = (char *)NULL;
+
+ if (parent)
+ file = parent;
+ else
+ file = filename_non_directory (containing_file);
+
+ if (!file)
+ file = containing_file;
+
+ if (!*file)
+ file = "dir";
+
+ sprintf (line_buffer, "* (%s)%s::", file, node->nodename);
+ }
+
+ len = pad_to (36, line_buffer);
+
+ {
+ int lines = 1;
+
+ for (i = 0; i < node->nodelen; i++)
+ if (node->contents[i] == '\n')
+ lines++;
+
+ sprintf (line_buffer + len, "%d", lines);
+ }
+
+ len = pad_to (44, line_buffer);
+ sprintf (line_buffer + len, "%d", node->nodelen);
+
+ if (node->filename && *(node->filename))
+ {
+ len = pad_to (51, line_buffer);
+ sprintf (line_buffer + len, node->filename);
+ }
+
+ return (strdup (line_buffer));
+}
+
+/* Little string comparison routine for qsort (). */
+static int
+compare_strings (string1, string2)
+ char **string1, **string2;
+{
+ return (strcasecmp (*string1, *string2));
+}
+
+/* The name of the nodemenu node. */
+static char *nodemenu_nodename = "*Node Menu*";
+
+/* Produce an informative listing of all the visited nodes, and return it
+ in a node. If FILTER_FUNC is non-null, it is a function which filters
+ which nodes will appear in the listing. FILTER_FUNC takes an argument
+ of NODE, and returns non-zero if the node should appear in the listing. */
+NODE *
+get_visited_nodes (filter_func)
+ Function *filter_func;
+{
+ register int i, iw_index;
+ INFO_WINDOW *info_win;
+ NODE *node;
+ char **lines = (char **)NULL;
+ int lines_index = 0, lines_slots = 0;
+
+ if (!info_windows)
+ return ((NODE *)NULL);
+
+ for (iw_index = 0; info_win = info_windows[iw_index]; iw_index++)
+ {
+ for (i = 0; i < info_win->nodes_index; i++)
+ {
+ node = info_win->nodes[i];
+
+ /* We skip mentioning "*Node Menu*" nodes. */
+ if (internal_info_node_p (node) &&
+ (strcmp (node->nodename, nodemenu_nodename) == 0))
+ continue;
+
+ if (node && (!filter_func || (*filter_func) (node)))
+ {
+ char *line;
+
+ line = format_node_info (node);
+ add_pointer_to_array
+ (line, lines_index, lines, lines_slots, 20, char *);
+ }
+ }
+ }
+
+ /* Sort the array of information lines, if there are any. */
+ if (lines)
+ {
+ register int j, newlen;
+ char **temp;
+
+ qsort (lines, lines_index, sizeof (char *), compare_strings);
+
+ /* Delete duplicates. */
+ for (i = 0, newlen = 1; i < lines_index - 1; i++)
+ {
+ if (strcmp (lines[i], lines[i + 1]) == 0)
+ {
+ free (lines[i]);
+ lines[i] = (char *)NULL;
+ }
+ else
+ newlen++;
+ }
+
+ /* We have free ()'d and marked all of the duplicate slots.
+ Copy the live slots rather than pruning the dead slots. */
+ temp = (char **)xmalloc ((1 + newlen) * sizeof (char *));
+ for (i = 0, j = 0; i < lines_index; i++)
+ if (lines[i])
+ temp[j++] = lines[i];
+
+ temp[j] = (char *)NULL;
+ free (lines);
+ lines = temp;
+ lines_index = newlen;
+ }
+
+ initialize_message_buffer ();
+
+ printf_to_message_buffer
+ ("%s", replace_in_documentation
+ ("Here is the menu of nodes you have recently visited.\n\
+Select one from this menu, or use `\\[history-node]' in another window.\n"));
+
+ printf_to_message_buffer ("%s\n", nodemenu_format_info ());
+
+ for (i = 0; (lines != (char **)NULL) && (i < lines_index); i++)
+ {
+ printf_to_message_buffer ("%s\n", lines[i]);
+ free (lines[i]);
+ }
+
+ if (lines)
+ free (lines);
+
+ node = message_buffer_to_node ();
+ add_gcable_pointer (node->contents);
+ return (node);
+}
+
+DECLARE_INFO_COMMAND (list_visited_nodes,
+ "Make a window containing a menu of all of the currently visited nodes")
+{
+ WINDOW *new;
+ NODE *node;
+
+ set_remembered_pagetop_and_point (window);
+
+ /* If a window is visible and showing the buffer list already, re-use it. */
+ for (new = windows; new; new = new->next)
+ {
+ node = new->node;
+
+ if (internal_info_node_p (node) &&
+ (strcmp (node->nodename, nodemenu_nodename) == 0))
+ break;
+ }
+
+ /* If we couldn't find an existing window, try to use the next window
+ in the chain. */
+ if (!new && window->next)
+ new = window->next;
+
+ /* If we still don't have a window, make a new one to contain the list. */
+ if (!new)
+ {
+ WINDOW *old_active;
+
+ old_active = active_window;
+ active_window = window;
+ new = window_make_window ((NODE *)NULL);
+ active_window = old_active;
+ }
+
+ /* If we couldn't make a new window, use this one. */
+ if (!new)
+ new = window;
+
+ /* Lines do not wrap in this window. */
+ new->flags |= W_NoWrap;
+ node = get_visited_nodes ((Function *)NULL);
+ name_internal_node (node, nodemenu_nodename);
+
+ /* Even if this is an internal node, we don't want the window
+ system to treat it specially. So we turn off the internalness
+ of it here. */
+ node->flags &= ~N_IsInternal;
+
+ /* If this window is already showing a node menu, reuse the existing node
+ slot. */
+ {
+ int remember_me = 1;
+
+#if defined (NOTDEF)
+ if (internal_info_node_p (new->node) &&
+ (strcmp (new->node->nodename, nodemenu_nodename) == 0))
+ remember_me = 0;
+#endif /* NOTDEF */
+
+ window_set_node_of_window (new, node);
+
+ if (remember_me)
+ remember_window_and_node (new, node);
+ }
+
+ active_window = new;
+}
+
+DECLARE_INFO_COMMAND (select_visited_node,
+ "Select a node which has been previously visited in a visible window")
+{
+ char *line;
+ NODE *node;
+ REFERENCE **menu;
+
+ node = get_visited_nodes ((Function *)NULL);
+
+ menu = info_menu_of_node (node);
+ free (node);
+
+ line =
+ info_read_completing_in_echo_area (window, "Select visited node: ", menu);
+
+ window = active_window;
+
+ /* User aborts, just quit. */
+ if (!line)
+ {
+ info_abort_key (window, 0, 0);
+ info_free_references (menu);
+ return;
+ }
+
+ if (*line)
+ {
+ REFERENCE *entry;
+
+ /* Find the selected label in the references. */
+ entry = info_get_labeled_reference (line, menu);
+
+ if (!entry)
+ info_error ("The reference disappeared! (%s).", line);
+ else
+ info_select_reference (window, entry);
+ }
+
+ free (line);
+ info_free_references (menu);
+
+ if (!info_error_was_printed)
+ window_clear_echo_area ();
+}
diff --git a/contrib/texinfo/info/nodes.c b/contrib/texinfo/info/nodes.c
new file mode 100644
index 0000000..8995c78
--- /dev/null
+++ b/contrib/texinfo/info/nodes.c
@@ -0,0 +1,1207 @@
+/* nodes.c -- How to get an Info file and node. */
+
+/* This file is part of GNU Info, a program for reading online documentation
+ stored in Info format.
+
+ Copyright (C) 1993 Free Software Foundation, Inc.
+
+ 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Written by Brian Fox (bfox@ai.mit.edu). */
+
+#include <stdio.h>
+#include <ctype.h>
+#include <sys/types.h>
+#if defined (HAVE_SYS_FILE_H)
+#include <sys/file.h>
+#endif /* HAVE_SYS_FILE_H */
+#include <sys/errno.h>
+#include <sys/stat.h>
+#if defined (HAVE_STRING_H)
+#include <string.h>
+#endif /* HAVE_STRING_H */
+#include "nodes.h"
+#include "search.h"
+#include "filesys.h"
+#include "info-utils.h"
+
+#if defined (HANDLE_MAN_PAGES)
+# include "man.h"
+#endif /* HANDLE_MAN_PAGES */
+
+#if !defined (O_RDONLY)
+#if defined (HAVE_SYS_FCNTL_H)
+#include <sys/fcntl.h>
+#else /* !HAVE_SYS_FCNTL_H */
+#include <fcntl.h>
+#endif /* !HAVE_SYS_FCNTL_H */
+#endif /* !O_RDONLY */
+
+#if !defined (errno)
+extern int errno;
+#endif /* !errno */
+
+/* **************************************************************** */
+/* */
+/* Functions Static to this File */
+/* */
+/* **************************************************************** */
+
+static void forget_info_file (), remember_info_file ();
+static void free_file_buffer_tags (), free_info_tag ();
+static void get_nodes_of_tags_table (), get_nodes_of_info_file ();
+static void get_tags_of_indirect_tags_table ();
+static void info_reload_file_buffer_contents ();
+static char *adjust_nodestart ();
+static FILE_BUFFER *info_load_file_internal (), *info_find_file_internal ();
+static NODE *info_node_of_file_buffer_tags ();
+
+static long get_node_length ();
+
+/* Magic number that RMS used to decide how much a tags table pointer could
+ be off by. I feel that it should be much smaller, like on the order of
+ 4. */
+#define DEFAULT_INFO_FUDGE 1000
+
+/* Passed to *_internal functions. INFO_GET_TAGS says to do what is
+ neccessary to fill in the nodes or tags arrays in FILE_BUFFER. */
+#define INFO_NO_TAGS 0
+#define INFO_GET_TAGS 1
+
+/* **************************************************************** */
+/* */
+/* Global Variables */
+/* */
+/* **************************************************************** */
+
+/* When non-zero, this is a string describing the recent file error. */
+char *info_recent_file_error = (char *)NULL;
+
+/* The list of already loaded nodes. */
+FILE_BUFFER **info_loaded_files = (FILE_BUFFER **)NULL;
+
+/* The number of slots currently allocated to LOADED_FILES. */
+int info_loaded_files_slots = 0;
+
+/* **************************************************************** */
+/* */
+/* Public Functions for Node Manipulation */
+/* */
+/* **************************************************************** */
+
+/* Used to build "dir" menu from "localdir" files found in INFOPATH. */
+extern void maybe_build_dir_node ();
+
+/* Return a pointer to a NODE structure for the Info node (FILENAME)NODENAME.
+ FILENAME can be passed as NULL, in which case the filename of "dir" is used.
+ NODENAME can be passed as NULL, in which case the nodename of "Top" is used.
+ If the node cannot be found, return a NULL pointer. */
+NODE *
+info_get_node (filename, nodename)
+ char *filename, *nodename;
+{
+ FILE_BUFFER *file_buffer;
+ NODE *node;
+
+ file_buffer = (FILE_BUFFER *)NULL;
+ info_recent_file_error = (char *)NULL;
+
+ info_parse_node (nodename, DONT_SKIP_NEWLINES);
+ nodename = (char *)NULL;
+
+ if (info_parsed_filename)
+ filename = info_parsed_filename;
+
+ if (info_parsed_nodename)
+ nodename = info_parsed_nodename;
+
+ /* If FILENAME is not specified, it defaults to "dir". */
+ if (!filename)
+ filename = "dir";
+
+ /* If the file to be looked up is "dir", build the contents from all of
+ the "dir"s and "localdir"s found in INFOPATH. */
+ if (strcasecmp (filename, "dir") == 0)
+ maybe_build_dir_node (filename);
+
+ /* Find the correct info file. */
+ file_buffer = info_find_file (filename);
+
+ if (!file_buffer)
+ {
+ if (filesys_error_number)
+ info_recent_file_error =
+ filesys_error_string (filename, filesys_error_number);
+ return ((NODE *)NULL);
+ }
+
+ node = info_get_node_of_file_buffer (nodename, file_buffer);
+ /* If the node looked for was "Top", try again looking for the node under
+ a slightly different name. */
+ if (!node && (nodename == NULL || strcasecmp (nodename, "Top") == 0))
+ {
+ node = info_get_node_of_file_buffer ("Top", file_buffer);
+ if (!node)
+ node = info_get_node_of_file_buffer ("top", file_buffer);
+ if (!node)
+ node = info_get_node_of_file_buffer ("TOP", file_buffer);
+ }
+ return (node);
+}
+
+/* Return a pointer to a NODE structure for the Info node NODENAME in
+ FILE_BUFFER. NODENAME can be passed as NULL, in which case the
+ nodename of "Top" is used. If the node cannot be found, return a
+ NULL pointer. */
+NODE *
+info_get_node_of_file_buffer (nodename, file_buffer)
+ char *nodename;
+ FILE_BUFFER *file_buffer;
+{
+ NODE *node = (NODE *)NULL;
+
+ /* If we are unable to find the file, we have to give up. There isn't
+ anything else we can do. */
+ if (!file_buffer)
+ return ((NODE *)NULL);
+
+ /* If the file buffer was gc'ed, reload the contents now. */
+ if (!file_buffer->contents)
+ info_reload_file_buffer_contents (file_buffer);
+
+ /* If NODENAME is not specified, it defaults to "Top". */
+ if (!nodename)
+ nodename = "Top";
+
+ /* If the name of the node that we wish to find is exactly "*", then the
+ node body is the contents of the entire file. Create and return such
+ a node. */
+ if (strcmp (nodename, "*") == 0)
+ {
+ node = (NODE *)xmalloc (sizeof (NODE));
+ node->filename = file_buffer->fullpath;
+ node->parent = (char *)NULL;
+ node->nodename = strdup ("*");
+ node->contents = file_buffer->contents;
+ node->nodelen = file_buffer->filesize;
+ node->flags = 0;
+ }
+#if defined (HANDLE_MAN_PAGES)
+ /* If the file buffer is the magic one associated with manpages, call
+ the manpage node finding function instead. */
+ else if (file_buffer->flags & N_IsManPage)
+ {
+ node = get_manpage_node (file_buffer, nodename);
+ }
+#endif /* HANDLE_MAN_PAGES */
+ /* If this is the "main" info file, it might contain a tags table. Search
+ the tags table for an entry which matches the node that we want. If
+ there is a tags table, get the file which contains this node, but don't
+ bother building a node list for it. */
+ else if (file_buffer->tags)
+ {
+ node = info_node_of_file_buffer_tags (file_buffer, nodename);
+ }
+
+ /* Return the results of our node search. */
+ return (node);
+}
+
+/* Locate the file named by FILENAME, and return the information structure
+ describing this file. The file may appear in our list of loaded files
+ already, or it may not. If it does not already appear, find the file,
+ and add it to the list of loaded files. If the file cannot be found,
+ return a NULL FILE_BUFFER *. */
+FILE_BUFFER *
+info_find_file (filename)
+ char *filename;
+{
+ return (info_find_file_internal (filename, INFO_GET_TAGS));
+}
+
+/* Load the info file FILENAME, remembering information about it in a
+ file buffer. */
+FILE_BUFFER *
+info_load_file (filename)
+ char *filename;
+{
+ return (info_load_file_internal (filename, INFO_GET_TAGS));
+}
+
+
+/* **************************************************************** */
+/* */
+/* Private Functions Implementation */
+/* */
+/* **************************************************************** */
+
+/* The workhorse for info_find_file (). Non-zero 2nd argument says to
+ try to build a tags table (or otherwise glean the nodes) for this
+ file once found. By default, we build the tags table, but when this
+ function is called by info_get_node () when we already have a valid
+ tags table describing the nodes, it is unnecessary. */
+static FILE_BUFFER *
+info_find_file_internal (filename, get_tags)
+ char *filename;
+ int get_tags;
+{
+ register int i;
+ register FILE_BUFFER *file_buffer;
+
+ /* First try to find the file in our list of already loaded files. */
+ if (info_loaded_files)
+ {
+ for (i = 0; file_buffer = info_loaded_files[i]; i++)
+ if ((strcmp (filename, file_buffer->filename) == 0) ||
+ (strcmp (filename, file_buffer->fullpath) == 0) ||
+ ((*filename != '/') &&
+ strcmp (filename,
+ filename_non_directory (file_buffer->fullpath)) == 0))
+ {
+ struct stat new_info, *old_info;
+
+ /* This file is loaded. If the filename that we want is
+ specifically "dir", then simply return the file buffer. */
+ if (strcasecmp (filename_non_directory (filename), "dir") == 0)
+ return (file_buffer);
+
+#if defined (HANDLE_MAN_PAGES)
+ /* Do the same for the magic MANPAGE file. */
+ if (file_buffer->flags & N_IsManPage)
+ return (file_buffer);
+#endif /* HANDLE_MAN_PAGES */
+
+ /* The file appears to be already loaded, and it is not "dir".
+ Check to see if it has changed since the last time it was
+ loaded. */
+ if (stat (file_buffer->fullpath, &new_info) == -1)
+ {
+ filesys_error_number = errno;
+ return ((FILE_BUFFER *)NULL);
+ }
+
+ old_info = &file_buffer->finfo;
+
+ if ((new_info.st_size != old_info->st_size) ||
+ (new_info.st_mtime != old_info->st_mtime))
+ {
+ /* The file has changed. Forget that we ever had loaded it
+ in the first place. */
+ forget_info_file (filename);
+ break;
+ }
+ else
+ {
+ /* The info file exists, and has not changed since the last
+ time it was loaded. If the caller requested a nodes list
+ for this file, and there isn't one here, build the nodes
+ for this file_buffer. In any case, return the file_buffer
+ object. */
+ if (get_tags && !file_buffer->tags)
+ build_tags_and_nodes (file_buffer);
+
+ return (file_buffer);
+ }
+ }
+ }
+
+ /* The file wasn't loaded. Try to load it now. */
+#if defined (HANDLE_MAN_PAGES)
+ /* If the name of the file that we want is our special file buffer for
+ Unix manual pages, then create the file buffer, and return it now. */
+ if (strcasecmp (filename, MANPAGE_FILE_BUFFER_NAME) == 0)
+ file_buffer = create_manpage_file_buffer ();
+ else
+#endif /* HANDLE_MAN_PAGES */
+ file_buffer = info_load_file_internal (filename, get_tags);
+
+ /* If the file was loaded, remember the name under which it was found. */
+ if (file_buffer)
+ remember_info_file (file_buffer);
+
+ return (file_buffer);
+}
+
+/* The workhorse function for info_load_file (). Non-zero second argument
+ says to build a list of tags (or nodes) for this file. This is the
+ default behaviour when info_load_file () is called, but it is not
+ necessary when loading a subfile for which we already have tags. */
+static FILE_BUFFER *
+info_load_file_internal (filename, get_tags)
+ char *filename;
+ int get_tags;
+{
+ char *fullpath, *contents;
+ long filesize;
+ struct stat finfo;
+ int retcode;
+ FILE_BUFFER *file_buffer = (FILE_BUFFER *)NULL;
+
+ /* Get the full pathname of this file, as known by the info system.
+ That is to say, search along INFOPATH and expand tildes, etc. */
+ fullpath = info_find_fullpath (filename);
+
+ /* Did we actually find the file? */
+ retcode = stat (fullpath, &finfo);
+
+ /* If the file referenced by the name returned from info_find_fullpath ()
+ doesn't exist, then try again with the last part of the filename
+ appearing in lowercase. */
+ if (retcode < 0)
+ {
+ char *lowered_name;
+ char *basename;
+
+ lowered_name = strdup (filename);
+ basename = (char *) strrchr (lowered_name, '/');
+
+ if (basename)
+ basename++;
+ else
+ basename = lowered_name;
+
+ while (*basename)
+ {
+ if (isupper (*basename))
+ *basename = tolower (*basename);
+
+ basename++;
+ }
+
+ fullpath = info_find_fullpath (lowered_name);
+ free (lowered_name);
+
+ retcode = stat (fullpath, &finfo);
+ }
+
+ /* If the file wasn't found, give up, returning a NULL pointer. */
+ if (retcode < 0)
+ {
+ filesys_error_number = errno;
+ return ((FILE_BUFFER *)NULL);
+ }
+
+ /* Otherwise, try to load the file. */
+ contents = filesys_read_info_file (fullpath, &filesize, &finfo);
+
+ if (!contents)
+ return ((FILE_BUFFER *)NULL);
+
+ /* The file was found, and can be read. Allocate FILE_BUFFER and fill
+ in the various members. */
+ file_buffer = make_file_buffer ();
+ file_buffer->filename = strdup (filename);
+ file_buffer->fullpath = strdup (fullpath);
+ file_buffer->finfo = finfo;
+ file_buffer->filesize = filesize;
+ file_buffer->contents = contents;
+ if (file_buffer->filesize != file_buffer->finfo.st_size)
+ file_buffer->flags |= N_IsCompressed;
+
+ /* If requested, build the tags and nodes for this file buffer. */
+ if (get_tags)
+ build_tags_and_nodes (file_buffer);
+
+ return (file_buffer);
+}
+
+/* Grovel FILE_BUFFER->contents finding tags and nodes, and filling in the
+ various slots. This can also be used to rebuild a tag or node table. */
+void
+build_tags_and_nodes (file_buffer)
+ FILE_BUFFER *file_buffer;
+{
+ SEARCH_BINDING binding;
+ long position;
+
+ free_file_buffer_tags (file_buffer);
+ file_buffer->flags &= ~N_HasTagsTable;
+
+ /* See if there is a tags table in this info file. */
+ binding.buffer = file_buffer->contents;
+ binding.start = file_buffer->filesize;
+ binding.end = binding.start - 1000;
+ if (binding.end < 0)
+ binding.end = 0;
+ binding.flags = S_FoldCase;
+
+ position = search_backward (TAGS_TABLE_END_LABEL, &binding);
+
+ /* If there is a tag table, find the start of it, and grovel over it
+ extracting tag information. */
+ if (position != -1)
+ while (1)
+ {
+ long tags_table_begin, tags_table_end;
+
+ binding.end = position;
+ binding.start = binding.end - 5 - strlen (TAGS_TABLE_END_LABEL);
+ if (binding.start < 0)
+ binding.start = 0;
+
+ position = find_node_separator (&binding);
+
+ /* For this test, (and all others here) failure indicates a bogus
+ tags table. Grovel the file. */
+ if (position == -1)
+ break;
+
+ /* Remember the end of the tags table. */
+ binding.start = position;
+ tags_table_end = binding.start;
+ binding.end = 0;
+
+ /* Locate the start of the tags table. */
+ position = search_backward (TAGS_TABLE_BEG_LABEL, &binding);
+
+ if (position == -1)
+ break;
+
+ binding.end = position;
+ binding.start = binding.end - 5 - strlen (TAGS_TABLE_BEG_LABEL);
+ position = find_node_separator (&binding);
+
+ if (position == -1)
+ break;
+
+ /* The file contains a valid tags table. Fill the FILE_BUFFER's
+ tags member. */
+ file_buffer->flags |= N_HasTagsTable;
+ tags_table_begin = position;
+
+ /* If this isn't an indirect tags table, just remember the nodes
+ described locally in this tags table. Note that binding.end
+ is pointing to just after the beginning label. */
+ binding.start = binding.end;
+ binding.end = file_buffer->filesize;
+
+ if (!looking_at (TAGS_TABLE_IS_INDIRECT_LABEL, &binding))
+ {
+ binding.start = tags_table_begin;
+ binding.end = tags_table_end;
+ get_nodes_of_tags_table (file_buffer, &binding);
+ return;
+ }
+ else
+ {
+ /* This is an indirect tags table. Build TAGS member. */
+ SEARCH_BINDING indirect;
+
+ indirect.start = tags_table_begin;
+ indirect.end = 0;
+ indirect.buffer = binding.buffer;
+ indirect.flags = S_FoldCase;
+
+ position = search_backward (INDIRECT_TAGS_TABLE_LABEL, &indirect);
+
+ if (position == -1)
+ {
+ /* This file is malformed. Give up. */
+ return;
+ }
+
+ indirect.start = position;
+ indirect.end = tags_table_begin;
+ binding.start = tags_table_begin;
+ binding.end = tags_table_end;
+ get_tags_of_indirect_tags_table (file_buffer, &indirect, &binding);
+ return;
+ }
+ }
+
+ /* This file doesn't contain any kind of tags table. Grovel the
+ file and build node entries for it. */
+ get_nodes_of_info_file (file_buffer);
+}
+
+/* Search through FILE_BUFFER->contents building an array of TAG *,
+ one entry per each node present in the file. Store the tags in
+ FILE_BUFFER->tags, and the number of allocated slots in
+ FILE_BUFFER->tags_slots. */
+static void
+get_nodes_of_info_file (file_buffer)
+ FILE_BUFFER *file_buffer;
+{
+ long nodestart;
+ int tags_index = 0;
+ SEARCH_BINDING binding;
+
+ binding.buffer = file_buffer->contents;
+ binding.start = 0;
+ binding.end = file_buffer->filesize;
+ binding.flags = S_FoldCase;
+
+ while ((nodestart = find_node_separator (&binding)) != -1)
+ {
+ int start, end;
+ char *nodeline;
+ TAG *entry;
+
+ /* Skip past the characters just found. */
+ binding.start = nodestart;
+ binding.start += skip_node_separator (binding.buffer + binding.start);
+
+ /* Move to the start of the line defining the node. */
+ nodeline = binding.buffer + binding.start;
+
+ /* Find "Node:" */
+ start = string_in_line (INFO_NODE_LABEL, nodeline);
+
+ /* If not there, this is not the start of a node. */
+ if (start == -1)
+ continue;
+
+ /* Find the start of the nodename. */
+ start += skip_whitespace (nodeline + start);
+
+ /* Find the end of the nodename. */
+ end = start +
+ skip_node_characters (nodeline + start, DONT_SKIP_NEWLINES);
+
+ /* Okay, we have isolated the node name, and we know where the
+ node starts. Remember this information in a NODE structure. */
+ entry = (TAG *)xmalloc (sizeof (TAG));
+ entry->nodename = (char *)xmalloc (1 + (end - start));
+ strncpy (entry->nodename, nodeline + start, end - start);
+ entry->nodename[end - start] = '\0';
+ entry->nodestart = nodestart;
+ {
+ SEARCH_BINDING node_body;
+
+ node_body.buffer = binding.buffer + binding.start;
+ node_body.start = 0;
+ node_body.end = binding.end - binding.start;
+ node_body.flags = S_FoldCase;
+ entry->nodelen = get_node_length (&node_body);
+ }
+
+ entry->filename = file_buffer->fullpath;
+
+ /* Add this tag to the array of tag structures in this FILE_BUFFER. */
+ add_pointer_to_array (entry, tags_index, file_buffer->tags,
+ file_buffer->tags_slots, 100, TAG *);
+ }
+}
+
+/* Return the length of the node which starts at BINDING. */
+static long
+get_node_length (binding)
+ SEARCH_BINDING *binding;
+{
+ register int i;
+ char *body;
+
+ /* From the Info-RFC file:
+ [A node] ends with either a ^_, a ^L, or the end of file. */
+ for (i = binding->start, body = binding->buffer; i < binding->end; i++)
+ {
+ if (body[i] == INFO_FF || body[i] == INFO_COOKIE)
+ break;
+ }
+ return ((long) i - binding->start);
+}
+
+/* Build and save the array of nodes in FILE_BUFFER by searching through the
+ contents of BUFFER_BINDING for a tags table, and groveling the contents. */
+static void
+get_nodes_of_tags_table (file_buffer, buffer_binding)
+ FILE_BUFFER *file_buffer;
+ SEARCH_BINDING *buffer_binding;
+{
+ int offset, tags_index = 0;
+ SEARCH_BINDING *search;
+ long position;
+
+ search = copy_binding (buffer_binding);
+
+ /* Find the start of the tags table. */
+ position = find_tags_table (search);
+
+ /* If none, we're all done. */
+ if (position == -1)
+ return;
+
+ /* Move to one character before the start of the actual table. */
+ search->start = position;
+ search->start += skip_node_separator (search->buffer + search->start);
+ search->start += strlen (TAGS_TABLE_BEG_LABEL);
+ search->start--;
+
+ /* The tag table consists of lines containing node names and positions.
+ Do each line until we find one that doesn't contain a node name. */
+ while ((position = search_forward ("\n", search)) != -1)
+ {
+ TAG *entry;
+ char *nodedef;
+
+ /* Prepare to skip this line. */
+ search->start = position;
+ search->start++;
+
+ /* Skip past informative "(Indirect)" tags table line. */
+ if (!tags_index && looking_at (TAGS_TABLE_IS_INDIRECT_LABEL, search))
+ continue;
+
+ /* Find the label preceding the node name. */
+ offset =
+ string_in_line (INFO_NODE_LABEL, search->buffer + search->start);
+
+ /* If not there, not a defining line, so we must be out of the
+ tags table. */
+ if (offset == -1)
+ break;
+
+ /* Point to the beginning of the node definition. */
+ search->start += offset;
+ nodedef = search->buffer + search->start;
+ nodedef += skip_whitespace (nodedef);
+
+ /* Move past the node's name. */
+ for (offset = 0;
+ (nodedef[offset]) && (nodedef[offset] != INFO_TAGSEP);
+ offset++);
+
+ if (nodedef[offset] != INFO_TAGSEP)
+ continue;
+
+ entry = (TAG *)xmalloc (sizeof (TAG));
+ entry->nodename = (char *)xmalloc (1 + offset);
+ strncpy (entry->nodename, nodedef, offset);
+ entry->nodename[offset] = '\0';
+ offset++;
+ entry->nodestart = (long) atol (nodedef + offset);
+
+ /* We don't know the length of this node yet. */
+ entry->nodelen = -1;
+
+ /* The filename of this node is currently known as the same as the
+ name of this file. */
+ entry->filename = file_buffer->fullpath;
+
+ /* Add this node structure to the array of node structures in this
+ FILE_BUFFER. */
+ add_pointer_to_array (entry, tags_index, file_buffer->tags,
+ file_buffer->tags_slots, 100, TAG *);
+ }
+ free (search);
+}
+
+/* A structure used only in get_tags_of_indirect_tags_table () to hold onto
+ an intermediate value. */
+typedef struct {
+ char *filename;
+ long first_byte;
+} SUBFILE;
+
+/* Remember in FILE_BUFFER the nodenames, subfilenames, and offsets within the
+ subfiles of every node which appears in TAGS_BINDING. The 2nd argument is
+ a binding surrounding the indirect files list. */
+static void
+get_tags_of_indirect_tags_table (file_buffer, indirect_binding, tags_binding)
+ FILE_BUFFER *file_buffer;
+ SEARCH_BINDING *indirect_binding, *tags_binding;
+{
+ register int i;
+ SUBFILE **subfiles = (SUBFILE **)NULL;
+ int subfiles_index = 0, subfiles_slots = 0;
+ TAG *entry;
+
+ /* First get the list of tags from the tags table. Then lookup the
+ associated file in the indirect list for each tag, and update it. */
+ get_nodes_of_tags_table (file_buffer, tags_binding);
+
+ /* We have the list of tags in file_buffer->tags. Get the list of
+ subfiles from the indirect table. */
+ {
+ char *start, *end, *line;
+ SUBFILE *subfile;
+
+ start = indirect_binding->buffer + indirect_binding->start;
+ end = indirect_binding->buffer + indirect_binding->end;
+ line = start;
+
+ while (line < end)
+ {
+ int colon;
+
+ colon = string_in_line (":", line);
+
+ if (colon == -1)
+ break;
+
+ subfile = (SUBFILE *)xmalloc (sizeof (SUBFILE));
+ subfile->filename = (char *)xmalloc (colon);
+ strncpy (subfile->filename, line, colon - 1);
+ subfile->filename[colon - 1] = '\0';
+ subfile->first_byte = (long) atol (line + colon);
+
+ add_pointer_to_array
+ (subfile, subfiles_index, subfiles, subfiles_slots, 10, SUBFILE *);
+
+ while (*line++ != '\n');
+ }
+ }
+
+ /* If we have successfully built the indirect files table, then
+ merge the information in the two tables. */
+ if (!subfiles)
+ {
+ free_file_buffer_tags (file_buffer);
+ return;
+ }
+ else
+ {
+ register int tags_index;
+ long header_length;
+ SEARCH_BINDING binding;
+
+ /* Find the length of the header of the file containing the indirect
+ tags table. This header appears at the start of every file. We
+ want the absolute position of each node within each subfile, so
+ we subtract the start of the containing subfile from the logical
+ position of the node, and then add the length of the header in. */
+ binding.buffer = file_buffer->contents;
+ binding.start = 0;
+ binding.end = file_buffer->filesize;
+ binding.flags = S_FoldCase;
+
+ header_length = find_node_separator (&binding);
+ if (header_length == -1)
+ header_length = 0;
+
+ /* Build the file buffer's list of subfiles. */
+ {
+ char *containing_dir, *temp;
+ int len_containing_dir;
+
+ containing_dir = strdup (file_buffer->fullpath);
+ temp = (char *) strrchr (containing_dir, '/');
+
+ if (temp)
+ *temp = '\0';
+
+ len_containing_dir = strlen (containing_dir);
+
+ for (i = 0; subfiles[i]; i++);
+
+ file_buffer->subfiles = (char **) xmalloc ((1 + i) * sizeof (char *));
+
+ for (i = 0; subfiles[i]; i++)
+ {
+ char *fullpath;
+
+ fullpath = (char *) xmalloc
+ (2 + strlen (subfiles[i]->filename) + len_containing_dir);
+
+ sprintf (fullpath, "%s/%s",
+ containing_dir, subfiles[i]->filename);
+
+ file_buffer->subfiles[i] = fullpath;
+ }
+ file_buffer->subfiles[i] = (char *)NULL;
+ free (containing_dir);
+ }
+
+ /* For each node in the file's tags table, remember the starting
+ position. */
+ for (tags_index = 0;
+ entry = file_buffer->tags[tags_index];
+ tags_index++)
+ {
+ for (i = 0;
+ subfiles[i] && entry->nodestart >= subfiles[i]->first_byte;
+ i++);
+
+ /* If the Info file containing the indirect tags table is
+ malformed, then give up. */
+ if (!i)
+ {
+ /* The Info file containing the indirect tags table is
+ malformed. Give up. */
+ for (i = 0; subfiles[i]; i++)
+ {
+ free (subfiles[i]->filename);
+ free (subfiles[i]);
+ free (file_buffer->subfiles[i]);
+ }
+ file_buffer->subfiles = (char **)NULL;
+ free_file_buffer_tags (file_buffer);
+ return;
+ }
+
+ /* SUBFILES[i] is the index of the first subfile whose logical
+ first byte is greater than the logical offset of this node's
+ starting position. This means that the subfile directly
+ preceding this one is the one containing the node. */
+
+ entry->filename = file_buffer->subfiles[i - 1];
+ entry->nodestart -= subfiles[i -1]->first_byte;
+ entry->nodestart += header_length;
+ entry->nodelen = -1;
+ }
+
+ /* We have successfully built the tags table. Remember that it
+ was indirect. */
+ file_buffer->flags |= N_TagsIndirect;
+ }
+
+ /* Free the structures assigned to SUBFILES. Free the names as well
+ as the structures themselves, then finally, the array. */
+ for (i = 0; subfiles[i]; i++)
+ {
+ free (subfiles[i]->filename);
+ free (subfiles[i]);
+ }
+ free (subfiles);
+}
+
+/* Return the node from FILE_BUFFER which matches NODENAME by searching
+ the tags table in FILE_BUFFER. If the node could not be found, return
+ a NULL pointer. */
+static NODE *
+info_node_of_file_buffer_tags (file_buffer, nodename)
+ FILE_BUFFER *file_buffer;
+ char *nodename;
+{
+ register int i;
+ TAG *tag;
+
+ for (i = 0; tag = file_buffer->tags[i]; i++)
+ if (strcmp (nodename, tag->nodename) == 0)
+ {
+ FILE_BUFFER *subfile;
+
+ subfile = info_find_file_internal (tag->filename, INFO_NO_TAGS);
+
+ if (!subfile)
+ return ((NODE *)NULL);
+
+ if (!subfile->contents)
+ {
+ info_reload_file_buffer_contents (subfile);
+
+ if (!subfile->contents)
+ return ((NODE *)NULL);
+ }
+
+ /* If we were able to find this file and load it, then return
+ the node within it. */
+ {
+ NODE *node;
+
+ node = (NODE *)xmalloc (sizeof (NODE));
+ node->filename = (subfile->fullpath);
+ node->nodename = tag->nodename;
+ node->contents = subfile->contents + tag->nodestart;
+ node->flags = 0;
+ node->parent = (char *)NULL;
+
+ if (file_buffer->flags & N_HasTagsTable)
+ {
+ node->flags |= N_HasTagsTable;
+
+ if (file_buffer->flags & N_TagsIndirect)
+ {
+ node->flags |= N_TagsIndirect;
+ node->parent = file_buffer->fullpath;
+ }
+ }
+
+ if (subfile->flags & N_IsCompressed)
+ node->flags |= N_IsCompressed;
+
+ /* If TAG->nodelen hasn't been calculated yet, then we aren't
+ in a position to trust the entry pointer. Adjust things so
+ that ENTRY->nodestart gets the exact address of the start of
+ the node separator which starts this node, and NODE->contents
+ gets the address of the line defining this node. If we cannot
+ do that, the node isn't really here. */
+ if (tag->nodelen == -1)
+ {
+ int min, max;
+ char *node_sep;
+ SEARCH_BINDING node_body;
+ char *buff_end;
+
+ min = max = DEFAULT_INFO_FUDGE;
+
+ if (tag->nodestart < DEFAULT_INFO_FUDGE)
+ min = tag->nodestart;
+
+ if (DEFAULT_INFO_FUDGE >
+ (subfile->filesize - tag->nodestart))
+ max = subfile->filesize - tag->nodestart;
+
+ /* NODE_SEP gets the address of the separator which defines
+ this node, or (char *)NULL if the node wasn't found.
+ NODE->contents is side-effected to point to right after
+ the separator. */
+ node_sep = adjust_nodestart (node, min, max);
+ if (node_sep == (char *)NULL)
+ {
+ free (node);
+ return ((NODE *)NULL);
+ }
+ /* Readjust tag->nodestart. */
+ tag->nodestart = node_sep - subfile->contents;
+
+ /* Calculate the length of the current node. */
+ buff_end = subfile->contents + subfile->filesize;
+
+ node_body.buffer = node->contents;
+ node_body.start = 0;
+ node_body.end = buff_end - node_body.buffer;
+ node_body.flags = 0;
+ tag->nodelen = get_node_length (&node_body);
+ }
+ else
+ {
+ /* Since we know the length of this node, we have already
+ adjusted tag->nodestart to point to the exact start of
+ it. Simply skip the node separator. */
+ node->contents += skip_node_separator (node->contents);
+ }
+
+ node->nodelen = tag->nodelen;
+ return (node);
+ }
+ }
+
+ /* There was a tag table for this file, and the node wasn't found.
+ Return NULL, since this file doesn't contain the desired node. */
+ return ((NODE *)NULL);
+}
+
+/* **************************************************************** */
+/* */
+/* Managing file_buffers, nodes, and tags. */
+/* */
+/* **************************************************************** */
+
+/* Create a new, empty file buffer. */
+FILE_BUFFER *
+make_file_buffer ()
+{
+ FILE_BUFFER *file_buffer;
+
+ file_buffer = (FILE_BUFFER *)xmalloc (sizeof (FILE_BUFFER));
+ file_buffer->filename = file_buffer->fullpath = (char *)NULL;
+ file_buffer->contents = (char *)NULL;
+ file_buffer->tags = (TAG **)NULL;
+ file_buffer->subfiles = (char **)NULL;
+ file_buffer->tags_slots = 0;
+ file_buffer->flags = 0;
+
+ return (file_buffer);
+}
+
+/* Add FILE_BUFFER to our list of already loaded info files. */
+static void
+remember_info_file (file_buffer)
+ FILE_BUFFER *file_buffer;
+{
+ int i;
+
+ for (i = 0; info_loaded_files && info_loaded_files[i]; i++)
+ ;
+
+ add_pointer_to_array (file_buffer, i, info_loaded_files,
+ info_loaded_files_slots, 10, FILE_BUFFER *);
+}
+
+/* Forget the contents, tags table, nodes list, and names of FILENAME. */
+static void
+forget_info_file (filename)
+ char *filename;
+{
+ register int i;
+ FILE_BUFFER *file_buffer;
+
+ if (!info_loaded_files)
+ return;
+
+ for (i = 0; file_buffer = info_loaded_files[i]; i++)
+ if ((strcmp (filename, file_buffer->filename) == 0) ||
+ (strcmp (filename, file_buffer->fullpath) == 0))
+ {
+ free (file_buffer->filename);
+ free (file_buffer->fullpath);
+
+ if (file_buffer->contents)
+ free (file_buffer->contents);
+
+ /* Note that free_file_buffer_tags () also kills the subfiles
+ list, since the subfiles list is only of use in conjunction
+ with tags. */
+ free_file_buffer_tags (file_buffer);
+
+ while (info_loaded_files[i] = info_loaded_files[++i])
+ ;
+
+ break;
+ }
+}
+
+/* Free the tags (if any) associated with FILE_BUFFER. */
+static void
+free_file_buffer_tags (file_buffer)
+ FILE_BUFFER *file_buffer;
+{
+ register int i;
+
+ if (file_buffer->tags)
+ {
+ register TAG *tag;
+
+ for (i = 0; tag = file_buffer->tags[i]; i++)
+ free_info_tag (tag);
+
+ free (file_buffer->tags);
+ file_buffer->tags = (TAG **)NULL;
+ file_buffer->tags_slots = 0;
+ }
+
+ if (file_buffer->subfiles)
+ {
+ for (i = 0; file_buffer->subfiles[i]; i++)
+ free (file_buffer->subfiles[i]);
+
+ free (file_buffer->subfiles);
+ file_buffer->subfiles = (char **)NULL;
+ }
+}
+
+/* Free the data associated with TAG, as well as TAG itself. */
+static void
+free_info_tag (tag)
+ TAG *tag;
+{
+ free (tag->nodename);
+
+ /* We don't free tag->filename, because that filename is part of the
+ subfiles list for the containing FILE_BUFFER. free_info_tags ()
+ will free the subfiles when it is appropriate. */
+
+ free (tag);
+}
+
+/* Load the contents of FILE_BUFFER->contents. This function is called
+ when a file buffer was loaded, and then in order to conserve memory, the
+ file buffer's contents were freed and the pointer was zero'ed. Note that
+ the file was already loaded at least once successfully, so the tags and/or
+ nodes members are still correctly filled. */
+static void
+info_reload_file_buffer_contents (fb)
+ FILE_BUFFER *fb;
+{
+
+#if defined (HANDLE_MAN_PAGES)
+ /* If this is the magic manpage node, don't try to reload, just give up. */
+ if (fb->flags & N_IsManPage)
+ return;
+#endif
+
+ fb->flags &= ~N_IsCompressed;
+
+ /* Let the filesystem do all the work for us. */
+ fb->contents =
+ filesys_read_info_file (fb->fullpath, &(fb->filesize), &(fb->finfo));
+ if (fb->filesize != (long) (fb->finfo.st_size))
+ fb->flags |= N_IsCompressed;
+}
+
+/* Return the actual starting memory location of NODE, side-effecting
+ NODE->contents. MIN and MAX are bounds for a search if one is necessary.
+ Because of the way that tags are implemented, the physical nodestart may
+ not actually be where the tag says it is. If that is the case, but the
+ node was found anyway, set N_UpdateTags in NODE->flags. If the node is
+ found, return non-zero. NODE->contents is returned positioned right after
+ the node separator that precedes this node, while the return value is
+ position directly on the separator that precedes this node. If the node
+ could not be found, return a NULL pointer. */
+static char *
+adjust_nodestart (node, min, max)
+ NODE *node;
+ int min, max;
+{
+ long position;
+ SEARCH_BINDING node_body;
+
+ /* Define the node body. */
+ node_body.buffer = node->contents;
+ node_body.start = 0;
+ node_body.end = max;
+ node_body.flags = 0;
+
+ /* Try the optimal case first. Who knows? This file may actually be
+ formatted (mostly) correctly. */
+ if (node_body.buffer[0] != INFO_COOKIE && min > 2)
+ node_body.buffer -= 3;
+
+ position = find_node_separator (&node_body);
+
+ /* If we found a node start, then check it out. */
+ if (position != -1)
+ {
+ int sep_len;
+
+ sep_len = skip_node_separator (node->contents);
+
+ /* If we managed to skip a node separator, then check for this node
+ being the right one. */
+ if (sep_len != 0)
+ {
+ char *nodedef, *nodestart;
+ int offset;
+
+ nodestart = node_body.buffer + position + sep_len;
+ nodedef = nodestart;
+ offset = string_in_line (INFO_NODE_LABEL, nodedef);
+
+ if (offset != -1)
+ {
+ nodedef += offset;
+ nodedef += skip_whitespace (nodedef);
+ offset = skip_node_characters (nodedef, DONT_SKIP_NEWLINES);
+ if ((offset == strlen (node->nodename)) &&
+ (strncmp (node->nodename, nodedef, offset) == 0))
+ {
+ node->contents = nodestart;
+ return (node_body.buffer + position);
+ }
+ }
+ }
+ }
+
+ /* Oh well, I guess we have to try to find it in a larger area. */
+ node_body.buffer = node->contents - min;
+ node_body.start = 0;
+ node_body.end = min + max;
+ node_body.flags = 0;
+
+ position = find_node_in_binding (node->nodename, &node_body);
+
+ /* If the node couldn't be found, we lose big. */
+ if (position == -1)
+ return ((char *)NULL);
+
+ /* Otherwise, the node was found, but the tags table could need updating
+ (if we used a tag to get here, that is). Set the flag in NODE->flags. */
+ node->contents = node_body.buffer + position;
+ node->contents += skip_node_separator (node->contents);
+ if (node->flags & N_HasTagsTable)
+ node->flags |= N_UpdateTags;
+ return (node_body.buffer + position);
+}
diff --git a/contrib/texinfo/info/nodes.h b/contrib/texinfo/info/nodes.h
new file mode 100644
index 0000000..7ddea17
--- /dev/null
+++ b/contrib/texinfo/info/nodes.h
@@ -0,0 +1,168 @@
+/* nodes.h -- How we represent nodes internally. */
+
+/* This file is part of GNU Info, a program for reading online documentation
+ stored in Info format.
+
+ Copyright (C) 1993 Free Software Foundation, Inc.
+
+ 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Written by Brian Fox (bfox@ai.mit.edu). */
+
+#if !defined (_NODES_H_)
+#define _NODES_H_
+
+#include "general.h"
+
+/* **************************************************************** */
+/* */
+/* User Code Interface */
+/* */
+/* **************************************************************** */
+
+/* Callers generally only want the node itself. This structure is used
+ to pass node information around. None of the information in this
+ structure should ever be directly freed. The structure itself can
+ be passed to free (). Note that NODE->parent is non-null if this
+ node's file is a subfile. In that case, NODE->parent is the logical
+ name of the file containing this node. Both names are given as full
+ paths, so you might have: node->filename = "/usr/gnu/info/emacs-1",
+ with node->parent = "/usr/gnu/info/emacs". */
+typedef struct {
+ char *filename; /* The physical file containing this node. */
+ char *parent; /* Non-null is the logical file name. */
+ char *nodename; /* The name of this node. */
+ char *contents; /* Characters appearing in this node. */
+ long nodelen; /* The length of the CONTENTS member. */
+ int flags; /* See immediately below. */
+} NODE;
+
+/* Defines that can appear in NODE->flags. All informative. */
+#define N_HasTagsTable 0x01 /* This node was found through a tags table. */
+#define N_TagsIndirect 0x02 /* The tags table was an indirect one. */
+#define N_UpdateTags 0x04 /* The tags table is out of date. */
+#define N_IsCompressed 0x08 /* The file is compressed on disk. */
+#define N_IsInternal 0x10 /* This node was made by Info. */
+#define N_CannotGC 0x20 /* File buffer cannot be gc'ed. */
+#define N_IsManPage 0x40 /* This node is a Un*x manpage. */
+
+/* **************************************************************** */
+/* */
+/* Internal Data Structures */
+/* */
+/* **************************************************************** */
+
+/* Some defines describing details about Info file contents. */
+
+/* String Constants. */
+#define INFO_FILE_LABEL "File:"
+#define INFO_NODE_LABEL "Node:"
+#define INFO_PREV_LABEL "Prev:"
+#define INFO_ALTPREV_LABEL "Previous:"
+#define INFO_NEXT_LABEL "Next:"
+#define INFO_UP_LABEL "Up:"
+#define INFO_MENU_LABEL "\n* Menu:"
+#define INFO_MENU_ENTRY_LABEL "\n* "
+#define INFO_XREF_LABEL "*Note"
+#define TAGS_TABLE_END_LABEL "\nEnd Tag Table"
+#define TAGS_TABLE_BEG_LABEL "Tag Table:\n"
+#define INDIRECT_TAGS_TABLE_LABEL "Indirect:\n"
+#define TAGS_TABLE_IS_INDIRECT_LABEL "(Indirect)"
+
+/* Character Constants. */
+#define INFO_COOKIE '\037'
+#define INFO_FF '\014'
+#define INFO_TAGSEP '\177'
+
+/* For each logical file that we have loaded, we keep a list of the names
+ of the nodes that are found in that file. A pointer to a node in an
+ info file is called a "tag". For split files, the tag pointer is
+ "indirect"; that is, the pointer also contains the name of the split
+ file where the node can be found. For non-split files, the filename
+ member in the structure below simply contains the name of the current
+ file. The following structure describes a single node within a file. */
+typedef struct {
+ char *filename; /* The file where this node can be found. */
+ char *nodename; /* The node pointed to by this tag. */
+ long nodestart; /* The offset of the start of this node. */
+ long nodelen; /* The length of this node. */
+} TAG;
+
+/* The following structure is used to remember information about the contents
+ of Info files that we have loaded at least once before. The FINFO member
+ is present so that we can reload the file if it has been modified since
+ last being loaded. All of the arrays appearing within this structure
+ are NULL terminated, and each array which can change size has a
+ corresponding SLOTS member which says how many slots have been allocated
+ (with malloc ()) for this array. */
+typedef struct {
+ char *filename; /* The filename used to find this file. */
+ char *fullpath; /* The full pathname of this info file. */
+ struct stat finfo; /* Information about this file. */
+ char *contents; /* The contents of this particular file. */
+ long filesize; /* The number of bytes this file expands to. */
+ char **subfiles; /* If non-null, the list of subfiles. */
+ TAG **tags; /* If non-null, the indirect tags table. */
+ int tags_slots; /* Number of slots allocated for TAGS. */
+ int flags; /* Various flags. Mimics of N_* flags. */
+} FILE_BUFFER;
+
+/* **************************************************************** */
+/* */
+/* Externally Visible Functions */
+/* */
+/* **************************************************************** */
+
+/* Array of FILE_BUFFER * which represents the currently loaded info files. */
+extern FILE_BUFFER **info_loaded_files;
+
+/* The number of slots currently allocated to INFO_LOADED_FILES. */
+extern int info_loaded_files_slots;
+
+/* Locate the file named by FILENAME, and return the information structure
+ describing this file. The file may appear in our list of loaded files
+ already, or it may not. If it does not already appear, find the file,
+ and add it to the list of loaded files. If the file cannot be found,
+ return a NULL FILE_BUFFER *. */
+extern FILE_BUFFER *info_find_file ();
+
+/* Force load the file named FILENAME, and return the information structure
+ describing this file. Even if the file was already loaded, this loads
+ a new buffer, rebuilds tags and nodes, and returns a new FILE_BUFFER *. */
+extern FILE_BUFFER *info_load_file ();
+
+/* Return a pointer to a NODE structure for the Info node (FILENAME)NODENAME.
+ FILENAME can be passed as NULL, in which case the filename of "dir" is used.
+ NODENAME can be passed as NULL, in which case the nodename of "Top" is used.
+ If the node cannot be found, return a NULL pointer. */
+extern NODE *info_get_node ();
+
+/* Return a pointer to a NODE structure for the Info node NODENAME in
+ FILE_BUFFER. NODENAME can be passed as NULL, in which case the
+ nodename of "Top" is used. If the node cannot be found, return a
+ NULL pointer. */
+extern NODE *info_get_node_of_file_buffer ();
+
+/* Grovel FILE_BUFFER->contents finding tags and nodes, and filling in the
+ various slots. This can also be used to rebuild a tag or node table. */
+extern void build_tags_and_nodes ();
+
+/* When non-zero, this is a string describing the most recent file error. */
+extern char *info_recent_file_error;
+
+/* Create a new, empty file buffer. */
+extern FILE_BUFFER *make_file_buffer ();
+
+#endif /* !_NODES_H_ */
diff --git a/contrib/texinfo/info/search.c b/contrib/texinfo/info/search.c
new file mode 100644
index 0000000..c5fd477
--- /dev/null
+++ b/contrib/texinfo/info/search.c
@@ -0,0 +1,519 @@
+/* search.c -- How to search large bodies of text. */
+
+/* This file is part of GNU Info, a program for reading online documentation
+ stored in Info format.
+
+ Copyright (C) 1993 Free Software Foundation, Inc.
+
+ 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Written by Brian Fox (bfox@ai.mit.edu). */
+
+#include <ctype.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include "general.h"
+#include "search.h"
+#include "nodes.h"
+
+#if !defined (NULL)
+# define NULL 0x0
+#endif /* !NULL */
+
+/* The search functions take two arguments:
+
+ 1) a string to search for, and
+
+ 2) a pointer to a SEARCH_BINDING which contains the buffer, start,
+ and end of the search.
+
+ They return a long, which is the offset from the start of the buffer
+ at which the match was found. An offset of -1 indicates failure. */
+
+/* A function which makes a binding with buffer and bounds. */
+SEARCH_BINDING *
+make_binding (buffer, start, end)
+ char *buffer;
+ long start, end;
+{
+ SEARCH_BINDING *binding;
+
+ binding = (SEARCH_BINDING *)xmalloc (sizeof (SEARCH_BINDING));
+ binding->buffer = buffer;
+ binding->start = start;
+ binding->end = end;
+ binding->flags = 0;
+
+ return (binding);
+}
+
+/* Make a copy of BINDING without duplicating the data. */
+SEARCH_BINDING *
+copy_binding (binding)
+ SEARCH_BINDING *binding;
+{
+ SEARCH_BINDING *copy;
+
+ copy = make_binding (binding->buffer, binding->start, binding->end);
+ copy->flags = binding->flags;
+ return (copy);
+}
+
+
+/* **************************************************************** */
+/* */
+/* The Actual Searching Functions */
+/* */
+/* **************************************************************** */
+
+/* Search forwards or backwards for the text delimited by BINDING.
+ The search is forwards if BINDING->start is greater than BINDING->end. */
+long
+search (string, binding)
+ char *string;
+ SEARCH_BINDING *binding;
+{
+ long result;
+
+ /* If the search is backwards, then search backwards, otherwise forwards. */
+ if (binding->start > binding->end)
+ result = search_backward (string, binding);
+ else
+ result = search_forward (string, binding);
+
+ return (result);
+}
+
+/* Search forwards for STRING through the text delimited in BINDING. */
+long
+search_forward (string, binding)
+ char *string;
+ SEARCH_BINDING *binding;
+{
+ register int c, i, len;
+ register char *buff, *end;
+ char *alternate = (char *)NULL;
+
+ len = strlen (string);
+
+ /* We match characters in the search buffer against STRING and ALTERNATE.
+ ALTERNATE is a case reversed version of STRING; this is cheaper than
+ case folding each character before comparison. Alternate is only
+ used if the case folding bit is turned on in the passed BINDING. */
+
+ if (binding->flags & S_FoldCase)
+ {
+ alternate = strdup (string);
+
+ for (i = 0; i < len; i++)
+ {
+ if (islower (alternate[i]))
+ alternate[i] = toupper (alternate[i]);
+ else if (isupper (alternate[i]))
+ alternate[i] = tolower (alternate[i]);
+ }
+ }
+
+ buff = binding->buffer + binding->start;
+ end = binding->buffer + binding->end + 1;
+
+ while (buff < (end - len))
+ {
+ for (i = 0; i < len; i++)
+ {
+ c = buff[i];
+
+ if ((c != string[i]) && (!alternate || c != alternate[i]))
+ break;
+ }
+
+ if (!string[i])
+ {
+ if (alternate)
+ free (alternate);
+ if (binding->flags & S_SkipDest)
+ buff += len;
+ return ((long) (buff - binding->buffer));
+ }
+
+ buff++;
+ }
+
+ if (alternate)
+ free (alternate);
+
+ return ((long) -1);
+}
+
+/* Search for STRING backwards through the text delimited in BINDING. */
+long
+search_backward (input_string, binding)
+ char *input_string;
+ SEARCH_BINDING *binding;
+{
+ register int c, i, len;
+ register char *buff, *end;
+ char *string;
+ char *alternate = (char *)NULL;
+
+ len = strlen (input_string);
+
+ /* Reverse the characters in the search string. */
+ string = (char *)xmalloc (1 + len);
+ for (c = 0, i = len - 1; input_string[c]; c++, i--)
+ string[i] = input_string[c];
+
+ string[c] = '\0';
+
+ /* We match characters in the search buffer against STRING and ALTERNATE.
+ ALTERNATE is a case reversed version of STRING; this is cheaper than
+ case folding each character before comparison. ALTERNATE is only
+ used if the case folding bit is turned on in the passed BINDING. */
+
+ if (binding->flags & S_FoldCase)
+ {
+ alternate = strdup (string);
+
+ for (i = 0; i < len; i++)
+ {
+ if (islower (alternate[i]))
+ alternate[i] = toupper (alternate[i]);
+ else if (isupper (alternate[i]))
+ alternate[i] = tolower (alternate[i]);
+ }
+ }
+
+ buff = binding->buffer + binding->start - 1;
+ end = binding->buffer + binding->end;
+
+ while (buff > (end + len))
+ {
+ for (i = 0; i < len; i++)
+ {
+ c = *(buff - i);
+
+ if (c != string[i] && (alternate && c != alternate[i]))
+ break;
+ }
+
+ if (!string[i])
+ {
+ free (string);
+ if (alternate)
+ free (alternate);
+
+ if (binding->flags & S_SkipDest)
+ buff -= len;
+ return ((long) (1 + (buff - binding->buffer)));
+ }
+
+ buff--;
+ }
+
+ free (string);
+ if (alternate)
+ free (alternate);
+
+ return ((long) -1);
+}
+
+/* Find STRING in LINE, returning the offset of the end of the string.
+ Return an offset of -1 if STRING does not appear in LINE. The search
+ is bound by the end of the line (i.e., either NEWLINE or 0). */
+int
+string_in_line (string, line)
+ char *string, *line;
+{
+ register int end;
+ SEARCH_BINDING binding;
+
+ /* Find the end of the line. */
+ for (end = 0; line[end] && line[end] != '\n'; end++);
+
+ /* Search for STRING within these confines. */
+ binding.buffer = line;
+ binding.start = 0;
+ binding.end = end;
+ binding.flags = S_FoldCase | S_SkipDest;
+
+ return (search_forward (string, &binding));
+}
+
+/* Return non-zero if STRING is the first text to appear at BINDING. */
+int
+looking_at (string, binding)
+ char *string;
+ SEARCH_BINDING *binding;
+{
+ long search_end;
+
+ search_end = search (string, binding);
+
+ /* If the string was not found, SEARCH_END is -1. If the string was found,
+ but not right away, SEARCH_END is != binding->start. Otherwise, the
+ string was found at binding->start. */
+ return (search_end == binding->start);
+}
+
+/* **************************************************************** */
+/* */
+/* Small String Searches */
+/* */
+/* **************************************************************** */
+
+/* Function names that start with "skip" are passed a string, and return
+ an offset from the start of that string. Function names that start
+ with "find" are passed a SEARCH_BINDING, and return an absolute position
+ marker of the item being searched for. "Find" functions return a value
+ of -1 if the item being looked for couldn't be found. */
+
+/* Return the index of the first non-whitespace character in STRING. */
+int
+skip_whitespace (string)
+ char *string;
+{
+ register int i;
+
+ for (i = 0; string && whitespace (string[i]); i++);
+ return (i);
+}
+
+/* Return the index of the first non-whitespace or newline character in
+ STRING. */
+int
+skip_whitespace_and_newlines (string)
+ char *string;
+{
+ register int i;
+
+ for (i = 0; string && (whitespace (string[i]) || string[i] == '\n'); i++);
+ return (i);
+}
+
+/* Return the index of the first whitespace character in STRING. */
+int
+skip_non_whitespace (string)
+ char *string;
+{
+ register int i;
+
+ for (i = 0; string && !whitespace (string[i]); i++);
+ return (i);
+}
+
+/* Return the index of the first non-node character in STRING. Note that
+ this function contains quite a bit of hair to ignore periods in some
+ special cases. This is because we here at GNU ship some info files which
+ contain nodenames that contain periods. No such nodename can start with
+ a period, or continue with whitespace, newline, or ')' immediately following
+ the period. If second argument NEWLINES_OKAY is non-zero, newlines should
+ be skipped while parsing out the nodename specification. */
+int
+skip_node_characters (string, newlines_okay)
+ char *string;
+ int newlines_okay;
+{
+ register int c, i = 0;
+ int paren_seen = 0;
+ int paren = 0;
+
+ /* Handle special case. This is when another function has parsed out the
+ filename component of the node name, and we just want to parse out the
+ nodename proper. In that case, a period at the start of the nodename
+ indicates an empty nodename. */
+ if (string && *string == '.')
+ return (0);
+
+ if (string && *string == '(')
+ {
+ paren++;
+ paren_seen++;
+ i++;
+ }
+
+ for (; string && (c = string[i]); i++)
+ {
+ if (paren)
+ {
+ if (c == '(')
+ paren++;
+ else if (c == ')')
+ paren--;
+
+ continue;
+ }
+
+ /* If the character following the close paren is a space or period,
+ then this node name has no more characters associated with it. */
+ if (c == '\t' ||
+ c == ',' ||
+ c == INFO_TAGSEP ||
+ ((!newlines_okay) && (c == '\n')) ||
+ ((paren_seen && string[i - 1] == ')') &&
+ (c == ' ' || c == '.')) ||
+ (c == '.' &&
+ ((!string[i + 1]) ||
+ (whitespace_or_newline (string[i + 1])) ||
+ (string[i + 1] == ')'))))
+ break;
+ }
+ return (i);
+}
+
+
+/* **************************************************************** */
+/* */
+/* Searching FILE_BUFFER's */
+/* */
+/* **************************************************************** */
+
+/* Return the absolute position of the first occurence of a node separator in
+ BINDING-buffer. The search starts at BINDING->start. Return -1 if no node
+ separator was found. */
+long
+find_node_separator (binding)
+ SEARCH_BINDING *binding;
+{
+ register long i;
+ char *body;
+
+ body = binding->buffer;
+
+ /* A node is started by [^L]^_[^L]\n. That is to say, the C-l's are
+ optional, but the DELETE and NEWLINE are not. This separator holds
+ true for all separated elements in an Info file, including the tags
+ table (if present) and the indirect tags table (if present). */
+ for (i = binding->start; i < binding->end - 1; i++)
+ if (((body[i] == INFO_FF && body[i + 1] == INFO_COOKIE) &&
+ (body[i + 2] == '\n' ||
+ (body[i + 2] == INFO_FF && body[i + 3] == '\n'))) ||
+ ((body[i] == INFO_COOKIE) &&
+ (body[i + 1] == '\n' ||
+ (body[i + 1] == INFO_FF && body[i + 2] == '\n'))))
+ return (i);
+ return (-1);
+}
+
+/* Return the length of the node separator characters that BODY is
+ currently pointing at. */
+int
+skip_node_separator (body)
+ char *body;
+{
+ register int i;
+
+ i = 0;
+
+ if (body[i] == INFO_FF)
+ i++;
+
+ if (body[i++] != INFO_COOKIE)
+ return (0);
+
+ if (body[i] == INFO_FF)
+ i++;
+
+ if (body[i++] != '\n')
+ return (0);
+
+ return (i);
+}
+
+/* Return the number of characters from STRING to the start of
+ the next line. */
+int
+skip_line (string)
+ char *string;
+{
+ register int i;
+
+ for (i = 0; string && string[i] && string[i] != '\n'; i++);
+
+ if (string[i] == '\n')
+ i++;
+
+ return (i);
+}
+
+/* Return the absolute position of the beginning of a tags table in this
+ binding starting the search at binding->start. */
+long
+find_tags_table (binding)
+ SEARCH_BINDING *binding;
+{
+ SEARCH_BINDING search;
+ long position;
+
+ search.buffer = binding->buffer;
+ search.start = binding->start;
+ search.end = binding->end;
+ search.flags = S_FoldCase;
+
+ while ((position = find_node_separator (&search)) != -1 )
+ {
+ search.start = position;
+ search.start += skip_node_separator (search.buffer + search.start);
+
+ if (looking_at (TAGS_TABLE_BEG_LABEL, &search))
+ return (position);
+ }
+ return (-1);
+}
+
+/* Return the absolute position of the node named NODENAME in BINDING.
+ This is a brute force search, and we wish to avoid it when possible.
+ This function is called when a tag (indirect or otherwise) doesn't
+ really point to the right node. It returns the absolute position of
+ the separator preceding the node. */
+long
+find_node_in_binding (nodename, binding)
+ char *nodename;
+ SEARCH_BINDING *binding;
+{
+ register long position;
+ register int offset, namelen;
+ SEARCH_BINDING search;
+
+ namelen = strlen (nodename);
+
+ search.buffer = binding->buffer;
+ search.start = binding->start;
+ search.end = binding->end;
+ search.flags = 0;
+
+ while ((position = find_node_separator (&search)) != -1)
+ {
+ search.start = position;
+ search.start += skip_node_separator (search.buffer + search.start);
+
+ offset = string_in_line (INFO_NODE_LABEL, search.buffer + search.start);
+
+ if (offset == -1)
+ continue;
+
+ search.start += offset;
+ search.start += skip_whitespace (search.buffer + search.start);
+ offset = skip_node_characters
+ (search.buffer + search.start, DONT_SKIP_NEWLINES);
+
+ /* Notice that this is an exact match. You cannot grovel through
+ the buffer with this function looking for random nodes. */
+ if ((offset == namelen) &&
+ (search.buffer[search.start] == nodename[0]) &&
+ (strncmp (search.buffer + search.start, nodename, offset) == 0))
+ return (position);
+ }
+ return (-1);
+}
diff --git a/contrib/texinfo/info/search.h b/contrib/texinfo/info/search.h
new file mode 100644
index 0000000..72695c3
--- /dev/null
+++ b/contrib/texinfo/info/search.h
@@ -0,0 +1,75 @@
+/* search.h -- Structure used to search large bodies of text, with bounds. */
+
+/* This file is part of GNU Info, a program for reading online documentation
+ stored in Info format.
+
+ Copyright (C) 1993 Free Software Foundation, Inc.
+
+ 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Written by Brian Fox (bfox@ai.mit.edu). */
+
+/* The search functions take two arguments:
+
+ 1) a string to search for, and
+
+ 2) a pointer to a SEARCH_BINDING which contains the buffer, start,
+ and end of the search.
+
+ They return a long, which is the offset from the start of the buffer
+ at which the match was found. An offset of -1 indicates failure. */
+
+#if !defined (_SEARCH_H_)
+#define _SEARCH_H_
+
+typedef struct {
+ char *buffer; /* The buffer of text to search. */
+ long start; /* Offset of the start of the search. */
+ long end; /* Offset of the end of the searh. */
+ int flags; /* Flags controlling the type of search. */
+} SEARCH_BINDING;
+
+#define S_FoldCase 0x01 /* Set means fold case in searches. */
+#define S_SkipDest 0x02 /* Set means return pointing after the dest. */
+
+SEARCH_BINDING *make_binding (), *copy_binding ();
+extern long search_forward (), search_backward (), search ();
+extern int looking_at ();
+
+/* Note that STRING_IN_LINE () always returns the offset of the 1st character
+ after the string. */
+extern int string_in_line ();
+
+/* Some unixes don't have strcasecmp or strncasecmp. */
+#if !defined (HAVE_STRCASECMP)
+extern int strcasecmp (), strncasecmp ();
+#endif /* !HAVE_STRCASECMP */
+
+/* Function names that start with "skip" are passed a string, and return
+ an offset from the start of that string. Function names that start
+ with "find" are passed a SEARCH_BINDING, and return an absolute position
+ marker of the item being searched for. "Find" functions return a value
+ of -1 if the item being looked for couldn't be found. */
+extern int skip_whitespace (), skip_non_whitespace ();
+extern int skip_whitespace_and_newlines (), skip_line ();
+extern int skip_node_characters (), skip_node_separator ();
+#define DONT_SKIP_NEWLINES 0
+#define SKIP_NEWLINES 1
+
+extern long find_node_separator (), find_tags_table ();
+extern long find_node_in_binding ();
+
+#endif /* !_SEARCH_H_ */
+
diff --git a/contrib/texinfo/info/session.c b/contrib/texinfo/info/session.c
new file mode 100644
index 0000000..be3076c
--- /dev/null
+++ b/contrib/texinfo/info/session.c
@@ -0,0 +1,4263 @@
+/* session.c -- The user windowing interface to Info. */
+
+/* This file is part of GNU Info, a program for reading online documentation
+ stored in Info format.
+
+ Copyright (C) 1993, 96 Free Software Foundation, Inc.
+
+ 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Written by Brian Fox (bfox@ai.mit.edu). */
+
+#include "info.h"
+#if defined (HAVE_SYS_FILE_H)
+#include <sys/file.h>
+#endif /* HAVE_SYS_FILE_H */
+#include <sys/ioctl.h>
+#include <fcntl.h>
+
+#if defined (HAVE_SYS_TIME_H)
+# include <sys/time.h>
+# define HAVE_STRUCT_TIMEVAL
+#endif /* HAVE_SYS_TIME_H */
+
+#if defined (HANDLE_MAN_PAGES)
+# include "man.h"
+#endif
+
+static void info_clear_pending_input (), info_set_pending_input ();
+static void info_handle_pointer ();
+
+/* **************************************************************** */
+/* */
+/* Running an Info Session */
+/* */
+/* **************************************************************** */
+
+/* The place that we are reading input from. */
+static FILE *info_input_stream = (FILE *)NULL;
+
+/* The last executed command. */
+VFunction *info_last_executed_command = (VFunction *)NULL;
+
+/* Becomes non-zero when 'q' is typed to an Info window. */
+int quit_info_immediately = 0;
+
+/* Array of structures describing for each window which nodes have been
+ visited in that window. */
+INFO_WINDOW **info_windows = (INFO_WINDOW **)NULL;
+
+/* Where to add the next window, if we need to add one. */
+static int info_windows_index = 0;
+
+/* Number of slots allocated to INFO_WINDOWS. */
+static int info_windows_slots = 0;
+
+void remember_window_and_node (), forget_window_and_nodes ();
+void initialize_info_session (), info_session ();
+void display_startup_message_and_start ();
+
+/* Begin an info session finding the nodes specified by FILENAME and NODENAMES.
+ For each loaded node, create a new window. Always split the largest of the
+ available windows. */
+void
+begin_multiple_window_info_session (filename, nodenames)
+ char *filename;
+ char **nodenames;
+{
+ register int i;
+ WINDOW *window = (WINDOW *)NULL;
+
+ for (i = 0; nodenames[i]; i++)
+ {
+ NODE *node;
+
+ node = info_get_node (filename, nodenames[i]);
+
+ if (!node)
+ break;
+
+ /* If this is the first node, initialize the info session. */
+ if (!window)
+ {
+ initialize_info_session (node);
+ window = active_window;
+ }
+ else
+ {
+ /* Find the largest window in WINDOWS, and make that be the active
+ one. Then split it and add our window and node to the list
+ of remembered windows and nodes. Then tile the windows. */
+ register WINDOW *win, *largest = (WINDOW *)NULL;
+ int max_height = 0;
+
+ for (win = windows; win; win = win->next)
+ if (win->height > max_height)
+ {
+ max_height = win->height;
+ largest = win;
+ }
+
+ if (!largest)
+ {
+ display_update_display (windows);
+ info_error (CANT_FIND_WIND);
+ info_session ();
+ exit (0);
+ }
+
+ active_window = largest;
+ window = window_make_window (node);
+ if (window)
+ {
+ window_tile_windows (TILE_INTERNALS);
+ remember_window_and_node (window, node);
+ }
+ else
+ {
+ display_update_display (windows);
+ info_error (WIN_TOO_SMALL);
+ info_session ();
+ exit (0);
+ }
+ }
+ }
+ display_startup_message_and_start ();
+}
+
+/* Start an info session with INITIAL_NODE, and an error message in the echo
+ area made from FORMAT and ARG. */
+void
+begin_info_session_with_error (initial_node, format, arg)
+ NODE *initial_node;
+ char *format;
+ void *arg;
+{
+ initialize_info_session (initial_node);
+ info_error (format, arg, (void *)NULL);
+ info_session ();
+}
+
+/* Start an info session with INITIAL_NODE. */
+void
+begin_info_session (initial_node)
+ NODE *initial_node;
+{
+ initialize_info_session (initial_node);
+ display_startup_message_and_start ();
+}
+
+void
+display_startup_message_and_start ()
+{
+ char *format;
+
+ format = replace_in_documentation
+ ("Welcome to Info version %s. \"\\[get-help-window]\" for help, \"\\[menu-item]\" for menu item.");
+
+ window_message_in_echo_area (format, version_string ());
+ info_session ();
+}
+
+/* Run an info session with an already initialized window and node. */
+void
+info_session ()
+{
+ terminal_prep_terminal ();
+ display_update_display (windows);
+ info_last_executed_command = (VFunction *)NULL;
+ info_read_and_dispatch ();
+ /* On program exit, leave the cursor at the bottom of the window, and
+ restore the terminal I/O. */
+ terminal_goto_xy (0, screenheight - 1);
+ terminal_clear_to_eol ();
+ fflush (stdout);
+ terminal_unprep_terminal ();
+ close_dribble_file ();
+}
+
+/* Here is a window-location dependent event loop. Called from the
+ functions info_session (), and from read_xxx_in_echo_area (). */
+void
+info_read_and_dispatch ()
+{
+ unsigned char key;
+ int done;
+ done = 0;
+
+ while (!done && !quit_info_immediately)
+ {
+ int lk;
+
+ /* If we haven't just gone up or down a line, there is no
+ goal column for this window. */
+ if ((info_last_executed_command != info_next_line) &&
+ (info_last_executed_command != info_prev_line))
+ active_window->goal_column = -1;
+
+ if (echo_area_is_active)
+ {
+ lk = echo_area_last_command_was_kill;
+ echo_area_prep_read ();
+ }
+
+ if (!info_any_buffered_input_p ())
+ display_update_display (windows);
+
+ display_cursor_at_point (active_window);
+ info_initialize_numeric_arg ();
+
+ initialize_keyseq ();
+ key = info_get_input_char ();
+
+ /* No errors yet. We just read a character, that's all. Only clear
+ the echo_area if it is not currently active. */
+ if (!echo_area_is_active)
+ window_clear_echo_area ();
+
+ info_error_was_printed = 0;
+
+ /* Do the selected command. */
+ info_dispatch_on_key (key, active_window->keymap);
+
+ if (echo_area_is_active)
+ {
+ /* Echo area commands that do killing increment the value of
+ ECHO_AREA_LAST_COMMAND_WAS_KILL. Thus, if there is no
+ change in the value of this variable, the last command
+ executed was not a kill command. */
+ if (lk == echo_area_last_command_was_kill)
+ echo_area_last_command_was_kill = 0;
+
+ if (ea_last_executed_command == ea_newline ||
+ info_aborted_echo_area)
+ {
+ ea_last_executed_command = (VFunction *)NULL;
+ done = 1;
+ }
+
+ if (info_last_executed_command == info_quit)
+ quit_info_immediately = 1;
+ }
+ else if (info_last_executed_command == info_quit)
+ done = 1;
+ }
+}
+
+/* Found in signals.c */
+extern void initialize_info_signal_handler ();
+
+/* Initialize the first info session by starting the terminal, window,
+ and display systems. */
+void
+initialize_info_session (node)
+ NODE *node;
+{
+ char *getenv (), *term_name;
+
+ term_name = getenv ("TERM");
+ terminal_initialize_terminal (term_name);
+
+ if (terminal_is_dumb_p)
+ {
+ if (!term_name)
+ term_name = "dumb";
+
+ info_error (TERM_TOO_DUMB, term_name);
+ exit (1);
+ }
+
+ terminal_clear_screen ();
+ initialize_info_keymaps ();
+ window_initialize_windows (screenwidth, screenheight);
+ initialize_info_signal_handler ();
+ display_initialize_display (screenwidth, screenheight);
+ info_set_node_of_window (active_window, node);
+
+ /* Tell the window system how to notify us when a window needs to be
+ asynchronously deleted (e.g., user resizes window very small). */
+ window_deletion_notifier = forget_window_and_nodes;
+
+ /* If input has not been redirected yet, make it come from STDIN. */
+ if (!info_input_stream)
+ info_input_stream = stdin;
+
+ info_windows_initialized_p = 1;
+}
+
+/* Tell Info that input is coming from the file FILENAME. */
+void
+info_set_input_from_file (filename)
+ char *filename;
+{
+ FILE *stream;
+
+ stream = fopen (filename, "r");
+
+ if (!stream)
+ return;
+
+ if ((info_input_stream != (FILE *)NULL) &&
+ (info_input_stream != stdin))
+ fclose (info_input_stream);
+
+ info_input_stream = stream;
+
+ if (stream != stdin)
+ display_inhibited = 1;
+}
+
+/* Return the INFO_WINDOW containing WINDOW, or NULL if there isn't one. */
+static INFO_WINDOW *
+get_info_window_of_window (window)
+ WINDOW *window;
+{
+ register int i;
+ INFO_WINDOW *info_win = (INFO_WINDOW *)NULL;
+
+ for (i = 0; info_windows && (info_win = info_windows[i]); i++)
+ if (info_win->window == window)
+ break;
+
+ return (info_win);
+}
+
+/* Reset the remembered pagetop and point of WINDOW to WINDOW's current
+ values if the window and node are the same as the current one being
+ displayed. */
+void
+set_remembered_pagetop_and_point (window)
+ WINDOW *window;
+{
+ INFO_WINDOW *info_win;
+
+ info_win = get_info_window_of_window (window);
+
+ if (!info_win)
+ return;
+
+ if (info_win->nodes_index &&
+ (info_win->nodes[info_win->current] == window->node))
+ {
+ info_win->pagetops[info_win->current] = window->pagetop;
+ info_win->points[info_win->current] = window->point;
+ }
+}
+
+void
+remember_window_and_node (window, node)
+ WINDOW *window;
+ NODE *node;
+{
+ INFO_WINDOW *info_win;
+
+ /* See if we already have this window in our list. */
+ info_win = get_info_window_of_window (window);
+
+ /* If the window wasn't already on our list, then make a new entry. */
+ if (!info_win)
+ {
+ info_win = (INFO_WINDOW *)xmalloc (sizeof (INFO_WINDOW));
+ info_win->window = window;
+ info_win->nodes = (NODE **)NULL;
+ info_win->pagetops = (int *)NULL;
+ info_win->points = (long *)NULL;
+ info_win->current = 0;
+ info_win->nodes_index = 0;
+ info_win->nodes_slots = 0;
+
+ add_pointer_to_array (info_win, info_windows_index, info_windows,
+ info_windows_slots, 10, INFO_WINDOW *);
+ }
+
+ /* If this node, the current pagetop, and the current point are the
+ same as the last saved node and pagetop, don't really add this to
+ the list of history nodes. */
+ {
+ int ni = info_win->nodes_index - 1;
+
+ if ((ni != -1) &&
+ (info_win->nodes[ni]->contents == node->contents) &&
+ (info_win->pagetops[ni] == window->pagetop) &&
+ (info_win->points[ni] == window->point))
+ return;
+ }
+
+ /* Remember this node, the currently displayed pagetop, and the current
+ location of point in this window. Because we are updating pagetops
+ and points as well as nodes, it is more efficient to avoid the
+ add_pointer_to_array macro here. */
+ if (info_win->nodes_index + 2 >= info_win->nodes_slots)
+ {
+ info_win->nodes = (NODE **)
+ xrealloc (info_win->nodes,
+ (info_win->nodes_slots += 20) * sizeof (NODE *));
+
+ info_win->pagetops = (int *)
+ xrealloc (info_win->pagetops, info_win->nodes_slots * sizeof (int));
+
+ info_win->points = (long *)
+ xrealloc (info_win->points, info_win->nodes_slots * sizeof (long));
+ }
+
+ info_win->nodes[info_win->nodes_index] = node;
+ info_win->pagetops[info_win->nodes_index] = window->pagetop;
+ info_win->points[info_win->nodes_index] = window->point;
+ info_win->current = info_win->nodes_index++;
+ info_win->nodes[info_win->nodes_index] = (NODE *)NULL;
+ info_win->pagetops[info_win->nodes_index] = 0;
+ info_win->points[info_win->nodes_index] = 0;
+}
+
+#define DEBUG_FORGET_WINDOW_AND_NODES
+#if defined (DEBUG_FORGET_WINDOW_AND_NODES)
+static void
+consistency_check_info_windows ()
+{
+ register int i;
+ INFO_WINDOW *info_win;
+
+ for (i = 0; i < info_windows_index; i++)
+ {
+ WINDOW *win;
+
+ for (win = windows; win; win = win->next)
+ if (win == info_windows[i]->window)
+ break;
+
+ if (!win)
+ abort ();
+ }
+}
+#endif /* DEBUG_FORGET_WINDOW_AND_NODES */
+
+/* Remove WINDOW and its associated list of nodes from INFO_WINDOWS. */
+void
+forget_window_and_nodes (window)
+ WINDOW *window;
+{
+ register int i;
+ INFO_WINDOW *info_win = (INFO_WINDOW *)NULL;
+
+ for (i = 0; info_windows && (info_win = info_windows[i]); i++)
+ if (info_win->window == window)
+ break;
+
+ /* If we found the window to forget, then do so. */
+ if (info_win)
+ {
+ while (i < info_windows_index)
+ {
+ info_windows[i] = info_windows[i + 1];
+ i++;
+ }
+
+ info_windows_index--;
+ info_windows[info_windows_index] = (INFO_WINDOW *)NULL;
+
+ if (info_win->nodes)
+ {
+ /* Free the node structures which held onto internal node contents
+ here. This doesn't free the contents; we have a garbage collector
+ which does that. */
+ for (i = 0; info_win->nodes[i]; i++)
+ if (internal_info_node_p (info_win->nodes[i]))
+ free (info_win->nodes[i]);
+ free (info_win->nodes);
+
+ maybe_free (info_win->pagetops);
+ maybe_free (info_win->points);
+ }
+
+ free (info_win);
+ }
+#if defined (DEBUG_FORGET_WINDOW_AND_NODES)
+ consistency_check_info_windows ();
+#endif /* DEBUG_FORGET_WINDOW_AND_NODES */
+}
+
+/* Set WINDOW to show NODE. Remember the new window in our list of Info
+ windows. If we are doing automatic footnote display, also try to display
+ the footnotes for this window. */
+void
+info_set_node_of_window (window, node)
+ WINDOW *window;
+ NODE *node;
+{
+ /* Put this node into the window. */
+ window_set_node_of_window (window, node);
+
+ /* Remember this node and window in our list of info windows. */
+ remember_window_and_node (window, node);
+
+ /* If doing auto-footnote display/undisplay, show the footnotes belonging
+ to this window's node. */
+ if (auto_footnotes_p)
+ info_get_or_remove_footnotes (window);
+}
+
+
+/* **************************************************************** */
+/* */
+/* Info Movement Commands */
+/* */
+/* **************************************************************** */
+
+/* Change the pagetop of WINDOW to DESIRED_TOP, perhaps scrolling the screen
+ to do so. */
+void
+set_window_pagetop (window, desired_top)
+ WINDOW *window;
+ int desired_top;
+{
+ int point_line, old_pagetop;
+
+ if (desired_top < 0)
+ desired_top = 0;
+ else if (desired_top > window->line_count)
+ desired_top = window->line_count - 1;
+
+ if (window->pagetop == desired_top)
+ return;
+
+ old_pagetop = window->pagetop;
+ window->pagetop = desired_top;
+
+ /* Make sure that point appears in this window. */
+ point_line = window_line_of_point (window);
+ if ((point_line < window->pagetop) ||
+ ((point_line - window->pagetop) > window->height - 1))
+ window->point =
+ window->line_starts[window->pagetop] - window->node->contents;
+
+ window->flags |= W_UpdateWindow;
+
+ /* Find out which direction to scroll, and scroll the window in that
+ direction. Do this only if there would be a savings in redisplay
+ time. This is true if the amount to scroll is less than the height
+ of the window, and if the number of lines scrolled would be greater
+ than 10 % of the window's height. */
+ if (old_pagetop < desired_top)
+ {
+ int start, end, amount;
+
+ amount = desired_top - old_pagetop;
+
+ if ((amount >= window->height) ||
+ (((window->height - amount) * 10) < window->height))
+ return;
+
+ start = amount + window->first_row;
+ end = window->height + window->first_row;
+
+ display_scroll_display (start, end, -amount);
+ }
+ else
+ {
+ int start, end, amount;
+
+ amount = old_pagetop - desired_top;
+
+ if ((amount >= window->height) ||
+ (((window->height - amount) * 10) < window->height))
+ return;
+
+ start = window->first_row;
+ end = (window->first_row + window->height) - amount;
+ display_scroll_display (start, end, amount);
+ }
+}
+
+/* Immediately make WINDOW->point visible on the screen, and move the
+ terminal cursor there. */
+static void
+info_show_point (window)
+ WINDOW *window;
+{
+ int old_pagetop;
+
+ old_pagetop = window->pagetop;
+ window_adjust_pagetop (window);
+ if (old_pagetop != window->pagetop)
+ {
+ int new_pagetop;
+
+ new_pagetop = window->pagetop;
+ window->pagetop = old_pagetop;
+ set_window_pagetop (window, new_pagetop);
+ }
+
+ if (window->flags & W_UpdateWindow)
+ display_update_one_window (window);
+
+ display_cursor_at_point (window);
+}
+
+/* Move WINDOW->point from OLD line index to NEW line index. */
+static void
+move_to_new_line (old, new, window)
+ int old, new;
+ WINDOW *window;
+{
+ if (old == -1)
+ {
+ info_error (CANT_FIND_POINT);
+ }
+ else
+ {
+ int goal;
+
+ if (new >= window->line_count || new < 0)
+ return;
+
+ goal = window_get_goal_column (window);
+ window->goal_column = goal;
+
+ window->point = window->line_starts[new] - window->node->contents;
+ window->point += window_chars_to_goal (window->line_starts[new], goal);
+ info_show_point (window);
+ }
+}
+
+/* Move WINDOW's point down to the next line if possible. */
+DECLARE_INFO_COMMAND (info_next_line, "Move down to the next line")
+{
+ int old_line, new_line;
+
+ if (count < 0)
+ info_prev_line (window, -count, key);
+ else
+ {
+ old_line = window_line_of_point (window);
+ new_line = old_line + count;
+ move_to_new_line (old_line, new_line, window);
+ }
+}
+
+/* Move WINDOW's point up to the previous line if possible. */
+DECLARE_INFO_COMMAND (info_prev_line, "Move up to the previous line")
+{
+ int old_line, new_line;
+
+ if (count < 0)
+ info_next_line (window, -count, key);
+ else
+ {
+ old_line = window_line_of_point (window);
+ new_line = old_line - count;
+ move_to_new_line (old_line, new_line, window);
+ }
+}
+
+/* Move WINDOW's point to the end of the true line. */
+DECLARE_INFO_COMMAND (info_end_of_line, "Move to the end of the line")
+{
+ register int point, len;
+ register char *buffer;
+
+ buffer = window->node->contents;
+ len = window->node->nodelen;
+
+ for (point = window->point;
+ (point < len) && (buffer[point] != '\n');
+ point++);
+
+ if (point != window->point)
+ {
+ window->point = point;
+ info_show_point (window);
+ }
+}
+
+/* Move WINDOW's point to the beginning of the true line. */
+DECLARE_INFO_COMMAND (info_beginning_of_line, "Move to the start of the line")
+{
+ register int point;
+ register char *buffer;
+
+ buffer = window->node->contents;
+ point = window->point;
+
+ for (; (point) && (buffer[point - 1] != '\n'); point--);
+
+ /* If at a line start alreay, do nothing. */
+ if (point != window->point)
+ {
+ window->point = point;
+ info_show_point (window);
+ }
+}
+
+/* Move point forward in the node. */
+DECLARE_INFO_COMMAND (info_forward_char, "Move forward a character")
+{
+ if (count < 0)
+ info_backward_char (window, -count, key);
+ else
+ {
+ window->point += count;
+
+ if (window->point >= window->node->nodelen)
+ window->point = window->node->nodelen - 1;
+
+ info_show_point (window);
+ }
+}
+
+/* Move point backward in the node. */
+DECLARE_INFO_COMMAND (info_backward_char, "Move backward a character")
+{
+ if (count < 0)
+ info_forward_char (window, -count, key);
+ else
+ {
+ window->point -= count;
+
+ if (window->point < 0)
+ window->point = 0;
+
+ info_show_point (window);
+ }
+}
+
+#define alphabetic(c) (islower (c) || isupper (c) || isdigit (c))
+
+/* Move forward a word in this node. */
+DECLARE_INFO_COMMAND (info_forward_word, "Move forward a word")
+{
+ long point;
+ char *buffer;
+ int end, c;
+
+ if (count < 0)
+ {
+ info_backward_word (window, -count, key);
+ return;
+ }
+
+ point = window->point;
+ buffer = window->node->contents;
+ end = window->node->nodelen;
+
+ while (count)
+ {
+ if (point + 1 >= end)
+ return;
+
+ /* If we are not in a word, move forward until we are in one.
+ Then, move forward until we hit a non-alphabetic character. */
+ c = buffer[point];
+
+ if (!alphabetic (c))
+ {
+ while (++point < end)
+ {
+ c = buffer[point];
+ if (alphabetic (c))
+ break;
+ }
+ }
+
+ if (point >= end) return;
+
+ while (++point < end)
+ {
+ c = buffer[point];
+ if (!alphabetic (c))
+ break;
+ }
+ --count;
+ }
+ window->point = point;
+ info_show_point (window);
+}
+
+DECLARE_INFO_COMMAND (info_backward_word, "Move backward a word")
+{
+ long point;
+ char *buffer;
+ int c;
+
+ if (count < 0)
+ {
+ info_forward_word (window, -count, key);
+ return;
+ }
+
+ buffer = window->node->contents;
+ point = window->point;
+
+ while (count)
+ {
+ if (point == 0)
+ break;
+
+ /* Like info_forward_word (), except that we look at the
+ characters just before point. */
+
+ c = buffer[point - 1];
+
+ if (!alphabetic (c))
+ {
+ while (--point)
+ {
+ c = buffer[point - 1];
+ if (alphabetic (c))
+ break;
+ }
+ }
+
+ while (point)
+ {
+ c = buffer[point - 1];
+ if (!alphabetic (c))
+ break;
+ else
+ --point;
+ }
+ --count;
+ }
+ window->point = point;
+ info_show_point (window);
+}
+
+/* Here is a list of time counter names which correspond to ordinal numbers.
+ It is used to print "once" instead of "1". */
+static char *counter_names[] = {
+ "not at all", "once", "twice", "three", "four", "five", "six",
+ (char *)NULL
+};
+
+/* Buffer used to return values from times_description (). */
+static char td_buffer[50];
+
+/* Function returns a static string fully describing the number of times
+ present in COUNT. */
+static char *
+times_description (count)
+ int count;
+{
+ register int i;
+
+ td_buffer[0] = '\0';
+
+ for (i = 0; counter_names[i]; i++)
+ if (count == i)
+ break;
+
+ if (counter_names[i])
+ sprintf (td_buffer, "%s%s", counter_names[i], count > 2 ? " times" : "");
+ else
+ sprintf (td_buffer, "%d times", count);
+
+ return (td_buffer);
+}
+
+/* Variable controlling the behaviour of default scrolling when you are
+ already at the bottom of a node. Possible values are defined in session.h.
+ The meanings are:
+
+ IS_Continuous Try to get first menu item, or failing that, the
+ "Next:" pointer, or failing that, the "Up:" and
+ "Next:" of the up.
+ IS_NextOnly Try to get "Next:" menu item.
+ IS_PageOnly Simply give up at the bottom of a node. */
+
+int info_scroll_behaviour = IS_Continuous;
+
+/* Choices used by the completer when reading a value for the user-visible
+ variable "scroll-behaviour". */
+char *info_scroll_choices[] = {
+ "Continuous", "Next Only", "Page Only", (char *)NULL
+};
+
+/* Move to 1st menu item, Next, Up/Next, or error in this window. */
+static void
+forward_move_node_structure (window, behaviour)
+ WINDOW *window;
+ int behaviour;
+{
+ switch (behaviour)
+ {
+ case IS_PageOnly:
+ info_error (AT_NODE_BOTTOM);
+ break;
+
+ case IS_NextOnly:
+ info_next_label_of_node (window->node);
+ if (!info_parsed_nodename && !info_parsed_filename)
+ info_error ("No \"Next\" pointer for this node.");
+ else
+ {
+ window_message_in_echo_area ("Following \"Next\" node...");
+ info_handle_pointer ("Next", window);
+ }
+ break;
+
+ case IS_Continuous:
+ {
+ /* First things first. If this node contains a menu, move down
+ into the menu. */
+ {
+ REFERENCE **menu;
+
+ menu = info_menu_of_node (window->node);
+
+ if (menu)
+ {
+ info_free_references (menu);
+ window_message_in_echo_area ("Selecting first menu item...");
+ info_menu_digit (window, 1, '1');
+ return;
+ }
+ }
+
+ /* Okay, this node does not contain a menu. If it contains a
+ "Next:" pointer, use that. */
+ info_next_label_of_node (window->node);
+ if (info_label_was_found)
+ {
+ window_message_in_echo_area ("Selecting \"Next\" node...");
+ info_handle_pointer ("Next", window);
+ return;
+ }
+
+ /* Okay, there wasn't a "Next:" for this node. Move "Up:" until we
+ can move "Next:". If that isn't possible, complain that there
+ are no more nodes. */
+ {
+ int up_counter, old_current;
+ INFO_WINDOW *info_win;
+
+ /* Remember the current node and location. */
+ info_win = get_info_window_of_window (window);
+ old_current = info_win->current;
+
+ /* Back up through the "Up:" pointers until we have found a "Next:"
+ that isn't the same as the first menu item found in that node. */
+ up_counter = 0;
+ while (!info_error_was_printed)
+ {
+ info_up_label_of_node (window->node);
+ if (info_label_was_found)
+ {
+ info_handle_pointer ("Up", window);
+ if (info_error_was_printed)
+ continue;
+
+ up_counter++;
+
+ info_next_label_of_node (window->node);
+
+ /* If no "Next" pointer, keep backing up. */
+ if (!info_label_was_found)
+ continue;
+
+ /* If this node's first menu item is the same as this node's
+ Next pointer, keep backing up. */
+ if (!info_parsed_filename)
+ {
+ REFERENCE **menu;
+ char *next_nodename;
+
+ /* Remember the name of the Next node, since reading
+ the menu can overwrite the contents of the
+ info_parsed_xxx strings. */
+ next_nodename = strdup (info_parsed_nodename);
+
+ menu = info_menu_of_node (window->node);
+ if (menu &&
+ (strcmp
+ (menu[0]->nodename, next_nodename) == 0))
+ {
+ info_free_references (menu);
+ free (next_nodename);
+ continue;
+ }
+ else
+ {
+ /* Restore the world to where it was before
+ reading the menu contents. */
+ info_free_references (menu);
+ free (next_nodename);
+ info_next_label_of_node (window->node);
+ }
+ }
+
+ /* This node has a "Next" pointer, and it is not the
+ same as the first menu item found in this node. */
+ window_message_in_echo_area
+ ("Moving \"Up\" %s, then \"Next\".",
+ times_description (up_counter));
+
+ info_handle_pointer ("Next", window);
+ return;
+ }
+ else
+ {
+ /* No more "Up" pointers. Print an error, and call it
+ quits. */
+ register int i;
+
+ for (i = 0; i < up_counter; i++)
+ {
+ info_win->nodes_index--;
+ free (info_win->nodes[info_win->nodes_index]);
+ info_win->nodes[info_win->nodes_index] = (NODE *)NULL;
+ }
+ info_win->current = old_current;
+ window->node = info_win->nodes[old_current];
+ window->pagetop = info_win->pagetops[old_current];
+ window->point = info_win->points[old_current];
+ recalculate_line_starts (window);
+ window->flags |= W_UpdateWindow;
+ info_error ("No more nodes.");
+ }
+ }
+ }
+ break;
+ }
+ }
+}
+
+/* Move Prev, Up or error in WINDOW depending on BEHAVIOUR. */
+static void
+backward_move_node_structure (window, behaviour)
+ WINDOW *window;
+ int behaviour;
+{
+ switch (behaviour)
+ {
+ case IS_PageOnly:
+ info_error (AT_NODE_TOP);
+ break;
+
+ case IS_NextOnly:
+ info_prev_label_of_node (window->node);
+ if (!info_parsed_nodename && !info_parsed_filename)
+ info_error ("No \"Prev\" for this node.");
+ else
+ {
+ window_message_in_echo_area ("Moving \"Prev\" in this window.");
+ info_handle_pointer ("Prev", window);
+ }
+ break;
+
+ case IS_Continuous:
+ info_prev_label_of_node (window->node);
+
+ if (!info_parsed_nodename && !info_parsed_filename)
+ {
+ info_up_label_of_node (window->node);
+ if (!info_parsed_nodename && !info_parsed_filename)
+ info_error ("No \"Prev\" or \"Up\" for this node.");
+ else
+ {
+ window_message_in_echo_area ("Moving \"Up\" in this window.");
+ info_handle_pointer ("Up", window);
+ }
+ }
+ else
+ {
+ REFERENCE **menu;
+ int inhibit_menu_traversing = 0;
+
+ /* Watch out! If this node's Prev is the same as the Up, then
+ move Up. Otherwise, we could move Prev, and then to the last
+ menu item in the Prev. This would cause the user to loop
+ through a subsection of the info file. */
+ if (!info_parsed_filename && info_parsed_nodename)
+ {
+ char *pnode;
+
+ pnode = strdup (info_parsed_nodename);
+ info_up_label_of_node (window->node);
+
+ if (!info_parsed_filename && info_parsed_nodename &&
+ strcmp (info_parsed_nodename, pnode) == 0)
+ {
+ /* The nodes are the same. Inhibit moving to the last
+ menu item. */
+ free (pnode);
+ inhibit_menu_traversing = 1;
+ }
+ else
+ {
+ free (pnode);
+ info_prev_label_of_node (window->node);
+ }
+ }
+
+ /* Move to the previous node. If this node now contains a menu,
+ and we have not inhibited movement to it, move to the node
+ corresponding to the last menu item. */
+ window_message_in_echo_area ("Moving \"Prev\" in this window.");
+ info_handle_pointer ("Prev", window);
+
+ if (!inhibit_menu_traversing)
+ {
+ while (!info_error_was_printed &&
+ (menu = info_menu_of_node (window->node)))
+ {
+ info_free_references (menu);
+ window_message_in_echo_area
+ ("Moving to \"Prev\"'s last menu item.");
+ info_menu_digit (window, 1, '0');
+ }
+ }
+ }
+ break;
+ }
+}
+
+/* Move continuously forward through the node structure of this info file. */
+DECLARE_INFO_COMMAND (info_global_next_node,
+ "Move forwards or down through node structure")
+{
+ if (count < 0)
+ info_global_prev_node (window, -count, key);
+ else
+ {
+ while (count && !info_error_was_printed)
+ {
+ forward_move_node_structure (window, IS_Continuous);
+ count--;
+ }
+ }
+}
+
+/* Move continuously backward through the node structure of this info file. */
+DECLARE_INFO_COMMAND (info_global_prev_node,
+ "Move backwards or up through node structure")
+{
+ if (count < 0)
+ info_global_next_node (window, -count, key);
+ else
+ {
+ while (count && !info_error_was_printed)
+ {
+ backward_move_node_structure (window, IS_Continuous);
+ count--;
+ }
+ }
+}
+
+/* Show the next screen of WINDOW's node. */
+DECLARE_INFO_COMMAND (info_scroll_forward, "Scroll forward in this window")
+{
+ if (count < 0)
+ info_scroll_backward (window, -count, key);
+ else
+ {
+ int desired_top;
+
+ /* Without an explicit numeric argument, scroll the bottom two
+ lines to the top of this window, Or, if at bottom of window,
+ and the user wishes to scroll through nodes get the "Next" node
+ for this window. */
+ if (!info_explicit_arg && count == 1)
+ {
+ desired_top = window->pagetop + (window->height - 2);
+
+ /* If there are no more lines to scroll here, error, or get
+ another node, depending on INFO_SCROLL_BEHAVIOUR. */
+ if (desired_top > window->line_count)
+ {
+ int behaviour = info_scroll_behaviour;
+
+ /* Here is a hack. If the key being used is not SPC, do the
+ PageOnly behaviour. */
+ if (key != SPC && key != DEL)
+ behaviour = IS_PageOnly;
+
+ forward_move_node_structure (window, behaviour);
+ return;
+ }
+ }
+ else
+ desired_top = window->pagetop + count;
+
+ if (desired_top >= window->line_count)
+ desired_top = window->line_count - 2;
+
+ if (window->pagetop > desired_top)
+ return;
+ else
+ set_window_pagetop (window, desired_top);
+ }
+}
+
+/* Show the previous screen of WINDOW's node. */
+DECLARE_INFO_COMMAND (info_scroll_backward, "Scroll backward in this window")
+{
+ if (count < 0)
+ info_scroll_forward (window, -count, key);
+ else
+ {
+ int desired_top;
+
+ /* Without an explicit numeric argument, scroll the top two lines
+ to the bottom of this window, or move to the previous, or Up'th
+ node. */
+ if (!info_explicit_arg && count == 1)
+ {
+ desired_top = window->pagetop - (window->height - 2);
+
+ if ((desired_top < 0) && (window->pagetop == 0))
+ {
+ int behaviour = info_scroll_behaviour;
+
+ /* Same kind of hack as in info_scroll_forward. If the key
+ used to invoke this command is not DEL, do only the PageOnly
+ behaviour. */
+ if (key != DEL && key != SPC)
+ behaviour = IS_PageOnly;
+
+ backward_move_node_structure (window, behaviour);
+ return;
+ }
+ }
+ else
+ desired_top = window->pagetop - count;
+
+ if (desired_top < 0)
+ desired_top = 0;
+
+ set_window_pagetop (window, desired_top);
+ }
+}
+
+/* Move to the beginning of the node. */
+DECLARE_INFO_COMMAND (info_beginning_of_node, "Move to the start of this node")
+{
+ window->pagetop = window->point = 0;
+ window->flags |= W_UpdateWindow;
+}
+
+/* Move to the end of the node. */
+DECLARE_INFO_COMMAND (info_end_of_node, "Move to the end of this node")
+{
+ window->point = window->node->nodelen - 1;
+ info_show_point (window);
+}
+
+/* **************************************************************** */
+/* */
+/* Commands for Manipulating Windows */
+/* */
+/* **************************************************************** */
+
+/* Make the next window in the chain be the active window. */
+DECLARE_INFO_COMMAND (info_next_window, "Select the next window")
+{
+ if (count < 0)
+ {
+ info_prev_window (window, -count, key);
+ return;
+ }
+
+ /* If no other window, error now. */
+ if (!windows->next && !echo_area_is_active)
+ {
+ info_error (ONE_WINDOW);
+ return;
+ }
+
+ while (count--)
+ {
+ if (window->next)
+ window = window->next;
+ else
+ {
+ if (window == the_echo_area || !echo_area_is_active)
+ window = windows;
+ else
+ window = the_echo_area;
+ }
+ }
+
+ if (active_window != window)
+ {
+ if (auto_footnotes_p)
+ info_get_or_remove_footnotes (window);
+
+ window->flags |= W_UpdateWindow;
+ active_window = window;
+ }
+}
+
+/* Make the previous window in the chain be the active window. */
+DECLARE_INFO_COMMAND (info_prev_window, "Select the previous window")
+{
+ if (count < 0)
+ {
+ info_next_window (window, -count, key);
+ return;
+ }
+
+ /* Only one window? */
+
+ if (!windows->next && !echo_area_is_active)
+ {
+ info_error (ONE_WINDOW);
+ return;
+ }
+
+ while (count--)
+ {
+ /* If we are in the echo area, or if the echo area isn't active and we
+ are in the first window, find the last window in the chain. */
+ if (window == the_echo_area ||
+ (window == windows && !echo_area_is_active))
+ {
+ register WINDOW *win, *last;
+
+ for (win = windows; win; win = win->next)
+ last = win;
+
+ window = last;
+ }
+ else
+ {
+ if (window == windows)
+ window = the_echo_area;
+ else
+ window = window->prev;
+ }
+ }
+
+ if (active_window != window)
+ {
+ if (auto_footnotes_p)
+ info_get_or_remove_footnotes (window);
+
+ window->flags |= W_UpdateWindow;
+ active_window = window;
+ }
+}
+
+/* Split WINDOW into two windows, both showing the same node. If we
+ are automatically tiling windows, re-tile after the split. */
+DECLARE_INFO_COMMAND (info_split_window, "Split the current window")
+{
+ WINDOW *split, *old_active;
+ int pagetop;
+
+ /* Remember the current pagetop of the window being split. If it doesn't
+ change, we can scroll its contents around after the split. */
+ pagetop = window->pagetop;
+
+ /* Make the new window. */
+ old_active = active_window;
+ active_window = window;
+ split = window_make_window (window->node);
+ active_window = old_active;
+
+ if (!split)
+ {
+ info_error (WIN_TOO_SMALL);
+ }
+ else
+ {
+#if defined (SPLIT_BEFORE_ACTIVE)
+ /* Try to scroll the old window into its new postion. */
+ if (pagetop == window->pagetop)
+ {
+ int start, end, amount;
+
+ start = split->first_row;
+ end = start + window->height;
+ amount = split->height + 1;
+ display_scroll_display (start, end, amount);
+ }
+#else /* !SPLIT_BEFORE_ACTIVE */
+ /* Make sure point still appears in the active window. */
+ info_show_point (window);
+#endif /* !SPLIT_BEFORE_ACTIVE */
+
+ /* If the window just split was one internal to Info, try to display
+ something else in it. */
+ if (internal_info_node_p (split->node))
+ {
+ register int i, j;
+ INFO_WINDOW *iw;
+ NODE *node = (NODE *)NULL;
+ char *filename;
+
+ for (i = 0; iw = info_windows[i]; i++)
+ {
+ for (j = 0; j < iw->nodes_index; j++)
+ if (!internal_info_node_p (iw->nodes[j]))
+ {
+ if (iw->nodes[j]->parent)
+ filename = iw->nodes[j]->parent;
+ else
+ filename = iw->nodes[j]->filename;
+
+ node = info_get_node (filename, iw->nodes[j]->nodename);
+ if (node)
+ {
+ window_set_node_of_window (split, node);
+ i = info_windows_index - 1;
+ break;
+ }
+ }
+ }
+ }
+ split->pagetop = window->pagetop;
+
+ if (auto_tiling_p)
+ window_tile_windows (DONT_TILE_INTERNALS);
+ else
+ window_adjust_pagetop (split);
+
+ remember_window_and_node (split, split->node);
+ }
+}
+
+/* Delete WINDOW, forgetting the list of last visited nodes. If we are
+ automatically displaying footnotes, show or remove the footnotes
+ window. If we are automatically tiling windows, re-tile after the
+ deletion. */
+DECLARE_INFO_COMMAND (info_delete_window, "Delete the current window")
+{
+ if (!windows->next)
+ {
+ info_error (CANT_KILL_LAST);
+ }
+ else if (window->flags & W_WindowIsPerm)
+ {
+ info_error ("Cannot delete a permanent window");
+ }
+ else
+ {
+ info_delete_window_internal (window);
+
+ if (auto_footnotes_p)
+ info_get_or_remove_footnotes (active_window);
+
+ if (auto_tiling_p)
+ window_tile_windows (DONT_TILE_INTERNALS);
+ }
+}
+
+/* Do the physical deletion of WINDOW, and forget this window and
+ associated nodes. */
+void
+info_delete_window_internal (window)
+ WINDOW *window;
+{
+ if (windows->next && ((window->flags & W_WindowIsPerm) == 0))
+ {
+ /* We not only delete the window from the display, we forget it from
+ our list of remembered windows. */
+ forget_window_and_nodes (window);
+ window_delete_window (window);
+
+ if (echo_area_is_active)
+ echo_area_inform_of_deleted_window (window);
+ }
+}
+
+/* Just keep WINDOW, deleting all others. */
+DECLARE_INFO_COMMAND (info_keep_one_window, "Delete all other windows")
+{
+ int num_deleted; /* The number of windows we deleted. */
+ int pagetop, start, end;
+
+ /* Remember a few things about this window. We may be able to speed up
+ redisplay later by scrolling its contents. */
+ pagetop = window->pagetop;
+ start = window->first_row;
+ end = start + window->height;
+
+ num_deleted = 0;
+
+ while (1)
+ {
+ WINDOW *win;
+
+ /* Find an eligible window and delete it. If no eligible windows
+ are found, we are done. A window is eligible for deletion if
+ is it not permanent, and it is not WINDOW. */
+ for (win = windows; win; win = win->next)
+ if (win != window && ((win->flags & W_WindowIsPerm) == 0))
+ break;
+
+ if (!win)
+ break;
+
+ info_delete_window_internal (win);
+ num_deleted++;
+ }
+
+ /* Scroll the contents of this window into the right place so that the
+ user doesn't have to wait any longer than necessary for redisplay. */
+ if (num_deleted)
+ {
+ int amount;
+
+ amount = (window->first_row - start);
+ amount -= (window->pagetop - pagetop);
+ display_scroll_display (start, end, amount);
+ }
+
+ window->flags |= W_UpdateWindow;
+}
+
+/* Scroll the "other" window of WINDOW. */
+DECLARE_INFO_COMMAND (info_scroll_other_window, "Scroll the other window")
+{
+ WINDOW *other;
+
+ /* If only one window, give up. */
+ if (!windows->next)
+ {
+ info_error (ONE_WINDOW);
+ return;
+ }
+
+ other = window->next;
+
+ if (!other)
+ other = window->prev;
+
+ info_scroll_forward (other, count, key);
+}
+
+/* Change the size of WINDOW by AMOUNT. */
+DECLARE_INFO_COMMAND (info_grow_window, "Grow (or shrink) this window")
+{
+ window_change_window_height (window, count);
+}
+
+/* When non-zero, tiling takes place automatically when info_split_window
+ is called. */
+int auto_tiling_p = 0;
+
+/* Tile all of the visible windows. */
+DECLARE_INFO_COMMAND (info_tile_windows,
+ "Divide the available screen space among the visible windows")
+{
+ window_tile_windows (TILE_INTERNALS);
+}
+
+/* Toggle the state of this window's wrapping of lines. */
+DECLARE_INFO_COMMAND (info_toggle_wrap,
+ "Toggle the state of line wrapping in the current window")
+{
+ window_toggle_wrap (window);
+}
+
+/* **************************************************************** */
+/* */
+/* Info Node Commands */
+/* */
+/* **************************************************************** */
+
+/* Using WINDOW for various defaults, select the node referenced by ENTRY
+ in it. If the node is selected, the window and node are remembered. */
+void
+info_select_reference (window, entry)
+ WINDOW *window;
+ REFERENCE *entry;
+{
+ NODE *node;
+ char *filename, *nodename, *file_system_error;
+
+ file_system_error = (char *)NULL;
+
+ filename = entry->filename;
+ if (!filename)
+ filename = window->node->parent;
+ if (!filename)
+ filename = window->node->filename;
+
+ if (filename)
+ filename = strdup (filename);
+
+ if (entry->nodename)
+ nodename = strdup (entry->nodename);
+ else
+ nodename = strdup ("Top");
+
+ node = info_get_node (filename, nodename);
+
+ /* Try something a little weird. If the node couldn't be found, and the
+ reference was of the form "foo::", see if the entry->label can be found
+ as a file, with a node of "Top". */
+ if (!node)
+ {
+ if (info_recent_file_error)
+ file_system_error = strdup (info_recent_file_error);
+
+ if (entry->nodename && (strcmp (entry->nodename, entry->label) == 0))
+ {
+ node = info_get_node (entry->label, "Top");
+ if (!node && info_recent_file_error)
+ {
+ maybe_free (file_system_error);
+ file_system_error = strdup (info_recent_file_error);
+ }
+ }
+ }
+
+ if (!node)
+ {
+ if (file_system_error)
+ info_error (file_system_error);
+ else
+ info_error (CANT_FIND_NODE, nodename);
+ }
+
+ maybe_free (file_system_error);
+ maybe_free (filename);
+ maybe_free (nodename);
+
+ if (node)
+ {
+ set_remembered_pagetop_and_point (window);
+ info_set_node_of_window (window, node);
+ }
+}
+
+/* Parse the node specification in LINE using WINDOW to default the filename.
+ Select the parsed node in WINDOW and remember it, or error if the node
+ couldn't be found. */
+static void
+info_parse_and_select (line, window)
+ char *line;
+ WINDOW *window;
+{
+ REFERENCE entry;
+
+ info_parse_node (line, DONT_SKIP_NEWLINES);
+
+ entry.nodename = info_parsed_nodename;
+ entry.filename = info_parsed_filename;
+ entry.label = "*info-parse-and-select*";
+
+ info_select_reference (window, &entry);
+}
+
+/* Given that the values of INFO_PARSED_FILENAME and INFO_PARSED_NODENAME
+ are previously filled, try to get the node represented by them into
+ WINDOW. The node should have been pointed to by the LABEL pointer of
+ WINDOW->node. */
+static void
+info_handle_pointer (label, window)
+ char *label;
+ WINDOW *window;
+{
+ if (info_parsed_filename || info_parsed_nodename)
+ {
+ char *filename, *nodename;
+ NODE *node;
+
+ filename = nodename = (char *)NULL;
+
+ if (info_parsed_filename)
+ filename = strdup (info_parsed_filename);
+ else
+ {
+ if (window->node->parent)
+ filename = strdup (window->node->parent);
+ else if (window->node->filename)
+ filename = strdup (window->node->filename);
+ }
+
+ if (info_parsed_nodename)
+ nodename = strdup (info_parsed_nodename);
+ else
+ nodename = strdup ("Top");
+
+ node = info_get_node (filename, nodename);
+
+ if (node)
+ {
+ INFO_WINDOW *info_win;
+
+ info_win = get_info_window_of_window (window);
+ if (info_win)
+ {
+ info_win->pagetops[info_win->current] = window->pagetop;
+ info_win->points[info_win->current] = window->point;
+ }
+ set_remembered_pagetop_and_point (window);
+ info_set_node_of_window (window, node);
+ }
+ else
+ {
+ if (info_recent_file_error)
+ info_error (info_recent_file_error);
+ else
+ info_error (CANT_FILE_NODE, filename, nodename);
+ }
+
+ free (filename);
+ free (nodename);
+ }
+ else
+ {
+ info_error (NO_POINTER, label);
+ }
+}
+
+/* Make WINDOW display the "Next:" node of the node currently being
+ displayed. */
+DECLARE_INFO_COMMAND (info_next_node, "Select the `Next' node")
+{
+ info_next_label_of_node (window->node);
+ info_handle_pointer ("Next", window);
+}
+
+/* Make WINDOW display the "Prev:" node of the node currently being
+ displayed. */
+DECLARE_INFO_COMMAND (info_prev_node, "Select the `Prev' node")
+{
+ info_prev_label_of_node (window->node);
+ info_handle_pointer ("Prev", window);
+}
+
+/* Make WINDOW display the "Up:" node of the node currently being
+ displayed. */
+DECLARE_INFO_COMMAND (info_up_node, "Select the `Up' node")
+{
+ info_up_label_of_node (window->node);
+ info_handle_pointer ("Up", window);
+}
+
+/* Make WINDOW display the last node of this info file. */
+DECLARE_INFO_COMMAND (info_last_node, "Select the last node in this file")
+{
+ register int i;
+ FILE_BUFFER *fb = file_buffer_of_window (window);
+ NODE *node = (NODE *)NULL;
+
+ if (fb && fb->tags)
+ {
+ for (i = 0; fb->tags[i]; i++);
+ node = info_get_node (fb->filename, fb->tags[i - 1]->nodename);
+ }
+
+ if (!node)
+ info_error ("This window has no additional nodes");
+ else
+ {
+ set_remembered_pagetop_and_point (window);
+ info_set_node_of_window (window, node);
+ }
+}
+
+/* Make WINDOW display the first node of this info file. */
+DECLARE_INFO_COMMAND (info_first_node, "Select the first node in this file")
+{
+ FILE_BUFFER *fb = file_buffer_of_window (window);
+ NODE *node = (NODE *)NULL;
+
+ if (fb && fb->tags)
+ node = info_get_node (fb->filename, fb->tags[0]->nodename);
+
+ if (!node)
+ info_error ("This window has no additional nodes");
+ else
+ {
+ set_remembered_pagetop_and_point (window);
+ info_set_node_of_window (window, node);
+ }
+}
+
+/* Make WINDOW display the previous node displayed in this window. */
+DECLARE_INFO_COMMAND (info_history_node,
+ "Select the most recently selected node")
+{
+ INFO_WINDOW *info_win;
+
+ /* Find the INFO_WINDOW which contains WINDOW. */
+ info_win = get_info_window_of_window (window);
+
+ if (!info_win)
+ {
+ info_error ("Requested window is not present!");
+ return;
+ }
+
+ set_remembered_pagetop_and_point (window);
+ if (!info_win->current)
+ {
+ if (info_win->nodes_index > 1)
+ {
+ window_message_in_echo_area
+ ("Now wrapped around to beginning of history.");
+ info_win->current = info_win->nodes_index;
+ }
+ else
+ {
+ info_error ("No earlier nodes in this window.");
+ return;
+ }
+ }
+
+ info_win->current--;
+ window_set_node_of_window (window, info_win->nodes[info_win->current]);
+ window->pagetop = info_win->pagetops[info_win->current];
+ window->point = info_win->points[info_win->current];
+ window->flags |= W_UpdateWindow;
+ if (auto_footnotes_p)
+ info_get_or_remove_footnotes (window);
+}
+
+/* Select the last menu item in WINDOW->node. */
+DECLARE_INFO_COMMAND (info_last_menu_item,
+ "Select the last item in this node's menu")
+{
+ info_menu_digit (window, 1, '0');
+}
+
+/* Use KEY (a digit) to select the Nth menu item in WINDOW->node. */
+DECLARE_INFO_COMMAND (info_menu_digit, "Select this menu item")
+{
+ register int i, item;
+ register REFERENCE *entry, **menu;
+
+ menu = info_menu_of_node (window->node);
+
+ if (!menu)
+ {
+ info_error (NO_MENU_NODE);
+ return;
+ }
+
+ /* We have the menu. See if there are this many items in it. */
+ item = key - '0';
+
+ /* Special case. Item "0" is the last item in this menu. */
+ if (item == 0)
+ for (i = 0; menu[i + 1]; i++);
+ else
+ {
+ for (i = 0; entry = menu[i]; i++)
+ if (i == item - 1)
+ break;
+ }
+
+ if (menu[i])
+ info_select_reference (window, menu[i]);
+ else
+ info_error ("There aren't %d items in this menu.", item);
+
+ info_free_references (menu);
+ return;
+}
+
+/* Read a menu or followed reference from the user defaulting to the
+ reference found on the current line, and select that node. The
+ reading is done with completion. BUILDER is the function used
+ to build the list of references. ASK_P is non-zero if the user
+ should be prompted, or zero to select the default item. */
+static void
+info_menu_or_ref_item (window, count, key, builder, ask_p)
+ WINDOW *window;
+ int count;
+ unsigned char key;
+ REFERENCE **(*builder) ();
+ int ask_p;
+{
+ REFERENCE **menu, *entry, *defentry = (REFERENCE *)NULL;
+ char *line;
+
+ menu = (*builder) (window->node);
+
+ if (!menu)
+ {
+ if (builder == info_menu_of_node)
+ info_error (NO_MENU_NODE);
+ else
+ info_error (NO_XREF_NODE);
+ return;
+ }
+
+ /* Default the selected reference to the one which is on the line that
+ point is in. */
+ {
+ REFERENCE **refs = (REFERENCE **)NULL;
+ int point_line;
+
+ point_line = window_line_of_point (window);
+
+ if (point_line != -1)
+ {
+ SEARCH_BINDING binding;
+
+ binding.buffer = window->node->contents;
+ binding.start = window->line_starts[point_line] - binding.buffer;
+ if (window->line_starts[point_line + 1])
+ binding.end = window->line_starts[point_line + 1] - binding.buffer;
+ else
+ binding.end = window->node->nodelen;
+ binding.flags = 0;
+
+ if (builder == info_menu_of_node)
+ {
+ if (point_line)
+ {
+ binding.start--;
+ refs = info_menu_items (&binding);
+ }
+ }
+ else
+ {
+#if defined (HANDLE_MAN_PAGES)
+ if (window->node->flags & N_IsManPage)
+ refs = manpage_xrefs_in_binding (window->node, &binding);
+ else
+#endif /* HANDLE_MAN_PAGES */
+ refs = info_xrefs (&binding);
+ }
+
+ if (refs)
+ {
+ if ((strcmp (refs[0]->label, "Menu") != 0) ||
+ (builder == info_xrefs_of_node))
+ {
+ int which = 0;
+
+ /* Find the closest reference to point. */
+ if (builder == info_xrefs_of_node)
+ {
+ int closest = -1;
+
+ for (; refs[which]; which++)
+ {
+ if ((window->point >= refs[which]->start) &&
+ (window->point <= refs[which]->end))
+ {
+ closest = which;
+ break;
+ }
+ else if (window->point < refs[which]->start)
+ {
+ break;
+ }
+ }
+ if (closest == -1)
+ which--;
+ else
+ which = closest;
+ }
+
+ defentry = (REFERENCE *)xmalloc (sizeof (REFERENCE));
+ defentry->label = strdup (refs[which]->label);
+ defentry->filename = refs[which]->filename;
+ defentry->nodename = refs[which]->nodename;
+
+ if (defentry->filename)
+ defentry->filename = strdup (defentry->filename);
+ if (defentry->nodename)
+ defentry->nodename = strdup (defentry->nodename);
+ }
+ info_free_references (refs);
+ }
+ }
+ }
+
+ /* If we are going to ask the user a question, do it now. */
+ if (ask_p)
+ {
+ char *prompt;
+
+ /* Build the prompt string. */
+ if (defentry)
+ prompt = (char *)xmalloc (20 + strlen (defentry->label));
+ else
+ prompt = (char *)xmalloc (20);
+
+ if (builder == info_menu_of_node)
+ {
+ if (defentry)
+ sprintf (prompt, "Menu item (%s): ", defentry->label);
+ else
+ sprintf (prompt, "Menu item: ");
+ }
+ else
+ {
+ if (defentry)
+ sprintf (prompt, "Follow xref (%s): ", defentry->label);
+ else
+ sprintf (prompt, "Follow xref: ");
+ }
+
+ line = info_read_completing_in_echo_area (window, prompt, menu);
+ free (prompt);
+
+ window = active_window;
+
+ /* User aborts, just quit. */
+ if (!line)
+ {
+ maybe_free (defentry);
+ info_free_references (menu);
+ info_abort_key (window, 0, 0);
+ return;
+ }
+
+ /* If we had a default and the user accepted it, use that. */
+ if (!*line)
+ {
+ free (line);
+ if (defentry)
+ line = strdup (defentry->label);
+ else
+ line = (char *)NULL;
+ }
+ }
+ else
+ {
+ /* Not going to ask any questions. If we have a default entry, use
+ that, otherwise return. */
+ if (!defentry)
+ return;
+ else
+ line = strdup (defentry->label);
+ }
+
+ if (line)
+ {
+ /* Find the selected label in the references. */
+ entry = info_get_labeled_reference (line, menu);
+
+ if (!entry && defentry)
+ info_error ("The reference disappeared! (%s).", line);
+ else
+ {
+ NODE *orig;
+
+ orig = window->node;
+ info_select_reference (window, entry);
+ if ((builder == info_xrefs_of_node) && (window->node != orig))
+ {
+ long offset;
+ long start;
+
+ if (window->line_count > 0)
+ start = window->line_starts[1] - window->node->contents;
+ else
+ start = 0;
+
+ offset =
+ info_target_search_node (window->node, entry->label, start);
+
+ if (offset != -1)
+ {
+ window->point = offset;
+ window_adjust_pagetop (window);
+ }
+ }
+ }
+
+ free (line);
+ if (defentry)
+ {
+ free (defentry->label);
+ maybe_free (defentry->filename);
+ maybe_free (defentry->nodename);
+ free (defentry);
+ }
+ }
+
+ info_free_references (menu);
+
+ if (!info_error_was_printed)
+ window_clear_echo_area ();
+}
+
+/* Read a line (with completion) which is the name of a menu item,
+ and select that item. */
+DECLARE_INFO_COMMAND (info_menu_item, "Read a menu item and select its node")
+{
+ info_menu_or_ref_item (window, count, key, info_menu_of_node, 1);
+}
+
+/* Read a line (with completion) which is the name of a reference to
+ follow, and select the node. */
+DECLARE_INFO_COMMAND
+ (info_xref_item, "Read a footnote or cross reference and select its node")
+{
+ info_menu_or_ref_item (window, count, key, info_xrefs_of_node, 1);
+}
+
+/* Position the cursor at the start of this node's menu. */
+DECLARE_INFO_COMMAND (info_find_menu, "Move to the start of this node's menu")
+{
+ SEARCH_BINDING binding;
+ long position;
+
+ binding.buffer = window->node->contents;
+ binding.start = 0;
+ binding.end = window->node->nodelen;
+ binding.flags = S_FoldCase | S_SkipDest;
+
+ position = search (INFO_MENU_LABEL, &binding);
+
+ if (position == -1)
+ info_error (NO_MENU_NODE);
+ else
+ {
+ window->point = position;
+ window_adjust_pagetop (window);
+ window->flags |= W_UpdateWindow;
+ }
+}
+
+/* Visit as many menu items as is possible, each in a separate window. */
+DECLARE_INFO_COMMAND (info_visit_menu,
+ "Visit as many menu items at once as possible")
+{
+ register int i;
+ REFERENCE *entry, **menu;
+
+ menu = info_menu_of_node (window->node);
+
+ if (!menu)
+ info_error (NO_MENU_NODE);
+
+ for (i = 0; (!info_error_was_printed) && (entry = menu[i]); i++)
+ {
+ WINDOW *new;
+
+ new = window_make_window (window->node);
+ window_tile_windows (TILE_INTERNALS);
+
+ if (!new)
+ info_error (WIN_TOO_SMALL);
+ else
+ {
+ active_window = new;
+ info_select_reference (new, entry);
+ }
+ }
+}
+
+/* Read a line of input which is a node name, and go to that node. */
+DECLARE_INFO_COMMAND (info_goto_node, "Read a node name and select it")
+{
+ char *line;
+ NODE *node;
+
+#define GOTO_COMPLETES
+#if defined (GOTO_COMPLETES)
+ /* Build a completion list of all of the known nodes. */
+ {
+ register int fbi, i;
+ FILE_BUFFER *current;
+ REFERENCE **items = (REFERENCE **)NULL;
+ int items_index = 0;
+ int items_slots = 0;
+
+ current = file_buffer_of_window (window);
+
+ for (fbi = 0; info_loaded_files && info_loaded_files[fbi]; fbi++)
+ {
+ FILE_BUFFER *fb;
+ REFERENCE *entry;
+ int this_is_the_current_fb;
+
+ fb = info_loaded_files[fbi];
+ this_is_the_current_fb = (current == fb);
+
+ entry = (REFERENCE *)xmalloc (sizeof (REFERENCE));
+ entry->filename = entry->nodename = (char *)NULL;
+ entry->label = (char *)xmalloc (4 + strlen (fb->filename));
+ sprintf (entry->label, "(%s)*", fb->filename);
+
+ add_pointer_to_array
+ (entry, items_index, items, items_slots, 10, REFERENCE *);
+
+ if (fb->tags)
+ {
+ for (i = 0; fb->tags[i]; i++)
+ {
+ entry = (REFERENCE *)xmalloc (sizeof (REFERENCE));
+ entry->filename = entry->nodename = (char *)NULL;
+ entry->label = (char *) xmalloc
+ (4 + strlen (fb->filename) + strlen (fb->tags[i]->nodename));
+ sprintf (entry->label, "(%s)%s",
+ fb->filename, fb->tags[i]->nodename);
+
+ add_pointer_to_array
+ (entry, items_index, items, items_slots, 100, REFERENCE *);
+ }
+
+ if (this_is_the_current_fb)
+ {
+ for (i = 0; fb->tags[i]; i++)
+ {
+ entry = (REFERENCE *)xmalloc (sizeof (REFERENCE));
+ entry->filename = entry->nodename = (char *)NULL;
+ entry->label = strdup (fb->tags[i]->nodename);
+ add_pointer_to_array (entry, items_index, items,
+ items_slots, 100, REFERENCE *);
+ }
+ }
+ }
+ }
+ line = info_read_maybe_completing (window, "Goto Node: ", items);
+ info_free_references (items);
+ }
+#else /* !GOTO_COMPLETES */
+ line = info_read_in_echo_area (window, "Goto Node: ");
+#endif /* !GOTO_COMPLETES */
+
+ /* If the user aborted, quit now. */
+ if (!line)
+ {
+ info_abort_key (window, 0, 0);
+ return;
+ }
+
+ canonicalize_whitespace (line);
+
+ if (*line)
+ info_parse_and_select (line, window);
+
+ free (line);
+ if (!info_error_was_printed)
+ window_clear_echo_area ();
+}
+
+#if defined (HANDLE_MAN_PAGES)
+DECLARE_INFO_COMMAND (info_man, "Read a manpage reference and select it")
+{
+ char *line;
+ NODE *node;
+
+ line = info_read_in_echo_area (window, "Get Manpage: ");
+
+ if (!line)
+ {
+ info_abort_key (window, 0, 0);
+ return;
+ }
+
+ canonicalize_whitespace (line);
+
+ if (*line)
+ {
+ char *goto_command;
+
+ goto_command = (char *)xmalloc
+ (4 + strlen (MANPAGE_FILE_BUFFER_NAME) + strlen (line));
+
+ sprintf (goto_command, "(%s)%s", MANPAGE_FILE_BUFFER_NAME, line);
+
+ info_parse_and_select (goto_command, window);
+ free (goto_command);
+ }
+
+ free (line);
+ if (!info_error_was_printed)
+ window_clear_echo_area ();
+}
+#endif /* HANDLE_MAN_PAGES */
+
+/* Move to the "Top" node in this file. */
+DECLARE_INFO_COMMAND (info_top_node, "Select the node `Top' in this file")
+{
+ info_parse_and_select ("Top", window);
+}
+
+/* Move to the node "(dir)Top". */
+DECLARE_INFO_COMMAND (info_dir_node, "Select the node `(dir)'")
+{
+ info_parse_and_select ("(dir)Top", window);
+}
+
+/* Try to delete the current node appearing in this window, showing the most
+ recently selected node in this window. */
+DECLARE_INFO_COMMAND (info_kill_node, "Kill this node")
+{
+ register int iw, i;
+ register INFO_WINDOW *info_win;
+ char *nodename = (char *)NULL;
+ NODE *temp = (NODE *)NULL;
+
+ /* Read the name of a node to kill. The list of available nodes comes
+ from the nodes appearing in the current window configuration. */
+ {
+ REFERENCE **menu = (REFERENCE **)NULL;
+ int menu_index = 0, menu_slots = 0;
+ char *default_nodename, *prompt;
+
+ for (iw = 0; info_win = info_windows[iw]; iw++)
+ {
+ REFERENCE *entry;
+
+ entry = (REFERENCE *)xmalloc (sizeof (REFERENCE));
+ entry->label = strdup (info_win->window->node->nodename);
+ entry->filename = entry->nodename = (char *)NULL;
+
+ add_pointer_to_array
+ (entry, menu_index, menu, menu_slots, 10, REFERENCE *);
+ }
+
+ default_nodename = strdup (active_window->node->nodename);
+ prompt = (char *)xmalloc (40 + strlen (default_nodename));
+ sprintf (prompt, "Kill node (%s): ", default_nodename);
+
+ nodename = info_read_completing_in_echo_area (window, prompt, menu);
+ free (prompt);
+ info_free_references (menu);
+ if (nodename && !*nodename)
+ {
+ free (nodename);
+ nodename = default_nodename;
+ }
+ else
+ free (default_nodename);
+ }
+
+ /* If there is no nodename to kill, quit now. */
+ if (!nodename)
+ {
+ info_abort_key (window, 0, 0);
+ return;
+ }
+
+ /* If there is a nodename, find it in our window list. */
+ for (iw = 0; info_win = info_windows[iw]; iw++)
+ if (strcmp (nodename, info_win->nodes[info_win->current]->nodename) == 0)
+ break;
+
+ if (!info_win)
+ {
+ if (*nodename)
+ info_error ("Cannot kill the node `%s'", nodename);
+ else
+ window_clear_echo_area ();
+
+ return;
+ }
+
+ /* If there are no more nodes left anywhere to view, complain and exit. */
+ if (info_windows_index == 1 && info_windows[0]->nodes_index == 1)
+ {
+ info_error ("Cannot kill the last node");
+ return;
+ }
+
+ /* INFO_WIN contains the node that the user wants to stop viewing.
+ Delete this node from the list of nodes previously shown in this
+ window. */
+ for (i = info_win->current; i < info_win->nodes_index; i++)
+ info_win->nodes[i] = info_win->nodes[i++];
+
+ /* There is one less node in this window's history list. */
+ info_win->nodes_index--;
+
+ /* Make this window show the most recent history node. */
+ info_win->current = info_win->nodes_index - 1;
+
+ /* If there aren't any nodes left in this window, steal one from the
+ next window. */
+ if (info_win->current < 0)
+ {
+ INFO_WINDOW *stealer;
+ int which, pagetop;
+ long point;
+
+ if (info_windows[iw + 1])
+ stealer = info_windows[iw + 1];
+ else
+ stealer = info_windows[0];
+
+ /* If the node being displayed in the next window is not the most
+ recently loaded one, get the most recently loaded one. */
+ if ((stealer->nodes_index - 1) != stealer->current)
+ which = stealer->nodes_index - 1;
+
+ /* Else, if there is another node behind the stealers current node,
+ use that one. */
+ else if (stealer->current > 0)
+ which = stealer->current - 1;
+
+ /* Else, just use the node appearing in STEALER's window. */
+ else
+ which = stealer->current;
+
+ /* Copy this node. */
+ {
+ NODE *copy;
+
+ temp = stealer->nodes[which];
+ point = stealer->points[which];
+ pagetop = stealer->pagetops[which];
+
+ copy = (NODE *)xmalloc (sizeof (NODE));
+ copy->filename = temp->filename;
+ copy->parent = temp->parent;
+ copy->nodename = temp->nodename;
+ copy->contents = temp->contents;
+ copy->nodelen = temp->nodelen;
+ copy->flags = temp->flags;
+
+ temp = copy;
+ }
+
+ window_set_node_of_window (info_win->window, temp);
+ window->point = point;
+ window->pagetop = pagetop;
+ remember_window_and_node (info_win->window, temp);
+ }
+ else
+ {
+ temp = info_win->nodes[info_win->current];
+ window_set_node_of_window (info_win->window, temp);
+ }
+ if (!info_error_was_printed)
+ window_clear_echo_area ();
+}
+
+/* Read the name of a file and select the entire file. */
+DECLARE_INFO_COMMAND (info_view_file, "Read the name of a file and select it")
+{
+ char *line;
+
+ line = info_read_in_echo_area (window, "Find file: ");
+ if (!line)
+ {
+ info_abort_key (active_window, 1, 0);
+ return;
+ }
+
+ if (*line)
+ {
+ NODE *node;
+
+ node = info_get_node (line, "*");
+ if (!node)
+ {
+ if (info_recent_file_error)
+ info_error (info_recent_file_error);
+ else
+ info_error ("Cannot find \"%s\".", line);
+ }
+ else
+ {
+ set_remembered_pagetop_and_point (active_window);
+ info_set_node_of_window (window, node);
+ }
+ free (line);
+ }
+
+ if (!info_error_was_printed)
+ window_clear_echo_area ();
+}
+
+/* **************************************************************** */
+/* */
+/* Dumping and Printing Nodes */
+/* */
+/* **************************************************************** */
+
+#define VERBOSE_NODE_DUMPING
+static void write_node_to_stream ();
+static void dump_node_to_stream ();
+static void initialize_dumping ();
+
+/* Dump the nodes specified by FILENAME and NODENAMES to the file named
+ in OUTPUT_FILENAME. If DUMP_SUBNODES is non-zero, recursively dump
+ the nodes which appear in the menu of each node dumped. */
+void
+dump_nodes_to_file (filename, nodenames, output_filename, dump_subnodes)
+ char *filename;
+ char **nodenames;
+ char *output_filename;
+ int dump_subnodes;
+{
+ register int i;
+ FILE *output_stream;
+
+ /* Get the stream to print the nodes to. Special case of an output
+ filename of "-" means to dump the nodes to stdout. */
+ if (strcmp (output_filename, "-") == 0)
+ output_stream = stdout;
+ else
+ output_stream = fopen (output_filename, "w");
+
+ if (!output_stream)
+ {
+ info_error ("Could not create output file \"%s\".", output_filename);
+ return;
+ }
+
+ /* Print each node to stream. */
+ initialize_dumping ();
+ for (i = 0; nodenames[i]; i++)
+ dump_node_to_stream (filename, nodenames[i], output_stream, dump_subnodes);
+
+ if (output_stream != stdout)
+ fclose (output_stream);
+
+#if defined (VERBOSE_NODE_DUMPING)
+ info_error ("Done.");
+#endif /* VERBOSE_NODE_DUMPING */
+}
+
+/* A place to remember already dumped nodes. */
+static char **dumped_already = (char **)NULL;
+static int dumped_already_index = 0;
+static int dumped_already_slots = 0;
+
+static void
+initialize_dumping ()
+{
+ dumped_already_index = 0;
+}
+
+/* Get and print the node specified by FILENAME and NODENAME to STREAM.
+ If DUMP_SUBNODES is non-zero, recursively dump the nodes which appear
+ in the menu of each node dumped. */
+static void
+dump_node_to_stream (filename, nodename, stream, dump_subnodes)
+ char *filename, *nodename;
+ FILE *stream;
+ int dump_subnodes;
+{
+ register int i;
+ NODE *node;
+
+ node = info_get_node (filename, nodename);
+
+ if (!node)
+ {
+ if (info_recent_file_error)
+ info_error (info_recent_file_error);
+ else
+ {
+ if (filename && *nodename != '(')
+ info_error
+ (CANT_FILE_NODE, filename_non_directory (filename), nodename);
+ else
+ info_error (CANT_FIND_NODE, nodename);
+ }
+ return;
+ }
+
+ /* If we have already dumped this node, don't dump it again. */
+ for (i = 0; i < dumped_already_index; i++)
+ if (strcmp (node->nodename, dumped_already[i]) == 0)
+ {
+ free (node);
+ return;
+ }
+ add_pointer_to_array (node->nodename, dumped_already_index, dumped_already,
+ dumped_already_slots, 50, char *);
+
+#if defined (VERBOSE_NODE_DUMPING)
+ /* Maybe we should print some information about the node being output. */
+ if (node->filename)
+ info_error ("Writing node \"(%s)%s\"...",
+ filename_non_directory (node->filename), node->nodename);
+ else
+ info_error ("Writing node \"%s\"...", node->nodename);
+#endif /* VERBOSE_NODE_DUMPING */
+
+ write_node_to_stream (node, stream);
+
+ /* If we are dumping subnodes, get the list of menu items in this node,
+ and dump each one recursively. */
+ if (dump_subnodes)
+ {
+ REFERENCE **menu = (REFERENCE **)NULL;
+
+ /* If this node is an Index, do not dump the menu references. */
+ if (string_in_line ("Index", node->nodename) == -1)
+ menu = info_menu_of_node (node);
+
+ if (menu)
+ {
+ for (i = 0; menu[i]; i++)
+ {
+ /* We don't dump Info files which are different than the
+ current one. */
+ if (!menu[i]->filename)
+ dump_node_to_stream
+ (filename, menu[i]->nodename, stream, dump_subnodes);
+ }
+ info_free_references (menu);
+ }
+ }
+
+ free (node);
+}
+
+/* Dump NODE to FILENAME. If DUMP_SUBNODES is non-zero, recursively dump
+ the nodes which appear in the menu of each node dumped. */
+void
+dump_node_to_file (node, filename, dump_subnodes)
+ NODE *node;
+ char *filename;
+ int dump_subnodes;
+{
+ FILE *output_stream;
+ char *nodes_filename;
+
+ /* Get the stream to print this node to. Special case of an output
+ filename of "-" means to dump the nodes to stdout. */
+ if (strcmp (filename, "-") == 0)
+ output_stream = stdout;
+ else
+ output_stream = fopen (filename, "w");
+
+ if (!output_stream)
+ {
+ info_error ("Could not create output file \"%s\".", filename);
+ return;
+ }
+
+ if (node->parent)
+ nodes_filename = node->parent;
+ else
+ nodes_filename = node->filename;
+
+ initialize_dumping ();
+ dump_node_to_stream
+ (nodes_filename, node->nodename, output_stream, dump_subnodes);
+
+ if (output_stream != stdout)
+ fclose (output_stream);
+
+#if defined (VERBOSE_NODE_DUMPING)
+ info_error ("Done.");
+#endif /* VERBOSE_NODE_DUMPING */
+}
+
+#if !defined (DEFAULT_INFO_PRINT_COMMAND)
+# define DEFAULT_INFO_PRINT_COMMAND "lpr"
+#endif /* !DEFAULT_INFO_PRINT_COMMAND */
+
+DECLARE_INFO_COMMAND (info_print_node,
+ "Pipe the contents of this node through INFO_PRINT_COMMAND")
+{
+ print_node (window->node);
+}
+
+/* Print NODE on a printer piping it into INFO_PRINT_COMMAND. */
+void
+print_node (node)
+ NODE *node;
+{
+ char *print_command, *getenv ();
+ FILE *printer_pipe;
+
+ print_command = getenv ("INFO_PRINT_COMMAND");
+
+ if (!print_command || !*print_command)
+ print_command = DEFAULT_INFO_PRINT_COMMAND;
+
+ printer_pipe = popen (print_command, "w");
+
+ if (!printer_pipe)
+ {
+ info_error ("Cannot open pipe to \"%s\".", print_command);
+ return;
+ }
+
+#if defined (VERBOSE_NODE_DUMPING)
+ /* Maybe we should print some information about the node being output. */
+ if (node->filename)
+ info_error ("Printing node \"(%s)%s\"...",
+ filename_non_directory (node->filename), node->nodename);
+ else
+ info_error ("Printing node \"%s\"...", node->nodename);
+#endif /* VERBOSE_NODE_DUMPING */
+
+ write_node_to_stream (node, printer_pipe);
+ pclose (printer_pipe);
+
+#if defined (VERBOSE_NODE_DUMPING)
+ info_error ("Done.");
+#endif /* VERBOSE_NODE_DUMPING */
+}
+
+static void
+write_node_to_stream (node, stream)
+ NODE *node;
+ FILE *stream;
+{
+ fwrite (node->contents, 1, node->nodelen, stream);
+}
+
+/* **************************************************************** */
+/* */
+/* Info Searching Commands */
+/* */
+/* **************************************************************** */
+
+/* Variable controlling the garbage collection of files briefly visited
+ during searches. Such files are normally gc'ed, unless they were
+ compressed to begin with. If this variable is non-zero, it says
+ to gc even those file buffer contents which had to be uncompressed. */
+int gc_compressed_files = 0;
+
+static void info_gc_file_buffers ();
+
+static char *search_string = (char *)NULL;
+static int search_string_index = 0;
+static int search_string_size = 0;
+static int isearch_is_active = 0;
+
+/* Return the file buffer which belongs to WINDOW's node. */
+FILE_BUFFER *
+file_buffer_of_window (window)
+ WINDOW *window;
+{
+ /* If this window has no node, then it has no file buffer. */
+ if (!window->node)
+ return ((FILE_BUFFER *)NULL);
+
+ if (window->node->parent)
+ return (info_find_file (window->node->parent));
+
+ if (window->node->filename)
+ return (info_find_file (window->node->filename));
+
+ return ((FILE_BUFFER *)NULL);
+}
+
+/* Search for STRING in NODE starting at START. Return -1 if the string
+ was not found, or the location of the string if it was. If WINDOW is
+ passed as non-null, set the window's node to be NODE, its point to be
+ the found string, and readjust the window's pagetop. Final argument
+ DIR says which direction to search in. If it is positive, search
+ forward, else backwards. */
+long
+info_search_in_node (string, node, start, window, dir)
+ char *string;
+ NODE *node;
+ long start;
+ WINDOW *window;
+ int dir;
+{
+ SEARCH_BINDING binding;
+ long offset;
+
+ binding.buffer = node->contents;
+ binding.start = start;
+ binding.end = node->nodelen;
+ binding.flags = S_FoldCase;
+
+ if (dir < 0)
+ {
+ binding.end = 0;
+ binding.flags |= S_SkipDest;
+ }
+
+ if (binding.start < 0)
+ return (-1);
+
+ /* For incremental searches, we always wish to skip past the string. */
+ if (isearch_is_active)
+ binding.flags |= S_SkipDest;
+
+ offset = search (string, &binding);
+
+ if (offset != -1 && window)
+ {
+ set_remembered_pagetop_and_point (window);
+ if (window->node != node)
+ window_set_node_of_window (window, node);
+ window->point = offset;
+ window_adjust_pagetop (window);
+ }
+ return (offset);
+}
+
+/* Search NODE, looking for the largest possible match of STRING. Start the
+ search at START. Return the absolute position of the match, or -1, if
+ no part of the string could be found. */
+long
+info_target_search_node (node, string, start)
+ NODE *node;
+ char *string;
+ long start;
+{
+ register int i;
+ long offset;
+ char *target;
+
+ target = strdup (string);
+ i = strlen (target);
+
+ /* Try repeatedly searching for this string while removing words from
+ the end of it. */
+ while (i)
+ {
+ target[i] = '\0';
+ offset = info_search_in_node (target, node, start, (WINDOW *)NULL, 1);
+
+ if (offset != -1)
+ break;
+
+ /* Delete the last word from TARGET. */
+ for (; i && (!whitespace (target[i]) && (target[i] != ',')); i--);
+ }
+ free (target);
+ return (offset);
+}
+
+/* Search for STRING starting in WINDOW at point. If the string is found
+ in this node, set point to that position. Otherwise, get the file buffer
+ associated with WINDOW's node, and search through each node in that file.
+ If the search fails, return non-zero, else zero. Side-effect window
+ leaving the node and point where the string was found current. */
+static char *last_searched_for_string = (char *)NULL;
+static int
+info_search_internal (string, window, dir)
+ char *string;
+ WINDOW *window;
+ int dir;
+{
+ register int i;
+ FILE_BUFFER *file_buffer;
+ char *initial_nodename;
+ long ret, start = 0;
+
+ file_buffer = file_buffer_of_window (window);
+ initial_nodename = window->node->nodename;
+
+ if ((info_last_executed_command == info_search) &&
+ (last_searched_for_string) &&
+ (strcmp (last_searched_for_string, string) == 0))
+ {
+ ret = info_search_in_node
+ (string, window->node, window->point + dir, window, dir);
+ }
+ else
+ {
+ ret = info_search_in_node
+ (string, window->node, window->point, window, dir);
+ }
+
+ maybe_free (last_searched_for_string);
+ last_searched_for_string = strdup (string);
+
+ if (ret != -1)
+ {
+ /* We won! */
+ if (!echo_area_is_active && !isearch_is_active)
+ window_clear_echo_area ();
+ return (0);
+ }
+
+ /* The string wasn't found in the current node. Search through the
+ window's file buffer, iff the current node is not "*". */
+ if (!file_buffer || (strcmp (initial_nodename, "*") == 0))
+ return (-1);
+
+ /* If this file has tags, search through every subfile, starting at
+ this node's subfile and node. Otherwise, search through the
+ file's node list. */
+ if (file_buffer->tags)
+ {
+ register int current_tag, number_of_tags;
+ char *last_subfile;
+ TAG *tag;
+
+ /* Find number of tags and current tag. */
+ last_subfile = (char *)NULL;
+ for (i = 0; file_buffer->tags[i]; i++)
+ if (strcmp (initial_nodename, file_buffer->tags[i]->nodename) == 0)
+ {
+ current_tag = i;
+ last_subfile = file_buffer->tags[i]->filename;
+ }
+
+ number_of_tags = i;
+
+ /* If there is no last_subfile, our tag wasn't found. */
+ if (!last_subfile)
+ return (-1);
+
+ /* Search through subsequent nodes, wrapping around to the top
+ of the info file until we find the string or return to this
+ window's node and point. */
+ while (1)
+ {
+ NODE *node;
+
+ /* Allow C-g to quit the search, failing it if pressed. */
+ return_if_control_g (-1);
+
+ current_tag += dir;
+
+ if (current_tag < 0)
+ current_tag = number_of_tags - 1;
+ else if (current_tag == number_of_tags)
+ current_tag = 0;
+
+ tag = file_buffer->tags[current_tag];
+
+ if (!echo_area_is_active && (last_subfile != tag->filename))
+ {
+ window_message_in_echo_area
+ ("Searching subfile \"%s\"...",
+ filename_non_directory (tag->filename));
+
+ last_subfile = tag->filename;
+ }
+
+ node = info_get_node (file_buffer->filename, tag->nodename);
+
+ if (!node)
+ {
+ /* If not doing i-search... */
+ if (!echo_area_is_active)
+ {
+ if (info_recent_file_error)
+ info_error (info_recent_file_error);
+ else
+ info_error (CANT_FILE_NODE,
+ filename_non_directory (file_buffer->filename),
+ tag->nodename);
+ }
+ return (-1);
+ }
+
+ if (dir < 0)
+ start = tag->nodelen;
+
+ ret =
+ info_search_in_node (string, node, start, window, dir);
+
+ /* Did we find the string in this node? */
+ if (ret != -1)
+ {
+ /* Yes! We win. */
+ remember_window_and_node (window, node);
+ if (!echo_area_is_active)
+ window_clear_echo_area ();
+ return (0);
+ }
+
+ /* No. Free this node, and make sure that we haven't passed
+ our starting point. */
+ free (node);
+
+ if (strcmp (initial_nodename, tag->nodename) == 0)
+ return (-1);
+ }
+ }
+ return (-1);
+}
+
+DECLARE_INFO_COMMAND (info_search, "Read a string and search for it")
+{
+ char *line, *prompt;
+ int result, old_pagetop;
+ int direction;
+
+ if (count < 0)
+ direction = -1;
+ else
+ direction = 1;
+
+ /* Read a string from the user, defaulting the search to SEARCH_STRING. */
+ if (!search_string)
+ {
+ search_string = (char *)xmalloc (search_string_size = 100);
+ search_string[0] = '\0';
+ }
+
+ prompt = (char *)xmalloc (50 + strlen (search_string));
+
+ sprintf (prompt, "%s for string [%s]: ",
+ direction < 0 ? "Search backward" : "Search",
+ search_string);
+
+ line = info_read_in_echo_area (window, prompt);
+ free (prompt);
+
+ if (!line)
+ {
+ info_abort_key ();
+ return;
+ }
+
+ if (*line)
+ {
+ if (strlen (line) + 1 > search_string_size)
+ search_string = (char *)
+ xrealloc (search_string, (search_string_size += 50 + strlen (line)));
+
+ strcpy (search_string, line);
+ search_string_index = strlen (line);
+ free (line);
+ }
+
+ old_pagetop = active_window->pagetop;
+ result = info_search_internal (search_string, active_window, direction);
+
+ if (result != 0 && !info_error_was_printed)
+ info_error ("Search failed.");
+ else if (old_pagetop != active_window->pagetop)
+ {
+ int new_pagetop;
+
+ new_pagetop = active_window->pagetop;
+ active_window->pagetop = old_pagetop;
+ set_window_pagetop (active_window, new_pagetop);
+ if (auto_footnotes_p)
+ info_get_or_remove_footnotes (active_window);
+ }
+
+ /* Perhaps free the unreferenced file buffers that were searched, but
+ not retained. */
+ info_gc_file_buffers ();
+}
+
+/* **************************************************************** */
+/* */
+/* Incremental Searching */
+/* */
+/* **************************************************************** */
+
+static void incremental_search ();
+
+DECLARE_INFO_COMMAND (isearch_forward,
+ "Search interactively for a string as you type it")
+{
+ incremental_search (window, count, key);
+}
+
+DECLARE_INFO_COMMAND (isearch_backward,
+ "Search interactively for a string as you type it")
+{
+ incremental_search (window, -count, key);
+}
+
+/* Incrementally search for a string as it is typed. */
+/* The last accepted incremental search string. */
+static char *last_isearch_accepted = (char *)NULL;
+
+/* The current incremental search string. */
+static char *isearch_string = (char *)NULL;
+static int isearch_string_index = 0;
+static int isearch_string_size = 0;
+static unsigned char isearch_terminate_search_key = ESC;
+
+/* Structure defining the current state of an incremental search. */
+typedef struct {
+ WINDOW_STATE_DECL; /* The node, pagetop and point. */
+ int search_index; /* Offset of the last char in the search string. */
+ int direction; /* The direction that this search is heading in. */
+ int failing; /* Whether or not this search failed. */
+} SEARCH_STATE;
+
+/* Array of search states. */
+static SEARCH_STATE **isearch_states = (SEARCH_STATE **)NULL;
+static int isearch_states_index = 0;
+static int isearch_states_slots = 0;
+
+/* Push the state of this search. */
+static void
+push_isearch (window, search_index, direction, failing)
+ WINDOW *window;
+ int search_index, direction, failing;
+{
+ SEARCH_STATE *state;
+
+ state = (SEARCH_STATE *)xmalloc (sizeof (SEARCH_STATE));
+ window_get_state (window, state);
+ state->search_index = search_index;
+ state->direction = direction;
+ state->failing = failing;
+
+ add_pointer_to_array (state, isearch_states_index, isearch_states,
+ isearch_states_slots, 20, SEARCH_STATE *);
+}
+
+/* Pop the state of this search to WINDOW, SEARCH_INDEX, and DIRECTION. */
+static void
+pop_isearch (window, search_index, direction, failing)
+ WINDOW *window;
+ int *search_index, *direction, *failing;
+{
+ SEARCH_STATE *state;
+
+ if (isearch_states_index)
+ {
+ isearch_states_index--;
+ state = isearch_states[isearch_states_index];
+ window_set_state (window, state);
+ *search_index = state->search_index;
+ *direction = state->direction;
+ *failing = state->failing;
+
+ free (state);
+ isearch_states[isearch_states_index] = (SEARCH_STATE *)NULL;
+ }
+}
+
+/* Free the memory used by isearch_states. */
+static void
+free_isearch_states ()
+{
+ register int i;
+
+ for (i = 0; i < isearch_states_index; i++)
+ {
+ free (isearch_states[i]);
+ isearch_states[i] = (SEARCH_STATE *)NULL;
+ }
+ isearch_states_index = 0;
+}
+
+/* Display the current search in the echo area. */
+static void
+show_isearch_prompt (dir, string, failing_p)
+ int dir;
+ unsigned char *string;
+ int failing_p;
+{
+ register int i;
+ char *prefix, *prompt, *p_rep;
+ int prompt_len, p_rep_index, p_rep_size;
+
+ if (dir < 0)
+ prefix = "I-search backward: ";
+ else
+ prefix = "I-search: ";
+
+ p_rep_index = p_rep_size = 0;
+ p_rep = (char *)NULL;
+ for (i = 0; string[i]; i++)
+ {
+ char *rep;
+
+ switch (string[i])
+ {
+ case ' ': rep = " "; break;
+ case LFD: rep = "\\n"; break;
+ case TAB: rep = "\\t"; break;
+ default:
+ rep = pretty_keyname (string[i]);
+ }
+ if ((p_rep_index + strlen (rep) + 1) >= p_rep_size)
+ p_rep = (char *)xrealloc (p_rep, p_rep_size += 100);
+
+ strcpy (p_rep + p_rep_index, rep);
+ p_rep_index += strlen (rep);
+ }
+
+ prompt_len = strlen (prefix) + p_rep_index + 20;
+ prompt = (char *)xmalloc (prompt_len);
+ sprintf (prompt, "%s%s%s", failing_p ? "Failing " : "", prefix,
+ p_rep ? p_rep : "");
+
+ window_message_in_echo_area ("%s", prompt);
+ maybe_free (p_rep);
+ free (prompt);
+ display_cursor_at_point (active_window);
+}
+
+static void
+incremental_search (window, count, ignore)
+ WINDOW *window;
+ int count;
+ unsigned char ignore;
+{
+ unsigned char key;
+ int last_search_result, search_result, dir;
+ SEARCH_STATE mystate, orig_state;
+
+ if (count < 0)
+ dir = -1;
+ else
+ dir = 1;
+
+ last_search_result = search_result = 0;
+
+ window_get_state (window, &orig_state);
+
+ isearch_string_index = 0;
+ if (!isearch_string_size)
+ isearch_string = (char *)xmalloc (isearch_string_size = 50);
+
+ /* Show the search string in the echo area. */
+ isearch_string[isearch_string_index] = '\0';
+ show_isearch_prompt (dir, isearch_string, search_result);
+
+ isearch_is_active = 1;
+
+ while (isearch_is_active)
+ {
+ VFunction *func = (VFunction *)NULL;
+ int quoted = 0;
+
+ /* If a recent display was interrupted, then do the redisplay now if
+ it is convenient. */
+ if (!info_any_buffered_input_p () && display_was_interrupted_p)
+ {
+ display_update_one_window (window);
+ display_cursor_at_point (active_window);
+ }
+
+ /* Read a character and dispatch on it. */
+ key = info_get_input_char ();
+ window_get_state (window, &mystate);
+
+ if (key == DEL)
+ {
+ /* User wants to delete one level of search? */
+ if (!isearch_states_index)
+ {
+ terminal_ring_bell ();
+ continue;
+ }
+ else
+ {
+ pop_isearch
+ (window, &isearch_string_index, &dir, &search_result);
+ isearch_string[isearch_string_index] = '\0';
+ show_isearch_prompt (dir, isearch_string, search_result);
+ goto after_search;
+ }
+ }
+ else if (key == Control ('q'))
+ {
+ key = info_get_input_char ();
+ quoted = 1;
+ }
+
+ /* We are about to search again, or quit. Save the current search. */
+ push_isearch (window, isearch_string_index, dir, search_result);
+
+ if (quoted)
+ goto insert_and_search;
+
+ if (!Meta_p (key) || (ISO_Latin_p && key < 160))
+ {
+ func = window->keymap[key].function;
+
+ /* If this key invokes an incremental search, then this means that
+ we will either search again in the same direction, search
+ again in the reverse direction, or insert the last search
+ string that was accepted through incremental searching. */
+ if (func == isearch_forward || func == isearch_backward)
+ {
+ if ((func == isearch_forward && dir > 0) ||
+ (func == isearch_backward && dir < 0))
+ {
+ /* If the user has typed no characters, then insert the
+ last successful search into the current search string. */
+ if (isearch_string_index == 0)
+ {
+ /* Of course, there must be something to insert. */
+ if (last_isearch_accepted)
+ {
+ if (strlen (last_isearch_accepted) + 1 >=
+ isearch_string_size)
+ isearch_string = (char *)
+ xrealloc (isearch_string,
+ isearch_string_size += 10 +
+ strlen (last_isearch_accepted));
+ strcpy (isearch_string, last_isearch_accepted);
+ isearch_string_index = strlen (isearch_string);
+ goto search_now;
+ }
+ else
+ continue;
+ }
+ else
+ {
+ /* Search again in the same direction. This means start
+ from a new place if the last search was successful. */
+ if (search_result == 0)
+ window->point += dir;
+ }
+ }
+ else
+ {
+ /* Reverse the direction of the search. */
+ dir = -dir;
+ }
+ }
+ else if (isprint (key) || func == (VFunction *)NULL)
+ {
+ insert_and_search:
+
+ if (isearch_string_index + 2 >= isearch_string_size)
+ isearch_string = (char *)xrealloc
+ (isearch_string, isearch_string_size += 100);
+
+ isearch_string[isearch_string_index++] = key;
+ isearch_string[isearch_string_index] = '\0';
+ goto search_now;
+ }
+ else if (func == info_abort_key)
+ {
+ /* If C-g pressed, and the search is failing, pop the search
+ stack back to the last unfailed search. */
+ if (isearch_states_index && (search_result != 0))
+ {
+ terminal_ring_bell ();
+ while (isearch_states_index && (search_result != 0))
+ pop_isearch
+ (window, &isearch_string_index, &dir, &search_result);
+ isearch_string[isearch_string_index] = '\0';
+ show_isearch_prompt (dir, isearch_string, search_result);
+ continue;
+ }
+ else
+ goto exit_search;
+ }
+ else
+ goto exit_search;
+ }
+ else
+ {
+ exit_search:
+ /* The character is not printable, or it has a function which is
+ non-null. Exit the search, remembering the search string. If
+ the key is not the same as the isearch_terminate_search_key,
+ then push it into pending input. */
+ if (isearch_string_index && func != info_abort_key)
+ {
+ maybe_free (last_isearch_accepted);
+ last_isearch_accepted = strdup (isearch_string);
+ }
+
+ if (key != isearch_terminate_search_key)
+ info_set_pending_input (key);
+
+ if (func == info_abort_key)
+ {
+ if (isearch_states_index)
+ window_set_state (window, &orig_state);
+ }
+
+ if (!echo_area_is_active)
+ window_clear_echo_area ();
+
+ if (auto_footnotes_p)
+ info_get_or_remove_footnotes (active_window);
+
+ isearch_is_active = 0;
+ continue;
+ }
+
+ /* Search for the contents of isearch_string. */
+ search_now:
+ show_isearch_prompt (dir, isearch_string, search_result);
+
+ if (search_result == 0)
+ {
+ /* Check to see if the current search string is right here. If
+ we are looking at it, then don't bother calling the search
+ function. */
+ if (((dir < 0) &&
+ (strncasecmp (window->node->contents + window->point,
+ isearch_string, isearch_string_index) == 0)) ||
+ ((dir > 0) &&
+ ((window->point - isearch_string_index) >= 0) &&
+ (strncasecmp (window->node->contents +
+ (window->point - (isearch_string_index - 1)),
+ isearch_string, isearch_string_index) == 0)))
+ {
+ if (dir > 0)
+ window->point++;
+ }
+ else
+ search_result = info_search_internal (isearch_string, window, dir);
+ }
+
+ /* If this search failed, and we didn't already have a failed search,
+ then ring the terminal bell. */
+ if (search_result != 0 && last_search_result == 0)
+ terminal_ring_bell ();
+
+ after_search:
+ show_isearch_prompt (dir, isearch_string, search_result);
+
+ if (search_result == 0)
+ {
+ if ((mystate.node == window->node) &&
+ (mystate.pagetop != window->pagetop))
+ {
+ int newtop = window->pagetop;
+ window->pagetop = mystate.pagetop;
+ set_window_pagetop (window, newtop);
+ }
+ display_update_one_window (window);
+ display_cursor_at_point (window);
+ }
+
+ last_search_result = search_result;
+ }
+
+ /* Free the memory used to remember each search state. */
+ free_isearch_states ();
+
+ /* Perhaps GC some file buffers. */
+ info_gc_file_buffers ();
+
+ /* After searching, leave the window in the correct state. */
+ if (!echo_area_is_active)
+ window_clear_echo_area ();
+}
+
+/* GC some file buffers. A file buffer can be gc-ed if there we have
+ no nodes in INFO_WINDOWS that reference this file buffer's contents.
+ Garbage collecting a file buffer means to free the file buffers
+ contents. */
+static void
+info_gc_file_buffers ()
+{
+ register int fb_index, iw_index, i;
+ register FILE_BUFFER *fb;
+ register INFO_WINDOW *iw;
+
+ if (!info_loaded_files)
+ return;
+
+ for (fb_index = 0; fb = info_loaded_files[fb_index]; fb_index++)
+ {
+ int fb_referenced_p = 0;
+
+ /* If already gc-ed, do nothing. */
+ if (!fb->contents)
+ continue;
+
+ /* If this file had to be uncompressed, check to see if we should
+ gc it. This means that the user-variable "gc-compressed-files"
+ is non-zero. */
+ if ((fb->flags & N_IsCompressed) && !gc_compressed_files)
+ continue;
+
+ /* If this file's contents are not gc-able, move on. */
+ if (fb->flags & N_CannotGC)
+ continue;
+
+ /* Check each INFO_WINDOW to see if it has any nodes which reference
+ this file. */
+ for (iw_index = 0; iw = info_windows[iw_index]; iw_index++)
+ {
+ for (i = 0; iw->nodes && iw->nodes[i]; i++)
+ {
+ if ((strcmp (fb->fullpath, iw->nodes[i]->filename) == 0) ||
+ (strcmp (fb->filename, iw->nodes[i]->filename) == 0))
+ {
+ fb_referenced_p = 1;
+ break;
+ }
+ }
+ }
+
+ /* If this file buffer wasn't referenced, free its contents. */
+ if (!fb_referenced_p)
+ {
+ free (fb->contents);
+ fb->contents = (char *)NULL;
+ }
+ }
+}
+
+/* **************************************************************** */
+/* */
+/* Traversing and Selecting References */
+/* */
+/* **************************************************************** */
+
+/* Move to the next or previous cross reference in this node. */
+static void
+info_move_to_xref (window, count, key, dir)
+ WINDOW *window;
+ int count;
+ unsigned char key;
+ int dir;
+{
+ long firstmenu, firstxref;
+ long nextmenu, nextxref;
+ long placement = -1;
+ long start = 0;
+ NODE *node = window->node;
+
+ if (dir < 0)
+ start = node->nodelen;
+
+ /* This search is only allowed to fail if there is no menu or cross
+ reference in the current node. Otherwise, the first menu or xref
+ found is moved to. */
+
+ firstmenu = info_search_in_node
+ (INFO_MENU_ENTRY_LABEL, node, start, (WINDOW *)NULL, dir);
+
+ /* FIRSTMENU may point directly to the line defining the menu. Skip that
+ and go directly to the first item. */
+
+ if (firstmenu != -1)
+ {
+ char *text = node->contents + firstmenu;
+
+ if (strncmp (text, INFO_MENU_LABEL, strlen (INFO_MENU_LABEL)) == 0)
+ firstmenu = info_search_in_node
+ (INFO_MENU_ENTRY_LABEL, node, firstmenu + dir, (WINDOW *)NULL, dir);
+ }
+
+ firstxref =
+ info_search_in_node (INFO_XREF_LABEL, node, start, (WINDOW *)NULL, dir);
+
+#if defined (HANDLE_MAN_PAGES)
+ if ((firstxref == -1) && (node->flags & N_IsManPage))
+ {
+ firstxref = locate_manpage_xref (node, start, dir);
+ }
+#endif /* HANDLE_MAN_PAGES */
+
+ if (firstmenu == -1 && firstxref == -1)
+ {
+ info_error ("No cross references in this node.");
+ return;
+ }
+
+ /* There is at least one cross reference or menu entry in this node.
+ Try hard to find the next available one. */
+
+ nextmenu = info_search_in_node
+ (INFO_MENU_ENTRY_LABEL, node, window->point + dir, (WINDOW *)NULL, dir);
+
+ nextxref = info_search_in_node
+ (INFO_XREF_LABEL, node, window->point + dir, (WINDOW *)NULL, dir);
+
+#if defined (HANDLE_MAN_PAGES)
+ if ((nextxref == -1) && (node->flags & N_IsManPage) && (firstxref != -1))
+ nextxref = locate_manpage_xref (node, window->point + dir, dir);
+#endif /* HANDLE_MAN_PAGES */
+
+ /* Ignore "Menu:" as a menu item. */
+ if (nextmenu != -1)
+ {
+ char *text = node->contents + nextmenu;
+
+ if (strncmp (text, INFO_MENU_LABEL, strlen (INFO_MENU_LABEL)) == 0)
+ nextmenu = info_search_in_node
+ (INFO_MENU_ENTRY_LABEL, node, nextmenu + dir, (WINDOW *)NULL, dir);
+ }
+
+ /* If there is both a next menu entry, and a next xref entry, choose the
+ one which occurs first. Otherwise, select the one which actually
+ appears in this node following point. */
+ if (nextmenu != -1 && nextxref != -1)
+ {
+ if (((dir == 1) && (nextmenu < nextxref)) ||
+ ((dir == -1) && (nextmenu > nextxref)))
+ placement = nextmenu + 1;
+ else
+ placement = nextxref;
+ }
+ else if (nextmenu != -1)
+ placement = nextmenu + 1;
+ else if (nextxref != -1)
+ placement = nextxref;
+
+ /* If there was neither a menu or xref entry appearing in this node after
+ point, choose the first menu or xref entry appearing in this node. */
+ if (placement == -1)
+ {
+ if (firstmenu != -1 && firstxref != -1)
+ {
+ if (((dir == 1) && (firstmenu < firstxref)) ||
+ ((dir == -1) && (firstmenu > firstxref)))
+ placement = firstmenu + 1;
+ else
+ placement = firstxref;
+ }
+ else if (firstmenu != -1)
+ placement = firstmenu + 1;
+ else
+ placement = firstxref;
+ }
+ window->point = placement;
+ window_adjust_pagetop (window);
+ window->flags |= W_UpdateWindow;
+}
+
+DECLARE_INFO_COMMAND (info_move_to_prev_xref,
+ "Move to the previous cross reference")
+{
+ if (count < 0)
+ info_move_to_prev_xref (window, -count, key);
+ else
+ info_move_to_xref (window, count, key, -1);
+}
+
+DECLARE_INFO_COMMAND (info_move_to_next_xref,
+ "Move to the next cross reference")
+{
+ if (count < 0)
+ info_move_to_next_xref (window, -count, key);
+ else
+ info_move_to_xref (window, count, key, 1);
+}
+
+/* Select the menu item or reference that appears on this line. */
+DECLARE_INFO_COMMAND (info_select_reference_this_line,
+ "Select reference or menu item appearing on this line")
+{
+ char *line;
+ NODE *orig;
+
+ line = window->line_starts[window_line_of_point (window)];
+ orig = window->node;
+
+ /* If this line contains a menu item, select that one. */
+ if (strncmp ("* ", line, 2) == 0)
+ info_menu_or_ref_item (window, count, key, info_menu_of_node, 0);
+ else
+ info_menu_or_ref_item (window, count, key, info_xrefs_of_node, 0);
+}
+
+/* **************************************************************** */
+/* */
+/* Miscellaneous Info Commands */
+/* */
+/* **************************************************************** */
+
+/* What to do when C-g is pressed in a window. */
+DECLARE_INFO_COMMAND (info_abort_key, "Cancel current operation")
+{
+ /* If error printing doesn't oridinarily ring the bell, do it now,
+ since C-g always rings the bell. Otherwise, let the error printer
+ do it. */
+ if (!info_error_rings_bell_p)
+ terminal_ring_bell ();
+ info_error ("Quit");
+
+ info_initialize_numeric_arg ();
+ info_clear_pending_input ();
+ info_last_executed_command = (VFunction *)NULL;
+}
+
+/* Move the cursor to the desired line of the window. */
+DECLARE_INFO_COMMAND (info_move_to_window_line,
+ "Move to the cursor to a specific line of the window")
+{
+ int line;
+
+ /* With no numeric argument of any kind, default to the center line. */
+ if (!info_explicit_arg && count == 1)
+ line = (window->height / 2) + window->pagetop;
+ else
+ {
+ if (count < 0)
+ line = (window->height + count) + window->pagetop;
+ else
+ line = window->pagetop + count;
+ }
+
+ /* If the line doesn't appear in this window, make it do so. */
+ if ((line - window->pagetop) >= window->height)
+ line = window->pagetop + (window->height - 1);
+
+ /* If the line is too small, make it fit. */
+ if (line < window->pagetop)
+ line = window->pagetop;
+
+ /* If the selected line is past the bottom of the node, force it back. */
+ if (line >= window->line_count)
+ line = window->line_count - 1;
+
+ window->point = (window->line_starts[line] - window->node->contents);
+}
+
+/* Clear the screen and redraw its contents. Given a numeric argument,
+ move the line the cursor is on to the COUNT'th line of the window. */
+DECLARE_INFO_COMMAND (info_redraw_display, "Redraw the display")
+{
+ if ((!info_explicit_arg && count == 1) || echo_area_is_active)
+ {
+ terminal_clear_screen ();
+ display_clear_display (the_display);
+ window_mark_chain (windows, W_UpdateWindow);
+ display_update_display (windows);
+ }
+ else
+ {
+ int desired_line, point_line;
+ int new_pagetop;
+
+ point_line = window_line_of_point (window) - window->pagetop;
+
+ if (count < 0)
+ desired_line = window->height + count;
+ else
+ desired_line = count;
+
+ if (desired_line < 0)
+ desired_line = 0;
+
+ if (desired_line >= window->height)
+ desired_line = window->height - 1;
+
+ if (desired_line == point_line)
+ return;
+
+ new_pagetop = window->pagetop + (point_line - desired_line);
+
+ set_window_pagetop (window, new_pagetop);
+ }
+}
+/* This command does nothing. It is the fact that a key is bound to it
+ that has meaning. See the code at the top of info_session (). */
+DECLARE_INFO_COMMAND (info_quit, "Quit using Info")
+{}
+
+
+/* **************************************************************** */
+/* */
+/* Reading Keys and Dispatching on Them */
+/* */
+/* **************************************************************** */
+
+/* Declaration only. Special cased in info_dispatch_on_key (). */
+DECLARE_INFO_COMMAND (info_do_lowercase_version, "")
+{}
+
+static void
+dispatch_error (keyseq)
+ char *keyseq;
+{
+ char *rep;
+
+ rep = pretty_keyseq (keyseq);
+
+ if (!echo_area_is_active)
+ info_error ("Unknown command (%s).", rep);
+ else
+ {
+ char *temp;
+
+ temp = (char *)xmalloc (1 + strlen (rep) + strlen ("\"\" is invalid"));
+
+ sprintf (temp, "\"%s\" is invalid", rep);
+ terminal_ring_bell ();
+ inform_in_echo_area (temp);
+ free (temp);
+ }
+}
+
+/* Keeping track of key sequences. */
+static char *info_keyseq = (char *)NULL;
+static char keyseq_rep[100];
+static int info_keyseq_index = 0;
+static int info_keyseq_size = 0;
+static int info_keyseq_displayed_p = 0;
+
+/* Initialize the length of the current key sequence. */
+void
+initialize_keyseq ()
+{
+ info_keyseq_index = 0;
+ info_keyseq_displayed_p = 0;
+}
+
+/* Add CHARACTER to the current key sequence. */
+void
+add_char_to_keyseq (character)
+ char character;
+{
+ if (info_keyseq_index + 2 >= info_keyseq_size)
+ info_keyseq = (char *)xrealloc (info_keyseq, info_keyseq_size += 10);
+
+ info_keyseq[info_keyseq_index++] = character;
+ info_keyseq[info_keyseq_index] = '\0';
+}
+
+/* Return the pretty printable string which represents KEYSEQ. */
+char *
+pretty_keyseq (keyseq)
+ char *keyseq;
+{
+ register int i;
+
+ keyseq_rep[0] = '\0';
+
+ for (i = 0; keyseq[i]; i++)
+ {
+ sprintf (keyseq_rep + strlen (keyseq_rep), "%s%s",
+ strlen (keyseq_rep) ? " " : "",
+ pretty_keyname (keyseq[i]));
+ }
+
+ return (keyseq_rep);
+}
+
+/* Display the current value of info_keyseq. If argument EXPECTING is
+ non-zero, input is expected to be read after the key sequence is
+ displayed, so add an additional prompting character to the sequence. */
+void
+display_info_keyseq (expecting_future_input)
+ int expecting_future_input;
+{
+ char *rep;
+
+ rep = pretty_keyseq (info_keyseq);
+ if (expecting_future_input)
+ strcat (rep, "-");
+
+ if (echo_area_is_active)
+ inform_in_echo_area (rep);
+ else
+ {
+ window_message_in_echo_area (rep);
+ display_cursor_at_point (active_window);
+ }
+ info_keyseq_displayed_p = 1;
+}
+
+/* Called by interactive commands to read a keystroke. */
+unsigned char
+info_get_another_input_char ()
+{
+ int ready = 0;
+
+ /* If there isn't any input currently available, then wait a
+ moment looking for input. If we don't get it fast enough,
+ prompt a little bit with the current key sequence. */
+ if (!info_keyseq_displayed_p &&
+ !info_any_buffered_input_p () &&
+ !info_input_pending_p ())
+ {
+#if defined (FD_SET)
+ struct timeval timer;
+ fd_set readfds;
+
+ FD_ZERO (&readfds);
+ FD_SET (fileno (info_input_stream), &readfds);
+ timer.tv_sec = 1;
+ timer.tv_usec = 750;
+ ready = select (1, &readfds, (fd_set *)NULL, (fd_set *)NULL, &timer);
+#endif /* FD_SET */
+ }
+
+ if (!ready)
+ display_info_keyseq (1);
+
+ return (info_get_input_char ());
+}
+
+/* Do the command associated with KEY in MAP. If the associated command is
+ really a keymap, then read another key, and dispatch into that map. */
+void
+info_dispatch_on_key (key, map)
+ unsigned char key;
+ Keymap map;
+{
+ if (Meta_p (key) && (!ISO_Latin_p || map[key].function != ea_insert))
+ {
+ if (map[ESC].type == ISKMAP)
+ {
+ map = (Keymap)map[ESC].function;
+ add_char_to_keyseq (ESC);
+ key = UnMeta (key);
+ info_dispatch_on_key (key, map);
+ }
+ else
+ {
+ dispatch_error (info_keyseq);
+ }
+ return;
+ }
+
+ switch (map[key].type)
+ {
+ case ISFUNC:
+ {
+ VFunction *func;
+
+ func = map[key].function;
+ if (func != (VFunction *)NULL)
+ {
+ /* Special case info_do_lowercase_version (). */
+ if (func == info_do_lowercase_version)
+ {
+ info_dispatch_on_key (tolower (key), map);
+ return;
+ }
+
+ add_char_to_keyseq (key);
+
+ if (info_keyseq_displayed_p)
+ display_info_keyseq (0);
+
+ {
+ WINDOW *where;
+
+ where = active_window;
+ (*map[key].function)
+ (active_window, info_numeric_arg * info_numeric_arg_sign, key);
+
+ /* If we have input pending, then the last command was a prefix
+ command. Don't change the value of the last function vars.
+ Otherwise, remember the last command executed in the var
+ appropriate to the window in which it was executed. */
+ if (!info_input_pending_p ())
+ {
+ if (where == the_echo_area)
+ ea_last_executed_command = map[key].function;
+ else
+ info_last_executed_command = map[key].function;
+ }
+ }
+ }
+ else
+ {
+ add_char_to_keyseq (key);
+ dispatch_error (info_keyseq);
+ return;
+ }
+ }
+ break;
+
+ case ISKMAP:
+ add_char_to_keyseq (key);
+ if (map[key].function != (VFunction *)NULL)
+ {
+ unsigned char newkey;
+
+ newkey = info_get_another_input_char ();
+ info_dispatch_on_key (newkey, (Keymap)map[key].function);
+ }
+ else
+ {
+ dispatch_error (info_keyseq);
+ return;
+ }
+ break;
+ }
+}
+
+/* **************************************************************** */
+/* */
+/* Numeric Arguments */
+/* */
+/* **************************************************************** */
+
+/* Handle C-u style numeric args, as well as M--, and M-digits. */
+
+/* Non-zero means that an explicit argument has been passed to this
+ command, as in C-u C-v. */
+int info_explicit_arg = 0;
+
+/* The sign of the numeric argument. */
+int info_numeric_arg_sign = 1;
+
+/* The value of the argument itself. */
+int info_numeric_arg = 1;
+
+/* Add the current digit to the argument in progress. */
+DECLARE_INFO_COMMAND (info_add_digit_to_numeric_arg,
+ "Add this digit to the current numeric argument")
+{
+ info_numeric_arg_digit_loop (window, 0, key);
+}
+
+/* C-u, universal argument. Multiply the current argument by 4.
+ Read a key. If the key has nothing to do with arguments, then
+ dispatch on it. If the key is the abort character then abort. */
+DECLARE_INFO_COMMAND (info_universal_argument,
+ "Start (or multiply by 4) the current numeric argument")
+{
+ info_numeric_arg *= 4;
+ info_numeric_arg_digit_loop (window, 0, 0);
+}
+
+/* Create a default argument. */
+void
+info_initialize_numeric_arg ()
+{
+ info_numeric_arg = info_numeric_arg_sign = 1;
+ info_explicit_arg = 0;
+}
+
+DECLARE_INFO_COMMAND (info_numeric_arg_digit_loop,
+ "Internally used by \\[universal-argument]")
+{
+ unsigned char pure_key;
+ Keymap keymap = window->keymap;
+
+ while (1)
+ {
+ if (key)
+ pure_key = key;
+ else
+ {
+ if (display_was_interrupted_p && !info_any_buffered_input_p ())
+ display_update_display (windows);
+
+ if (active_window != the_echo_area)
+ display_cursor_at_point (active_window);
+
+ pure_key = key = info_get_another_input_char ();
+
+ if (Meta_p (key))
+ add_char_to_keyseq (ESC);
+
+ add_char_to_keyseq (UnMeta (key));
+ }
+
+ if (Meta_p (key))
+ key = UnMeta (key);
+
+ if (keymap[key].type == ISFUNC &&
+ keymap[key].function == info_universal_argument)
+ {
+ info_numeric_arg *= 4;
+ key = 0;
+ continue;
+ }
+
+ if (isdigit (key))
+ {
+ if (info_explicit_arg)
+ info_numeric_arg = (info_numeric_arg * 10) + (key - '0');
+ else
+ info_numeric_arg = (key - '0');
+ info_explicit_arg = 1;
+ }
+ else
+ {
+ if (key == '-' && !info_explicit_arg)
+ {
+ info_numeric_arg_sign = -1;
+ info_numeric_arg = 1;
+ }
+ else
+ {
+ info_keyseq_index--;
+ info_dispatch_on_key (pure_key, keymap);
+ return;
+ }
+ }
+ key = 0;
+ }
+}
+
+/* **************************************************************** */
+/* */
+/* Input Character Buffering */
+/* */
+/* **************************************************************** */
+
+/* Character waiting to be read next. */
+static int pending_input_character = 0;
+
+/* How to make there be no pending input. */
+static void
+info_clear_pending_input ()
+{
+ pending_input_character = 0;
+}
+
+/* How to set the pending input character. */
+static void
+info_set_pending_input (key)
+ unsigned char key;
+{
+ pending_input_character = key;
+}
+
+/* How to see if there is any pending input. */
+unsigned char
+info_input_pending_p ()
+{
+ return (pending_input_character);
+}
+
+/* Largest number of characters that we can read in advance. */
+#define MAX_INFO_INPUT_BUFFERING 512
+
+static int pop_index = 0, push_index = 0;
+static unsigned char info_input_buffer[MAX_INFO_INPUT_BUFFERING];
+
+/* Add KEY to the buffer of characters to be read. */
+static void
+info_push_typeahead (key)
+ unsigned char key;
+{
+ /* Flush all pending input in the case of C-g pressed. */
+ if (key == Control ('g'))
+ {
+ push_index = pop_index;
+ info_set_pending_input (Control ('g'));
+ }
+ else
+ {
+ info_input_buffer[push_index++] = key;
+ if (push_index >= sizeof (info_input_buffer))
+ push_index = 0;
+ }
+}
+
+/* Return the amount of space available in INFO_INPUT_BUFFER for new chars. */
+static int
+info_input_buffer_space_available ()
+{
+ if (pop_index > push_index)
+ return (pop_index - push_index);
+ else
+ return (sizeof (info_input_buffer) - (push_index - pop_index));
+}
+
+/* Get a key from the buffer of characters to be read.
+ Return the key in KEY.
+ Result is non-zero if there was a key, or 0 if there wasn't. */
+static int
+info_get_key_from_typeahead (key)
+ unsigned char *key;
+{
+ if (push_index == pop_index)
+ return (0);
+
+ *key = info_input_buffer[pop_index++];
+
+ if (pop_index >= sizeof (info_input_buffer))
+ pop_index = 0;
+
+ return (1);
+}
+
+int
+info_any_buffered_input_p ()
+{
+ info_gather_typeahead ();
+ return (push_index != pop_index);
+}
+
+/* Push KEY into the *front* of the input buffer. Returns non-zero if
+ successful, zero if there is no space left in the buffer. */
+static int
+info_replace_key_to_typeahead (key)
+ unsigned char key;
+{
+ if (info_input_buffer_space_available ())
+ {
+ pop_index--;
+ if (pop_index < 0)
+ pop_index = sizeof (info_input_buffer) - 1;
+ info_input_buffer[pop_index] = key;
+ return (1);
+ }
+ return (0);
+}
+
+/* If characters are available to be read, then read them and stuff them into
+ info_input_buffer. Otherwise, do nothing. */
+void
+info_gather_typeahead ()
+{
+ register int i = 0;
+ int tty, space_avail;
+ long chars_avail;
+ unsigned char input[MAX_INFO_INPUT_BUFFERING];
+
+ tty = fileno (info_input_stream);
+ chars_avail = 0;
+
+ space_avail = info_input_buffer_space_available ();
+
+ /* If we can just find out how many characters there are to read, do so. */
+#if defined (FIONREAD)
+ {
+ ioctl (tty, FIONREAD, &chars_avail);
+
+ if (chars_avail > space_avail)
+ chars_avail = space_avail;
+
+ if (chars_avail)
+ read (tty, &input[0], chars_avail);
+ }
+#else /* !FIONREAD */
+# if defined (O_NDELAY)
+ {
+ int flags;
+
+ flags = fcntl (tty, F_GETFL, 0);
+
+ fcntl (tty, F_SETFL, (flags | O_NDELAY));
+ chars_avail = read (tty, &input[0], space_avail);
+ fcntl (tty, F_SETFL, flags);
+
+ if (chars_avail == -1)
+ chars_avail = 0;
+ }
+# endif /* O_NDELAY */
+#endif /* !FIONREAD */
+
+ while (i < chars_avail)
+ {
+ info_push_typeahead (input[i]);
+ i++;
+ }
+}
+
+/* How to read a single character. */
+unsigned char
+info_get_input_char ()
+{
+ unsigned char keystroke;
+
+ info_gather_typeahead ();
+
+ if (pending_input_character)
+ {
+ keystroke = pending_input_character;
+ pending_input_character = 0;
+ }
+ else if (info_get_key_from_typeahead (&keystroke) == 0)
+ {
+ int rawkey;
+
+ rawkey = getc (info_input_stream);
+ keystroke = rawkey;
+
+ if (rawkey == EOF)
+ {
+ if (info_input_stream != stdin)
+ {
+ fclose (info_input_stream);
+ info_input_stream = stdin;
+ display_inhibited = 0;
+ display_update_display (windows);
+ display_cursor_at_point (active_window);
+ rawkey = getc (info_input_stream);
+ keystroke = rawkey;
+ }
+
+ if (rawkey == EOF)
+ {
+ terminal_unprep_terminal ();
+ close_dribble_file ();
+ exit (0);
+ }
+ }
+ }
+
+ if (info_dribble_file)
+ dribble (keystroke);
+
+ return (keystroke);
+}
diff --git a/contrib/texinfo/info/session.h b/contrib/texinfo/info/session.h
new file mode 100644
index 0000000..98b8ccf
--- /dev/null
+++ b/contrib/texinfo/info/session.h
@@ -0,0 +1,146 @@
+/* session.h -- Functions found in session.c. */
+
+/* This file is part of GNU Info, a program for reading online documentation
+ stored in Info format.
+
+ Copyright (C) 1993 Free Software Foundation, Inc.
+
+ 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Written by Brian Fox (bfox@ai.mit.edu). */
+
+#if !defined (_SESSION_H_)
+#define _SESSION_H_
+
+#include "general.h"
+#include "dribble.h"
+
+/* All commands that can be invoked from within info_session () receive
+ arguments in the same way. This simple define declares the header
+ of a function named NAME, with associated documentation DOC. The
+ documentation string is groveled out of the source files by the
+ utility program `makedoc', which is also responsible for making
+ the documentation/function-pointer maps. */
+#define DECLARE_INFO_COMMAND(name, doc) \
+void name (window, count, key) WINDOW *window; int count; unsigned char key;
+
+/* Variables found in session.h. */
+extern VFunction *info_last_executed_command;
+
+/* Variable controlling the garbage collection of files briefly visited
+ during searches. Such files are normally gc'ed, unless they were
+ compressed to begin with. If this variable is non-zero, it says
+ to gc even those file buffer contents which had to be uncompressed. */
+extern int gc_compressed_files;
+
+/* When non-zero, tiling takes place automatically when info_split_window
+ is called. */
+extern int auto_tiling_p;
+
+/* Variable controlling the behaviour of default scrolling when you are
+ already at the bottom of a node. */
+extern int info_scroll_behaviour;
+extern char *info_scroll_choices[];
+
+/* Values for info_scroll_behaviour. */
+#define IS_Continuous 0 /* Try to get first menu item, or failing that, the
+ "Next:" pointer, or failing that, the "Up:" and
+ "Next:" of the up. */
+#define IS_NextOnly 1 /* Try to get "Next:" menu item. */
+#define IS_PageOnly 2 /* Simply give up at the bottom of a node. */
+
+/* Utility functions found in session.c */
+extern void info_dispatch_on_key ();
+extern unsigned char info_get_input_char (), info_get_another_input_char ();
+extern unsigned char info_input_pending_p ();
+extern void remember_window_and_node (), set_remembered_pagetop_and_point ();
+extern void set_window_pagetop (), info_set_node_of_window ();
+extern char *pretty_keyseq ();
+extern void initialize_keyseq (), add_char_to_keyseq ();
+extern void info_gather_typeahead ();
+extern FILE_BUFFER *file_buffer_of_window ();
+extern long info_search_in_node (), info_target_search_node ();
+extern void info_select_reference ();
+extern int info_any_buffered_input_p ();
+extern void print_node ();
+extern void dump_node_to_file (), dump_nodes_to_file ();
+
+/* Do the physical deletion of WINDOW, and forget this window and
+ associated nodes. */
+extern void info_delete_window_internal ();
+
+/* Tell Info that input is coming from the file FILENAME. */
+extern void info_set_input_from_file ();
+
+#define return_if_control_g(val) \
+ do { \
+ info_gather_typeahead (); \
+ if (info_input_pending_p () == Control ('g')) \
+ return (val); \
+ } while (0)
+
+/* The names of the functions that run an info session. */
+
+/* Starting an info session. */
+extern void begin_multiple_window_info_session (), begin_info_session ();
+extern void begin_info_session_with_error (), info_session ();
+extern void info_read_and_dispatch ();
+
+/* Moving the point within a node. */
+extern void info_next_line (), info_prev_line ();
+extern void info_end_of_line (), info_beginning_of_line ();
+extern void info_forward_char (), info_backward_char ();
+extern void info_forward_word (), info_backward_word ();
+extern void info_beginning_of_node (), info_end_of_node ();
+extern void info_move_to_prev_xref (), info_move_to_next_xref ();
+
+/* Scrolling text within a window. */
+extern void info_scroll_forward (), info_scroll_backward ();
+extern void info_redraw_display (), info_toggle_wrap ();
+extern void info_move_to_window_line ();
+
+/* Manipulating multiple windows. */
+extern void info_split_window (), info_delete_window ();
+extern void info_keep_one_window (), info_grow_window ();
+extern void info_scroll_other_window (), info_tile_windows ();
+extern void info_next_window (), info_prev_window ();
+
+/* Selecting nodes. */
+extern void info_next_node (), info_prev_node (), info_up_node ();
+extern void info_last_node (), info_first_node (), info_history_node ();
+extern void info_goto_node (), info_top_node (), info_dir_node ();
+extern void info_global_next_node (), info_global_prev_node ();
+extern void info_kill_node (), info_view_file ();
+
+/* Selecting cross references. */
+extern void info_menu_digit (), info_menu_item (), info_xref_item ();
+extern void info_find_menu (), info_select_reference_this_line ();
+
+/* Hacking numeric arguments. */
+extern int info_explicit_arg, info_numeric_arg, info_numeric_arg_sign;
+
+extern void info_add_digit_to_numeric_arg (), info_universal_argument ();
+extern void info_initialize_numeric_arg (), info_numeric_arg_digit_loop ();
+
+/* Searching commands. */
+extern void info_search (), isearch_forward (), isearch_backward ();
+
+/* Dumping and printing nodes. */
+extern void info_print_node ();
+
+/* Miscellaneous commands. */
+extern void info_abort_key (), info_quit (), info_do_lowercase_version ();
+
+#endif /* _SESSION_H_ */
diff --git a/contrib/texinfo/info/signals.c b/contrib/texinfo/info/signals.c
new file mode 100644
index 0000000..a60777f
--- /dev/null
+++ b/contrib/texinfo/info/signals.c
@@ -0,0 +1,173 @@
+/* signals.c -- Install and maintain Info signal handlers. */
+
+/* This file is part of GNU Info, a program for reading online documentation
+ stored in Info format.
+
+ Copyright (C) 1993, 1994, 1995 Free Software Foundation, Inc.
+
+ 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Written by Brian Fox (bfox@ai.mit.edu). */
+
+#include "info.h"
+#include "signals.h"
+
+/* **************************************************************** */
+/* */
+/* Pretending That We Have POSIX Signals */
+/* */
+/* **************************************************************** */
+
+#if !defined (HAVE_SIGPROCMASK) && defined (HAVE_SIGSETMASK)
+/* Perform OPERATION on NEWSET, perhaps leaving information in OLDSET. */
+static void
+sigprocmask (operation, newset, oldset)
+ int operation, *newset, *oldset;
+{
+ switch (operation)
+ {
+ case SIG_UNBLOCK:
+ sigsetmask (sigblock (0) & ~(*newset));
+ break;
+
+ case SIG_BLOCK:
+ *oldset = sigblock (*newset);
+ break;
+
+ case SIG_SETMASK:
+ sigsetmask (*newset);
+ break;
+
+ default:
+ abort ();
+ }
+}
+#endif /* !HAVE_SIGPROCMASK && HAVE_SIGSETMASK */
+
+/* **************************************************************** */
+/* */
+/* Signal Handling for Info */
+/* */
+/* **************************************************************** */
+
+typedef void SigHandlerType;
+typedef SigHandlerType SigHandler ();
+
+static SigHandlerType info_signal_handler ();
+static SigHandler *old_TSTP, *old_TTOU, *old_TTIN;
+static SigHandler *old_WINCH, *old_INT;
+
+void
+initialize_info_signal_handler ()
+{
+#if defined (SIGTSTP)
+ old_TSTP = (SigHandler *) signal (SIGTSTP, info_signal_handler);
+ old_TTOU = (SigHandler *) signal (SIGTTOU, info_signal_handler);
+ old_TTIN = (SigHandler *) signal (SIGTTIN, info_signal_handler);
+#endif /* SIGTSTP */
+
+#if defined (SIGWINCH)
+ old_WINCH = (SigHandler *) signal (SIGWINCH, info_signal_handler);
+#endif
+
+#if defined (SIGINT)
+ old_INT = (SigHandler *) signal (SIGINT, info_signal_handler);
+#endif
+}
+
+static void
+redisplay_after_signal ()
+{
+ terminal_clear_screen ();
+ display_clear_display (the_display);
+ window_mark_chain (windows, W_UpdateWindow);
+ display_update_display (windows);
+ display_cursor_at_point (active_window);
+ fflush (stdout);
+}
+
+static SigHandlerType
+info_signal_handler (sig)
+ int sig;
+{
+ SigHandler **old_signal_handler;
+
+ switch (sig)
+ {
+#if defined (SIGTSTP)
+ case SIGTSTP:
+ case SIGTTOU:
+ case SIGTTIN:
+#endif
+#if defined (SIGINT)
+ case SIGINT:
+#endif
+ {
+#if defined (SIGTSTP)
+ if (sig == SIGTSTP)
+ old_signal_handler = &old_TSTP;
+ if (sig == SIGTTOU)
+ old_signal_handler = &old_TTOU;
+ if (sig == SIGTTIN)
+ old_signal_handler = &old_TTIN;
+#endif /* SIGTSTP */
+ if (sig == SIGINT)
+ old_signal_handler = &old_INT;
+
+ /* For stop signals, restore the terminal IO, leave the cursor
+ at the bottom of the window, and stop us. */
+ terminal_goto_xy (0, screenheight - 1);
+ terminal_clear_to_eol ();
+ fflush (stdout);
+ terminal_unprep_terminal ();
+ signal (sig, *old_signal_handler);
+ UNBLOCK_SIGNAL (sig);
+ kill (getpid (), sig);
+
+ /* The program is returning now. Restore our signal handler,
+ turn on terminal handling, redraw the screen, and place the
+ cursor where it belongs. */
+ terminal_prep_terminal ();
+ *old_signal_handler = (SigHandler *) signal (sig, info_signal_handler);
+ redisplay_after_signal ();
+ fflush (stdout);
+ }
+ break;
+
+#if defined (SIGWINCH)
+ case SIGWINCH:
+ {
+ /* Turn off terminal IO, tell our parent that the window has changed,
+ then reinitialize the terminal and rebuild our windows. */
+ old_signal_handler = &old_WINCH;
+ terminal_goto_xy (0, 0);
+ fflush (stdout);
+ terminal_unprep_terminal ();
+ signal (sig, *old_signal_handler);
+ UNBLOCK_SIGNAL (sig);
+ kill (getpid (), sig);
+
+ /* After our old signal handler returns... */
+ terminal_get_screen_size ();
+ terminal_prep_terminal ();
+ display_initialize_display (screenwidth, screenheight);
+ window_new_screen_size (screenwidth, screenheight, (VFunction *)NULL);
+ *old_signal_handler = (SigHandler *) signal (sig, info_signal_handler);
+ redisplay_after_signal ();
+ }
+ break;
+#endif /* SIGWINCH */
+ }
+}
diff --git a/contrib/texinfo/info/signals.h b/contrib/texinfo/info/signals.h
new file mode 100644
index 0000000..ab87a3b
--- /dev/null
+++ b/contrib/texinfo/info/signals.h
@@ -0,0 +1,89 @@
+/* signals.h -- Header to include system dependent signal definitions. */
+
+/* This file is part of GNU Info, a program for reading online documentation
+ stored in Info format.
+
+ Copyright (C) 1993, 1994, 1995 Free Software Foundation, Inc.
+
+ 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Written by Brian Fox (bfox@ai.mit.edu). */
+
+#if !defined (_SIGNALS_H_)
+#define _SIGNALS_H_
+
+#include <signal.h>
+
+#if !defined (HAVE_SIGPROCMASK) && !defined (sigmask)
+# define sigmask(x) (1 << ((x)-1))
+#endif /* !HAVE_SIGPROCMASK && !sigmask */
+
+#if !defined (HAVE_SIGPROCMASK)
+# if !defined (SIG_BLOCK)
+# define SIG_UNBLOCK 1
+# define SIG_BLOCK 2
+# define SIG_SETMASK 3
+# endif /* SIG_BLOCK */
+
+/* Type of a signal set. */
+# define sigset_t int
+
+/* Make SET have no signals in it. */
+# define sigemptyset(set) (*(set) = (sigset_t)0x0)
+
+/* Make SET have the full range of signal specifications possible. */
+# define sigfillset(set) (*(set) = (sigset_t)0xffffffffff)
+
+/* Add SIG to the contents of SET. */
+# define sigaddset(set, sig) *(set) |= sigmask (sig)
+
+/* Delete SIG from the contents of SET. */
+# define sigdelset(set, sig) *(set) &= ~(sigmask (sig))
+
+/* Tell if SET contains SIG. */
+# define sigismember(set, sig) (*(set) & (sigmask (sig)))
+
+/* Suspend the process until the reception of one of the signals
+ not present in SET. */
+# define sigsuspend(set) sigpause (*(set))
+#endif /* !HAVE_SIGPROCMASK */
+
+#if defined (HAVE_SIGPROCMASK) || defined (HAVE_SIGSETMASK)
+/* These definitions are used both in POSIX and non-POSIX implementations. */
+
+#define BLOCK_SIGNAL(sig) \
+ do { \
+ sigset_t nvar, ovar; \
+ sigemptyset (&nvar); \
+ sigemptyset (&ovar); \
+ sigaddset (&nvar, sig); \
+ sigprocmask (SIG_BLOCK, &nvar, &ovar); \
+ } while (0)
+
+#define UNBLOCK_SIGNAL(sig) \
+ do { \
+ sigset_t nvar, ovar; \
+ sigemptyset (&ovar); \
+ sigemptyset (&nvar); \
+ sigaddset (&nvar, sig); \
+ sigprocmask (SIG_UNBLOCK, &nvar, &ovar); \
+ } while (0)
+
+#else /* !HAVE_SIGPROCMASK && !HAVE_SIGSETMASK */
+# define BLOCK_SIGNAL(sig)
+# define UNBLOCK_SIGNAL(sig)
+#endif /* !HAVE_SIGPROCMASK && !HAVE_SIGSETMASK */
+
+#endif /* !_SIGNALS_H_ */
diff --git a/contrib/texinfo/info/termdep.h b/contrib/texinfo/info/termdep.h
new file mode 100644
index 0000000..4f8ce90
--- /dev/null
+++ b/contrib/texinfo/info/termdep.h
@@ -0,0 +1,76 @@
+/* termdep.h -- System things that terminal.c depends on.
+ $Id: termdep.h,v 1.3 1996/10/02 22:23:52 karl Exp $
+
+ This file is part of GNU Info, a program for reading online documentation
+ stored in Info format.
+
+ Copyright (C) 1993, 96 Free Software Foundation, Inc.
+
+ 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Written by Brian Fox (bfox@ai.mit.edu). */
+
+#if !defined (_TERMDEP_H_)
+# define _TERMDEP_H_
+
+#if defined (HAVE_SYS_FCNTL_H)
+# include <sys/fcntl.h>
+#else
+# include <fcntl.h>
+#endif /* !HAVE_SYS_FCNTL_H */
+
+#if defined (HAVE_SYS_FILE_H)
+# include <sys/file.h>
+#endif /* HAVE_SYS_FILE_H */
+
+#if defined (HAVE_STRINGS_H)
+# include <strings.h>
+#else
+# if defined (HAVE_STRING_H)
+# include <string.h>
+# endif
+#endif
+
+#if defined (HAVE_TERMIOS_H)
+# include <termios.h>
+#else
+# if defined (HAVE_TERMIO_H)
+# include <termio.h>
+# if defined (HAVE_SYS_PTEM_H)
+# if defined (M_UNIX) || !defined (M_XENIX)
+# include <sys/stream.h>
+# include <sys/ptem.h>
+# undef TIOCGETC
+# else /* M_XENIX */
+# define tchars tc
+# endif /* M_XENIX */
+# endif /* HAVE_SYS_PTEM_H */
+# else /* !HAVE_TERMIO_H */
+# include <sgtty.h>
+# endif /* !HAVE_TERMIO_H */
+#endif /* !HAVE_TERMIOS_H */
+
+#if defined (HAVE_SYS_TTOLD_H)
+# include <sys/ttold.h>
+#endif /* HAVE_SYS_TTOLD_H */
+
+#if !defined (HAVE_STRCHR)
+# undef strchr
+# undef strrchr
+# define strchr index
+# define strrchr rindex
+#endif /* !HAVE_STRCHR */
+
+#endif /* _TERMDEP_H_ */
diff --git a/contrib/texinfo/info/terminal.c b/contrib/texinfo/info/terminal.c
new file mode 100644
index 0000000..9c10176
--- /dev/null
+++ b/contrib/texinfo/info/terminal.c
@@ -0,0 +1,769 @@
+/* terminal.c -- How to handle the physical terminal for Info. */
+
+/* This file is part of GNU Info, a program for reading online documentation
+ stored in Info format.
+
+ This file has appeared in prior works by the Free Software Foundation;
+ thus it carries copyright dates from 1988 through 1993.
+
+ Copyright (C) 1988, 89, 90, 91, 92, 93, 96 Free Software Foundation, Inc.
+
+ 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Written by Brian Fox (bfox@ai.mit.edu). */
+
+#include <stdio.h>
+#include <sys/types.h>
+#include "terminal.h"
+#include "termdep.h"
+
+extern void *xmalloc (), *xrealloc ();
+
+/* The Unix termcap interface code. */
+
+extern int tgetnum (), tgetflag (), tgetent ();
+extern char *tgetstr (), *tgoto ();
+extern char *getenv ();
+extern void tputs ();
+
+/* Function "hooks". If you make one of these point to a function, that
+ function is called when appropriate instead of its namesake. Your
+ function is called with exactly the same arguments that were passed
+ to the namesake function. */
+VFunction *terminal_begin_inverse_hook = (VFunction *)NULL;
+VFunction *terminal_end_inverse_hook = (VFunction *)NULL;
+VFunction *terminal_prep_terminal_hook = (VFunction *)NULL;
+VFunction *terminal_unprep_terminal_hook = (VFunction *)NULL;
+VFunction *terminal_up_line_hook = (VFunction *)NULL;
+VFunction *terminal_down_line_hook = (VFunction *)NULL;
+VFunction *terminal_clear_screen_hook = (VFunction *)NULL;
+VFunction *terminal_clear_to_eol_hook = (VFunction *)NULL;
+VFunction *terminal_get_screen_size_hook = (VFunction *)NULL;
+VFunction *terminal_goto_xy_hook = (VFunction *)NULL;
+VFunction *terminal_initialize_terminal_hook = (VFunction *)NULL;
+VFunction *terminal_new_terminal_hook = (VFunction *)NULL;
+VFunction *terminal_put_text_hook = (VFunction *)NULL;
+VFunction *terminal_ring_bell_hook = (VFunction *)NULL;
+VFunction *terminal_write_chars_hook = (VFunction *)NULL;
+VFunction *terminal_scroll_terminal_hook = (VFunction *)NULL;
+
+/* **************************************************************** */
+/* */
+/* Terminal and Termcap */
+/* */
+/* **************************************************************** */
+
+/* On Solaris2, sys/types.h #includes sys/reg.h, which #defines PC.
+ Unfortunately, PC is a global variable used by the termcap library. */
+#undef PC
+
+/* TERMCAP requires these variables, whether we access them or not. */
+char PC;
+char *BC, *UP;
+short ospeed;
+
+/* A buffer which holds onto the current terminal description, and a pointer
+ used to float within it. */
+static char *term_buffer = (char *)NULL;
+static char *term_string_buffer = (char *)NULL;
+
+/* Some strings to control terminal actions. These are output by tputs (). */
+static char *term_goto, *term_clreol, *term_cr, *term_clrpag;
+static char *term_begin_use, *term_end_use;
+static char *term_AL, *term_DL, *term_al, *term_dl;
+
+/* How to go up a line. */
+static char *term_up;
+
+/* How to go down a line. */
+static char *term_dn;
+
+/* An audible bell, if the terminal can be made to make noise. */
+static char *audible_bell;
+
+/* A visible bell, if the terminal can be made to flash the screen. */
+static char *visible_bell;
+
+/* The string to write to turn on the meta key, if this term has one. */
+static char *term_mm;
+
+/* The string to write to turn off the meta key, if this term has one. */
+static char *term_mo;
+
+/* The string to turn on inverse mode, if this term has one. */
+static char *term_invbeg;
+
+/* The string to turn off inverse mode, if this term has one. */
+static char *term_invend;
+
+static void
+output_character_function (c)
+ int c;
+{
+ putc (c, stdout);
+}
+
+/* Macro to send STRING to the terminal. */
+#define send_to_terminal(string) \
+ do { \
+ if (string) \
+ tputs (string, 1, output_character_function); \
+ } while (0)
+
+/* Tell the terminal that we will be doing cursor addressable motion. */
+static void
+terminal_begin_using_terminal ()
+{
+ send_to_terminal (term_begin_use);
+}
+
+/* Tell the terminal that we will not be doing any more cursor addressable
+ motion. */
+static void
+terminal_end_using_terminal ()
+{
+ send_to_terminal (term_end_use);
+}
+
+/* **************************************************************** */
+/* */
+/* Necessary Terminal Functions */
+/* */
+/* **************************************************************** */
+
+/* The functions and variables on this page implement the user visible
+ portion of the terminal interface. */
+
+/* The width and height of the terminal. */
+int screenwidth, screenheight;
+
+/* Non-zero means this terminal can't really do anything. */
+int terminal_is_dumb_p = 0;
+
+/* Non-zero means that this terminal has a meta key. */
+int terminal_has_meta_p = 0;
+
+/* Non-zero means that this terminal can produce a visible bell. */
+int terminal_has_visible_bell_p = 0;
+
+/* Non-zero means to use that visible bell if at all possible. */
+int terminal_use_visible_bell_p = 0;
+
+/* Non-zero means that the terminal can do scrolling. */
+int terminal_can_scroll = 0;
+
+/* The key sequences output by the arrow keys, if this terminal has any. */
+char *term_ku = (char *)NULL;
+char *term_kd = (char *)NULL;
+char *term_kr = (char *)NULL;
+char *term_kl = (char *)NULL;
+
+/* Move the cursor to the terminal location of X and Y. */
+void
+terminal_goto_xy (x, y)
+ int x, y;
+{
+ if (terminal_goto_xy_hook)
+ (*terminal_goto_xy_hook) (x, y);
+ else
+ {
+ if (term_goto)
+ tputs (tgoto (term_goto, x, y), 1, output_character_function);
+ }
+}
+
+/* Print STRING to the terminal at the current position. */
+void
+terminal_put_text (string)
+ char *string;
+{
+ if (terminal_put_text_hook)
+ (*terminal_put_text_hook) (string);
+ else
+ {
+ printf ("%s", string);
+ }
+}
+
+/* Print NCHARS from STRING to the terminal at the current position. */
+void
+terminal_write_chars (string, nchars)
+ char *string;
+ int nchars;
+{
+ if (terminal_write_chars_hook)
+ (*terminal_write_chars_hook) (string, nchars);
+ else
+ {
+ if (nchars)
+ fwrite (string, 1, nchars, stdout);
+ }
+}
+
+/* Clear from the current position of the cursor to the end of the line. */
+void
+terminal_clear_to_eol ()
+{
+ if (terminal_clear_to_eol_hook)
+ (*terminal_clear_to_eol_hook) ();
+ else
+ {
+ send_to_terminal (term_clreol);
+ }
+}
+
+/* Clear the entire terminal screen. */
+void
+terminal_clear_screen ()
+{
+ if (terminal_clear_screen_hook)
+ (*terminal_clear_screen_hook) ();
+ else
+ {
+ send_to_terminal (term_clrpag);
+ }
+}
+
+/* Move the cursor up one line. */
+void
+terminal_up_line ()
+{
+ if (terminal_up_line_hook)
+ (*terminal_up_line_hook) ();
+ else
+ {
+ send_to_terminal (term_up);
+ }
+}
+
+/* Move the cursor down one line. */
+void
+terminal_down_line ()
+{
+ if (terminal_down_line_hook)
+ (*terminal_down_line_hook) ();
+ else
+ {
+ send_to_terminal (term_dn);
+ }
+}
+
+/* Turn on reverse video if possible. */
+void
+terminal_begin_inverse ()
+{
+ if (terminal_begin_inverse_hook)
+ (*terminal_begin_inverse_hook) ();
+ else
+ {
+ send_to_terminal (term_invbeg);
+ }
+}
+
+/* Turn off reverse video if possible. */
+void
+terminal_end_inverse ()
+{
+ if (terminal_end_inverse_hook)
+ (*terminal_end_inverse_hook) ();
+ else
+ {
+ send_to_terminal (term_invend);
+ }
+}
+
+/* Ring the terminal bell. The bell is run visibly if it both has one and
+ terminal_use_visible_bell_p is non-zero. */
+void
+terminal_ring_bell ()
+{
+ if (terminal_ring_bell_hook)
+ (*terminal_ring_bell_hook) ();
+ else
+ {
+ if (terminal_has_visible_bell_p && terminal_use_visible_bell_p)
+ send_to_terminal (visible_bell);
+ else
+ send_to_terminal (audible_bell);
+ }
+}
+
+/* At the line START, delete COUNT lines from the terminal display. */
+static void
+terminal_delete_lines (start, count)
+ int start, count;
+{
+ int lines;
+
+ /* Normalize arguments. */
+ if (start < 0)
+ start = 0;
+
+ lines = screenheight - start;
+ terminal_goto_xy (0, start);
+ if (term_DL)
+ tputs (tgoto (term_DL, 0, count), lines, output_character_function);
+ else
+ {
+ while (count--)
+ tputs (term_dl, lines, output_character_function);
+ }
+
+ fflush (stdout);
+}
+
+/* At the line START, insert COUNT lines in the terminal display. */
+static void
+terminal_insert_lines (start, count)
+ int start, count;
+{
+ int lines;
+
+ /* Normalize arguments. */
+ if (start < 0)
+ start = 0;
+
+ lines = screenheight - start;
+ terminal_goto_xy (0, start);
+
+ if (term_AL)
+ tputs (tgoto (term_AL, 0, count), lines, output_character_function);
+ else
+ {
+ while (count--)
+ tputs (term_al, lines, output_character_function);
+ }
+
+ fflush (stdout);
+}
+
+/* Scroll an area of the terminal, starting with the region from START
+ to END, AMOUNT lines. If AMOUNT is negative, the lines are scrolled
+ towards the top of the screen, else they are scrolled towards the
+ bottom of the screen. */
+void
+terminal_scroll_terminal (start, end, amount)
+ int start, end, amount;
+{
+ if (!terminal_can_scroll)
+ return;
+
+ /* Any scrolling at all? */
+ if (amount == 0)
+ return;
+
+ if (terminal_scroll_terminal_hook)
+ (*terminal_scroll_terminal_hook) (start, end, amount);
+ else
+ {
+ /* If we are scrolling down, delete AMOUNT lines at END. Then insert
+ AMOUNT lines at START. */
+ if (amount > 0)
+ {
+ terminal_delete_lines (end, amount);
+ terminal_insert_lines (start, amount);
+ }
+
+ /* If we are scrolling up, delete AMOUNT lines before START. This
+ actually does the upwards scroll. Then, insert AMOUNT lines
+ after the already scrolled region (i.e., END - AMOUNT). */
+ if (amount < 0)
+ {
+ int abs_amount = -amount;
+ terminal_delete_lines (start - abs_amount, abs_amount);
+ terminal_insert_lines (end - abs_amount, abs_amount);
+ }
+ }
+}
+
+/* Re-initialize the terminal considering that the TERM/TERMCAP variable
+ has changed. */
+void
+terminal_new_terminal (terminal_name)
+ char *terminal_name;
+{
+ if (terminal_new_terminal_hook)
+ (*terminal_new_terminal_hook) (terminal_name);
+ else
+ {
+ terminal_initialize_terminal (terminal_name);
+ }
+}
+
+/* Set the global variables SCREENWIDTH and SCREENHEIGHT. */
+void
+terminal_get_screen_size ()
+{
+ if (terminal_get_screen_size_hook)
+ (*terminal_get_screen_size_hook) ();
+ else
+ {
+ screenwidth = screenheight = 0;
+
+#if defined (TIOCGWINSZ)
+ {
+ struct winsize window_size;
+
+ if (ioctl (fileno (stdout), TIOCGWINSZ, &window_size) == 0)
+ {
+ screenwidth = (int) window_size.ws_col;
+ screenheight = (int) window_size.ws_row;
+ }
+ }
+#endif /* TIOCGWINSZ */
+
+ /* Environment variable COLUMNS overrides setting of "co". */
+ if (screenwidth <= 0)
+ {
+ char *sw = getenv ("COLUMNS");
+
+ if (sw)
+ screenwidth = atoi (sw);
+
+ if (screenwidth <= 0)
+ screenwidth = tgetnum ("co");
+ }
+
+ /* Environment variable LINES overrides setting of "li". */
+ if (screenheight <= 0)
+ {
+ char *sh = getenv ("LINES");
+
+ if (sh)
+ screenheight = atoi (sh);
+
+ if (screenheight <= 0)
+ screenheight = tgetnum ("li");
+ }
+
+ /* If all else fails, default to 80x24 terminal. */
+ if (screenwidth <= 0)
+ screenwidth = 80;
+
+ if (screenheight <= 0)
+ screenheight = 24;
+ }
+}
+
+/* Initialize the terminal which is known as TERMINAL_NAME. If this terminal
+ doesn't have cursor addressability, TERMINAL_IS_DUMB_P becomes non-zero.
+ The variables SCREENHEIGHT and SCREENWIDTH are set to the dimensions that
+ this terminal actually has. The variable TERMINAL_HAS_META_P becomes non-
+ zero if this terminal supports a Meta key. Finally, the terminal screen is
+ cleared. */
+void
+terminal_initialize_terminal (terminal_name)
+ char *terminal_name;
+{
+ char *term, *buffer;
+
+ terminal_is_dumb_p = 0;
+
+ if (terminal_initialize_terminal_hook)
+ {
+ (*terminal_initialize_terminal_hook) (terminal_name);
+ return;
+ }
+
+ term = terminal_name ? terminal_name : getenv ("TERM");
+
+ if (!term_string_buffer)
+ term_string_buffer = (char *)xmalloc (2048);
+
+ if (!term_buffer)
+ term_buffer = (char *)xmalloc (2048);
+
+ buffer = term_string_buffer;
+
+ term_clrpag = term_cr = term_clreol = (char *)NULL;
+
+ if (!term)
+ term = "dumb";
+
+ if (tgetent (term_buffer, term) <= 0)
+ {
+ terminal_is_dumb_p = 1;
+ screenwidth = 80;
+ screenheight = 24;
+ term_cr = "\r";
+ term_up = term_dn = audible_bell = visible_bell = (char *)NULL;
+ term_ku = term_kd = term_kl = term_kr = (char *)NULL;
+ return;
+ }
+
+ BC = tgetstr ("pc", &buffer);
+ PC = BC ? *BC : 0;
+
+#if defined (TIOCGETP)
+ {
+ struct sgttyb sg;
+
+ if (ioctl (fileno (stdout), TIOCGETP, &sg) != -1)
+ ospeed = sg.sg_ospeed;
+ else
+ ospeed = B9600;
+ }
+#else
+ ospeed = B9600;
+#endif /* !TIOCGETP */
+
+ term_cr = tgetstr ("cr", &buffer);
+ term_clreol = tgetstr ("ce", &buffer);
+ term_clrpag = tgetstr ("cl", &buffer);
+ term_goto = tgetstr ("cm", &buffer);
+
+ /* Find out about this terminals scrolling capability. */
+ term_AL = tgetstr ("AL", &buffer);
+ term_DL = tgetstr ("DL", &buffer);
+ term_al = tgetstr ("al", &buffer);
+ term_dl = tgetstr ("dl", &buffer);
+
+ terminal_can_scroll = ((term_AL || term_al) && (term_DL || term_dl));
+
+ term_invbeg = tgetstr ("mr", &buffer);
+ if (term_invbeg)
+ term_invend = tgetstr ("me", &buffer);
+ else
+ term_invend = (char *)NULL;
+
+ if (!term_cr)
+ term_cr = "\r";
+
+ terminal_get_screen_size ();
+
+ term_up = tgetstr ("up", &buffer);
+ term_dn = tgetstr ("dn", &buffer);
+ visible_bell = tgetstr ("vb", &buffer);
+ terminal_has_visible_bell_p = (visible_bell != (char *)NULL);
+ audible_bell = tgetstr ("bl", &buffer);
+ if (!audible_bell)
+ audible_bell = "\007";
+ term_begin_use = tgetstr ("ti", &buffer);
+ term_end_use = tgetstr ("te", &buffer);
+
+ /* Check to see if this terminal has a meta key. */
+ terminal_has_meta_p = (tgetflag ("km") || tgetflag ("MT"));
+ if (terminal_has_meta_p)
+ {
+ term_mm = tgetstr ("mm", &buffer);
+ term_mo = tgetstr ("mo", &buffer);
+ }
+ else
+ {
+ term_mm = (char *)NULL;
+ term_mo = (char *)NULL;
+ }
+
+ /* Attempt to find the arrow keys. */
+ term_ku = tgetstr ("ku", &buffer);
+ term_kd = tgetstr ("kd", &buffer);
+ term_kr = tgetstr ("kr", &buffer);
+ term_kl = tgetstr ("kl", &buffer);
+
+ /* If this terminal is not cursor addressable, then it is really dumb. */
+ if (!term_goto)
+ terminal_is_dumb_p = 1;
+
+ terminal_begin_using_terminal ();
+}
+
+/* **************************************************************** */
+/* */
+/* How to Read Characters From the Terminal */
+/* */
+/* **************************************************************** */
+
+#if defined (TIOCGETC)
+/* A buffer containing the terminal interrupt characters upon entry
+ to Info. */
+struct tchars original_tchars;
+#endif
+
+#if defined (TIOCGLTC)
+/* A buffer containing the local terminal mode characters upon entry
+ to Info. */
+struct ltchars original_ltchars;
+#endif
+
+#if defined (HAVE_TERMIOS_H)
+struct termios original_termios, ttybuff;
+#else
+# if defined (HAVE_TERMIO_H)
+/* A buffer containing the terminal mode flags upon entry to info. */
+struct termio original_termio, ttybuff;
+# else /* !HAVE_TERMIO_H */
+/* Buffers containing the terminal mode flags upon entry to info. */
+int original_tty_flags = 0;
+int original_lmode;
+struct sgttyb ttybuff;
+# endif /* !HAVE_TERMIO_H */
+#endif /* !HAVE_TERMIOS_H */
+
+/* Prepare to start using the terminal to read characters singly. */
+void
+terminal_prep_terminal ()
+{
+ int tty;
+
+ if (terminal_prep_terminal_hook)
+ {
+ (*terminal_prep_terminal_hook) ();
+ return;
+ }
+
+ tty = fileno (stdin);
+
+#if defined (HAVE_TERMIOS_H)
+ tcgetattr (tty, &original_termios);
+ tcgetattr (tty, &ttybuff);
+#else
+# if defined (HAVE_TERMIO_H)
+ ioctl (tty, TCGETA, &original_termio);
+ ioctl (tty, TCGETA, &ttybuff);
+# endif
+#endif
+
+#if defined (HAVE_TERMIOS_H) || defined (HAVE_TERMIO_H)
+ ttybuff.c_iflag &= (~ISTRIP & ~INLCR & ~IGNCR & ~ICRNL & ~IXON);
+ ttybuff.c_oflag &= (~ONLCR & ~OCRNL);
+ ttybuff.c_lflag &= (~ICANON & ~ECHO);
+
+ ttybuff.c_cc[VMIN] = 1;
+ ttybuff.c_cc[VTIME] = 0;
+
+ if (ttybuff.c_cc[VINTR] == '\177')
+ ttybuff.c_cc[VINTR] = -1;
+
+ if (ttybuff.c_cc[VQUIT] == '\177')
+ ttybuff.c_cc[VQUIT] = -1;
+#endif
+
+#if defined (HAVE_TERMIOS_H)
+ tcsetattr (tty, TCSANOW, &ttybuff);
+#else
+# if defined (HAVE_TERMIO_H)
+ ioctl (tty, TCSETA, &ttybuff);
+# endif
+#endif
+
+#if !defined (HAVE_TERMIOS_H) && !defined (HAVE_TERMIO_H)
+ ioctl (tty, TIOCGETP, &ttybuff);
+
+ if (!original_tty_flags)
+ original_tty_flags = ttybuff.sg_flags;
+
+ /* Make this terminal pass 8 bits around while we are using it. */
+# if defined (PASS8)
+ ttybuff.sg_flags |= PASS8;
+# endif /* PASS8 */
+
+# if defined (TIOCLGET) && defined (LPASS8)
+ {
+ int flags;
+ ioctl (tty, TIOCLGET, &flags);
+ original_lmode = flags;
+ flags |= LPASS8;
+ ioctl (tty, TIOCLSET, &flags);
+ }
+# endif /* TIOCLGET && LPASS8 */
+
+# if defined (TIOCGETC)
+ {
+ struct tchars temp;
+
+ ioctl (tty, TIOCGETC, &original_tchars);
+ temp = original_tchars;
+
+ /* C-s and C-q. */
+ temp.t_startc = temp.t_stopc = -1;
+
+ /* Often set to C-d. */
+ temp.t_eofc = -1;
+
+ /* If the a quit or interrupt character conflicts with one of our
+ commands, then make it go away. */
+ if (temp.t_intrc == '\177')
+ temp.t_intrc = -1;
+
+ if (temp.t_quitc == '\177')
+ temp.t_quitc = -1;
+
+ ioctl (tty, TIOCSETC, &temp);
+ }
+# endif /* TIOCGETC */
+
+# if defined (TIOCGLTC)
+ {
+ struct ltchars temp;
+
+ ioctl (tty, TIOCGLTC, &original_ltchars);
+ temp = original_ltchars;
+
+ /* Make the interrupt keys go away. Just enough to make people happy. */
+ temp.t_lnextc = -1; /* C-v. */
+ temp.t_dsuspc = -1; /* C-y. */
+ temp.t_flushc = -1; /* C-o. */
+ ioctl (tty, TIOCSLTC, &temp);
+ }
+# endif /* TIOCGLTC */
+
+ ttybuff.sg_flags &= ~ECHO;
+ ttybuff.sg_flags |= CBREAK;
+ ioctl (tty, TIOCSETN, &ttybuff);
+#endif /* !HAVE_TERMIOS_H && !HAVE_TERMIO_H */
+}
+
+/* Restore the tty settings back to what they were before we started using
+ this terminal. */
+void
+terminal_unprep_terminal ()
+{
+ int tty;
+
+ if (terminal_unprep_terminal_hook)
+ {
+ (*terminal_unprep_terminal_hook) ();
+ return;
+ }
+
+ tty = fileno (stdin);
+
+#if defined (HAVE_TERMIOS_H)
+ tcsetattr (tty, TCSANOW, &original_termios);
+#else
+# if defined (HAVE_TERMIO_H)
+ ioctl (tty, TCSETA, &original_termio);
+# else /* !HAVE_TERMIO_H */
+ ioctl (tty, TIOCGETP, &ttybuff);
+ ttybuff.sg_flags = original_tty_flags;
+ ioctl (tty, TIOCSETN, &ttybuff);
+
+# if defined (TIOCGETC)
+ ioctl (tty, TIOCSETC, &original_tchars);
+# endif /* TIOCGETC */
+
+# if defined (TIOCGLTC)
+ ioctl (tty, TIOCSLTC, &original_ltchars);
+# endif /* TIOCGLTC */
+
+# if defined (TIOCLGET) && defined (LPASS8)
+ ioctl (tty, TIOCLSET, &original_lmode);
+# endif /* TIOCLGET && LPASS8 */
+
+# endif /* !HAVE_TERMIO_H */
+#endif /* !HAVE_TERMIOS_H */
+ terminal_end_using_terminal ();
+}
+
diff --git a/contrib/texinfo/info/terminal.h b/contrib/texinfo/info/terminal.h
new file mode 100644
index 0000000..7cb1158
--- /dev/null
+++ b/contrib/texinfo/info/terminal.h
@@ -0,0 +1,129 @@
+/* terminal.h -- The external interface to terminal I/O. */
+
+/* This file is part of GNU Info, a program for reading online documentation
+ stored in Info format.
+
+ Copyright (C) 1993, 96 Free Software Foundation, Inc.
+
+ 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Written by Brian Fox (bfox@ai.mit.edu). */
+
+#if !defined (_TERMINAL_H_)
+#define _TERMINAL_H_
+
+/* We use the following data type to talk about pointers to functions. */
+#if !defined (__FUNCTION_DEF)
+# define __FUNCTION_DEF
+typedef int Function ();
+typedef void VFunction ();
+#endif /* _FUNCTION_DEF */
+
+/* For almost every function externally visible from terminal.c, there is
+ a corresponding "hook" function which can be bound in order to replace
+ the functionality of the one found in terminal.c. This is how we go
+ about implemented X window display. */
+
+/* The width and height of the terminal. */
+extern int screenwidth, screenheight;
+
+/* Non-zero means this terminal can't really do anything. */
+extern int terminal_is_dumb_p;
+
+/* Non-zero means that this terminal has a meta key. */
+extern int terminal_has_meta_p;
+
+/* Non-zero means that this terminal can produce a visible bell. */
+extern int terminal_has_visible_bell_p;
+
+/* Non-zero means to use that visible bell if at all possible. */
+extern int terminal_use_visible_bell_p;
+
+/* Non-zero means that this terminal can scroll lines up and down. */
+extern int terminal_can_scroll;
+
+/* Initialize the terminal which is known as TERMINAL_NAME. If this terminal
+ doesn't have cursor addressability, TERMINAL_IS_DUMB_P becomes non-zero.
+ The variables SCREENHEIGHT and SCREENWIDTH are set to the dimensions that
+ this terminal actually has. The variable TERMINAL_HAS_META_P becomes non-
+ zero if this terminal supports a Meta key. */
+extern void terminal_initialize_terminal ();
+extern VFunction *terminal_initialize_terminal_hook;
+
+/* Return the current screen width and height in the variables
+ SCREENWIDTH and SCREENHEIGHT. */
+extern void terminal_get_screen_size ();
+extern VFunction *terminal_get_screen_size_hook;
+
+/* Save and restore tty settings. */
+extern void terminal_prep_terminal (), terminal_unprep_terminal ();
+extern VFunction *terminal_prep_terminal_hook, *terminal_unprep_terminal_hook;
+
+/* Re-initialize the terminal to TERMINAL_NAME. */
+extern void terminal_new_terminal ();
+extern VFunction *terminal_new_terminal_hook;
+
+/* Move the cursor to the terminal location of X and Y. */
+extern void terminal_goto_xy ();
+extern VFunction *terminal_goto_xy_hook;
+
+/* Print STRING to the terminal at the current position. */
+extern void terminal_put_text ();
+extern VFunction *terminal_put_text_hook;
+
+/* Print NCHARS from STRING to the terminal at the current position. */
+extern void terminal_write_chars ();
+extern VFunction *terminal_write_chars_hook;
+
+/* Clear from the current position of the cursor to the end of the line. */
+extern void terminal_clear_to_eol ();
+extern VFunction *terminal_clear_to_eol_hook;
+
+/* Clear the entire terminal screen. */
+extern void terminal_clear_screen ();
+extern VFunction *terminal_clear_screen_hook;
+
+/* Move the cursor up one line. */
+extern void terminal_up_line ();
+extern VFunction *terminal_up_line_hook;
+
+/* Move the cursor down one line. */
+extern void terminal_down_line ();
+extern VFunction *terminal_down_line_hook;
+
+/* Turn on reverse video if possible. */
+extern void terminal_begin_inverse ();
+extern VFunction *terminal_begin_inverse_hook;
+
+/* Turn off reverse video if possible. */
+extern void terminal_end_inverse ();
+extern VFunction *terminal_end_inverse_hook;
+
+/* Scroll an area of the terminal, starting with the region from START
+ to END, AMOUNT lines. If AMOUNT is negative, the lines are scrolled
+ towards the top of the screen, else they are scrolled towards the
+ bottom of the screen. */
+extern void terminal_scroll_terminal ();
+extern VFunction *terminal_scroll_terminal_hook;
+
+/* Ring the terminal bell. The bell is run visibly if it both has one and
+ terminal_use_visible_bell_p is non-zero. */
+extern void terminal_ring_bell ();
+extern VFunction *terminal_ring_bell_hook;
+
+/* The key sequences output by the arrow keys, if this terminal has any. */
+extern char *term_ku, *term_kd, *term_kr, *term_kl;
+
+#endif /* !_TERMINAL_H_ */
diff --git a/contrib/texinfo/info/tilde.c b/contrib/texinfo/info/tilde.c
new file mode 100644
index 0000000..191d222
--- /dev/null
+++ b/contrib/texinfo/info/tilde.c
@@ -0,0 +1,376 @@
+/* tilde.c -- Tilde expansion code (~/foo := $HOME/foo).
+ $Id: tilde.c,v 1.3 1996/09/29 23:12:30 karl Exp $
+
+ This file is part of GNU Info, a program for reading online documentation
+ stored in Info format.
+
+ Copyright (C) 1988, 89, 90, 91, 92, 93, 96 Free Software Foundation, Inc.
+
+ 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Written by Brian Fox (bfox@ai.mit.edu). */
+
+#if defined (__GNUC__)
+# define alloca __builtin_alloca
+#else /* !__GNUC__ */
+# if defined (_AIX)
+ #pragma alloca
+# else /* !_AIX */
+# if defined (HAVE_ALLOCA_H)
+# include <alloca.h>
+# endif /* HAVE_ALLOCA_H */
+# endif /* !AIX */
+#endif /* !__GNUC__ */
+
+#if defined (HAVE_STDLIB_H)
+#include <stdlib.h>
+#endif
+
+#include "tilde.h"
+#include <pwd.h>
+
+#if defined (HAVE_STRING_H)
+#include <string.h>
+#endif
+
+#include "clib.h"
+
+#if !defined (NULL)
+# define NULL 0x0
+#endif
+
+#if defined (TEST) || defined (STATIC_MALLOC)
+static void *xmalloc (), *xrealloc ();
+#else
+extern void *xmalloc (), *xrealloc ();
+#endif /* TEST || STATIC_MALLOC */
+
+/* The default value of tilde_additional_prefixes. This is set to
+ whitespace preceding a tilde so that simple programs which do not
+ perform any word separation get desired behaviour. */
+static char *default_prefixes[] =
+ { " ~", "\t~", (char *)NULL };
+
+/* The default value of tilde_additional_suffixes. This is set to
+ whitespace or newline so that simple programs which do not
+ perform any word separation get desired behaviour. */
+static char *default_suffixes[] =
+ { " ", "\n", (char *)NULL };
+
+/* If non-null, this contains the address of a function to call if the
+ standard meaning for expanding a tilde fails. The function is called
+ with the text (sans tilde, as in "foo"), and returns a malloc()'ed string
+ which is the expansion, or a NULL pointer if there is no expansion. */
+CFunction *tilde_expansion_failure_hook = (CFunction *)NULL;
+
+/* When non-null, this is a NULL terminated array of strings which
+ are duplicates for a tilde prefix. Bash uses this to expand
+ `=~' and `:~'. */
+char **tilde_additional_prefixes = default_prefixes;
+
+/* When non-null, this is a NULL terminated array of strings which match
+ the end of a username, instead of just "/". Bash sets this to
+ `:' and `=~'. */
+char **tilde_additional_suffixes = default_suffixes;
+
+/* Find the start of a tilde expansion in STRING, and return the index of
+ the tilde which starts the expansion. Place the length of the text
+ which identified this tilde starter in LEN, excluding the tilde itself. */
+static int
+tilde_find_prefix (string, len)
+ char *string;
+ int *len;
+{
+ register int i, j, string_len;
+ register char **prefixes = tilde_additional_prefixes;
+
+ string_len = strlen (string);
+ *len = 0;
+
+ if (!*string || *string == '~')
+ return (0);
+
+ if (prefixes)
+ {
+ for (i = 0; i < string_len; i++)
+ {
+ for (j = 0; prefixes[j]; j++)
+ {
+ if (strncmp (string + i, prefixes[j], strlen (prefixes[j])) == 0)
+ {
+ *len = strlen (prefixes[j]) - 1;
+ return (i + *len);
+ }
+ }
+ }
+ }
+ return (string_len);
+}
+
+/* Find the end of a tilde expansion in STRING, and return the index of
+ the character which ends the tilde definition. */
+static int
+tilde_find_suffix (string)
+ char *string;
+{
+ register int i, j, string_len;
+ register char **suffixes = tilde_additional_suffixes;
+
+ string_len = strlen (string);
+
+ for (i = 0; i < string_len; i++)
+ {
+ if (string[i] == '/' || !string[i])
+ break;
+
+ for (j = 0; suffixes && suffixes[j]; j++)
+ {
+ if (strncmp (string + i, suffixes[j], strlen (suffixes[j])) == 0)
+ return (i);
+ }
+ }
+ return (i);
+}
+
+/* Return a new string which is the result of tilde expanding STRING. */
+char *
+tilde_expand (string)
+ char *string;
+{
+ char *result, *tilde_expand_word ();
+ int result_size, result_index;
+
+ result_size = result_index = 0;
+ result = (char *)NULL;
+
+ /* Scan through STRING expanding tildes as we come to them. */
+ while (1)
+ {
+ register int start, end;
+ char *tilde_word, *expansion;
+ int len;
+
+ /* Make START point to the tilde which starts the expansion. */
+ start = tilde_find_prefix (string, &len);
+
+ /* Copy the skipped text into the result. */
+ if ((result_index + start + 1) > result_size)
+ result = (char *)xrealloc (result, 1 + (result_size += (start + 20)));
+
+ strncpy (result + result_index, string, start);
+ result_index += start;
+
+ /* Advance STRING to the starting tilde. */
+ string += start;
+
+ /* Make END be the index of one after the last character of the
+ username. */
+ end = tilde_find_suffix (string);
+
+ /* If both START and END are zero, we are all done. */
+ if (!start && !end)
+ break;
+
+ /* Expand the entire tilde word, and copy it into RESULT. */
+ tilde_word = (char *)xmalloc (1 + end);
+ strncpy (tilde_word, string, end);
+ tilde_word[end] = '\0';
+ string += end;
+
+ expansion = tilde_expand_word (tilde_word);
+ free (tilde_word);
+
+ len = strlen (expansion);
+ if ((result_index + len + 1) > result_size)
+ result = (char *)xrealloc (result, 1 + (result_size += (len + 20)));
+
+ strcpy (result + result_index, expansion);
+ result_index += len;
+ free (expansion);
+ }
+
+ result[result_index] = '\0';
+
+ return (result);
+}
+
+/* Do the work of tilde expansion on FILENAME. FILENAME starts with a
+ tilde. If there is no expansion, call tilde_expansion_failure_hook. */
+char *
+tilde_expand_word (filename)
+ char *filename;
+{
+ char *dirname;
+
+ dirname = filename ? strdup (filename) : (char *)NULL;
+
+ if (dirname && *dirname == '~')
+ {
+ char *temp_name;
+ if (!dirname[1] || dirname[1] == '/')
+ {
+ /* Prepend $HOME to the rest of the string. */
+ extern char *getenv ();
+ char *temp_home = getenv ("HOME");
+
+ /* If there is no HOME variable, look up the directory in
+ the password database. */
+ if (!temp_home)
+ {
+ struct passwd *entry;
+
+ entry = (struct passwd *) getpwuid (getuid ());
+ if (entry)
+ temp_home = entry->pw_dir;
+ }
+
+ temp_name = (char *)
+ alloca (1 + strlen (&dirname[1])
+ + (temp_home ? strlen (temp_home) : 0));
+ temp_name[0] = '\0';
+ if (temp_home)
+ strcpy (temp_name, temp_home);
+ strcat (temp_name, &dirname[1]);
+ free (dirname);
+ dirname = strdup (temp_name);
+ }
+ else
+ {
+ struct passwd *user_entry;
+ char *username = (char *)alloca (257);
+ int i, c;
+
+ for (i = 1; c = dirname[i]; i++)
+ {
+ if (c == '/')
+ break;
+ else
+ username[i - 1] = c;
+ }
+ username[i - 1] = '\0';
+
+ if (!(user_entry = (struct passwd *) getpwnam (username)))
+ {
+ /* If the calling program has a special syntax for
+ expanding tildes, and we couldn't find a standard
+ expansion, then let them try. */
+ if (tilde_expansion_failure_hook)
+ {
+ char *expansion;
+
+ expansion = (*tilde_expansion_failure_hook) (username);
+
+ if (expansion)
+ {
+ temp_name = (char *)alloca
+ (1 + strlen (expansion) + strlen (&dirname[i]));
+ strcpy (temp_name, expansion);
+ strcat (temp_name, &dirname[i]);
+ free (expansion);
+ goto return_name;
+ }
+ }
+ /* We shouldn't report errors. */
+ }
+ else
+ {
+ temp_name = (char *)alloca
+ (1 + strlen (user_entry->pw_dir) + strlen (&dirname[i]));
+ strcpy (temp_name, user_entry->pw_dir);
+ strcat (temp_name, &dirname[i]);
+ return_name:
+ free (dirname);
+ dirname = strdup (temp_name);
+ }
+ endpwent ();
+ }
+ }
+ return (dirname);
+}
+
+
+#if defined (TEST)
+#undef NULL
+#include <stdio.h>
+
+main (argc, argv)
+ int argc;
+ char **argv;
+{
+ char *result, line[512];
+ int done = 0;
+
+ while (!done)
+ {
+ printf ("~expand: ");
+ fflush (stdout);
+
+ if (!gets (line))
+ strcpy (line, "done");
+
+ if ((strcmp (line, "done") == 0) ||
+ (strcmp (line, "quit") == 0) ||
+ (strcmp (line, "exit") == 0))
+ {
+ done = 1;
+ break;
+ }
+
+ result = tilde_expand (line);
+ printf (" --> %s\n", result);
+ free (result);
+ }
+ exit (0);
+}
+
+static void memory_error_and_abort ();
+
+static void *
+xmalloc (bytes)
+ int bytes;
+{
+ void *temp = (void *)malloc (bytes);
+
+ if (!temp)
+ memory_error_and_abort ();
+ return (temp);
+}
+
+static void *
+xrealloc (pointer, bytes)
+ void *pointer;
+ int bytes;
+{
+ void *temp;
+
+ if (!pointer)
+ temp = (char *)malloc (bytes);
+ else
+ temp = (char *)realloc (pointer, bytes);
+
+ if (!temp)
+ memory_error_and_abort ();
+
+ return (temp);
+}
+
+static void
+memory_error_and_abort ()
+{
+ fprintf (stderr, "readline: Out of virtual memory!\n");
+ abort ();
+}
+#endif /* TEST */
+
diff --git a/contrib/texinfo/info/tilde.h b/contrib/texinfo/info/tilde.h
new file mode 100644
index 0000000..d66aee9
--- /dev/null
+++ b/contrib/texinfo/info/tilde.h
@@ -0,0 +1,58 @@
+/* tilde.h: Externally available variables and function in libtilde.a. */
+
+/* This file is part of GNU Info, a program for reading online documentation
+ stored in Info format.
+
+ This file has appeared in prior works by the Free Software Foundation;
+ thus it carries copyright dates from 1988 through 1993.
+
+ Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993 Free Software
+ Foundation, Inc.
+
+ 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Written by Brian Fox (bfox@ai.mit.edu). */
+
+/* Function pointers can be declared as (Function *)foo. */
+#if !defined (__FUNCTION_DEF)
+# define __FUNCTION_DEF
+typedef int Function ();
+typedef void VFunction ();
+typedef char *CFunction ();
+#endif /* _FUNCTION_DEF */
+
+/* If non-null, this contains the address of a function to call if the
+ standard meaning for expanding a tilde fails. The function is called
+ with the text (sans tilde, as in "foo"), and returns a malloc()'ed string
+ which is the expansion, or a NULL pointer if there is no expansion. */
+extern CFunction *tilde_expansion_failure_hook;
+
+/* When non-null, this is a NULL terminated array of strings which
+ are duplicates for a tilde prefix. Bash uses this to expand
+ `=~' and `:~'. */
+extern char **tilde_additional_prefixes;
+
+/* When non-null, this is a NULL terminated array of strings which match
+ the end of a username, instead of just "/". Bash sets this to
+ `:' and `=~'. */
+extern char **tilde_additional_suffixes;
+
+/* Return a new string which is the result of tilde expanding STRING. */
+extern char *tilde_expand ();
+
+/* Do the work of tilde expansion on FILENAME. FILENAME starts with a
+ tilde. If there is no expansion, call tilde_expansion_failure_hook. */
+extern char *tilde_expand_word ();
+
diff --git a/contrib/texinfo/info/userdoc.texi b/contrib/texinfo/info/userdoc.texi
new file mode 100644
index 0000000..f9349c6
--- /dev/null
+++ b/contrib/texinfo/info/userdoc.texi
@@ -0,0 +1,1270 @@
+@c This file is meant to be included in any arbitrary piece of
+@c documentation that wishes to describe the info program. Some day
+@c info-stnd.texi should probably use this file instead of duplicating
+@c its contents.
+@c
+@c This file documents the use of the standalone GNU Info program,
+@c versions 2.7 and later.
+
+@ifclear InfoProgVer
+@set InfoProgVer 2.11
+@end ifclear
+@synindex vr cp
+@synindex fn cp
+@synindex ky cp
+
+@heading What is Info?
+
+This text documents the use of the GNU Info program, version
+@value{InfoProgVer}.
+
+@dfn{Info} is a program which is used to view info files on an ASCII
+terminal. @dfn{info files} are the result of processing texinfo files
+with the program @code{makeinfo} or with the Emacs command @code{M-x
+texinfo-format-buffer}. Finally, @dfn{texinfo} is a documentation
+language which allows a printed manual and online documentation (an info
+file) to be produced from a single source file.
+
+@menu
+* Options:: Options you can pass on the command line.
+* Cursor Commands:: Commands which move the cursor within a node.
+* Scrolling Commands:: Commands for moving the node around in a window.
+* Node Commands:: Commands for selecting a new node.
+* Searching Commands:: Commands for searching an info file.
+* Xref Commands:: Commands for selecting cross references.
+* Window Commands:: Commands which manipulate multiple windows.
+* Printing Nodes:: How to print out the contents of a node.
+* Miscellaneous Commands:: A few commands that defy categories.
+* Variables:: How to change the default behaviour of Info.
+@ifset NOTSET
+* Info for Sys Admins:: How to setup Info. Using special options.
+@end ifset
+@ifset STANDALONE
+* GNU Info Global Index:: Global index containing keystrokes, command names,
+ variable names, and general concepts.
+@end ifset
+@end menu
+
+@node Options
+@chapter Command Line Options
+@cindex command line options
+@cindex arguments, command line
+
+GNU Info accepts several options to control the initial node being
+viewed, and to specify which directories to search for info files. Here
+is a template showing an invocation of GNU Info from the shell:
+
+@example
+info [--@var{option-name} @var{option-value}] @var{menu-item}@dots{}
+@end example
+
+The following @var{option-names} are available when invoking Info from
+the shell:
+
+@table @code
+@cindex directory path
+@item --directory @var{directory-path}
+@itemx -d @var{directory-path}
+Adds @var{directory-path} to the list of directory paths searched when
+Info needs to find a file. You may issue @code{--directory} multiple
+times; once for each directory which contains info files.
+Alternatively, you may specify a value for the environment variable
+@code{INFOPATH}; if @code{--directory} is not given, the value of
+@code{INFOPATH} is used. The value of @code{INFOPATH} is a colon
+separated list of directory names. If you do not supply
+@code{INFOPATH} or @code{--directory-path} a default path is used.
+
+@item --file @var{filename}
+@itemx -f @var{filename}
+@cindex info file, selecting
+Specifies a particular info file to visit. Instead of visiting the file
+@code{dir}, Info will start with @code{(@var{filename})Top} as the first
+file and node.
+
+@item --node @var{nodename}
+@itemx -n @var{nodename}
+@cindex node, selecting
+Specifies a particular node to visit in the initial file loaded. This
+is especially useful in conjunction with @code{--file}@footnote{Of
+course, you can specify both the file and node in a @code{--node}
+command; but don't forget to escape the open and close parentheses from
+the shell as in: @code{info --node '(emacs)Buffers'}}. You may specify
+@code{--node} multiple times; for an interactive Info, each
+@var{nodename} is visited in its own window, for a non-interactive Info
+(such as when @code{--output} is given) each @var{nodename} is processed
+sequentially.
+
+@item --output @var{filename}
+@itemx -o @var{filename}
+@cindex file, outputting to
+@cindex outputting to a file
+Specify @var{filename} as the name of a file to output to. Each node
+that Info visits will be output to @var{filename} instead of
+interactively viewed. A value of @code{-} for @var{filename} specifies
+the standard output.
+
+@item --subnodes
+@cindex @code{--subnodes}, command line option
+This option only has meaning when given in conjunction with
+@code{--output}. It means to recursively output the nodes appearing in
+the menus of each node being output. Menu items which resolve to
+external info files are not output, and neither are menu items which are
+members of an index. Each node is only output once.
+
+@item --help
+@itemx -h
+Produces a relatively brief description of the available Info options.
+
+@item --version
+@cindex version information
+Prints the version information of Info and exits.
+
+@item @var{menu-item}
+@cindex menu, following
+Remaining arguments to Info are treated as the names of menu items. The
+first argument would be a menu item in the initial node visited, while
+the second argument would be a menu item in the first argument's node.
+You can easily move to the node of your choice by specifying the menu
+names which describe the path to that node. For example,
+
+@example
+info emacs buffers
+@end example
+
+first selects the menu item @samp{Emacs} in the node @samp{(dir)Top},
+and then selects the menu item @samp{Buffers} in the node
+@samp{(emacs)Top}.
+
+@end table
+
+@node Cursor Commands
+@chapter Moving the Cursor
+@cindex cursor, moving
+Many people find that reading screens of text page by page is made
+easier when one is able to indicate particular pieces of text with some
+kind of pointing device. Since this is the case, GNU Info (both the
+Emacs and standalone versions) have several commands which allow you to
+move the cursor about the screen. The notation used in this manual to
+describe keystrokes is identical to the notation used within the Emacs
+manual, and the GNU Readline manual. @xref{Characters, , Character
+Conventions, emacs, the GNU Emacs Manual}, if you are unfamilar with the
+notation.
+
+The following table lists the basic cursor movement commands in Info.
+Each entry consists of the key sequence you should type to execute the
+cursor movement, the @code{M-x}@footnote{@code{M-x} is also a command; it
+invokes @code{execute-extended-command}. @xref{M-x, , Executing an
+extended command, emacs, the GNU Emacs Manual}, for more detailed
+information.} command name (displayed in parentheses), and a short
+description of what the command does. All of the cursor motion commands
+can take an @dfn{numeric} argument (@pxref{Miscellaneous Commands,
+@code{universal-argument}}), to find out how to supply them. With a
+numeric argument, the motion commands are simply executed that
+many times; for example, a numeric argument of 4 given to
+@code{next-line} causes the cursor to move down 4 lines. With a
+negative numeric argument, the motion is reversed; an argument of -4
+given to the @code{next-line} command would cause the cursor to move
+@emph{up} 4 lines.
+
+@table @asis
+@item @code{C-n} (@code{next-line})
+@kindex C-n
+@findex next-line
+Moves the cursor down to the next line.
+
+@item @code{C-p} (@code{prev-line})
+@kindex C-p
+@findex prev-line
+Move the cursor up to the previous line.
+
+@item @code{C-a} (@code{beginning-of-line})
+@kindex C-a, in Info windows
+@findex beginning-of-line
+Move the cursor to the start of the current line.
+
+@item @code{C-e} (@code{end-of-line})
+@kindex C-e, in Info windows
+@findex end-of-line
+Moves the cursor to the end of the current line.
+
+@item @code{C-f} (@code{forward-char})
+@kindex C-f, in Info windows
+@findex forward-char
+Move the cursor forward a character.
+
+@item @code{C-b} (@code{backward-char})
+@kindex C-b, in Info windows
+@findex backward-char
+Move the cursor backward a character.
+
+@item @code{M-f} (@code{forward-word})
+@kindex M-f, in Info windows
+@findex forward-word
+Moves the cursor forward a word.
+
+@item @code{M-b} (@code{backward-word})
+@kindex M-b, in Info winows
+@findex backward-word
+Moves the cursor backward a word.
+
+@item @code{M-<} (@code{beginning-of-node})
+@itemx @code{b}
+@kindex b, in Info winows
+@kindex M-<
+@findex beginning-of-node
+Moves the cursor to the start of the current node.
+
+@item @code{M->} (@code{end-of-node})
+@kindex M->
+@findex end-of-node
+Moves the cursor to the end of the current node.
+
+@item @code{M-r} (@code{move-to-window-line})
+@kindex M-r
+@findex move-to-window-line
+Moves the cursor to a specific line of the window. Without a numeric
+argument, @code{M-r} moves the cursor to the start of the line in the
+center of the window. With a numeric argument of @var{n}, @code{M-r}
+moves the cursor to the start of the @var{n}th line in the window.
+@end table
+
+@node Scrolling Commands
+@chapter Moving Text Within a Window
+@cindex scrolling
+
+Sometimes you are looking at a screenful of text, and only part of the
+current paragraph you are reading is visible on the screen. The
+commands detailed in this section are used to shift which part of the
+current node is visible on the screen.
+
+@table @asis
+@item @code{SPC} (@code{scroll-forward})
+@itemx @code{C-v}
+@kindex SPC, in Info windows
+@kindex C-v
+@findex scroll-forward
+Shift the text in this window up. That is, show more of the node which
+is currently below the bottom of the window. With a numeric argument,
+show that many more lines at the bottom of the window; a numeric
+argument of 4 would shift all of the text in the window up 4 lines
+(discarding the top 4 lines), and show you four new lines at the bottom
+of the window. Without a numeric argument, @key{SPC} takes the bottom
+two lines of the window and places them at the top of the window,
+redisplaying almost a completely new screenful of lines.
+
+@item @code{DEL} (@code{scroll-backward})
+@itemx @code{M-v}
+@kindex DEL, in Info windows
+@kindex M-v
+@findex scroll-backward
+Shift the text in this window down. The inverse of
+@code{scroll-forward}.
+
+@end table
+
+@cindex scrolling through node structure
+The @code{scroll-forward} and @code{scroll-backward} commands can also
+move forward and backward through the node structure of the file. If
+you press @key{SPC} while viewing the end of a node, or @key{DEL} while
+viewing the beginning of a node, what happens is controlled by the
+variable @code{scroll-behaviour}. @xref{Variables,
+@code{scroll-behaviour}}, for more information.
+
+@table @asis
+@item @code{C-l} (@code{redraw-display})
+@kindex C-l
+@findex redraw-display
+Redraw the display from scratch, or shift the line containing the cursor
+to a specified location. With no numeric argument, @samp{C-l} clears
+the screen, and then redraws its entire contents. Given a numeric
+argument of @var{n}, the line containing the cursor is shifted so that
+it is on the @var{n}th line of the window.
+
+@item @code{C-x w} (@code{toggle-wrap})
+@kindex C-w
+@findex toggle-wrap
+Toggles the state of line wrapping in the current window. Normally,
+lines which are longer than the screen width @dfn{wrap}, i.e., they are
+continued on the next line. Lines which wrap have a @samp{\} appearing
+in the rightmost column of the screen. You can cause such lines to be
+terminated at the rightmost column by changing the state of line
+wrapping in the window with @code{C-x w}. When a line which needs more
+space than one screen width to display is displayed, a @samp{$} appears
+in the rightmost column of the screen, and the remainder of the line is
+invisible.
+@end table
+
+@node Node Commands
+@chapter Selecting a New Node
+@cindex nodes, selection of
+
+This section details the numerous Info commands which select a new node
+to view in the current window.
+
+The most basic node commands are @samp{n}, @samp{p}, @samp{u}, and
+@samp{l}.
+
+When you are viewing a node, the top line of the node contains some Info
+@dfn{pointers} which describe where the next, previous, and up nodes
+are. Info uses this line to move about the node structure of the file
+when you use the following commands:
+
+@table @asis
+@item @code{n} (@code{next-node})
+@kindex n
+@findex next-node
+Selects the `Next' node.
+
+@item @code{p} (@code{prev-node})
+@kindex p
+@findex prev-node
+Selects the `Prev' node.
+
+@item @code{u} (@code{up-node})
+@kindex u
+@findex up-node
+Selects the `Up' node.
+@end table
+
+You can easily select a node that you have already viewed in this window
+by using the @samp{l} command -- this name stands for "last", and
+actually moves through the list of already visited nodes for this
+window. @samp{l} with a negative numeric argument moves forward through
+the history of nodes for this window, so you can quickly step between
+two adjacent (in viewing history) nodes.
+
+@table @asis
+@item @code{l} (@code{history-node})
+@kindex l
+@findex history-node
+Selects the most recently selected node in this window.
+@end table
+
+Two additional commands make it easy to select the most commonly
+selected nodes; they are @samp{t} and @samp{d}.
+
+@table @asis
+@item @code{t} (@code{top-node})
+@kindex t
+@findex top-node
+Selects the node @samp{Top} in the current info file.
+
+@item @code{d} (@code{dir-node})
+@kindex d
+@findex dir-node
+Selects the directory node (i.e., the node @samp{(dir)}).
+@end table
+
+Here are some other commands which immediately result in the selection
+of a different node in the current window:
+
+@table @asis
+@item @code{<} (@code{first-node})
+@kindex <
+@findex first-node
+Selects the first node which appears in this file. This node is most
+often @samp{Top}, but it doesn't have to be.
+
+@item @code{>} (@code{last-node})
+@kindex >
+@findex last-node
+Selects the last node which appears in this file.
+
+@item @code{]} (@code{global-next-node})
+@kindex ]
+@findex global-next-node
+Moves forward or down through node structure. If the node that you are
+currently viewing has a @samp{Next} pointer, that node is selected.
+Otherwise, if this node has a menu, the first menu item is selected. If
+there is no @samp{Next} and no menu, the same process is tried with the
+@samp{Up} node of this node.
+
+@item @code{[} (@code{global-prev-node})
+@kindex [
+@findex global-prev-node
+Moves backward or up through node structure. If the node that you are
+currently viewing has a @samp{Prev} pointer, that node is selected.
+Otherwise, if the node has an @samp{Up} pointer, that node is selected,
+and if it has a menu, the last item in the menu is selected.
+@end table
+
+You can get the same behaviour as @code{global-next-node} and
+@code{global-prev-node} while simply scrolling through the file with
+@key{SPC} and @key{DEL}; @xref{Variables, @code{scroll-behaviour}}, for
+more information.
+
+@table @asis
+@item @code{g} (@code{goto-node})
+@kindex g
+@findex goto-node
+Reads the name of a node and selects it. No completion is done while
+reading the node name, since the desired node may reside in a separate
+file. The node must be typed exactly as it appears in the info file. A
+file name may be included as with any node specification, for example
+
+@example
+@code{g(emacs)Buffers}
+@end example
+
+finds the node @samp{Buffers} in the info file @file{emacs}.
+
+@item @code{C-x k} (@code{kill-node})
+@kindex C-x k
+@findex kill-node
+Kills a node. The node name is prompted for in the echo area, with a
+default of the current node. @dfn{Killing} a node means that Info tries
+hard to forget about it, removing it from the list of history nodes kept
+for the window where that node is found. Another node is selected in
+the window which contained the killed node.
+
+@item @code{C-x C-f} (@code{view-file})
+@kindex C-x C-f
+@findex view-file
+Reads the name of a file and selects the entire file. The command
+@example
+@code{C-x C-f @var{filename}}
+@end example
+is equivalent to typing
+@example
+@code{g(@var{filename})*}
+@end example
+
+@item @code{C-x C-b} (@code{list-visited-nodes})
+@kindex C-x C-b
+@findex list-visited-nodes
+Makes a window containing a menu of all of the currently visited nodes.
+This window becomes the selected window, and you may use the standard
+Info commands within it.
+
+@item @code{C-x b} (@code{select-visited-node})
+@kindex C-x b
+@findex select-visited-node
+Selects a node which has been previously visited in a visible window.
+This is similar to @samp{C-x C-b} followed by @samp{m}, but no window is
+created.
+@end table
+
+@node Searching Commands
+@chapter Searching an Info File
+@cindex searching
+
+GNU Info allows you to search for a sequence of characters throughout an
+entire info file, search through the indices of an info file, or find
+areas within an info file which discuss a particular topic.
+
+@table @asis
+@item @code{s} (@code{search})
+@kindex s
+@findex search
+Reads a string in the echo area and searches for it.
+
+@item @code{C-s} (@code{isearch-forward})
+@kindex C-s
+@findex isearch-forward
+Interactively searches forward through the info file for a string as you
+type it.
+
+@item @code{C-r} (@code{isearch-backward})
+@kindex C-r
+@findex isearch-backward
+Interactively searches backward through the info file for a string as
+you type it.
+
+@item @code{i} (@code{index-search})
+@kindex i
+@findex index-search
+Looks up a string in the indices for this info file, and selects a node
+where the found index entry points to.
+
+@item @code{,} (@code{next-index-match})
+@kindex ,
+@findex next-index-match
+Moves to the node containing the next matching index item from the last
+@samp{i} command.
+@end table
+
+The most basic searching command is @samp{s} (@code{search}). The
+@samp{s} command prompts you for a string in the echo area, and then
+searches the remainder of the info file for an ocurrence of that string.
+If the string is found, the node containing it is selected, and the
+cursor is left positioned at the start of the found string. Subsequent
+@samp{s} commands show you the default search string within @samp{[} and
+@samp{]}; pressing @key{RET} instead of typing a new string will use the
+default search string.
+
+@dfn{Incremental searching} is similar to basic searching, but the
+string is looked up while you are typing it, instead of waiting until
+the entire search string has been specified.
+
+@node Xref Commands
+@chapter Selecting Cross References
+
+We have already discussed the @samp{Next}, @samp{Prev}, and @samp{Up}
+pointers which appear at the top of a node. In addition to these
+pointers, a node may contain other pointers which refer you to a
+different node, perhaps in another info file. Such pointers are called
+@dfn{cross references}, or @dfn{xrefs} for short.
+
+@menu
+* Parts of an Xref:: What a cross reference is made of.
+* Selecting Xrefs:: Commands for selecting menu or note items.
+@end menu
+
+@node Parts of an Xref
+@section Parts of an Xref
+
+Cross references have two major parts: the first part is called the
+@dfn{label}; it is the name that you can use to refer to the cross
+reference, and the second is the @dfn{target}; it is the full name of
+the node that the cross reference points to.
+
+The target is separated from the label by a colon @samp{:}; first the
+label appears, and then the target. For example, in the sample menu
+cross reference below, the single colon separates the label from the
+target.
+
+@example
+* Foo Label: Foo Target. More information about Foo.
+@end example
+
+Note the @samp{.} which ends the name of the target. The @samp{.} is
+not part of the target; it serves only to let Info know where the target
+name ends.
+
+A shorthand way of specifying references allows two adjacent colons to
+stand for a target name which is the same as the label name:
+
+@example
+* Foo Commands:: Commands pertaining to Foo.
+@end example
+
+In the above example, the name of the target is the same as the name of
+the label, in this case @code{Foo Commands}.
+
+You will normally see two types of cross references while viewing nodes:
+@dfn{menu} references, and @dfn{note} references. Menu references
+appear within a node's menu; they begin with a @samp{*} at the beginning
+of a line, and continue with a label, a target, and a comment which
+describes what the contents of the node pointed to contains.
+
+Note references appear within the body of the node text; they begin with
+@code{*Note}, and continue with a label and a target.
+
+Like @samp{Next}, @samp{Prev} and @samp{Up} pointers, cross references
+can point to any valid node. They are used to refer you to a place
+where more detailed information can be found on a particular subject.
+Here is a cross reference which points to a node within the Texinfo
+documentation: @xref{xref, , Writing an Xref, texinfo, the Texinfo
+Manual}, for more information on creating your own texinfo cross
+references.
+
+@node Selecting Xrefs
+@section Selecting Xrefs
+
+The following table lists the Info commands which operate on menu items.
+
+@table @asis
+@item @code{1} (@code{menu-digit})
+@itemx @code{2} @dots{} @code{9}
+@cindex 1 @dots{} 9, in Info windows
+@kindex 1 @dots{} 9, in Info windows
+@findex menu-digit
+Within an Info window, pressing a single digit, (such as @samp{1}),
+selects that menu item, and places its node in the current window.
+For convenience, there is one exception; pressing @samp{0} selects the
+@emph{last} item in the node's menu.
+
+@item @code{0} (@code{last-menu-item})
+@kindex 0, in Info windows
+@findex last-menu-item
+Select the last item in the current node's menu.
+
+@item @code{m} (@code{menu-item})
+@kindex m
+@findex menu-item
+Reads the name of a menu item in the echo area and selects its node.
+Completion is available while reading the menu label.
+
+@item @code{M-x find-menu}
+@findex find-menu
+Moves the cursor to the start of this node's menu.
+@end table
+
+This table lists the Info commands which operate on note cross references.
+
+@table @asis
+@item @code{f} (@code{xref-item})
+@itemx @code{r}
+@kindex f
+@kindex r
+@findex xref-item
+Reads the name of a note cross reference in the echo area and selects
+its node. Completion is available while reading the cross reference
+label.
+@end table
+
+Finally, the next few commands operate on menu or note references alike:
+
+@table @asis
+@item @code{TAB} (@code{move-to-next-xref})
+@kindex TAB, in Info windows
+@findex move-to-next-xref
+Moves the cursor to the start of the next nearest menu item or note
+reference in this node. You can then use @key{RET}
+(@code{select-reference-this-line} to select the menu or note reference.
+
+@item @code{M-TAB} (@code{move-to-prev-xref})
+@kindex M-TAB, in Info windows
+@findex move-to-prev-xref
+Moves the cursor the start of the nearest previous menu item or note
+reference in this node.
+
+@item @code{RET} (@code{select-reference-this-line})
+@kindex RET, in Info windows
+@findex select-reference-this-line
+Selects the menu item or note reference appearing on this line.
+@end table
+
+@node Window Commands
+@chapter Manipulating Multiple Windows
+@cindex windows, manipulating
+
+A @dfn{window} is a place to show the text of a node. Windows have a
+view area where the text of the node is displayed, and an associated
+@dfn{mode line}, which briefly describes the node being viewed.
+
+GNU Info supports multiple windows appearing in a single screen; each
+window is separated from the next by its modeline. At any time, there
+is only one @dfn{active} window, that is, the window in which the cursor
+appears. There are commands available for creating windows, changing
+the size of windows, selecting which window is active, and for deleting
+windows.
+
+@menu
+* The Mode Line:: What appears in the mode line?
+* Basic Windows:: Manipulating windows in Info.
+* The Echo Area:: Used for displaying errors and reading input.
+@end menu
+
+@node The Mode Line
+@section The Mode Line
+
+A @dfn{mode line} is a line of inverse video which appears at the bottom
+of an info window. It describes the contents of the window just above
+it; this information includes the name of the file and node appearing in
+that window, the number of screen lines it takes to display the node,
+and the percentage of text that is above the top of the window. It can
+also tell you if the indirect tags table for this info file needs to be
+updated, and whether or not the info file was compressed when stored on
+disk.
+
+Here is a sample mode line for a window containing an uncompressed file
+named @file{dir}, showing the node @samp{Top}.
+
+@example
+-----Info: (dir)Top, 40 lines --Top---------------------------------------
+ ^^ ^ ^^^ ^^
+ (file)Node #lines where
+@end example
+
+When a node comes from a file which is compressed on disk, this is
+indicated in the mode line with two small @samp{z}'s. In addition, if
+the info file containing the node has been split into subfiles, the name
+of the subfile containing the node appears in the modeline as well:
+
+@example
+--zz-Info: (emacs)Top, 291 lines --Top-- Subfile: emacs-1.Z---------------
+@end example
+
+When Info makes a node internally, such that there is no corresponding
+info file on disk, the name of the node is surrounded by asterisks
+(@samp{*}). The name itself tells you what the contents of the window
+are; the sample mode line below shows an internally constructed node
+showing possible completions:
+
+@example
+-----Info: *Completions*, 7 lines --All-----------------------------------
+@end example
+
+@node Basic Windows
+@section Window Commands
+
+It can be convenient to view more than one node at a time. To allow
+this, Info can display more than one @dfn{window}. Each window has its
+own mode line (@pxref{The Mode Line}) and history of nodes viewed in that
+window (@pxref{Node Commands, , @code{history-node}}).
+
+@table @asis
+@item @code{C-x o} (@code{next-window})
+@cindex windows, selecting
+@kindex C-x o
+@findex next-window
+Selects the next window on the screen. Note that the echo area can only be
+selected if it is already in use, and you have left it temporarily.
+Normally, @samp{C-x o} simply moves the cursor into the next window on
+the screen, or if you are already within the last window, into the first
+window on the screen. Given a numeric argument, @samp{C-x o} moves over
+that many windows. A negative argument causes @samp{C-x o} to select
+the previous window on the screen.
+
+@item @code{M-x prev-window}
+@findex prev-window
+Selects the previous window on the screen. This is identical to
+@samp{C-x o} with a negative argument.
+
+@item @code{C-x 2} (@code{split-window})
+@cindex windows, creating
+@kindex C-x 2
+@findex split-window
+Splits the current window into two windows, both showing the same node.
+Each window is one half the size of the original window, and the cursor
+remains in the original window. The variable @code{automatic-tiling}
+can cause all of the windows on the screen to be resized for you
+automatically, please @pxref{Variables, , automatic-tiling} for more
+information.
+
+@item @code{C-x 0} (@code{delete-window})
+@cindex windows, deleting
+@kindex C-x 0
+@findex delete-window
+Deletes the current window from the screen. If you have made too many
+windows and your screen appears cluttered, this is the way to get rid of
+some of them.
+
+@item @code{C-x 1} (@code{keep-one-window})
+@kindex C-x 1
+@findex keep-one-window
+Deletes all of the windows excepting the current one.
+
+@item @code{ESC C-v} (@code{scroll-other-window})
+@kindex ESC C-v, in Info windows
+@findex scroll-other-window
+Scrolls the other window, in the same fashion that @samp{C-v} might
+scroll the current window. Given a negative argument, the "other"
+window is scrolled backward.
+
+@item @code{C-x ^} (@code{grow-window})
+@kindex C-x ^
+@findex grow-window
+Grows (or shrinks) the current window. Given a numeric argument, grows
+the current window that many lines; with a negative numeric argument,
+the window is shrunk instead.
+
+@item @code{C-x t} (@code{tile-windows})
+@cindex tiling
+@kindex C-x t
+@findex tile-windows
+Divides the available screen space among all of the visible windows.
+Each window is given an equal portion of the screen in which to display
+its contents. The variable @code{automatic-tiling} can cause
+@code{tile-windows} to be called when a window is created or deleted.
+@xref{Variables, , @code{automatic-tiling}}.
+@end table
+
+@node The Echo Area
+@section The Echo Area
+@cindex echo area
+
+The @dfn{echo area} is a one line window which appears at the bottom of
+the screen. It is used to display informative or error messages, and to
+read lines of input from you when that is necessary. Almost all of the
+commands available in the echo area are identical to their Emacs
+counterparts, so please refer to that documentation for greater depth of
+discussion on the concepts of editing a line of text. The following
+table briefly lists the commands that are available while input is being
+read in the echo area:
+
+@table @asis
+@item @code{C-f} (@code{echo-area-forward})
+@kindex C-f, in the echo area
+@findex echo-area-forward
+Moves forward a character.
+
+@item @code{C-b} (@code{echo-area-backward})
+@kindex C-b, in the echo area
+@findex echo-area-backward
+Moves backward a character.
+
+@item @code{C-a} (@code{echo-area-beg-of-line})
+@kindex C-a, in the echo area
+@findex echo-area-beg-of-line
+Moves to the start of the input line.
+
+@item @code{C-e} (@code{echo-area-end-of-line})
+@kindex C-e, in the echo area
+@findex echo-area-end-of-line
+Moves to the end of the input line.
+
+@item @code{M-f} (@code{echo-area-forward-word})
+@kindex M-f, in the echo area
+@findex echo-area-forward-word
+Moves forward a word.
+
+@item @code{M-b} (@code{echo-area-backward-word})
+@kindex M-b, in the echo area
+@findex echo-area-backward-word
+Moves backward a word.
+
+@item @code{C-d} (@code{echo-area-delete})
+@kindex C-d, in the echo area
+@findex echo-area-delete
+Deletes the character under the cursor.
+
+@item @code{DEL} (@code{echo-area-rubout})
+@kindex DEL, in the echo area
+@findex echo-area-rubout
+Deletes the character behind the cursor.
+
+@item @code{C-g} (@code{echo-area-abort})
+@kindex C-g, in the echo area
+@findex echo-area-abort
+Cancels or quits the current operation. If completion is being read,
+@samp{C-g} discards the text of the input line which does not match any
+completion. If the input line is empty, @samp{C-g} aborts the calling
+function.
+
+@item @code{RET} (@code{echo-area-newline})
+@kindex RET, in the echo area
+@findex echo-area-newline
+Accepts (or forces completion of) the current input line.
+
+@item @code{C-q} (@code{echo-area-quoted-insert})
+@kindex C-q, in the echo area
+@findex echo-area-quoted-insert
+Inserts the next character verbatim. This is how you can insert control
+characters into a search string, for example.
+
+@item @var{printing character} (@code{echo-area-insert})
+@kindex printing characters, in the echo area
+@findex echo-area-insert
+Inserts the character.
+
+@item @code{M-TAB} (@code{echo-area-tab-insert})
+@kindex M-TAB, in the echo area
+@findex echo-area-tab-insert
+Inserts a TAB character.
+
+@item @code{C-t} (@code{echo-area-transpose-chars})
+@kindex C-t, in the echo area
+@findex echo-area-transpose-chars
+Transposes the characters at the cursor.
+@end table
+
+The next group of commands deal with @dfn{killing}, and @dfn{yanking}
+text. For an in depth discussion of killing and yanking,
+@pxref{Killing, , Killing and Deleting, emacs, the GNU Emacs Manual}
+
+@table @asis
+@item @code{M-d} (@code{echo-area-kill-word})
+@kindex M-d, in the echo area
+@findex echo-area-kill-word
+Kills the word following the cursor.
+
+@item @code{M-DEL} (@code{echo-area-backward-kill-word})
+@kindex M-DEL, in the echo area
+@findex echo-area-backward-kill-word
+Kills the word preceding the cursor.
+
+@item @code{C-k} (@code{echo-area-kill-line})
+@kindex C-k, in the echo area
+@findex echo-area-kill-line
+Kills the text from the cursor to the end of the line.
+
+@item @code{C-x DEL} (@code{echo-area-backward-kill-line})
+@kindex C-x DEL, in the echo area
+@findex echo-area-backward-kill-line
+Kills the text from the cursor to the beginning of the line.
+
+@item @code{C-y} (@code{echo-area-yank})
+@kindex C-y, in the echo area
+@findex echo-area-yank
+Yanks back the contents of the last kill.
+
+@item @code{M-y} (@code{echo-area-yank-pop})
+@kindex M-y, in the echo area
+@findex echo-area-yank-pop
+Yanks back a previous kill, removing the last yanked text first.
+@end table
+
+Sometimes when reading input in the echo area, the command that needed
+input will only accept one of a list of several choices. The choices
+represent the @dfn{possible completions}, and you must respond with one
+of them. Since there are a limited number of responses you can make,
+Info allows you to abbreviate what you type, only typing as much of the
+response as is necessary to uniquely identify it. In addition, you can
+request Info to fill in as much of the response as is possible; this
+is called @dfn{completion}.
+
+The following commands are available when completing in the echo area:
+
+@table @asis
+@item @code{TAB} (@code{echo-area-complete})
+@itemx @code{SPC}
+@kindex TAB, in the echo area
+@kindex SPC, in the echo area
+@findex echo-area-complete
+Inserts as much of a completion as is possible.
+
+@item @code{?} (@code{echo-area-possible-completions})
+@kindex ?, in the echo area
+@findex echo-area-possible-completions
+Displays a window containing a list of the possible completions of what
+you have typed so far. For example, if the available choices are:
+@example
+bar
+foliate
+food
+forget
+@end example
+and you have typed an @samp{f}, followed by @samp{?}, the possible
+completions would contain:
+@example
+foliate
+food
+forget
+@end example
+i.e., all of the choices which begin with @samp{f}. Pressing @key{SPC}
+or @key{TAB} would result in @samp{fo} appearing in the echo area, since
+all of the choices which begin with @samp{f} continue with @samp{o}.
+Now, typing @samp{l} followed by @samp{TAB} results in @samp{foliate}
+appearing in the echo area, since that is the only choice which begins
+with @samp{fol}.
+
+@item @code{ESC C-v} (@code{echo-area-scroll-completions-window})
+@kindex ESC C-v, in the echo area
+@findex echo-area-scroll-completions-window
+Scrolls the completions window, if that is visible, or the "other"
+window if not.
+@end table
+
+@node Printing Nodes
+@chapter Printing Out Nodes
+@cindex printing
+
+You may wish to print out the contents of a node as a quick reference
+document for later use. Info provides you with a command for doing
+this. In general, we recommend that you use @TeX{} to format the
+document and print sections of it, by running @code{tex} on the texinfo
+source file.
+
+@table @asis
+@item @code{M-x print-node}
+@findex print-node
+@cindex INFO_PRINT_COMMAND, environment variable
+Pipes the contents of the current node through the command in the
+environment variable @code{INFO_PRINT_COMMAND}. If the variable doesn't
+exist, the node is simply piped to @code{lpr}.
+@end table
+
+@node Miscellaneous Commands
+@chapter Miscellaneous Commands
+
+GNU Info contains several commands which self-document GNU Info:
+
+@table @asis
+@item @code{M-x describe-command}
+@cindex functions, describing
+@cindex commands, describing
+@findex describe-command
+Reads the name of an Info command in the echo area and then displays a
+brief description of what that command does.
+
+@item @code{M-x describe-key}
+@cindex keys, describing
+@findex describe-key
+Reads a key sequence in the echo area, and then displays the name and
+documentation of the Info command that the key sequence invokes.
+
+@item @code{M-x describe-variable}
+Reads the name of a variable in the echo area and then displays a brief
+description of what the variable affects.
+
+@item @code{M-x where-is}
+@findex where-is
+Reads the name of an Info command in the echo area, and then displays
+a key sequence which can be typed in order to invoke that command.
+
+@item @code{C-h} (@code{get-help-window})
+@itemx @code{?}
+@kindex C-h
+@kindex ?, in Info windows
+@findex get-help-window
+Creates (or moves into) the window displaying @code{*Help*}, and places
+a node containing a quick reference card into it. This window displays
+the most concise information about GNU Info available.
+
+@item @code{h} (@code{get-info-help-node})
+@kindex h
+@findex get-info-help-node
+Tries hard to visit the node @code{(info)Help}. The info file
+@file{info.texi} distributed with GNU Info contains this node. Of
+course, the file must first be processed with @code{makeinfo}, and then
+placed into the location of your info directory.
+@end table
+
+Here are the commands for creating a numeric argument:
+
+@table @asis
+@item @code{C-u} (@code{universal-argument})
+@cindex numeric arguments
+@kindex C-u
+@findex universal-argument
+Starts (or multiplies by 4) the current numeric argument. @samp{C-u} is
+a good way to give a small numeric argument to cursor movement or
+scrolling commands; @samp{C-u C-v} scrolls the screen 4 lines, while
+@samp{C-u C-u C-n} moves the cursor down 16 lines.
+
+@item @code{M-1} (@code{add-digit-to-numeric-arg})
+@itemx @code{M-2} @dots{} @code{M-9}
+@kindex M-1 @dots{} M-9
+@findex add-digit-to-numeric-arg
+Adds the digit value of the invoking key to the current numeric
+argument. Once Info is reading a numeric argument, you may just type
+the digits of the argument, without the Meta prefix. For example, you
+might give @samp{C-l} a numeric argument of 32 by typing:
+
+@example
+@kbd{C-u 3 2 C-l}
+@end example
+or
+@example
+@kbd{M-3 2 C-l}
+@end example
+@end table
+
+@samp{C-g} is used to abort the reading of a multi-character key
+sequence, to cancel lengthy operations (such as multi-file searches) and
+to cancel reading input in the echo area.
+
+@table @asis
+@item @code{C-g} (@code{abort-key})
+@cindex cancelling typeahead
+@cindex cancelling the current operation
+@kindex C-g, in Info windows
+@findex abort-key
+Cancels current operation.
+@end table
+
+The @samp{q} command of Info simply quits running Info.
+
+@table @asis
+@item @code{q} (@code{quit})
+@cindex quitting
+@kindex q
+@findex quit
+Exits GNU Info.
+@end table
+
+If the operating system tells GNU Info that the screen is 60 lines tall,
+and it is actually only 40 lines tall, here is a way to tell Info that
+the operating system is correct.
+
+@table @asis
+@item @code{M-x set-screen-height}
+@findex set-screen-height
+@cindex screen, changing the height of
+Reads a height value in the echo area and sets the height of the
+displayed screen to that value.
+@end table
+
+Finally, Info provides a convenient way to display footnotes which might
+be associated with the current node that you are viewing:
+
+@table @asis
+@item @code{ESC C-f} (@code{show-footnotes})
+@kindex ESC C-f
+@findex show-footnotes
+@cindex footnotes, displaying
+Shows the footnotes (if any) associated with the current node in another
+window. You can have Info automatically display the footnotes
+associated with a node when the node is selected by setting the variable
+@code{automatic-footnotes}. @xref{Variables, , @code{automatic-footnotes}}.
+@end table
+
+@node Variables
+@chapter Manipulating Variables
+
+GNU Info contains several @dfn{variables} whose values are looked at by various
+Info commands. You can change the values of these variables, and thus
+change the behaviour of Info to more closely match your environment and
+info file reading manner.
+
+@table @asis
+@item @code{M-x set-variable}
+@cindex variables, setting
+@findex set-variable
+Reads the name of a variable, and the value for it, in the echo area and
+then sets the variable to that value. Completion is available when
+reading the variable name; often, completion is available when reading
+the value to give to the variable, but that depends on the variable
+itself. If a variable does @emph{not} supply multiple choices to
+complete over, it expects a numeric value.
+
+@item @code{M-x describe-variable}
+@cindex variables, describing
+@findex describe-variable
+Reads the name of a variable in the echo area and then displays a brief
+description of what the variable affects.
+@end table
+
+Here is a list of the variables that you can set in Info.
+
+@table @code
+@item automatic-footnotes
+@vindex automatic-footnotes
+When set to @code{On}, footnotes appear and disappear automatically.
+This variable is @code{On} by default. When a node is selected, a
+window containing the footnotes which appear in that node is created,
+and the footnotes are displayed within the new window. The window that
+Info creates to contain the footnotes is called @samp{*Footnotes*}. If
+a node is selected which contains no footnotes, and a @samp{*Footnotes*}
+window is on the screen, the @samp{*Footnotes*} window is deleted.
+Footnote windows created in this fashion are not automatically tiled so
+that they can use as little of the display as is possible.
+
+@item automatic-tiling
+@vindex automatic-tiling
+When set to @code{On}, creating or deleting a window resizes other
+windows. This variable is @code{Off} by default. Normally, typing
+@samp{C-x 2} divides the current window into two equal parts. When
+@code{automatic-tiling} is set to @code{On}, all of the windows are
+resized automatically, keeping an equal number of lines visible in each
+window. There are exceptions to the automatic tiling; specifically, the
+windows @samp{*Completions*} and @samp{*Footnotes*} are @emph{not}
+resized through automatic tiling; they remain their original size.
+
+@item visible-bell
+@vindex visible-bell
+When set to @code{On}, GNU Info attempts to flash the screen instead of
+ringing the bell. This variable is @code{Off} by default. Of course,
+Info can only flash the screen if the terminal allows it; in the case
+that the terminal does not allow it, the setting of this variable has no
+effect. However, you can make Info perform quietly by setting the
+@code{errors-ring-bell} variable to @code{Off}.
+
+@item errors-ring-bell
+@vindex errors-ring-bell
+When set to @code{On}, errors cause the bell to ring. The default
+setting of this variable is @code{On}.
+
+@item gc-compressed-files
+@vindex gc-compressed-files
+When set to @code{On}, Info garbage collects files which had to be
+uncompressed. The default value of this variable is @code{Off}.
+Whenever a node is visited in Info, the info file containing that node
+is read into core, and Info reads information about the tags and nodes
+contained in that file. Once the tags information is read by Info, it
+is never forgotten. However, the actual text of the nodes does not need
+to remain in core unless a particular info window needs it. For
+non-compressed files, the text of the nodes does not remain in core when
+it is no longer in use. But de-compressing a file can be a time
+consuming operation, and so Info tries hard not to do it twice.
+@code{gc-compressed-files} tells Info it is okay to garbage collect the
+text of the nodes of a file which was compressed on disk.
+
+@item show-index-match
+@vindex show-index-match
+When set to @code{On}, the portion of the matched search string is
+highlighted in the message which explains where the matched search
+string was found. The default value of this variable is @code{On}.
+When Info displays the location where an index match was found,
+(@pxref{Searching Commands, , @code{next-index-match}}), the portion of the
+string that you had typed is highlighted by displaying it in the inverse
+case from its surrounding characters.
+
+@item scroll-behaviour
+@vindex scroll-behaviour
+Controls what happens when forward scrolling is requested at the end of
+a node, or when backward scrolling is requested at the beginning of a
+node. The default value for this variable is @code{Continuous}. There
+are three possible values for this variable:
+
+@table @code
+@item Continuous
+Tries to get the first item in this node's menu, or failing that, the
+@samp{Next} node, or failing that, the @samp{Next} of the @samp{Up}.
+This behaviour is identical to using the @samp{]}
+(@code{global-next-node}) and @samp{[} (@code{global-prev-node})
+commands.
+
+@item Next Only
+Only tries to get the @samp{Next} node.
+
+@item Page Only
+Simply gives up, changing nothing. If @code{scroll-behaviour} is
+@code{Page Only}, no scrolling command can change the node that is being
+viewed.
+@end table
+
+@item scroll-step
+@vindex scroll-step
+The number of lines to scroll when the cursor moves out of the window.
+Scrolling happens automatically if the cursor has moved out of the
+visible portion of the node text when it is time to display. Usually
+the scrolling is done so as to put the cursor on the center line of the
+current window. However, if the variable @code{scroll-step} has a
+nonzero value, Info attempts to scroll the node text by that many lines;
+if that is enough to bring the cursor back into the window, that is what
+is done. The default value of this variable is 0, thus placing the
+cursor (and the text it is attached to) in the center of the window.
+Setting this variable to 1 causes a kind of "smooth scrolling" which
+some people prefer.
+
+@item ISO-Latin
+@cindex ISO Latin characters
+@vindex ISO-Latin
+When set to @code{On}, Info accepts and displays ISO Latin characters.
+By default, Info assumes an ASCII character set. @code{ISO-Latin} tells
+Info that it is running in an environment where the European standard
+character set is in use, and allows you to input such characters to
+Info, as well as display them.
+@end table
+
+@c The following node and its children are currently unfinished. Please feel
+@c free to finish it!
+
+@ifset NOTSET
+@node Info for Sys Admins
+@chapter Info for System Administrators
+
+This text describes some common ways of setting up an Info heierarchy
+from scratch, and details the various options that are available when
+installing Info. This text is designed for the person who is installing
+GNU Info on the system; although users may find the information present
+in this section interesting, none of it is vital to understanding how to
+use GNU Info.
+
+@menu
+* Setting the INFOPATH:: Where are my Info files kept?
+* Editing the DIR node:: What goes in `DIR', and why?
+* Storing Info files:: Alternate formats allow flexibilty in setups.
+* Using `localdir':: Building DIR on the fly.
+* Example setups:: Some common ways to origanize Info files.
+@end menu
+
+@node Setting the INFOPATH
+@section Setting the INFOPATH
+Where are my Info files kept?
+
+@node Editing the DIR node
+@section Editing the DIR node
+What goes in `DIR', and why?
+
+@node Storing Info files
+@section Storing Info files
+Alternate formats allow flexibilty in setups.
+
+@node Using `localdir'
+@section Using `localdir'
+Building DIR on the fly.
+
+@node Example setups
+@section Example setups
+Some common ways to origanize Info files.
+@end ifset
+
+@ifset STANDALONE
+@node GNU Info Global Index
+@appendix Global Index
+@printindex cp
+@end ifset
diff --git a/contrib/texinfo/info/variables.c b/contrib/texinfo/info/variables.c
new file mode 100644
index 0000000..7798701
--- /dev/null
+++ b/contrib/texinfo/info/variables.c
@@ -0,0 +1,272 @@
+/* variables.c -- How to manipulate user visible variables in Info. */
+
+/* This file is part of GNU Info, a program for reading online documentation
+ stored in Info format.
+
+ Copyright (C) 1993 Free Software Foundation, Inc.
+
+ 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Written by Brian Fox (bfox@ai.mit.edu). */
+
+#include "info.h"
+#include "variables.h"
+
+/* **************************************************************** */
+/* */
+/* User Visible Variables in Info */
+/* */
+/* **************************************************************** */
+
+/* Choices used by the completer when reading a zero/non-zero value for
+ a variable. */
+static char *on_off_choices[] = { "Off", "On", (char *)NULL };
+
+VARIABLE_ALIST info_variables[] = {
+ { "automatic-footnotes",
+ "When \"On\", footnotes appear and disappear automatically",
+ &auto_footnotes_p, (char **)on_off_choices },
+
+ { "automatic-tiling",
+ "When \"On\", creating or deleting a window resizes other windows",
+ &auto_tiling_p, (char **)on_off_choices },
+
+ { "visible-bell",
+ "When \"On\", flash the screen instead of ringing the bell",
+ &terminal_use_visible_bell_p, (char **)on_off_choices },
+
+ { "errors-ring-bell",
+ "When \"On\", errors cause the bell to ring",
+ &info_error_rings_bell_p, (char **)on_off_choices },
+
+ { "gc-compressed-files",
+ "When \"On\", Info garbage collects files which had to be uncompressed",
+ &gc_compressed_files, (char **)on_off_choices },
+ { "show-index-match",
+ "When \"On\", the portion of the matched search string is highlighted",
+ &show_index_match, (char **)on_off_choices },
+
+ { "scroll-behaviour",
+ "Controls what happens when scrolling is requested at the end of a node",
+ &info_scroll_behaviour, (char **)info_scroll_choices },
+
+ { "scroll-step",
+ "The number lines to scroll when the cursor moves out of the window",
+ &window_scroll_step, (char **)NULL },
+
+ { "ISO-Latin",
+ "When \"On\", Info accepts and displays ISO Latin characters",
+ &ISO_Latin_p, (char **)on_off_choices },
+
+ { (char *)NULL, (char *)NULL, (int *)NULL, (char **)NULL }
+};
+
+DECLARE_INFO_COMMAND (describe_variable, "Explain the use of a variable")
+{
+ VARIABLE_ALIST *var;
+ char *description;
+
+ /* Get the variable's name. */
+ var = read_variable_name ("Describe variable: ", window);
+
+ if (!var)
+ return;
+
+ description = (char *)xmalloc (20 + strlen (var->name) + strlen (var->doc));
+
+ if (var->choices)
+ sprintf (description, "%s (%s): %s.",
+ var->name, var->choices[*(var->value)], var->doc);
+ else
+ sprintf (description, "%s (%d): %s.", var->name, *(var->value), var->doc);
+
+ window_message_in_echo_area ("%s", description);
+ free (description);
+}
+
+DECLARE_INFO_COMMAND (set_variable, "Set the value of an Info variable")
+{
+ VARIABLE_ALIST *var;
+ char *line;
+
+ /* Get the variable's name and value. */
+ var = read_variable_name ("Set variable: ", window);
+
+ if (!var)
+ return;
+
+ /* Read a new value for this variable. */
+ {
+ char prompt[100];
+
+ if (!var->choices)
+ {
+ int potential_value;
+
+ if (info_explicit_arg || count != 1)
+ potential_value = count;
+ else
+ potential_value = *(var->value);
+
+ sprintf (prompt, "Set %s to value (%d): ",
+ var->name, potential_value);
+ line = info_read_in_echo_area (active_window, prompt);
+
+ /* If no error was printed, clear the echo area. */
+ if (!info_error_was_printed)
+ window_clear_echo_area ();
+
+ /* User aborted? */
+ if (!line)
+ return;
+
+ /* If the user specified a value, get that, otherwise, we are done. */
+ canonicalize_whitespace (line);
+ if (*line)
+ *(var->value) = atoi (line);
+ else
+ *(var->value) = potential_value;
+
+ free (line);
+ }
+ else
+ {
+ register int i;
+ REFERENCE **array = (REFERENCE **)NULL;
+ int array_index = 0;
+ int array_slots = 0;
+
+ for (i = 0; var->choices[i]; i++)
+ {
+ REFERENCE *entry;
+
+ entry = (REFERENCE *)xmalloc (sizeof (REFERENCE));
+ entry->label = strdup (var->choices[i]);
+ entry->nodename = (char *)NULL;
+ entry->filename = (char *)NULL;
+
+ add_pointer_to_array
+ (entry, array_index, array, array_slots, 10, REFERENCE *);
+ }
+
+ sprintf (prompt, "Set %s to value (%s): ",
+ var->name, var->choices[*(var->value)]);
+
+ /* Ask the completer to read a variable value for us. */
+ line = info_read_completing_in_echo_area (window, prompt, array);
+
+ info_free_references (array);
+
+ if (!echo_area_is_active)
+ window_clear_echo_area ();
+
+ /* User aborted? */
+ if (!line)
+ {
+ info_abort_key (active_window, 0, 0);
+ return;
+ }
+
+ /* User accepted default choice? If so, no change. */
+ if (!*line)
+ {
+ free (line);
+ return;
+ }
+
+ /* Find the choice in our list of choices. */
+ for (i = 0; var->choices[i]; i++)
+ if (strcmp (var->choices[i], line) == 0)
+ break;
+
+ if (var->choices[i])
+ *(var->value) = i;
+ }
+ }
+}
+
+/* Read the name of an Info variable in the echo area and return the
+ address of a VARIABLE_ALIST member. A return value of NULL indicates
+ that no variable could be read. */
+VARIABLE_ALIST *
+read_variable_name (prompt, window)
+ char *prompt;
+ WINDOW *window;
+{
+ register int i;
+ char *line;
+ REFERENCE **variables;
+
+ /* Get the completion array of variable names. */
+ variables = make_variable_completions_array ();
+
+ /* Ask the completer to read a variable for us. */
+ line =
+ info_read_completing_in_echo_area (window, prompt, variables);
+
+ info_free_references (variables);
+
+ if (!echo_area_is_active)
+ window_clear_echo_area ();
+
+ /* User aborted? */
+ if (!line)
+ {
+ info_abort_key (active_window, 0, 0);
+ return ((VARIABLE_ALIST *)NULL);
+ }
+
+ /* User accepted "default"? (There is none.) */
+ if (!*line)
+ {
+ free (line);
+ return ((VARIABLE_ALIST *)NULL);
+ }
+
+ /* Find the variable in our list of variables. */
+ for (i = 0; info_variables[i].name; i++)
+ if (strcmp (info_variables[i].name, line) == 0)
+ break;
+
+ if (!info_variables[i].name)
+ return ((VARIABLE_ALIST *)NULL);
+ else
+ return (&(info_variables[i]));
+}
+
+/* Make an array of REFERENCE which actually contains the names of the
+ variables available in Info. */
+REFERENCE **
+make_variable_completions_array ()
+{
+ register int i;
+ REFERENCE **array = (REFERENCE **)NULL;
+ int array_index = 0, array_slots = 0;
+
+ for (i = 0; info_variables[i].name; i++)
+ {
+ REFERENCE *entry;
+
+ entry = (REFERENCE *)xmalloc (sizeof (REFERENCE));
+ entry->label = strdup (info_variables[i].name);
+ entry->nodename = (char *)NULL;
+ entry->filename = (char *)NULL;
+
+ add_pointer_to_array
+ (entry, array_index, array, array_slots, 200, REFERENCE *);
+ }
+
+ return (array);
+}
diff --git a/contrib/texinfo/info/variables.h b/contrib/texinfo/info/variables.h
new file mode 100644
index 0000000..85bde27
--- /dev/null
+++ b/contrib/texinfo/info/variables.h
@@ -0,0 +1,64 @@
+/* variables.h -- Description of user visible variables in Info. */
+
+/* This file is part of GNU Info, a program for reading online documentation
+ stored in Info format.
+
+ Copyright (C) 1993 Free Software Foundation, Inc.
+
+ 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Written by Brian Fox (bfox@ai.mit.edu). */
+
+#if !defined (_VARIABLES_H_)
+#define _VARIABLES_H_
+
+/* A variable (in the Info sense) is an integer value with a user-visible
+ name. You may supply an array of strings to complete over when the
+ variable is set; in that case, the variable is set to the index of the
+ string that the user chose. If you supply a null list, the user can
+ set the variable to a numeric value. */
+
+/* Structure describing a user visible variable. */
+typedef struct {
+ char *name; /* Polite name. */
+ char *doc; /* Documentation string. */
+ int *value; /* Address of value. */
+ char **choices; /* Array of strings or NULL if numeric only. */
+} VARIABLE_ALIST;
+
+/* Read the name of an Info variable in the echo area and return the
+ address of a VARIABLE_ALIST member. A return value of NULL indicates
+ that no variable could be read. */
+extern VARIABLE_ALIST *read_variable_name ();
+
+/* Make an array of REFERENCE which actually contains the names of the
+ variables available in Info. */
+extern REFERENCE **make_variable_completions_array ();
+
+/* Set the value of an info variable. */
+extern void set_variable ();
+
+/* The list of user-visible variables. */
+extern int auto_footnotes_p;
+extern int auto_tiling_p;
+extern int terminal_use_visible_bell_p;
+extern int info_error_rings_bell_p;
+extern int gc_compressed_files;
+extern int show_index_match;
+extern int info_scroll_behaviour;
+extern int window_scroll_step;
+extern int ISO_Latin_p;
+
+#endif /* _VARIABLES_H_ */
diff --git a/contrib/texinfo/info/window.c b/contrib/texinfo/info/window.c
new file mode 100644
index 0000000..304e89c
--- /dev/null
+++ b/contrib/texinfo/info/window.c
@@ -0,0 +1,1482 @@
+/* window.c -- Windows in Info. */
+
+/* This file is part of GNU Info, a program for reading online documentation
+ stored in Info format.
+
+ Copyright (C) 1993 Free Software Foundation, Inc.
+
+ 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Written by Brian Fox (bfox@ai.mit.edu). */
+
+#include <stdio.h>
+#include <ctype.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include "nodes.h"
+#include "window.h"
+#include "display.h"
+#include "info-utils.h"
+#include "infomap.h"
+
+/* The window which describes the screen. */
+WINDOW *the_screen = (WINDOW *)NULL;
+
+/* The window which describes the echo area. */
+WINDOW *the_echo_area = (WINDOW *)NULL;
+
+/* The list of windows in Info. */
+WINDOW *windows = (WINDOW *)NULL;
+
+/* Pointer to the active window in WINDOW_LIST. */
+WINDOW *active_window = (WINDOW *)NULL;
+
+/* The size of the echo area in Info. It never changes, irregardless of the
+ size of the screen. */
+#define ECHO_AREA_HEIGHT 1
+
+/* Macro returns the amount of space that the echo area truly requires relative
+ to the entire screen. */
+#define echo_area_required (1 + the_echo_area->height)
+
+/* Initalize the window system by creating THE_SCREEN and THE_ECHO_AREA.
+ Create the first window ever.
+ You pass the dimensions of the total screen size. */
+void
+window_initialize_windows (width, height)
+ int width, height;
+{
+ the_screen = (WINDOW *)xmalloc (sizeof (WINDOW));
+ the_echo_area = (WINDOW *)xmalloc (sizeof (WINDOW));
+ windows = (WINDOW *)xmalloc (sizeof (WINDOW));
+ active_window = windows;
+
+ zero_mem (the_screen, sizeof (WINDOW));
+ zero_mem (the_echo_area, sizeof (WINDOW));
+ zero_mem (active_window, sizeof (WINDOW));
+
+ /* None of these windows has a goal column yet. */
+ the_echo_area->goal_column = -1;
+ active_window->goal_column = -1;
+ the_screen->goal_column = -1;
+
+ /* The active and echo_area windows are visible.
+ The echo_area is permanent.
+ The screen is permanent. */
+ active_window->flags = W_WindowVisible;
+ the_echo_area->flags = W_WindowIsPerm | W_InhibitMode | W_WindowVisible;
+ the_screen->flags = W_WindowIsPerm;
+
+ /* The height of the echo area never changes. It is statically set right
+ here, and it must be at least 1 line for display. The size of the
+ initial window cannot be the same size as the screen, since the screen
+ includes the echo area. So, we make the height of the initial window
+ equal to the screen's displayable region minus the height of the echo
+ area. */
+ the_echo_area->height = ECHO_AREA_HEIGHT;
+ active_window->height = the_screen->height - 1 - the_echo_area->height;
+ window_new_screen_size (width, height, (VFunction *)NULL);
+
+ /* The echo area uses a different keymap than normal info windows. */
+ the_echo_area->keymap = echo_area_keymap;
+ active_window->keymap = info_keymap;
+}
+
+/* Given that the size of the screen has changed to WIDTH and HEIGHT
+ from whatever it was before (found in the_screen->height, ->width),
+ change the size (and possibly location) of each window in the screen.
+ If a window would become too small, call the function DELETER on it,
+ after deleting the window from our chain of windows. If DELETER is NULL,
+ nothing extra is done. The last window can never be deleted, but it can
+ become invisible. */
+
+/* If non-null, a function to call with WINDOW as argument when the function
+ window_new_screen_size () has deleted WINDOW. */
+VFunction *window_deletion_notifier = (VFunction *)NULL;
+
+void
+window_new_screen_size (width, height)
+ int width, height;
+{
+ register WINDOW *win;
+ int delta_height, delta_each, delta_leftover;
+ int numwins;
+
+ /* If no change, do nothing. */
+ if (width == the_screen->width && height == the_screen->height)
+ return;
+
+ /* If the new window height is too small, make it be zero. */
+ if (height < (WINDOW_MIN_SIZE + the_echo_area->height))
+ height = 0;
+ if (width < 0)
+ width = 0;
+
+ /* Find out how many windows will change. */
+ for (numwins = 0, win = windows; win; win = win->next, numwins++);
+
+ /* See if some windows will need to be deleted. This is the case if
+ the screen is getting smaller, and the available space divided by
+ the number of windows is less than WINDOW_MIN_SIZE. In that case,
+ delete some windows and try again until there is either enough
+ space to divy up among the windows, or until there is only one
+ window left. */
+ while ((height - echo_area_required) / numwins <= WINDOW_MIN_SIZE)
+ {
+ /* If only one window, make the size of it be zero, and return
+ immediately. */
+ if (!windows->next)
+ {
+ windows->height = 0;
+ maybe_free (windows->line_starts);
+ windows->line_starts = (char **)NULL;
+ windows->line_count = 0;
+ break;
+ }
+
+ /* If we have some temporary windows, delete one of them. */
+ for (win = windows; win; win = win->next)
+ if (win->flags & W_TempWindow)
+ break;
+
+ /* Otherwise, delete the first window, and try again. */
+ if (!win)
+ win = windows;
+
+ if (window_deletion_notifier)
+ (*window_deletion_notifier) (win);
+
+ window_delete_window (win);
+ numwins--;
+ }
+
+ /* The screen has changed height and width. */
+ delta_height = height - the_screen->height; /* This is how much. */
+ the_screen->height = height; /* This is the new height. */
+ the_screen->width = width; /* This is the new width. */
+
+ /* Set the start of the echo area. */
+ the_echo_area->first_row = height - the_echo_area->height;
+ the_echo_area->width = width;
+
+ /* Check to see if the screen can really be changed this way. */
+ if ((!windows->next) && ((windows->height == 0) && (delta_height < 0)))
+ return;
+
+ /* Divide the change in height among the available windows. */
+ delta_each = delta_height / numwins;
+ delta_leftover = delta_height - (delta_each * numwins);
+
+ /* Change the height of each window in the chain by delta_each. Change
+ the height of the last window in the chain by delta_each and by the
+ leftover amount of change. Change the width of each window to be
+ WIDTH. */
+ for (win = windows; win; win = win->next)
+ {
+ if ((win->width != width) && ((win->flags & W_InhibitMode) == 0))
+ {
+ win->width = width;
+ maybe_free (win->modeline);
+ win->modeline = (char *)xmalloc (1 + width);
+ }
+
+ win->height += delta_each;
+
+ /* If the previous height of this window was zero, it was the only
+ window, and it was not visible. Thus we need to compensate for
+ the echo_area. */
+ if (win->height == delta_each)
+ win->height -= (1 + the_echo_area->height);
+
+ /* If this is not the first window in the chain, then change the
+ first row of it. We cannot just add delta_each to the first row,
+ since this window's first row is the sum of the collective increases
+ that have gone before it. So we just add one to the location of the
+ previous window's modeline. */
+ if (win->prev)
+ win->first_row = (win->prev->first_row + win->prev->height) + 1;
+
+ /* The last window in the chain gets the extra space (or shrinkage). */
+ if (!win->next)
+ win->height += delta_leftover;
+
+ if (win->node)
+ recalculate_line_starts (win);
+
+ win->flags |= W_UpdateWindow;
+ }
+
+ /* If the screen got smaller, check over the windows just shrunk to
+ keep them within bounds. Some of the windows may have gotten smaller
+ than WINDOW_MIN_HEIGHT in which case some of the other windows are
+ larger than the available display space in the screen. Because of our
+ intial test above, we know that there is enough space for all of the
+ windows. */
+ if ((delta_each < 0) && ((windows->height != 0) && windows->next))
+ {
+ int avail;
+
+ avail = the_screen->height - (numwins + the_echo_area->height);
+ win = windows;
+
+ while (win)
+ {
+ if ((win->height < WINDOW_MIN_HEIGHT) ||
+ (win->height > avail))
+ {
+ WINDOW *lastwin;
+
+ /* Split the space among the available windows. */
+ delta_each = avail / numwins;
+ delta_leftover = avail - (delta_each * numwins);
+
+ for (win = windows; win; win = win->next)
+ {
+ lastwin = win;
+ if (win->prev)
+ win->first_row =
+ (win->prev->first_row + win->prev->height) + 1;
+ win->height = delta_each;
+ }
+
+ /* Give the leftover space (if any) to the last window. */
+ lastwin->height += delta_leftover;
+ break;
+ }
+ else
+ win= win->next;
+ }
+ }
+}
+
+/* Make a new window showing NODE, and return that window structure.
+ If NODE is passed as NULL, then show the node showing in the active
+ window. If the window could not be made return a NULL pointer. The
+ active window is not changed.*/
+WINDOW *
+window_make_window (node)
+ NODE *node;
+{
+ WINDOW *window;
+
+ if (!node)
+ node = active_window->node;
+
+ /* If there isn't enough room to make another window, return now. */
+ if ((active_window->height / 2) < WINDOW_MIN_SIZE)
+ return ((WINDOW *)NULL);
+
+ /* Make and initialize the new window.
+ The fudging about with -1 and +1 is because the following window in the
+ chain cannot start at window->height, since that is where the modeline
+ for the previous window is displayed. The inverse adjustment is made
+ in window_delete_window (). */
+ window = (WINDOW *)xmalloc (sizeof (WINDOW));
+ window->width = the_screen->width;
+ window->height = (active_window->height / 2) - 1;
+#if defined (SPLIT_BEFORE_ACTIVE)
+ window->first_row = active_window->first_row;
+#else
+ window->first_row = active_window->first_row +
+ (active_window->height - window->height);
+#endif
+ window->keymap = info_keymap;
+ window->goal_column = -1;
+ window->modeline = (char *)xmalloc (1 + window->width);
+ window->line_starts = (char **)NULL;
+ window->flags = W_UpdateWindow | W_WindowVisible;
+ window_set_node_of_window (window, node);
+
+ /* Adjust the height of the old active window. */
+ active_window->height -= (window->height + 1);
+#if defined (SPLIT_BEFORE_ACTIVE)
+ active_window->first_row += (window->height + 1);
+#endif
+ active_window->flags |= W_UpdateWindow;
+
+ /* Readjust the new and old windows so that their modelines and contents
+ will be displayed correctly. */
+#if defined (NOTDEF)
+ /* We don't have to do this for WINDOW since window_set_node_of_window ()
+ already did. */
+ window_adjust_pagetop (window);
+ window_make_modeline (window);
+#endif /* NOTDEF */
+
+ /* We do have to readjust the existing active window. */
+ window_adjust_pagetop (active_window);
+ window_make_modeline (active_window);
+
+#if defined (SPLIT_BEFORE_ACTIVE)
+ /* This window is just before the active one. The active window gets
+ bumped down one. The active window is not changed. */
+ window->next = active_window;
+
+ window->prev = active_window->prev;
+ active_window->prev = window;
+
+ if (window->prev)
+ window->prev->next = window;
+ else
+ windows = window;
+#else
+ /* This window is just after the active one. Which window is active is
+ not changed. */
+ window->prev = active_window;
+ window->next = active_window->next;
+ active_window->next = window;
+ if (window->next)
+ window->next->prev = window;
+#endif /* !SPLIT_BEFORE_ACTIVE */
+ return (window);
+}
+
+/* These useful macros make it possible to read the code in
+ window_change_window_height (). */
+#define grow_me_shrinking_next(me, next, diff) \
+ do { \
+ me->height += diff; \
+ next->height -= diff; \
+ next->first_row += diff; \
+ window_adjust_pagetop (next); \
+ } while (0)
+
+#define grow_me_shrinking_prev(me, prev, diff) \
+ do { \
+ me->height += diff; \
+ prev->height -= diff; \
+ me->first_row -=diff; \
+ window_adjust_pagetop (prev); \
+ } while (0)
+
+#define shrink_me_growing_next(me, next, diff) \
+ do { \
+ me->height -= diff; \
+ next->height += diff; \
+ next->first_row -= diff; \
+ window_adjust_pagetop (next); \
+ } while (0)
+
+#define shrink_me_growing_prev(me, prev, diff) \
+ do { \
+ me->height -= diff; \
+ prev->height += diff; \
+ me->first_row += diff; \
+ window_adjust_pagetop (prev); \
+ } while (0)
+
+/* Change the height of WINDOW by AMOUNT. This also automagically adjusts
+ the previous and next windows in the chain. If there is only one user
+ window, then no change takes place. */
+void
+window_change_window_height (window, amount)
+ WINDOW *window;
+ int amount;
+{
+ register WINDOW *win, *prev, *next;
+
+ /* If there is only one window, or if the amount of change is zero,
+ return immediately. */
+ if (!windows->next || amount == 0)
+ return;
+
+ /* Find this window in our chain. */
+ for (win = windows; win; win = win->next)
+ if (win == window)
+ break;
+
+ /* If the window is isolated (i.e., doesn't appear in our window list,
+ then quit now. */
+ if (!win)
+ return;
+
+ /* Change the height of this window by AMOUNT, if that is possible.
+ It can be impossible if there isn't enough available room on the
+ screen, or if the resultant window would be too small. */
+
+ prev = window->prev;
+ next = window->next;
+
+ /* WINDOW decreasing in size? */
+ if (amount < 0)
+ {
+ int abs_amount = -amount; /* It is easier to deal with this way. */
+
+ /* If the resultant window would be too small, stop here. */
+ if ((window->height - abs_amount) < WINDOW_MIN_HEIGHT)
+ return;
+
+ /* If we have two neighboring windows, choose the smaller one to get
+ larger. */
+ if (next && prev)
+ {
+ if (prev->height < next->height)
+ shrink_me_growing_prev (window, prev, abs_amount);
+ else
+ shrink_me_growing_next (window, next, abs_amount);
+ }
+ else if (next)
+ shrink_me_growing_next (window, next, abs_amount);
+ else
+ shrink_me_growing_prev (window, prev, abs_amount);
+ }
+
+ /* WINDOW increasing in size? */
+ if (amount > 0)
+ {
+ int total_avail, next_avail = 0, prev_avail = 0;
+
+ if (next)
+ next_avail = next->height - WINDOW_MIN_SIZE;
+
+ if (prev)
+ prev_avail = prev->height - WINDOW_MIN_SIZE;
+
+ total_avail = next_avail + prev_avail;
+
+ /* If there isn't enough space available to grow this window, give up. */
+ if (amount > total_avail)
+ return;
+
+ /* If there aren't two neighboring windows, or if one of the neighbors
+ is larger than the other one by at least AMOUNT, grow that one. */
+ if ((next && !prev) || ((next_avail - amount) >= prev_avail))
+ grow_me_shrinking_next (window, next, amount);
+ else if ((prev && !next) || ((prev_avail - amount) >= next_avail))
+ grow_me_shrinking_prev (window, prev, amount);
+ else
+ {
+ int change;
+
+ /* This window has two neighbors. They both must be shrunk in to
+ make enough space for WINDOW to grow. Make them both the same
+ size. */
+ if (prev_avail > next_avail)
+ {
+ change = prev_avail - next_avail;
+ grow_me_shrinking_prev (window, prev, change);
+ amount -= change;
+ }
+ else
+ {
+ change = next_avail - prev_avail;
+ grow_me_shrinking_next (window, next, change);
+ amount -= change;
+ }
+
+ /* Both neighbors are the same size. Split the difference in
+ AMOUNT between them. */
+ while (amount)
+ {
+ window->height++;
+ amount--;
+
+ /* Odd numbers grow next, even grow prev. */
+ if (amount & 1)
+ {
+ prev->height--;
+ window->first_row--;
+ }
+ else
+ {
+ next->height--;
+ next->first_row++;
+ }
+ }
+ window_adjust_pagetop (prev);
+ window_adjust_pagetop (next);
+ }
+ }
+ if (prev)
+ prev->flags |= W_UpdateWindow;
+
+ if (next)
+ next->flags |= W_UpdateWindow;
+
+ window->flags |= W_UpdateWindow;
+ window_adjust_pagetop (window);
+}
+
+/* Tile all of the windows currently displayed in the global variable
+ WINDOWS. If argument STYLE is TILE_INTERNALS, tile windows displaying
+ internal nodes as well, otherwise do not change the height of such
+ windows. */
+void
+window_tile_windows (style)
+ int style;
+{
+ WINDOW *win, *last_adjusted;
+ int numwins, avail, per_win_height, leftover;
+ int do_internals;
+
+ numwins = avail = 0;
+ do_internals = (style == TILE_INTERNALS);
+
+ for (win = windows; win; win = win->next)
+ if (do_internals || !win->node ||
+ (win->node->flags & N_IsInternal) == 0)
+ {
+ avail += win->height;
+ numwins++;
+ }
+
+ if (numwins <= 1 || !the_screen->height)
+ return;
+
+ /* Find the size for each window. Divide the size of the usable portion
+ of the screen by the number of windows. */
+ per_win_height = avail / numwins;
+ leftover = avail - (per_win_height * numwins);
+
+ last_adjusted = (WINDOW *)NULL;
+ for (win = windows; win; win = win->next)
+ {
+ if (do_internals || !win->node ||
+ (win->node->flags & N_IsInternal) == 0)
+ {
+ last_adjusted = win;
+ win->height = per_win_height;
+ }
+ }
+
+ if (last_adjusted)
+ last_adjusted->height += leftover;
+
+ /* Readjust the first_row of every window in the chain. */
+ for (win = windows; win; win = win->next)
+ {
+ if (win->prev)
+ win->first_row = win->prev->first_row + win->prev->height + 1;
+
+ window_adjust_pagetop (win);
+ win->flags |= W_UpdateWindow;
+ }
+}
+
+/* Toggle the state of line wrapping in WINDOW. This can do a bit of fancy
+ redisplay. */
+void
+window_toggle_wrap (window)
+ WINDOW *window;
+{
+ if (window->flags & W_NoWrap)
+ window->flags &= ~W_NoWrap;
+ else
+ window->flags |= W_NoWrap;
+
+ if (window != the_echo_area)
+ {
+ char **old_starts;
+ int old_lines, old_pagetop;
+
+ old_starts = window->line_starts;
+ old_lines = window->line_count;
+ old_pagetop = window->pagetop;
+
+ calculate_line_starts (window);
+
+ /* Make sure that point appears within this window. */
+ window_adjust_pagetop (window);
+
+ /* If the pagetop hasn't changed maybe we can do some scrolling now
+ to speed up the display. Many of the line starts will be the same,
+ so scrolling here is a very good optimization.*/
+ if (old_pagetop == window->pagetop)
+ display_scroll_line_starts
+ (window, old_pagetop, old_starts, old_lines);
+ maybe_free (old_starts);
+ }
+ window->flags |= W_UpdateWindow;
+}
+
+/* Set WINDOW to display NODE. */
+void
+window_set_node_of_window (window, node)
+ WINDOW *window;
+ NODE *node;
+{
+ window->node = node;
+ window->pagetop = 0;
+ window->point = 0;
+ recalculate_line_starts (window);
+ window->flags |= W_UpdateWindow;
+ window_adjust_pagetop (window);
+ window_make_modeline (window);
+}
+
+/* Delete WINDOW from the list of known windows. If this window was the
+ active window, make the next window in the chain be the active window.
+ If the active window is the next or previous window, choose that window
+ as the recipient of the extra space. Otherwise, prefer the next window. */
+void
+window_delete_window (window)
+ WINDOW *window;
+{
+ WINDOW *next, *prev, *window_to_fix;
+
+ next = window->next;
+ prev = window->prev;
+
+ /* You cannot delete the only window or a permanent window. */
+ if ((!next && !prev) || (window->flags & W_WindowIsPerm))
+ return;
+
+ if (next)
+ next->prev = prev;
+
+ if (!prev)
+ windows = next;
+ else
+ prev->next = next;
+
+ if (window->line_starts)
+ free (window->line_starts);
+
+ if (window->modeline)
+ free (window->modeline);
+
+ if (window == active_window)
+ {
+ /* If there isn't a next window, then there must be a previous one,
+ since we cannot delete the last window. If there is a next window,
+ prefer to use that as the active window. */
+ if (next)
+ active_window = next;
+ else
+ active_window = prev;
+ }
+
+ if (next && active_window == next)
+ window_to_fix = next;
+ else if (prev && active_window == prev)
+ window_to_fix = prev;
+ else if (next)
+ window_to_fix = next;
+ else if (prev)
+ window_to_fix = prev;
+ else
+ window_to_fix = windows;
+
+ if (window_to_fix->first_row > window->first_row)
+ {
+ int diff;
+
+ /* Try to adjust the visible part of the node so that as little
+ text as possible has to move. */
+ diff = window_to_fix->first_row - window->first_row;
+ window_to_fix->first_row = window->first_row;
+
+ window_to_fix->pagetop -= diff;
+ if (window_to_fix->pagetop < 0)
+ window_to_fix->pagetop = 0;
+ }
+
+ /* The `+ 1' is to offset the difference between the first_row locations.
+ See the code in window_make_window (). */
+ window_to_fix->height += window->height + 1;
+ window_to_fix->flags |= W_UpdateWindow;
+
+ free (window);
+}
+
+/* For every window in CHAIN, set the flags member to have FLAG set. */
+void
+window_mark_chain (chain, flag)
+ WINDOW *chain;
+ int flag;
+{
+ register WINDOW *win;
+
+ for (win = chain; win; win = win->next)
+ win->flags |= flag;
+}
+
+/* For every window in CHAIN, clear the flags member of FLAG. */
+void
+window_unmark_chain (chain, flag)
+ WINDOW *chain;
+ int flag;
+{
+ register WINDOW *win;
+
+ for (win = chain; win; win = win->next)
+ win->flags &= ~flag;
+}
+
+/* Return the number of characters it takes to display CHARACTER on the
+ screen at HPOS. */
+int
+character_width (character, hpos)
+ int character, hpos;
+{
+ int printable_limit = 127;
+ int width = 1;
+
+ if (ISO_Latin_p)
+ printable_limit = 160;
+
+ if (character > printable_limit)
+ width = 3;
+ else if (iscntrl (character))
+ {
+ switch (character)
+ {
+ case '\r':
+ case '\n':
+ width = the_screen->width - hpos;
+ break;
+ case '\t':
+ width = ((hpos + 8) & 0xf8) - hpos;
+ break;
+ default:
+ width = 2;
+ }
+ }
+ else if (character == DEL)
+ width = 2;
+
+ return (width);
+}
+
+/* Return the number of characters it takes to display STRING on the screen
+ at HPOS. */
+int
+string_width (string, hpos)
+ char *string;
+ int hpos;
+{
+ register int i, width, this_char_width;
+
+ for (width = 0, i = 0; string[i]; i++)
+ {
+ this_char_width = character_width (string[i], hpos);
+ width += this_char_width;
+ hpos += this_char_width;
+ }
+ return (width);
+}
+
+/* Quickly guess the approximate number of lines to that NODE would
+ take to display. This really only counts carriage returns. */
+int
+window_physical_lines (node)
+ NODE *node;
+{
+ register int i, lines;
+ char *contents;
+
+ if (!node)
+ return (0);
+
+ contents = node->contents;
+ for (i = 0, lines = 1; i < node->nodelen; i++)
+ if (contents[i] == '\n')
+ lines++;
+
+ return (lines);
+}
+
+/* Calculate a list of line starts for the node belonging to WINDOW. The line
+ starts are pointers to the actual text within WINDOW->NODE. */
+void
+calculate_line_starts (window)
+ WINDOW *window;
+{
+ register int i, hpos;
+ char **line_starts = (char **)NULL;
+ int line_starts_index = 0, line_starts_slots = 0;
+ int bump_index;
+ NODE *node;
+
+ window->line_starts = (char **)NULL;
+ window->line_count = 0;
+ node = window->node;
+
+ if (!node)
+ return;
+
+ /* Grovel the node starting at the top, and for each line calculate the
+ width of the characters appearing in that line. Add each line start
+ to our array. */
+ i = 0;
+ hpos = 0;
+ bump_index = 0;
+
+ while (i < node->nodelen)
+ {
+ char *line = node->contents + i;
+ unsigned int cwidth, c;
+
+ add_pointer_to_array (line, line_starts_index, line_starts,
+ line_starts_slots, 100, char *);
+ if (bump_index)
+ {
+ i++;
+ bump_index = 0;
+ }
+
+ while (1)
+ {
+ c = node->contents[i];
+ cwidth = character_width (c, hpos);
+
+ /* If this character fits within this line, just do the next one. */
+ if ((hpos + cwidth) < window->width)
+ {
+ i++;
+ hpos += cwidth;
+ continue;
+ }
+ else
+ {
+ /* If this character would position the cursor at the start of
+ the next printed screen line, then do the next line. */
+ if (c == '\n' || c == '\r' || c == '\t')
+ {
+ i++;
+ hpos = 0;
+ break;
+ }
+ else
+ {
+ /* This character passes the window width border. Postion
+ the cursor after the printed character, but remember this
+ line start as where this character is. A bit tricky. */
+
+ /* If this window doesn't wrap lines, proceed to the next
+ physical line here. */
+ if (window->flags & W_NoWrap)
+ {
+ hpos = 0;
+ while (i < node->nodelen && node->contents[i] != '\n')
+ i++;
+
+ if (node->contents[i] == '\n')
+ i++;
+ }
+ else
+ {
+ hpos = the_screen->width - hpos;
+ bump_index++;
+ }
+ break;
+ }
+ }
+ }
+ }
+ window->line_starts = line_starts;
+ window->line_count = line_starts_index;
+}
+
+/* Given WINDOW, recalculate the line starts for the node it displays. */
+void
+recalculate_line_starts (window)
+ WINDOW *window;
+{
+ maybe_free (window->line_starts);
+ calculate_line_starts (window);
+}
+
+/* Global variable control redisplay of scrolled windows. If non-zero, it
+ is the desired number of lines to scroll the window in order to make
+ point visible. A user might set this to 1 for smooth scrolling. If
+ set to zero, the line containing point is centered within the window. */
+int window_scroll_step = 0;
+
+/* Adjust the pagetop of WINDOW such that the cursor point will be visible. */
+void
+window_adjust_pagetop (window)
+ WINDOW *window;
+{
+ register int line = 0;
+ char *contents;
+
+ if (!window->node)
+ return;
+
+ contents = window->node->contents;
+
+ /* Find the first printed line start which is after WINDOW->point. */
+ for (line = 0; line < window->line_count; line++)
+ {
+ char *line_start;
+
+ line_start = window->line_starts[line];
+
+ if ((line_start - contents) > window->point)
+ break;
+ }
+
+ /* The line index preceding the line start which is past point is the
+ one containing point. */
+ line--;
+
+ /* If this line appears in the current displayable page, do nothing.
+ Otherwise, adjust the top of the page to make this line visible. */
+ if ((line < window->pagetop) ||
+ (line - window->pagetop > (window->height - 1)))
+ {
+ /* The user-settable variable "scroll-step" is used to attempt
+ to make point visible, iff it is non-zero. If that variable
+ is zero, then the line containing point is centered within
+ the window. */
+ if (window_scroll_step < window->height)
+ {
+ if ((line < window->pagetop) &&
+ ((window->pagetop - window_scroll_step) <= line))
+ window->pagetop -= window_scroll_step;
+ else if ((line - window->pagetop > (window->height - 1)) &&
+ ((line - (window->pagetop + window_scroll_step)
+ < window->height)))
+ window->pagetop += window_scroll_step;
+ else
+ window->pagetop = line - ((window->height - 1) / 2);
+ }
+ else
+ window->pagetop = line - ((window->height - 1) / 2);
+
+ if (window->pagetop < 0)
+ window->pagetop = 0;
+ window->flags |= W_UpdateWindow;
+ }
+}
+
+/* Return the index of the line containing point. */
+int
+window_line_of_point (window)
+ WINDOW *window;
+{
+ register int i, start = 0;
+
+ /* Try to optimize. Check to see if point is past the pagetop for
+ this window, and if so, start searching forward from there. */
+ if ((window->pagetop > -1 && window->pagetop < window->line_count) &&
+ (window->line_starts[window->pagetop] - window->node->contents)
+ <= window->point)
+ start = window->pagetop;
+
+ for (i = start; i < window->line_count; i++)
+ {
+ if ((window->line_starts[i] - window->node->contents) > window->point)
+ break;
+ }
+
+ return (i - 1);
+}
+
+/* Get and return the goal column for this window. */
+int
+window_get_goal_column (window)
+ WINDOW *window;
+{
+ if (!window->node)
+ return (-1);
+
+ if (window->goal_column != -1)
+ return (window->goal_column);
+
+ /* Okay, do the work. Find the printed offset of the cursor
+ in this window. */
+ return (window_get_cursor_column (window));
+}
+
+/* Get and return the printed column offset of the cursor in this window. */
+int
+window_get_cursor_column (window)
+ WINDOW *window;
+{
+ int i, hpos, end;
+ char *line;
+
+ i = window_line_of_point (window);
+
+ if (i < 0)
+ return (-1);
+
+ line = window->line_starts[i];
+ end = window->point - (line - window->node->contents);
+
+ for (hpos = 0, i = 0; i < end; i++)
+ hpos += character_width (line[i], hpos);
+
+ return (hpos);
+}
+
+/* Count the number of characters in LINE that precede the printed column
+ offset of GOAL. */
+int
+window_chars_to_goal (line, goal)
+ char *line;
+ int goal;
+{
+ register int i, check, hpos;
+
+ for (hpos = 0, i = 0; line[i] != '\n'; i++)
+ {
+
+ check = hpos + character_width (line[i], hpos);
+
+ if (check > goal)
+ break;
+
+ hpos = check;
+ }
+ return (i);
+}
+
+/* Create a modeline for WINDOW, and store it in window->modeline. */
+void
+window_make_modeline (window)
+ WINDOW *window;
+{
+ register int i;
+ char *modeline;
+ char location_indicator[4];
+ int lines_remaining;
+
+ /* Only make modelines for those windows which have one. */
+ if (window->flags & W_InhibitMode)
+ return;
+
+ /* Find the number of lines actually displayed in this window. */
+ lines_remaining = window->line_count - window->pagetop;
+
+ if (window->pagetop == 0)
+ {
+ if (lines_remaining <= window->height)
+ strcpy (location_indicator, "All");
+ else
+ strcpy (location_indicator, "Top");
+ }
+ else
+ {
+ if (lines_remaining <= window->height)
+ strcpy (location_indicator, "Bot");
+ else
+ {
+ float pt, lc;
+ int percentage;
+
+ pt = (float)window->pagetop;
+ lc = (float)window->line_count;
+
+ percentage = 100 * (pt / lc);
+
+ sprintf (location_indicator, "%2d%%", percentage);
+ }
+ }
+
+ /* Calculate the maximum size of the information to stick in MODELINE. */
+ {
+ int modeline_len = 0;
+ char *parent = (char *)NULL, *filename = "*no file*";
+ char *nodename = "*no node*";
+ char *update_message = (char *)NULL;
+ NODE *node = window->node;
+
+ if (node)
+ {
+ if (node->nodename)
+ nodename = node->nodename;
+
+ if (node->parent)
+ {
+ parent = filename_non_directory (node->parent);
+ modeline_len += strlen ("Subfile: ") + strlen (node->filename);
+ }
+
+ if (node->filename)
+ filename = filename_non_directory (node->filename);
+
+ if (node->flags & N_UpdateTags)
+ update_message = "--*** Tags out of Date ***";
+ }
+
+ if (update_message)
+ modeline_len += strlen (update_message);
+ modeline_len += strlen (filename);
+ modeline_len += strlen (nodename);
+ modeline_len += 4; /* strlen (location_indicator). */
+
+ /* 10 for the decimal representation of the number of lines in this
+ node, and the remainder of the text that can appear in the line. */
+ modeline_len += 10 + strlen ("-----Info: (), lines ----, ");
+ modeline_len += window->width;
+
+ modeline = (char *)xmalloc (1 + modeline_len);
+
+ /* Special internal windows have no filename. */
+ if (!parent && !*filename)
+ sprintf (modeline, "-%s---Info: %s, %d lines --%s--",
+ (window->flags & W_NoWrap) ? "$" : "-",
+ nodename, window->line_count, location_indicator);
+ else
+ sprintf (modeline, "-%s%s-Info: (%s)%s, %d lines --%s--",
+ (window->flags & W_NoWrap) ? "$" : "-",
+ (node && (node->flags & N_IsCompressed)) ? "zz" : "--",
+ parent ? parent : filename,
+ nodename, window->line_count, location_indicator);
+
+ if (parent)
+ sprintf (modeline + strlen (modeline), " Subfile: %s", filename);
+
+ if (update_message)
+ sprintf (modeline + strlen (modeline), "%s", update_message);
+
+ i = strlen (modeline);
+
+ if (i >= window->width)
+ modeline[window->width] = '\0';
+ else
+ {
+ while (i < window->width)
+ modeline[i++] = '-';
+ modeline[i] = '\0';
+ }
+
+ strcpy (window->modeline, modeline);
+ free (modeline);
+ }
+}
+
+/* Make WINDOW start displaying at PERCENT percentage of its node. */
+void
+window_goto_percentage (window, percent)
+ WINDOW *window;
+ int percent;
+{
+ int desired_line;
+
+ if (!percent)
+ desired_line = 0;
+ else
+ desired_line =
+ (int) ((float)window->line_count * ((float)percent / 100.0));
+
+ window->pagetop = desired_line;
+ window->point =
+ window->line_starts[window->pagetop] - window->node->contents;
+ window->flags |= W_UpdateWindow;
+ window_make_modeline (window);
+}
+
+/* Get the state of WINDOW, and save it in STATE. */
+void
+window_get_state (window, state)
+ WINDOW *window;
+ WINDOW_STATE *state;
+{
+ state->node = window->node;
+ state->pagetop = window->pagetop;
+ state->point = window->point;
+}
+
+/* Set the node, pagetop, and point of WINDOW. */
+void
+window_set_state (window, state)
+ WINDOW *window;
+ WINDOW_STATE *state;
+{
+ if (window->node != state->node)
+ window_set_node_of_window (window, state->node);
+ window->pagetop = state->pagetop;
+ window->point = state->point;
+}
+
+
+/* **************************************************************** */
+/* */
+/* Manipulating Home-Made Nodes */
+/* */
+/* **************************************************************** */
+
+/* A place to buffer echo area messages. */
+static NODE *echo_area_node = (NODE *)NULL;
+
+/* Make the node of the_echo_area be an empty one. */
+static void
+free_echo_area ()
+{
+ if (echo_area_node)
+ {
+ maybe_free (echo_area_node->contents);
+ free (echo_area_node);
+ }
+
+ echo_area_node = (NODE *)NULL;
+ window_set_node_of_window (the_echo_area, echo_area_node);
+}
+
+/* Clear the echo area, removing any message that is already present.
+ The echo area is cleared immediately. */
+void
+window_clear_echo_area ()
+{
+ free_echo_area ();
+ display_update_one_window (the_echo_area);
+}
+
+/* Make a message appear in the echo area, built from FORMAT, ARG1 and ARG2.
+ The arguments are treated similar to printf () arguments, but not all of
+ printf () hair is present. The message appears immediately. If there was
+ already a message appearing in the echo area, it is removed. */
+void
+window_message_in_echo_area (format, arg1, arg2)
+ char *format;
+ void *arg1, *arg2;
+{
+ free_echo_area ();
+ echo_area_node = build_message_node (format, arg1, arg2);
+ window_set_node_of_window (the_echo_area, echo_area_node);
+ display_update_one_window (the_echo_area);
+}
+
+/* Place a temporary message in the echo area built from FORMAT, ARG1
+ and ARG2. The message appears immediately, but does not destroy
+ any existing message. A future call to unmessage_in_echo_area ()
+ restores the old contents. */
+static NODE **old_echo_area_nodes = (NODE **)NULL;
+static int old_echo_area_nodes_index = 0;
+static int old_echo_area_nodes_slots = 0;
+
+void
+message_in_echo_area (format, arg1, arg2)
+ char *format;
+ void *arg1, *arg2;
+{
+ if (echo_area_node)
+ {
+ add_pointer_to_array (echo_area_node, old_echo_area_nodes_index,
+ old_echo_area_nodes, old_echo_area_nodes_slots,
+ 4, NODE *);
+ }
+ echo_area_node = (NODE *)NULL;
+ window_message_in_echo_area (format, arg1, arg2);
+}
+
+void
+unmessage_in_echo_area ()
+{
+ free_echo_area ();
+
+ if (old_echo_area_nodes_index)
+ echo_area_node = old_echo_area_nodes[--old_echo_area_nodes_index];
+
+ window_set_node_of_window (the_echo_area, echo_area_node);
+ display_update_one_window (the_echo_area);
+}
+
+/* A place to build a message. */
+static char *message_buffer = (char *)NULL;
+static int message_buffer_index = 0;
+static int message_buffer_size = 0;
+
+/* Ensure that there is enough space to stuff LENGTH characters into
+ MESSAGE_BUFFER. */
+static void
+message_buffer_resize (length)
+ int length;
+{
+ if (!message_buffer)
+ {
+ message_buffer_size = length + 1;
+ message_buffer = (char *)xmalloc (message_buffer_size);
+ message_buffer_index = 0;
+ }
+
+ while (message_buffer_size <= message_buffer_index + length)
+ message_buffer = (char *)
+ xrealloc (message_buffer,
+ message_buffer_size += 100 + (2 * length));
+}
+
+/* Format MESSAGE_BUFFER with the results of printing FORMAT with ARG1 and
+ ARG2. */
+static void
+build_message_buffer (format, arg1, arg2)
+ char *format;
+ void *arg1, *arg2;
+{
+ register int i, len;
+ void *args[2];
+ int arg_index = 0;
+
+ args[0] = arg1;
+ args[1] = arg2;
+
+ len = strlen (format);
+
+ message_buffer_resize (len);
+
+ for (i = 0; format[i]; i++)
+ {
+ if (format[i] != '%')
+ {
+ message_buffer[message_buffer_index++] = format[i];
+ len--;
+ }
+ else
+ {
+ char c;
+
+ c = format[++i];
+
+ switch (c)
+ {
+ case '%': /* Insert a percent sign. */
+ message_buffer_resize (len + 1);
+ message_buffer[message_buffer_index++] = '%';
+ break;
+
+ case 's': /* Insert the current arg as a string. */
+ {
+ char *string;
+ int string_len;
+
+ string = (char *)args[arg_index++];
+ string_len = strlen (string);
+
+ message_buffer_resize (len + string_len);
+ sprintf
+ (message_buffer + message_buffer_index, "%s", string);
+ message_buffer_index += string_len;
+ }
+ break;
+
+ case 'd': /* Insert the current arg as an integer. */
+ {
+ long long_val;
+ int integer;
+
+ long_val = (long)args[arg_index++];
+ integer = (int)long_val;
+
+ message_buffer_resize (len + 32);
+ sprintf
+ (message_buffer + message_buffer_index, "%d", integer);
+ message_buffer_index = strlen (message_buffer);
+ }
+ break;
+
+ case 'c': /* Insert the current arg as a character. */
+ {
+ long long_val;
+ int character;
+
+ long_val = (long)args[arg_index++];
+ character = (int)long_val;
+
+ message_buffer_resize (len + 1);
+ message_buffer[message_buffer_index++] = character;
+ }
+ break;
+
+ default:
+ abort ();
+ }
+ }
+ }
+ message_buffer[message_buffer_index] = '\0';
+}
+
+/* Build a new node which has FORMAT printed with ARG1 and ARG2 as the
+ contents. */
+NODE *
+build_message_node (format, arg1, arg2)
+ char *format;
+ void *arg1, *arg2;
+{
+ NODE *node;
+
+ message_buffer_index = 0;
+ build_message_buffer (format, arg1, arg2);
+
+ node = message_buffer_to_node ();
+ return (node);
+}
+
+/* Convert the contents of the message buffer to a node. */
+NODE *
+message_buffer_to_node ()
+{
+ NODE *node;
+
+ node = (NODE *)xmalloc (sizeof (NODE));
+ node->filename = (char *)NULL;
+ node->parent = (char *)NULL;
+ node->nodename = (char *)NULL;
+ node->flags = 0;
+
+ /* Make sure that this buffer ends with a newline. */
+ node->nodelen = 1 + strlen (message_buffer);
+ node->contents = (char *)xmalloc (1 + node->nodelen);
+ strcpy (node->contents, message_buffer);
+ node->contents[node->nodelen - 1] = '\n';
+ node->contents[node->nodelen] = '\0';
+ return (node);
+}
+
+/* Useful functions can be called from outside of window.c. */
+void
+initialize_message_buffer ()
+{
+ message_buffer_index = 0;
+}
+
+/* Print FORMAT with ARG1,2 to the end of the current message buffer. */
+void
+printf_to_message_buffer (format, arg1, arg2)
+ char *format;
+ void *arg1, *arg2;
+{
+ build_message_buffer (format, arg1, arg2);
+}
+
+/* Return the current horizontal position of the "cursor" on the most
+ recently output message buffer line. */
+int
+message_buffer_length_this_line ()
+{
+ register int i;
+
+ if (!message_buffer_index)
+ return (0);
+
+ for (i = message_buffer_index; i && message_buffer[i - 1] != '\n'; i--);
+
+ return (string_width (message_buffer + i, 0));
+}
+
+/* Pad STRING to COUNT characters by inserting blanks. */
+int
+pad_to (count, string)
+ int count;
+ char *string;
+{
+ register int i;
+
+ i = strlen (string);
+
+ if (i >= count)
+ string[i++] = ' ';
+ else
+ {
+ while (i < count)
+ string[i++] = ' ';
+ }
+ string[i] = '\0';
+
+ return (i);
+}
diff --git a/contrib/texinfo/info/window.h b/contrib/texinfo/info/window.h
new file mode 100644
index 0000000..5bde64a
--- /dev/null
+++ b/contrib/texinfo/info/window.h
@@ -0,0 +1,229 @@
+/* window.h -- Structure and flags used in manipulating Info windows. */
+
+/* This file is part of GNU Info, a program for reading online documentation
+ stored in Info format.
+
+ Copyright (C) 1993 Free Software Foundation, Inc.
+
+ 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Written by Brian Fox (bfox@ai.mit.edu). */
+
+#if !defined (_WINDOW_H_)
+#define _WINDOW_H_
+
+#include "nodes.h"
+#include "infomap.h"
+
+/* Smallest number of visible lines in a window. The actual height is
+ always one more than this number because each window has a modeline. */
+#define WINDOW_MIN_HEIGHT 2
+
+/* Smallest number of screen lines that can be used to fully present a
+ window. This number includes the modeline of the window. */
+#define WINDOW_MIN_SIZE (WINDOW_MIN_HEIGHT + 1)
+
+/* The exact same elements are used within the WINDOW_STATE structure and a
+ subsection of the WINDOW structure. We could define a structure which
+ contains this elements, and include that structure in each of WINDOW_STATE
+ and WINDOW. But that would lead references in the code such as
+ window->state->node which we would like to avoid. Instead, we #define the
+ elements here, and simply include the define in both data structures. Thus,
+ if you need to change window state information, here is where you would
+ do it. NB> The last element does NOT end with a semi-colon. */
+#define WINDOW_STATE_DECL \
+ NODE *node; /* The node displayed in this window. */ \
+ int pagetop; /* LINE_STARTS[PAGETOP] is first line in WINDOW. */ \
+ long point /* Offset within NODE of the cursor position. */
+
+/* Structure which defines a window. Windows are doubly linked, next
+ and prev. The list of windows is kept on WINDOWS. The structure member
+ window->height is the total height of the window. The position location
+ (0, window->height + window->first_row) is the first character of this
+ windows modeline. The number of lines that can be displayed in a window
+ is equal to window->height - 1. */
+typedef struct __window__ {
+ struct __window__ *next; /* Next window in this chain. */
+ struct __window__ *prev; /* Previous window in this chain. */
+ int width; /* Width of this window. */
+ int height; /* Height of this window. */
+ int first_row; /* Offset of the first line in the_screen. */
+ int goal_column; /* The column we would like the cursor to appear in. */
+ Keymap keymap; /* Keymap used to read commands in this window. */
+ WINDOW_STATE_DECL; /* Node, pagetop and point. */
+ char *modeline; /* Calculated text of the modeline for this window. */
+ char **line_starts; /* Array of printed line starts for this node. */
+ int line_count; /* Number of lines appearing in LINE_STARTS. */
+ int flags; /* See below for details. */
+} WINDOW;
+
+typedef struct {
+ WINDOW_STATE_DECL; /* What gets saved. */
+} WINDOW_STATE;
+
+#define W_UpdateWindow 0x01 /* WINDOW needs updating. */
+#define W_WindowIsPerm 0x02 /* This WINDOW is a permanent object. */
+#define W_WindowVisible 0x04 /* This WINDOW is currently visible. */
+#define W_InhibitMode 0x08 /* This WINDOW has no modeline. */
+#define W_NoWrap 0x10 /* Lines do not wrap in this window. */
+#define W_InputWindow 0x20 /* Window accepts input. */
+#define W_TempWindow 0x40 /* Window is less important. */
+
+extern WINDOW *windows; /* List of visible Info windows. */
+extern WINDOW *active_window; /* The currently active window. */
+extern WINDOW *the_screen; /* The Info screen is just another window. */
+extern WINDOW *the_echo_area; /* THE_ECHO_AREA is a window in THE_SCREEN. */
+
+/* Global variable control redisplay of scrolled windows. If non-zero, it
+ is the desired number of lines to scroll the window in order to make
+ point visible. A user might set this to 1 for smooth scrolling. If
+ set to zero, the line containing point is centered within the window. */
+extern int window_scroll_step;
+
+ /* Make the modeline member for WINDOW. */
+extern void window_make_modeline ();
+
+/* Initalize the window system by creating THE_SCREEN and THE_ECHO_AREA.
+ Create the first window ever, and make it permanent.
+ You pass WIDTH and HEIGHT; the dimensions of the total screen size. */
+extern void window_initialize_windows ();
+
+/* Make a new window showing NODE, and return that window structure.
+ The new window is made to be the active window. If NODE is passed
+ as NULL, then show the node showing in the active window. If the
+ window could not be made return a NULL pointer. The active window
+ is not changed.*/
+extern WINDOW *window_make_window ();
+
+/* Delete WINDOW from the list of known windows. If this window was the
+ active window, make the next window in the chain be the active window,
+ or the previous window in the chain if there is no next window. */
+extern void window_delete_window ();
+
+/* A function to call when the screen changes size, and some windows have
+ to get deleted. The function is called with the window to be deleted
+ as an argument, and it can't do anything about the window getting deleted;
+ it can only clean up dangling references to that window. */
+extern VFunction *window_deletion_notifier;
+
+/* Set WINDOW to display NODE. */
+extern void window_set_node_of_window ();
+
+/* Tell the window system that the size of the screen has changed. This
+ causes lots of interesting things to happen. The permanent windows
+ are resized, as well as every visible window. You pass WIDTH and HEIGHT;
+ the dimensions of the total screen size. */
+extern void window_new_screen_size ();
+
+/* Change the height of WINDOW by AMOUNT. This also automagically adjusts
+ the previous and next windows in the chain. If there is only one user
+ window, then no change takes place. */
+extern void window_change_window_height ();
+
+/* Adjust the pagetop of WINDOW such that the cursor point will be visible. */
+extern void window_adjust_pagetop ();
+
+/* Tile all of the windows currently displayed in the global variable
+ WINDOWS. If argument DO_INTERNALS is non-zero, tile windows displaying
+ internal nodes as well. */
+#define DONT_TILE_INTERNALS 0
+#define TILE_INTERNALS 1
+extern void window_tile_windows ();
+
+/* Toggle the state of line wrapping in WINDOW. This can do a bit of fancy
+ redisplay. */
+extern void window_toggle_wrap ();
+
+/* For every window in CHAIN, set the flags member to have FLAG set. */
+extern void window_mark_chain ();
+
+/* For every window in CHAIN, clear the flags member of FLAG. */
+extern void window_unmark_chain ();
+
+/* Make WINDOW start displaying at PERCENT percentage of its node. */
+extern void window_goto_percentage ();
+
+/* Build a new node which has FORMAT printed with ARG1 and ARG2 as the
+ contents. */
+extern NODE *build_message_node ();
+
+/* Useful functions can be called from outside of window.c. */
+extern void initialize_message_buffer ();
+
+/* Print FORMAT with ARG1,2 to the end of the current message buffer. */
+extern void printf_to_message_buffer ();
+
+/* Convert the contents of the message buffer to a node. */
+extern NODE *message_buffer_to_node ();
+
+/* Return the length of the most recently printed line in message buffer. */
+extern int message_buffer_length_this_line ();
+
+/* Pad STRING to COUNT characters by inserting blanks. */
+extern int pad_to ();
+
+/* Make a message appear in the echo area, built from FORMAT, ARG1 and ARG2.
+ The arguments are treated similar to printf () arguments, but not all of
+ printf () hair is present. The message appears immediately. If there was
+ already a message appearing in the echo area, it is removed. */
+extern void window_message_in_echo_area ();
+
+/* Place a temporary message in the echo area built from FORMAT, ARG1
+ and ARG2. The message appears immediately, but does not destroy
+ any existing message. A future call to unmessage_in_echo_area ()
+ restores the old contents. */
+extern void message_in_echo_area ();
+extern void unmessage_in_echo_area ();
+
+/* Clear the echo area, removing any message that is already present.
+ The echo area is cleared immediately. */
+extern void window_clear_echo_area ();
+
+/* Quickly guess the approximate number of lines to that NODE would
+ take to display. This really only counts carriage returns. */
+extern int window_physical_lines ();
+
+/* Calculate a list of line starts for the node belonging to WINDOW. The line
+ starts are pointers to the actual text within WINDOW->NODE. */
+extern void calculate_line_starts ();
+
+/* Given WINDOW, recalculate the line starts for the node it displays. */
+extern void recalculate_line_starts ();
+
+/* Return the number of characters it takes to display CHARACTER on the
+ screen at HPOS. */
+extern int character_width ();
+
+/* Return the number of characters it takes to display STRING on the
+ screen at HPOS. */
+extern int string_width ();
+
+/* Return the index of the line containing point. */
+extern int window_line_of_point ();
+
+/* Get and return the goal column for this window. */
+extern int window_get_goal_column ();
+
+/* Get and return the printed column offset of the cursor in this window. */
+extern int window_get_cursor_column ();
+
+/* Get and Set the node, pagetop, and point of WINDOW. */
+extern void window_get_state (), window_set_state ();
+
+/* Count the number of characters in LINE that precede the printed column
+ offset of GOAL. */
+extern int window_chars_to_goal ();
+
+#endif /* !_WINDOW_H_ */
diff --git a/contrib/texinfo/info/xmalloc.c b/contrib/texinfo/info/xmalloc.c
new file mode 100644
index 0000000..156989e
--- /dev/null
+++ b/contrib/texinfo/info/xmalloc.c
@@ -0,0 +1,80 @@
+/* xmalloc.c -- safe versions of malloc and realloc */
+
+/* This file is part of GNU Info, a program for reading online documentation
+ stored in Info format.
+
+ This file has appeared in prior works by the Free Software Foundation;
+ thus it carries copyright dates from 1988 through 1993.
+
+ Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993 Free Software
+ Foundation, Inc.
+
+ 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Written by Brian Fox (bfox@ai.mit.edu). */
+
+#if !defined (ALREADY_HAVE_XMALLOC)
+#include <stdio.h>
+#include <sys/types.h>
+
+extern void *malloc (), *realloc ();
+static void memory_error_and_abort ();
+
+/* **************************************************************** */
+/* */
+/* Memory Allocation and Deallocation. */
+/* */
+/* **************************************************************** */
+
+/* Return a pointer to free()able block of memory large enough
+ to hold BYTES number of bytes. If the memory cannot be allocated,
+ print an error message and abort. */
+void *
+xmalloc (bytes)
+ int bytes;
+{
+ void *temp = malloc (bytes);
+
+ if (!temp)
+ memory_error_and_abort ("xmalloc");
+ return (temp);
+}
+
+void *
+xrealloc (pointer, bytes)
+ void *pointer;
+ int bytes;
+{
+ void *temp;
+
+ if (!pointer)
+ temp = malloc (bytes);
+ else
+ temp = realloc (pointer, bytes);
+
+ if (!temp)
+ memory_error_and_abort ("xrealloc");
+
+ return (temp);
+}
+
+static void
+memory_error_and_abort (fname)
+ char *fname;
+{
+ fprintf (stderr, "%s: Out of virtual memory!\n", fname);
+ abort ();
+}
+#endif /* !ALREADY_HAVE_XMALLOC */
diff --git a/contrib/texinfo/install-sh b/contrib/texinfo/install-sh
new file mode 100755
index 0000000..2c212cc
--- /dev/null
+++ b/contrib/texinfo/install-sh
@@ -0,0 +1,250 @@
+#! /bin/sh
+#
+# install - install a program, script, or datafile
+# This comes from X11R5 (mit/util/scripts/install.sh).
+#
+# Copyright 1991 by the Massachusetts Institute of Technology
+#
+# Permission to use, copy, modify, distribute, and sell this software and its
+# documentation for any purpose is hereby granted without fee, provided that
+# the above copyright notice appear in all copies and that both that
+# copyright notice and this permission notice appear in supporting
+# documentation, and that the name of M.I.T. not be used in advertising or
+# publicity pertaining to distribution of the software without specific,
+# written prior permission. M.I.T. makes no representations about the
+# suitability of this software for any purpose. It is provided "as is"
+# without express or implied warranty.
+#
+# Calling this script install-sh is preferred over install.sh, to prevent
+# `make' implicit rules from creating a file called install from it
+# when there is no Makefile.
+#
+# This script is compatible with the BSD install script, but was written
+# from scratch.
+#
+
+
+# set DOITPROG to echo to test this script
+
+# Don't use :- since 4.3BSD and earlier shells don't like it.
+doit="${DOITPROG-}"
+
+
+# put in absolute paths if you don't have them in your path; or use env. vars.
+
+mvprog="${MVPROG-mv}"
+cpprog="${CPPROG-cp}"
+chmodprog="${CHMODPROG-chmod}"
+chownprog="${CHOWNPROG-chown}"
+chgrpprog="${CHGRPPROG-chgrp}"
+stripprog="${STRIPPROG-strip}"
+rmprog="${RMPROG-rm}"
+mkdirprog="${MKDIRPROG-mkdir}"
+
+transformbasename=""
+transform_arg=""
+instcmd="$mvprog"
+chmodcmd="$chmodprog 0755"
+chowncmd=""
+chgrpcmd=""
+stripcmd=""
+rmcmd="$rmprog -f"
+mvcmd="$mvprog"
+src=""
+dst=""
+dir_arg=""
+
+while [ x"$1" != x ]; do
+ case $1 in
+ -c) instcmd="$cpprog"
+ shift
+ continue;;
+
+ -d) dir_arg=true
+ shift
+ continue;;
+
+ -m) chmodcmd="$chmodprog $2"
+ shift
+ shift
+ continue;;
+
+ -o) chowncmd="$chownprog $2"
+ shift
+ shift
+ continue;;
+
+ -g) chgrpcmd="$chgrpprog $2"
+ shift
+ shift
+ continue;;
+
+ -s) stripcmd="$stripprog"
+ shift
+ continue;;
+
+ -t=*) transformarg=`echo $1 | sed 's/-t=//'`
+ shift
+ continue;;
+
+ -b=*) transformbasename=`echo $1 | sed 's/-b=//'`
+ shift
+ continue;;
+
+ *) if [ x"$src" = x ]
+ then
+ src=$1
+ else
+ # this colon is to work around a 386BSD /bin/sh bug
+ :
+ dst=$1
+ fi
+ shift
+ continue;;
+ esac
+done
+
+if [ x"$src" = x ]
+then
+ echo "install: no input file specified"
+ exit 1
+else
+ true
+fi
+
+if [ x"$dir_arg" != x ]; then
+ dst=$src
+ src=""
+
+ if [ -d $dst ]; then
+ instcmd=:
+ else
+ instcmd=mkdir
+ fi
+else
+
+# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
+# might cause directories to be created, which would be especially bad
+# if $src (and thus $dsttmp) contains '*'.
+
+ if [ -f $src -o -d $src ]
+ then
+ true
+ else
+ echo "install: $src does not exist"
+ exit 1
+ fi
+
+ if [ x"$dst" = x ]
+ then
+ echo "install: no destination specified"
+ exit 1
+ else
+ true
+ fi
+
+# If destination is a directory, append the input filename; if your system
+# does not like double slashes in filenames, you may need to add some logic
+
+ if [ -d $dst ]
+ then
+ dst="$dst"/`basename $src`
+ else
+ true
+ fi
+fi
+
+## this sed command emulates the dirname command
+dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
+
+# Make sure that the destination directory exists.
+# this part is taken from Noah Friedman's mkinstalldirs script
+
+# Skip lots of stat calls in the usual case.
+if [ ! -d "$dstdir" ]; then
+defaultIFS='
+'
+IFS="${IFS-${defaultIFS}}"
+
+oIFS="${IFS}"
+# Some sh's can't handle IFS=/ for some reason.
+IFS='%'
+set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'`
+IFS="${oIFS}"
+
+pathcomp=''
+
+while [ $# -ne 0 ] ; do
+ pathcomp="${pathcomp}${1}"
+ shift
+
+ if [ ! -d "${pathcomp}" ] ;
+ then
+ $mkdirprog "${pathcomp}"
+ else
+ true
+ fi
+
+ pathcomp="${pathcomp}/"
+done
+fi
+
+if [ x"$dir_arg" != x ]
+then
+ $doit $instcmd $dst &&
+
+ if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi &&
+ if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi &&
+ if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi &&
+ if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi
+else
+
+# If we're going to rename the final executable, determine the name now.
+
+ if [ x"$transformarg" = x ]
+ then
+ dstfile=`basename $dst`
+ else
+ dstfile=`basename $dst $transformbasename |
+ sed $transformarg`$transformbasename
+ fi
+
+# don't allow the sed command to completely eliminate the filename
+
+ if [ x"$dstfile" = x ]
+ then
+ dstfile=`basename $dst`
+ else
+ true
+ fi
+
+# Make a temp file name in the proper directory.
+
+ dsttmp=$dstdir/#inst.$$#
+
+# Move or copy the file name to the temp name
+
+ $doit $instcmd $src $dsttmp &&
+
+ trap "rm -f ${dsttmp}" 0 &&
+
+# and set any options; do chmod last to preserve setuid bits
+
+# If any of these fail, we abort the whole thing. If we want to
+# ignore errors from any of these, just make sure not to ignore
+# errors from the above "$doit $instcmd $src $dsttmp" command.
+
+ if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi &&
+ if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi &&
+ if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi &&
+ if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi &&
+
+# Now rename the file to the real destination.
+
+ $doit $rmcmd -f $dstdir/$dstfile &&
+ $doit $mvcmd $dsttmp $dstdir/$dstfile
+
+fi &&
+
+
+exit 0
diff --git a/contrib/texinfo/libtxi/Makefile.in b/contrib/texinfo/libtxi/Makefile.in
new file mode 100644
index 0000000..58cb2a3
--- /dev/null
+++ b/contrib/texinfo/libtxi/Makefile.in
@@ -0,0 +1,82 @@
+# Makefile for GNU texinfo/libtxi. -*- Indented-Text -*-
+# $Id: Makefile.in,v 1.3 1996/10/03 18:32:28 karl Exp $
+
+# Copyright (C) 1993, 96 Free Software Foundation, Inc.
+
+# 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+SHELL = /bin/sh
+srcdir = @srcdir@
+VPATH = $(srcdir)
+
+CC = @CC@
+AR = ar
+RANLIB = @RANLIB@
+
+DEFS = @DEFS@
+LIBS = @LIBS@
+LOADLIBES = $(LIBS)
+
+CFLAGS = @CFLAGS@
+LDFLAGS = @LDFLAGS@
+
+# This is normally inherited from parent make, but if someone wants to
+# build libtxi.a alone, this variable will still be properly defined.
+ALLOCA = @ALLOCA@
+
+# Standard functions that may be missing.
+LIBOBJS = @LIBOBJS@
+
+SRCS = getopt.c getopt1.c bzero.c getopt.h
+OBJS = getopt.o getopt1.o bzero.o $(ALLOCA) $(LIBOBJS)
+
+PROGS = libtxi.a
+
+all: $(PROGS)
+sub-all: all
+
+.c.o:
+ $(CC) -c $(CPPFLAGS) -I. -I$(srcdir) $(DEFS) $(CFLAGS) $<
+
+libtxi.a: $(OBJS)
+ rm -f $@
+ $(AR) cq $@ $(OBJS)
+ $(RANLIB) $@
+
+getopt.o: getopt.c getopt.h
+getopt1.o: getopt1.c getopt.h
+alloca.o: alloca.c
+
+install:
+uninstall:
+
+TAGS: $(SRCS)
+ etags $(SRCS)
+
+clean:
+ rm -f *.o a.out core core.* $(PROGS)
+
+mostlyclean: clean
+
+distclean: clean
+ rm -f Makefile config.status TAGS ID
+
+realclean: distclean
+
+Makefile: Makefile.in ../config.status
+ cd .. && sh config.status
+
+# Prevent GNU make v3 from overflowing arg limit on SysV.
+.NOEXPORT:
diff --git a/contrib/texinfo/libtxi/alloca.c b/contrib/texinfo/libtxi/alloca.c
new file mode 100644
index 0000000..8f98b73
--- /dev/null
+++ b/contrib/texinfo/libtxi/alloca.c
@@ -0,0 +1,504 @@
+/* alloca.c -- allocate automatically reclaimed memory
+ (Mostly) portable public-domain implementation -- D A Gwyn
+
+ This implementation of the PWB library alloca function,
+ which is used to allocate space off the run-time stack so
+ that it is automatically reclaimed upon procedure exit,
+ was inspired by discussions with J. Q. Johnson of Cornell.
+ J.Otto Tennant <jot@cray.com> contributed the Cray support.
+
+ There are some preprocessor constants that can
+ be defined when compiling for your specific system, for
+ improved efficiency; however, the defaults should be okay.
+
+ The general concept of this implementation is to keep
+ track of all alloca-allocated blocks, and reclaim any
+ that are found to be deeper in the stack than the current
+ invocation. This heuristic does not reclaim storage as
+ soon as it becomes invalid, but it will do so eventually.
+
+ As a special case, alloca(0) reclaims storage without
+ allocating any. It is a good idea to use alloca(0) in
+ your main control loop, etc. to force garbage collection. */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+
+#ifdef emacs
+#include "blockinput.h"
+#endif
+
+/* If compiling with GCC 2, this file's not needed. */
+#if !defined (__GNUC__) || __GNUC__ < 2
+
+/* If someone has defined alloca as a macro,
+ there must be some other way alloca is supposed to work. */
+#ifndef alloca
+
+#ifdef emacs
+#ifdef static
+/* actually, only want this if static is defined as ""
+ -- this is for usg, in which emacs must undefine static
+ in order to make unexec workable
+ */
+#ifndef STACK_DIRECTION
+you
+lose
+-- must know STACK_DIRECTION at compile-time
+#endif /* STACK_DIRECTION undefined */
+#endif /* static */
+#endif /* emacs */
+
+/* If your stack is a linked list of frames, you have to
+ provide an "address metric" ADDRESS_FUNCTION macro. */
+
+#if defined (CRAY) && defined (CRAY_STACKSEG_END)
+long i00afunc ();
+#define ADDRESS_FUNCTION(arg) (char *) i00afunc (&(arg))
+#else
+#define ADDRESS_FUNCTION(arg) &(arg)
+#endif
+
+#if __STDC__
+typedef void *pointer;
+#else
+typedef char *pointer;
+#endif
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+/* Different portions of Emacs need to call different versions of
+ malloc. The Emacs executable needs alloca to call xmalloc, because
+ ordinary malloc isn't protected from input signals. On the other
+ hand, the utilities in lib-src need alloca to call malloc; some of
+ them are very simple, and don't have an xmalloc routine.
+
+ Non-Emacs programs expect this to call use xmalloc.
+
+ Callers below should use malloc. */
+
+#ifndef emacs
+#define malloc xmalloc
+#endif
+extern pointer malloc ();
+
+/* Define STACK_DIRECTION if you know the direction of stack
+ growth for your system; otherwise it will be automatically
+ deduced at run-time.
+
+ STACK_DIRECTION > 0 => grows toward higher addresses
+ STACK_DIRECTION < 0 => grows toward lower addresses
+ STACK_DIRECTION = 0 => direction of growth unknown */
+
+#ifndef STACK_DIRECTION
+#define STACK_DIRECTION 0 /* Direction unknown. */
+#endif
+
+#if STACK_DIRECTION != 0
+
+#define STACK_DIR STACK_DIRECTION /* Known at compile-time. */
+
+#else /* STACK_DIRECTION == 0; need run-time code. */
+
+static int stack_dir; /* 1 or -1 once known. */
+#define STACK_DIR stack_dir
+
+static void
+find_stack_direction ()
+{
+ static char *addr = NULL; /* Address of first `dummy', once known. */
+ auto char dummy; /* To get stack address. */
+
+ if (addr == NULL)
+ { /* Initial entry. */
+ addr = ADDRESS_FUNCTION (dummy);
+
+ find_stack_direction (); /* Recurse once. */
+ }
+ else
+ {
+ /* Second entry. */
+ if (ADDRESS_FUNCTION (dummy) > addr)
+ stack_dir = 1; /* Stack grew upward. */
+ else
+ stack_dir = -1; /* Stack grew downward. */
+ }
+}
+
+#endif /* STACK_DIRECTION == 0 */
+
+/* An "alloca header" is used to:
+ (a) chain together all alloca'ed blocks;
+ (b) keep track of stack depth.
+
+ It is very important that sizeof(header) agree with malloc
+ alignment chunk size. The following default should work okay. */
+
+#ifndef ALIGN_SIZE
+#define ALIGN_SIZE sizeof(double)
+#endif
+
+typedef union hdr
+{
+ char align[ALIGN_SIZE]; /* To force sizeof(header). */
+ struct
+ {
+ union hdr *next; /* For chaining headers. */
+ char *deep; /* For stack depth measure. */
+ } h;
+} header;
+
+static header *last_alloca_header = NULL; /* -> last alloca header. */
+
+/* Return a pointer to at least SIZE bytes of storage,
+ which will be automatically reclaimed upon exit from
+ the procedure that called alloca. Originally, this space
+ was supposed to be taken from the current stack frame of the
+ caller, but that method cannot be made to work for some
+ implementations of C, for example under Gould's UTX/32. */
+
+pointer
+alloca (size)
+ unsigned size;
+{
+ auto char probe; /* Probes stack depth: */
+ register char *depth = ADDRESS_FUNCTION (probe);
+
+#if STACK_DIRECTION == 0
+ if (STACK_DIR == 0) /* Unknown growth direction. */
+ find_stack_direction ();
+#endif
+
+ /* Reclaim garbage, defined as all alloca'd storage that
+ was allocated from deeper in the stack than currently. */
+
+ {
+ register header *hp; /* Traverses linked list. */
+
+#ifdef emacs
+ BLOCK_INPUT;
+#endif
+
+ for (hp = last_alloca_header; hp != NULL;)
+ if ((STACK_DIR > 0 && hp->h.deep > depth)
+ || (STACK_DIR < 0 && hp->h.deep < depth))
+ {
+ register header *np = hp->h.next;
+
+ free ((pointer) hp); /* Collect garbage. */
+
+ hp = np; /* -> next header. */
+ }
+ else
+ break; /* Rest are not deeper. */
+
+ last_alloca_header = hp; /* -> last valid storage. */
+
+#ifdef emacs
+ UNBLOCK_INPUT;
+#endif
+ }
+
+ if (size == 0)
+ return NULL; /* No allocation required. */
+
+ /* Allocate combined header + user data storage. */
+
+ {
+ register pointer new = malloc (sizeof (header) + size);
+ /* Address of header. */
+
+ if (new == 0)
+ abort();
+
+ ((header *) new)->h.next = last_alloca_header;
+ ((header *) new)->h.deep = depth;
+
+ last_alloca_header = (header *) new;
+
+ /* User storage begins just after header. */
+
+ return (pointer) ((char *) new + sizeof (header));
+ }
+}
+
+#if defined (CRAY) && defined (CRAY_STACKSEG_END)
+
+#ifdef DEBUG_I00AFUNC
+#include <stdio.h>
+#endif
+
+#ifndef CRAY_STACK
+#define CRAY_STACK
+#ifndef CRAY2
+/* Stack structures for CRAY-1, CRAY X-MP, and CRAY Y-MP */
+struct stack_control_header
+ {
+ long shgrow:32; /* Number of times stack has grown. */
+ long shaseg:32; /* Size of increments to stack. */
+ long shhwm:32; /* High water mark of stack. */
+ long shsize:32; /* Current size of stack (all segments). */
+ };
+
+/* The stack segment linkage control information occurs at
+ the high-address end of a stack segment. (The stack
+ grows from low addresses to high addresses.) The initial
+ part of the stack segment linkage control information is
+ 0200 (octal) words. This provides for register storage
+ for the routine which overflows the stack. */
+
+struct stack_segment_linkage
+ {
+ long ss[0200]; /* 0200 overflow words. */
+ long sssize:32; /* Number of words in this segment. */
+ long ssbase:32; /* Offset to stack base. */
+ long:32;
+ long sspseg:32; /* Offset to linkage control of previous
+ segment of stack. */
+ long:32;
+ long sstcpt:32; /* Pointer to task common address block. */
+ long sscsnm; /* Private control structure number for
+ microtasking. */
+ long ssusr1; /* Reserved for user. */
+ long ssusr2; /* Reserved for user. */
+ long sstpid; /* Process ID for pid based multi-tasking. */
+ long ssgvup; /* Pointer to multitasking thread giveup. */
+ long sscray[7]; /* Reserved for Cray Research. */
+ long ssa0;
+ long ssa1;
+ long ssa2;
+ long ssa3;
+ long ssa4;
+ long ssa5;
+ long ssa6;
+ long ssa7;
+ long sss0;
+ long sss1;
+ long sss2;
+ long sss3;
+ long sss4;
+ long sss5;
+ long sss6;
+ long sss7;
+ };
+
+#else /* CRAY2 */
+/* The following structure defines the vector of words
+ returned by the STKSTAT library routine. */
+struct stk_stat
+ {
+ long now; /* Current total stack size. */
+ long maxc; /* Amount of contiguous space which would
+ be required to satisfy the maximum
+ stack demand to date. */
+ long high_water; /* Stack high-water mark. */
+ long overflows; /* Number of stack overflow ($STKOFEN) calls. */
+ long hits; /* Number of internal buffer hits. */
+ long extends; /* Number of block extensions. */
+ long stko_mallocs; /* Block allocations by $STKOFEN. */
+ long underflows; /* Number of stack underflow calls ($STKRETN). */
+ long stko_free; /* Number of deallocations by $STKRETN. */
+ long stkm_free; /* Number of deallocations by $STKMRET. */
+ long segments; /* Current number of stack segments. */
+ long maxs; /* Maximum number of stack segments so far. */
+ long pad_size; /* Stack pad size. */
+ long current_address; /* Current stack segment address. */
+ long current_size; /* Current stack segment size. This
+ number is actually corrupted by STKSTAT to
+ include the fifteen word trailer area. */
+ long initial_address; /* Address of initial segment. */
+ long initial_size; /* Size of initial segment. */
+ };
+
+/* The following structure describes the data structure which trails
+ any stack segment. I think that the description in 'asdef' is
+ out of date. I only describe the parts that I am sure about. */
+
+struct stk_trailer
+ {
+ long this_address; /* Address of this block. */
+ long this_size; /* Size of this block (does not include
+ this trailer). */
+ long unknown2;
+ long unknown3;
+ long link; /* Address of trailer block of previous
+ segment. */
+ long unknown5;
+ long unknown6;
+ long unknown7;
+ long unknown8;
+ long unknown9;
+ long unknown10;
+ long unknown11;
+ long unknown12;
+ long unknown13;
+ long unknown14;
+ };
+
+#endif /* CRAY2 */
+#endif /* not CRAY_STACK */
+
+#ifdef CRAY2
+/* Determine a "stack measure" for an arbitrary ADDRESS.
+ I doubt that "lint" will like this much. */
+
+static long
+i00afunc (long *address)
+{
+ struct stk_stat status;
+ struct stk_trailer *trailer;
+ long *block, size;
+ long result = 0;
+
+ /* We want to iterate through all of the segments. The first
+ step is to get the stack status structure. We could do this
+ more quickly and more directly, perhaps, by referencing the
+ $LM00 common block, but I know that this works. */
+
+ STKSTAT (&status);
+
+ /* Set up the iteration. */
+
+ trailer = (struct stk_trailer *) (status.current_address
+ + status.current_size
+ - 15);
+
+ /* There must be at least one stack segment. Therefore it is
+ a fatal error if "trailer" is null. */
+
+ if (trailer == 0)
+ abort ();
+
+ /* Discard segments that do not contain our argument address. */
+
+ while (trailer != 0)
+ {
+ block = (long *) trailer->this_address;
+ size = trailer->this_size;
+ if (block == 0 || size == 0)
+ abort ();
+ trailer = (struct stk_trailer *) trailer->link;
+ if ((block <= address) && (address < (block + size)))
+ break;
+ }
+
+ /* Set the result to the offset in this segment and add the sizes
+ of all predecessor segments. */
+
+ result = address - block;
+
+ if (trailer == 0)
+ {
+ return result;
+ }
+
+ do
+ {
+ if (trailer->this_size <= 0)
+ abort ();
+ result += trailer->this_size;
+ trailer = (struct stk_trailer *) trailer->link;
+ }
+ while (trailer != 0);
+
+ /* We are done. Note that if you present a bogus address (one
+ not in any segment), you will get a different number back, formed
+ from subtracting the address of the first block. This is probably
+ not what you want. */
+
+ return (result);
+}
+
+#else /* not CRAY2 */
+/* Stack address function for a CRAY-1, CRAY X-MP, or CRAY Y-MP.
+ Determine the number of the cell within the stack,
+ given the address of the cell. The purpose of this
+ routine is to linearize, in some sense, stack addresses
+ for alloca. */
+
+static long
+i00afunc (long address)
+{
+ long stkl = 0;
+
+ long size, pseg, this_segment, stack;
+ long result = 0;
+
+ struct stack_segment_linkage *ssptr;
+
+ /* Register B67 contains the address of the end of the
+ current stack segment. If you (as a subprogram) store
+ your registers on the stack and find that you are past
+ the contents of B67, you have overflowed the segment.
+
+ B67 also points to the stack segment linkage control
+ area, which is what we are really interested in. */
+
+ stkl = CRAY_STACKSEG_END ();
+ ssptr = (struct stack_segment_linkage *) stkl;
+
+ /* If one subtracts 'size' from the end of the segment,
+ one has the address of the first word of the segment.
+
+ If this is not the first segment, 'pseg' will be
+ nonzero. */
+
+ pseg = ssptr->sspseg;
+ size = ssptr->sssize;
+
+ this_segment = stkl - size;
+
+ /* It is possible that calling this routine itself caused
+ a stack overflow. Discard stack segments which do not
+ contain the target address. */
+
+ while (!(this_segment <= address && address <= stkl))
+ {
+#ifdef DEBUG_I00AFUNC
+ fprintf (stderr, "%011o %011o %011o\n", this_segment, address, stkl);
+#endif
+ if (pseg == 0)
+ break;
+ stkl = stkl - pseg;
+ ssptr = (struct stack_segment_linkage *) stkl;
+ size = ssptr->sssize;
+ pseg = ssptr->sspseg;
+ this_segment = stkl - size;
+ }
+
+ result = address - this_segment;
+
+ /* If you subtract pseg from the current end of the stack,
+ you get the address of the previous stack segment's end.
+ This seems a little convoluted to me, but I'll bet you save
+ a cycle somewhere. */
+
+ while (pseg != 0)
+ {
+#ifdef DEBUG_I00AFUNC
+ fprintf (stderr, "%011o %011o\n", pseg, size);
+#endif
+ stkl = stkl - pseg;
+ ssptr = (struct stack_segment_linkage *) stkl;
+ size = ssptr->sssize;
+ pseg = ssptr->sspseg;
+ result += size;
+ }
+ return (result);
+}
+
+#endif /* not CRAY2 */
+#endif /* CRAY */
+
+#endif /* no alloca */
+#endif /* not GCC version 2 */
diff --git a/contrib/texinfo/libtxi/bzero.c b/contrib/texinfo/libtxi/bzero.c
new file mode 100644
index 0000000..e737382
--- /dev/null
+++ b/contrib/texinfo/libtxi/bzero.c
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 1993 Free Software Foundation, Inc.
+ *
+ * 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, 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, you can either send email to this
+ * program's author (see below) or write to: The Free Software Foundation,
+ * Inc.; 59 Temple Place - Suite 330. Boston, MA 02111-1307, USA.
+ */
+
+#if !defined (HAVE_MEMSET) && !defined (HAVE_BZERO)
+
+void
+bzero (b, length)
+ register char *b;
+ register int length;
+{
+#ifdef VMS /* but this is definitely VMS-specific */
+ short zero = 0;
+ long max_str = 65535;
+
+ while (length > max_str)
+ {
+ (void) LIB$MOVC5 (&zero, &zero, &zero, &max_str, b);
+ length -= max_str;
+ b += max_str;
+ }
+ (void) LIB$MOVC5 (&zero, &zero, &zero, &length, b);
+#else
+ while (length-- > 0)
+ *b++ = 0;
+#endif /* not VMS */
+}
+
+#endif /* not HAVE_MEMSET && not HAVE_BZERO */
diff --git a/contrib/texinfo/libtxi/getopt.c b/contrib/texinfo/libtxi/getopt.c
new file mode 100644
index 0000000..36ebf5c
--- /dev/null
+++ b/contrib/texinfo/libtxi/getopt.c
@@ -0,0 +1,762 @@
+/* Getopt for GNU.
+ NOTE: getopt is now part of the C library, so if you don't know what
+ "Keep this file name-space clean" means, talk to roland@gnu.ai.mit.edu
+ before changing it!
+
+ Copyright (C) 1987, 88, 89, 90, 91, 92, 93, 94, 95
+ Free Software Foundation, Inc.
+
+ 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, 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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* This tells Alpha OSF/1 not to define a getopt prototype in <stdio.h>.
+ Ditto for AIX 3.2 and <stdlib.h>. */
+#ifndef _NO_PROTO
+#define _NO_PROTO
+#endif
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#if !defined (__STDC__) || !__STDC__
+/* This is a separate conditional since some stdc systems
+ reject `defined (const)'. */
+#ifndef const
+#define const
+#endif
+#endif
+
+#include <stdio.h>
+
+/* Comment out all this code if we are using the GNU C Library, and are not
+ actually compiling the library itself. This code is part of the GNU C
+ Library, but also included in many other GNU distributions. Compiling
+ and linking in this code is a waste when using the GNU C library
+ (especially if it is a shared library). Rather than having every GNU
+ program understand `configure --with-gnu-libc' and omit the object files,
+ it is simpler to just do this in the source for each such file. */
+
+#if defined (_LIBC) || !defined (__GNU_LIBRARY__)
+
+
+/* This needs to come after some library #include
+ to get __GNU_LIBRARY__ defined. */
+#ifdef __GNU_LIBRARY__
+/* Don't include stdlib.h for non-GNU C libraries because some of them
+ contain conflicting prototypes for getopt. */
+#include <stdlib.h>
+#endif /* GNU C library. */
+
+/* This is for other GNU distributions with internationalized messages.
+ The GNU C Library itself does not yet support such messages. */
+#if HAVE_LIBINTL_H
+# include <libintl.h>
+#else
+# define gettext(msgid) (msgid)
+#endif
+
+/* This version of `getopt' appears to the caller like standard Unix `getopt'
+ but it behaves differently for the user, since it allows the user
+ to intersperse the options with the other arguments.
+
+ As `getopt' works, it permutes the elements of ARGV so that,
+ when it is done, all the options precede everything else. Thus
+ all application programs are extended to handle flexible argument order.
+
+ Setting the environment variable POSIXLY_CORRECT disables permutation.
+ Then the behavior is completely standard.
+
+ GNU application programs can use a third alternative mode in which
+ they can distinguish the relative order of options and other arguments. */
+
+#include "getopt.h"
+
+/* For communication from `getopt' to the caller.
+ When `getopt' finds an option that takes an argument,
+ the argument value is returned here.
+ Also, when `ordering' is RETURN_IN_ORDER,
+ each non-option ARGV-element is returned here. */
+
+char *optarg = NULL;
+
+/* Index in ARGV of the next element to be scanned.
+ This is used for communication to and from the caller
+ and for communication between successive calls to `getopt'.
+
+ On entry to `getopt', zero means this is the first call; initialize.
+
+ When `getopt' returns EOF, this is the index of the first of the
+ non-option elements that the caller should itself scan.
+
+ Otherwise, `optind' communicates from one call to the next
+ how much of ARGV has been scanned so far. */
+
+/* XXX 1003.2 says this must be 1 before any call. */
+int optind = 0;
+
+/* The next char to be scanned in the option-element
+ in which the last option character we returned was found.
+ This allows us to pick up the scan where we left off.
+
+ If this is zero, or a null string, it means resume the scan
+ by advancing to the next ARGV-element. */
+
+static char *nextchar;
+
+/* Callers store zero here to inhibit the error message
+ for unrecognized options. */
+
+int opterr = 1;
+
+/* Set to an option character which was unrecognized.
+ This must be initialized on some systems to avoid linking in the
+ system's own getopt implementation. */
+
+int optopt = '?';
+
+/* Describe how to deal with options that follow non-option ARGV-elements.
+
+ If the caller did not specify anything,
+ the default is REQUIRE_ORDER if the environment variable
+ POSIXLY_CORRECT is defined, PERMUTE otherwise.
+
+ REQUIRE_ORDER means don't recognize them as options;
+ stop option processing when the first non-option is seen.
+ This is what Unix does.
+ This mode of operation is selected by either setting the environment
+ variable POSIXLY_CORRECT, or using `+' as the first character
+ of the list of option characters.
+
+ PERMUTE is the default. We permute the contents of ARGV as we scan,
+ so that eventually all the non-options are at the end. This allows options
+ to be given in any order, even with programs that were not written to
+ expect this.
+
+ RETURN_IN_ORDER is an option available to programs that were written
+ to expect options and other ARGV-elements in any order and that care about
+ the ordering of the two. We describe each non-option ARGV-element
+ as if it were the argument of an option with character code 1.
+ Using `-' as the first character of the list of option characters
+ selects this mode of operation.
+
+ The special argument `--' forces an end of option-scanning regardless
+ of the value of `ordering'. In the case of RETURN_IN_ORDER, only
+ `--' can cause `getopt' to return EOF with `optind' != ARGC. */
+
+static enum
+{
+ REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER
+} ordering;
+
+/* Value of POSIXLY_CORRECT environment variable. */
+static char *posixly_correct;
+
+#ifdef __GNU_LIBRARY__
+/* We want to avoid inclusion of string.h with non-GNU libraries
+ because there are many ways it can cause trouble.
+ On some systems, it contains special magic macros that don't work
+ in GCC. */
+#include <string.h>
+#define my_index strchr
+#else
+
+/* Avoid depending on library functions or files
+ whose names are inconsistent. */
+
+char *getenv ();
+
+static char *
+my_index (str, chr)
+ const char *str;
+ int chr;
+{
+ while (*str)
+ {
+ if (*str == chr)
+ return (char *) str;
+ str++;
+ }
+ return 0;
+}
+
+/* If using GCC, we can safely declare strlen this way.
+ If not using GCC, it is ok not to declare it. */
+#ifdef __GNUC__
+/* Note that Motorola Delta 68k R3V7 comes with GCC but not stddef.h.
+ That was relevant to code that was here before. */
+#if !defined (__STDC__) || !__STDC__
+/* gcc with -traditional declares the built-in strlen to return int,
+ and has done so at least since version 2.4.5. -- rms. */
+extern int strlen (const char *);
+#endif /* not __STDC__ */
+#endif /* __GNUC__ */
+
+#endif /* not __GNU_LIBRARY__ */
+
+/* Handle permutation of arguments. */
+
+/* Describe the part of ARGV that contains non-options that have
+ been skipped. `first_nonopt' is the index in ARGV of the first of them;
+ `last_nonopt' is the index after the last of them. */
+
+static int first_nonopt;
+static int last_nonopt;
+
+/* Exchange two adjacent subsequences of ARGV.
+ One subsequence is elements [first_nonopt,last_nonopt)
+ which contains all the non-options that have been skipped so far.
+ The other is elements [last_nonopt,optind), which contains all
+ the options processed since those non-options were skipped.
+
+ `first_nonopt' and `last_nonopt' are relocated so that they describe
+ the new indices of the non-options in ARGV after they are moved. */
+
+static void
+exchange (argv)
+ char **argv;
+{
+ int bottom = first_nonopt;
+ int middle = last_nonopt;
+ int top = optind;
+ char *tem;
+
+ /* Exchange the shorter segment with the far end of the longer segment.
+ That puts the shorter segment into the right place.
+ It leaves the longer segment in the right place overall,
+ but it consists of two parts that need to be swapped next. */
+
+ while (top > middle && middle > bottom)
+ {
+ if (top - middle > middle - bottom)
+ {
+ /* Bottom segment is the short one. */
+ int len = middle - bottom;
+ register int i;
+
+ /* Swap it with the top part of the top segment. */
+ for (i = 0; i < len; i++)
+ {
+ tem = argv[bottom + i];
+ argv[bottom + i] = argv[top - (middle - bottom) + i];
+ argv[top - (middle - bottom) + i] = tem;
+ }
+ /* Exclude the moved bottom segment from further swapping. */
+ top -= len;
+ }
+ else
+ {
+ /* Top segment is the short one. */
+ int len = top - middle;
+ register int i;
+
+ /* Swap it with the bottom part of the bottom segment. */
+ for (i = 0; i < len; i++)
+ {
+ tem = argv[bottom + i];
+ argv[bottom + i] = argv[middle + i];
+ argv[middle + i] = tem;
+ }
+ /* Exclude the moved top segment from further swapping. */
+ bottom += len;
+ }
+ }
+
+ /* Update records for the slots the non-options now occupy. */
+
+ first_nonopt += (optind - last_nonopt);
+ last_nonopt = optind;
+}
+
+/* Initialize the internal data when the first call is made. */
+
+static const char *
+_getopt_initialize (optstring)
+ const char *optstring;
+{
+ /* Start processing options with ARGV-element 1 (since ARGV-element 0
+ is the program name); the sequence of previously skipped
+ non-option ARGV-elements is empty. */
+
+ first_nonopt = last_nonopt = optind = 1;
+
+ nextchar = NULL;
+
+ posixly_correct = getenv ("POSIXLY_CORRECT");
+
+ /* Determine how to handle the ordering of options and nonoptions. */
+
+ if (optstring[0] == '-')
+ {
+ ordering = RETURN_IN_ORDER;
+ ++optstring;
+ }
+ else if (optstring[0] == '+')
+ {
+ ordering = REQUIRE_ORDER;
+ ++optstring;
+ }
+ else if (posixly_correct != NULL)
+ ordering = REQUIRE_ORDER;
+ else
+ ordering = PERMUTE;
+
+ return optstring;
+}
+
+/* Scan elements of ARGV (whose length is ARGC) for option characters
+ given in OPTSTRING.
+
+ If an element of ARGV starts with '-', and is not exactly "-" or "--",
+ then it is an option element. The characters of this element
+ (aside from the initial '-') are option characters. If `getopt'
+ is called repeatedly, it returns successively each of the option characters
+ from each of the option elements.
+
+ If `getopt' finds another option character, it returns that character,
+ updating `optind' and `nextchar' so that the next call to `getopt' can
+ resume the scan with the following option character or ARGV-element.
+
+ If there are no more option characters, `getopt' returns `EOF'.
+ Then `optind' is the index in ARGV of the first ARGV-element
+ that is not an option. (The ARGV-elements have been permuted
+ so that those that are not options now come last.)
+
+ OPTSTRING is a string containing the legitimate option characters.
+ If an option character is seen that is not listed in OPTSTRING,
+ return '?' after printing an error message. If you set `opterr' to
+ zero, the error message is suppressed but we still return '?'.
+
+ If a char in OPTSTRING is followed by a colon, that means it wants an arg,
+ so the following text in the same ARGV-element, or the text of the following
+ ARGV-element, is returned in `optarg'. Two colons mean an option that
+ wants an optional arg; if there is text in the current ARGV-element,
+ it is returned in `optarg', otherwise `optarg' is set to zero.
+
+ If OPTSTRING starts with `-' or `+', it requests different methods of
+ handling the non-option ARGV-elements.
+ See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above.
+
+ Long-named options begin with `--' instead of `-'.
+ Their names may be abbreviated as long as the abbreviation is unique
+ or is an exact match for some defined option. If they have an
+ argument, it follows the option name in the same ARGV-element, separated
+ from the option name by a `=', or else the in next ARGV-element.
+ When `getopt' finds a long-named option, it returns 0 if that option's
+ `flag' field is nonzero, the value of the option's `val' field
+ if the `flag' field is zero.
+
+ The elements of ARGV aren't really const, because we permute them.
+ But we pretend they're const in the prototype to be compatible
+ with other systems.
+
+ LONGOPTS is a vector of `struct option' terminated by an
+ element containing a name which is zero.
+
+ LONGIND returns the index in LONGOPT of the long-named option found.
+ It is only valid when a long-named option has been found by the most
+ recent call.
+
+ If LONG_ONLY is nonzero, '-' as well as '--' can introduce
+ long-named options. */
+
+int
+_getopt_internal (argc, argv, optstring, longopts, longind, long_only)
+ int argc;
+ char *const *argv;
+ const char *optstring;
+ const struct option *longopts;
+ int *longind;
+ int long_only;
+{
+ optarg = NULL;
+
+ if (optind == 0)
+ {
+ optstring = _getopt_initialize (optstring);
+ optind = 1; /* Don't scan ARGV[0], the program name. */
+ }
+
+ if (nextchar == NULL || *nextchar == '\0')
+ {
+ /* Advance to the next ARGV-element. */
+
+ if (ordering == PERMUTE)
+ {
+ /* If we have just processed some options following some non-options,
+ exchange them so that the options come first. */
+
+ if (first_nonopt != last_nonopt && last_nonopt != optind)
+ exchange ((char **) argv);
+ else if (last_nonopt != optind)
+ first_nonopt = optind;
+
+ /* Skip any additional non-options
+ and extend the range of non-options previously skipped. */
+
+ while (optind < argc
+ && (argv[optind][0] != '-' || argv[optind][1] == '\0'))
+ optind++;
+ last_nonopt = optind;
+ }
+
+ /* The special ARGV-element `--' means premature end of options.
+ Skip it like a null option,
+ then exchange with previous non-options as if it were an option,
+ then skip everything else like a non-option. */
+
+ if (optind != argc && !strcmp (argv[optind], "--"))
+ {
+ optind++;
+
+ if (first_nonopt != last_nonopt && last_nonopt != optind)
+ exchange ((char **) argv);
+ else if (first_nonopt == last_nonopt)
+ first_nonopt = optind;
+ last_nonopt = argc;
+
+ optind = argc;
+ }
+
+ /* If we have done all the ARGV-elements, stop the scan
+ and back over any non-options that we skipped and permuted. */
+
+ if (optind == argc)
+ {
+ /* Set the next-arg-index to point at the non-options
+ that we previously skipped, so the caller will digest them. */
+ if (first_nonopt != last_nonopt)
+ optind = first_nonopt;
+ return EOF;
+ }
+
+ /* If we have come to a non-option and did not permute it,
+ either stop the scan or describe it to the caller and pass it by. */
+
+ if ((argv[optind][0] != '-' || argv[optind][1] == '\0'))
+ {
+ if (ordering == REQUIRE_ORDER)
+ return EOF;
+ optarg = argv[optind++];
+ return 1;
+ }
+
+ /* We have found another option-ARGV-element.
+ Skip the initial punctuation. */
+
+ nextchar = (argv[optind] + 1
+ + (longopts != NULL && argv[optind][1] == '-'));
+ }
+
+ /* Decode the current option-ARGV-element. */
+
+ /* Check whether the ARGV-element is a long option.
+
+ If long_only and the ARGV-element has the form "-f", where f is
+ a valid short option, don't consider it an abbreviated form of
+ a long option that starts with f. Otherwise there would be no
+ way to give the -f short option.
+
+ On the other hand, if there's a long option "fubar" and
+ the ARGV-element is "-fu", do consider that an abbreviation of
+ the long option, just like "--fu", and not "-f" with arg "u".
+
+ This distinction seems to be the most useful approach. */
+
+ if (longopts != NULL
+ && (argv[optind][1] == '-'
+ || (long_only && (argv[optind][2] || !my_index (optstring, argv[optind][1])))))
+ {
+ char *nameend;
+ const struct option *p;
+ const struct option *pfound = NULL;
+ int exact = 0;
+ int ambig = 0;
+ int indfound;
+ int option_index;
+
+ for (nameend = nextchar; *nameend && *nameend != '='; nameend++)
+ /* Do nothing. */ ;
+
+ /* Test all long options for either exact match
+ or abbreviated matches. */
+ for (p = longopts, option_index = 0; p->name; p++, option_index++)
+ if (!strncmp (p->name, nextchar, nameend - nextchar))
+ {
+ if (nameend - nextchar == strlen (p->name))
+ {
+ /* Exact match found. */
+ pfound = p;
+ indfound = option_index;
+ exact = 1;
+ break;
+ }
+ else if (pfound == NULL)
+ {
+ /* First nonexact match found. */
+ pfound = p;
+ indfound = option_index;
+ }
+ else
+ /* Second or later nonexact match found. */
+ ambig = 1;
+ }
+
+ if (ambig && !exact)
+ {
+ if (opterr)
+ fprintf (stderr, gettext ("%s: option `%s' is ambiguous\n"),
+ argv[0], argv[optind]);
+ nextchar += strlen (nextchar);
+ optind++;
+ return '?';
+ }
+
+ if (pfound != NULL)
+ {
+ option_index = indfound;
+ optind++;
+ if (*nameend)
+ {
+ /* Don't test has_arg with >, because some C compilers don't
+ allow it to be used on enums. */
+ if (pfound->has_arg)
+ optarg = nameend + 1;
+ else
+ {
+ if (opterr)
+ if (argv[optind - 1][1] == '-')
+ /* --option */
+ fprintf (stderr,
+ gettext ("%s: option `--%s' doesn't allow an argument\n"),
+ argv[0], pfound->name);
+ else
+ /* +option or -option */
+ fprintf (stderr,
+ gettext ("%s: option `%c%s' doesn't allow an argument\n"),
+ argv[0], argv[optind - 1][0], pfound->name);
+
+ nextchar += strlen (nextchar);
+ return '?';
+ }
+ }
+ else if (pfound->has_arg == 1)
+ {
+ if (optind < argc)
+ optarg = argv[optind++];
+ else
+ {
+ if (opterr)
+ fprintf (stderr,
+ gettext ("%s: option `%s' requires an argument\n"),
+ argv[0], argv[optind - 1]);
+ nextchar += strlen (nextchar);
+ return optstring[0] == ':' ? ':' : '?';
+ }
+ }
+ nextchar += strlen (nextchar);
+ if (longind != NULL)
+ *longind = option_index;
+ if (pfound->flag)
+ {
+ *(pfound->flag) = pfound->val;
+ return 0;
+ }
+ return pfound->val;
+ }
+
+ /* Can't find it as a long option. If this is not getopt_long_only,
+ or the option starts with '--' or is not a valid short
+ option, then it's an error.
+ Otherwise interpret it as a short option. */
+ if (!long_only || argv[optind][1] == '-'
+ || my_index (optstring, *nextchar) == NULL)
+ {
+ if (opterr)
+ {
+ if (argv[optind][1] == '-')
+ /* --option */
+ fprintf (stderr, gettext ("%s: unrecognized option `--%s'\n"),
+ argv[0], nextchar);
+ else
+ /* +option or -option */
+ fprintf (stderr, gettext ("%s: unrecognized option `%c%s'\n"),
+ argv[0], argv[optind][0], nextchar);
+ }
+ nextchar = (char *) "";
+ optind++;
+ return '?';
+ }
+ }
+
+ /* Look at and handle the next short option-character. */
+
+ {
+ char c = *nextchar++;
+ char *temp = my_index (optstring, c);
+
+ /* Increment `optind' when we start to process its last character. */
+ if (*nextchar == '\0')
+ ++optind;
+
+ if (temp == NULL || c == ':')
+ {
+ if (opterr)
+ {
+ if (posixly_correct)
+ /* 1003.2 specifies the format of this message. */
+ fprintf (stderr, gettext ("%s: illegal option -- %c\n"),
+ argv[0], c);
+ else
+ fprintf (stderr, gettext ("%s: invalid option -- %c\n"),
+ argv[0], c);
+ }
+ optopt = c;
+ return '?';
+ }
+ if (temp[1] == ':')
+ {
+ if (temp[2] == ':')
+ {
+ /* This is an option that accepts an argument optionally. */
+ if (*nextchar != '\0')
+ {
+ optarg = nextchar;
+ optind++;
+ }
+ else
+ optarg = NULL;
+ nextchar = NULL;
+ }
+ else
+ {
+ /* This is an option that requires an argument. */
+ if (*nextchar != '\0')
+ {
+ optarg = nextchar;
+ /* If we end this ARGV-element by taking the rest as an arg,
+ we must advance to the next element now. */
+ optind++;
+ }
+ else if (optind == argc)
+ {
+ if (opterr)
+ {
+ /* 1003.2 specifies the format of this message. */
+ fprintf (stderr,
+ gettext ("%s: option requires an argument -- %c\n"),
+ argv[0], c);
+ }
+ optopt = c;
+ if (optstring[0] == ':')
+ c = ':';
+ else
+ c = '?';
+ }
+ else
+ /* We already incremented `optind' once;
+ increment it again when taking next ARGV-elt as argument. */
+ optarg = argv[optind++];
+ nextchar = NULL;
+ }
+ }
+ return c;
+ }
+}
+
+int
+getopt (argc, argv, optstring)
+ int argc;
+ char *const *argv;
+ const char *optstring;
+{
+ return _getopt_internal (argc, argv, optstring,
+ (const struct option *) 0,
+ (int *) 0,
+ 0);
+}
+
+#endif /* _LIBC or not __GNU_LIBRARY__. */
+
+#ifdef TEST
+
+/* Compile with -DTEST to make an executable for use in testing
+ the above definition of `getopt'. */
+
+int
+main (argc, argv)
+ int argc;
+ char **argv;
+{
+ int c;
+ int digit_optind = 0;
+
+ while (1)
+ {
+ int this_option_optind = optind ? optind : 1;
+
+ c = getopt (argc, argv, "abc:d:0123456789");
+ if (c == EOF)
+ break;
+
+ switch (c)
+ {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ if (digit_optind != 0 && digit_optind != this_option_optind)
+ printf ("digits occur in two different argv-elements.\n");
+ digit_optind = this_option_optind;
+ printf ("option %c\n", c);
+ break;
+
+ case 'a':
+ printf ("option a\n");
+ break;
+
+ case 'b':
+ printf ("option b\n");
+ break;
+
+ case 'c':
+ printf ("option c with value `%s'\n", optarg);
+ break;
+
+ case '?':
+ break;
+
+ default:
+ printf ("?? getopt returned character code 0%o ??\n", c);
+ }
+ }
+
+ if (optind < argc)
+ {
+ printf ("non-option ARGV-elements: ");
+ while (optind < argc)
+ printf ("%s ", argv[optind++]);
+ printf ("\n");
+ }
+
+ exit (0);
+}
+
+#endif /* TEST */
diff --git a/contrib/texinfo/libtxi/getopt.h b/contrib/texinfo/libtxi/getopt.h
new file mode 100644
index 0000000..952f483
--- /dev/null
+++ b/contrib/texinfo/libtxi/getopt.h
@@ -0,0 +1,129 @@
+/* Declarations for getopt.
+ Copyright (C) 1989, 90, 91, 92, 93, 94 Free Software Foundation, Inc.
+
+ 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, 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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifndef _GETOPT_H
+#define _GETOPT_H 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* For communication from `getopt' to the caller.
+ When `getopt' finds an option that takes an argument,
+ the argument value is returned here.
+ Also, when `ordering' is RETURN_IN_ORDER,
+ each non-option ARGV-element is returned here. */
+
+extern char *optarg;
+
+/* Index in ARGV of the next element to be scanned.
+ This is used for communication to and from the caller
+ and for communication between successive calls to `getopt'.
+
+ On entry to `getopt', zero means this is the first call; initialize.
+
+ When `getopt' returns EOF, this is the index of the first of the
+ non-option elements that the caller should itself scan.
+
+ Otherwise, `optind' communicates from one call to the next
+ how much of ARGV has been scanned so far. */
+
+extern int optind;
+
+/* Callers store zero here to inhibit the error message `getopt' prints
+ for unrecognized options. */
+
+extern int opterr;
+
+/* Set to an option character which was unrecognized. */
+
+extern int optopt;
+
+/* Describe the long-named options requested by the application.
+ The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector
+ of `struct option' terminated by an element containing a name which is
+ zero.
+
+ The field `has_arg' is:
+ no_argument (or 0) if the option does not take an argument,
+ required_argument (or 1) if the option requires an argument,
+ optional_argument (or 2) if the option takes an optional argument.
+
+ If the field `flag' is not NULL, it points to a variable that is set
+ to the value given in the field `val' when the option is found, but
+ left unchanged if the option is not found.
+
+ To have a long-named option do something other than set an `int' to
+ a compiled-in constant, such as set a value from `optarg', set the
+ option's `flag' field to zero and its `val' field to a nonzero
+ value (the equivalent single-letter option character, if there is
+ one). For long options that have a zero `flag' field, `getopt'
+ returns the contents of the `val' field. */
+
+struct option
+{
+#if defined (__STDC__) && __STDC__
+ const char *name;
+#else
+ char *name;
+#endif
+ /* has_arg can't be an enum because some compilers complain about
+ type mismatches in all the code that assumes it is an int. */
+ int has_arg;
+ int *flag;
+ int val;
+};
+
+/* Names for the values of the `has_arg' field of `struct option'. */
+
+#define no_argument 0
+#define required_argument 1
+#define optional_argument 2
+
+#if defined (__STDC__) && __STDC__
+#ifdef __GNU_LIBRARY__
+/* Many other libraries have conflicting prototypes for getopt, with
+ differences in the consts, in stdlib.h. To avoid compilation
+ errors, only prototype getopt for the GNU C library. */
+extern int getopt (int argc, char *const *argv, const char *shortopts);
+#else /* not __GNU_LIBRARY__ */
+extern int getopt ();
+#endif /* __GNU_LIBRARY__ */
+extern int getopt_long (int argc, char *const *argv, const char *shortopts,
+ const struct option *longopts, int *longind);
+extern int getopt_long_only (int argc, char *const *argv,
+ const char *shortopts,
+ const struct option *longopts, int *longind);
+
+/* Internal only. Users should not call this directly. */
+extern int _getopt_internal (int argc, char *const *argv,
+ const char *shortopts,
+ const struct option *longopts, int *longind,
+ int long_only);
+#else /* not __STDC__ */
+extern int getopt ();
+extern int getopt_long ();
+extern int getopt_long_only ();
+
+extern int _getopt_internal ();
+#endif /* __STDC__ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _GETOPT_H */
diff --git a/contrib/texinfo/libtxi/getopt1.c b/contrib/texinfo/libtxi/getopt1.c
new file mode 100644
index 0000000..7cf0bfb
--- /dev/null
+++ b/contrib/texinfo/libtxi/getopt1.c
@@ -0,0 +1,180 @@
+/* getopt_long and getopt_long_only entry points for GNU getopt.
+ Copyright (C) 1987, 88, 89, 90, 91, 92, 1993, 1994
+ Free Software Foundation, Inc.
+
+ 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, 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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "getopt.h"
+
+#if !defined (__STDC__) || !__STDC__
+/* This is a separate conditional since some stdc systems
+ reject `defined (const)'. */
+#ifndef const
+#define const
+#endif
+#endif
+
+#include <stdio.h>
+
+/* Comment out all this code if we are using the GNU C Library, and are not
+ actually compiling the library itself. This code is part of the GNU C
+ Library, but also included in many other GNU distributions. Compiling
+ and linking in this code is a waste when using the GNU C library
+ (especially if it is a shared library). Rather than having every GNU
+ program understand `configure --with-gnu-libc' and omit the object files,
+ it is simpler to just do this in the source for each such file. */
+
+#if defined (_LIBC) || !defined (__GNU_LIBRARY__)
+
+
+/* This needs to come after some library #include
+ to get __GNU_LIBRARY__ defined. */
+#ifdef __GNU_LIBRARY__
+#include <stdlib.h>
+#else
+char *getenv ();
+#endif
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+int
+getopt_long (argc, argv, options, long_options, opt_index)
+ int argc;
+ char *const *argv;
+ const char *options;
+ const struct option *long_options;
+ int *opt_index;
+{
+ return _getopt_internal (argc, argv, options, long_options, opt_index, 0);
+}
+
+/* Like getopt_long, but '-' as well as '--' can indicate a long option.
+ If an option that starts with '-' (not '--') doesn't match a long option,
+ but does match a short option, it is parsed as a short option
+ instead. */
+
+int
+getopt_long_only (argc, argv, options, long_options, opt_index)
+ int argc;
+ char *const *argv;
+ const char *options;
+ const struct option *long_options;
+ int *opt_index;
+{
+ return _getopt_internal (argc, argv, options, long_options, opt_index, 1);
+}
+
+
+#endif /* _LIBC or not __GNU_LIBRARY__. */
+
+#ifdef TEST
+
+#include <stdio.h>
+
+int
+main (argc, argv)
+ int argc;
+ char **argv;
+{
+ int c;
+ int digit_optind = 0;
+
+ while (1)
+ {
+ int this_option_optind = optind ? optind : 1;
+ int option_index = 0;
+ static struct option long_options[] =
+ {
+ {"add", 1, 0, 0},
+ {"append", 0, 0, 0},
+ {"delete", 1, 0, 0},
+ {"verbose", 0, 0, 0},
+ {"create", 0, 0, 0},
+ {"file", 1, 0, 0},
+ {0, 0, 0, 0}
+ };
+
+ c = getopt_long (argc, argv, "abc:d:0123456789",
+ long_options, &option_index);
+ if (c == EOF)
+ break;
+
+ switch (c)
+ {
+ case 0:
+ printf ("option %s", long_options[option_index].name);
+ if (optarg)
+ printf (" with arg %s", optarg);
+ printf ("\n");
+ break;
+
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ if (digit_optind != 0 && digit_optind != this_option_optind)
+ printf ("digits occur in two different argv-elements.\n");
+ digit_optind = this_option_optind;
+ printf ("option %c\n", c);
+ break;
+
+ case 'a':
+ printf ("option a\n");
+ break;
+
+ case 'b':
+ printf ("option b\n");
+ break;
+
+ case 'c':
+ printf ("option c with value `%s'\n", optarg);
+ break;
+
+ case 'd':
+ printf ("option d with value `%s'\n", optarg);
+ break;
+
+ case '?':
+ break;
+
+ default:
+ printf ("?? getopt returned character code 0%o ??\n", c);
+ }
+ }
+
+ if (optind < argc)
+ {
+ printf ("non-option ARGV-elements: ");
+ while (optind < argc)
+ printf ("%s ", argv[optind++]);
+ printf ("\n");
+ }
+
+ exit (0);
+}
+
+#endif /* TEST */
diff --git a/contrib/texinfo/libtxi/memcpy.c b/contrib/texinfo/libtxi/memcpy.c
new file mode 100644
index 0000000..5216254
--- /dev/null
+++ b/contrib/texinfo/libtxi/memcpy.c
@@ -0,0 +1,20 @@
+/* Copy LEN bytes starting at SRCADDR to DESTADDR. Result undefined
+ if the source overlaps with the destination.
+ Return DESTADDR. */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+char *
+memcpy (destaddr, srcaddr, len)
+ char *destaddr;
+ const char *srcaddr;
+ int len;
+{
+ char *dest = destaddr;
+
+ while (len-- > 0)
+ *destaddr++ = *srcaddr++;
+ return dest;
+}
diff --git a/contrib/texinfo/libtxi/memmove.c b/contrib/texinfo/libtxi/memmove.c
new file mode 100644
index 0000000..d7bdd7c
--- /dev/null
+++ b/contrib/texinfo/libtxi/memmove.c
@@ -0,0 +1,24 @@
+/* memmove.c -- copy memory.
+ Copy LENGTH bytes from SOURCE to DEST. Does not null-terminate.
+ In the public domain.
+ By David MacKenzie <djm@gnu.ai.mit.edu>. */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+void
+memmove (dest, source, length)
+ char *dest;
+ const char *source;
+ unsigned length;
+{
+ if (source < dest)
+ /* Moving from low mem to hi mem; start at end. */
+ for (source += length, dest += length; length; --length)
+ *--dest = *--source;
+ else if (source != dest)
+ /* Moving from hi mem to low mem; start at beginning. */
+ for (; length; --length)
+ *dest++ = *source++;
+}
diff --git a/contrib/texinfo/libtxi/strdup.c b/contrib/texinfo/libtxi/strdup.c
new file mode 100644
index 0000000..1d60f13
--- /dev/null
+++ b/contrib/texinfo/libtxi/strdup.c
@@ -0,0 +1,43 @@
+/* strdup.c -- return a newly allocated copy of a string
+ Copyright (C) 1990 Free Software Foundation, Inc.
+
+ 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, 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. */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifdef STDC_HEADERS
+#include <string.h>
+#include <stdlib.h>
+#else
+char *malloc ();
+char *strcpy ();
+#endif
+
+/* Return a newly allocated copy of STR,
+ or 0 if out of memory. */
+
+char *
+strdup (str)
+ const char *str;
+{
+ char *newstr;
+
+ newstr = (char *) malloc (strlen (str) + 1);
+ if (newstr)
+ strcpy (newstr, str);
+ return newstr;
+}
diff --git a/contrib/texinfo/makeinfo/Makefile.in b/contrib/texinfo/makeinfo/Makefile.in
new file mode 100644
index 0000000..d08ee36
--- /dev/null
+++ b/contrib/texinfo/makeinfo/Makefile.in
@@ -0,0 +1,112 @@
+# Makefile for GNU makeinfo.
+# $Id: Makefile.in,v 1.9 1996/10/01 21:45:00 karl Exp $
+#
+# Copyright (C) 1993, 96 Free Software Foundation, Inc.
+
+# 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+#### Start of system configuration section. ####
+
+srcdir = @srcdir@
+VPATH = $(srcdir):$(common)
+
+common = $(srcdir)/../libtxi
+
+CC = @CC@
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_DATA = @INSTALL_DATA@
+
+LN = ln
+RM = rm -f
+MKDIR = mkdir
+
+DEFS = @DEFS@
+LIBS = -L../libtxi -ltxi @LIBS@
+LOADLIBES = $(LIBS)
+
+SHELL = /bin/sh
+
+CFLAGS = @CFLAGS@
+LDFLAGS = @LDFLAGS@
+
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+bindir = $(exec_prefix)/bin
+# Prefix for each installed program, normally empty or `g'.
+binprefix =
+infodir = $(prefix)/info
+
+#### End of system configuration section. ####
+
+SRCS = makeinfo.c multi.c
+OBJS = makeinfo.o multi.o
+
+PROGS = makeinfo
+
+all: $(PROGS) makeinfo.info
+sub-all: all
+
+.c.o:
+ $(CC) -c $(CPPFLAGS) -I. -I$(srcdir) -I$(common) $(DEFS) $(CFLAGS) $<
+
+makeinfo: $(OBJS) ../libtxi/libtxi.a
+ $(CC) $(LDFLAGS) -o makeinfo $(OBJS) $(LOADLIBES)
+
+../libtxi/libtxi.a:
+ (cd ../libtxi && $(MAKE) $(MFLAGS) libtxi.a)
+
+makeinfo.o: makeinfo.c $(common)/getopt.h
+
+$(OBJS): makeinfo.h
+
+info makeinfo.info: ./makeinfo makeinfo.texi #macro.texi
+ ./makeinfo --no-split -I$(srcdir) makeinfo.texi
+
+# makeinfo.texi: ./makeinfo makeinfo.mki
+# ./makeinfo -E makeinfo.texi -I$(srcdir) makeinfo.mki
+
+dvi makeinfo.dvi: ./makeinfo makeinfo.texi #macro.texi
+ $(srcdir)/../util/texi2dvi makeinfo.txi
+
+install: all
+ $(INSTALL_PROGRAM) makeinfo $(bindir)/$(binprefix)makeinfo
+ -d=$(srcdir); test -f ./makeinfo.info && d=.; $(INSTALL_DATA) $$d/makeinfo.info $(infodir)/makeinfo.info
+ $(POST_INSTALL)
+ ../util/install-info --info-dir=$(infodir) $(infodir)/makeinfo.info
+
+uninstall:
+ for f in $(PROGS); do rm -f $(bindir)/$(binprefix)$$f; done
+ rm -f $(infodir)/makeinfo.info
+
+TAGS: $(SRCS)
+ etags $(SRCS)
+
+clean:
+ rm -f *.o a.out core core.* $(PROGS)
+
+mostlyclean: clean
+
+distclean: clean
+ rm -f TAGS Makefile config.status *.info */*.info
+
+realclean: distclean
+maintainer-clean: distclean
+
+Makefile: Makefile.in ../config.status
+ cd .. && sh config.status
+
+# Prevent GNU make v3 from overflowing arg limit on SysV.
+.NOEXPORT:
diff --git a/contrib/texinfo/makeinfo/macro.texi b/contrib/texinfo/makeinfo/macro.texi
new file mode 100644
index 0000000..8a3fe80
--- /dev/null
+++ b/contrib/texinfo/makeinfo/macro.texi
@@ -0,0 +1,177 @@
+@c This file is included in makeinfo.texi.
+@c
+@ifinfo
+@comment Here are some useful examples of the macro facility.
+
+@c Simply insert the right version of the texinfo name.
+@macro texinfo{}
+TeXinfo
+@end macro
+
+@macro dfn{text}
+@dfn{\text\}
+@cpindex \text\
+@end macro
+
+@c Define a macro which expands to a pretty version of the name of the
+@c Makeinfo program.
+@macro makeinfo{}
+@code{Makeinfo}
+@end macro
+
+@c Define a macro which is used to define other macros. This one makes
+@c a macro which creates a node and gives it a sectioning command. Note
+@c that the created macro uses the original definition within the
+@c expansion text. This takes advantage of the non-recursion feature of
+@c macro execution.
+@macro node_define{orig-name}
+@macro \orig-name\{title}
+@node \title\
+@\orig-name\ \title\
+@end macro
+@end macro
+
+@c Now actually define a new set of sectioning commands.
+@node_define {chapter}
+@node_define {section}
+@node_define {subsection}
+@end ifinfo
+
+@chapter The Macro Facility
+
+This chapter describes the new macro facility.
+
+A @dfn{macro} is a command that you define in terms of other commands.
+It doesn't exist as a @texinfo{} command until you define it as part of
+the input file to @makeinfo{}. Once the command exists, it behaves much
+as any other @texinfo{} command. Macros are a useful way to ease the
+details and tedium of writing a `correct' info file. The following
+sections explain how to write and invoke macros.
+
+@menu
+* How to Use Macros in @texinfo{}::
+ How to use the macro facility.
+
+* Using Macros Recursively::
+ How to write a macro which does (or doesn't) recurse.
+
+* Using @texinfo{} Macros As Arguments::
+ Passing a macro as an argument.
+@end menu
+
+@section How to Use Macros in @texinfo{}
+
+Using macros in @texinfo{} is easy. First you define the macro. After
+that, the macro command is available as a normal @texinfo{} command.
+Here is what a definition looks like:
+
+@example
+@@macro @var{name}@{@var{arg1}, @var{@dots{}} @var{argn}@}
+@var{@texinfo{} commands@dots{}}
+@@end macro
+@end example
+
+The arguments that you specify that the macro takes are expanded with
+the actual parameters used when calling the macro if they are seen
+surrounded by backslashes. For example, here is a definition of
+@code{@@codeitem}, a macro which can be used wherever @code{@@item} can
+be used, but which surrounds its argument with @code{@@code@{@dots{}@}}.
+
+@example
+@@macro codeitem@{item@}
+@@item @@code@{\item\@}
+@@end macro
+@end example
+
+When the macro is expanded, all of the text between the @code{@@macro}
+and @code{@@end macro} is inserted into the document at the expansion
+point, with the actual parameters substituted for the named parameters.
+So, a call to the above macro might look like:
+
+@example
+@@codeitem@{Foo@}
+@end example
+
+and @makeinfo{} would execute the following code:
+
+@example
+@@item @@code@{Foo@}
+@end example
+
+A special case is made for macros which only take a single argument, and
+which are invoked without any brace characters (i.e.,
+@samp{@{}@dots{}@samp{@}}) surrounding an argument; the rest of the line
+is supplied as is as the sole argument to the macro. This special case
+allows one to redefine some standard @texinfo{} commands without
+modifying the input file. Along with the non-recursive action of macro
+invocation, one can easily redefine the sectioning commands to also
+provide index entries:
+
+@example
+@@macro chapter@{name@}
+@@chapter \name\
+@@findex \name\
+@@end macro
+@end example
+
+Thus, the text:
+
+@example
+@@chapter strlen
+@end example
+
+will expand to:
+
+@example
+@@chapter strlen
+@@findex strlen
+@end example
+
+@section Using Macros Recursively
+
+Normally, while a particular macro is executing, any call to that macro
+will be seen as a call to a builtin @texinfo{} command. This allows one
+to redefine a builtin @texinfo{} command as a macro, and then use that
+command within the definition of the macro itself. For example, one
+might wish to make sure that whereever a term was defined with
+@code{@@dfn@{@dots{}@}}, the location of the definition would appear
+in the concept index for the manual. Here is a macro which redefines
+@code{@@dfn} to do just that:
+
+@example
+@@macro dfn@{text@}
+@@dfn@{\text\@}
+@@cpindex \text\
+@@end macro
+@end example
+
+Note that we used the builtin @texinfo{} command @code{@@dfn} within our
+overriding macro definition.
+
+This behaviour itself can be overridden for macro execution by writing a
+special @dfn{macro control command} in the definition of the macro. The
+command is considered special because it doesn't affect the output text
+directly, rather, it affects the way in which the macro is defined. One
+such special command is @code{@@allow-recursion}.
+
+@example
+@@macro silly@{arg@}
+@@allow-recursion
+\arg\
+@@end macro
+@end example
+
+Now @code{@@silly} is a macro that can be used within a call to itself:
+
+@example
+This text @@silly@{@@silly@{some text@}@} is ``some text''.
+@end example
+
+@section Using @texinfo{} Macros As Arguments
+
+@printindex cp
+How to use @texinfo{} macros as arguments to other @texinfo{} macros.
+
+@bye
+
+
diff --git a/contrib/texinfo/makeinfo/makeinfo.c b/contrib/texinfo/makeinfo/makeinfo.c
new file mode 100644
index 0000000..ee12ef2
--- /dev/null
+++ b/contrib/texinfo/makeinfo/makeinfo.c
@@ -0,0 +1,9349 @@
+/* Makeinfo -- convert texinfo format files into info files.
+ $Id: makeinfo.c,v 1.37 1996/10/04 18:20:52 karl Exp $
+
+ Copyright (C) 1987, 92, 93, 94, 95, 96 Free Software Foundation, Inc.
+
+ 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Makeinfo is authored by Brian Fox (bfox@ai.mit.edu). */
+
+int major_version = 1;
+int minor_version = 67;
+
+/* You can change some of the behaviour of Makeinfo by changing the
+ following defines: */
+
+/* Define INDENT_PARAGRAPHS_IN_TABLE if you want the paragraphs which
+ appear within an @table, @ftable, or @itemize environment to have
+ standard paragraph indentation. Without this, such paragraphs have
+ no starting indentation. */
+/* #define INDENT_PARAGRAPHS_IN_TABLE */
+
+/* Define DEFAULT_INDENTATION_INCREMENT as an integer which is the amount
+ that @example should increase indentation by. This incremement is used
+ for all insertions which indent the enclosed text. */
+#define DEFAULT_INDENTATION_INCREMENT 5
+
+/* Define PARAGRAPH_START_INDENT to be the amount of indentation that
+ the first lines of paragraphs receive by default, where no other
+ value has been specified. Users can change this value on the command
+ line, with the --paragraph-indent option, or within the texinfo file,
+ with the @paragraphindent command. */
+#define PARAGRAPH_START_INDENT 3
+
+/* Define DEFAULT_PARAGRAPH_SPACING as the number of blank lines that you
+ wish to appear between paragraphs. A value of 1 creates a single blank
+ line between paragraphs. Paragraphs are defined by 2 or more consecutive
+ newlines in the input file (i.e., one or more blank lines). */
+#define DEFAULT_PARAGRAPH_SPACING 1
+
+/* Define HAVE_MACROS to enable the macro facility of Texinfo. Using this
+ facility, users can create their own command procedures with arguments. */
+#define HAVE_MACROS
+
+
+/* Indent #pragma so that older Cpp's don't try to parse it. */
+#if defined (_AIX)
+ # pragma alloca
+#endif /* _AIX */
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <ctype.h>
+#include <sys/stat.h>
+#include <pwd.h>
+#include <errno.h>
+
+#if defined (HAVE_VARARGS_H)
+#include <varargs.h>
+#endif /* HAVE_VARARGS_H */
+#include "getopt.h"
+
+#if defined (HAVE_UNISTD_H)
+#include <unistd.h>
+#endif /* HAVE_UNISTD_H */
+
+#if defined (VMS)
+#include <perror.h>
+#endif
+
+#if defined (HAVE_STRING_H)
+#include <string.h>
+#else
+#include <strings.h>
+#endif /* !HAVE_STRING_H */
+
+#if defined (TM_IN_SYS_TIME)
+#include <sys/time.h>
+#else
+#include <time.h>
+#endif /* !TM_IN_SYS_TIME */
+
+#if defined (HAVE_SYS_FCNTL_H)
+#include <sys/fcntl.h>
+#else
+#include <fcntl.h>
+#endif /* !HAVE_SYS_FCNTL_H */
+
+#if defined (HAVE_SYS_FILE_H)
+#include <sys/file.h>
+#endif /* HAVE_SYS_FILE_H */
+
+#if defined (__GNUC__)
+#define alloca __builtin_alloca
+#else
+#if defined(HAVE_ALLOCA_H)
+#include <alloca.h>
+#else /* !HAVE_ALLOCA_H */
+#if !defined (_AIX)
+extern char *alloca ();
+#endif /* !_AIX */
+#endif /* !HAVE_ALLOCA_H */
+#endif /* !__GNUC__ */
+
+void *xmalloc (), *xrealloc ();
+#if defined (__osf__)
+extern void *malloc (), *realloc ();
+#endif /* __osf__ */
+
+char **get_brace_args ();
+int array_len ();
+void free_array ();
+static void isolate_nodename ();
+
+#define COMPILING_MAKEINFO
+#include "makeinfo.h"
+
+/* Non-zero means that we are currently hacking the insides of an
+ insertion which would use a fixed width font. */
+static int in_fixed_width_font = 0;
+
+/* Non-zero means that start_paragraph () MUST be called before we pay
+ any attention to close_paragraph () calls. */
+int must_start_paragraph = 0;
+
+/* Non-zero means a string is in execution, as opposed to a file. */
+static int executing_string = 0;
+
+#if defined (HAVE_MACROS)
+/* If non-NULL, this is an output stream to write the full macro expansion
+ of the input text to. The resultant file is another texinfo file, but
+ missing @include, @infoinclude, @macro, and macro invocations. Instead,
+ all of the text is placed within the file. */
+FILE *macro_expansion_output_stream = (FILE *)NULL;
+
+/* Here is a structure used to remember input text strings and offsets
+ within them. */
+typedef struct {
+ char *pointer; /* Pointer to the input text. */
+ int offset; /* Offset of the last character output. */
+} ITEXT;
+
+static ITEXT **itext_info = (ITEXT **)NULL;
+static int itext_size = 0;
+
+/* Non-zero means to inhibit the writing of macro expansions to the output
+ stream. This is used in special cases where the output has already been
+ written. */
+int me_inhibit_expansion = 0;
+
+ITEXT *remember_itext ();
+void forget_itext (), me_append_before_this_command ();
+void append_to_expansion_output (), write_region_to_macro_output ();
+void maybe_write_itext (), me_execute_string ();
+#endif /* HAVE_MACROS */
+
+/* Some systems don't declare this function in pwd.h. */
+struct passwd *getpwnam ();
+
+/* **************************************************************** */
+/* */
+/* Global Variables */
+/* */
+/* **************************************************************** */
+
+/* Global pointer to argv[0]. */
+char *progname;
+
+/* Return non-zero if STRING is the text at input_text + input_text_offset,
+ else zero. */
+#define looking_at(string) \
+ (strncmp (input_text + input_text_offset, string, strlen (string)) == 0)
+
+/* And writing to the output. */
+
+/* The output file name. */
+char *output_filename = (char *)NULL;
+char *pretty_output_filename;
+
+/* Name of the output file that the user elected to pass on the command line.
+ Such a name overrides any name found with the @setfilename command. */
+char *command_output_filename = (char *)NULL;
+
+/* A colon separated list of directories to search for files included
+ with @include. This can be controlled with the `-I' option to makeinfo. */
+char *include_files_path = (char *)NULL;
+
+/* Current output stream. */
+FILE *output_stream;
+
+/* Position in the output file. */
+int output_position;
+
+#define INITIAL_PARAGRAPH_SPACE 5000
+int paragraph_buffer_len = INITIAL_PARAGRAPH_SPACE;
+
+/* Filling.. */
+/* Non-zero indicates that filling will take place on long lines. */
+int filling_enabled = 1;
+
+/* Non-zero means that words are not to be split, even in long lines. This
+ gets changed for cm_w (). */
+int non_splitting_words = 0;
+
+/* Non-zero indicates that filling a line also indents the new line. */
+int indented_fill = 0;
+
+/* The amount of indentation to add at the starts of paragraphs.
+ 0 means don't change existing indentation at paragraph starts.
+ > 0 is amount to indent new paragraphs by.
+ < 0 means indent to column zero by removing indentation if necessary.
+
+ This is normally zero, but some people prefer paragraph starts to be
+ somewhat more indented than paragraph bodies. A pretty value for
+ this is 3. */
+int paragraph_start_indent = PARAGRAPH_START_INDENT;
+
+/* Non-zero means that the use of paragraph_start_indent is inhibited.
+ @example uses this to line up the left columns of the example text.
+ A negative value for this variable is incremented each time it is used.
+ @noindent uses this to inhibit indentation for a single paragraph. */
+int inhibit_paragraph_indentation = 0;
+
+/* Indentation that is pending insertion. We have this for hacking lines
+ which look blank, but contain whitespace. We want to treat those as
+ blank lines. */
+int pending_indent = 0;
+
+/* The amount that indentation increases/decreases by. */
+int default_indentation_increment = DEFAULT_INDENTATION_INCREMENT;
+
+/* Non-zero indicates that indentation is temporarily turned off. */
+int no_indent = 1;
+
+/* Non-zero means forcing output text to be flushright. */
+int force_flush_right = 0;
+
+/* Non-zero means that the footnote style for this document was set on
+ the command line, which overrides any other settings. */
+int footnote_style_preset = 0;
+
+/* Non-zero means that we automatically number footnotes that have no
+ specified marker. */
+int number_footnotes = 1;
+
+/* The current footnote number in this node. Each time a new node is
+ started this is reset to 1. */
+int current_footnote_number = 1;
+
+/* Command name in the process of being hacked. */
+char *command;
+
+/* The index in our internal command table of the currently
+ executing command. */
+int command_index;
+
+/* A search string which is used to find a line defining a node. */
+char node_search_string[] =
+ { '\n', COMMAND_PREFIX, 'n', 'o', 'd', 'e', ' ', '\0' };
+
+/* A search string which is used to find a line defining a menu. */
+char menu_search_string[] =
+ { '\n', COMMAND_PREFIX, 'm', 'e', 'n', 'u', '\0' };
+
+/* A search string which is used to find the first @setfilename. */
+char setfilename_search[] =
+ { COMMAND_PREFIX,
+ 's', 'e', 't', 'f', 'i', 'l', 'e', 'n', 'a', 'm', 'e', '\0' };
+
+/* A stack of file information records. If a new file is read in with
+ "@input", we remember the old input file state on this stack. */
+typedef struct fstack
+{
+ struct fstack *next;
+ char *filename;
+ char *text;
+ int size;
+ int offset;
+ int line_number;
+} FSTACK;
+
+FSTACK *filestack = (FSTACK *) NULL;
+
+/* Stuff for nodes. */
+/* The current nodes node name. */
+char *current_node = (char *)NULL;
+
+/* The current nodes section level. */
+int current_section = 0;
+
+/* The filename of the current input file. This is never freed. */
+char *node_filename = (char *)NULL;
+
+/* What we remember for each node. */
+typedef struct tentry
+{
+ struct tentry *next_ent;
+ char *node; /* name of this node. */
+ char *prev; /* name of "Prev:" for this node. */
+ char *next; /* name of "Next:" for this node. */
+ char *up; /* name of "Up:" for this node. */
+ int position; /* output file position of this node. */
+ int line_no; /* defining line in source file. */
+ char *filename; /* The file that this node was found in. */
+ int touched; /* non-zero means this node has been referenced. */
+ int flags; /* Room for growth. Right now, contains 1 bit. */
+} TAG_ENTRY;
+
+/* If node-a has a "Next" for node-b, but node-b has no "Prev" for node-a,
+ we turn on this flag bit in node-b's tag entry. This means that when
+ it is time to validate node-b, we don't report an additional error
+ if there was no "Prev" field. */
+#define PREV_ERROR 0x1
+#define NEXT_ERROR 0x2
+#define UP_ERROR 0x4
+#define NO_WARN 0x8
+#define IS_TOP 0x10
+
+TAG_ENTRY *tag_table = (TAG_ENTRY *) NULL;
+
+#if defined (HAVE_MACROS)
+#define ME_RECURSE 0x01
+#define ME_QUOTE_ARG 0x02
+
+/* Macro definitions for user-defined commands. */
+typedef struct {
+ char *name; /* Name of the macro. */
+ char **arglist; /* Args to replace when executing. */
+ char *body; /* Macro body. */
+ char *source_file; /* File where this macro is defined. */
+ int source_lineno; /* Line number within FILENAME. */
+ int inhibited; /* Non-zero means make find_macro () fail. */
+ int flags; /* ME_RECURSE, ME_QUOTE_ARG, etc. */
+} MACRO_DEF;
+
+void add_macro (), execute_macro ();
+MACRO_DEF *find_macro (), *delete_macro ();
+#endif /* HAVE_MACROS */
+
+/* Menu reference, *note reference, and validation hacking. */
+
+/* The various references that we know about. */
+enum reftype
+{
+ menu_reference, followed_reference
+};
+
+/* A structure to remember references with. A reference to a node is
+ either an entry in a menu, or a cross-reference made with [px]ref. */
+typedef struct node_ref
+{
+ struct node_ref *next;
+ char *node; /* Name of node referred to. */
+ char *containing_node; /* Name of node containing this reference. */
+ int line_no; /* Line number where the reference occurs. */
+ int section; /* Section level where the reference occurs. */
+ char *filename; /* Name of file where the reference occurs. */
+ enum reftype type; /* Type of reference, either menu or note. */
+} NODE_REF;
+
+/* The linked list of such structures. */
+NODE_REF *node_references = (NODE_REF *) NULL;
+
+/* Flag which tells us whether to examine menu lines or not. */
+int in_menu = 0;
+
+/* Flag which tells us how to examine menu lines. */
+int in_detailmenu = 0;
+
+/* Non-zero means that we have seen "@top" once already. */
+int top_node_seen = 0;
+
+/* Non-zero means that we have seen a non-"@top" node already. */
+int non_top_node_seen = 0;
+
+/* Flags controlling the operation of the program. */
+
+/* Default is to notify users of bad choices. */
+int print_warnings = 1;
+
+/* Default is to check node references. */
+int validating = 1;
+
+/* Non-zero means do not output "Node: Foo" for node separations. */
+int no_headers = 0;
+
+/* Number of errors that we tolerate on a given fileset. */
+int max_error_level = 100;
+
+/* Maximum number of references to a single node before complaining. */
+int reference_warning_limit = 1000;
+
+/* Non-zero means print out information about what is going on when it
+ is going on. */
+int verbose_mode = 0;
+
+/* Non-zero means to be relaxed about the input file. This is useful when
+ we can successfully format the input, but it doesn't strictly match our
+ somewhat pedantic ideas of correctness. Right now, it affects what
+ @table and @itemize do without arguments. */
+int allow_lax_format = 0;
+
+/* The list of commands that we hack in texinfo. Each one
+ has an associated function. When the command is encountered in the
+ text, the associated function is called with START as the argument.
+ If the function expects arguments in braces, it remembers itself on
+ the stack. When the corresponding close brace is encountered, the
+ function is called with END as the argument. */
+
+#define START 0
+#define END 1
+
+typedef struct brace_element
+{
+ struct brace_element *next;
+ COMMAND_FUNCTION *proc;
+ int pos, line;
+ int in_fixed_width_font;
+} BRACE_ELEMENT;
+
+BRACE_ELEMENT *brace_stack = (BRACE_ELEMENT *) NULL;
+
+/* Forward declarations. */
+#if !defined (HAVE_STRDUP)
+extern char *strdup ();
+#endif /* HAVE_STRDUP */
+
+extern void do_multitable ();
+
+void print_version_info ();
+void usage ();
+void push_node_filename (), pop_node_filename ();
+void remember_error ();
+void convert_from_stream (), convert_from_file (), convert_from_loaded_file ();
+void init_internals (), init_paragraph (), init_brace_stack ();
+void init_insertion_stack (), init_indices ();
+void init_tag_table (), write_tag_table (), write_tag_table_internal ();
+void validate_file (), validate_other_references (), split_file ();
+void free_node_references (), do_enumeration (), handle_variable ();
+void handle_variable_internal ();
+void execute_string ();
+void normalize_node_name ();
+void undefindex (), top_defindex (), gen_defindex ();
+void define_user_command ();
+void free_pending_notes (), output_pending_notes ();
+
+void reader_loop (), read_command ();
+void remember_brace (), remember_brace_1 ();
+void pop_and_call_brace (), discard_braces ();
+void add_word_args (), add_word (), add_char (), insert (), flush_output ();
+void insert_string ();
+void close_paragraph_with_lines (), close_paragraph ();
+void ignore_blank_line ();
+void do_flush_right_indentation ();
+void start_paragraph (), indent ();
+
+void insert_self (), insert_space (), cm_ignore_line ();
+
+void
+ cm_TeX (), cm_asterisk (), cm_bullet (), cm_cite (),
+ cm_code (), cm_copyright (), cm_ctrl (), cm_dfn (), cm_dircategory (),
+ cm_direntry (), cm_dots (), cm_emph (), cm_enddots (),
+ cm_kbd (), cm_angle_brackets (), cm_no_op (), cm_not_fixed_width (),
+ cm_strong (), cm_var (), cm_w ();
+
+/* Sectioning. */
+void
+ cm_chapter (), cm_unnumbered (), cm_appendix (), cm_top (),
+ cm_section (), cm_unnumberedsec (), cm_appendixsec (),
+ cm_subsection (), cm_unnumberedsubsec (), cm_appendixsubsec (),
+ cm_subsubsection (), cm_unnumberedsubsubsec (), cm_appendixsubsubsec (),
+ cm_heading (), cm_chapheading (), cm_subheading (), cm_subsubheading (),
+ cm_majorheading (), cm_raisesections (), cm_lowersections ();
+
+/* All @defxxx commands map to cm_defun, most accent commands map to
+ cm_accent, most non-English letters map to cm_special_char. */
+void cm_defun (), cm_accent (), cm_special_char (), cm_dotless ();
+
+void
+ cm_node (), cm_menu (), cm_xref (), cm_ftable (), cm_vtable (), cm_pxref (),
+ cm_inforef (), cm_quotation (), cm_display (), cm_itemize (),
+ cm_enumerate (), cm_tab (), cm_table (), cm_itemx (), cm_noindent (),
+ cm_setfilename (), cm_br (), cm_sp (), cm_page (), cm_group (),
+ cm_center (), cm_include (), cm_bye (), cm_item (), cm_end (),
+ cm_ifinfo (), cm_kindex (), cm_cindex (),
+ cm_findex (), cm_pindex (), cm_vindex (), cm_tindex (),
+ cm_synindex (), cm_printindex (), cm_minus (), cm_footnote (),
+ cm_example (), cm_smallexample (), cm_lisp (), cm_format (), cm_exdent (),
+ cm_defindex (), cm_defcodeindex (), cm_sc (), cm_result (), cm_expansion (),
+ cm_equiv (), cm_print (), cm_error (), cm_point (), cm_today (),
+ cm_flushleft (), cm_flushright (), cm_smalllisp (), cm_finalout (),
+ cm_cartouche (), cm_detailmenu (), cm_multitable ();
+
+/* Conditionals. */
+void cm_set (), cm_clear (), cm_ifset (), cm_ifclear ();
+void cm_value (), cm_ifeq ();
+
+#if defined (HAVE_MACROS)
+/* Define a user-defined command which is simple substitution. */
+void cm_macro (), cm_unmacro ();
+#endif /* HAVE_MACROS */
+
+/* Options. */
+void cm_paragraphindent (), cm_footnotestyle ();
+
+/* Internals. */
+void command_name_condition (), misplaced_brace (), cm_obsolete (),
+ cm_ideprecated ();
+
+typedef struct
+{
+ char *name;
+ COMMAND_FUNCTION *proc;
+ int argument_in_braces;
+} COMMAND;
+
+/* Stuff for defining commands on the fly. */
+COMMAND **user_command_array = (COMMAND **) NULL;
+int user_command_array_len = 0;
+
+#define NO_BRACE_ARGS 0
+#define BRACE_ARGS 1
+
+static COMMAND CommandTable[] = {
+ { "\t", insert_space, NO_BRACE_ARGS },
+ { "\n", insert_space, NO_BRACE_ARGS },
+ { " ", insert_self, NO_BRACE_ARGS },
+ { "!", insert_self, NO_BRACE_ARGS },
+ { "\"", insert_self, NO_BRACE_ARGS },
+ { "'", insert_self, NO_BRACE_ARGS },
+ { "*", cm_asterisk, NO_BRACE_ARGS },
+ { ",", cm_accent, BRACE_ARGS },
+ { "-", cm_no_op, NO_BRACE_ARGS },
+ { ".", insert_self, NO_BRACE_ARGS },
+ { ":", cm_no_op, NO_BRACE_ARGS },
+ { "=", insert_self, NO_BRACE_ARGS },
+ { "?", insert_self, NO_BRACE_ARGS },
+ { "@", insert_self, NO_BRACE_ARGS },
+ { "^", insert_self, NO_BRACE_ARGS },
+ { "`", insert_self, NO_BRACE_ARGS },
+ { "{", insert_self, NO_BRACE_ARGS },
+ { "|", cm_no_op, NO_BRACE_ARGS },
+ { "}", insert_self, NO_BRACE_ARGS },
+ { "~", insert_self, NO_BRACE_ARGS },
+ { "AA", insert_self, BRACE_ARGS },
+ { "AE", insert_self, BRACE_ARGS },
+ { "H", cm_accent, BRACE_ARGS },
+ { "L", cm_special_char, BRACE_ARGS },
+ { "O", cm_special_char, BRACE_ARGS },
+ { "OE", insert_self, BRACE_ARGS },
+ { "TeX", cm_TeX, BRACE_ARGS },
+ { "aa", insert_self, BRACE_ARGS },
+ { "ae", insert_self, BRACE_ARGS },
+ { "appendix", cm_appendix, NO_BRACE_ARGS },
+ { "appendixsection", cm_appendixsec, NO_BRACE_ARGS },
+ { "appendixsec", cm_appendixsec, NO_BRACE_ARGS },
+ { "appendixsubsec", cm_appendixsubsec, NO_BRACE_ARGS },
+ { "appendixsubsubsec", cm_appendixsubsubsec, NO_BRACE_ARGS },
+ { "asis", cm_no_op, BRACE_ARGS },
+ { "b", cm_not_fixed_width, BRACE_ARGS },
+ { "bullet", cm_bullet, BRACE_ARGS },
+ { "bye", cm_bye, NO_BRACE_ARGS },
+ { "c", cm_ignore_line, NO_BRACE_ARGS },
+ { "cartouche", cm_cartouche, NO_BRACE_ARGS },
+ { "center", cm_center, NO_BRACE_ARGS },
+ { "centerchap", cm_unnumbered, NO_BRACE_ARGS },
+ { "chapheading", cm_chapheading, NO_BRACE_ARGS },
+ { "chapter", cm_chapter, NO_BRACE_ARGS },
+ { "cindex", cm_cindex, NO_BRACE_ARGS },
+ { "cite", cm_cite, BRACE_ARGS },
+ { "clear", cm_clear, NO_BRACE_ARGS },
+ { "code", cm_code, BRACE_ARGS },
+ { "comment", cm_ignore_line, NO_BRACE_ARGS },
+ { "contents", cm_no_op, NO_BRACE_ARGS },
+ { "copyright", cm_copyright, BRACE_ARGS },
+ { "ctrl", cm_obsolete, BRACE_ARGS },
+ { "defcodeindex", cm_defcodeindex, NO_BRACE_ARGS },
+ { "defindex", cm_defindex, NO_BRACE_ARGS },
+/* The `def' commands. */
+ { "defcv", cm_defun, NO_BRACE_ARGS },
+ { "defcvx", cm_defun, NO_BRACE_ARGS },
+ { "deffn", cm_defun, NO_BRACE_ARGS },
+ { "deffnx", cm_defun, NO_BRACE_ARGS },
+ { "defivar", cm_defun, NO_BRACE_ARGS },
+ { "defivarx", cm_defun, NO_BRACE_ARGS },
+ { "defmac", cm_defun, NO_BRACE_ARGS },
+ { "defmacx", cm_defun, NO_BRACE_ARGS },
+ { "defmethod", cm_defun, NO_BRACE_ARGS },
+ { "defmethodx", cm_defun, NO_BRACE_ARGS },
+ { "defop", cm_defun, NO_BRACE_ARGS },
+ { "defopt", cm_defun, NO_BRACE_ARGS },
+ { "defoptx", cm_defun, NO_BRACE_ARGS },
+ { "defopx", cm_defun, NO_BRACE_ARGS },
+ { "defspec", cm_defun, NO_BRACE_ARGS },
+ { "defspecx", cm_defun, NO_BRACE_ARGS },
+ { "deftp", cm_defun, NO_BRACE_ARGS },
+ { "deftpx", cm_defun, NO_BRACE_ARGS },
+ { "deftypefn", cm_defun, NO_BRACE_ARGS },
+ { "deftypefnx", cm_defun, NO_BRACE_ARGS },
+ { "deftypefun", cm_defun, NO_BRACE_ARGS },
+ { "deftypefunx", cm_defun, NO_BRACE_ARGS },
+ { "deftypemethod", cm_defun, NO_BRACE_ARGS },
+ { "deftypemethodx", cm_defun, NO_BRACE_ARGS },
+ { "deftypevar", cm_defun, NO_BRACE_ARGS },
+ { "deftypevarx", cm_defun, NO_BRACE_ARGS },
+ { "deftypevr", cm_defun, NO_BRACE_ARGS },
+ { "deftypevrx", cm_defun, NO_BRACE_ARGS },
+ { "defun", cm_defun, NO_BRACE_ARGS },
+ { "defunx", cm_defun, NO_BRACE_ARGS },
+ { "defvar", cm_defun, NO_BRACE_ARGS },
+ { "defvarx", cm_defun, NO_BRACE_ARGS },
+ { "defvr", cm_defun, NO_BRACE_ARGS },
+ { "defvrx", cm_defun, NO_BRACE_ARGS },
+/* The end of the `def' commands. */
+ { "detailmenu", cm_detailmenu, NO_BRACE_ARGS },
+ { "dfn", cm_dfn, BRACE_ARGS },
+ { "dircategory", cm_dircategory, NO_BRACE_ARGS },
+ { "direntry", cm_direntry, NO_BRACE_ARGS },
+ { "display", cm_display, NO_BRACE_ARGS },
+ { "dmn", cm_no_op, BRACE_ARGS },
+ { "dotaccent", cm_accent, BRACE_ARGS },
+ { "dotless", cm_dotless, BRACE_ARGS },
+ { "dots", cm_dots, BRACE_ARGS },
+ { "email", cm_angle_brackets, BRACE_ARGS },
+ { "emph", cm_emph, BRACE_ARGS },
+ { "end", cm_end, NO_BRACE_ARGS },
+ { "enddots", cm_enddots, BRACE_ARGS },
+ { "enumerate", cm_enumerate, NO_BRACE_ARGS },
+ { "equiv", cm_equiv, BRACE_ARGS },
+ { "error", cm_error, BRACE_ARGS },
+ { "example", cm_example, NO_BRACE_ARGS },
+ { "exclamdown", cm_special_char, BRACE_ARGS },
+ { "exdent", cm_exdent, NO_BRACE_ARGS },
+ { "expansion", cm_expansion, BRACE_ARGS },
+ { "file", cm_code, BRACE_ARGS },
+ { "finalout", cm_no_op, NO_BRACE_ARGS },
+ { "findex", cm_findex, NO_BRACE_ARGS },
+ { "flushleft", cm_flushleft, NO_BRACE_ARGS },
+ { "flushright", cm_flushright, NO_BRACE_ARGS },
+ { "footnote", cm_footnote, NO_BRACE_ARGS}, /* self-arg eater */
+ { "footnotestyle", cm_footnotestyle, NO_BRACE_ARGS },
+ { "format", cm_format, NO_BRACE_ARGS },
+ { "ftable", cm_ftable, NO_BRACE_ARGS },
+ { "group", cm_group, NO_BRACE_ARGS },
+ { "heading", cm_heading, NO_BRACE_ARGS },
+ { "headings", cm_ignore_line, NO_BRACE_ARGS },
+ { "hyphenation", cm_no_op, BRACE_ARGS },
+ { "i", cm_not_fixed_width, BRACE_ARGS },
+ { "ifclear", cm_ifclear, NO_BRACE_ARGS },
+ { "ifeq", cm_ifeq, NO_BRACE_ARGS },
+ { "ifhtml", command_name_condition, NO_BRACE_ARGS },
+ { "ifinfo", cm_ifinfo, NO_BRACE_ARGS },
+ { "ifset", cm_ifset, NO_BRACE_ARGS },
+ { "iftex", command_name_condition, NO_BRACE_ARGS },
+ { "ignore", command_name_condition, NO_BRACE_ARGS },
+ { "include", cm_include, NO_BRACE_ARGS },
+ { "inforef", cm_inforef, BRACE_ARGS },
+ { "item", cm_item, NO_BRACE_ARGS },
+ { "itemize", cm_itemize, NO_BRACE_ARGS },
+ { "itemx", cm_itemx, NO_BRACE_ARGS },
+ { "kbd", cm_kbd, BRACE_ARGS },
+ { "key", cm_angle_brackets, BRACE_ARGS },
+ { "kindex", cm_kindex, NO_BRACE_ARGS },
+ { "l", cm_special_char, BRACE_ARGS },
+ { "lisp", cm_lisp, NO_BRACE_ARGS },
+ { "lowersections", cm_lowersections, NO_BRACE_ARGS },
+#if defined (HAVE_MACROS)
+ { "macro", cm_macro, NO_BRACE_ARGS },
+#endif
+ { "majorheading", cm_majorheading, NO_BRACE_ARGS },
+ { "math", cm_no_op, BRACE_ARGS },
+ { "menu", cm_menu, NO_BRACE_ARGS },
+ { "minus", cm_minus, BRACE_ARGS },
+ { "multitable", cm_multitable, NO_BRACE_ARGS },
+ { "need", cm_ignore_line, NO_BRACE_ARGS },
+ { "node", cm_node, NO_BRACE_ARGS },
+ { "noindent", cm_noindent, NO_BRACE_ARGS },
+ { "nwnode", cm_node, NO_BRACE_ARGS },
+ { "o", cm_special_char, BRACE_ARGS },
+ { "oe", insert_self, BRACE_ARGS },
+ { "page", cm_no_op, NO_BRACE_ARGS },
+ { "paragraphindent", cm_paragraphindent, NO_BRACE_ARGS },
+ { "pindex", cm_pindex, NO_BRACE_ARGS },
+ { "point", cm_point, BRACE_ARGS },
+ { "pounds", cm_special_char, BRACE_ARGS },
+ { "print", cm_print, BRACE_ARGS },
+ { "printindex", cm_printindex, NO_BRACE_ARGS },
+ { "pxref", cm_pxref, BRACE_ARGS },
+ { "questiondown", cm_special_char, BRACE_ARGS },
+ { "quotation", cm_quotation, NO_BRACE_ARGS },
+ { "r", cm_not_fixed_width, BRACE_ARGS },
+ { "raisesections", cm_raisesections, NO_BRACE_ARGS },
+ { "ref", cm_xref, BRACE_ARGS },
+ { "refill", cm_no_op, NO_BRACE_ARGS },
+ { "result", cm_result, BRACE_ARGS },
+ { "ringaccent", cm_accent, BRACE_ARGS },
+ { "samp", cm_code, BRACE_ARGS },
+ { "sc", cm_sc, BRACE_ARGS },
+ { "section", cm_section, NO_BRACE_ARGS },
+ { "set", cm_set, NO_BRACE_ARGS },
+ { "setchapternewpage", cm_ignore_line, NO_BRACE_ARGS },
+ { "setchapterstyle", cm_obsolete, NO_BRACE_ARGS },
+ { "setfilename", cm_setfilename, NO_BRACE_ARGS },
+ { "settitle", cm_ignore_line, NO_BRACE_ARGS },
+ { "shortcontents", cm_no_op, NO_BRACE_ARGS },
+ { "shorttitlepage", cm_ignore_line, NO_BRACE_ARGS },
+ { "smallbook", cm_ignore_line, NO_BRACE_ARGS },
+ { "smallexample", cm_smallexample, NO_BRACE_ARGS },
+ { "smalllisp", cm_smalllisp, NO_BRACE_ARGS },
+ { "sp", cm_sp, NO_BRACE_ARGS },
+ { "ss", insert_self, BRACE_ARGS },
+ { "strong", cm_strong, BRACE_ARGS },
+ { "subheading", cm_subheading, NO_BRACE_ARGS },
+ { "subsection", cm_subsection, NO_BRACE_ARGS },
+ { "subsubheading", cm_subsubheading, NO_BRACE_ARGS },
+ { "subsubsection", cm_subsubsection, NO_BRACE_ARGS },
+ { "summarycontents", cm_no_op, NO_BRACE_ARGS },
+ { "syncodeindex", cm_synindex, NO_BRACE_ARGS },
+ { "synindex", cm_synindex, NO_BRACE_ARGS },
+ { "t", cm_no_op, BRACE_ARGS },
+ { "tab", cm_tab, NO_BRACE_ARGS },
+ { "table", cm_table, NO_BRACE_ARGS },
+ { "tex", command_name_condition, NO_BRACE_ARGS },
+ { "tieaccent", cm_accent, BRACE_ARGS },
+ { "tindex", cm_tindex, NO_BRACE_ARGS },
+ { "titlefont", cm_not_fixed_width, BRACE_ARGS },
+ { "titlepage", command_name_condition, NO_BRACE_ARGS },
+ { "today", cm_today, BRACE_ARGS },
+ { "top", cm_top, NO_BRACE_ARGS },
+ { "u", cm_accent, BRACE_ARGS },
+ { "ubaraccent", cm_accent, BRACE_ARGS },
+ { "udotaccent", cm_accent, BRACE_ARGS },
+#if defined (HAVE_MACROS)
+ { "unmacro", cm_unmacro, NO_BRACE_ARGS },
+#endif
+ { "unnumbered", cm_unnumbered, NO_BRACE_ARGS },
+ { "unnumberedsec", cm_unnumberedsec, NO_BRACE_ARGS },
+ { "unnumberedsubsec", cm_unnumberedsubsec, NO_BRACE_ARGS },
+ { "unnumberedsubsubsec", cm_unnumberedsubsubsec, NO_BRACE_ARGS },
+ { "url", cm_code, BRACE_ARGS },
+ { "v", cm_accent, BRACE_ARGS },
+ { "value", cm_value, BRACE_ARGS },
+ { "var", cm_var, BRACE_ARGS },
+ { "vindex", cm_vindex, NO_BRACE_ARGS },
+ { "vtable", cm_vtable, NO_BRACE_ARGS },
+ { "w", cm_w, BRACE_ARGS },
+ { "xref", cm_xref, BRACE_ARGS },
+
+ /* Deprecated commands. These used to be for italics. */
+ { "iappendix", cm_ideprecated, NO_BRACE_ARGS },
+ { "iappendixsec", cm_ideprecated, NO_BRACE_ARGS },
+ { "iappendixsection", cm_ideprecated, NO_BRACE_ARGS },
+ { "iappendixsubsec", cm_ideprecated, NO_BRACE_ARGS },
+ { "iappendixsubsubsec", cm_ideprecated, NO_BRACE_ARGS },
+ { "ichapter", cm_ideprecated, NO_BRACE_ARGS },
+ { "isection", cm_ideprecated, NO_BRACE_ARGS },
+ { "isubsection", cm_ideprecated, NO_BRACE_ARGS },
+ { "isubsubsection", cm_ideprecated, NO_BRACE_ARGS },
+ { "iunnumbered", cm_ideprecated, NO_BRACE_ARGS },
+ { "iunnumberedsec", cm_ideprecated, NO_BRACE_ARGS },
+ { "iunnumberedsubsec", cm_ideprecated, NO_BRACE_ARGS },
+ { "iunnumberedsubsubsec", cm_ideprecated, NO_BRACE_ARGS },
+
+ /* Now @include does what this was supposed to. */
+ { "infoinclude", cm_obsolete, NO_BRACE_ARGS },
+ { "titlespec", cm_obsolete, NO_BRACE_ARGS },
+
+ {(char *) NULL, (COMMAND_FUNCTION *) NULL}, NO_BRACE_ARGS};
+
+struct option long_options[] =
+{
+ { "error-limit", 1, 0, 'e' }, /* formerly -el */
+ { "fill-column", 1, 0, 'f' }, /* formerly -fc */
+ { "footnote-style", 1, 0, 's' }, /* formerly -ft */
+ { "no-headers", 0, &no_headers, 1 }, /* Do not output Node: foo */
+ { "no-pointer-validate", 0, &validating, 0 }, /* formerly -nv */
+ { "no-validate", 0, &validating, 0 }, /* formerly -nv */
+ { "no-split", 0, &splitting, 0 }, /* formerly -ns */
+ { "no-warn", 0, &print_warnings, 0 }, /* formerly -nw */
+#if defined (HAVE_MACROS)
+ { "macro-expand", 1, 0, 'E' },
+#endif /* HAVE_MACROS */
+ { "number-footnotes", 0, &number_footnotes, 1 },
+ { "no-number-footnotes", 0, &number_footnotes, 0 },
+ { "output", 1, 0, 'o' },
+ { "paragraph-indent", 1, 0, 'p' }, /* formerly -pi */
+ { "reference-limit", 1, 0, 'r' }, /* formerly -rl */
+ { "verbose", 0, &verbose_mode, 1 }, /* formerly -verbose */
+ { "help", 0, 0, 'h' },
+ { "version", 0, 0, 'V' },
+ {NULL, 0, NULL, 0}
+};
+
+/* Values for calling handle_variable_internal (). */
+#define SET 1
+#define CLEAR 2
+#define IFSET 3
+#define IFCLEAR 4
+
+/* **************************************************************** */
+/* */
+/* Main () Start of code */
+/* */
+/* **************************************************************** */
+
+/* For each file mentioned in the command line, process it, turning
+ Texinfo commands into wonderfully formatted output text. */
+int
+main (argc, argv)
+ int argc;
+ char **argv;
+{
+ extern int errors_printed;
+ char *filename_part ();
+ int c, ind;
+ int reading_from_stdin = 0;
+
+ /* The name of this program is the last filename in argv[0]. */
+ progname = filename_part (argv[0]);
+
+ /* Parse argument flags from the input line. */
+ while ((c = getopt_long
+ (argc, argv,
+#if defined (HAVE_MACROS)
+ "D:E:U:I:f:o:p:e:r:s:V",
+#else
+ "D:U:I:f:o:p:e:r:s:V",
+#endif /* !HAVE_MACROS */
+ long_options, &ind))
+ != EOF)
+ {
+ if (c == 0 && long_options[ind].flag == 0)
+ c = long_options[ind].val;
+
+ switch (c)
+ {
+ /* User specified variable to set or clear? */
+ case 'D':
+ case 'U':
+ handle_variable_internal ((c == 'D') ? SET : CLEAR, optarg);
+ break;
+
+#if defined (HAVE_MACROS)
+ /* Use specified a macro expansion output file? */
+ case 'E':
+ if (!macro_expansion_output_stream)
+ {
+ macro_expansion_output_stream = fopen (optarg, "w");
+ if (!macro_expansion_output_stream)
+ error ("Couldn't open macro expansion output \"%s\"", optarg);
+ }
+ else
+ error ("Cannot specify more than one macro expansion output");
+ break;
+#endif /* HAVE_MACROS */
+
+ /* User specified include file path? */
+ case 'I':
+ if (!include_files_path)
+ include_files_path = strdup (".");
+
+ include_files_path = (char *)
+ xrealloc (include_files_path,
+ 2 + strlen (include_files_path) + strlen (optarg));
+ strcat (include_files_path, ":");
+ strcat (include_files_path, optarg);
+ break;
+
+ /* User specified fill_column? */
+ case 'f':
+ if (sscanf (optarg, "%d", &fill_column) != 1)
+ {
+ fprintf (stderr,
+ "%s: --fill-column arg must be numeric, not `%s'.\n",
+ progname, optarg);
+ usage (FATAL);
+ }
+ break;
+
+ /* User specified output file? */
+ case 'o':
+ command_output_filename = strdup (optarg);
+ break;
+
+ /* User specified paragraph indent (paragraph_start_index)? */
+ case 'p':
+ if (set_paragraph_indent (optarg) < 0)
+ {
+ fprintf (stderr,
+ "%s: --paragraph-indent arg must be numeric/none/asis, not `%s'.\n",
+ progname, optarg);
+ usage (FATAL);
+ }
+ break;
+
+ /* User specified error level? */
+ case 'e':
+ if (sscanf (optarg, "%d", &max_error_level) != 1)
+ {
+ fprintf (stderr,
+ "%s: --error-limit arg must be numeric, not `%s'.\n",
+ progname, optarg);
+ }
+ usage (stderr, FATAL);
+ break;
+
+ /* User specified reference warning limit? */
+ case 'r':
+ if (sscanf (optarg, "%d", &reference_warning_limit) != 1)
+ {
+ fprintf (stderr,
+ "%s: --reference-limit arg must be numeric, not `%s'.\n",
+ progname, optarg);
+ usage (FATAL);
+ }
+ break;
+
+ /* User specified footnote style? */
+ case 's':
+ if (set_footnote_style (optarg) < 0)
+ {
+ fprintf (stderr,
+ "%s: --footnote-style arg must be `separate' or `end', not `%s'.\n",
+ progname, optarg);
+ usage (FATAL);
+ }
+ footnote_style_preset = 1;
+ break;
+
+ case 'h':
+ usage (NO_ERROR);
+ break;
+
+ /* User requested version info? */
+ case 'V':
+ print_version_info ();
+ puts ("Copyright (C) 1996 Free Software Foundation, Inc.\n\
+There is NO warranty. You may redistribute this software\n\
+under the terms of the GNU General Public License.\n\
+For more information about these matters, see the files named COPYING.");
+ exit (NO_ERROR);
+ break;
+
+ case '?':
+ usage (FATAL);
+ break;
+ }
+ }
+
+ if (optind == argc)
+ {
+ /* Check to see if input is a file. If so, process that. */
+ if (!isatty (fileno (stdin)))
+ reading_from_stdin = 1;
+ else
+ {
+ fprintf (stderr, "%s: missing file argument.\n", progname);
+ usage (FATAL);
+ }
+ }
+
+ /* If the user has specified --no-headers, this should imply --no-split.
+ Do that here. I think it might also imply that we should ignore the
+ setfilename at the top of the file, but this might break some FSF things,
+ so I will hold off on that. */
+ if (no_headers)
+ {
+ splitting = 0;
+
+ /* If the user has not specified an output file, then use stdout by
+ default. */
+ if (!command_output_filename)
+ command_output_filename = strdup ("-");
+ }
+
+ if (verbose_mode)
+ print_version_info ();
+
+ /* Remaining arguments are file names of texinfo files.
+ Convert them, one by one. */
+ if (!reading_from_stdin)
+ {
+ while (optind != argc)
+ convert_from_file (argv[optind++]);
+ }
+ else
+ convert_from_stream (stdin, "stdin");
+
+ if (errors_printed)
+ return (SYNTAX);
+ else
+ return (NO_ERROR);
+}
+
+/* Display the version info of this invocation of Makeinfo. */
+void
+print_version_info ()
+{
+ printf ("GNU Makeinfo (Texinfo 3.9) %d.%d\n", major_version, minor_version);
+}
+
+/* **************************************************************** */
+/* */
+/* Generic Utilities */
+/* */
+/* **************************************************************** */
+
+static void
+memory_error (callers_name, bytes_wanted)
+ char *callers_name;
+ int bytes_wanted;
+{
+ char printable_string[80];
+
+ sprintf (printable_string,
+ "Virtual memory exhausted in %s ()! Needed %d bytes.",
+ callers_name, bytes_wanted);
+
+ error (printable_string);
+ abort ();
+}
+
+/* Just like malloc, but kills the program in case of fatal error. */
+void *
+xmalloc (nbytes)
+ unsigned int nbytes;
+{
+ void *temp = (void *) malloc (nbytes);
+
+ if (nbytes && temp == (void *)NULL)
+ memory_error ("xmalloc", nbytes);
+
+ return (temp);
+}
+
+/* Like realloc (), but barfs if there isn't enough memory. */
+void *
+xrealloc (pointer, nbytes)
+ void *pointer;
+ unsigned int nbytes;
+{
+ void *temp;
+
+ if (!pointer)
+ temp = (void *)xmalloc (nbytes);
+ else
+ temp = (void *)realloc (pointer, nbytes);
+
+ if (nbytes && !temp)
+ memory_error ("xrealloc", nbytes);
+
+ return (temp);
+}
+
+/* If EXIT_VALUE is zero, print the full usage message to stdout.
+ Otherwise, just say to use --help for more info.
+ Then exit with EXIT_VALUE. */
+void
+usage (exit_value)
+ int exit_value;
+{
+ if (exit_value != 0)
+ fprintf (stderr, "Try `%s --help' for more information.\n", progname);
+ else
+ printf ("Usage: %s [OPTION]... TEXINFO-FILE...\n\
+\n\
+Translate Texinfo source documentation to a format suitable for reading\n\
+with GNU Info.\n\
+\n\
+Options:\n\
+-D VAR define a variable, as with @set.\n\
+-E MACRO-OFILE process macros only, output texinfo source.\n\
+-I DIR add DIR to the directory search list for @include.\n\
+-U VAR undefine a variable, as with @clear.\n\
+--error-limit NUM quit after NUM errors (default %d).\n\
+--fill-column NUM break lines at NUM characters (default %d).\n\
+--footnote-style STYLE output footnotes according to STYLE:\n\
+ `separate' to place footnotes in their own node,\n\
+ `end' to place the footnotes at the end of\n\
+ the node in which they are defined (the default).\n\
+--help display this help and exit.\n\
+--no-validate suppress node cross-reference validation.\n\
+--no-warn suppress warnings (but not errors).\n\
+--no-split suppress splitting of large files.\n\
+--no-headers suppress node separators and Node: Foo headers.\n\
+--output FILE, -o FILE output to FILE, and ignore any @setfilename.\n\
+--paragraph-indent NUM indent paragraphs with NUM spaces (default %d).\n\
+--reference-limit NUM complain about at most NUM references (default %d).\n\
+--verbose report about what is being done.\n\
+--version display version information and exit.\n\
+\n\
+Email bug reports to bug-texinfo@prep.ai.mit.edu.\n\
+",
+ progname, paragraph_start_indent,
+ fill_column, max_error_level, reference_warning_limit);
+ exit (exit_value);
+}
+
+/* Manipulating Lists */
+
+typedef struct generic_list {
+ struct generic_list *next;
+} GENERIC_LIST;
+
+/* Reverse the chain of structures in LIST. Output the new head
+ of the chain. You should always assign the output value of this
+ function to something, or you will lose the chain. */
+GENERIC_LIST *
+reverse_list (list)
+ register GENERIC_LIST *list;
+{
+ register GENERIC_LIST *next;
+ register GENERIC_LIST *prev = (GENERIC_LIST *) NULL;
+
+ while (list)
+ {
+ next = list->next;
+ list->next = prev;
+ prev = list;
+ list = next;
+ }
+ return (prev);
+}
+
+/* Pushing and Popping Files */
+
+/* Find and load the file named FILENAME. Return a pointer to
+ the loaded file, or NULL if it can't be loaded. */
+char *
+find_and_load (filename)
+ char *filename;
+{
+ struct stat fileinfo;
+ long file_size;
+ int file = -1, n, i, count = 0;
+ char *fullpath, *result, *get_file_info_in_path ();
+
+ result = fullpath = (char *)NULL;
+
+ fullpath = get_file_info_in_path (filename, include_files_path, &fileinfo);
+
+ if (!fullpath)
+ goto error_exit;
+
+ filename = fullpath;
+ file_size = (long) fileinfo.st_size;
+
+ file = open (filename, O_RDONLY);
+ if (file < 0)
+ goto error_exit;
+
+ /* Load the file. */
+ result = (char *)xmalloc (1 + file_size);
+
+ /* VMS stat lies about the st_size value. The actual number of
+ readable bytes is always less than this value. The arcane
+ mysteries of VMS/RMS are too much to probe, so this hack
+ suffices to make things work. */
+#if defined (VMS)
+ while ((n = read (file, result + count, file_size)) > 0)
+ count += n;
+ if (n == -1)
+#else /* !VMS */
+ count = file_size;
+ if (read (file, result, file_size) != file_size)
+#endif /* !VMS */
+ error_exit:
+ {
+ if (result)
+ free (result);
+
+ if (fullpath)
+ free (fullpath);
+
+ if (file != -1)
+ close (file);
+
+ return ((char *) NULL);
+ }
+ close (file);
+
+ /* Set the globals to the new file. */
+ input_text = result;
+ size_of_input_text = count;
+ input_filename = fullpath;
+ node_filename = strdup (fullpath);
+ input_text_offset = 0;
+ line_number = 1;
+ /* Not strictly necessary. This magic prevents read_token () from doing
+ extra unnecessary work each time it is called (that is a lot of times).
+ The SIZE_OF_INPUT_TEXT is one past the actual end of the text. */
+ input_text[size_of_input_text] = '\n';
+ return (result);
+}
+
+/* Save the state of the current input file. */
+void
+pushfile ()
+{
+ FSTACK *newstack = (FSTACK *) xmalloc (sizeof (FSTACK));
+ newstack->filename = input_filename;
+ newstack->text = input_text;
+ newstack->size = size_of_input_text;
+ newstack->offset = input_text_offset;
+ newstack->line_number = line_number;
+ newstack->next = filestack;
+
+ filestack = newstack;
+ push_node_filename ();
+}
+
+/* Make the current file globals be what is on top of the file stack. */
+void
+popfile ()
+{
+ FSTACK *tos = filestack;
+
+ if (!tos)
+ abort (); /* My fault. I wonder what I did? */
+
+#if defined (HAVE_MACROS)
+ if (macro_expansion_output_stream)
+ {
+ maybe_write_itext (input_text, input_text_offset);
+ forget_itext (input_text);
+ }
+#endif /* HAVE_MACROS */
+
+ /* Pop the stack. */
+ filestack = filestack->next;
+
+ /* Make sure that commands with braces have been satisfied. */
+ if (!executing_string)
+ discard_braces ();
+
+ /* Get the top of the stack into the globals. */
+ input_filename = tos->filename;
+ input_text = tos->text;
+ size_of_input_text = tos->size;
+ input_text_offset = tos->offset;
+ line_number = tos->line_number;
+ free (tos);
+
+ /* Go back to the (now) current node. */
+ pop_node_filename ();
+}
+
+/* Flush all open files on the file stack. */
+void
+flush_file_stack ()
+{
+ while (filestack)
+ {
+ char *fname = input_filename;
+ char *text = input_text;
+ popfile ();
+ free (fname);
+ free (text);
+ }
+}
+
+int node_filename_stack_index = 0;
+int node_filename_stack_size = 0;
+char **node_filename_stack = (char **)NULL;
+
+void
+push_node_filename ()
+{
+ if (node_filename_stack_index + 1 > node_filename_stack_size)
+ node_filename_stack = (char **)xrealloc
+ (node_filename_stack, (node_filename_stack_size += 10) * sizeof (char *));
+
+ node_filename_stack[node_filename_stack_index] = node_filename;
+ node_filename_stack_index++;
+}
+
+void
+pop_node_filename ()
+{
+ node_filename = node_filename_stack[--node_filename_stack_index];
+}
+
+/* Return just the simple part of the filename; i.e. the
+ filename without the path information, or extensions.
+ This conses up a new string. */
+char *
+filename_part (filename)
+ char *filename;
+{
+ char *basename;
+
+ basename = strrchr (filename, '/');
+ if (!basename)
+ basename = filename;
+ else
+ basename++;
+
+ basename = strdup (basename);
+#if defined (REMOVE_OUTPUT_EXTENSIONS)
+
+ /* See if there is an extension to remove. If so, remove it. */
+ {
+ char *temp;
+
+ temp = strrchr (basename, '.');
+ if (temp)
+ *temp = '\0';
+ }
+#endif /* REMOVE_OUTPUT_EXTENSIONS */
+ return (basename);
+}
+
+/* Return the pathname part of filename. This can be NULL. */
+char *
+pathname_part (filename)
+ char *filename;
+{
+ char *expand_filename ();
+ char *result = (char *) NULL;
+ register int i;
+
+ filename = expand_filename (filename, "");
+
+ i = strlen (filename) - 1;
+
+ while (i && filename[i] != '/')
+ i--;
+ if (filename[i] == '/')
+ i++;
+
+ if (i)
+ {
+ result = (char *)xmalloc (1 + i);
+ strncpy (result, filename, i);
+ result[i] = '\0';
+ }
+ free (filename);
+ return (result);
+}
+
+char *
+filename_non_directory (name)
+ char *name;
+{
+ register int i;
+
+ for (i = strlen (name) - 1; i; i--)
+ if (name[i] == '/')
+ return (strdup (name + i + 1));
+
+ return (strdup (name));
+}
+
+/* Return the expansion of FILENAME. */
+char *
+expand_filename (filename, input_name)
+ char *filename, *input_name;
+{
+ register int i;
+ char *full_pathname ();
+
+ if (filename)
+ filename = full_pathname (filename);
+ else
+ {
+ filename = filename_non_directory (input_name);
+
+ if (!*filename)
+ {
+ free (filename);
+ filename = strdup ("noname.texi");
+ }
+
+ for (i = strlen (filename) - 1; i; i--)
+ if (filename[i] == '.')
+ break;
+
+ if (!i)
+ i = strlen (filename);
+
+ if (i + 6 > (strlen (filename)))
+ filename = (char *)xrealloc (filename, i + 6);
+ strcpy (filename + i, ".info");
+ return (filename);
+ }
+
+ if (filename[0] == '.' || filename[0] == '/')
+ return (filename);
+
+ if (filename[0] != '/' && input_name[0] == '/')
+ {
+ /* Make it so that relative names work. */
+ char *result;
+
+ i = strlen (input_name) - 1;
+
+ result = (char *)xmalloc (1 + strlen (input_name) + strlen (filename));
+ strcpy (result, input_name);
+
+ while (result[i] != '/' && i)
+ i--;
+
+ if (result[i] == '/')
+ i++;
+
+ strcpy (&result[i], filename);
+ free (filename);
+ return (result);
+ }
+ return (filename);
+}
+
+/* Return the full path to FILENAME. */
+char *
+full_pathname (filename)
+ char *filename;
+{
+ int initial_character;
+ char *result;
+
+ /* No filename given? */
+ if (!filename || !(initial_character = *filename))
+ return (strdup (""));
+
+ /* Already absolute? */
+ if ((initial_character == '/') ||
+ ((strncmp (filename, "./", 2) == 0) ||
+ (strncmp (filename, "../", 3) == 0)))
+ return (strdup (filename));
+
+ if (initial_character != '~')
+ {
+ char *localdir;
+
+ localdir = (char *)xmalloc (1025);
+#if defined (HAVE_GETCWD)
+ if (!getcwd (localdir, 1024))
+#else /* !HAVE_GETCWD */
+ if (!getwd (localdir))
+#endif /* !HAVE_GETCWD */
+ {
+ fprintf (stderr, "%s: getwd: %s, %s\n",
+ progname, filename, localdir);
+ exit (1);
+ }
+
+ strcat (localdir, "/");
+ strcat (localdir, filename);
+ result = strdup (localdir);
+ free (localdir);
+ }
+ else
+ {
+ if (filename[1] == '/')
+ {
+ /* Return the concatenation of the environment variable HOME
+ and the rest of the string. */
+ char *temp_home;
+
+ temp_home = (char *) getenv ("HOME");
+ result = (char *)xmalloc (strlen (&filename[1])
+ + 1
+ + temp_home ? strlen (temp_home)
+ : 0);
+ *result = '\0';
+
+ if (temp_home)
+ strcpy (result, temp_home);
+
+ strcat (result, &filename[1]);
+ }
+ else
+ {
+ struct passwd *user_entry;
+ int i, c;
+ char *username = (char *)xmalloc (257);
+
+ for (i = 1; c = filename[i]; i++)
+ {
+ if (c == '/')
+ break;
+ else
+ username[i - 1] = c;
+ }
+ if (c)
+ username[i - 1] = '\0';
+
+ user_entry = getpwnam (username);
+
+ if (!user_entry)
+ return (strdup (filename));
+
+ result = (char *)xmalloc (1 + strlen (user_entry->pw_dir)
+ + strlen (&filename[i]));
+ strcpy (result, user_entry->pw_dir);
+ strcat (result, &filename[i]);
+ }
+ }
+ return (result);
+}
+
+char *
+output_name_from_input_name (name)
+ char *name;
+{
+ return (expand_filename ((char *)NULL, name));
+}
+
+/* **************************************************************** */
+/* */
+/* Error Handling */
+/* */
+/* **************************************************************** */
+
+/* Number of errors encountered. */
+int errors_printed = 0;
+
+/* Print the last error gotten from the file system. */
+int
+fs_error (filename)
+ char *filename;
+{
+ remember_error ();
+ perror (filename);
+ return (0);
+}
+
+/* Print an error message, and return false. */
+#if defined (HAVE_VARARGS_H) && defined (HAVE_VFPRINTF)
+
+int
+error (va_alist)
+ va_dcl
+{
+ char *format;
+ va_list args;
+
+ remember_error ();
+ va_start (args);
+ format = va_arg (args, char *);
+ vfprintf (stderr, format, args);
+ va_end (args);
+ putc ('\n', stderr);
+}
+
+/* Just like error (), but print the line number as well. */
+int
+line_error (va_alist)
+ va_dcl
+{
+ char *format;
+ va_list args;
+
+ remember_error ();
+ va_start (args);
+ format = va_arg (args, char *);
+ fprintf (stderr, "%s:%d: ", input_filename, line_number);
+ vfprintf (stderr, format, args);
+ fprintf (stderr, ".\n");
+ va_end (args);
+ return ((int) 0);
+}
+
+int
+warning (va_alist)
+ va_dcl
+{
+ char *format;
+ va_list args;
+
+ va_start (args);
+ format = va_arg (args, char *);
+ if (print_warnings)
+ {
+ fprintf (stderr, "%s:%d: Warning: ", input_filename, line_number);
+ vfprintf (stderr, format, args);
+ fprintf (stderr, ".\n");
+ }
+ va_end (args);
+ return ((int) 0);
+}
+
+#else /* !(HAVE_VARARGS_H && HAVE_VFPRINTF) */
+
+int
+error (format, arg1, arg2, arg3, arg4, arg5)
+ char *format;
+{
+ remember_error ();
+ fprintf (stderr, format, arg1, arg2, arg3, arg4, arg5);
+ putc ('\n', stderr);
+ return ((int) 0);
+}
+
+/* Just like error (), but print the line number as well. */
+int
+line_error (format, arg1, arg2, arg3, arg4, arg5)
+ char *format;
+{
+ remember_error ();
+ fprintf (stderr, "%s:%d: ", input_filename, line_number);
+ fprintf (stderr, format, arg1, arg2, arg3, arg4, arg5);
+ fprintf (stderr, ".\n");
+ return ((int) 0);
+}
+
+int
+warning (format, arg1, arg2, arg3, arg4, arg5)
+ char *format;
+{
+ if (print_warnings)
+ {
+ fprintf (stderr, "%s:%d: Warning: ", input_filename, line_number);
+ fprintf (stderr, format, arg1, arg2, arg3, arg4, arg5);
+ fprintf (stderr, ".\n");
+ }
+ return ((int) 0);
+}
+
+#endif /* !(HAVE_VARARGS_H && HAVE_VFPRINTF) */
+
+/* Remember that an error has been printed. If this is the first
+ error printed, then tell them which program is printing them.
+ If more than max_error_level have been printed, then exit the
+ program. */
+void
+remember_error ()
+{
+ errors_printed++;
+ if (max_error_level && (errors_printed > max_error_level))
+ {
+ fprintf (stderr, "Too many errors! Gave up.\n");
+ flush_file_stack ();
+ cm_bye ();
+ exit (1);
+ }
+}
+
+/* **************************************************************** */
+/* */
+/* Hacking Tokens and Strings */
+/* */
+/* **************************************************************** */
+
+/* Return the next token as a string pointer. We cons the string. */
+char *
+read_token ()
+{
+ int i, character;
+ char *result;
+
+ /* If the first character to be read is self-delimiting, then that
+ is the command itself. */
+ character = curchar ();
+ if (self_delimiting (character))
+ {
+ input_text_offset++;
+
+ if (character == '\n')
+ line_number++;
+
+ result = strdup (" ");
+ *result = character;
+ return (result);
+ }
+
+ for (i = 0; ((input_text_offset != size_of_input_text)
+ && (character = curchar ())
+ && command_char (character));
+ i++, input_text_offset++);
+ result = (char *)xmalloc (i + 1);
+ memcpy (result, &input_text[input_text_offset - i], i);
+ result[i] = '\0';
+ return (result);
+}
+
+/* Return non-zero if CHARACTER is self-delimiting. */
+int
+self_delimiting (character)
+ int character;
+{
+ /* @; and @\ are not Texinfo commands, but they are listed here
+ anyway. I don't know why. --karl, 10aug96. */
+ return member (character, "~{|}`^\\@?=;:.-,*\'\" !\n\t");
+}
+
+/* Clear whitespace from the front and end of string. */
+void
+canon_white (string)
+ char *string;
+{
+ int len = strlen (string);
+ int x;
+
+ if (!len)
+ return;
+
+ for (x = 0; x < len; x++)
+ {
+ if (!cr_or_whitespace (string[x]))
+ {
+ strcpy (string, string + x);
+ break;
+ }
+ }
+ len = strlen (string);
+ if (len)
+ len--;
+ while (len > -1 && cr_or_whitespace (string[len]))
+ len--;
+ string[len + 1] = '\0';
+}
+
+/* Bash STRING, replacing all whitespace with just one space. */
+void
+fix_whitespace (string)
+ char *string;
+{
+ char *temp = (char *)xmalloc (strlen (string) + 1);
+ int string_index = 0;
+ int temp_index = 0;
+ int c;
+
+ canon_white (string);
+
+ while (string[string_index])
+ {
+ c = temp[temp_index++] = string[string_index++];
+
+ if (c == ' ' || c == '\n' || c == '\t')
+ {
+ temp[temp_index - 1] = ' ';
+ while ((c = string[string_index]) && (c == ' ' ||
+ c == '\t' ||
+ c == '\n'))
+ string_index++;
+ }
+ }
+ temp[temp_index] = '\0';
+ strcpy (string, temp);
+ free (temp);
+}
+
+/* Discard text until the desired string is found. The string is
+ included in the discarded text. */
+void
+discard_until (string)
+ char *string;
+{
+ int temp = search_forward (string, input_text_offset);
+
+ int tt = (temp < 0) ? size_of_input_text : temp + strlen (string);
+ int from = input_text_offset;
+
+ /* Find out what line we are on. */
+ while (from != tt)
+ if (input_text[from++] == '\n')
+ line_number++;
+
+ if (temp < 0)
+ {
+ input_text_offset = size_of_input_text - strlen (string);
+
+ if (strcmp (string, "\n") != 0)
+ {
+ line_error ("Expected `%s'", string);
+ return;
+ }
+ }
+ else
+ input_text_offset = temp;
+
+ input_text_offset += strlen (string);
+}
+
+/* Read characters from the file until we are at MATCH.
+ Place the characters read into STRING.
+ On exit input_text_offset is after the match string.
+ Return the offset where the string starts. */
+int
+get_until (match, string)
+ char *match, **string;
+{
+ int len, current_point, x, new_point, tem;
+
+ current_point = x = input_text_offset;
+ new_point = search_forward (match, input_text_offset);
+
+ if (new_point < 0)
+ new_point = size_of_input_text;
+ len = new_point - current_point;
+
+ /* Keep track of which line number we are at. */
+ tem = new_point + (strlen (match) - 1);
+ while (x != tem)
+ if (input_text[x++] == '\n')
+ line_number++;
+
+ *string = (char *)xmalloc (len + 1);
+
+ memcpy (*string, &input_text[current_point], len);
+ (*string)[len] = '\0';
+
+ /* Now leave input_text_offset in a consistent state. */
+ input_text_offset = tem;
+
+ if (input_text_offset > size_of_input_text)
+ input_text_offset = size_of_input_text;
+
+ return (new_point);
+}
+
+/* Read characters from the file until we are at MATCH or end of line.
+ Place the characters read into STRING. */
+void
+get_until_in_line (match, string)
+ char *match, **string;
+{
+ int real_bottom, temp;
+
+ real_bottom = size_of_input_text;
+ temp = search_forward ("\n", input_text_offset);
+
+ if (temp < 0)
+ temp = size_of_input_text;
+
+ size_of_input_text = temp;
+ get_until (match, string);
+ size_of_input_text = real_bottom;
+}
+
+void
+get_rest_of_line (string)
+ char **string;
+{
+ get_until ("\n", string);
+ canon_white (*string);
+
+ if (curchar () == '\n') /* as opposed to the end of the file... */
+ {
+ line_number++;
+ input_text_offset++;
+ }
+}
+
+/* Backup the input pointer to the previous character, keeping track
+ of the current line number. */
+void
+backup_input_pointer ()
+{
+ if (input_text_offset)
+ {
+ input_text_offset--;
+ if (curchar () == '\n')
+ line_number--;
+ }
+}
+
+/* Read characters from the file until we are at MATCH or closing brace.
+ Place the characters read into STRING. */
+void
+get_until_in_braces (match, string)
+ char *match, **string;
+{
+ int i, brace = 0;
+ int match_len = strlen (match);
+ char *temp;
+
+ for (i = input_text_offset; i < size_of_input_text; i++)
+ {
+ if (input_text[i] == '{')
+ brace++;
+ else if (input_text[i] == '}')
+ brace--;
+ else if (input_text[i] == '\n')
+ line_number++;
+
+ if (brace < 0 ||
+ (brace == 0 && strncmp (input_text + i, match, match_len) == 0))
+ break;
+ }
+
+ match_len = i - input_text_offset;
+ temp = (char *)xmalloc (2 + match_len);
+ strncpy (temp, input_text + input_text_offset, match_len);
+ temp[match_len] = '\0';
+ input_text_offset = i;
+ *string = temp;
+}
+
+/* **************************************************************** */
+/* */
+/* Converting the File */
+/* */
+/* **************************************************************** */
+
+/* Convert the file named by NAME. The output is saved on the file
+ named as the argument to the @setfilename command. */
+static char *suffixes[] = {
+ ".texinfo",
+ ".texi",
+ ".txinfo",
+ "",
+ (char *)NULL
+};
+
+void
+initialize_conversion ()
+{
+ init_tag_table ();
+ init_indices ();
+ init_internals ();
+ init_paragraph ();
+
+ /* This is used for splitting the output file and for doing section
+ headings. It was previously initialized in `init_paragraph', but its
+ use there loses with the `init_paragraph' calls done by the
+ multitable code; the tag indices get reset to zero. */
+ output_position = 0;
+}
+
+/* We read in multiples of 4k, simply because it is a typical pipe size
+ on unix systems. */
+#define READ_BUFFER_GROWTH (4 * 4096)
+
+/* Convert the texinfo file coming from the open stream STREAM. Assume the
+ source of the stream is named NAME. */
+void
+convert_from_stream (stream, name)
+ FILE *stream;
+ char *name;
+{
+ char *buffer = (char *)NULL;
+ int buffer_offset = 0, buffer_size = 0;
+
+ initialize_conversion ();
+
+ /* Read until the end of the stream. This isn't strictly correct, since
+ the texinfo input may end before the stream ends, but it is a quick
+ working hueristic. */
+ while (!feof (stream))
+ {
+ int count;
+
+ if (buffer_offset + (READ_BUFFER_GROWTH + 1) >= buffer_size)
+ buffer = (char *)
+ xrealloc (buffer, (buffer_size += READ_BUFFER_GROWTH));
+
+ count = fread (buffer + buffer_offset, 1, READ_BUFFER_GROWTH, stream);
+
+ if (count < 0)
+ {
+ perror (name);
+ exit (FATAL);
+ }
+
+ buffer_offset += count;
+ if (count == 0)
+ break;
+ }
+
+ /* Set the globals to the new file. */
+ input_text = buffer;
+ size_of_input_text = buffer_offset;
+ input_filename = strdup (name);
+ node_filename = strdup (name);
+ input_text_offset = 0;
+ line_number = 1;
+
+ /* Not strictly necessary. This magic prevents read_token () from doing
+ extra unnecessary work each time it is called (that is a lot of times).
+ The SIZE_OF_INPUT_TEXT is one past the actual end of the text. */
+ input_text[size_of_input_text] = '\n';
+
+ convert_from_loaded_file (name);
+}
+
+void
+convert_from_file (name)
+ char *name;
+{
+ register int i;
+ char *filename = (char *)xmalloc (strlen (name) + 50);
+
+ initialize_conversion ();
+
+ /* Try to load the file specified by NAME, concatenated with our
+ various suffixes. Prefer files like `makeinfo.texi' to
+ `makeinfo'. */
+ for (i = 0; suffixes[i]; i++)
+ {
+ strcpy (filename, name);
+ strcat (filename, suffixes[i]);
+
+ if (find_and_load (filename))
+ break;
+
+ if (!suffixes[i][0] && strrchr (filename, '.'))
+ {
+ fs_error (filename);
+ free (filename);
+ return;
+ }
+ }
+
+ if (!suffixes[i])
+ {
+ fs_error (name);
+ free (filename);
+ return;
+ }
+
+ input_filename = filename;
+
+ convert_from_loaded_file (name);
+}
+
+void
+convert_from_loaded_file (name)
+ char *name;
+{
+ char *expand_filename (), *filename_part ();
+ char *real_output_filename = (char *)NULL;
+
+#if defined (HAVE_MACROS)
+ remember_itext (input_text, 0);
+#endif /* HAVE_MACROS */
+
+ /* Search this file looking for the special string which starts conversion.
+ Once found, we may truly begin. */
+ input_text_offset = 0;
+ while (input_text_offset >= 0)
+ {
+ input_text_offset =
+ search_forward (setfilename_search, input_text_offset);
+
+ if ((input_text_offset == 0) ||
+ ((input_text_offset > 0) &&
+ (input_text[input_text_offset -1] == '\n')))
+ break;
+ else if (input_text_offset > 0)
+ input_text_offset++;
+ }
+
+ if (input_text_offset < 0)
+ {
+ if (!command_output_filename)
+ {
+#if defined (REQUIRE_SETFILENAME)
+ error ("No `%s' found in `%s'", setfilename_search, name);
+ goto finished;
+#else
+ register int i, end_of_first_line;
+
+ /* Find the end of the first line in the file. */
+ for (i = 0; i < size_of_input_text - 1; i++)
+ if (input_text[i] == '\n')
+ break;
+
+ end_of_first_line = i + 1;
+
+ input_text_offset = 0;
+
+ for (i = 0; i < end_of_first_line; i++)
+ {
+ if ((input_text[i] == '\\') &&
+ (strncmp (input_text + i + 1, "include", 7) == 0))
+ {
+ input_text_offset = end_of_first_line;
+ break;
+ }
+ }
+ command_output_filename = output_name_from_input_name (name);
+#endif /* !REQUIRE_SETFILENAME */
+ }
+ }
+ else
+ input_text_offset += strlen (setfilename_search);
+
+ if (!command_output_filename)
+ get_until ("\n", &output_filename);
+ else
+ {
+ if (input_text_offset != -1)
+ discard_until ("\n");
+ else
+ input_text_offset = 0;
+
+ real_output_filename = output_filename = command_output_filename;
+ command_output_filename = (char *)NULL;
+ }
+
+ canon_white (output_filename);
+
+ if (real_output_filename &&
+ strcmp (real_output_filename, "-") == 0)
+ {
+ real_output_filename = strdup (real_output_filename);
+ output_stream = stdout;
+ splitting = 0; /* Cannot split when writing to stdout. */
+ }
+ else
+ {
+ if (!real_output_filename)
+ real_output_filename = expand_filename (output_filename, name);
+ else
+ real_output_filename = strdup (real_output_filename);
+
+ output_stream = fopen (real_output_filename, "w");
+ }
+
+ if (output_stream != stdout)
+ printf ("Making %s file `%s' from `%s'.\n",
+ no_headers ? "text" : "info", output_filename, input_filename);
+
+ if (output_stream == NULL)
+ {
+ fs_error (real_output_filename);
+ goto finished;
+ }
+
+ /* Make the displayable filename from output_filename. Only the base
+ portion of the filename need be displayed. */
+ if (output_stream != stdout)
+ pretty_output_filename = filename_part (output_filename);
+ else
+ pretty_output_filename = strdup ("stdout");
+
+ /* For this file only, count the number of newlines from the top of
+ the file to here. This way, we keep track of line numbers for
+ error reporting. Line_number starts at 1, since the user isn't
+ zero-based. */
+ {
+ int temp = 0;
+ line_number = 1;
+ while (temp != input_text_offset)
+ if (input_text[temp++] == '\n')
+ line_number++;
+ }
+
+ if (!no_headers)
+ {
+ add_word_args ("This is Info file %s, produced by Makeinfo version %d.%d",
+ output_filename, major_version, minor_version);
+ add_word_args (" from the input file %s.\n", input_filename);
+ }
+
+ close_paragraph ();
+ reader_loop ();
+
+finished:
+ close_paragraph ();
+ flush_file_stack ();
+
+#if defined (HAVE_MACROS)
+ if (macro_expansion_output_stream)
+ fclose (macro_expansion_output_stream);
+#endif /* HAVE_MACROS */
+
+ if (output_stream != NULL)
+ {
+ output_pending_notes ();
+ free_pending_notes ();
+ if (tag_table != NULL)
+ {
+ tag_table = (TAG_ENTRY *) reverse_list (tag_table);
+ if (!no_headers)
+ write_tag_table ();
+ }
+
+ if (output_stream != stdout)
+ fclose (output_stream);
+
+ /* If validating, then validate the entire file right now. */
+ if (validating)
+ validate_file (tag_table);
+
+ /* This used to test && !errors_printed.
+ But some files might have legit warnings. So split anyway. */
+ if (splitting)
+ split_file (real_output_filename, 0);
+ }
+ free (real_output_filename);
+}
+
+void
+free_and_clear (pointer)
+ char **pointer;
+{
+ if ((*pointer) != (char *) NULL)
+ {
+ free (*pointer);
+ *pointer = (char *) NULL;
+ }
+}
+
+ /* Initialize some state. */
+void
+init_internals ()
+{
+ free_and_clear (&current_node);
+ free_and_clear (&output_filename);
+ free_and_clear (&command);
+ free_and_clear (&input_filename);
+ free_node_references ();
+ init_insertion_stack ();
+ init_brace_stack ();
+ command_index = 0;
+ in_menu = 0;
+ in_detailmenu = 0;
+ top_node_seen = 0;
+ non_top_node_seen = 0;
+}
+
+void
+init_paragraph ()
+{
+ free_and_clear (&output_paragraph);
+ output_paragraph = (unsigned char *)xmalloc (paragraph_buffer_len);
+ output_paragraph[0] = '\0';
+ output_paragraph_offset = 0;
+ output_column = 0;
+ paragraph_is_open = 0;
+ current_indent = 0;
+}
+
+/* Okay, we are ready to start the conversion. Call the reader on
+ some text, and fill the text as it is output. Handle commands by
+ remembering things like open braces and the current file position on a
+ stack, and when the corresponding close brace is found, you can call
+ the function with the proper arguments. */
+void
+reader_loop ()
+{
+ int character;
+ int done = 0;
+ int dash_count = 0;
+
+ while (!done)
+ {
+ if (input_text_offset >= size_of_input_text)
+ break;
+
+ character = curchar ();
+
+ if (!in_fixed_width_font &&
+ (character == '\'' || character == '`') &&
+ input_text[input_text_offset + 1] == character)
+ {
+ input_text_offset++;
+ character = '"';
+ }
+
+ if (character == '-')
+ {
+ dash_count++;
+ if (dash_count == 2 && !in_fixed_width_font)
+ {
+ input_text_offset++;
+ continue;
+ }
+ }
+ else
+ {
+ dash_count = 0;
+ }
+
+ /* If this is a whitespace character, then check to see if the line
+ is blank. If so, advance to the carriage return. */
+ if (whitespace (character))
+ {
+ register int i = input_text_offset + 1;
+
+ while (i < size_of_input_text && whitespace (input_text[i]))
+ i++;
+
+ if (i == size_of_input_text || input_text[i] == '\n')
+ {
+ if (i == size_of_input_text)
+ i--;
+
+ input_text_offset = i;
+ character = curchar ();
+ }
+ }
+
+ if (character == '\n')
+ {
+ line_number++;
+
+ /* Check for a menu entry here, since the "escape sequence"
+ that begins menu entries is "\n* ". */
+ if (in_menu && input_text_offset + 1 < size_of_input_text)
+ {
+ char *glean_node_from_menu (), *tem;
+
+ /* Note that the value of TEM is discarded, since it is
+ gauranteed to be NULL when glean_node_from_menu () is
+ called with a non-zero argument. */
+ if (!in_detailmenu)
+ tem = glean_node_from_menu (1);
+ }
+ }
+
+ switch (character)
+ {
+ case COMMAND_PREFIX:
+ read_command ();
+ break;
+
+ case '{':
+
+ /* Special case. I'm not supposed to see this character by itself.
+ If I do, it means there is a syntax error in the input text.
+ Report the error here, but remember this brace on the stack so
+ you can ignore its partner. */
+
+ line_error ("Misplaced `{'");
+ remember_brace (misplaced_brace);
+
+ /* Don't advance input_text_offset since this happens in
+ remember_brace ().
+ input_text_offset++;
+ */
+ break;
+
+ case '}':
+ pop_and_call_brace ();
+ input_text_offset++;
+ break;
+
+ default:
+ add_char (character);
+ input_text_offset++;
+ }
+ }
+#if defined (HAVE_MACROS)
+ if (macro_expansion_output_stream)
+ maybe_write_itext (input_text, input_text_offset);
+#endif /* HAVE_MACROS */
+}
+
+/* Find the command corresponding to STRING. If the command
+ is found, return a pointer to the data structure. Otherwise
+ return (-1). */
+COMMAND *
+get_command_entry (string)
+ char *string;
+{
+ register int i;
+
+ for (i = 0; CommandTable[i].name; i++)
+ if (strcmp (CommandTable[i].name, string) == 0)
+ return (&CommandTable[i]);
+
+ /* This command is not in our predefined command table. Perhaps
+ it is a user defined command. */
+ for (i = 0; i < user_command_array_len; i++)
+ if (user_command_array[i] &&
+ (strcmp (user_command_array[i]->name, string) == 0))
+ return (user_command_array[i]);
+
+ /* Nope, we never heard of this command. */
+ return ((COMMAND *) -1);
+}
+
+/* input_text_offset is right at the command prefix character.
+ Read the next token to determine what to do. */
+void
+read_command ()
+{
+ COMMAND *entry;
+
+ input_text_offset++;
+ free_and_clear (&command);
+ command = read_token ();
+
+#if defined (HAVE_MACROS)
+ /* Check to see if this command is a macro. If so, execute it here. */
+ {
+ MACRO_DEF *def;
+
+ def = find_macro (command);
+
+ if (def)
+ {
+ /* We disallow recursive use of a macro call. Inhibit the expansion
+ of this macro during the life of its execution. */
+ if (!(def->flags & ME_RECURSE))
+ def->inhibited = 1;
+
+ execute_macro (def);
+
+ if (!(def->flags & ME_RECURSE))
+ def->inhibited = 0;
+
+ return;
+ }
+ }
+#endif /* HAVE_MACROS */
+
+ entry = get_command_entry (command);
+
+ if (entry == (COMMAND *)-1)
+ {
+ line_error ("Unknown command `%s'", command);
+ return;
+ }
+
+ if (entry->argument_in_braces)
+ remember_brace (entry->proc);
+
+ (*(entry->proc)) (START, output_paragraph_offset, 0);
+}
+
+/* Return the string which invokes PROC; a pointer to a function. */
+char *
+find_proc_name (proc)
+ COMMAND_FUNCTION *proc;
+{
+ register int i;
+
+ for (i = 0; CommandTable[i].name; i++)
+ if (proc == CommandTable[i].proc)
+ return (CommandTable[i].name);
+ return ("NO_NAME!");
+}
+
+void
+init_brace_stack ()
+{
+ brace_stack = (BRACE_ELEMENT *) NULL;
+}
+
+void
+remember_brace (proc)
+ COMMAND_FUNCTION *proc;
+{
+ if (curchar () != '{')
+ line_error ("%c%s expected `{..}'", COMMAND_PREFIX, command);
+ else
+ input_text_offset++;
+ remember_brace_1 (proc, output_paragraph_offset);
+}
+
+/* Remember the current output position here. Save PROC
+ along with it so you can call it later. */
+void
+remember_brace_1 (proc, position)
+ COMMAND_FUNCTION *proc;
+ int position;
+{
+ BRACE_ELEMENT *new = (BRACE_ELEMENT *) xmalloc (sizeof (BRACE_ELEMENT));
+ new->next = brace_stack;
+ new->proc = proc;
+ new->pos = position;
+ new->line = line_number;
+ new->in_fixed_width_font = in_fixed_width_font;
+ brace_stack = new;
+}
+
+/* Pop the top of the brace stack, and call the associated function
+ with the args END and POS. */
+void
+pop_and_call_brace ()
+{
+ BRACE_ELEMENT *temp;
+ COMMAND_FUNCTION *proc;
+ int pos;
+
+ if (brace_stack == (BRACE_ELEMENT *) NULL)
+ {
+ line_error ("Unmatched }");
+ return;
+ }
+
+ pos = brace_stack->pos;
+ proc = brace_stack->proc;
+ in_fixed_width_font = brace_stack->in_fixed_width_font;
+ temp = brace_stack->next;
+ free (brace_stack);
+ brace_stack = temp;
+
+ (*proc) (END, pos, output_paragraph_offset);
+}
+
+/* Shift all of the markers in `brace_stack' by AMOUNT. */
+void
+adjust_braces_following (here, amount)
+ int here, amount;
+{
+ register BRACE_ELEMENT *stack = brace_stack;
+
+ while (stack)
+ {
+ if (stack->pos >= here)
+ stack->pos += amount;
+ stack = stack->next;
+ }
+}
+
+/* You call discard_braces () when you shouldn't have any braces on the stack.
+ I used to think that this happens for commands that don't take arguments
+ in braces, but that was wrong because of things like @code{foo @@}. So now
+ I only detect it at the beginning of nodes. */
+void
+discard_braces ()
+{
+ if (!brace_stack)
+ return;
+
+ while (brace_stack)
+ {
+ if (brace_stack->proc != misplaced_brace)
+ {
+ char *proc_name;
+ int temp_line_number = line_number;
+
+ line_number = brace_stack->line;
+ proc_name = find_proc_name (brace_stack->proc);
+ line_error ("%c%s missing close brace", COMMAND_PREFIX, proc_name);
+ line_number = temp_line_number;
+ pop_and_call_brace ();
+ }
+ else
+ {
+ BRACE_ELEMENT *temp;
+ temp = brace_stack->next;
+ free (brace_stack);
+ brace_stack = temp;
+ }
+ }
+}
+
+int
+get_char_len (character)
+ int character;
+{
+ /* Return the printed length of the character. */
+ int len;
+
+ switch (character)
+ {
+ case '\t':
+ len = (output_column + 8) & 0xf7;
+ if (len > fill_column)
+ len = fill_column - output_column;
+ else
+ len = len - output_column;
+ break;
+
+ case '\n':
+ len = fill_column - output_column;
+ break;
+
+ default:
+ if (character < ' ')
+ len = 2;
+ else
+ len = 1;
+ }
+ return (len);
+}
+
+#if defined (HAVE_VARARGS_H) && defined (HAVE_VSPRINTF)
+
+void
+add_word_args (va_alist)
+ va_dcl
+{
+ char buffer[1000];
+ char *format;
+ va_list args;
+
+ va_start (args);
+ format = va_arg (args, char *);
+ vsprintf (buffer, format, args);
+ va_end (args);
+ add_word (buffer);
+}
+
+#else /* !(HAVE_VARARGS_H && HAVE_VSPRINTF) */
+
+void
+add_word_args (format, arg1, arg2, arg3, arg4, arg5)
+ char *format;
+{
+ char buffer[1000];
+ sprintf (buffer, format, arg1, arg2, arg3, arg4, arg5);
+ add_word (buffer);
+}
+
+#endif /* !(HAVE_VARARGS_H && HAVE_VSPRINTF) */
+
+/* Add STRING to output_paragraph. */
+void
+add_word (string)
+ char *string;
+{
+ while (*string)
+ add_char (*string++);
+}
+
+/* Non-zero if the last character inserted has the syntax class of NEWLINE. */
+int last_char_was_newline = 1;
+
+/* The actual last inserted character. Note that this may be something
+ other than NEWLINE even if last_char_was_newline is 1. */
+int last_inserted_character = 0;
+
+/* Non-zero means that a newline character has already been
+ inserted, so close_paragraph () should insert one less. */
+int line_already_broken = 0;
+
+/* When non-zero we have finished an insertion (see end_insertion ()) and we
+ want to ignore false continued paragraph closings. */
+int insertion_paragraph_closed = 0;
+
+/* Non-zero means attempt to make all of the lines have fill_column width. */
+int do_justification = 0;
+
+/* Add the character to the current paragraph. If filling_enabled is
+ non-zero, then do filling as well. */
+void
+add_char (character)
+ int character;
+{
+ /* If we are avoiding outputting headers, and we are currently
+ in a menu, then simply return. */
+ if (no_headers && (in_menu || in_detailmenu))
+ return;
+
+ /* If we are adding a character now, then we don't have to
+ ignore close_paragraph () calls any more. */
+ if (must_start_paragraph && character != '\n')
+ {
+ must_start_paragraph = 0;
+ line_already_broken = 0; /* The line is no longer broken. */
+ if (current_indent > output_column)
+ {
+ indent (current_indent - output_column);
+ output_column = current_indent;
+ }
+ }
+
+ if (non_splitting_words && member (character, " \t\n"))
+ character = ' ' | 0x80;
+
+ insertion_paragraph_closed = 0;
+
+ switch (character)
+ {
+ case '\n':
+ if (!filling_enabled)
+ {
+ insert ('\n');
+
+ if (force_flush_right)
+ {
+ close_paragraph ();
+ /* Hack to force single blank lines out in this mode. */
+ flush_output ();
+ }
+
+ output_column = 0;
+
+ if (!no_indent && paragraph_is_open)
+ indent (output_column = current_indent);
+ break;
+ }
+ else /* CHARACTER is newline, and filling is enabled. */
+ {
+ if (sentence_ender (last_inserted_character))
+ {
+ insert (' ');
+ output_column++;
+ last_inserted_character = character;
+ }
+ }
+
+ if (last_char_was_newline)
+ {
+ close_paragraph ();
+ pending_indent = 0;
+ }
+ else
+ {
+ last_char_was_newline = 1;
+ insert (' ');
+ output_column++;
+ }
+ break;
+
+ default:
+ {
+ int len = get_char_len (character);
+ int suppress_insert = 0;
+
+ if ((character == ' ') && (last_char_was_newline))
+ {
+ if (!paragraph_is_open)
+ {
+ pending_indent++;
+ return;
+ }
+ }
+
+ if (!paragraph_is_open)
+ {
+ start_paragraph ();
+
+ /* If the paragraph is supposed to be indented a certain way,
+ then discard all of the pending whitespace. Otherwise, we
+ let the whitespace stay. */
+ if (!paragraph_start_indent)
+ indent (pending_indent);
+ pending_indent = 0;
+ }
+
+ if ((output_column += len) > fill_column)
+ {
+ if (filling_enabled)
+ {
+ int temp = output_paragraph_offset;
+ while (--temp > 0 && output_paragraph[temp] != '\n')
+ {
+ /* If we have found a space, we have the place to break
+ the line. */
+ if (output_paragraph[temp] == ' ')
+ {
+ /* Remove trailing whitespace from output. */
+ while (temp && whitespace (output_paragraph[temp - 1]))
+ temp--;
+
+ output_paragraph[temp++] = '\n';
+
+ /* We have correctly broken the line where we want
+ to. What we don't want is spaces following where
+ we have decided to break the line. We get rid of
+ them. */
+ {
+ int t1 = temp;
+
+ for (;; t1++)
+ {
+ if (t1 == output_paragraph_offset)
+ {
+ if (whitespace (character))
+ suppress_insert = 1;
+ break;
+ }
+ if (!whitespace (output_paragraph[t1]))
+ break;
+ }
+
+ if (t1 != temp)
+ {
+ adjust_braces_following (temp, (- (t1 - temp)));
+ strncpy ((char *) &output_paragraph[temp],
+ (char *) &output_paragraph[t1],
+ (output_paragraph_offset - t1));
+ output_paragraph_offset -= (t1 - temp);
+ }
+ }
+
+ /* Filled, but now indent if that is right. */
+ if (indented_fill && current_indent)
+ {
+ int buffer_len = ((output_paragraph_offset - temp)
+ + current_indent);
+ char *temp_buffer = (char *)xmalloc (buffer_len);
+ int indentation = 0;
+
+ /* We have to shift any markers that are in
+ front of the wrap point. */
+ adjust_braces_following (temp, current_indent);
+
+ while (current_indent > 0 &&
+ indentation != current_indent)
+ temp_buffer[indentation++] = ' ';
+
+ strncpy ((char *) &temp_buffer[current_indent],
+ (char *) &output_paragraph[temp],
+ buffer_len - current_indent);
+
+ if (output_paragraph_offset + buffer_len
+ >= paragraph_buffer_len)
+ {
+ unsigned char *tt = xrealloc
+ (output_paragraph,
+ (paragraph_buffer_len += buffer_len));
+ output_paragraph = tt;
+ }
+ strncpy ((char *) &output_paragraph[temp],
+ temp_buffer, buffer_len);
+ output_paragraph_offset += current_indent;
+ free (temp_buffer);
+ }
+ output_column = 0;
+ while (temp < output_paragraph_offset)
+ output_column +=
+ get_char_len (output_paragraph[temp++]);
+ output_column += len;
+ break;
+ }
+ }
+ }
+ }
+
+ if (!suppress_insert)
+ {
+ insert (character);
+ last_inserted_character = character;
+ }
+ last_char_was_newline = 0;
+ line_already_broken = 0;
+ }
+ }
+}
+
+/* Insert CHARACTER into `output_paragraph'. */
+void
+insert (character)
+ int character;
+{
+ output_paragraph[output_paragraph_offset++] = character;
+ if (output_paragraph_offset == paragraph_buffer_len)
+ {
+ output_paragraph =
+ xrealloc (output_paragraph, (paragraph_buffer_len += 100));
+ }
+}
+
+/* Insert the null-terminated string STRING into `output_paragraph'. */
+void
+insert_string (string)
+ char *string;
+{
+ while (*string)
+ insert (*string++);
+}
+
+/* Remove upto COUNT characters of whitespace from the
+ the current output line. If COUNT is less than zero,
+ then remove until none left. */
+void
+kill_self_indent (count)
+ int count;
+{
+ /* Handle infinite case first. */
+ if (count < 0)
+ {
+ output_column = 0;
+ while (output_paragraph_offset)
+ {
+ if (whitespace (output_paragraph[output_paragraph_offset - 1]))
+ output_paragraph_offset--;
+ else
+ break;
+ }
+ }
+ else
+ {
+ while (output_paragraph_offset && count--)
+ if (whitespace (output_paragraph[output_paragraph_offset - 1]))
+ output_paragraph_offset--;
+ else
+ break;
+ }
+}
+
+/* Non-zero means do not honor calls to flush_output (). */
+static int flushing_ignored = 0;
+
+/* Prevent calls to flush_output () from having any effect. */
+void
+inhibit_output_flushing ()
+{
+ flushing_ignored++;
+}
+
+/* Allow calls to flush_output () to write the paragraph data. */
+void
+uninhibit_output_flushing ()
+{
+ flushing_ignored--;
+}
+
+void
+flush_output ()
+{
+ register int i;
+
+ if (!output_paragraph_offset || flushing_ignored)
+ return;
+
+ for (i = 0; i < output_paragraph_offset; i++)
+ {
+ /* If we turned on the 8th bit for a space
+ inside @w, turn it back off for output. */
+ if (output_paragraph[i] & meta_character_bit)
+ {
+ int temp = UNMETA (output_paragraph[i]);
+ if (temp == ' ')
+ output_paragraph[i] &= 0x7f;
+ }
+ }
+
+ fwrite (output_paragraph, 1, output_paragraph_offset, output_stream);
+
+ output_position += output_paragraph_offset;
+ output_paragraph_offset = 0;
+}
+
+/* How to close a paragraph controlling the number of lines between
+ this one and the last one. */
+
+/* Paragraph spacing is controlled by this variable. It is the number of
+ blank lines that you wish to appear between paragraphs. A value of
+ 1 creates a single blank line between paragraphs. */
+int paragraph_spacing = DEFAULT_PARAGRAPH_SPACING;
+
+/* Close the current paragraph, leaving no blank lines between them. */
+void
+close_single_paragraph ()
+{
+ close_paragraph_with_lines (0);
+}
+
+/* Close a paragraph after an insertion has ended. */
+void
+close_insertion_paragraph ()
+{
+ if (!insertion_paragraph_closed)
+ {
+ /* Close the current paragraph, breaking the line. */
+ close_single_paragraph ();
+
+ /* Start a new paragraph here, inserting whatever indention is correct
+ for the now current insertion level (one above the one that we are
+ ending). */
+ start_paragraph ();
+
+ /* Tell close_paragraph () that the previous line has already been
+ broken, so it should insert one less newline. */
+ line_already_broken = 1;
+
+ /* Let functions such as add_char () know that we have already found a
+ newline. */
+ ignore_blank_line ();
+ }
+ else
+ {
+ /* If the insertion paragraph is closed already, then we are seeing
+ two `@end' commands in a row. Note that the first one we saw was
+ handled in the first part of this if-then-else clause, and at that
+ time start_paragraph () was called, partially to handle the proper
+ indentation of the current line. However, the indentation level
+ may have just changed again, so we may have to outdent the current
+ line to the new indentation level. */
+ if (current_indent < output_column)
+ kill_self_indent (output_column - current_indent);
+ }
+
+ insertion_paragraph_closed = 1;
+}
+
+void
+close_paragraph_with_lines (lines)
+ int lines;
+{
+ int old_spacing = paragraph_spacing;
+ paragraph_spacing = lines;
+ close_paragraph ();
+ paragraph_spacing = old_spacing;
+}
+
+/* Close the currently open paragraph. */
+void
+close_paragraph ()
+{
+ register int i;
+
+ /* The insertion paragraph is no longer closed. */
+ insertion_paragraph_closed = 0;
+
+ if (paragraph_is_open && !must_start_paragraph)
+ {
+ register int tindex, c;
+
+ tindex = output_paragraph_offset;
+
+ /* Back up to last non-newline/space character, forcing all such
+ subsequent characters to be newlines. This isn't strictly
+ necessary, but a couple of functions use the presence of a newline
+ to make decisions. */
+ for (tindex = output_paragraph_offset - 1; tindex >= 0; --tindex)
+ {
+ c = output_paragraph[tindex];
+
+ if (c == ' '|| c == '\n')
+ output_paragraph[tindex] = '\n';
+ else
+ break;
+ }
+
+ /* All trailing whitespace is ignored. */
+ output_paragraph_offset = ++tindex;
+
+ /* Break the line if that is appropriate. */
+ if (paragraph_spacing >= 0)
+ insert ('\n');
+
+ /* Add as many blank lines as is specified in PARAGRAPH_SPACING. */
+ if (!force_flush_right)
+ {
+ for (i = 0; i < (paragraph_spacing - line_already_broken); i++)
+ insert ('\n');
+ }
+
+ /* If we are doing flush right indentation, then do it now
+ on the paragraph (really a single line). */
+ if (force_flush_right)
+ do_flush_right_indentation ();
+
+ flush_output ();
+ paragraph_is_open = 0;
+ no_indent = 0;
+ output_column = 0;
+ }
+ ignore_blank_line ();
+}
+
+/* Make the last line just read look as if it were only a newline. */
+void
+ignore_blank_line ()
+{
+ last_inserted_character = '\n';
+ last_char_was_newline = 1;
+}
+
+/* Align the end of the text in output_paragraph with fill_column. */
+void
+do_flush_right_indentation ()
+{
+ char *temp;
+ int temp_len;
+
+ kill_self_indent (-1);
+
+ if (output_paragraph[0] != '\n')
+ {
+ output_paragraph[output_paragraph_offset] = '\0';
+
+ if (output_paragraph_offset < fill_column)
+ {
+ register int i;
+
+ if (fill_column >= paragraph_buffer_len)
+ output_paragraph =
+ xrealloc (output_paragraph,
+ (paragraph_buffer_len += fill_column));
+
+ temp_len = strlen ((char *)output_paragraph);
+ temp = (char *)xmalloc (temp_len + 1);
+ memcpy (temp, (char *)output_paragraph, temp_len);
+
+ for (i = 0; i < fill_column - output_paragraph_offset; i++)
+ output_paragraph[i] = ' ';
+
+ memcpy ((char *)output_paragraph + i, temp, temp_len);
+ free (temp);
+ output_paragraph_offset = fill_column;
+ }
+ }
+}
+
+/* Begin a new paragraph. */
+void
+start_paragraph ()
+{
+ /* First close existing one. */
+ if (paragraph_is_open)
+ close_paragraph ();
+
+ /* In either case, the insertion paragraph is no longer closed. */
+ insertion_paragraph_closed = 0;
+
+ /* However, the paragraph is open! */
+ paragraph_is_open = 1;
+
+ /* If we MUST_START_PARAGRAPH, that simply means that start_paragraph ()
+ had to be called before we would allow any other paragraph operations
+ to have an effect. */
+ if (!must_start_paragraph)
+ {
+ int amount_to_indent = 0;
+
+ /* If doing indentation, then insert the appropriate amount. */
+ if (!no_indent)
+ {
+ if (inhibit_paragraph_indentation)
+ {
+ amount_to_indent = current_indent;
+ if (inhibit_paragraph_indentation < 0)
+ inhibit_paragraph_indentation++;
+ }
+ else if (paragraph_start_indent < 0)
+ amount_to_indent = current_indent;
+ else
+ amount_to_indent = current_indent + paragraph_start_indent;
+
+ if (amount_to_indent >= output_column)
+ {
+ amount_to_indent -= output_column;
+ indent (amount_to_indent);
+ output_column += amount_to_indent;
+ }
+ }
+ }
+ else
+ must_start_paragraph = 0;
+}
+
+/* Insert the indentation specified by AMOUNT. */
+void
+indent (amount)
+ int amount;
+{
+ register BRACE_ELEMENT *elt = brace_stack;
+
+ /* For every START_POS saved within the brace stack which will be affected
+ by this indentation, bump that start pos forward. */
+ while (elt)
+ {
+ if (elt->pos >= output_paragraph_offset)
+ elt->pos += amount;
+ elt = elt->next;
+ }
+
+ while (--amount >= 0)
+ insert (' ');
+}
+
+/* Search forward for STRING in input_text.
+ FROM says where where to start. */
+int
+search_forward (string, from)
+ char *string;
+ int from;
+{
+ int len = strlen (string);
+
+ while (from < size_of_input_text)
+ {
+ if (strncmp (input_text + from, string, len) == 0)
+ return (from);
+ from++;
+ }
+ return (-1);
+}
+
+/* Whoops, Unix doesn't have strcasecmp. */
+
+/* Case independent string compare. */
+#if !defined (HAVE_STRCASECMP)
+int
+strcasecmp (string1, string2)
+ char *string1, *string2;
+{
+ char ch1, ch2;
+
+ for (;;)
+ {
+ ch1 = *string1++;
+ ch2 = *string2++;
+
+ if (!(ch1 | ch2))
+ return (0);
+
+ ch1 = coerce_to_upper (ch1);
+ ch2 = coerce_to_upper (ch2);
+
+ if (ch1 != ch2)
+ return (ch1 - ch2);
+ }
+}
+#endif /* !HAVE_STRCASECMP */
+
+void
+init_insertion_stack ()
+{
+ insertion_stack = (INSERTION_ELT *) NULL;
+}
+
+/* Return the type of the current insertion. */
+enum insertion_type
+current_insertion_type ()
+{
+ if (!insertion_level)
+ return (bad_type);
+ else
+ return (insertion_stack->insertion);
+}
+
+/* Return a pointer to the string which is the function to wrap around
+ items. */
+char *
+current_item_function ()
+{
+ register int level, done;
+ register INSERTION_ELT *elt;
+
+ level = insertion_level;
+ elt = insertion_stack;
+ done = 0;
+
+ /* Skip down through the stack until we find a non-conditional insertion. */
+ while (!done && (elt != NULL))
+ {
+ switch (elt->insertion)
+ {
+ case ifinfo:
+ case ifset:
+ case ifclear:
+ case cartouche:
+ elt = elt->next;
+ level--;
+ break;
+
+ default:
+ done = 1;
+ }
+ }
+
+ if (!level)
+ return ((char *) NULL);
+ else
+ return (elt->item_function);
+}
+
+char *
+get_item_function ()
+{
+ char *item_function;
+ get_rest_of_line (&item_function);
+ backup_input_pointer ();
+ canon_white (item_function);
+ return (item_function);
+}
+
+ /* Push the state of the current insertion on the stack. */
+void
+push_insertion (type, item_function)
+ enum insertion_type type;
+ char *item_function;
+{
+ INSERTION_ELT *new = (INSERTION_ELT *) xmalloc (sizeof (INSERTION_ELT));
+
+ new->item_function = item_function;
+ new->filling_enabled = filling_enabled;
+ new->indented_fill = indented_fill;
+ new->insertion = type;
+ new->line_number = line_number;
+ new->filename = strdup (input_filename);
+ new->inhibited = inhibit_paragraph_indentation;
+ new->in_fixed_width_font = in_fixed_width_font;
+ new->next = insertion_stack;
+ insertion_stack = new;
+ insertion_level++;
+}
+
+ /* Pop the value on top of the insertion stack into the
+ global variables. */
+void
+pop_insertion ()
+{
+ INSERTION_ELT *temp = insertion_stack;
+
+ if (temp == (INSERTION_ELT *) NULL)
+ return;
+
+ in_fixed_width_font = temp->in_fixed_width_font;
+ inhibit_paragraph_indentation = temp->inhibited;
+ filling_enabled = temp->filling_enabled;
+ indented_fill = temp->indented_fill;
+ free_and_clear (&(temp->item_function));
+ free_and_clear (&(temp->filename));
+ insertion_stack = insertion_stack->next;
+ free (temp);
+ insertion_level--;
+}
+
+ /* Return a pointer to the print name of this
+ enumerated type. */
+char *
+insertion_type_pname (type)
+ enum insertion_type type;
+{
+ if ((int) type < (int) bad_type)
+ return (insertion_type_names[(int) type]);
+ else
+ return ("Broken-Type in insertion_type_pname");
+}
+
+/* Return the insertion_type associated with NAME.
+ If the type is not one of the known ones, return BAD_TYPE. */
+enum insertion_type
+find_type_from_name (name)
+ char *name;
+{
+ int index = 0;
+ while (index < (int) bad_type)
+ {
+ if (strcmp (name, insertion_type_names[index]) == 0)
+ return (enum insertion_type) index;
+ index++;
+ }
+ return (bad_type);
+}
+
+int
+defun_insertion (type)
+ enum insertion_type type;
+{
+ return
+ ((type == deffn)
+ || (type == defun)
+ || (type == defmac)
+ || (type == defspec)
+ || (type == defvr)
+ || (type == defvar)
+ || (type == defopt)
+ || (type == deftypefn)
+ || (type == deftypefun)
+ || (type == deftypevr)
+ || (type == deftypevar)
+ || (type == defcv)
+ || (type == defivar)
+ || (type == defop)
+ || (type == defmethod)
+ || (type == deftypemethod)
+ || (type == deftp));
+}
+
+/* MAX_NS is the maximum nesting level for enumerations. I picked 100
+ which seemed reasonable. This doesn't control the number of items,
+ just the number of nested lists. */
+#define max_stack_depth 100
+#define ENUM_DIGITS 1
+#define ENUM_ALPHA 2
+typedef struct {
+ int enumtype;
+ int enumval;
+} DIGIT_ALPHA;
+
+DIGIT_ALPHA enumstack[max_stack_depth];
+int enumstack_offset = 0;
+int current_enumval = 1;
+int current_enumtype = ENUM_DIGITS;
+char *enumeration_arg = (char *)NULL;
+
+void
+start_enumerating (at, type)
+ int at, type;
+{
+ if ((enumstack_offset + 1) == max_stack_depth)
+ {
+ line_error ("Enumeration stack overflow");
+ return;
+ }
+ enumstack[enumstack_offset].enumtype = current_enumtype;
+ enumstack[enumstack_offset].enumval = current_enumval;
+ enumstack_offset++;
+ current_enumval = at;
+ current_enumtype = type;
+}
+
+void
+stop_enumerating ()
+{
+ --enumstack_offset;
+ if (enumstack_offset < 0)
+ enumstack_offset = 0;
+
+ current_enumval = enumstack[enumstack_offset].enumval;
+ current_enumtype = enumstack[enumstack_offset].enumtype;
+}
+
+/* Place a letter or digits into the output stream. */
+void
+enumerate_item ()
+{
+ char temp[10];
+
+ if (current_enumtype == ENUM_ALPHA)
+ {
+ if (current_enumval == ('z' + 1) || current_enumval == ('Z' + 1))
+ {
+ current_enumval = ((current_enumval - 1) == 'z' ? 'a' : 'A');
+ warning ("Lettering overflow, restarting at %c", current_enumval);
+ }
+ sprintf (temp, "%c. ", current_enumval);
+ }
+ else
+ sprintf (temp, "%d. ", current_enumval);
+
+ indent (output_column += (current_indent - strlen (temp)));
+ add_word (temp);
+ current_enumval++;
+}
+
+/* This is where the work for all the "insertion" style
+ commands is done. A huge switch statement handles the
+ various setups, and generic code is on both sides. */
+void
+begin_insertion (type)
+ enum insertion_type type;
+{
+ int no_discard = 0;
+
+ if (defun_insertion (type))
+ {
+ push_insertion (type, strdup (""));
+ no_discard++;
+ }
+ else
+ push_insertion (type, get_item_function ());
+
+ switch (type)
+ {
+ case menu:
+ if (!no_headers)
+ close_paragraph ();
+
+ filling_enabled = no_indent = 0;
+ inhibit_paragraph_indentation = 1;
+
+ if (!no_headers)
+ add_word ("* Menu:\n");
+
+ in_menu++;
+ no_discard++;
+ break;
+
+ case detailmenu:
+
+ if (!in_menu)
+ {
+ if (!no_headers)
+ close_paragraph ();
+
+ filling_enabled = no_indent = 0;
+ inhibit_paragraph_indentation = 1;
+
+ no_discard++;
+ }
+
+ in_detailmenu++;
+ break;
+
+ case direntry:
+ close_single_paragraph ();
+ filling_enabled = no_indent = 0;
+ inhibit_paragraph_indentation = 1;
+ insert_string ("START-INFO-DIR-ENTRY\n");
+ break;
+
+ /* I think @quotation is meant to do filling.
+ If you don't want filling, then use @display. */
+ case quotation:
+ close_single_paragraph ();
+ last_char_was_newline = no_indent = 0;
+ indented_fill = filling_enabled = 1;
+ inhibit_paragraph_indentation = 1;
+ current_indent += default_indentation_increment;
+ break;
+
+ case display:
+ case example:
+ case smallexample:
+ case lisp:
+ case smalllisp:
+ /* Just like @example, but no indentation. */
+ case format:
+
+ close_single_paragraph ();
+ inhibit_paragraph_indentation = 1;
+ in_fixed_width_font++;
+ filling_enabled = 0;
+ last_char_was_newline = 0;
+
+ if (type != format)
+ current_indent += default_indentation_increment;
+
+ break;
+
+ case multitable:
+ do_multitable ();
+ break;
+
+ case table:
+ case ftable:
+ case vtable:
+ case itemize:
+ close_single_paragraph ();
+ current_indent += default_indentation_increment;
+ filling_enabled = indented_fill = 1;
+#if defined (INDENT_PARAGRAPHS_IN_TABLE)
+ inhibit_paragraph_indentation = 0;
+#else
+ inhibit_paragraph_indentation = 1;
+#endif /* !INDENT_PARAGRAPHS_IN_TABLE */
+
+ /* Make things work for losers who forget the itemize syntax. */
+ if (allow_lax_format && (type == itemize))
+ {
+ if (!(*insertion_stack->item_function))
+ {
+ free (insertion_stack->item_function);
+ insertion_stack->item_function = strdup ("@bullet");
+ insertion_stack->item_function[0] = COMMAND_PREFIX;
+ }
+ }
+
+ if (!*insertion_stack->item_function)
+ {
+ line_error ("%s requires an argument: the formatter for %citem",
+ insertion_type_pname (type), COMMAND_PREFIX);
+ }
+ break;
+
+ case enumerate:
+ close_single_paragraph ();
+ no_indent = 0;
+#if defined (INDENT_PARAGRAPHS_IN_TABLE)
+ inhibit_paragraph_indentation = 0;
+#else
+ inhibit_paragraph_indentation = 1;
+#endif /* !INDENT_PARAGRAPHS_IN_TABLE */
+
+ current_indent += default_indentation_increment;
+ filling_enabled = indented_fill = 1;
+
+ if (isdigit (*enumeration_arg))
+ start_enumerating (atoi (enumeration_arg), ENUM_DIGITS);
+ else
+ start_enumerating (*enumeration_arg, ENUM_ALPHA);
+ break;
+
+ /* Does nothing special in makeinfo. */
+ case group:
+ /* Only close the paragraph if we are not inside of an @example. */
+ if (!insertion_stack->next ||
+ insertion_stack->next->insertion != example)
+ close_single_paragraph ();
+ break;
+
+ /* Insertions that are no-ops in info, but do something in TeX. */
+ case ifinfo:
+ case ifset:
+ case ifclear:
+ case cartouche:
+ if (in_menu)
+ no_discard++;
+ break;
+
+ case deffn:
+ case defun:
+ case defmac:
+ case defspec:
+ case defvr:
+ case defvar:
+ case defopt:
+ case deftypefn:
+ case deftypefun:
+ case deftypevr:
+ case deftypevar:
+ case defcv:
+ case defivar:
+ case defop:
+ case defmethod:
+ case deftypemethod:
+ case deftp:
+ inhibit_paragraph_indentation = 1;
+ filling_enabled = indented_fill = 1;
+ current_indent += default_indentation_increment;
+ no_indent = 0;
+ break;
+
+ case flushleft:
+ close_single_paragraph ();
+ inhibit_paragraph_indentation = 1;
+ filling_enabled = indented_fill = no_indent = 0;
+ break;
+
+ case flushright:
+ close_single_paragraph ();
+ filling_enabled = indented_fill = no_indent = 0;
+ inhibit_paragraph_indentation = 1;
+ force_flush_right++;
+ break;
+ }
+
+ if (!no_discard)
+ discard_until ("\n");
+}
+
+/* Try to end the insertion with the specified TYPE.
+ TYPE, with a value of bad_type, gets translated to match
+ the value currently on top of the stack.
+ Otherwise, if TYPE doesn't match the top of the insertion stack,
+ give error. */
+void
+end_insertion (type)
+ enum insertion_type type;
+{
+ enum insertion_type temp_type;
+
+ if (!insertion_level)
+ return;
+
+ temp_type = current_insertion_type ();
+
+ if (type == bad_type)
+ type = temp_type;
+
+ if (type != temp_type)
+ {
+ line_error
+ ("`%cend' expected `%s', but saw `%s'", COMMAND_PREFIX,
+ insertion_type_pname (temp_type), insertion_type_pname (type));
+ return;
+ }
+
+ pop_insertion ();
+
+ switch (type)
+ {
+ /* Insertions which have no effect on paragraph formatting. */
+ case ifinfo:
+ case ifset:
+ case ifclear:
+ break;
+
+ case direntry:
+ insert_string ("END-INFO-DIR-ENTRY\n\n");
+ close_insertion_paragraph ();
+ break;
+
+ case detailmenu:
+ in_detailmenu--; /* No longer hacking menus. */
+ if (!in_menu)
+ {
+ if (!no_headers)
+ close_insertion_paragraph ();
+ }
+ break;
+
+ case menu:
+ in_menu--; /* No longer hacking menus. */
+ if (!no_headers)
+ close_insertion_paragraph ();
+ break;
+
+ case multitable:
+ end_multitable ();
+ break;
+
+ case enumerate:
+ stop_enumerating ();
+ close_insertion_paragraph ();
+ current_indent -= default_indentation_increment;
+ break;
+
+ case flushleft:
+ case group:
+ case cartouche:
+ close_insertion_paragraph ();
+ break;
+
+ case format:
+ case display:
+ case example:
+ case smallexample:
+ case lisp:
+ case smalllisp:
+ case quotation:
+
+ /* @format is the only fixed_width insertion without a change
+ in indentation. */
+ if (type != format)
+ current_indent -= default_indentation_increment;
+
+ /* The ending of one of these insertions always marks the
+ start of a new paragraph. */
+ close_insertion_paragraph ();
+ break;
+
+ case table:
+ case ftable:
+ case vtable:
+ case itemize:
+ current_indent -= default_indentation_increment;
+ break;
+
+ case flushright:
+ force_flush_right--;
+ close_insertion_paragraph ();
+ break;
+
+ /* Handle the @defun style insertions with a default clause. */
+ default:
+ current_indent -= default_indentation_increment;
+ close_insertion_paragraph ();
+ break;
+ }
+}
+
+/* Insertions cannot cross certain boundaries, such as node beginnings. In
+ code that creates such boundaries, you should call discard_insertions ()
+ before doing anything else. It prints the errors for you, and cleans up
+ the insertion stack. */
+void
+discard_insertions ()
+{
+ int real_line_number = line_number;
+ while (insertion_stack)
+ {
+ if (insertion_stack->insertion == ifinfo ||
+ insertion_stack->insertion == ifset ||
+ insertion_stack->insertion == ifclear)
+ break;
+ else
+ {
+ char *offender;
+ char *current_filename;
+
+ current_filename = input_filename;
+ offender = (char *)insertion_type_pname (insertion_stack->insertion);
+ input_filename = insertion_stack->filename;
+ line_number = insertion_stack->line_number;
+ line_error ("This `%s' doesn't have a matching `%cend %s'", offender,
+ COMMAND_PREFIX, offender);
+ input_filename = current_filename;
+ pop_insertion ();
+ }
+ }
+ line_number = real_line_number;
+}
+
+/* The Texinfo commands. */
+
+/* Commands which insert their own names. */
+void
+insert_self (arg)
+ int arg;
+{
+ if (arg == START)
+ add_word (command);
+}
+
+void
+insert_space (arg)
+ int arg;
+{
+ if (arg == START)
+ add_char (' ');
+}
+
+/* Force a line break in the output. */
+void
+cm_asterisk ()
+{
+ close_single_paragraph ();
+#if !defined (ASTERISK_NEW_PARAGRAPH)
+ cm_noindent ();
+#endif /* ASTERISK_NEW_PARAGRAPH */
+}
+
+/* Insert ellipsis. */
+void
+cm_dots (arg)
+ int arg;
+{
+ if (arg == START)
+ add_word ("...");
+}
+
+/* Insert ellipsis for sentence end. */
+void
+cm_enddots (arg)
+ int arg;
+{
+ if (arg == START)
+ add_word ("....");
+}
+
+void
+cm_bullet (arg)
+ int arg;
+{
+ if (arg == START)
+ add_char ('*');
+}
+
+void
+cm_minus (arg)
+ int arg;
+{
+ if (arg == START)
+ add_char ('-');
+}
+
+/* Insert "TeX". */
+void
+cm_TeX (arg)
+ int arg;
+{
+ if (arg == START)
+ add_word ("TeX");
+}
+
+/* Copyright symbol. */
+void
+cm_copyright (arg)
+ int arg;
+{
+ if (arg == START)
+ add_word ("(C)");
+}
+
+/* Accent commands that take explicit arguments. */
+void
+cm_accent (arg)
+ int arg;
+{
+ if (arg == START)
+ {
+ if (strcmp (command, "dotaccent") == 0) /* overdot */
+ add_char ('.');
+ else if (strcmp (command, "H") == 0) /* Hungarian umlaut */
+ add_word ("''");
+ else if (strcmp (command, "ringaccent") == 0)
+ add_char ('*');
+ else if (strcmp (command, "tieaccent") == 0)
+ add_char ('[');
+ else if (strcmp (command, "u") == 0) /* breve */
+ add_char ('(');
+ else if (strcmp (command, "v") == 0) /* hacek/check */
+ add_char ('<');
+ }
+ else if (arg == END)
+ {
+ if (strcmp (command, "ubaraccent") == 0) /* underbar */
+ add_char ('_');
+ else if (strcmp (command, "udotaccent") == 0) /* underdot */
+ add_word ("-.");
+ else if (strcmp (command, ",") == 0) /* cedilla */
+ add_word (",");
+ }
+}
+
+/* Non-English letters/characters that don't insert themselves. */
+void
+cm_special_char (arg)
+{
+ if (arg == START)
+ {
+ if ((*command == 'L' || *command == 'l'
+ || *command == 'O' || *command == 'o')
+ && command[1] == 0)
+ {
+ /* Lslash lslash Oslash oslash */
+ add_char (*command);
+ add_char ('/');
+ }
+ else if (strcmp (command, "exclamdown") == 0)
+ add_char ('!');
+ else if (strcmp (command, "pounds") == 0)
+ add_char ('#');
+ else if (strcmp (command, "questiondown") == 0)
+ add_char ('?');
+ else
+ fprintf (stderr, "How did @%s end up in cm_special_char?\n", command);
+ }
+}
+
+/* Dotless i or j. */
+void
+cm_dotless (arg, start, end)
+ int arg, start, end;
+{
+ if (arg == END)
+ {
+ if (output_paragraph[start] != 'i' && output_paragraph[start] != 'j')
+ /* This error message isn't perfect if the argument is multiple
+ characters, but it doesn't seem worth getting right. */
+ line_error ("%c%s expects `i' or `j' as argument, not `%c'",
+ COMMAND_PREFIX, command, output_paragraph[start]);
+
+ else if (end - start != 1)
+ line_error ("%c%s expects a single character `i' or `j' as argument",
+ COMMAND_PREFIX, command);
+
+ /* We've already inserted the `i' or `j', so nothing to do. */
+ }
+}
+
+#if defined (__osf__)
+#define LOCALTIME_CAST(x) (time_t *)(x)
+#else
+#define LOCALTIME_CAST(x) (x)
+#endif
+
+void
+cm_today (arg)
+ int arg;
+{
+ static char * months [12] =
+ { "January", "February", "March", "April", "May", "June", "July",
+ "August", "September", "October", "November", "December" };
+ if (arg == START)
+ {
+ long timer = time (0);
+ struct tm *ts = localtime (LOCALTIME_CAST (&timer));
+ add_word_args
+ ("%d %s %d",
+ (ts -> tm_mday),
+ (months [ts -> tm_mon]),
+ ((ts -> tm_year) + 1900));
+ }
+}
+
+void
+cm_code (arg)
+ int arg;
+{
+ extern int printing_index;
+
+ if (arg == START)
+ {
+ in_fixed_width_font++;
+
+ if (!printing_index)
+ add_char ('`');
+ }
+ else
+ {
+ if (!printing_index)
+ add_char ('\'');
+ }
+}
+
+void
+cm_kbd (arg)
+ int arg;
+{
+ /* People use @kbd in an example to get the "user input" font.
+ We don't want quotes in that case. */
+ if (!in_fixed_width_font)
+ cm_code (arg);
+}
+
+void
+cm_angle_brackets (arg)
+ int arg;
+{
+ add_char (arg == START ? '<' : '>');
+}
+
+/* Convert the character at position into a true control character. */
+void
+cm_ctrl (arg, start, end)
+ int arg, start, end;
+{
+ /* Should we allow multiple character arguments? I think yes. */
+ if (arg == END)
+ {
+ register int i, character;
+#if defined (NO_MULTIPLE_CTRL)
+ if ((end - start) != 1)
+ line_error ("%c%s expects a single character as an argument",
+ COMMAND_PREFIX, command);
+ else
+#endif
+ for (i = start; i < end; i++)
+ {
+ character = output_paragraph[i];
+
+ if (isletter (character))
+ output_paragraph[i] = CTL (coerce_to_upper (character));
+ }
+ }
+}
+
+/* Handle a command that switches to a non-fixed-width font. */
+void
+not_fixed_width (arg)
+ int arg;
+{
+ if (arg == START)
+ in_fixed_width_font = 0;
+}
+
+/* Small caps in makeinfo has to do just all caps. */
+void
+cm_sc (arg, start_pos, end_pos)
+ int arg, start_pos, end_pos;
+{
+ not_fixed_width (arg);
+
+ if (arg == END)
+ {
+ while (start_pos < end_pos)
+ {
+ output_paragraph[start_pos] =
+ coerce_to_upper (output_paragraph[start_pos]);
+ start_pos++;
+ }
+ }
+}
+
+/* @var in makeinfo just uppercases the text. */
+void
+cm_var (arg, start_pos, end_pos)
+ int arg, start_pos, end_pos;
+{
+ not_fixed_width (arg);
+
+ if (arg == END)
+ {
+ while (start_pos < end_pos)
+ {
+ output_paragraph[start_pos] =
+ coerce_to_upper (output_paragraph[start_pos]);
+ start_pos++;
+ }
+ }
+}
+
+void
+cm_dfn (arg, position)
+ int arg, position;
+{
+ add_char ('"');
+}
+
+void
+cm_emph (arg)
+ int arg;
+{
+ add_char ('*');
+}
+
+void
+cm_strong (arg, position)
+ int arg, position;
+{
+ cm_emph (arg);
+}
+
+void
+cm_cite (arg, position)
+ int arg, position;
+{
+ if (arg == START)
+ add_word ("`");
+ else
+ add_word ("'");
+}
+
+/* No highlighting, but argument switches fonts. */
+void
+cm_not_fixed_width (arg, start, end)
+ int arg, start, end;
+{
+ not_fixed_width (arg);
+}
+
+/* Various commands are NOP's. */
+void
+cm_no_op ()
+{
+}
+
+/* Prevent the argument from being split across two lines. */
+void
+cm_w (arg, start, end)
+ int arg, start, end;
+{
+ if (arg == START)
+ non_splitting_words++;
+ else
+ non_splitting_words--;
+}
+
+
+/* Explain that this command is obsolete, thus the user shouldn't
+ do anything with it. */
+void
+cm_obsolete (arg, start, end)
+ int arg, start, end;
+{
+ if (arg == START)
+ warning ("The command `%c%s' is obsolete", COMMAND_PREFIX, command);
+}
+
+/* Insert the text following input_text_offset up to the end of the line
+ in a new, separate paragraph. Directly underneath it, insert a
+ line of WITH_CHAR, the same length of the inserted text. */
+void
+insert_and_underscore (with_char)
+ int with_char;
+{
+ register int i, len;
+ int old_no_indent, starting_pos, ending_pos;
+ char *temp;
+
+ close_paragraph ();
+ filling_enabled = indented_fill = 0;
+ old_no_indent = no_indent;
+ no_indent = 1;
+
+#if defined (HAVE_MACROS)
+ if (macro_expansion_output_stream)
+ append_to_expansion_output (input_text_offset + 1);
+#endif /* HAVE_MACROS */
+
+ get_rest_of_line (&temp);
+
+ starting_pos = output_position + output_paragraph_offset;
+#if defined (HAVE_MACROS)
+ if (macro_expansion_output_stream)
+ {
+ char *temp1;
+
+ temp1 = (char *)xmalloc (2 + strlen (temp));
+ sprintf (temp1, "%s\n", temp);
+ remember_itext (input_text, input_text_offset);
+ me_execute_string (temp1);
+ free (temp1);
+ }
+ else
+#endif /* HAVE_MACROS */
+ execute_string ("%s\n", temp);
+
+ ending_pos = output_position + output_paragraph_offset;
+ free (temp);
+
+ len = (ending_pos - starting_pos) - 1;
+ for (i = 0; i < len; i++)
+ add_char (with_char);
+ insert ('\n');
+ close_paragraph ();
+ filling_enabled = 1;
+ no_indent = old_no_indent;
+}
+
+/* Here is a structure which associates sectioning commands with
+ an integer, hopefully to reflect the `depth' of the current
+ section. */
+struct {
+ char *name;
+ int level;
+} section_alist[] = {
+ { "unnumberedsubsubsec", 5 },
+ { "unnumberedsubsec", 4 },
+ { "unnumberedsec", 3 },
+ { "unnumbered", 2 },
+ { "appendixsubsubsec", 5 },
+ { "appendixsubsec", 4 },
+ { "appendixsec", 3 },
+ { "appendixsection", 3 },
+ { "appendix", 2 },
+ { "subsubsec", 5 },
+ { "subsubsection", 5 },
+ { "subsection", 4 },
+ { "section", 3 },
+ { "chapter", 2 },
+ { "top", 1 },
+
+ { (char *)NULL, 0 }
+};
+
+/* Amount to offset the name of sectioning commands to levels by. */
+int section_alist_offset = 0;
+
+/* Shift the meaning of @section to @chapter. */
+void
+cm_raisesections ()
+{
+ discard_until ("\n");
+ section_alist_offset--;
+}
+
+/* Shift the meaning of @chapter to @section. */
+void
+cm_lowersections ()
+{
+ discard_until ("\n");
+ section_alist_offset++;
+}
+
+/* Return an integer which identifies the type section present in TEXT. */
+int
+what_section (text)
+ char *text;
+{
+ register int i, j;
+ char *t;
+
+ find_section_command:
+ for (j = 0; text[j] && cr_or_whitespace (text[j]); j++);
+ if (text[j] != COMMAND_PREFIX)
+ return (-1);
+
+ text = text + j + 1;
+
+ /* We skip @c, @comment, and @?index commands. */
+ if ((strncmp (text, "comment", strlen ("comment")) == 0) ||
+ (text[0] == 'c' && cr_or_whitespace (text[1])) ||
+ (strcmp (text + 1, "index") == 0))
+ {
+ while (*text++ != '\n');
+ goto find_section_command;
+ }
+
+ /* Handle italicized sectioning commands. */
+ if (*text == 'i')
+ text++;
+
+ for (j = 0; text[j] && !cr_or_whitespace (text[j]); j++);
+
+ for (i = 0; t = section_alist[i].name; i++)
+ {
+ if (j == strlen (t) && strncmp (t, text, j) == 0)
+ {
+ int return_val;
+
+ return_val = (section_alist[i].level + section_alist_offset);
+
+ if (return_val < 0)
+ return_val = 0;
+ else if (return_val > 5)
+ return_val = 5;
+ return (return_val);
+ }
+ }
+ return (-1);
+}
+
+/* Set the level of @top to LEVEL. Return the old level of @top. */
+int
+set_top_section_level (level)
+ int level;
+{
+ register int i, result = -1;
+
+ for (i = 0; section_alist[i].name; i++)
+ if (strcmp (section_alist[i].name, "top") == 0)
+ {
+ result = section_alist[i].level;
+ section_alist[i].level = level;
+ break;
+ }
+ return (result);
+}
+
+/* Treat this just like @unnumbered. The only difference is
+ in node defaulting. */
+void
+cm_top ()
+{
+ /* It is an error to have more than one @top. */
+ if (top_node_seen)
+ {
+ TAG_ENTRY *tag = tag_table;
+
+ line_error ("There already is a node having %ctop as a section",
+ COMMAND_PREFIX);
+
+ while (tag != (TAG_ENTRY *)NULL)
+ {
+ if ((tag->flags & IS_TOP))
+ {
+ int old_line_number = line_number;
+ char *old_input_filename = input_filename;
+
+ line_number = tag->line_no;
+ input_filename = tag->filename;
+ line_error ("Here is the %ctop node", COMMAND_PREFIX);
+ input_filename = old_input_filename;
+ line_number = old_line_number;
+ return;
+ }
+ tag = tag->next_ent;
+ }
+ }
+ else
+ {
+ top_node_seen = 1;
+
+ /* It is an error to use @top before you have used @node. */
+ if (!tag_table)
+ {
+ char *top_name;
+
+ get_rest_of_line (&top_name);
+ free (top_name);
+ line_error ("%ctop used before %cnode, defaulting to %s",
+ COMMAND_PREFIX, COMMAND_PREFIX, top_name);
+ execute_string ("@node Top, , (dir), (dir)\n@top %s\n", top_name);
+ return;
+ }
+
+ cm_unnumbered ();
+
+ /* The most recently defined node is the top node. */
+ tag_table->flags |= IS_TOP;
+
+ /* Now set the logical hierarchical level of the Top node. */
+ {
+ int orig_offset = input_text_offset;
+
+ input_text_offset = search_forward (node_search_string, orig_offset);
+
+ if (input_text_offset > 0)
+ {
+ int this_section;
+
+ /* We have encountered a non-top node, so mark that one exists. */
+ non_top_node_seen = 1;
+
+ /* Move to the end of this line, and find out what the
+ sectioning command is here. */
+ while (input_text[input_text_offset] != '\n')
+ input_text_offset++;
+
+ if (input_text_offset < size_of_input_text)
+ input_text_offset++;
+
+ this_section = what_section (input_text + input_text_offset);
+
+ /* If we found a sectioning command, then give the top section
+ a level of this section - 1. */
+ if (this_section != -1)
+ set_top_section_level (this_section - 1);
+ }
+ input_text_offset = orig_offset;
+ }
+ }
+}
+
+/* Organized by level commands. That is, "*" == chapter, "=" == section. */
+char *scoring_characters = "*=-.";
+
+void
+sectioning_underscore (command)
+ char *command;
+{
+ char character;
+ char *temp;
+ int level;
+
+ temp = (char *)xmalloc (2 + strlen (command));
+ temp[0] = COMMAND_PREFIX;
+ strcpy (&temp[1], command);
+ level = what_section (temp);
+ free (temp);
+ level -= 2;
+
+ if (level < 0)
+ level = 0;
+
+ character = scoring_characters[level];
+
+ insert_and_underscore (character);
+}
+
+/* The command still works, but prints a warning message in addition. */
+void
+cm_ideprecated (arg, start, end)
+ int arg, start, end;
+{
+ warning ("The command `%c%s' is obsolete; use `%c%s' instead",
+ COMMAND_PREFIX, command, COMMAND_PREFIX, command + 1);
+ sectioning_underscore (command + 1);
+}
+
+/* The remainder of the text on this line is a chapter heading. */
+void
+cm_chapter ()
+{
+ sectioning_underscore ("chapter");
+}
+
+/* The remainder of the text on this line is a section heading. */
+void
+cm_section ()
+{
+ sectioning_underscore ("section");
+}
+
+/* The remainder of the text on this line is a subsection heading. */
+void
+cm_subsection ()
+{
+ sectioning_underscore ("subsection");
+}
+
+/* The remainder of the text on this line is a subsubsection heading. */
+void
+cm_subsubsection ()
+{
+ sectioning_underscore ("subsubsection");
+}
+
+/* The remainder of the text on this line is an unnumbered heading. */
+void
+cm_unnumbered ()
+{
+ cm_chapter ();
+}
+
+/* The remainder of the text on this line is an unnumbered section heading. */
+void
+cm_unnumberedsec ()
+{
+ cm_section ();
+}
+
+/* The remainder of the text on this line is an unnumbered
+ subsection heading. */
+void
+cm_unnumberedsubsec ()
+{
+ cm_subsection ();
+}
+
+/* The remainder of the text on this line is an unnumbered
+ subsubsection heading. */
+void
+cm_unnumberedsubsubsec ()
+{
+ cm_subsubsection ();
+}
+
+/* The remainder of the text on this line is an appendix heading. */
+void
+cm_appendix ()
+{
+ cm_chapter ();
+}
+
+/* The remainder of the text on this line is an appendix section heading. */
+void
+cm_appendixsec ()
+{
+ cm_section ();
+}
+
+/* The remainder of the text on this line is an appendix subsection heading. */
+void
+cm_appendixsubsec ()
+{
+ cm_subsection ();
+}
+
+/* The remainder of the text on this line is an appendix
+ subsubsection heading. */
+void
+cm_appendixsubsubsec ()
+{
+ cm_subsubsection ();
+}
+
+/* Compatibility functions substitute for chapter, section, etc. */
+void
+cm_majorheading ()
+{
+ cm_chapheading ();
+}
+
+void
+cm_chapheading ()
+{
+ cm_chapter ();
+}
+
+void
+cm_heading ()
+{
+ cm_section ();
+}
+
+void
+cm_subheading ()
+{
+ cm_subsection ();
+}
+
+void
+cm_subsubheading ()
+{
+ cm_subsubsection ();
+}
+
+/* **************************************************************** */
+/* */
+/* Adding nodes, and making tags */
+/* */
+/* **************************************************************** */
+
+/* Start a new tag table. */
+void
+init_tag_table ()
+{
+ while (tag_table != (TAG_ENTRY *) NULL)
+ {
+ TAG_ENTRY *temp = tag_table;
+ free (temp->node);
+ free (temp->prev);
+ free (temp->next);
+ free (temp->up);
+ tag_table = tag_table->next_ent;
+ free (temp);
+ }
+}
+
+void
+write_tag_table ()
+{
+ write_tag_table_internal (0); /* Not indirect. */
+}
+
+void
+write_tag_table_indirect ()
+{
+ write_tag_table_internal (1);
+}
+
+/* Write out the contents of the existing tag table.
+ INDIRECT_P says how to format the output. */
+void
+write_tag_table_internal (indirect_p)
+ int indirect_p;
+{
+ TAG_ENTRY *node = tag_table;
+ int old_indent = no_indent;
+
+ no_indent = 1;
+ filling_enabled = 0;
+ must_start_paragraph = 0;
+ close_paragraph ();
+
+ if (!indirect_p)
+ {
+ no_indent = 1;
+ insert ('\n');
+ }
+
+ add_word_args ("\037\nTag Table:\n%s", indirect_p ? "(Indirect)\n" : "");
+
+ while (node != (TAG_ENTRY *) NULL)
+ {
+ execute_string ("Node: %s", node->node);
+ add_word_args ("\177%d\n", node->position);
+ node = node->next_ent;
+ }
+
+ add_word ("\037\nEnd Tag Table\n");
+ flush_output ();
+ no_indent = old_indent;
+}
+
+char *
+get_node_token ()
+{
+ char *string;
+
+ get_until_in_line (",", &string);
+
+ if (curchar () == ',')
+ input_text_offset++;
+
+ canon_white (string);
+
+ /* Force all versions of "top" to be "Top". */
+ normalize_node_name (string);
+
+ return (string);
+}
+
+/* Convert "top" and friends into "Top". */
+void
+normalize_node_name (string)
+ char *string;
+{
+ if (strcasecmp (string, "Top") == 0)
+ strcpy (string, "Top");
+}
+
+/* Look up NAME in the tag table, and return the associated
+ tag_entry. If the node is not in the table return NULL. */
+TAG_ENTRY *
+find_node (name)
+ char *name;
+{
+ TAG_ENTRY *tag = tag_table;
+
+ while (tag != (TAG_ENTRY *) NULL)
+ {
+ if (strcmp (tag->node, name) == 0)
+ return (tag);
+ tag = tag->next_ent;
+ }
+ return ((TAG_ENTRY *) NULL);
+}
+
+/* Remember NODE and associates. */
+void
+remember_node (node, prev, next, up, position, line_no, no_warn)
+ char *node, *prev, *next, *up;
+ int position, line_no, no_warn;
+{
+ /* Check for existence of this tag already. */
+ if (validating)
+ {
+ register TAG_ENTRY *tag = find_node (node);
+ if (tag)
+ {
+ line_error ("Node `%s' multiply defined (%d is first definition)",
+ node, tag->line_no);
+ return;
+ }
+ }
+
+ /* First, make this the current node. */
+ current_node = node;
+
+ /* Now add it to the list. */
+ {
+ TAG_ENTRY *new = (TAG_ENTRY *) xmalloc (sizeof (TAG_ENTRY));
+ new->node = node;
+ new->prev = prev;
+ new->next = next;
+ new->up = up;
+ new->position = position;
+ new->line_no = line_no;
+ new->filename = node_filename;
+ new->touched = 0; /* not yet referenced. */
+ new->flags = 0;
+ if (no_warn)
+ new->flags |= NO_WARN;
+ new->next_ent = tag_table;
+ tag_table = new;
+ }
+}
+
+/* The order is: nodename, nextnode, prevnode, upnode.
+ If all of the NEXT, PREV, and UP fields are empty, they are defaulted.
+ You must follow a node command which has those fields defaulted
+ with a sectioning command (e.g. @chapter) giving the "level" of that node.
+ It is an error not to do so.
+ The defaults come from the menu in this node's parent. */
+void
+cm_node ()
+{
+ char *node, *prev, *next, *up;
+ int new_node_pos, defaulting, this_section, no_warn = 0;
+ extern int already_outputting_pending_notes;
+
+ if (strcmp (command, "nwnode") == 0)
+ no_warn = 1;
+
+ /* Get rid of unmatched brace arguments from previous commands. */
+ discard_braces ();
+
+ /* There also might be insertions left lying around that haven't been
+ ended yet. Do that also. */
+ discard_insertions ();
+
+ if (!already_outputting_pending_notes)
+ {
+ close_paragraph ();
+ output_pending_notes ();
+ free_pending_notes ();
+ }
+
+ filling_enabled = indented_fill = 0;
+ new_node_pos = output_position;
+ current_footnote_number = 1;
+
+#if defined (HAVE_MACROS)
+ if (macro_expansion_output_stream)
+ append_to_expansion_output (input_text_offset + 1);
+#endif /* HAVE_MACROS */
+
+ node = get_node_token ();
+ next = get_node_token ();
+ prev = get_node_token ();
+ up = get_node_token ();
+
+#if defined (HAVE_MACROS)
+ if (macro_expansion_output_stream)
+ remember_itext (input_text, input_text_offset);
+#endif /* HAVE_MACROS */
+
+ no_indent = 1;
+ if (!no_headers)
+ {
+ add_word_args ("\037\nFile: %s, Node: ", pretty_output_filename);
+
+#if defined (HAVE_MACROS)
+ if (macro_expansion_output_stream)
+ me_execute_string (node);
+ else
+#endif /* HAVE_MACROS */
+ execute_string ("%s", node);
+ filling_enabled = indented_fill = 0;
+ }
+
+ /* Check for defaulting of this node's next, prev, and up fields. */
+ defaulting = ((strlen (next) == 0) &&
+ (strlen (prev) == 0) &&
+ (strlen (up) == 0));
+
+ this_section = what_section (input_text + input_text_offset);
+
+ /* If we are defaulting, then look at the immediately following
+ sectioning command (error if none) to determine the node's
+ level. Find the node that contains the menu mentioning this node
+ that is one level up (error if not found). That node is the "Up"
+ of this node. Default the "Next" and "Prev" from the menu. */
+ if (defaulting)
+ {
+ NODE_REF *last_ref = (NODE_REF *)NULL;
+ NODE_REF *ref = node_references;
+
+ if ((this_section < 0) && (strcmp (node, "Top") != 0))
+ {
+ char *polite_section_name = "top";
+ int i;
+
+ for (i = 0; section_alist[i].name; i++)
+ if (section_alist[i].level == current_section + 1)
+ {
+ polite_section_name = section_alist[i].name;
+ break;
+ }
+
+ line_error
+ ("Node `%s' requires a sectioning command (e.g. %c%s)",
+ node, COMMAND_PREFIX, polite_section_name);
+ }
+ else
+ {
+ if (strcmp (node, "Top") == 0)
+ {
+ /* Default the NEXT pointer to be the first menu item in
+ this node, if there is a menu in this node. We have to
+ try very hard to find the menu, as it may be obscured
+ by execution_strings which are on the filestack. For
+ every member of the filestack which has a FILENAME
+ member which is identical to the current INPUT_FILENAME,
+ search forward from that offset. */
+ int saved_input_text_offset = input_text_offset;
+ int saved_size_of_input_text = size_of_input_text;
+ char *saved_input_text = input_text;
+ FSTACK *next_file = filestack;
+
+ int orig_offset, orig_size;
+ char *glean_node_from_menu ();
+
+ /* No matter what, make this file point back at `(dir)'. */
+ free (up); up = strdup ("(dir)");
+
+ while (1)
+ {
+ orig_offset = input_text_offset;
+ orig_size =
+ search_forward (node_search_string, orig_offset);
+
+ if (orig_size < 0)
+ orig_size = size_of_input_text;
+
+ input_text_offset =
+ search_forward (menu_search_string, orig_offset);
+
+ if (input_text_offset > -1)
+ {
+ char *nodename_from_menu = (char *)NULL;
+
+ input_text_offset =
+ search_forward ("\n* ", input_text_offset);
+
+ if (input_text_offset != -1)
+ nodename_from_menu = glean_node_from_menu (0);
+
+ if (nodename_from_menu)
+ {
+ free (next); next = nodename_from_menu;
+ break;
+ }
+ }
+
+ /* We got here, so it hasn't been found yet. Try
+ the next file on the filestack if there is one. */
+ if (next_file &&
+ (strcmp (next_file->filename, input_filename) == 0))
+ {
+ input_text = next_file->text;
+ input_text_offset = next_file->offset;
+ size_of_input_text = next_file->size;
+ next_file = next_file->next;
+ }
+ else
+ {
+ /* No more input files to check. */
+ break;
+ }
+ }
+
+ input_text = saved_input_text;
+ input_text_offset = saved_input_text_offset;
+ size_of_input_text = saved_size_of_input_text;
+ }
+ }
+
+ /* Fix the level of the menu references in the Top node, iff it
+ was declared with @top, and no subsequent reference was found. */
+ if (top_node_seen && !non_top_node_seen)
+ {
+ /* Then this is the first non-@top node seen. */
+ int level;
+
+ level = set_top_section_level (this_section - 1);
+ non_top_node_seen = 1;
+
+ while (ref)
+ {
+ if (ref->section == level)
+ ref->section = this_section - 1;
+ ref = ref->next;
+ }
+
+ ref = node_references;
+ }
+
+ while (ref)
+ {
+ if (ref->section == (this_section - 1) &&
+ ref->type == menu_reference &&
+ strcmp (ref->node, node) == 0)
+ {
+ char *containing_node = ref->containing_node;
+
+ free (up);
+ up = strdup (containing_node);
+
+ if (last_ref &&
+ last_ref->type == menu_reference &&
+ (strcmp (last_ref->containing_node,
+ containing_node) == 0))
+ {
+ free (next);
+ next = strdup (last_ref->node);
+ }
+
+ while ((ref->section == this_section - 1) &&
+ (ref->next) &&
+ (ref->next->type != menu_reference))
+ ref = ref->next;
+
+ if (ref->next && ref->type == menu_reference &&
+ (strcmp (ref->next->containing_node,
+ containing_node) == 0))
+ {
+ free (prev);
+ prev = strdup (ref->next->node);
+ }
+ else if (!ref->next &&
+ strcasecmp (ref->containing_node, "Top") == 0)
+ {
+ free (prev);
+ prev = strdup (ref->containing_node);
+ }
+ break;
+ }
+ last_ref = ref;
+ ref = ref->next;
+ }
+ }
+
+#if defined (HAVE_MACROS)
+ /* Insert the correct args if we are expanding macros, and the node's
+ pointers weren't defaulted. */
+ if (macro_expansion_output_stream && !defaulting)
+ {
+ char *temp;
+ int op_orig = output_paragraph_offset;
+
+ temp = (char *)xmalloc (3 + strlen (next));
+ sprintf (temp, ", %s", next);
+ me_execute_string (temp);
+ free (temp);
+
+ temp = (char *)xmalloc (3 + strlen (prev));
+ sprintf (temp, ", %s", prev);
+ me_execute_string (temp);
+ free (temp);
+
+ temp = (char *)xmalloc (4 + strlen (up));
+ sprintf (temp, ", %s", up);
+ me_execute_string (temp);
+ free (temp);
+
+ output_paragraph_offset = op_orig;
+ }
+#endif /* HAVE_MACROS */
+
+ if (!no_headers)
+ {
+#if defined (HAVE_MACROS)
+ if (macro_expansion_output_stream)
+ me_inhibit_expansion++;
+#endif /* HAVE_MACROS */
+
+ if (*next)
+ {
+ execute_string (", Next: %s", next);
+ filling_enabled = indented_fill = 0;
+ }
+
+ if (*prev)
+ {
+ execute_string (", Prev: %s", prev);
+ filling_enabled = indented_fill = 0;
+ }
+
+ if (*up)
+ {
+ execute_string (", Up: %s", up);
+ filling_enabled = indented_fill = 0;
+ }
+#if defined (HAVE_MACROS)
+ if (macro_expansion_output_stream)
+ me_inhibit_expansion--;
+#endif /* HAVE_MACROS */
+ }
+
+ close_paragraph ();
+ no_indent = 0;
+
+ if (!*node)
+ {
+ line_error ("No node name specified for `%c%s' command",
+ COMMAND_PREFIX, command);
+ free (node);
+ free (next);
+ free (prev);
+ free (up);
+ }
+ else
+ {
+ if (!*next) { free (next); next = (char *)NULL; }
+ if (!*prev) { free (prev); prev = (char *)NULL; }
+ if (!*up) { free (up); up = (char *)NULL; }
+ remember_node (node, prev, next, up, new_node_pos, line_number, no_warn);
+ }
+
+ /* Change the section only if there was a sectioning command. */
+ if (this_section >= 0)
+ current_section = this_section;
+
+ filling_enabled = 1;
+}
+
+/* Validation of an info file.
+ Scan through the list of tag entries touching the Prev, Next, and Up
+ elements of each. It is an error not to be able to touch one of them,
+ except in the case of external node references, such as "(DIR)".
+
+ If the Prev is different from the Up,
+ then the Prev node must have a Next pointing at this node.
+
+ Every node except Top must have an Up.
+ The Up node must contain some sort of reference, other than a Next,
+ to this node.
+
+ If the Next is different from the Next of the Up,
+ then the Next node must have a Prev pointing at this node. */
+void
+validate_file (tag_table)
+ TAG_ENTRY *tag_table;
+{
+ char *old_input_filename = input_filename;
+ TAG_ENTRY *tags = tag_table;
+
+ while (tags != (TAG_ENTRY *) NULL)
+ {
+ register TAG_ENTRY *temp_tag;
+
+ input_filename = tags->filename;
+ line_number = tags->line_no;
+
+ /* If this is a "no warn" node, don't validate it in any way. */
+ if (tags->flags & NO_WARN)
+ {
+ tags = tags->next_ent;
+ continue;
+ }
+
+ /* If this node has a Next, then make sure that the Next exists. */
+ if (tags->next)
+ {
+ validate (tags->next, tags->line_no, "Next");
+
+ /* If the Next node exists, and there is no Up, then make
+ sure that the Prev of the Next points back. */
+ if (temp_tag = find_node (tags->next))
+ {
+ char *prev;
+
+ if (temp_tag->flags & NO_WARN)
+ {
+ /* Do nothing if we aren't supposed to issue warnings
+ about this node. */
+ }
+ else
+ {
+ prev = temp_tag->prev;
+ if (!prev || (strcmp (prev, tags->node) != 0))
+ {
+ line_error ("Node `%s''s Next field not pointed back to",
+ tags->node);
+ line_number = temp_tag->line_no;
+ input_filename = temp_tag->filename;
+ line_error
+ ("This node (`%s') is the one with the bad `Prev'",
+ temp_tag->node);
+ input_filename = tags->filename;
+ line_number = tags->line_no;
+ temp_tag->flags |= PREV_ERROR;
+ }
+ }
+ }
+ }
+
+ /* Validate the Prev field if there is one, and we haven't already
+ complained about it in some way. You don't have to have a Prev
+ field at this stage. */
+ if (!(tags->flags & PREV_ERROR) && tags->prev)
+ {
+ int valid = validate (tags->prev, tags->line_no, "Prev");
+
+ if (!valid)
+ tags->flags |= PREV_ERROR;
+ else
+ {
+ /* If the Prev field is not the same as the Up field,
+ then the node pointed to by the Prev field must have
+ a Next field which points to this node. */
+ if (tags->up && (strcmp (tags->prev, tags->up) != 0))
+ {
+ temp_tag = find_node (tags->prev);
+
+ /* If we aren't supposed to issue warnings about the
+ target node, do nothing. */
+ if (!temp_tag || (temp_tag->flags & NO_WARN))
+ {
+ /* Do nothing. */
+ }
+ else
+ {
+ if (!temp_tag->next ||
+ (strcmp (temp_tag->next, tags->node) != 0))
+ {
+ line_error
+ ("Node `%s''s Prev field not pointed back to",
+ tags->node);
+ line_number = temp_tag->line_no;
+ input_filename = temp_tag->filename;
+ line_error
+ ("This node (`%s') is the one with the bad `Next'",
+ temp_tag->node);
+ input_filename = tags->filename;
+ line_number = tags->line_no;
+ temp_tag->flags |= NEXT_ERROR;
+ }
+ }
+ }
+ }
+ }
+
+ if (!tags->up && (strcasecmp (tags->node, "Top") != 0))
+ line_error ("Node `%s' is missing an \"Up\" field", tags->node);
+ else if (tags->up)
+ {
+ int valid = validate (tags->up, tags->line_no, "Up");
+
+ /* If node X has Up: Y, then warn if Y fails to have a menu item
+ or note pointing at X, if Y isn't of the form "(Y)". */
+ if (valid && *tags->up != '(')
+ {
+ NODE_REF *nref, *tref, *list;
+ NODE_REF *find_node_reference ();
+
+ tref = (NODE_REF *) NULL;
+ list = node_references;
+
+ for (;;)
+ {
+ if (!(nref = find_node_reference (tags->node, list)))
+ break;
+
+ if (strcmp (nref->containing_node, tags->up) == 0)
+ {
+ if (nref->type != menu_reference)
+ {
+ tref = nref;
+ list = nref->next;
+ }
+ else
+ break;
+ }
+ list = nref->next;
+ }
+
+ if (!nref)
+ {
+ temp_tag = find_node (tags->up);
+ line_number = temp_tag->line_no;
+ input_filename = temp_tag->filename;
+ if (!tref)
+ line_error (
+"`%s' has an Up field of `%s', but `%s' has no menu item for `%s'",
+ tags->node, tags->up, tags->up, tags->node);
+ line_number = tags->line_no;
+ input_filename = tags->filename;
+ }
+ }
+ }
+ tags = tags->next_ent;
+ }
+
+ validate_other_references (node_references);
+ /* We have told the user about the references which didn't exist.
+ Now tell him about the nodes which aren't referenced. */
+
+ tags = tag_table;
+ while (tags != (TAG_ENTRY *) NULL)
+ {
+ /* If this node is a "no warn" node, do nothing. */
+ if (tags->flags & NO_WARN)
+ {
+ tags = tags->next_ent;
+ continue;
+ }
+
+ /* Special hack. If the node in question appears to have
+ been referenced more than REFERENCE_WARNING_LIMIT times,
+ give a warning. */
+ if (tags->touched > reference_warning_limit)
+ {
+ input_filename = tags->filename;
+ line_number = tags->line_no;
+ warning ("Node `%s' has been referenced %d times",
+ tags->node, tags->touched);
+ }
+
+ if (tags->touched == 0)
+ {
+ input_filename = tags->filename;
+ line_number = tags->line_no;
+
+ /* Notice that the node "Top" is special, and doesn't have to
+ be referenced. */
+ if (strcasecmp (tags->node, "Top") != 0)
+ warning ("Unreferenced node `%s'", tags->node);
+ }
+ tags = tags->next_ent;
+ }
+ input_filename = old_input_filename;
+}
+
+/* Return 1 if tag correctly validated, or 0 if not. */
+int
+validate (tag, line, label)
+ char *tag;
+ int line;
+ char *label;
+{
+ TAG_ENTRY *result;
+
+ /* If there isn't a tag to verify, or if the tag is in another file,
+ then it must be okay. */
+ if (!tag || !*tag || *tag == '(')
+ return (1);
+
+ /* Otherwise, the tag must exist. */
+ result = find_node (tag);
+
+ if (!result)
+ {
+ line_number = line;
+ line_error (
+"Validation error. `%s' field points to node `%s', which doesn't exist",
+ label, tag);
+ return (0);
+ }
+ result->touched++;
+ return (1);
+}
+
+/* Split large output files into a series of smaller files. Each file
+ is pointed to in the tag table, which then gets written out as the
+ original file. The new files have the same name as the original file
+ with a "-num" attached. SIZE is the largest number of bytes to allow
+ in any single split file. */
+void
+split_file (filename, size)
+ char *filename;
+ int size;
+{
+ char *root_filename, *root_pathname;
+ char *the_file, *filename_part ();
+ struct stat fileinfo;
+ long file_size;
+ char *the_header;
+ int header_size;
+
+ /* Can only do this to files with tag tables. */
+ if (!tag_table)
+ return;
+
+ if (size == 0)
+ size = DEFAULT_SPLIT_SIZE;
+
+ if ((stat (filename, &fileinfo) != 0) ||
+ (((long) fileinfo.st_size) < SPLIT_SIZE_THRESHOLD))
+ return;
+ file_size = (long) fileinfo.st_size;
+
+ the_file = find_and_load (filename);
+ if (!the_file)
+ return;
+
+ root_filename = filename_part (filename);
+ root_pathname = pathname_part (filename);
+
+ if (!root_pathname)
+ root_pathname = strdup ("");
+
+ /* Start splitting the file. Walk along the tag table
+ outputting sections of the file. When we have written
+ all of the nodes in the tag table, make the top-level
+ pointer file, which contains indirect pointers and
+ tags for the nodes. */
+ {
+ int which_file = 1;
+ TAG_ENTRY *tags = tag_table;
+ char *indirect_info = (char *)NULL;
+
+ /* Remember the `header' of this file. The first tag in the file is
+ the bottom of the header; the top of the file is the start. */
+ the_header = (char *)xmalloc (1 + (header_size = tags->position));
+ memcpy (the_header, the_file, header_size);
+
+ while (tags)
+ {
+ int file_top, file_bot, limit;
+
+ /* Have to include the Control-_. */
+ file_top = file_bot = tags->position;
+ limit = file_top + size;
+
+ /* If the rest of this file is only one node, then
+ that is the entire subfile. */
+ if (!tags->next_ent)
+ {
+ int i = tags->position + 1;
+ char last_char = the_file[i];
+
+ while (i < file_size)
+ {
+ if ((the_file[i] == '\037') &&
+ ((last_char == '\n') ||
+ (last_char == '\014')))
+ break;
+ else
+ last_char = the_file[i];
+ i++;
+ }
+ file_bot = i;
+ tags = tags->next_ent;
+ goto write_region;
+ }
+
+ /* Otherwise, find the largest number of nodes that can fit in
+ this subfile. */
+ for (; tags; tags = tags->next_ent)
+ {
+ if (!tags->next_ent)
+ {
+ /* This entry is the last node. Search forward for the end
+ of this node, and that is the end of this file. */
+ int i = tags->position + 1;
+ char last_char = the_file[i];
+
+ while (i < file_size)
+ {
+ if ((the_file[i] == '\037') &&
+ ((last_char == '\n') ||
+ (last_char == '\014')))
+ break;
+ else
+ last_char = the_file[i];
+ i++;
+ }
+ file_bot = i;
+
+ if (file_bot < limit)
+ {
+ tags = tags->next_ent;
+ goto write_region;
+ }
+ else
+ {
+ /* Here we want to write out everything before the last
+ node, and then write the last node out in a file
+ by itself. */
+ file_bot = tags->position;
+ goto write_region;
+ }
+ }
+
+ if (tags->next_ent->position > limit)
+ {
+ if (tags->position == file_top)
+ tags = tags->next_ent;
+
+ file_bot = tags->position;
+
+ write_region:
+ {
+ int fd;
+ char *split_filename;
+
+ split_filename = (char *) xmalloc
+ (10 + strlen (root_pathname) + strlen (root_filename));
+ sprintf
+ (split_filename,
+ "%s%s-%d", root_pathname, root_filename, which_file);
+
+ fd = open
+ (split_filename, O_WRONLY | O_TRUNC | O_CREAT, 0666);
+
+ if ((fd < 0) ||
+ (write (fd, the_header, header_size) != header_size) ||
+ (write (fd, the_file + file_top, file_bot - file_top)
+ != (file_bot - file_top)) ||
+ ((close (fd)) < 0))
+ {
+ perror (split_filename);
+ if (fd != -1)
+ close (fd);
+ exit (FATAL);
+ }
+
+ if (!indirect_info)
+ {
+ indirect_info = the_file + file_top;
+ sprintf (indirect_info, "\037\nIndirect:\n");
+ indirect_info += strlen (indirect_info);
+ }
+
+ sprintf (indirect_info, "%s-%d: %d\n",
+ root_filename, which_file, file_top);
+
+ free (split_filename);
+ indirect_info += strlen (indirect_info);
+ which_file++;
+ break;
+ }
+ }
+ }
+ }
+
+ /* We have sucessfully created the subfiles. Now write out the
+ original again. We must use `output_stream', or
+ write_tag_table_indirect () won't know where to place the output. */
+ output_stream = fopen (filename, "w");
+ if (!output_stream)
+ {
+ perror (filename);
+ exit (FATAL);
+ }
+
+ {
+ int distance = indirect_info - the_file;
+ fwrite (the_file, 1, distance, output_stream);
+
+ /* Inhibit newlines. */
+ paragraph_is_open = 0;
+
+ write_tag_table_indirect ();
+ fclose (output_stream);
+ free (the_header);
+ free (the_file);
+ return;
+ }
+ }
+}
+
+/* Some menu hacking. This is used to remember menu references while
+ reading the input file. After the output file has been written, if
+ validation is on, then we use the contents of NODE_REFERENCES as a
+ list of nodes to validate. */
+char *
+reftype_type_string (type)
+ enum reftype type;
+{
+ switch (type)
+ {
+ case menu_reference:
+ return ("Menu");
+ case followed_reference:
+ return ("Followed-Reference");
+ default:
+ return ("Internal-bad-reference-type");
+ }
+}
+
+/* Remember this node name for later validation use. */
+void
+remember_node_reference (node, line, type)
+ char *node;
+ int line;
+ enum reftype type;
+{
+ NODE_REF *temp = (NODE_REF *) xmalloc (sizeof (NODE_REF));
+
+ temp->next = node_references;
+ temp->node = strdup (node);
+ temp->line_no = line;
+ temp->section = current_section;
+ temp->type = type;
+ temp->containing_node = strdup (current_node ? current_node : "");
+ temp->filename = node_filename;
+
+ node_references = temp;
+}
+
+void
+validate_other_references (ref_list)
+ register NODE_REF *ref_list;
+{
+ char *old_input_filename = input_filename;
+
+ while (ref_list != (NODE_REF *) NULL)
+ {
+ input_filename = ref_list->filename;
+ validate (ref_list->node, ref_list->line_no,
+ reftype_type_string (ref_list->type));
+ ref_list = ref_list->next;
+ }
+ input_filename = old_input_filename;
+}
+
+/* Find NODE in REF_LIST. */
+NODE_REF *
+find_node_reference (node, ref_list)
+ char *node;
+ register NODE_REF *ref_list;
+{
+ while (ref_list)
+ {
+ if (strcmp (node, ref_list->node) == 0)
+ break;
+ ref_list = ref_list->next;
+ }
+ return (ref_list);
+}
+
+void
+free_node_references ()
+{
+ register NODE_REF *list, *temp;
+
+ list = node_references;
+
+ while (list)
+ {
+ temp = list;
+ free (list->node);
+ free (list->containing_node);
+ list = list->next;
+ free (temp);
+ }
+ node_references = (NODE_REF *) NULL;
+}
+
+ /* This function gets called at the start of every line while inside of
+ a menu. It checks to see if the line starts with "* ", and if so,
+ remembers the node reference that this menu refers to.
+ input_text_offset is at the \n just before the line start. */
+#define menu_starter "* "
+char *
+glean_node_from_menu (remember_reference)
+ int remember_reference;
+{
+ int i, orig_offset = input_text_offset;
+ char *nodename;
+
+ if (strncmp (&input_text[input_text_offset + 1],
+ menu_starter,
+ strlen (menu_starter)) != 0)
+ return ((char *)NULL);
+ else
+ input_text_offset += strlen (menu_starter) + 1;
+
+ get_until_in_line (":", &nodename);
+ if (curchar () == ':')
+ input_text_offset++;
+ canon_white (nodename);
+
+ if (curchar () == ':')
+ goto save_node;
+
+ free (nodename);
+ get_rest_of_line (&nodename);
+
+ /* Special hack: If the nodename follows the menu item name,
+ then we have to read the rest of the line in order to find
+ out what the nodename is. But we still have to read the
+ line later, in order to process any formatting commands that
+ might be present. So un-count the carriage return that has just
+ been counted. */
+ line_number--;
+
+ isolate_nodename (nodename);
+
+save_node:
+ input_text_offset = orig_offset;
+ normalize_node_name (nodename);
+ i = strlen (nodename);
+ if (i && nodename[i - 1] == ':')
+ nodename[i - 1] = '\0';
+
+ if (remember_reference)
+ {
+ remember_node_reference (nodename, line_number, menu_reference);
+ free (nodename);
+ return ((char *)NULL);
+ }
+ else
+ return (nodename);
+}
+
+static void
+isolate_nodename (nodename)
+ char *nodename;
+{
+ register int i, c;
+ int paren_seen, paren;
+
+ if (!nodename)
+ return;
+
+ canon_white (nodename);
+ paren_seen = paren = i = 0;
+
+ if (*nodename == '.' || !*nodename)
+ {
+ *nodename = '\0';
+ return;
+ }
+
+ if (*nodename == '(')
+ {
+ paren++;
+ paren_seen++;
+ i++;
+ }
+
+ for (; c = nodename[i]; i++)
+ {
+ if (paren)
+ {
+ if (c == '(')
+ paren++;
+ else if (c == ')')
+ paren--;
+
+ continue;
+ }
+
+ /* If the character following the close paren is a space, then this
+ node has no more characters associated with it. */
+ if (c == '\t' ||
+ c == '\n' ||
+ c == ',' ||
+ ((paren_seen && nodename[i - 1] == ')') &&
+ (c == ' ' || c == '.')) ||
+ (c == '.' &&
+ ((!nodename[i + 1] ||
+ (cr_or_whitespace (nodename[i + 1])) ||
+ (nodename[i + 1] == ')')))))
+ break;
+ }
+ nodename[i] = '\0';
+}
+
+void
+cm_menu ()
+{
+ if (current_node == (char *)NULL)
+ {
+ warning ("%cmenu seen before a node has been defined", COMMAND_PREFIX);
+ warning ("Creating `TOP' node.");
+ execute_string ("@node Top");
+ }
+ begin_insertion (menu);
+}
+
+void
+cm_detailmenu ()
+{
+ if (current_node == (char *)NULL)
+ {
+ warning ("%cmenu seen before a node has been defined", COMMAND_PREFIX);
+ warning ("Creating `TOP' node.");
+ execute_string ("@node Top");
+ }
+ begin_insertion (detailmenu);
+}
+
+/* **************************************************************** */
+/* */
+/* Cross Reference Hacking */
+/* */
+/* **************************************************************** */
+
+char *
+get_xref_token ()
+{
+ char *string;
+
+ get_until_in_braces (",", &string);
+ if (curchar () == ',')
+ input_text_offset++;
+ fix_whitespace (string);
+ return (string);
+}
+
+int px_ref_flag = 0; /* Controls initial output string. */
+
+/* Make a cross reference. */
+void
+cm_xref (arg)
+{
+ if (arg == START)
+ {
+ char *arg1, *arg2, *arg3, *arg4, *arg5;
+
+ arg1 = get_xref_token ();
+ arg2 = get_xref_token ();
+ arg3 = get_xref_token ();
+ arg4 = get_xref_token ();
+ arg5 = get_xref_token ();
+
+ add_word_args ("%s", px_ref_flag ? "*note " : "*Note ");
+
+ if (*arg5 || *arg4)
+ {
+ char *node_name;
+
+ if (!*arg2)
+ {
+ if (*arg3)
+ node_name = arg3;
+ else
+ node_name = arg1;
+ }
+ else
+ node_name = arg2;
+
+ execute_string ("%s: (%s)%s", node_name, arg4, arg1);
+ /* Free all of the arguments found. */
+ if (arg1) free (arg1);
+ if (arg2) free (arg2);
+ if (arg3) free (arg3);
+ if (arg4) free (arg4);
+ if (arg5) free (arg5);
+ return;
+ }
+ else
+ remember_node_reference (arg1, line_number, followed_reference);
+
+ if (*arg3)
+ {
+ if (!*arg2)
+ execute_string ("%s: %s", arg3, arg1);
+ else
+ execute_string ("%s: %s", arg2, arg1);
+ }
+ else
+ {
+ if (*arg2)
+ execute_string ("%s: %s", arg2, arg1);
+ else
+ execute_string ("%s::", arg1);
+ }
+
+ /* Free all of the arguments found. */
+ if (arg1) free (arg1);
+ if (arg2) free (arg2);
+ if (arg3) free (arg3);
+ if (arg4) free (arg4);
+ if (arg5) free (arg5);
+ }
+ else
+ {
+ /* Check to make sure that the next non-whitespace character is either
+ a period or a comma. input_text_offset is pointing at the "}" which
+ ended the xref or pxref command. */
+ int temp = input_text_offset + 1;
+
+ if (output_paragraph[output_paragraph_offset - 2] == ':' &&
+ output_paragraph[output_paragraph_offset - 1] == ':')
+ return;
+ while (temp < size_of_input_text)
+ {
+ if (cr_or_whitespace (input_text[temp]))
+ temp++;
+ else
+ {
+ if (input_text[temp] == '.' ||
+ input_text[temp] == ',' ||
+ input_text[temp] == '\t')
+ return;
+ else
+ {
+ line_error (
+ "Cross-reference must be terminated with a period or a comma");
+ return;
+ }
+ }
+ }
+ }
+}
+
+void
+cm_pxref (arg)
+ int arg;
+{
+ if (arg == START)
+ {
+ px_ref_flag++;
+ cm_xref (arg);
+ px_ref_flag--;
+ }
+ else
+ add_char ('.');
+}
+
+void
+cm_inforef (arg)
+ int arg;
+{
+ if (arg == START)
+ {
+ char *node, *pname, *file;
+
+ node = get_xref_token ();
+ pname = get_xref_token ();
+ file = get_xref_token ();
+
+ execute_string ("*note %s: (%s)%s", pname, file, node);
+ }
+}
+
+/* **************************************************************** */
+/* */
+/* Insertion Command Stubs */
+/* */
+/* **************************************************************** */
+
+void
+cm_quotation ()
+{
+ begin_insertion (quotation);
+}
+
+void
+cm_example ()
+{
+ begin_insertion (example);
+}
+
+void
+cm_smallexample ()
+{
+ begin_insertion (smallexample);
+}
+
+void
+cm_lisp ()
+{
+ begin_insertion (lisp);
+}
+
+void
+cm_smalllisp ()
+{
+ begin_insertion (smalllisp);
+}
+
+/* @cartouche/@end cartouche draws box with rounded corners in
+ TeX output. Right now, just a NOP insertion. */
+void
+cm_cartouche ()
+{
+ begin_insertion (cartouche);
+}
+
+void
+cm_format ()
+{
+ begin_insertion (format);
+}
+
+void
+cm_display ()
+{
+ begin_insertion (display);
+}
+
+void
+cm_direntry ()
+{
+ if (no_headers)
+ command_name_condition ();
+ else
+ begin_insertion (direntry);
+}
+
+void
+cm_itemize ()
+{
+ begin_insertion (itemize);
+}
+
+void
+cm_enumerate ()
+{
+ do_enumeration (enumerate, "1");
+}
+
+/* Start an enumeration insertion of type TYPE. If the user supplied
+ no argument on the line, then use DEFAULT_STRING as the initial string. */
+void
+do_enumeration (type, default_string)
+ int type;
+ char *default_string;
+{
+ get_until_in_line (".", &enumeration_arg);
+ canon_white (enumeration_arg);
+
+ if (!*enumeration_arg)
+ {
+ free (enumeration_arg);
+ enumeration_arg = strdup (default_string);
+ }
+
+ if (!isdigit (*enumeration_arg) && !isletter (*enumeration_arg))
+ {
+ warning ("%s requires a letter or a digit", insertion_type_pname (type));
+
+ switch (type)
+ {
+ case enumerate:
+ default_string = "1";
+ break;
+ }
+ enumeration_arg = strdup (default_string);
+ }
+ begin_insertion (type);
+}
+
+void
+cm_table ()
+{
+ begin_insertion (table);
+}
+
+void
+cm_multitable ()
+{
+ begin_insertion (multitable); /* @@ */
+}
+
+void
+cm_ftable ()
+{
+ begin_insertion (ftable);
+}
+
+void
+cm_vtable ()
+{
+ begin_insertion (vtable);
+}
+
+void
+cm_group ()
+{
+ begin_insertion (group);
+}
+
+void
+cm_ifinfo ()
+{
+ begin_insertion (ifinfo);
+}
+
+/* Begin an insertion where the lines are not filled or indented. */
+void
+cm_flushleft ()
+{
+ begin_insertion (flushleft);
+}
+
+/* Begin an insertion where the lines are not filled, and each line is
+ forced to the right-hand side of the page. */
+void
+cm_flushright ()
+{
+ begin_insertion (flushright);
+}
+
+/* **************************************************************** */
+/* */
+/* Conditional Handling */
+/* */
+/* **************************************************************** */
+
+/* A structure which contains `defined' variables. */
+typedef struct defines {
+ struct defines *next;
+ char *name;
+ char *value;
+} DEFINE;
+
+/* The linked list of `set' defines. */
+DEFINE *defines = (DEFINE *)NULL;
+
+/* Add NAME to the list of `set' defines. */
+void
+set (name, value)
+ char *name;
+ char *value;
+{
+ DEFINE *temp;
+
+ for (temp = defines; temp; temp = temp->next)
+ if (strcmp (name, temp->name) == 0)
+ {
+ free (temp->value);
+ temp->value = strdup (value);
+ return;
+ }
+
+ temp = (DEFINE *)xmalloc (sizeof (DEFINE));
+ temp->next = defines;
+ temp->name = strdup (name);
+ temp->value = strdup (value);
+ defines = temp;
+}
+
+/* Remove NAME from the list of `set' defines. */
+void
+clear (name)
+ char *name;
+{
+ register DEFINE *temp, *last;
+
+ last = (DEFINE *)NULL;
+ temp = defines;
+
+ while (temp)
+ {
+ if (strcmp (temp->name, name) == 0)
+ {
+ if (last)
+ last->next = temp->next;
+ else
+ defines = temp->next;
+
+ free (temp->name);
+ free (temp->value);
+ free (temp);
+ break;
+ }
+ last = temp;
+ temp = temp->next;
+ }
+}
+
+/* Return the value of NAME. The return value is NULL if NAME is unset. */
+char *
+set_p (name)
+ char *name;
+{
+ register DEFINE *temp;
+
+ for (temp = defines; temp; temp = temp->next)
+ if (strcmp (temp->name, name) == 0)
+ return (temp->value);
+
+ return ((char *)NULL);
+}
+
+/* Conditionally parse based on the current command name. */
+void
+command_name_condition ()
+{
+ char *discarder;
+
+ discarder = (char *)xmalloc (8 + strlen (command));
+
+ sprintf (discarder, "\n%cend %s", COMMAND_PREFIX, command);
+ discard_until (discarder);
+ discard_until ("\n");
+
+ free (discarder);
+}
+
+/* Create a variable whose name appears as the first word on this line. */
+void
+cm_set ()
+{
+ handle_variable (SET);
+}
+
+/* Remove a variable whose name appears as the first word on this line. */
+void
+cm_clear ()
+{
+ handle_variable (CLEAR);
+}
+
+void
+cm_ifset ()
+{
+ handle_variable (IFSET);
+}
+
+void
+cm_ifclear ()
+{
+ handle_variable (IFCLEAR);
+}
+
+/* This command takes braces, but we parse the contents specially, so we
+ don't use the standard brace popping code.
+
+ The syntax @ifeq{arg1, arg2, texinfo-commands} performs texinfo-commands
+ if ARG1 and ARG2 caselessly string compare to the same string, otherwise,
+ it produces no output. */
+void
+cm_ifeq ()
+{
+ register int i;
+ char **arglist;
+
+ arglist = get_brace_args (0);
+
+ if (arglist)
+ {
+ if (array_len (arglist) > 1)
+ {
+ if ((strcasecmp (arglist[0], arglist[1]) == 0) &&
+ (arglist[2] != (char *)NULL))
+ execute_string ("%s\n", arglist[2]);
+ }
+
+ free_array (arglist);
+ }
+}
+
+void
+cm_value (arg, start_pos, end_pos)
+ int arg, start_pos, end_pos;
+{
+ if (arg == END)
+ {
+ char *name, *value;
+ name = (char *)&output_paragraph[start_pos];
+ output_paragraph[end_pos] = '\0';
+ name = strdup (name);
+ value = set_p (name);
+ output_column -= end_pos - start_pos;
+ output_paragraph_offset = start_pos;
+
+ if (value)
+ execute_string ("%s", value);
+ else
+ add_word_args ("{No Value For \"%s\"}", name);
+
+ free (name);
+ }
+}
+
+/* Set, clear, or conditionalize based on ACTION. */
+void
+handle_variable (action)
+ int action;
+{
+ char *name;
+
+ get_rest_of_line (&name);
+ backup_input_pointer ();
+ canon_white (name);
+ handle_variable_internal (action, name);
+ free (name);
+}
+
+void
+handle_variable_internal (action, name)
+ int action;
+ char *name;
+{
+ char *temp;
+ int delimiter, additional_text_present = 0;
+
+ /* Only the first word of NAME is a valid tag. */
+ temp = name;
+ delimiter = 0;
+ while (*temp && (delimiter || !whitespace (*temp)))
+ {
+/* #if defined (SET_WITH_EQUAL) */
+ if (*temp == '"' || *temp == '\'')
+ {
+ if (*temp == delimiter)
+ delimiter = 0;
+ else
+ delimiter = *temp;
+ }
+/* #endif SET_WITH_EQUAL */
+ temp++;
+ }
+
+ if (*temp)
+ additional_text_present++;
+
+ *temp = '\0';
+
+ if (!*name)
+ line_error ("%c%s requires a name", COMMAND_PREFIX, command);
+ else
+ {
+ switch (action)
+ {
+ case SET:
+ {
+ char *value;
+
+#if defined (SET_WITH_EQUAL)
+ /* Allow a value to be saved along with a variable. The value is
+ the text following an `=' sign in NAME, if any is present. */
+
+ for (value = name; *value && *value != '='; value++);
+
+ if (*value)
+ *value++ = '\0';
+
+ if (*value == '"' || *value == '\'')
+ {
+ value++;
+ value[strlen (value) - 1] = '\0';
+ }
+
+#else /* !SET_WITH_EQUAL */
+ /* The VALUE of NAME is the remainder of the line sans
+ whitespace. */
+ if (additional_text_present)
+ {
+ value = temp + 1;
+ canon_white (value);
+ }
+ else
+ value = "";
+#endif /* !SET_WITH_VALUE */
+
+ set (name, value);
+ }
+ break;
+
+ case CLEAR:
+ clear (name);
+ break;
+
+ case IFSET:
+ case IFCLEAR:
+ /* If IFSET and NAME is not set, or if IFCLEAR and NAME is set,
+ read lines from the the file until we reach a matching
+ "@end CONDITION". This means that we only take note of
+ "@ifset/clear" and "@end" commands. */
+ {
+ char condition[8];
+ int condition_len;
+
+ if (action == IFSET)
+ strcpy (condition, "ifset");
+ else
+ strcpy (condition, "ifclear");
+
+ condition_len = strlen (condition);
+
+ if ((action == IFSET && !set_p (name)) ||
+ (action == IFCLEAR && set_p (name)))
+ {
+ int level = 0, done = 0;
+
+ while (!done)
+ {
+ char *freeable_line, *line;
+
+ get_rest_of_line (&freeable_line);
+
+ for (line = freeable_line; whitespace (*line); line++);
+
+ if (*line == COMMAND_PREFIX &&
+ (strncmp (line + 1, condition, condition_len) == 0))
+ level++;
+ else if (strncmp (line, "@end", 4) == 0)
+ {
+ char *cname = line + 4;
+ char *temp;
+
+ while (*cname && whitespace (*cname))
+ cname++;
+ temp = cname;
+
+ while (*temp && !whitespace (*temp))
+ temp++;
+ *temp = '\0';
+
+ if (strcmp (cname, condition) == 0)
+ {
+ if (!level)
+ {
+ done = 1;
+ }
+ else
+ level--;
+ }
+ }
+ free (freeable_line);
+ }
+ /* We found the end of a false @ifset/ifclear. If we are
+ in a menu, back up over the newline that ends the ifset,
+ since that newline may also begin the next menu entry. */
+ break;
+ }
+ else
+ {
+ if (action == IFSET)
+ begin_insertion (ifset);
+ else
+ begin_insertion (ifclear);
+ }
+ }
+ break;
+ }
+ }
+}
+
+/* Execution of random text not in file. */
+
+typedef struct {
+ char *string; /* The string buffer. */
+ int size; /* The size of the buffer. */
+ int in_use; /* Non-zero means string currently in use. */
+} EXECUTION_STRING;
+
+static EXECUTION_STRING **execution_strings = (EXECUTION_STRING **)NULL;
+static int execution_strings_index = 0;
+static int execution_strings_slots = 0;
+
+EXECUTION_STRING *
+get_execution_string (initial_size)
+ int initial_size;
+{
+ register int i = 0;
+ EXECUTION_STRING *es = (EXECUTION_STRING *)NULL;
+
+ if (execution_strings)
+ {
+ for (i = 0; i < execution_strings_index; i++)
+ if (execution_strings[i] && (execution_strings[i]->in_use == 0))
+ {
+ es = execution_strings[i];
+ break;
+ }
+ }
+
+ if (!es)
+ {
+ if (execution_strings_index + 1 >= execution_strings_slots)
+ {
+ execution_strings = (EXECUTION_STRING **)xrealloc
+ (execution_strings,
+ (execution_strings_slots += 3) * sizeof (EXECUTION_STRING *));
+ for (; i < execution_strings_slots; i++)
+ execution_strings[i] = (EXECUTION_STRING *)NULL;
+ }
+
+ execution_strings[execution_strings_index] =
+ (EXECUTION_STRING *)xmalloc (sizeof (EXECUTION_STRING));
+ es = execution_strings[execution_strings_index];
+ execution_strings_index++;
+
+ es->size = 0;
+ es->string = (char *)NULL;
+ es->in_use = 0;
+ }
+
+ if (initial_size > es->size)
+ {
+ es->string = (char *) xrealloc (es->string, initial_size);
+ es->size = initial_size;
+ }
+ return (es);
+}
+
+/* Execute the string produced by formatting the ARGs with FORMAT. This
+ is like submitting a new file with @include. */
+#if defined (HAVE_VARARGS_H) && defined (HAVE_VSPRINTF)
+void
+execute_string (va_alist)
+ va_dcl
+{
+ EXECUTION_STRING *es;
+ char *temp_string;
+ char *format;
+ va_list args;
+
+ es = get_execution_string (4000);
+ temp_string = es->string;
+ es->in_use = 1;
+
+ va_start (args);
+ format = va_arg (args, char *);
+ vsprintf (temp_string, format, args);
+ va_end (args);
+
+#else /* !(HAVE_VARARGS_H && HAVE_VSPRINTF) */
+
+void
+execute_string (format, arg1, arg2, arg3, arg4, arg5)
+ char *format;
+{
+ EXECUTION_STRING *es;
+ char *temp_string;
+
+ es = get_execution_string (4000);
+ temp_string = es->string;
+ es->in_use = 1;
+
+ sprintf (temp_string, format, arg1, arg2, arg3, arg4, arg5);
+
+#endif /* !(HAVE_VARARGS_H && HAVE_VSPRINTF) */
+
+ pushfile ();
+ input_text_offset = 0;
+ input_text = temp_string;
+ input_filename = strdup (input_filename);
+ size_of_input_text = strlen (temp_string);
+
+ executing_string++;
+ reader_loop ();
+ free (input_filename);
+
+ popfile ();
+ executing_string--;
+ es->in_use = 0;
+}
+
+
+/* Return what would be output for STR, i.e., expand Texinfo commands.
+ If IMPLICIT_CODE is set, expand @code{STR}. */
+
+char *
+expansion (str, implicit_code)
+ char *str;
+ int implicit_code;
+{
+ int length;
+ char *result;
+
+ /* Inhibit any real output. */
+ int start = output_paragraph_offset;
+ int saved_paragraph_is_open = paragraph_is_open;
+
+ inhibit_output_flushing ();
+ execute_string (implicit_code ? "@code{%s}" : "%s", str);
+ uninhibit_output_flushing ();
+
+ /* Copy the expansion from the buffer. */
+ length = output_paragraph_offset - start;
+ result = xmalloc (1 + length);
+ memcpy (result, (char *) (output_paragraph + start), length);
+ result[length] = 0;
+
+ /* Pretend it never happened. */
+ output_paragraph_offset = start;
+ paragraph_is_open = saved_paragraph_is_open;
+
+ return result;
+}
+
+/* @itemx, @item. */
+
+static int itemx_flag = 0;
+
+void
+cm_itemx ()
+{
+ itemx_flag++;
+ cm_item ();
+ itemx_flag--;
+}
+
+void
+cm_item ()
+{
+ char *rest_of_line, *item_func;
+
+ /* Can only hack "@item" while inside of an insertion. */
+ if (insertion_level)
+ {
+ INSERTION_ELT *stack = insertion_stack;
+ int original_input_text_offset;
+
+ skip_whitespace ();
+ original_input_text_offset = input_text_offset;
+
+ get_rest_of_line (&rest_of_line);
+ canon_white (rest_of_line);
+ item_func = current_item_function ();
+
+ /* Okay, do the right thing depending on which insertion function
+ is active. */
+
+ switch_top:
+ switch (stack->insertion)
+ {
+ case multitable:
+ multitable_item ();
+ /* Ultra special hack. It appears that some people incorrectly
+ place text directly after the @item, instead of on a new line
+ by itself. This happens to work in TeX, so I make it work
+ here. */
+ if (*rest_of_line)
+ {
+ line_number--;
+ input_text_offset = original_input_text_offset;
+ }
+ break;
+
+ case ifinfo:
+ case ifset:
+ case ifclear:
+ case cartouche:
+ stack = stack->next;
+ if (!stack)
+ goto no_insertion;
+ else
+ goto switch_top;
+ break;
+
+ case menu:
+ case quotation:
+ case example:
+ case smallexample:
+ case lisp:
+ case format:
+ case display:
+ case group:
+ line_error ("The `%c%s' command is meaningless within a `@%s' block",
+ COMMAND_PREFIX, command,
+ insertion_type_pname (current_insertion_type ()));
+ break;
+
+ case itemize:
+ case enumerate:
+ if (itemx_flag)
+ {
+ line_error ("%citemx is not meaningful inside of a `%s' block",
+ COMMAND_PREFIX,
+ insertion_type_pname (current_insertion_type ()));
+ }
+ else
+ {
+ start_paragraph ();
+ kill_self_indent (-1);
+ filling_enabled = indented_fill = 1;
+
+ if (current_insertion_type () == itemize)
+ {
+ indent (output_column = current_indent - 2);
+
+ /* I need some way to determine whether this command
+ takes braces or not. I believe the user can type
+ either "@bullet" or "@bullet{}". Of course, they
+ can also type "o" or "#" or whatever else they want. */
+ if (item_func && *item_func)
+ {
+ if (*item_func == COMMAND_PREFIX)
+ if (item_func[strlen (item_func) - 1] != '}')
+ execute_string ("%s{}", item_func);
+ else
+ execute_string ("%s", item_func);
+ else
+ execute_string ("%s", item_func);
+ }
+ insert (' ');
+ output_column++;
+ }
+ else
+ enumerate_item ();
+
+ /* Special hack. This makes close paragraph ignore you until
+ the start_paragraph () function has been called. */
+ must_start_paragraph = 1;
+
+ /* Ultra special hack. It appears that some people incorrectly
+ place text directly after the @item, instead of on a new line
+ by itself. This happens to work in TeX, so I make it work
+ here. */
+ if (*rest_of_line)
+ {
+ line_number--;
+ input_text_offset = original_input_text_offset;
+ }
+ }
+ break;
+
+ case table:
+ case ftable:
+ case vtable:
+ {
+ /* Get rid of extra characters. */
+ kill_self_indent (-1);
+
+ /* close_paragraph () almost does what we want. The problem
+ is when paragraph_is_open, and last_char_was_newline, and
+ the last newline has been turned into a space, because
+ filling_enabled. I handle it here. */
+ if (last_char_was_newline && filling_enabled && paragraph_is_open)
+ insert ('\n');
+ close_paragraph ();
+
+#if defined (INDENT_PARAGRAPHS_IN_TABLE)
+ /* Indent on a new line, but back up one indentation level. */
+ {
+ int t;
+
+ t = inhibit_paragraph_indentation;
+ inhibit_paragraph_indentation = 1;
+ /* At this point, inserting any non-whitespace character will
+ force the existing indentation to be output. */
+ add_char ('i');
+ inhibit_paragraph_indentation = t;
+ }
+#else /* !INDENT_PARAGRAPHS_IN_TABLE */
+ add_char ('i');
+#endif /* !INDENT_PARAGRAPHS_IN_TABLE */
+
+ output_paragraph_offset--;
+ kill_self_indent (default_indentation_increment + 1);
+
+ /* Add item's argument to the line. */
+ filling_enabled = 0;
+ if (item_func && *item_func)
+ execute_string ("%s{%s}", item_func, rest_of_line);
+ else
+ execute_string ("%s", rest_of_line);
+
+ if (current_insertion_type () == ftable)
+ execute_string ("%cfindex %s\n", COMMAND_PREFIX, rest_of_line);
+
+ if (current_insertion_type () == vtable)
+ execute_string ("%cvindex %s\n", COMMAND_PREFIX, rest_of_line);
+
+ /* Start a new line, and let start_paragraph ()
+ do the indenting of it for you. */
+ close_single_paragraph ();
+ indented_fill = filling_enabled = 1;
+ }
+ }
+ free (rest_of_line);
+ }
+ else
+ {
+ no_insertion:
+ line_error ("%c%s found outside of an insertion block",
+ COMMAND_PREFIX, command);
+ }
+}
+
+/* **************************************************************** */
+/* */
+/* Defun and Friends */
+/* */
+/* **************************************************************** */
+
+#define DEFUN_SELF_DELIMITING(c) \
+ (((c) == '(') \
+ || ((c) == ')') \
+ || ((c) == '[') \
+ || ((c) == ']'))
+
+struct token_accumulator
+{
+ unsigned int length;
+ unsigned int index;
+ char **tokens;
+};
+
+void
+initialize_token_accumulator (accumulator)
+ struct token_accumulator *accumulator;
+{
+ (accumulator->length) = 0;
+ (accumulator->index) = 0;
+ (accumulator->tokens) = NULL;
+}
+
+void
+accumulate_token (accumulator, token)
+ struct token_accumulator *accumulator;
+ char *token;
+{
+ if ((accumulator->index) >= (accumulator->length))
+ {
+ (accumulator->length) += 10;
+ (accumulator->tokens) = (char **) xrealloc
+ (accumulator->tokens, (accumulator->length * sizeof (char *)));
+ }
+ accumulator->tokens[accumulator->index] = token;
+ accumulator->index += 1;
+}
+
+char *
+copy_substring (start, end)
+ char *start;
+ char *end;
+{
+ char *result, *scan, *scan_result;
+
+ result = (char *) xmalloc ((end - start) + 1);
+ scan_result = result;
+ scan = start;
+
+ while (scan < end)
+ *scan_result++ = *scan++;
+
+ *scan_result = '\0';
+ return (result);
+}
+
+/* Given `string' pointing at an open brace, skip forward and return a
+ pointer to just past the matching close brace. */
+int
+scan_group_in_string (string_pointer)
+ char **string_pointer;
+{
+ register int c;
+ register char *scan_string;
+ register unsigned int level = 1;
+
+ scan_string = (*string_pointer) + 1;
+
+ while (1)
+ {
+ if (level == 0)
+ {
+ (*string_pointer) = scan_string;
+ return (1);
+ }
+ c = (*scan_string++);
+ if (c == '\0')
+ {
+ /* Tweak line_number to compensate for fact that
+ we gobbled the whole line before coming here. */
+ line_number -= 1;
+ line_error ("Missing `}' in %cdef arg", COMMAND_PREFIX);
+ line_number += 1;
+ (*string_pointer) = (scan_string - 1);
+ return (0);
+ }
+ if (c == '{')
+ level += 1;
+ if (c == '}')
+ level -= 1;
+ }
+}
+
+/* Return a list of tokens from the contents of `string'.
+ Commands and brace-delimited groups count as single tokens.
+ Contiguous whitespace characters are converted to a token
+ consisting of a single space. */
+char **
+args_from_string (string)
+ char *string;
+{
+ struct token_accumulator accumulator;
+ register char *scan_string = string;
+ char *token_start, *token_end;
+
+ initialize_token_accumulator (&accumulator);
+
+ while ((*scan_string) != '\0')
+ {
+ /* Replace arbitrary whitespace by a single space. */
+ if (whitespace (*scan_string))
+ {
+ scan_string += 1;
+ while (whitespace (*scan_string))
+ scan_string += 1;
+ accumulate_token ((&accumulator), (strdup (" ")));
+ continue;
+ }
+
+ /* Commands count as single tokens. */
+ if ((*scan_string) == COMMAND_PREFIX)
+ {
+ token_start = scan_string;
+ scan_string += 1;
+ if (self_delimiting (*scan_string))
+ scan_string += 1;
+ else
+ {
+ register int c;
+ while (1)
+ {
+ c = *scan_string++;
+
+ if ((c == '\0') || (c == '{') || (whitespace (c)))
+ {
+ scan_string -= 1;
+ break;
+ }
+ }
+
+ if (*scan_string == '{')
+ {
+ char *s = scan_string;
+ (void) scan_group_in_string (&s);
+ scan_string = s;
+ }
+ }
+ token_end = scan_string;
+ }
+
+ /* Parentheses and brackets are self-delimiting. */
+ else if (DEFUN_SELF_DELIMITING (*scan_string))
+ {
+ token_start = scan_string;
+ scan_string += 1;
+ token_end = scan_string;
+ }
+
+ /* Open brace introduces a group that is a single token. */
+ else if (*scan_string == '{')
+ {
+ char *s = scan_string;
+ int balanced = scan_group_in_string (&s);
+
+ token_start = scan_string + 1;
+ scan_string = s;
+ token_end = balanced ? (scan_string - 1) : scan_string;
+ }
+
+ /* Otherwise a token is delimited by whitespace, parentheses,
+ brackets, or braces. A token is also ended by a command. */
+ else
+ {
+ token_start = scan_string;
+
+ while (1)
+ {
+ register int c;
+
+ c = *scan_string++;
+
+ /* Do not back up if we're looking at a }; since the only
+ valid }'s are those matched with {'s, we want to give
+ an error. If we back up, we go into an infinite loop. */
+ if (!c || whitespace (c) || DEFUN_SELF_DELIMITING (c)
+ || c == '{')
+ {
+ scan_string--;
+ break;
+ }
+
+ /* If we encounter a command embedded within a token,
+ then end the token. */
+ if (c == COMMAND_PREFIX)
+ {
+ scan_string--;
+ break;
+ }
+ }
+ token_end = scan_string;
+ }
+
+ accumulate_token
+ (&accumulator, copy_substring (token_start, token_end));
+ }
+ accumulate_token (&accumulator, NULL);
+ return (accumulator.tokens);
+}
+
+void
+process_defun_args (defun_args, auto_var_p)
+ char **defun_args;
+ int auto_var_p;
+{
+ int pending_space = 0;
+
+ while (1)
+ {
+ char *defun_arg = *defun_args++;
+
+ if (defun_arg == NULL)
+ break;
+
+ if (defun_arg[0] == ' ')
+ {
+ pending_space = 1;
+ continue;
+ }
+
+ if (pending_space)
+ {
+ add_char (' ');
+ pending_space = 0;
+ }
+
+ if (DEFUN_SELF_DELIMITING (defun_arg[0]))
+ add_char (defun_arg[0]);
+ else if (defun_arg[0] == '&')
+ add_word (defun_arg);
+ else if (defun_arg[0] == COMMAND_PREFIX)
+ execute_string ("%s", defun_arg);
+ else if (auto_var_p)
+ execute_string ("%cvar{%s}", COMMAND_PREFIX, defun_arg);
+ else
+ add_word (defun_arg);
+ }
+}
+
+char *
+next_nonwhite_defun_arg (arg_pointer)
+ char ***arg_pointer;
+{
+ char **scan = (*arg_pointer);
+ char *arg = (*scan++);
+
+ if ((arg != 0) && (*arg == ' '))
+ arg = *scan++;
+
+ if (arg == 0)
+ scan -= 1;
+
+ *arg_pointer = scan;
+
+ return ((arg == 0) ? "" : arg);
+}
+
+/* Make the defun type insertion.
+ TYPE says which insertion this is.
+ X_P says not to start a new insertion if non-zero. */
+void
+defun_internal (type, x_p)
+ enum insertion_type type;
+ int x_p;
+{
+ enum insertion_type base_type;
+ char **defun_args, **scan_args;
+ char *category, *defined_name, *type_name, *type_name2;
+
+ {
+ char *line;
+ get_rest_of_line (&line);
+ defun_args = (args_from_string (line));
+ free (line);
+ }
+
+ scan_args = defun_args;
+
+ switch (type)
+ {
+ case defun:
+ category = "Function";
+ base_type = deffn;
+ break;
+ case defmac:
+ category = "Macro";
+ base_type = deffn;
+ break;
+ case defspec:
+ category = "Special Form";
+ base_type = deffn;
+ break;
+ case defvar:
+ category = "Variable";
+ base_type = defvr;
+ break;
+ case defopt:
+ category = "User Option";
+ base_type = defvr;
+ break;
+ case deftypefun:
+ category = "Function";
+ base_type = deftypefn;
+ break;
+ case deftypevar:
+ category = "Variable";
+ base_type = deftypevr;
+ break;
+ case defivar:
+ category = "Instance Variable";
+ base_type = defcv;
+ break;
+ case defmethod:
+ category = "Method";
+ base_type = defop;
+ break;
+ case deftypemethod:
+ category = "Method";
+ base_type = deftypemethod;
+ break;
+ default:
+ category = next_nonwhite_defun_arg (&scan_args);
+ base_type = type;
+ break;
+ }
+
+ if ((base_type == deftypefn)
+ || (base_type == deftypevr)
+ || (base_type == defcv)
+ || (base_type == defop)
+ || (base_type == deftypemethod))
+ type_name = next_nonwhite_defun_arg (&scan_args);
+
+ if (base_type == deftypemethod)
+ type_name2 = next_nonwhite_defun_arg (&scan_args);
+
+ defined_name = next_nonwhite_defun_arg (&scan_args);
+
+ /* This hack exists solely for the purposes of formatting the texinfo
+ manual. I couldn't think of a better way. The token might be
+ a simple @@ followed immediately by more text. If this is the case,
+ then the next defun arg is part of this one, and we should concatenate
+ them. */
+ if (*scan_args && **scan_args && !whitespace (**scan_args) &&
+ (strcmp (defined_name, "@@") == 0))
+ {
+ char *tem = (char *)xmalloc (3 + strlen (scan_args[0]));
+
+ sprintf (tem, "@@%s", scan_args[0]);
+
+ free (scan_args[0]);
+ scan_args[0] = tem;
+ scan_args++;
+ defined_name = tem;
+ }
+
+ if (!x_p)
+ begin_insertion (type);
+
+ /* Write the definition header line.
+ This should start at the normal indentation. */
+ current_indent -= default_indentation_increment;
+ start_paragraph ();
+
+ switch (base_type)
+ {
+ case deffn:
+ case defvr:
+ case deftp:
+ execute_string (" -- %s: %s", category, defined_name);
+ break;
+ case deftypefn:
+ case deftypevr:
+ execute_string (" -- %s: %s %s", category, type_name, defined_name);
+ break;
+ case defcv:
+ execute_string (" -- %s of %s: %s", category, type_name, defined_name);
+ break;
+ case defop:
+ execute_string (" -- %s on %s: %s", category, type_name, defined_name);
+ break;
+ case deftypemethod:
+ execute_string (" -- %s on %s: %s %s", category, type_name, type_name2,
+ defined_name);
+ break;
+ }
+ current_indent += default_indentation_increment;
+
+ /* Now process the function arguments, if any.
+ If these carry onto the next line, they should be indented by two
+ increments to distinguish them from the body of the definition,
+ which is indented by one increment. */
+ current_indent += default_indentation_increment;
+
+ switch (base_type)
+ {
+ case deffn:
+ case defop:
+ process_defun_args (scan_args, 1);
+ break;
+ case deftp:
+ case deftypefn:
+ case deftypemethod:
+ process_defun_args (scan_args, 0);
+ break;
+ }
+ current_indent -= default_indentation_increment;
+ close_single_paragraph ();
+
+ if (!macro_expansion_output_stream)
+ /* Make an entry in the appropriate index unless we are just
+ expanding macros. */
+ switch (base_type)
+ {
+ case deffn:
+ case deftypefn:
+ execute_string ("%cfindex %s\n", COMMAND_PREFIX, defined_name);
+ break;
+ case defvr:
+ case deftypevr:
+ case defcv:
+ execute_string ("%cvindex %s\n", COMMAND_PREFIX, defined_name);
+ break;
+ case defop:
+ case deftypemethod:
+ execute_string ("%cfindex %s on %s\n",
+ COMMAND_PREFIX, defined_name, type_name);
+ break;
+ case deftp:
+ execute_string ("%ctindex %s\n", COMMAND_PREFIX, defined_name);
+ break;
+ }
+
+ /* Deallocate the token list. */
+ scan_args = defun_args;
+ while (1)
+ {
+ char * arg = (*scan_args++);
+ if (arg == NULL)
+ break;
+ free (arg);
+ }
+ free (defun_args);
+}
+
+/* Add an entry for a function, macro, special form, variable, or option.
+ If the name of the calling command ends in `x', then this is an extra
+ entry included in the body of an insertion of the same type. */
+void
+cm_defun ()
+{
+ int x_p;
+ enum insertion_type type;
+ char *temp = strdup (command);
+
+ x_p = (command[strlen (command) - 1] == 'x');
+
+ if (x_p)
+ temp[strlen (temp) - 1] = '\0';
+
+ type = find_type_from_name (temp);
+ free (temp);
+
+ /* If we are adding to an already existing insertion, then make sure
+ that we are already in an insertion of type TYPE. */
+ if (x_p &&
+ (!insertion_level || insertion_stack->insertion != type))
+ {
+ line_error ("Must be in a `%s' insertion in order to use `%s'x",
+ command, command);
+ discard_until ("\n");
+ return;
+ }
+
+ defun_internal (type, x_p);
+}
+
+/* End existing insertion block. */
+void
+cm_end ()
+{
+ char *temp;
+ enum insertion_type type;
+
+ if (!insertion_level)
+ {
+ line_error ("Unmatched `%c%s'", COMMAND_PREFIX, command);
+ return;
+ }
+
+ get_rest_of_line (&temp);
+ canon_white (temp);
+
+ if (strlen (temp) == 0)
+ line_error ("`%c%s' needs something after it", COMMAND_PREFIX, command);
+
+ type = find_type_from_name (temp);
+
+ if (type == bad_type)
+ {
+ line_error ("Bad argument to `%s', `%s', using `%s'",
+ command, temp, insertion_type_pname (current_insertion_type ()));
+ }
+ end_insertion (type);
+ free (temp);
+}
+
+/* **************************************************************** */
+/* */
+/* Other Random Commands */
+/* */
+/* **************************************************************** */
+
+/* This says to inhibit the indentation of the next paragraph, but
+ not of following paragraphs. */
+void
+cm_noindent ()
+{
+ if (!inhibit_paragraph_indentation)
+ inhibit_paragraph_indentation = -1;
+}
+
+/* I don't know exactly what to do with this. Should I allow
+ someone to switch filenames in the middle of output? Since the
+ file could be partially written, this doesn't seem to make sense.
+ Another option: ignore it, since they don't *really* want to
+ switch files. Finally, complain, or at least warn. */
+void
+cm_setfilename ()
+{
+ char *filename;
+ get_rest_of_line (&filename);
+ /* warning ("`@%s %s' encountered and ignored", command, filename); */
+ free (filename);
+}
+
+void
+cm_ignore_line ()
+{
+ discard_until ("\n");
+}
+
+/* @br can be immediately followed by `{}', so we have to read those here.
+ It should simply close the paragraph. */
+void
+cm_br ()
+{
+ if (looking_at ("{}"))
+ input_text_offset += 2;
+
+ if (curchar () == '\n')
+ {
+ input_text_offset++;
+ line_number++;
+ }
+
+ close_paragraph ();
+}
+
+ /* Insert the number of blank lines passed as argument. */
+void
+cm_sp ()
+{
+ int lines;
+ char *line;
+
+ get_rest_of_line (&line);
+
+ if (sscanf (line, "%d", &lines) != 1)
+ {
+ line_error ("%csp requires a positive numeric argument", COMMAND_PREFIX);
+ }
+ else
+ {
+ if (lines < 0)
+ lines = 0;
+
+ while (lines--)
+ add_char ('\n');
+ }
+ free (line);
+}
+
+/* @dircategory LINE outputs INFO-DIR-SECTION LINE,
+ but not if --no-headers. */
+
+void
+cm_dircategory ()
+{
+ char *line, *p;
+
+ get_rest_of_line (&line);;
+
+ if (! no_headers)
+ {
+ insert_string ("INFO-DIR-SECTION ");
+ insert_string (line);
+ insert ('\n');
+ }
+
+ free (line);
+}
+
+/* Start a new line with just this text on it.
+ Then center the line of text.
+ This always ends the current paragraph. */
+void
+cm_center ()
+{
+ register int i, start, length;
+ int fudge_factor = 1;
+ unsigned char *line;
+
+ close_paragraph ();
+ filling_enabled = indented_fill = 0;
+ cm_noindent ();
+ start = output_paragraph_offset;
+ inhibit_output_flushing ();
+ get_rest_of_line ((char **)&line);
+ execute_string ("%s", (char *)line);
+ free (line);
+ uninhibit_output_flushing ();
+
+ i = output_paragraph_offset - 1;
+ while (i > (start - 1) && output_paragraph[i] == '\n')
+ i--;
+
+ output_paragraph_offset = ++i;
+ length = output_paragraph_offset - start;
+
+ if (length < (fill_column - fudge_factor))
+ {
+ line = (unsigned char *)xmalloc (1 + length);
+ memcpy (line, (char *)(output_paragraph + start), length);
+
+ i = (fill_column - fudge_factor - length) / 2;
+ output_paragraph_offset = start;
+
+ while (i--)
+ insert (' ');
+
+ for (i = 0; i < length; i++)
+ insert (line[i]);
+
+ free (line);
+ }
+
+ insert ('\n');
+ close_paragraph ();
+ filling_enabled = 1;
+}
+
+/* Show what an expression returns. */
+void
+cm_result (arg)
+ int arg;
+{
+ if (arg == END)
+ add_word ("=>");
+}
+
+/* What an expression expands to. */
+void
+cm_expansion (arg)
+ int arg;
+{
+ if (arg == END)
+ add_word ("==>");
+}
+
+/* Indicates two expressions are equivalent. */
+void
+cm_equiv (arg)
+ int arg;
+{
+ if (arg == END)
+ add_word ("==");
+}
+
+/* What an expression may print. */
+void
+cm_print (arg)
+ int arg;
+{
+ if (arg == END)
+ add_word ("-|");
+}
+
+/* An error signaled. */
+void
+cm_error (arg)
+ int arg;
+{
+ if (arg == END)
+ add_word ("error-->");
+}
+
+/* The location of point in an example of a buffer. */
+void
+cm_point (arg)
+ int arg;
+{
+ if (arg == END)
+ add_word ("-!-");
+}
+
+/* Start a new line with just this text on it.
+ The text is outdented one level if possible. */
+void
+cm_exdent ()
+{
+ char *line;
+ int i = current_indent;
+
+ if (current_indent)
+ current_indent -= default_indentation_increment;
+
+ get_rest_of_line (&line);
+ close_single_paragraph ();
+ execute_string ("%s", line);
+ current_indent = i;
+ free (line);
+ close_single_paragraph ();
+}
+
+#if !defined (HAVE_STRERROR)
+extern char *sys_errlist[];
+extern int sys_nerr;
+
+char *
+strerror (num)
+ int num;
+{
+ if (num >= sys_nerr)
+ return ("Unknown file system error");
+ else
+ return (sys_errlist[num]);
+}
+#endif /* !HAVE_STRERROR */
+
+/* Remember this file, and move onto the next. */
+void
+cm_include ()
+{
+ char *filename;
+
+#if defined (HAVE_MACROS)
+ if (macro_expansion_output_stream)
+ me_append_before_this_command ();
+#endif /* HAVE_MACROS */
+
+ close_paragraph ();
+ get_rest_of_line (&filename);
+
+#if defined (HAVE_MACROS)
+ if (macro_expansion_output_stream)
+ remember_itext (input_text, input_text_offset);
+#endif /* HAVE_MACROS */
+
+ pushfile ();
+
+ /* In verbose mode we print info about including another file. */
+ if (verbose_mode)
+ {
+ register int i = 0;
+ register FSTACK *stack = filestack;
+
+ for (i = 0, stack = filestack; stack; stack = stack->next, i++);
+
+ i *= 2;
+
+ printf ("%*s", i, "");
+ printf ("%c%s %s\n", COMMAND_PREFIX, command, filename);
+ fflush (stdout);
+ }
+
+ if (!find_and_load (filename))
+ {
+ extern int errno;
+
+ popfile ();
+ line_number--;
+
+ /* Cannot "@include foo", in line 5 of "/wh/bar". */
+ line_error ("`%c%s %s': %s", COMMAND_PREFIX, command, filename,
+ strerror (errno));
+
+ free (filename);
+ return;
+ }
+ else
+ {
+#if defined (HAVE_MACROS)
+ if (macro_expansion_output_stream)
+ remember_itext (input_text, input_text_offset);
+#endif /* HAVE_MACROS */
+ reader_loop ();
+ }
+ free (filename);
+ popfile ();
+}
+
+/* The other side of a malformed expression. */
+void
+misplaced_brace ()
+{
+ line_error ("Misplaced `}'");
+}
+
+/* Signals end of processing. Easy to make this happen. */
+void
+cm_bye ()
+{
+ input_text_offset = size_of_input_text;
+}
+
+/* **************************************************************** */
+/* */
+/* Indexing Stuff */
+/* */
+/* **************************************************************** */
+
+
+/* An index element... */
+typedef struct index_elt
+{
+ struct index_elt *next;
+ char *entry; /* The index entry itself. */
+ char *node; /* The node from whence it came. */
+ int code; /* Non-zero means add `@code{...}' when
+ printing this element. */
+ int defining_line; /* Line number where this entry was written. */
+} INDEX_ELT;
+
+/* A list of short-names for each index, and the index to that index in our
+ index array, the_indices. In addition, for each index, it is remembered
+ whether that index is a code index or not. Code indices have @code{}
+ inserted around the first word when they are printed with printindex. */
+typedef struct
+{
+ char *name;
+ int index;
+ int code;
+} INDEX_ALIST;
+
+INDEX_ALIST **name_index_alist = (INDEX_ALIST **) NULL;
+
+/* An array of pointers. Each one is for a different index. The
+ "synindex" command changes which array slot is pointed to by a
+ given "index". */
+INDEX_ELT **the_indices = (INDEX_ELT **) NULL;
+
+/* The number of defined indices. */
+int defined_indices = 0;
+
+/* We predefine these. */
+#define program_index 0
+#define function_index 1
+#define concept_index 2
+#define variable_index 3
+#define datatype_index 4
+#define key_index 5
+
+void
+init_indices ()
+{
+ int i;
+
+ /* Create the default data structures. */
+
+ /* Initialize data space. */
+ if (!the_indices)
+ {
+ the_indices = (INDEX_ELT **) xmalloc ((1 + defined_indices) *
+ sizeof (INDEX_ELT *));
+ the_indices[defined_indices] = (INDEX_ELT *) NULL;
+
+ name_index_alist = (INDEX_ALIST **) xmalloc ((1 + defined_indices) *
+ sizeof (INDEX_ALIST *));
+ name_index_alist[defined_indices] = (INDEX_ALIST *) NULL;
+ }
+
+ /* If there were existing indices, get rid of them now. */
+ for (i = 0; i < defined_indices; i++)
+ undefindex (name_index_alist[i]->name);
+
+ /* Add the default indices. */
+ top_defindex ("pg", 0);
+ top_defindex ("fn", 1); /* "fn" is a code index. */
+ top_defindex ("cp", 0);
+ top_defindex ("vr", 0);
+ top_defindex ("tp", 0);
+ top_defindex ("ky", 0);
+
+}
+
+/* Find which element in the known list of indices has this name.
+ Returns -1 if NAME isn't found. */
+int
+find_index_offset (name)
+ char *name;
+{
+ register int i;
+ for (i = 0; i < defined_indices; i++)
+ if (name_index_alist[i] &&
+ strcmp (name, name_index_alist[i]->name) == 0)
+ return (name_index_alist[i]->index);
+ return (-1);
+}
+
+/* Return a pointer to the entry of (name . index) for this name.
+ Return NULL if the index doesn't exist. */
+INDEX_ALIST *
+find_index (name)
+ char *name;
+{
+ int offset = find_index_offset (name);
+ if (offset > -1)
+ return (name_index_alist[offset]);
+ else
+ return ((INDEX_ALIST *) NULL);
+}
+
+/* Given an index name, return the offset in the_indices of this index,
+ or -1 if there is no such index. */
+int
+translate_index (name)
+ char *name;
+{
+ INDEX_ALIST *which = find_index (name);
+
+ if (which)
+ return (which->index);
+ else
+ return (-1);
+}
+
+/* Return the index list which belongs to NAME. */
+INDEX_ELT *
+index_list (name)
+ char *name;
+{
+ int which = translate_index (name);
+ if (which < 0)
+ return ((INDEX_ELT *) -1);
+ else
+ return (the_indices[which]);
+}
+
+/* Please release me, let me go... */
+void
+free_index (index)
+ INDEX_ELT *index;
+{
+ INDEX_ELT *temp;
+
+ while ((temp = index) != (INDEX_ELT *) NULL)
+ {
+ free (temp->entry);
+ free (temp->node);
+ index = index->next;
+ free (temp);
+ }
+}
+
+/* Flush an index by name. */
+void
+undefindex (name)
+ char *name;
+{
+ int i;
+ int which = find_index_offset (name);
+
+ if (which < 0)
+ return;
+
+ i = name_index_alist[which]->index;
+
+ free_index (the_indices[i]);
+ the_indices[i] = (INDEX_ELT *) NULL;
+
+ free (name_index_alist[which]->name);
+ free (name_index_alist[which]);
+ name_index_alist[which] = (INDEX_ALIST *) NULL;
+}
+
+/* Define an index known as NAME. We assign the slot number.
+ CODE if non-zero says to make this a code index. */
+void
+defindex (name, code)
+ char *name;
+ int code;
+{
+ register int i, slot;
+
+ /* If it already exists, flush it. */
+ undefindex (name);
+
+ /* Try to find an empty slot. */
+ slot = -1;
+ for (i = 0; i < defined_indices; i++)
+ if (!name_index_alist[i])
+ {
+ slot = i;
+ break;
+ }
+
+ if (slot < 0)
+ {
+ /* No such luck. Make space for another index. */
+ slot = defined_indices;
+ defined_indices++;
+
+ name_index_alist = (INDEX_ALIST **)
+ xrealloc ((char *)name_index_alist,
+ (1 + defined_indices) * sizeof (INDEX_ALIST *));
+ the_indices = (INDEX_ELT **)
+ xrealloc ((char *)the_indices,
+ (1 + defined_indices) * sizeof (INDEX_ELT *));
+ }
+
+ /* We have a slot. Start assigning. */
+ name_index_alist[slot] = (INDEX_ALIST *) xmalloc (sizeof (INDEX_ALIST));
+ name_index_alist[slot]->name = strdup (name);
+ name_index_alist[slot]->index = slot;
+ name_index_alist[slot]->code = code;
+
+ the_indices[slot] = (INDEX_ELT *) NULL;
+}
+
+/* Add the arguments to the current index command to the index NAME. */
+void
+index_add_arg (name)
+ char *name;
+{
+ int which;
+ char *index_entry;
+ INDEX_ALIST *tem;
+
+ tem = find_index (name);
+
+ which = tem ? tem->index : -1;
+
+#if defined (HAVE_MACROS)
+ if (macro_expansion_output_stream)
+ append_to_expansion_output (input_text_offset + 1);
+#endif /* HAVE_MACROS */
+
+ get_rest_of_line (&index_entry);
+ ignore_blank_line ();
+
+#if defined (HAVE_MACROS)
+ if (macro_expansion_output_stream)
+ {
+ int op_orig;
+
+ remember_itext (input_text, input_text_offset);
+ op_orig = output_paragraph_offset;
+ me_execute_string (index_entry);
+ me_execute_string ("\n");
+ output_paragraph_offset = op_orig;
+ }
+#endif /* HAVE_MACROS */
+
+ if (which < 0)
+ {
+ line_error ("Unknown index reference `%s'", name);
+ free (index_entry);
+ }
+ else
+ {
+ INDEX_ELT *new = (INDEX_ELT *) xmalloc (sizeof (INDEX_ELT));
+ new->next = the_indices[which];
+ new->entry = index_entry;
+ new->node = current_node;
+ new->code = tem->code;
+ new->defining_line = line_number - 1;
+ the_indices[which] = new;
+ }
+}
+
+#define INDEX_COMMAND_SUFFIX "index"
+
+/* The function which user defined index commands call. */
+void
+gen_index ()
+{
+ char *name = strdup (command);
+ if (strlen (name) >= strlen ("index"))
+ name[strlen (name) - strlen ("index")] = '\0';
+ index_add_arg (name);
+ free (name);
+}
+
+void
+top_defindex (name, code)
+ char *name;
+ int code;
+{
+ char *temp;
+
+ temp = (char *) xmalloc (1 + strlen (name) + strlen ("index"));
+ sprintf (temp, "%sindex", name);
+ define_user_command (temp, gen_index, 0);
+ defindex (name, code);
+ free (temp);
+}
+
+/* Define a new index command. Arg is name of index. */
+void
+cm_defindex ()
+{
+ gen_defindex (0);
+}
+
+void
+cm_defcodeindex ()
+{
+ gen_defindex (1);
+}
+
+void
+gen_defindex (code)
+ int code;
+{
+ char *name;
+ get_rest_of_line (&name);
+
+ if (find_index (name))
+ {
+ line_error ("Index `%s' already exists", name);
+ free (name);
+ return;
+ }
+ else
+ {
+ char *temp = (char *) alloca (1 + strlen (name) + strlen ("index"));
+ sprintf (temp, "%sindex", name);
+ define_user_command (temp, gen_index, 0);
+ defindex (name, code);
+ free (name);
+ }
+}
+
+/* Append LIST2 to LIST1. Return the head of the list. */
+INDEX_ELT *
+index_append (head, tail)
+ INDEX_ELT *head, *tail;
+{
+ register INDEX_ELT *t_head = head;
+
+ if (!t_head)
+ return (tail);
+
+ while (t_head->next)
+ t_head = t_head->next;
+ t_head->next = tail;
+ return (head);
+}
+
+/* Expects 2 args, on the same line. Both are index abbreviations.
+ Make the first one be a synonym for the second one, i.e. make the
+ first one have the same index as the second one. */
+void
+cm_synindex ()
+{
+ int redirector, redirectee;
+ char *temp;
+
+ skip_whitespace ();
+ get_until_in_line (" ", &temp);
+ redirectee = find_index_offset (temp);
+ skip_whitespace ();
+ free_and_clear (&temp);
+ get_until_in_line (" ", &temp);
+ redirector = find_index_offset (temp);
+ free (temp);
+ if (redirector < 0 || redirectee < 0)
+ {
+ line_error ("Unknown index reference");
+ }
+ else
+ {
+ /* I think that we should let the user make indices synonymous to
+ each other without any lossage of info. This means that one can
+ say @synindex cp dt anywhere in the file, and things that used to
+ be in cp will go into dt. */
+ INDEX_ELT *i1 = the_indices[redirectee], *i2 = the_indices[redirector];
+
+ if (i1 || i2)
+ {
+ if (i1)
+ the_indices[redirectee] = index_append (i1, i2);
+ else
+ the_indices[redirectee] = index_append (i2, i1);
+ }
+
+ name_index_alist[redirectee]->index =
+ name_index_alist[redirector]->index;
+ }
+}
+
+void
+cm_pindex () /* Pinhead index. */
+{
+ index_add_arg ("pg");
+}
+
+void
+cm_vindex () /* Variable index. */
+{
+ index_add_arg ("vr");
+}
+
+void
+cm_kindex () /* Key index. */
+{
+ index_add_arg ("ky");
+}
+
+void
+cm_cindex () /* Concept index. */
+{
+ index_add_arg ("cp");
+}
+
+void
+cm_findex () /* Function index. */
+{
+ index_add_arg ("fn");
+}
+
+void
+cm_tindex () /* Data Type index. */
+{
+ index_add_arg ("tp");
+}
+
+/* Sorting the index. */
+int
+index_element_compare (element1, element2)
+ INDEX_ELT **element1, **element2;
+{
+ return (strcasecmp ((*element1)->entry, (*element2)->entry));
+}
+
+/* Force all index entries to be unique. */
+void
+make_index_entries_unique (array, count)
+ INDEX_ELT **array;
+ int count;
+{
+ register int i, j;
+ INDEX_ELT **copy;
+ int counter = 1;
+
+ copy = (INDEX_ELT **)xmalloc ((1 + count) * sizeof (INDEX_ELT *));
+
+ for (i = 0, j = 0; i < count; i++)
+ {
+ if ((i == (count - 1)) ||
+ (array[i]->node != array[i + 1]->node) ||
+ (strcmp (array[i]->entry, array[i + 1]->entry) != 0))
+ copy[j++] = array[i];
+ else
+ {
+ free (array[i]->entry);
+ free (array[i]);
+ }
+ }
+ copy[j] = (INDEX_ELT *)NULL;
+
+ /* Now COPY contains only unique entries. Duplicated entries in the
+ original array have been freed. Replace the current array with
+ the copy, fixing the NEXT pointers. */
+ for (i = 0; copy[i] != (INDEX_ELT *)NULL; i++)
+ {
+
+ copy[i]->next = copy[i + 1];
+
+ /* Fix entry names which are the same. They point to different nodes,
+ so we make the entry name unique. */
+ if ((copy[i + 1] != (INDEX_ELT *)NULL) &&
+ (strcmp (copy[i]->entry, copy[i + 1]->entry) == 0))
+ {
+ char *new_entry_name;
+
+ new_entry_name = (char *)xmalloc (10 + strlen (copy[i]->entry));
+ sprintf (new_entry_name, "%s <%d>", copy[i]->entry, counter);
+ free (copy[i]->entry);
+ copy[i]->entry = new_entry_name;
+ counter++;
+ }
+ else
+ counter = 1;
+
+ array[i] = copy[i];
+ }
+ array[i] = (INDEX_ELT *)NULL;
+
+ /* Free the storage used only by COPY. */
+ free (copy);
+}
+
+/* Sort the index passed in INDEX, returning an array of
+ pointers to elements. The array is terminated with a NULL
+ pointer. We call qsort because it's supposed to be fast.
+ I think this looks bad. */
+INDEX_ELT **
+sort_index (index)
+ INDEX_ELT *index;
+{
+ INDEX_ELT *temp = index;
+ INDEX_ELT **array;
+ int count = 0;
+
+ while (temp != (INDEX_ELT *) NULL)
+ {
+ count++;
+ temp = temp->next;
+ }
+
+ /* We have the length. Make an array. */
+
+ array = (INDEX_ELT **) xmalloc ((count + 1) * sizeof (INDEX_ELT *));
+ count = 0;
+ temp = index;
+
+ while (temp != (INDEX_ELT *) NULL)
+ {
+ array[count++] = temp;
+
+ /* Maybe should set line number to the defining_line? Any errors
+ have already been given, though, I think. */
+
+ /* If this particular entry should be printed as a "code" index,
+ then wrap the entry with "@code{...}". */
+ array[count - 1]->entry = expansion (temp->entry, index->code);
+
+ temp = temp->next;
+ }
+ array[count] = (INDEX_ELT *) NULL; /* terminate the array. */
+
+ /* Sort the array. */
+ qsort (array, count, sizeof (INDEX_ELT *), index_element_compare);
+ make_index_entries_unique (array, count);
+ return (array);
+}
+
+/* Non-zero means that we are in the middle of printing an index. */
+int printing_index = 0;
+
+/* Takes one arg, a short name of an index to print.
+ Outputs a menu of the sorted elements of the index. */
+void
+cm_printindex ()
+{
+ int item;
+ INDEX_ELT *index;
+ INDEX_ELT **array;
+ char *index_name;
+ unsigned line_length;
+ char *line;
+ int saved_inhibit_paragraph_indentation = inhibit_paragraph_indentation;
+ int saved_filling_enabled = filling_enabled;
+
+ close_paragraph ();
+ get_rest_of_line (&index_name);
+
+ index = index_list (index_name);
+ if (index == (INDEX_ELT *)-1)
+ {
+ line_error ("Unknown index name `%s'", index_name);
+ free (index_name);
+ return;
+ }
+ else
+ free (index_name);
+
+ /* Do this before sorting, so execute_string in index_element_compare
+ will give the same results as when we actually print. */
+ printing_index = 1;
+ filling_enabled = 0;
+ inhibit_paragraph_indentation = 1;
+ array = sort_index (index);
+
+ close_paragraph ();
+ add_word ("* Menu:\n\n");
+
+#if defined (HAVE_MACROS)
+ me_inhibit_expansion++;
+#endif /* HAVE_MACROS */
+
+ /* This will probably be enough. */
+ line_length = 100;
+ line = xmalloc (line_length);
+
+ for (item = 0; (index = array[item]); item++)
+ {
+ /* A pathological document might have an index entry outside of any
+ node. Don't crash. Perhaps should warn. */
+ char *index_node = index->node ? index->node : "(none)";
+ unsigned new_length = strlen (index->entry) + strlen (index_node);
+
+ if (new_length > line_length)
+ {
+ line_length = new_length + 6; /* * : .\0 */
+ line = xrealloc (line, line_length);
+ }
+
+ /* Print the entry, nicely formatted. We've already expanded any
+ commands, including any implicit @code. Thus, can't call
+ execute_string, since @@ has turned into @. */
+ sprintf (line, "* %-37s %s.\n", index->entry, index_node);
+ line[2 + strlen (index->entry)] = ':';
+ insert_string (line);
+
+ /* Previous `output_paragraph' from growing to the size of the
+ whole index. */
+ flush_output ();
+ }
+
+ free (line);
+
+#if defined (HAVE_MACROS)
+ me_inhibit_expansion--;
+#endif /* HAVE_MACROS */
+
+ printing_index = 0;
+ free (array);
+ close_single_paragraph ();
+ filling_enabled = saved_filling_enabled;
+ inhibit_paragraph_indentation = saved_inhibit_paragraph_indentation;
+}
+
+/* User-defined commands. */
+
+void
+define_user_command (name, proc, needs_braces_p)
+ char *name;
+ COMMAND_FUNCTION *proc;
+ int needs_braces_p;
+{
+ int slot = user_command_array_len;
+ user_command_array_len++;
+
+ if (!user_command_array)
+ user_command_array = (COMMAND **) xmalloc (1 * sizeof (COMMAND *));
+
+ user_command_array = (COMMAND **) xrealloc (user_command_array,
+ (1 + user_command_array_len) *
+ sizeof (COMMAND *));
+
+ user_command_array[slot] = (COMMAND *) xmalloc (sizeof (COMMAND));
+ user_command_array[slot]->name = strdup (name);
+ user_command_array[slot]->proc = proc;
+ user_command_array[slot]->argument_in_braces = needs_braces_p;
+}
+
+/* Set the paragraph indentation variable to the value specified in STRING.
+ Values can be:
+ `asis': Don't change existing indentation.
+ `none': Remove existing indentation.
+ NUM: Indent NUM spaces at the starts of paragraphs.
+ Note that if NUM is zero, we assume `none'.
+
+ Returns 0 if successful, or non-zero if STRING isn't one of the above. */
+int
+set_paragraph_indent (string)
+ char *string;
+{
+ if (strcmp (string, "asis") == 0)
+ paragraph_start_indent = 0;
+ else if (strcmp (string, "none") == 0)
+ paragraph_start_indent = -1;
+ else
+ {
+ if (sscanf (string, "%d", &paragraph_start_indent) != 1)
+ return (-1);
+ else
+ {
+ if (paragraph_start_indent == 0)
+ paragraph_start_indent = -1;
+ }
+ }
+ return (0);
+}
+
+void
+cm_paragraphindent ()
+{
+ char *arg;
+
+ get_rest_of_line (&arg);
+ if (set_paragraph_indent (arg) != 0)
+ line_error ("Bad argument to %c%s", COMMAND_PREFIX, command);
+
+ free (arg);
+}
+
+/* Some support for footnotes. */
+
+/* Footnotes are a new construct in Info. We don't know the best method
+ of implementing them for sure, so we present two possiblities.
+
+ SeparateNode:
+ Make them look like followed references, with the reference
+ destinations in a makeinfo manufactured node or,
+
+ EndNode:
+ Make them appear at the bottom of the node that they originally
+ appeared in. */
+#define SeparateNode 0
+#define EndNode 1
+
+int footnote_style = EndNode;
+int first_footnote_this_node = 1;
+int footnote_count = 0;
+
+/* Set the footnote style based on he style identifier in STRING. */
+int
+set_footnote_style (string)
+ char *string;
+{
+ if ((strcasecmp (string, "separate") == 0) ||
+ (strcasecmp (string, "MN") == 0))
+ footnote_style = SeparateNode;
+ else if ((strcasecmp (string, "end") == 0) ||
+ (strcasecmp (string, "EN") == 0))
+ footnote_style = EndNode;
+ else
+ return (-1);
+
+ return (0);
+}
+
+void
+cm_footnotestyle ()
+{
+ char *arg;
+
+ get_rest_of_line (&arg);
+
+ /* If set on command line, do not change the footnote style. */
+ if (!footnote_style_preset && set_footnote_style (arg) != 0)
+ line_error ("Bad argument to %c%s", COMMAND_PREFIX, command);
+
+ free (arg);
+}
+
+typedef struct fn
+{
+ struct fn *next;
+ char *marker;
+ char *note;
+} FN;
+
+FN *pending_notes = (FN *) NULL;
+
+/* A method for remembering footnotes. Note that this list gets output
+ at the end of the current node. */
+void
+remember_note (marker, note)
+ char *marker, *note;
+{
+ FN *temp = (FN *) xmalloc (sizeof (FN));
+
+ temp->marker = strdup (marker);
+ temp->note = strdup (note);
+ temp->next = pending_notes;
+ pending_notes = temp;
+ footnote_count++;
+}
+
+/* How to get rid of existing footnotes. */
+void
+free_pending_notes ()
+{
+ FN *temp;
+
+ while ((temp = pending_notes) != (FN *) NULL)
+ {
+ free (temp->marker);
+ free (temp->note);
+ pending_notes = pending_notes->next;
+ free (temp);
+ }
+ first_footnote_this_node = 1;
+ footnote_count = 0;
+}
+
+/* What to do when you see a @footnote construct. */
+
+ /* Handle a "footnote".
+ footnote *{this is a footnote}
+ where "*" is the marker character for this note. */
+void
+cm_footnote ()
+{
+ char *marker;
+ char *note;
+
+ get_until ("{", &marker);
+ canon_white (marker);
+
+ /* Read the argument in braces. */
+ if (curchar () != '{')
+ {
+ line_error ("`%c%s' expected more than just `%s'. It needs something in `{...}'",
+ COMMAND_PREFIX, command, marker);
+ free (marker);
+ return;
+ }
+ else
+ {
+ int braces = 1;
+ int temp = ++input_text_offset;
+ int len;
+
+ while (braces)
+ {
+ if (temp == size_of_input_text)
+ {
+ line_error ("No closing brace for footnote `%s'", marker);
+ return;
+ }
+
+ if (input_text[temp] == '{')
+ braces++;
+ else if (input_text[temp] == '}')
+ braces--;
+ else if (input_text[temp] == '\n')
+ line_number ++;
+
+ temp++;
+ }
+
+ len = (temp - input_text_offset) - 1;
+ note = (char *)xmalloc (len + 1);
+ strncpy (note, &input_text[input_text_offset], len);
+ note[len] = '\0';
+ input_text_offset = temp;
+ }
+
+ if (!current_node || !*current_node)
+ {
+ line_error ("Footnote defined without parent node");
+ free (marker);
+ free (note);
+ return;
+ }
+
+ if (!*marker)
+ {
+ free (marker);
+
+ if (number_footnotes)
+ {
+ marker = (char *)xmalloc (10);
+ sprintf (marker, "%d", current_footnote_number);
+ current_footnote_number++;
+ }
+ else
+ marker = strdup ("*");
+ }
+
+ remember_note (marker, note);
+
+ /* Your method should at least insert MARKER. */
+ switch (footnote_style)
+ {
+ case SeparateNode:
+ add_word_args ("(%s)", marker);
+ if (first_footnote_this_node)
+ {
+ char *temp_string;
+
+ temp_string = (char *)
+ xmalloc ((strlen (current_node)) + (strlen ("-Footnotes")) + 1);
+
+ add_word_args (" (*note %s-Footnotes::)", current_node);
+ strcpy (temp_string, current_node);
+ strcat (temp_string, "-Footnotes");
+ remember_node_reference (temp_string, line_number, followed_reference);
+ free (temp_string);
+ first_footnote_this_node = 0;
+ }
+ break;
+
+ case EndNode:
+ add_word_args ("(%s)", marker);
+ break;
+
+ default:
+ break;
+ }
+ free (marker);
+ free (note);
+}
+
+/* Non-zero means that we are currently in the process of outputting
+ footnotes. */
+int already_outputting_pending_notes = 0;
+
+/* Output the footnotes. We are at the end of the current node. */
+void
+output_pending_notes ()
+{
+ FN *footnote = pending_notes;
+
+ if (!pending_notes)
+ return;
+
+ switch (footnote_style)
+ {
+ case SeparateNode:
+ {
+ char *old_current_node = current_node;
+ char *old_command = strdup (command);
+
+ already_outputting_pending_notes++;
+ execute_string ("%cnode %s-Footnotes,,,%s\n",
+ COMMAND_PREFIX, current_node, current_node);
+ already_outputting_pending_notes--;
+ current_node = old_current_node;
+ free (command);
+ command = old_command;
+ }
+ break;
+
+ case EndNode:
+ close_paragraph ();
+ in_fixed_width_font++;
+ execute_string ("---------- Footnotes ----------\n\n");
+ in_fixed_width_font--;
+ break;
+ }
+
+ /* Handle the footnotes in reverse order. */
+ {
+ FN **array = (FN **) xmalloc ((footnote_count + 1) * sizeof (FN *));
+
+ array[footnote_count] = (FN *) NULL;
+
+ while (--footnote_count > -1)
+ {
+ array[footnote_count] = footnote;
+ footnote = footnote->next;
+ }
+
+ filling_enabled = 1;
+ indented_fill = 1;
+
+ while (footnote = array[++footnote_count])
+ {
+
+ switch (footnote_style)
+ {
+ case SeparateNode:
+ case EndNode:
+ execute_string ("(%s) %s", footnote->marker, footnote->note);
+ close_paragraph ();
+ break;
+ }
+ }
+ close_paragraph ();
+ free (array);
+ }
+}
+
+/* **************************************************************** */
+/* */
+/* User definable Macros (text substitution) */
+/* */
+/* **************************************************************** */
+
+#if defined (HAVE_MACROS)
+
+/* Array of macros and definitions. */
+MACRO_DEF **macro_list = (MACRO_DEF **)NULL;
+
+int macro_list_len = 0; /* Number of elements. */
+int macro_list_size = 0; /* Number of slots in total. */
+
+/* Return the macro definition of NAME or NULL if NAME is not defined. */
+MACRO_DEF *
+find_macro (name)
+ char *name;
+{
+ register int i;
+ register MACRO_DEF *def;
+
+ def = (MACRO_DEF *)NULL;
+ for (i = 0; macro_list && (def = macro_list[i]); i++)
+ {
+ if ((!def->inhibited) && (strcmp (def->name, name) == 0))
+ break;
+ }
+ return (def);
+}
+
+/* Add the macro NAME with ARGLIST and BODY to the list of defined macros.
+ SOURCE_FILE is the name of the file where this definition can be found,
+ and SOURCE_LINENO is the line number within that file. If a macro already
+ exists with NAME, then a warning is produced, and that previous
+ definition is overwritten. */
+void
+add_macro (name, arglist, body, source_file, source_lineno, flags)
+ char *name;
+ char **arglist;
+ char *body;
+ char *source_file;
+ int source_lineno, flags;
+{
+ register MACRO_DEF *def;
+
+ def = find_macro (name);
+
+ if (!def)
+ {
+ if (macro_list_len + 2 >= macro_list_size)
+ macro_list = (MACRO_DEF **)xrealloc
+ (macro_list, ((macro_list_size += 10) * sizeof (MACRO_DEF *)));
+
+ macro_list[macro_list_len] = (MACRO_DEF *)xmalloc (sizeof (MACRO_DEF));
+ macro_list[macro_list_len + 1] = (MACRO_DEF *)NULL;
+
+ def = macro_list[macro_list_len];
+ macro_list_len += 1;
+ def->name = name;
+ }
+ else
+ {
+ char *temp_filename = input_filename;
+ int temp_line = line_number;
+
+ warning ("The macro `%s' is previously defined", name);
+
+ input_filename = def->source_file;
+ line_number = def->source_lineno;
+
+ warning ("Here is the previous definition of `%s'", name);
+
+ input_filename = temp_filename;
+ line_number = temp_line;
+
+ if (def->arglist)
+ {
+ register int i;
+
+ for (i = 0; def->arglist[i]; i++)
+ free (def->arglist[i]);
+
+ free (def->arglist);
+ }
+ free (def->source_file);
+ free (def->body);
+ }
+
+ def->source_file = strdup (source_file);
+ def->source_lineno = source_lineno;
+ def->body = body;
+ def->arglist = arglist;
+ def->inhibited = 0;
+ def->flags = flags;
+}
+
+/* Delete the macro with name NAME. The macro is deleted from the list,
+ but it is also returned. If there was no macro defined, NULL is
+ returned. */
+MACRO_DEF *
+delete_macro (name)
+ char *name;
+{
+ register int i;
+ register MACRO_DEF *def;
+
+ def = (MACRO_DEF *)NULL;
+
+ for (i = 0; macro_list && (def = macro_list[i]); i++)
+ if (strcmp (def->name, name) == 0)
+ {
+ memmove (macro_list + i, macro_list + i + 1,
+ ((macro_list_len + 1) - i) * sizeof (MACRO_DEF *));
+ break;
+ }
+ return (def);
+}
+
+/* Return the arglist on the current line. This can behave in two different
+ ways, depending on the variable BRACES_REQUIRED_FOR_MACRO_ARGS. */
+int braces_required_for_macro_args = 0;
+
+char **
+get_macro_args (def)
+ MACRO_DEF *def;
+{
+ register int i;
+ char *word;
+
+ /* Quickly check to see if this macro has been invoked with any arguments.
+ If not, then don't skip any of the following whitespace. */
+ for (i = input_text_offset; i < size_of_input_text; i++)
+ if (!cr_or_whitespace (input_text[i]))
+ break;
+
+ if (input_text[i] != '{')
+ {
+ if (braces_required_for_macro_args)
+ {
+ return ((char **)NULL);
+ }
+ else
+ {
+ /* Braces are not required to fill out the macro arguments. If
+ this macro takes one argument, it is considered to be the
+ remainder of the line, sans whitespace. */
+ if (def->arglist && def->arglist[0] && !def->arglist[1])
+ {
+ char **arglist;
+
+ get_rest_of_line (&word);
+ if (input_text[input_text_offset - 1] == '\n')
+ input_text_offset--;
+ /* canon_white (word); */
+ arglist = (char **)xmalloc (2 * sizeof (char *));
+ arglist[0] = word;
+ arglist[1] = (char *)NULL;
+ return (arglist);
+ }
+ else
+ {
+ /* The macro either took no arguments, or took more than
+ one argument. In that case, it must be invoked with
+ arguments surrounded by braces. */
+ return ((char **)NULL);
+ }
+ }
+ }
+ return (get_brace_args (def->flags & ME_QUOTE_ARG));
+}
+
+/* Substitute actual parameters for named parameters in body.
+ The named parameters which appear in BODY must by surrounded
+ reverse slashes, as in \foo\. */
+char *
+apply (named, actuals, body)
+ char **named, **actuals, *body;
+{
+ register int i;
+ int new_body_index, new_body_size;
+ char *new_body, *text;
+ int length_of_actuals;
+
+ length_of_actuals = array_len (actuals);
+ new_body_size = strlen (body);
+ new_body = (char *)xmalloc (1 + new_body_size);
+
+ /* Copy chars from BODY into NEW_BODY. */
+ i = 0; new_body_index = 0;
+
+ while (1)
+ {
+ if (!body[i])
+ break;
+
+ if (body[i] != '\\')
+ new_body[new_body_index++] = body[i++];
+ else
+ {
+ /* Snarf parameter name, check against named parameters. */
+ char *param;
+ int param_start, which, len;
+
+ param_start = ++i;
+ while ((body[i]) && (body[i] != '\\'))
+ i++;
+
+ len = i - param_start;
+ param = (char *)xmalloc (1 + len);
+ memcpy (param, body + param_start, len);
+ param[len] = '\0';
+
+ if (body[i])
+ i++;
+
+ /* Now check against named parameters. */
+ for (which = 0; named && named[which]; which++)
+ if (strcmp (named[which], param) == 0)
+ break;
+
+ if (named[which])
+ {
+ if (which < length_of_actuals)
+ text = actuals[which];
+ else
+ text = (char *)NULL;
+
+ if (!text)
+ text = "";
+
+ len = strlen (text);
+ }
+ else
+ {
+ len += 2;
+ text = (char *)xmalloc (1 + len);
+ sprintf (text, "\\%s\\", param);
+ }
+
+ if ((2 + strlen (param)) < len)
+ new_body = (char *)xrealloc
+ (new_body, new_body_size += (1 + len));
+
+ free (param);
+
+ strcpy (new_body + new_body_index, text);
+ new_body_index += len;
+
+ if (!named[which])
+ free (text);
+ }
+ }
+ new_body[new_body_index] = '\0';
+ return (new_body);
+}
+
+/* Execute the macro passed in DEF, a pointer to a MACRO_DEF. */
+void
+execute_macro (def)
+ MACRO_DEF *def;
+{
+ register int i;
+ char **arglist;
+ int num_args;
+ char *execution_string = (char *)NULL;
+
+ if (macro_expansion_output_stream && !me_inhibit_expansion)
+ me_append_before_this_command ();
+
+ /* Find out how many arguments this macro definition takes. */
+ num_args = array_len (def->arglist);
+
+ /* Gather the arguments present on the line if there are any. */
+ arglist = get_macro_args (def);
+
+ if (num_args < array_len (arglist))
+ {
+ free_array (arglist);
+ line_error ("Macro `%s' called with too many args", def->name);
+ return;
+ }
+
+ if (def->body)
+ execution_string = apply (def->arglist, arglist, def->body);
+
+ free_array (arglist);
+
+ if (def->body)
+ {
+ if (macro_expansion_output_stream && !me_inhibit_expansion)
+ {
+ remember_itext (input_text, input_text_offset);
+ me_execute_string (execution_string);
+ }
+ else
+ execute_string ("%s", execution_string);
+
+ free (execution_string);
+ }
+}
+
+/* Read and remember the definition of a macro. */
+void
+cm_macro ()
+{
+ register int i;
+ char *name, **arglist, *body, *line;
+ int body_size, body_index;
+ int depth = 1;
+ int defining_line = line_number;
+ int flags = 0;
+
+ arglist = (char **)NULL;
+ body = (char *)NULL;
+ body_size = 0;
+ body_index = 0;
+
+ if (macro_expansion_output_stream)
+ me_append_before_this_command ();
+
+ skip_whitespace ();
+
+ /* Get the name of the macro. This is the set of characters which are
+ not whitespace and are not `{' immediately following the @macro. */
+ {
+ int start = input_text_offset;
+ int len;
+
+ for (i = start;
+ (i < size_of_input_text) &&
+ (input_text[i] != '{') &&
+ (!cr_or_whitespace (input_text[i]));
+ i++);
+
+ len = i - start;
+ name = (char *)xmalloc (1 + len);
+ strncpy (name, input_text + start, len);
+ name[len] = '\0';
+ input_text_offset = i;
+ }
+
+ skip_whitespace ();
+
+ /* It is not required that the definition of a macro includes an arglist.
+ If not, don't try to get the named parameters, just use a null list. */
+ if (curchar () == '{')
+ {
+ int arglist_index = 0, arglist_size = 0;
+ int gathering_words = 1;
+ char *word = (char *)NULL;
+ int character;
+
+ /* Read the words inside of the braces which determine the arglist.
+ These words will be replaced within the body of the macro at
+ execution time. */
+
+ input_text_offset++;
+ skip_whitespace_and_newlines ();
+
+ while (gathering_words)
+ {
+ int len;
+
+ for (i = input_text_offset;
+ character = input_text[i];
+ i++)
+ {
+ switch (character)
+ {
+ case '\n':
+ line_number++;
+ case ' ':
+ case '\t':
+ case ',':
+ case '}':
+ /* Found the end of the current arglist word. Save it. */
+ len = i - input_text_offset;
+ word = (char *)xmalloc (1 + len);
+ strncpy (word, input_text + input_text_offset, len);
+ word[len] = '\0';
+ input_text_offset = i;
+
+ /* Advance to the comma or close-brace that signified
+ the end of the argument. */
+ while ((character = curchar ())
+ && character != ','
+ && character != '}')
+ {
+ input_text_offset++;
+ if (character == '\n')
+ line_number++;
+ }
+
+ /* Add the word to our list of words. */
+ if ((arglist_index + 2) >= arglist_size)
+ arglist = (char **)xrealloc
+ (arglist, (arglist_size += 10) * sizeof (char *));
+
+ arglist[arglist_index++] = word;
+ arglist[arglist_index] = (char *)NULL;
+ break;
+ }
+
+ if (character == '}')
+ {
+ input_text_offset++;
+ gathering_words = 0;
+ break;
+ }
+
+ if (character == ',')
+ {
+ input_text_offset++;
+ skip_whitespace_and_newlines ();
+ i = input_text_offset - 1;
+ }
+ }
+ }
+ }
+
+ /* Read the text carefully until we find an "@end macro" which
+ matches this one. The text in between is the body of the macro. */
+ skip_whitespace_and_newlines ();
+
+ while (depth)
+ {
+ if ((input_text_offset + 9) > size_of_input_text)
+ {
+ int temp_line = line_number;
+ line_number = defining_line;
+ line_error ("%cend macro not found", COMMAND_PREFIX);
+ line_number = temp_line;
+ return;
+ }
+
+ get_rest_of_line (&line);
+
+ /* Handle commands only meaningful within a macro. */
+ if ((*line == COMMAND_PREFIX) && (depth == 1) &&
+ (strncmp (line + 1, "allow-recursion", 15) == 0) &&
+ (line[16] == '\0' || whitespace (line[16])))
+ {
+ for (i = 16; whitespace (line[i]); i++);
+ strcpy (line, line + i);
+ flags |= ME_RECURSE;
+ if (!*line)
+ {
+ free (line);
+ continue;
+ }
+ }
+
+ if ((*line == COMMAND_PREFIX) && (depth == 1) &&
+ (strncmp (line + 1, "quote-arg", 9) == 0) &&
+ (line[10] == '\0' || whitespace (line[10])))
+ {
+ for (i = 10; whitespace (line[i]); i++);
+ strcpy (line, line + i);
+
+ if (arglist && arglist[0] && !arglist[1])
+ {
+ flags |= ME_QUOTE_ARG;
+ if (!*line)
+ {
+ free (line);
+ continue;
+ }
+ }
+ else
+ {
+ line_error ("%cquote-arg only useful when the macro takes a single argument",
+ COMMAND_PREFIX);
+ }
+ }
+
+ if ((*line == COMMAND_PREFIX) &&
+ (strncmp (line + 1, "macro ", 6) == 0))
+ depth++;
+
+ if ((*line == COMMAND_PREFIX) &&
+ (strncmp (line + 1, "end macro", 9) == 0))
+ depth--;
+
+ if (depth)
+ {
+ if ((body_index + strlen (line) + 3) >= body_size)
+ body = (char *)xrealloc
+ (body, body_size += 3 + strlen (line));
+ strcpy (body + body_index, line);
+ body_index += strlen (line);
+ body[body_index++] = '\n';
+ body[body_index] = '\0';
+ }
+ free (line);
+ }
+
+ /* We now have the name, the arglist, and the body. However, BODY
+ includes the final newline which preceded the `@end macro' text.
+ Delete it. */
+ if (body && strlen (body))
+ body[strlen (body) - 1] = '\0';
+
+ add_macro (name, arglist, body, input_filename, defining_line, flags);
+
+ if (macro_expansion_output_stream)
+ remember_itext (input_text, input_text_offset);
+}
+
+void
+cm_unmacro ()
+{
+ register int i;
+ char *line, *name;
+ MACRO_DEF *def;
+
+ if (macro_expansion_output_stream)
+ me_append_before_this_command ();
+
+ get_rest_of_line (&line);
+ canon_white (line);
+
+ for (i = 0; line[i] && !whitespace (line[i]); i++);
+ name = (char *)xmalloc (i);
+ strncpy (name, line, i);
+ name[i] = '\0';
+
+ def = delete_macro (name);
+
+ if (def)
+ {
+ free (def->source_file);
+ free (def->name);
+ free (def->body);
+
+ if (def->arglist)
+ {
+ register int i;
+
+ for (i = 0; def->arglist[i]; i++)
+ free (def->arglist[i]);
+
+ free (def->arglist);
+ }
+
+ free (def);
+ }
+
+ free (line);
+ free (name);
+
+ if (macro_expansion_output_stream)
+ remember_itext (input_text, input_text_offset);
+}
+
+/* How to output sections of the input file verbatim. */
+
+/* Set the value of POINTER's offset to OFFSET. */
+ITEXT *
+remember_itext (pointer, offset)
+ char *pointer;
+ int offset;
+{
+ register int i;
+ ITEXT *itext = (ITEXT *)NULL;
+
+ /* If we have no info, initialize a blank list. */
+ if (!itext_info)
+ {
+ itext_info = (ITEXT **)xmalloc ((itext_size = 10) * sizeof (ITEXT *));
+ for (i = 0; i < itext_size; i++)
+ itext_info[i] = (ITEXT *)NULL;
+ }
+
+ /* If the pointer is already present in the list, then set the offset. */
+ for (i = 0; i < itext_size; i++)
+ if ((itext_info[i] != (ITEXT *)NULL) &&
+ (itext_info[i]->pointer == pointer))
+ {
+ itext = itext_info[i];
+ itext_info[i]->offset = offset;
+ break;
+ }
+
+ if (i == itext_size)
+ {
+ /* Find a blank slot, (or create a new one), and remember the
+ pointer and offset. */
+ for (i = 0; i < itext_size; i++)
+ if (itext_info[i] == (ITEXT *)NULL)
+ break;
+
+ /* If not found, then add some slots. */
+ if (i == itext_size)
+ {
+ register int j;
+
+ itext_info = (ITEXT **)xrealloc
+ (itext_info, (itext_size += 10) * sizeof (ITEXT *));
+
+ for (j = i; j < itext_size; j++)
+ itext_info[j] = (ITEXT *)NULL;
+ }
+
+ /* Now add the pointer and the offset. */
+ itext_info[i] = (ITEXT *)xmalloc (sizeof (ITEXT));
+ itext_info[i]->pointer = pointer;
+ itext_info[i]->offset = offset;
+ itext = itext_info[i];
+ }
+ return (itext);
+}
+
+/* Forget the input text associated with POINTER. */
+void
+forget_itext (pointer)
+ char *pointer;
+{
+ register int i;
+
+ for (i = 0; i < itext_size; i++)
+ if (itext_info[i] && (itext_info[i]->pointer == pointer))
+ {
+ free (itext_info[i]);
+ itext_info[i] = (ITEXT *)NULL;
+ break;
+ }
+}
+
+/* Append the text which appeared in input_text from the last offset to
+ the character just before the command that we are currently executing. */
+void
+me_append_before_this_command ()
+{
+ register int i;
+
+ for (i = input_text_offset; i && (input_text[i] != COMMAND_PREFIX); i--);
+ maybe_write_itext (input_text, i);
+}
+
+/* Similar to execute_string (), but only takes a single string argument,
+ and remembers the input text location, etc. */
+void
+me_execute_string (execution_string)
+ char *execution_string;
+{
+ pushfile ();
+ input_text_offset = 0;
+ input_text = execution_string;
+ input_filename = strdup (input_filename);
+ size_of_input_text = strlen (execution_string);
+
+ remember_itext (execution_string, 0);
+
+ executing_string++;
+ reader_loop ();
+ popfile ();
+ executing_string--;
+}
+
+/* Append the text which appears in input_text from the last offset to
+ the current OFFSET. */
+void
+append_to_expansion_output (offset)
+ int offset;
+{
+ register int i;
+ ITEXT *itext = (ITEXT *)NULL;
+
+ for (i = 0; i < itext_size; i++)
+ if (itext_info[i] && itext_info[i]->pointer == input_text)
+ {
+ itext = itext_info[i];
+ break;
+ }
+
+ if (!itext)
+ itext = remember_itext (input_text, 0);
+
+ if (offset > itext->offset)
+ {
+ write_region_to_macro_output
+ (input_text, itext->offset, offset);
+ remember_itext (input_text, offset);
+ }
+}
+
+/* Only write this input text iff it appears in our itext list. */
+void
+maybe_write_itext (pointer, offset)
+ char *pointer;
+ int offset;
+{
+ register int i;
+ ITEXT *itext = (ITEXT *)NULL;
+
+ for (i = 0; i < itext_size; i++)
+ if (itext_info[i] && (itext_info[i]->pointer == pointer))
+ {
+ itext = itext_info[i];
+ break;
+ }
+
+ if (itext && (itext->offset < offset))
+ {
+ write_region_to_macro_output (itext->pointer, itext->offset, offset);
+ remember_itext (pointer, offset);
+ }
+}
+
+void
+write_region_to_macro_output (string, start, end)
+ char *string;
+ int start, end;
+{
+ if (macro_expansion_output_stream)
+ fwrite (string + start, 1, end - start, macro_expansion_output_stream);
+}
+
+#endif /* HAVE_MACROS */
+
+/* Return the length of the array in ARRAY. */
+int
+array_len (array)
+ char **array;
+{
+ register int i = 0;
+
+ if (array)
+ for (i = 0; array[i] != (char *)NULL; i++);
+
+ return (i);
+}
+
+void
+free_array (array)
+ char **array;
+{
+ if (array)
+ {
+ register int i;
+
+ for (i = 0; array[i] != (char *)NULL; i++)
+ free (array[i]);
+
+ free (array);
+ }
+}
+
+/* Function is used even when we don't have macros. Although, I have
+ to admit, it is unlikely that you would have a use for it if you
+ aren't using macros. */
+char **
+get_brace_args (quote_single)
+ int quote_single;
+{
+ char **arglist, *word;
+ int arglist_index, arglist_size;
+ int character, escape_seen, start;
+ int depth = 1;
+
+ /* There is an arglist in braces here, so gather the args inside of it. */
+ skip_whitespace_and_newlines ();
+ input_text_offset++;
+ arglist = (char **)NULL;
+ arglist_index = arglist_size = 0;
+
+ get_arg:
+ skip_whitespace_and_newlines ();
+ start = input_text_offset;
+ escape_seen = 0;
+
+ while (character = curchar ())
+ {
+ if (character == '\\')
+ {
+ input_text_offset += 2;
+ escape_seen = 1;
+ }
+ else if (character == '{')
+ {
+ depth++;
+ input_text_offset++;
+ }
+ else if ((character == ',' && !quote_single) ||
+ ((character == '}') && depth == 1))
+ {
+ int len = input_text_offset - start;
+
+ if (len || (character != '}'))
+ {
+ word = (char *)xmalloc (1 + len);
+ strncpy (word, input_text + start, len);
+ word[len] = '\0';
+
+ /* Clean up escaped characters. */
+ if (escape_seen)
+ {
+ register int i;
+
+ for (i = 0; word[i]; i++)
+ if (word[i] == '\\')
+ memmove (word + i, word + i + 1,
+ 1 + strlen (word + i + 1));
+ }
+
+ if (arglist_index + 2 >= arglist_size)
+ arglist = (char **)xrealloc
+ (arglist, (arglist_size += 10) * sizeof (char *));
+
+ arglist[arglist_index++] = word;
+ arglist[arglist_index] = (char *)NULL;
+ }
+
+ input_text_offset++;
+ if (character == '}')
+ break;
+ else
+ goto get_arg;
+ }
+ else if (character == '}')
+ {
+ depth--;
+ input_text_offset++;
+ }
+ else
+ {
+ input_text_offset++;
+ if (character == '\n') line_number++;
+ }
+ }
+ return (arglist);
+}
+
+/* **************************************************************** */
+/* */
+/* Looking For Include Files */
+/* */
+/* **************************************************************** */
+
+/* Given a string containing units of information separated by colons,
+ return the next one pointed to by INDEX, or NULL if there are no more.
+ Advance INDEX to the character after the colon. */
+char *
+extract_colon_unit (string, index)
+ char *string;
+ int *index;
+{
+ int i, start;
+
+ i = *index;
+
+ if (!string || (i >= strlen (string)))
+ return ((char *)NULL);
+
+ /* Each call to this routine leaves the index pointing at a colon if
+ there is more to the path. If I is > 0, then increment past the
+ `:'. If I is 0, then the path has a leading colon. Trailing colons
+ are handled OK by the `else' part of the if statement; an empty
+ string is returned in that case. */
+ if (i && string[i] == ':')
+ i++;
+
+ start = i;
+
+ while (string[i] && string[i] != ':') i++;
+
+ *index = i;
+
+ if (i == start)
+ {
+ if (string[i])
+ (*index)++;
+
+ /* Return "" in the case of a trailing `:'. */
+ return (strdup (""));
+ }
+ else
+ {
+ char *value;
+
+ value = (char *)xmalloc (1 + (i - start));
+ strncpy (value, &string[start], (i - start));
+ value [i - start] = '\0';
+
+ return (value);
+ }
+}
+
+/* Return the full pathname for FILENAME by searching along PATH.
+ When found, return the stat () info for FILENAME in FINFO.
+ If PATH is NULL, only the current directory is searched.
+ If the file could not be found, return a NULL pointer. */
+char *
+get_file_info_in_path (filename, path, finfo)
+ char *filename, *path;
+ struct stat *finfo;
+{
+ char *dir;
+ int result, index = 0;
+
+ if (path == (char *)NULL)
+ path = ".";
+
+ /* Handle absolute pathnames. "./foo", "/foo", "../foo". */
+ if (*filename == '/' ||
+ (*filename == '.' &&
+ (filename[1] == '/' ||
+ (filename[1] == '.' && filename[2] == '/'))))
+ {
+ if (stat (filename, finfo) == 0)
+ return (strdup (filename));
+ else
+ return ((char *)NULL);
+ }
+
+ while (dir = extract_colon_unit (path, &index))
+ {
+ char *fullpath;
+
+ if (!*dir)
+ {
+ free (dir);
+ dir = strdup (".");
+ }
+
+ fullpath = (char *)xmalloc (2 + strlen (dir) + strlen (filename));
+ sprintf (fullpath, "%s/%s", dir, filename);
+ free (dir);
+
+ result = stat (fullpath, finfo);
+
+ if (result == 0)
+ return (fullpath);
+ else
+ free (fullpath);
+ }
+ return ((char *)NULL);
+}
diff --git a/contrib/texinfo/makeinfo/makeinfo.h b/contrib/texinfo/makeinfo/makeinfo.h
new file mode 100644
index 0000000..610d39b
--- /dev/null
+++ b/contrib/texinfo/makeinfo/makeinfo.h
@@ -0,0 +1,193 @@
+/* makeinfo.h -- Declarations for Makeinfo.
+ $Id: makeinfo.h,v 1.2 1996/07/21 11:21:45 karl Exp $
+
+ Copyright (C) 1996 Free Software Foundation, Inc.
+
+ 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Written by Brian Fox (bfox@ai.mit.edu). */
+
+/* Why, oh why, did I ever listen to rms when he said:
+ "Don't make lots of small files, just make one big one!" I've
+ regretted it ever since with this program, and with readline.
+ bfox@ai.mit.edu Thu Jul 11 07:54:32 1996 */
+
+#if !defined (MAKEINFO_H)
+#define MAKEINFO_H
+
+#if defined (COMPILING_MAKEINFO)
+# define DECLARE(type, var, init) type var = init
+#else
+# define DECLARE(type, var, init) extern type var
+#endif
+
+enum insertion_type
+{
+ menu, detailmenu, quotation, lisp, smalllisp, example, smallexample,
+ display, itemize, format, enumerate, cartouche, multitable, table,
+ ftable, vtable, group, ifinfo, flushleft, flushright, ifset,
+ ifclear, deffn, defun, defmac, defspec, defvr, defvar, defopt,
+ deftypefn, deftypefun, deftypevr, deftypevar, defcv, defivar, defop,
+ defmethod, deftypemethod, deftp, direntry, bad_type
+};
+
+DECLARE (int, insertion_level, 0);
+
+#if defined (COMPILING_MAKEINFO)
+char *insertion_type_names[] =
+{
+ "menu", "detailmenu", "quotation", "lisp", "smalllisp", "example",
+ "smallexample", "display", "itemize", "format", "enumerate",
+ "cartouche", "multitable", "table", "ftable", "vtable", "group",
+ "ifinfo", "flushleft", "flushright", "ifset", "ifclear", "deffn",
+ "defun", "defmac", "defspec", "defvr", "defvar", "defopt",
+ "deftypefn", "deftypefun", "deftypevr", "deftypevar", "defcv",
+ "defivar", "defop", "defmethod", "deftypemethod", "deftp", "direntry",
+ "bad_type"
+};
+#endif
+
+typedef struct istack_elt
+{
+ struct istack_elt *next;
+ char *item_function;
+ char *filename;
+ int line_number;
+ int filling_enabled;
+ int indented_fill;
+ enum insertion_type insertion;
+ int inhibited;
+ int in_fixed_width_font;
+} INSERTION_ELT;
+
+DECLARE (INSERTION_ELT *, insertion_stack, (INSERTION_ELT *)NULL);
+
+/* Current output stream. */
+DECLARE (FILE *, output_stream, (FILE *)NULL);
+
+/* Output paragraph buffer. */
+DECLARE (unsigned char *, output_paragraph, (unsigned char *)NULL);
+
+/* Offset into OUTPUT_PARAGRAPH. */
+DECLARE (int, output_paragraph_offset, 0);
+
+/* The output paragraph "cursor" horizontal position. */
+DECLARE (int, output_column, 0);
+
+/* Non-zero means output_paragraph contains text. */
+DECLARE (int, paragraph_is_open, 0);
+
+/* The amount of indentation to apply at the start of each line. */
+DECLARE (int, current_indent, 0);
+
+/* nonzero if we are currently processing a multitable command */
+DECLARE (int, multitable_active, 0);
+
+/* The column at which long lines are broken. */
+DECLARE (int, fill_column, 72);
+
+/* The current input file state. */
+DECLARE (char *, input_filename, (char *)NULL);
+DECLARE (char *, input_text, (char *)NULL);
+DECLARE (int, size_of_input_text, 0);
+DECLARE (int, input_text_offset, 0);
+DECLARE (int, line_number, 0);
+
+#define curchar() input_text[input_text_offset]
+/* **************************************************************** */
+/* */
+/* Global Defines */
+/* */
+/* **************************************************************** */
+
+/* Error levels */
+#define NO_ERROR 0
+#define SYNTAX 2
+#define FATAL 4
+
+/* C's standard macros don't check to make sure that the characters being
+ changed are within range. So I have to check explicitly. */
+
+/* GNU Library doesn't have toupper(). Until GNU gets this fixed, I will
+ have to do it. */
+#ifndef toupper
+#define toupper(c) ((c) - 32)
+#endif
+
+#define coerce_to_upper(c) ((islower(c) ? toupper(c) : (c)))
+#define coerce_to_lower(c) ((isupper(c) ? tolower(c) : (c)))
+
+#define control_character_bit 0x40 /* %01000000, must be off. */
+#define meta_character_bit 0x080/* %10000000, must be on. */
+#define CTL(c) ((c) & (~control_character_bit))
+#define UNCTL(c) coerce_to_upper(((c)|control_character_bit))
+#define META(c) ((c) | (meta_character_bit))
+#define UNMETA(c) ((c) & (~meta_character_bit))
+
+#define whitespace(c) (((c) == '\t') || ((c) == ' '))
+#define sentence_ender(c) ((c) == '.' || (c) == '?' || (c) == '!')
+#define cr_or_whitespace(c) (((c) == '\t') || ((c) == ' ') || ((c) == '\n'))
+
+#ifndef isletter
+#define isletter(c) (((c) >= 'A' && (c) <= 'Z') || ((c) >= 'a' && (c) <= 'z'))
+#endif
+
+#ifndef isupper
+#define isupper(c) ((c) >= 'A' && (c) <= 'Z')
+#endif
+
+#ifndef isdigit
+#define isdigit(c) ((c) >= '0' && (c) <= '9')
+#endif
+
+#ifndef digit_value
+#define digit_value(c) ((c) - '0')
+#endif
+
+#define member(c, s) (strchr (s, c) != NULL)
+
+#define COMMAND_PREFIX '@'
+
+/* Stuff for splitting large files. */
+#define SPLIT_SIZE_THRESHOLD 70000 /* What's good enough for Stallman... */
+#define DEFAULT_SPLIT_SIZE 50000 /* Is probably good enough for me. */
+
+DECLARE (int, splitting, 1); /* Defaults to true for now. */
+
+typedef void COMMAND_FUNCTION (); /* So I can say COMMAND_FUNCTION *foo; */
+
+#define command_char(c) ((!whitespace(c)) && \
+ ((c) != '\n') && \
+ ((c) != '{') && \
+ ((c) != '}') && \
+ ((c) != '='))
+
+#define skip_whitespace() \
+ while ((input_text_offset != size_of_input_text) && \
+ whitespace (curchar())) \
+ input_text_offset++
+
+#define skip_whitespace_and_newlines() \
+ do { \
+ while ((input_text_offset != size_of_input_text) && \
+ (whitespace (curchar ()) || (curchar () == '\n'))) \
+ { \
+ if (curchar () == '\n') \
+ line_number++; \
+ input_text_offset++; \
+ } \
+ } while (0)
+
+#endif /* !MAKEINFO_H */
diff --git a/contrib/texinfo/makeinfo/makeinfo.texi b/contrib/texinfo/makeinfo/makeinfo.texi
new file mode 100644
index 0000000..f379ae0
--- /dev/null
+++ b/contrib/texinfo/makeinfo/makeinfo.texi
@@ -0,0 +1,303 @@
+\input texinfo @c -*-texinfo-*-
+@comment %**start of header
+@setfilename makeinfo.info
+@set VERSION 1.61
+@paragraphindent none
+@comment %**start of header
+@comment $Id: makeinfo.texi,v 1.2 1996/09/28 21:49:18 karl Exp $
+
+@dircategory Texinfo documentation system
+@direntry
+* makeinfo: (makeinfo). Convert Texinfo source to Info or plain ASCII.
+@end direntry
+
+@ifinfo
+This file is an extract from the @cite{Texinfo} manual.@*
+It documents Makeinfo, a program that converts Texinfo
+files into Info files.
+
+Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc.
+
+Permission is granted to make and distribute verbatim copies of
+this manual provided the copyright notice and this permission notice
+are preserved on all copies.
+
+@ignore
+Permission is granted to process this file through TeX and print the
+results, provided the printed document carries copying permission
+notice identical to this one except for the removal of this paragraph
+(this paragraph not being relevant to the printed manual).
+
+@end ignore
+Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, provided that the entire
+resulting derived work is distributed under the terms of a permission
+notice identical to this one.
+
+Permission is granted to copy and distribute translations of this manual
+into another language, under the above conditions for modified versions,
+except that this permission notice may be stated in a translation approved
+by the Free Software Foundation.
+@end ifinfo
+
+@titlepage
+@title GNU Makeinfo
+@author Brian J. Fox and Robert J. Chassell
+
+@page
+@vskip 0pt plus 1filll
+Copyright @copyright{} 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
+
+Permission is granted to make and distribute verbatim copies of
+this manual provided the copyright notice and this permission notice
+are preserved on all copies.
+
+Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, provided that the entire
+resulting derived work is distributed under the terms of a permission
+notice identical to this one.
+
+Permission is granted to copy and distribute translations of this manual
+into another language, under the above conditions for modified versions,
+except that this permission notice may be stated in a translation approved
+by the Free Software Foundation.
+@end titlepage
+
+@node Top
+@chapter What is @code{makeinfo}?
+
+@iftex
+This file documents the use of the @code{makeinfo} program, versions
+@value{VERSION} and later. It is an extract from the @cite{Texinfo} manual.
+@end iftex
+
+@code{makeinfo} is a program for converting @dfn{Texinfo} files into @dfn{Info}
+files. Texinfo is a documentation system that uses a single source file to
+produce both on-line information and printed output.
+
+You can read the on-line information using Info; type @code{info} to
+learn about Info.
+@ifinfo
+@xref{Top, Texinfo, Overview of Texinfo, Texinfo, Texinfo},
+@end ifinfo
+@iftex
+See the @cite{Texinfo} manual,
+@end iftex
+to learn about the Texinfo documentation system.
+
+@menu
+* Formatting Control:: Controlling the width of lines, paragraph
+ indentation, and other similar formatting.
+
+* Options:: Command line options which control the
+ behaviour of Makeinfo.
+
+* Pointer Validation:: How Makeinfo can help you to track node
+ references through complex Texinfo files.
+
+* Index:: Index of Concepts.
+@end menu
+
+@c Removed this for 3.8 until it's time to rewrite it.
+@c * The Macro Facility:: Makeinfo allows the use of @dfn{macros}.
+
+@node Formatting Control
+@section Controlling Paragraph Formats
+
+Without any special options, @code{makeinfo} @dfn{fills} the paragraphs that
+it outputs to an Info file. Filling is the process of breaking and connecting
+lines so that lines are the same length as or shorter than the number
+specified as the fill column. Lines are broken between words. With
+@code{makeinfo}, you can control:
+
+@itemize @bullet
+@item
+The width of each paragraph (the @dfn{fill-column}).
+@item
+The amount of indentation that the first line of
+each paragraph receives (the @dfn{paragraph-indentation}).
+@end itemize
+
+@node Options
+@section Command Line Options
+
+The following command line options are available for @code{makeinfo}.
+
+@need 100
+@table @code
+@item -D @var{var}
+Cause @var{var} to be defined. This is equivalent to
+@code{@@set @var{var}} in the Texinfo file.
+
+@need 150
+@item --error-limit @var{limit}
+Set the maximum number of errors that @code{makeinfo} will report
+before exiting (on the assumption that continuing would be useless).
+The default number of errors that can be reported before
+@code{makeinfo} gives up is 100.@refill
+
+@need 150
+@item --fill-column @var{width}
+Specify the maximum number of columns in a line; this is the right-hand
+edge of a line. Paragraphs that are filled will be filled to this
+width. The default value for @code{fill-column} is 72.
+@refill
+
+@item --footnote-style @var{style}
+Set the footnote style to @var{style}, either @samp{end} for the end
+node style or @samp{separate} for the separate node style. The value
+set by this option overrides the value set in a Texinfo file by an
+@code{@@footnotestyle} command. When the footnote style is
+@samp{separate}, @code{makeinfo} makes a new node containing the
+footnotes found in the current node. When the footnote style is
+@samp{end}, @code{makeinfo} places the footnote references at the end
+of the current node.@refill
+
+@need 150
+@item -I @var{dir}
+Add @code{dir} to the directory search list for finding files that are
+included using the @code{@@include} command. By default,
+@code{makeinfo} searches only the current directory.
+
+@need 150
+@item --no-headers
+Do not include menus or node lines in the output. This results in an
+@sc{ascii} file that you cannot read in Info since it does not contain
+the requisite nodes or menus; but you can print such a file in a
+single, typewriter-like font and produce acceptable output.
+
+@need 150
+@item --no-split
+Suppress the splitting stage of @code{makeinfo}. Normally, large
+output files (where the size is greater than 70k bytes) are split into
+smaller subfiles, each one approximately 50k bytes. If you specify
+@samp{--no-split}, @code{makeinfo} will not split up the output
+file.@refill
+
+@need 100
+@item --no-pointer-validate
+@item --no-validate
+Suppress the pointer-validation phase of @code{makeinfo}. Normally,
+after a Texinfo file is processed, some consistency checks are made to
+ensure that cross references can be resolved, etc.
+@xref{Pointer Validation}.@refill
+
+@need 150
+@item --no-warn
+Suppress the output of warning messages. This does @emph{not}
+suppress the output of error messages, only warnings. You might
+want this if the file you are creating has examples of Texinfo cross
+references within it, and the nodes that are referenced do not actually
+exist.@refill
+
+@item --no-number-footnotes
+Supress automatic footnote numbering. By default, @code{makeinfo}
+numbers each footnote sequentially in a single node, resetting the
+current footnote number to 1 at the start of each node.
+
+@need 150
+@item --output @var{file}
+@itemx -o @var{file}
+Specify that the output should be directed to @var{file} and not to the
+file name specified in the @code{@@setfilename} command found in the Texinfo
+source. @var{file} can be the special token @samp{-}, which specifies
+standard output.
+
+@need 150
+@item --paragraph-indent @var{indent}
+Set the paragraph indentation style to @var{indent}. The value set by
+this option overrides the value set in a Texinfo file by an
+@code{@@paragraphindent} command. The value of @var{indent} is
+interpreted as follows:@refill
+
+@itemize @bullet
+@item
+If the value of @var{indent} is @samp{asis}, do not change the
+existing indentation at the starts of paragraphs.@refill
+
+@item
+If the value of @var{indent} is zero, delete any existing
+indentation.@refill
+
+@item
+If the value of @var{indent} is greater than zero, indent each
+paragraph by that number of spaces.@refill
+@end itemize
+
+@need 100
+@item --reference-limit @var{limit}
+Set the value of the number of references to a node that
+@code{makeinfo} will make without reporting a warning. If a node has more
+than this number of references in it, @code{makeinfo} will make the
+references but also report a warning.@refill
+
+@need 150
+@item -U @var{var}
+Cause @var{var} to be undefined. This is equivalent to
+@code{@@clear @var{var}} in the Texinfo file.
+
+@need 100
+@item --verbose
+Cause @code{makeinfo} to display messages saying what it is doing.
+Normally, @code{makeinfo} only outputs messages if there are errors or
+warnings.@refill
+
+@need 100
+@item --version
+Report the version number of this copy of @code{makeinfo}.@refill
+
+@item --help
+Show a summary of the commend line arguments to @code{makeinfo}.
+@end table
+
+@node Pointer Validation
+@section Pointer Validation
+@cindex Pointer validation with @code{makeinfo}
+@cindex Validation of pointers
+
+If you do not suppress pointer-validation (by using the
+@samp{--no-pointer-validation} option), @code{makeinfo}
+will check the validity of the final Info file. Mostly,
+this means ensuring that nodes you have referenced
+really exist. Here is a complete list of what is
+checked:@refill
+
+@enumerate
+@item
+If a `Next', `Previous', or `Up' node reference is a reference to a
+node in the current file and is not an external reference such as to
+@file{(dir)}, then the referenced node must exist.@refill
+
+@item
+In every node, if the `Previous' node is different from the `Up' node,
+then the `Previous' node must also be pointed to by a `Next' node.@refill
+
+@item
+Every node except the `Top' node must have an `Up' pointer.@refill
+
+@item
+The node referenced by an `Up' pointer must contain a reference to the
+current node in some manner other than through a `Next' reference.
+This includes menu entries and cross references.@refill
+
+@item
+If the `Next' reference of a node is not the same as the `Next' reference
+of the `Up' reference, then the node referenced by the `Next' pointer
+must have a `Previous' pointer that points back to the current node.
+This rule allows the last node in a section to point to the first node
+of the next chapter.@refill
+@end enumerate
+
+@c We don't want to advertise redefining commands.
+@c lowersections
+@c include macro.texi
+@c raisesections
+
+@lowersections
+@node Index
+@appendix Index
+@printindex cp
+@raisesections
+
+@contents
+@bye
diff --git a/contrib/texinfo/makeinfo/multi.c b/contrib/texinfo/makeinfo/multi.c
new file mode 100644
index 0000000..0276ddc
--- /dev/null
+++ b/contrib/texinfo/makeinfo/multi.c
@@ -0,0 +1,418 @@
+/* multi.c -- Multitable stuff for makeinfo.
+ $Id: multi.c,v 1.7 1996/10/01 21:42:20 karl Exp $
+
+ Copyright (C) 1996 Free Software Foundation, Inc.
+
+ 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include <stdio.h>
+#include "makeinfo.h"
+
+#define MAXCOLS 100 /* remove this limit later @@ */
+
+
+/*
+ * Output environments. This is a hack grafted onto existing
+ * structure. The "output environment" used to consist of the
+ * global variables `output_paragraph', `fill_column', etc.
+ * Routines like add_char would manipulate these variables.
+ *
+ * Now, when formatting a multitable, we maintain separate environments
+ * for each column. That way we can build up the columns separately
+ * and write them all out at once. The "current" output environment"
+ * is still kept in those global variables, so that the old output
+ * routines don't have to change. But we provide routines to save
+ * and restore these variables in an "environment table". The
+ * `select_output_environment' function switches from one output
+ * environment to another.
+ *
+ * Environment #0 (i.e. element #0 of the table) is the regular
+ * environment that is used when we're not formatting a multitable.
+ *
+ * Environment #N (where N = 1,2,3,...) is the env. for column #N of
+ * the table, when a multitable is active.
+ */
+
+/* contents of an output environment */
+/* some more vars may end up being needed here later @@ */
+struct env
+{
+ unsigned char *output_paragraph;
+ int output_paragraph_offset;
+ int output_column;
+ int paragraph_is_open;
+ int current_indent;
+ int fill_column;
+} envs[MAXCOLS]; /* the environment table */
+
+/* index in environment table of currently selected environment */
+static int current_env_no;
+
+/* column number of last column in current multitable */
+static int last_column;
+
+/* flags indicating whether horizontal and vertical separators need
+ to be drawn, separating rows and columns in the current multitable. */
+static int hsep, vsep;
+
+void
+do_multitable ()
+{
+ int ncolumns;
+
+ /*
+ * multitable strategy:
+ * for each item {
+ * for each column in an item {
+ * initialize a new paragraph
+ * do ordinary formatting into the new paragraph
+ * save the paragraph away
+ * repeat if there are more paragraphs in the column
+ * }
+ * dump out the saved paragraphs and free the storage
+ * }
+ */
+
+ if (multitable_active)
+ {
+ line_error ("Multitables cannot be nested");
+ return;
+ }
+
+ /* scan the current item function to get the field widths
+ and number of columns, and set up the output environment list
+ accordingly. */
+ ncolumns = setup_multitable_parameters ();
+ if (hsep)
+ draw_horizontal_separator ();
+
+ /* The next @item command will direct stdout into the first column
+ and start processing. @tab will then switch to the next column,
+ and @item will flush out the saved output and return to the first
+ column. Environment #1 is the first column. (Environment #0 is
+ the normal output) */
+
+ ++multitable_active;
+}
+
+/* Read the parameters for a multitable from the current command
+ line, save the parameters away, and return the
+ number of columns. */
+int
+setup_multitable_parameters ()
+{
+ char *params = insertion_stack->item_function;
+ int nchars;
+ float columnfrac;
+ char command[200];
+ int i = 1;
+
+ /* We implement @hsep and @vsep even though TeX doesn't.
+ We don't get mixing of @columnfractions and templates right,
+ but TeX doesn't either. */
+ hsep = vsep = 0;
+
+ while (*params) {
+ while (whitespace (*params))
+ params++;
+
+ if (*params == '@') {
+ sscanf (params, "%s%n", command, &nchars);
+ params += nchars;
+ if (strcmp (command, "@hsep") == 0)
+ hsep++;
+ else if (strcmp (command, "@vsep") == 0)
+ vsep++;
+ else if (strcmp (command, "@columnfractions") == 0) {
+ /* Clobber old environments and create new ones,
+ starting at #1. Environment #0 is the normal standard output,
+ so we don't mess with it. */
+ for ( ; i <= MAXCOLS; i++) {
+ if (sscanf (params, "%f%n", &columnfrac, &nchars) < 1)
+ goto done;
+ params += nchars;
+ setup_output_environment (i, (int) (columnfrac * fill_column + .5));
+ }
+ }
+
+ } else if (*params == '{') {
+ char *start = params;
+ while ((*params != '}' || params[-1] == '@') && *params) {
+ params++;
+ }
+ /* This gives us two spaces between columns. Seems reasonable.
+ Really should expand the text, though, so a template of
+ `@code{foo}' has a width of three, not ten. Also have to match
+ braces, then. */
+ setup_output_environment (i++, params++ - start);
+
+ } else {
+ warning ("ignoring stray text `%s' after @multitable", params);
+ break;
+ }
+ }
+
+done:
+
+ flush_output ();
+ inhibit_output_flushing ();
+
+ last_column = i - 1;
+ return last_column;
+}
+
+/* Initialize environment number ENV_NO, of width WIDTH.
+ The idea is that we're going to use one environment for each column of
+ a multitable, so we can build them up separately and print them
+ all out at the end. */
+int
+setup_output_environment (env_no, width)
+ int env_no;
+ int width;
+{
+ int old_env = select_output_environment (env_no);
+
+ /* clobber old environment and set width of new one */
+ init_paragraph ();
+
+ /* make our change */
+ fill_column = width;
+
+ /* Save new environment and restore previous one. */
+ select_output_environment (old_env);
+
+ return env_no;
+}
+
+/* Direct current output to environment number N. Used when
+ switching work from one column of a multitable to the next.
+ Returns previous environment number. */
+int
+select_output_environment (n)
+ int n;
+{
+ struct env *e = &envs[current_env_no];
+ int old_env_no = current_env_no;
+
+ /* stash current env info from global vars into the old environment */
+ e->output_paragraph = output_paragraph;
+ e->output_paragraph_offset = output_paragraph_offset;
+ e->output_column = output_column;
+ e->paragraph_is_open = paragraph_is_open;
+ e->current_indent = current_indent;
+ e->fill_column = fill_column;
+
+ /* now copy new environment into global vars */
+ current_env_no = n;
+ e = &envs[current_env_no];
+ output_paragraph = e->output_paragraph;
+ output_paragraph_offset = e->output_paragraph_offset;
+ output_column = e->output_column;
+ paragraph_is_open = e->paragraph_is_open;
+ current_indent = e->current_indent;
+ fill_column = e->fill_column;
+ return old_env_no;
+}
+
+/* advance to the next environment number */
+int
+nselect_next_environment ()
+{
+ if (current_env_no >= last_column) {
+ line_error ("Too many columns in multitable item (max %d)", last_column);
+ return 1;
+ }
+ select_output_environment (current_env_no + 1);
+}
+
+
+static void output_multitable_row ();
+
+/* start a new item (row) of a multitable */
+multitable_item ()
+{
+ if (!multitable_active) {
+ /* impossible, I think. */
+ error ("multitable item not in active multitable");
+ exit (1);
+ }
+ if (current_env_no > 0) {
+ output_multitable_row ();
+ }
+ /* start at column 1 */
+ select_output_environment (1);
+ if (!output_paragraph) {
+ line_error ("Cannot select column #%d in multitable", current_env_no);
+ exit (FATAL);
+ }
+
+ init_column ();
+
+ return 0;
+}
+
+/* do anything needed at the beginning of processing a
+ multitable column. */
+init_column ()
+{
+ /* don't indent 1st paragraph in the item */
+ cm_noindent ();
+
+ /* throw away possible whitespace after @item or @tab command */
+ skip_whitespace ();
+}
+
+/* Output a row. Have to keep `output_position' up-to-date for each
+ character we output, or the tags table will be off, leading to
+ chopped-off output files and undefined nodes (because they're in the
+ wrong file, etc.). Perhaps it would be better to accumulate this
+ value somewhere and add it once at the end of the table, or return it
+ as the value, but this seems simplest. */
+
+static void
+out_char (ch)
+ int ch;
+{
+ extern int output_position;
+ putc (ch, output_stream);
+ output_position++;
+}
+
+
+static void
+output_multitable_row ()
+{
+ int i, j, remaining;
+
+ /* offset in the output paragraph of the next char needing
+ to be output for that column. */
+ int offset[MAXCOLS];
+
+ for (i = 0; i <= last_column; i++)
+ offset[i] = 0;
+
+ /* select the current environment, to make sure the env variables
+ get updated */
+ select_output_environment (current_env_no);
+
+#define CHAR_ADDR(n) (offset[i] + (n))
+#define CHAR_AT(n) (envs[i].output_paragraph[CHAR_ADDR(n)])
+
+ /* remove trailing whitespace from each column */
+ for (i = 1; i <= last_column; i++) {
+ while (cr_or_whitespace (CHAR_AT (envs[i].output_paragraph_offset - 1))) {
+ envs[i].output_paragraph_offset--;
+ }
+ }
+
+ /* read the current line from each column, outputting them all
+ pasted together. Do this til all lines are output from all
+ columns. */
+ for (;;) {
+ remaining = 0;
+ /* first, see if there is any work to do */
+ for (i = 1; i <= last_column; i++) {
+ if (CHAR_ADDR (0) < envs[i].output_paragraph_offset) {
+ remaining = 1;
+ break;
+ }
+ }
+ if (!remaining)
+ break;
+
+ if (vsep)
+ out_char ('|');
+
+ for (i = 1; i <= last_column; i++) {
+ for (j = 0; CHAR_ADDR (j) < envs[i].output_paragraph_offset; j++) {
+ if (CHAR_AT (j) == '\n')
+ break;
+ out_char (CHAR_AT (j));
+ }
+ offset[i] += j + 1; /* skip last text plus skip the newline */
+ for (; j <= envs[i].fill_column; j++)
+ out_char (' ');
+ if (vsep)
+ out_char ('|'); /* draw column separator */
+ }
+ out_char ('\n'); /* end of line */
+ }
+
+ if (hsep)
+ draw_horizontal_separator ();
+
+ /* Now dispose of the buffered output. */
+ for (i = 1; i <= last_column; i++) {
+ select_output_environment (i);
+ init_paragraph ();
+ }
+}
+
+#undef CHAR_AT
+#undef CHAR_ADDR
+
+int
+draw_horizontal_separator ()
+{
+ int i, j;
+ if (vsep)
+ out_char ('+');
+ for (i = 1; i <= last_column; i++) {
+ for (j = 0; j <= envs[i].fill_column; j++)
+ out_char ('-');
+ if (vsep)
+ out_char ('+');
+ }
+ out_char ('\n');
+}
+
+/* select a new column in current row of multitable */
+void
+cm_tab ()
+{
+ if (!multitable_active)
+ error ("ignoring @tab outside of multitable");
+
+ nselect_next_environment ();
+ init_column ();
+}
+
+/* close a multitable, flushing its output and resetting
+ whatever needs resetting */
+void
+end_multitable ()
+{
+ int i;
+
+ output_multitable_row ();
+
+ /* Multitables cannot be nested. Otherwise, we'd have to save the
+ previous output environment number on a stack somewhere, and then
+ restore to that environment. */
+ select_output_environment (0);
+ close_paragraph ();
+ insert ('\n'); /* we swallow newlines, so insert one of our own */
+
+ multitable_active = 0;
+ uninhibit_output_flushing ();
+
+#if 0
+ printf ("** Multicolumn output from last row:\n");
+ for (i = 1; i <= last_column; i++) {
+ select_output_environment (i);
+ printf ("* column #%d: output = %s\n", i, output_paragraph);
+ }
+#endif
+}
diff --git a/contrib/texinfo/texinfo.tex b/contrib/texinfo/texinfo.tex
new file mode 100644
index 0000000..e8375a3
--- /dev/null
+++ b/contrib/texinfo/texinfo.tex
@@ -0,0 +1,4692 @@
+%% TeX macros to handle texinfo files
+
+% Copyright (C) 1985, 86, 88, 90, 91, 92, 93,
+% 94, 95, 1996 Free Software Foundation, Inc.
+
+%This texinfo.tex file 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, or (at
+%your option) any later version.
+
+%This texinfo.tex file 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 texinfo.tex file; see the file COPYING. If not, write
+%to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+%Boston, MA 02111-1307, USA.
+
+
+%In other words, you are welcome to use, share and improve this program.
+%You are forbidden to forbid anyone else to use, share and improve
+%what you give them. Help stamp out software-hoarding!
+
+
+% Send bug reports to bug-texinfo@prep.ai.mit.edu.
+% Please include a *precise* test case in each bug report.
+
+
+% Make it possible to create a .fmt file just by loading this file:
+% if the underlying format is not loaded, start by loading it now.
+% Added by gildea November 1993.
+\expandafter\ifx\csname fmtname\endcsname\relax\input plain\fi
+
+% This automatically updates the version number based on RCS.
+\def\deftexinfoversion$#1: #2 ${\def\texinfoversion{#2}}
+\deftexinfoversion$Revision: 2.185 $
+\message{Loading texinfo package [Version \texinfoversion]:}
+
+% If in a .fmt file, print the version number
+% and turn on active characters that we couldn't do earlier because
+% they might have appeared in the input file name.
+\everyjob{\message{[Texinfo version \texinfoversion]}\message{}
+ \catcode`+=\active \catcode`\_=\active}
+
+% Save some parts of plain tex whose names we will redefine.
+
+\let\ptexb=\b
+\let\ptexbullet=\bullet
+\let\ptexc=\c
+\let\ptexcomma=\,
+\let\ptexdot=\.
+\let\ptexdots=\dots
+\let\ptexend=\end
+\let\ptexequiv = \equiv
+\let\ptexi=\i
+\let\ptexlbrace=\{
+\let\ptexrbrace=\}
+\let\ptexstar=\*
+\let\ptext=\t
+\let\ptextilde=\~
+
+% Be sure we're in horizontal mode when doing a tie, since we make space
+% equivalent to this in @example-like environments. Otherwise, a space
+% at the beginning of a line will start with \penalty -- and
+% since \penalty is valid in vertical mode, we'd end up putting the
+% penalty on the vertical list instead of in the new paragraph.
+{\catcode`@ = 11
+ % Avoid using \@M directly, because that causes trouble
+ % if the definition is written into an index file.
+ \global\let\tiepenalty = \@M
+ \gdef\tie{\leavevmode\penalty\tiepenalty\ }
+}
+\let\~ = \tie % And make it available as @~.
+
+
+\message{Basics,}
+\chardef\other=12
+
+% If this character appears in an error message or help string, it
+% starts a new line in the output.
+\newlinechar = `^^J
+
+% Set up fixed words for English.
+\ifx\putwordChapter\undefined{\gdef\putwordChapter{Chapter}}\fi%
+\def\putwordInfo{Info}%
+\ifx\putwordSee\undefined{\gdef\putwordSee{See}}\fi%
+\ifx\putwordsee\undefined{\gdef\putwordsee{see}}\fi%
+\ifx\putwordfile\undefined{\gdef\putwordfile{file}}\fi%
+\ifx\putwordpage\undefined{\gdef\putwordpage{page}}\fi%
+\ifx\putwordsection\undefined{\gdef\putwordsection{section}}\fi%
+\ifx\putwordSection\undefined{\gdef\putwordSection{Section}}\fi%
+\ifx\putwordTableofContents\undefined{\gdef\putwordTableofContents{Table of Contents}}\fi%
+\ifx\putwordShortContents\undefined{\gdef\putwordShortContents{Short Contents}}\fi%
+\ifx\putwordAppendix\undefined{\gdef\putwordAppendix{Appendix}}\fi%
+
+% Ignore a token.
+%
+\def\gobble#1{}
+
+\hyphenation{ap-pen-dix}
+\hyphenation{mini-buf-fer mini-buf-fers}
+\hyphenation{eshell}
+
+% Margin to add to right of even pages, to left of odd pages.
+\newdimen \bindingoffset
+\newdimen \normaloffset
+\newdimen\pagewidth \newdimen\pageheight
+
+% Sometimes it is convenient to have everything in the transcript file
+% and nothing on the terminal. We don't just call \tracingall here,
+% since that produces some useless output on the terminal.
+%
+\def\gloggingall{\begingroup \globaldefs = 1 \loggingall \endgroup}%
+\def\loggingall{\tracingcommands2 \tracingstats2
+ \tracingpages1 \tracingoutput1 \tracinglostchars1
+ \tracingmacros2 \tracingparagraphs1 \tracingrestores1
+ \showboxbreadth\maxdimen\showboxdepth\maxdimen
+}%
+
+%---------------------Begin change-----------------------
+%
+%%%% For @cropmarks command.
+% Dimensions to add cropmarks at corners Added by P. A. MacKay, 12 Nov. 1986
+%
+\newdimen\cornerlong \newdimen\cornerthick
+\newdimen \topandbottommargin
+\newdimen \outerhsize \newdimen \outervsize
+\cornerlong=1pc\cornerthick=.3pt % These set size of cropmarks
+\outerhsize=7in
+%\outervsize=9.5in
+% Alternative @smallbook page size is 9.25in
+\outervsize=9.25in
+\topandbottommargin=.75in
+%
+%---------------------End change-----------------------
+
+% \onepageout takes a vbox as an argument. Note that \pagecontents
+% does insertions, but you have to call it yourself.
+\chardef\PAGE=255 \output={\onepageout{\pagecontents\PAGE}}
+\def\onepageout#1{%
+ \hoffset=\normaloffset
+ \ifodd\pageno \advance\hoffset by \bindingoffset
+ \else \advance\hoffset by -\bindingoffset\fi
+ {%
+ \escapechar = `\\ % use backslash in output files.
+ \indexdummies
+ \shipout\vbox{%
+ {\let\hsize=\pagewidth \makeheadline}%
+ \pagebody{#1}%
+ {\let\hsize=\pagewidth \makefootline}%
+ }%
+ }%
+ \advancepageno
+ \ifnum\outputpenalty>-20000 \else\dosupereject\fi
+}
+
+%%%% For @cropmarks command %%%%
+
+% Here is a modification of the main output routine for Near East Publications
+% This provides right-angle cropmarks at all four corners.
+% The contents of the page are centerlined into the cropmarks,
+% and any desired binding offset is added as an \hskip on either
+% site of the centerlined box. (P. A. MacKay, 12 November, 1986)
+%
+\def\croppageout#1{\hoffset=0pt % make sure this doesn't mess things up
+{\escapechar=`\\\relax % makes sure backslash is used in output files.
+ \shipout
+ \vbox to \outervsize{\hsize=\outerhsize
+ \vbox{\line{\ewtop\hfill\ewtop}}
+ \nointerlineskip
+ \line{\vbox{\moveleft\cornerthick\nstop}
+ \hfill
+ \vbox{\moveright\cornerthick\nstop}}
+ \vskip \topandbottommargin
+ \centerline{\ifodd\pageno\hskip\bindingoffset\fi
+ \vbox{
+ {\let\hsize=\pagewidth \makeheadline}
+ \pagebody{#1}
+ {\let\hsize=\pagewidth \makefootline}}
+ \ifodd\pageno\else\hskip\bindingoffset\fi}
+ \vskip \topandbottommargin plus1fill minus1fill
+ \boxmaxdepth\cornerthick
+ \line{\vbox{\moveleft\cornerthick\nsbot}
+ \hfill
+ \vbox{\moveright\cornerthick\nsbot}}
+ \nointerlineskip
+ \vbox{\line{\ewbot\hfill\ewbot}}
+ }}
+ \advancepageno
+ \ifnum\outputpenalty>-20000 \else\dosupereject\fi}
+%
+% Do @cropmarks to get crop marks
+\def\cropmarks{\let\onepageout=\croppageout }
+
+\newinsert\margin \dimen\margin=\maxdimen
+
+\def\pagebody#1{\vbox to\pageheight{\boxmaxdepth=\maxdepth #1}}
+{\catcode`\@ =11
+\gdef\pagecontents#1{\ifvoid\topins\else\unvbox\topins\fi
+% marginal hacks, juha@viisa.uucp (Juha Takala)
+\ifvoid\margin\else % marginal info is present
+ \rlap{\kern\hsize\vbox to\z@{\kern1pt\box\margin \vss}}\fi
+\dimen@=\dp#1 \unvbox#1
+\ifvoid\footins\else\vskip\skip\footins\footnoterule \unvbox\footins\fi
+\ifr@ggedbottom \kern-\dimen@ \vfil \fi}
+}
+
+%
+% Here are the rules for the cropmarks. Note that they are
+% offset so that the space between them is truly \outerhsize or \outervsize
+% (P. A. MacKay, 12 November, 1986)
+%
+\def\ewtop{\vrule height\cornerthick depth0pt width\cornerlong}
+\def\nstop{\vbox
+ {\hrule height\cornerthick depth\cornerlong width\cornerthick}}
+\def\ewbot{\vrule height0pt depth\cornerthick width\cornerlong}
+\def\nsbot{\vbox
+ {\hrule height\cornerlong depth\cornerthick width\cornerthick}}
+
+% Parse an argument, then pass it to #1. The argument is the rest of
+% the input line (except we remove a trailing comment). #1 should be a
+% macro which expects an ordinary undelimited TeX argument.
+%
+\def\parsearg#1{%
+ \let\next = #1%
+ \begingroup
+ \obeylines
+ \futurelet\temp\parseargx
+}
+
+% If the next token is an obeyed space (from an @example environment or
+% the like), remove it and recurse. Otherwise, we're done.
+\def\parseargx{%
+ % \obeyedspace is defined far below, after the definition of \sepspaces.
+ \ifx\obeyedspace\temp
+ \expandafter\parseargdiscardspace
+ \else
+ \expandafter\parseargline
+ \fi
+}
+
+% Remove a single space (as the delimiter token to the macro call).
+{\obeyspaces %
+ \gdef\parseargdiscardspace {\futurelet\temp\parseargx}}
+
+{\obeylines %
+ \gdef\parseargline#1^^M{%
+ \endgroup % End of the group started in \parsearg.
+ %
+ % First remove any @c comment, then any @comment.
+ % Result of each macro is put in \toks0.
+ \argremovec #1\c\relax %
+ \expandafter\argremovecomment \the\toks0 \comment\relax %
+ %
+ % Call the caller's macro, saved as \next in \parsearg.
+ \expandafter\next\expandafter{\the\toks0}%
+ }%
+}
+
+% Since all \c{,omment} does is throw away the argument, we can let TeX
+% do that for us. The \relax here is matched by the \relax in the call
+% in \parseargline; it could be more or less anything, its purpose is
+% just to delimit the argument to the \c.
+\def\argremovec#1\c#2\relax{\toks0 = {#1}}
+\def\argremovecomment#1\comment#2\relax{\toks0 = {#1}}
+
+% \argremovec{,omment} might leave us with trailing spaces, though; e.g.,
+% @end itemize @c foo
+% will have two active spaces as part of the argument with the
+% `itemize'. Here we remove all active spaces from #1, and assign the
+% result to \toks0.
+%
+% This loses if there are any *other* active characters besides spaces
+% in the argument -- _ ^ +, for example -- since they get expanded.
+% Fortunately, Texinfo does not define any such commands. (If it ever
+% does, the catcode of the characters in questionwill have to be changed
+% here.) But this means we cannot call \removeactivespaces as part of
+% \argremovec{,omment}, since @c uses \parsearg, and thus the argument
+% that \parsearg gets might well have any character at all in it.
+%
+\def\removeactivespaces#1{%
+ \begingroup
+ \ignoreactivespaces
+ \edef\temp{#1}%
+ \global\toks0 = \expandafter{\temp}%
+ \endgroup
+}
+
+% Change the active space to expand to nothing.
+%
+\begingroup
+ \obeyspaces
+ \gdef\ignoreactivespaces{\obeyspaces\let =\empty}
+\endgroup
+
+
+\def\flushcr{\ifx\par\lisppar \def\next##1{}\else \let\next=\relax \fi \next}
+
+%% These are used to keep @begin/@end levels from running away
+%% Call \inENV within environments (after a \begingroup)
+\newif\ifENV \ENVfalse \def\inENV{\ifENV\relax\else\ENVtrue\fi}
+\def\ENVcheck{%
+\ifENV\errmessage{Still within an environment. Type Return to continue.}
+\endgroup\fi} % This is not perfect, but it should reduce lossage
+
+% @begin foo is the same as @foo, for now.
+\newhelp\EMsimple{Type <Return> to continue.}
+
+\outer\def\begin{\parsearg\beginxxx}
+
+\def\beginxxx #1{%
+\expandafter\ifx\csname #1\endcsname\relax
+{\errhelp=\EMsimple \errmessage{Undefined command @begin #1}}\else
+\csname #1\endcsname\fi}
+
+% @end foo executes the definition of \Efoo.
+%
+\def\end{\parsearg\endxxx}
+\def\endxxx #1{%
+ \removeactivespaces{#1}%
+ \edef\endthing{\the\toks0}%
+ %
+ \expandafter\ifx\csname E\endthing\endcsname\relax
+ \expandafter\ifx\csname \endthing\endcsname\relax
+ % There's no \foo, i.e., no ``environment'' foo.
+ \errhelp = \EMsimple
+ \errmessage{Undefined command `@end \endthing'}%
+ \else
+ \unmatchedenderror\endthing
+ \fi
+ \else
+ % Everything's ok; the right environment has been started.
+ \csname E\endthing\endcsname
+ \fi
+}
+
+% There is an environment #1, but it hasn't been started. Give an error.
+%
+\def\unmatchedenderror#1{%
+ \errhelp = \EMsimple
+ \errmessage{This `@end #1' doesn't have a matching `@#1'}%
+}
+
+% Define the control sequence \E#1 to give an unmatched @end error.
+%
+\def\defineunmatchedend#1{%
+ \expandafter\def\csname E#1\endcsname{\unmatchedenderror{#1}}%
+}
+
+
+% Single-spacing is done by various environments (specifically, in
+% \nonfillstart and \quotations).
+\newskip\singlespaceskip \singlespaceskip = 12.5pt
+\def\singlespace{%
+ % Why was this kern here? It messes up equalizing space above and below
+ % environments. --karl, 6may93
+ %{\advance \baselineskip by -\singlespaceskip
+ %\kern \baselineskip}%
+ \setleading \singlespaceskip
+}
+
+%% Simple single-character @ commands
+
+% @@ prints an @
+% Kludge this until the fonts are right (grr).
+\def\@{{\tt \char '100}}
+
+% This is turned off because it was never documented
+% and you can use @w{...} around a quote to suppress ligatures.
+%% Define @` and @' to be the same as ` and '
+%% but suppressing ligatures.
+%\def\`{{`}}
+%\def\'{{'}}
+
+% Used to generate quoted braces.
+\def\mylbrace {{\tt \char '173}}
+\def\myrbrace {{\tt \char '175}}
+\let\{=\mylbrace
+\let\}=\myrbrace
+\begingroup
+ % Definitions to produce actual \{ & \} command in an index.
+ \catcode`\{ = 12 \catcode`\} = 12
+ \catcode`\[ = 1 \catcode`\] = 2
+ \catcode`\@ = 0 \catcode`\\ = 12
+ @gdef@lbracecmd[\{]%
+ @gdef@rbracecmd[\}]%
+@endgroup
+
+% Accents: @, @dotaccent @ringaccent @ubaraccent @udotaccent
+% Others are defined by plain TeX: @` @' @" @^ @~ @= @v @H.
+\let\, = \c
+\let\dotaccent = \.
+\def\ringaccent#1{{\accent23 #1}}
+\let\tieaccent = \t
+\let\ubaraccent = \b
+\let\udotaccent = \d
+
+% Other special characters: @questiondown @exclamdown
+% Plain TeX defines: @AA @AE @O @OE @L (and lowercase versions) @ss.
+\def\questiondown{?`}
+\def\exclamdown{!`}
+
+% Dotless i and dotless j, used for accents.
+\def\imacro{i}
+\def\jmacro{j}
+\def\dotless#1{%
+ \def\temp{#1}%
+ \ifx\temp\imacro \ptexi
+ \else\ifx\temp\jmacro \j
+ \else \errmessage{@dotless can be used only with i or j}%
+ \fi\fi
+}
+
+% @: forces normal size whitespace following.
+\def\:{\spacefactor=1000 }
+
+% @* forces a line break.
+\def\*{\hfil\break\hbox{}\ignorespaces}
+
+% @. is an end-of-sentence period.
+\def\.{.\spacefactor=3000 }
+
+% @enddots{} is an end-of-sentence ellipsis.
+\gdef\enddots{$\mathinner{\ldotp\ldotp\ldotp\ldotp}$\spacefactor=3000}
+
+% @! is an end-of-sentence bang.
+\gdef\!{!\spacefactor=3000 }
+
+% @? is an end-of-sentence query.
+\gdef\?{?\spacefactor=3000 }
+
+% @w prevents a word break. Without the \leavevmode, @w at the
+% beginning of a paragraph, when TeX is still in vertical mode, would
+% produce a whole line of output instead of starting the paragraph.
+\def\w#1{\leavevmode\hbox{#1}}
+
+% @group ... @end group forces ... to be all on one page, by enclosing
+% it in a TeX vbox. We use \vtop instead of \vbox to construct the box
+% to keep its height that of a normal line. According to the rules for
+% \topskip (p.114 of the TeXbook), the glue inserted is
+% max (\topskip - \ht (first item), 0). If that height is large,
+% therefore, no glue is inserted, and the space between the headline and
+% the text is small, which looks bad.
+%
+\def\group{\begingroup
+ \ifnum\catcode13=\active \else
+ \errhelp = \groupinvalidhelp
+ \errmessage{@group invalid in context where filling is enabled}%
+ \fi
+ %
+ % The \vtop we start below produces a box with normal height and large
+ % depth; thus, TeX puts \baselineskip glue before it, and (when the
+ % next line of text is done) \lineskip glue after it. (See p.82 of
+ % the TeXbook.) Thus, space below is not quite equal to space
+ % above. But it's pretty close.
+ \def\Egroup{%
+ \egroup % End the \vtop.
+ \endgroup % End the \group.
+ }%
+ %
+ \vtop\bgroup
+ % We have to put a strut on the last line in case the @group is in
+ % the midst of an example, rather than completely enclosing it.
+ % Otherwise, the interline space between the last line of the group
+ % and the first line afterwards is too small. But we can't put the
+ % strut in \Egroup, since there it would be on a line by itself.
+ % Hence this just inserts a strut at the beginning of each line.
+ \everypar = {\strut}%
+ %
+ % Since we have a strut on every line, we don't need any of TeX's
+ % normal interline spacing.
+ \offinterlineskip
+ %
+ % OK, but now we have to do something about blank
+ % lines in the input in @example-like environments, which normally
+ % just turn into \lisppar, which will insert no space now that we've
+ % turned off the interline space. Simplest is to make them be an
+ % empty paragraph.
+ \ifx\par\lisppar
+ \edef\par{\leavevmode \par}%
+ %
+ % Reset ^^M's definition to new definition of \par.
+ \obeylines
+ \fi
+ %
+ % Do @comment since we are called inside an environment such as
+ % @example, where each end-of-line in the input causes an
+ % end-of-line in the output. We don't want the end-of-line after
+ % the `@group' to put extra space in the output. Since @group
+ % should appear on a line by itself (according to the Texinfo
+ % manual), we don't worry about eating any user text.
+ \comment
+}
+%
+% TeX puts in an \escapechar (i.e., `@') at the beginning of the help
+% message, so this ends up printing `@group can only ...'.
+%
+\newhelp\groupinvalidhelp{%
+group can only be used in environments such as @example,^^J%
+where each line of input produces a line of output.}
+
+% @need space-in-mils
+% forces a page break if there is not space-in-mils remaining.
+
+\newdimen\mil \mil=0.001in
+
+\def\need{\parsearg\needx}
+
+% Old definition--didn't work.
+%\def\needx #1{\par %
+%% This method tries to make TeX break the page naturally
+%% if the depth of the box does not fit.
+%{\baselineskip=0pt%
+%\vtop to #1\mil{\vfil}\kern -#1\mil\penalty 10000
+%\prevdepth=-1000pt
+%}}
+
+\def\needx#1{%
+ % Go into vertical mode, so we don't make a big box in the middle of a
+ % paragraph.
+ \par
+ %
+ % Don't add any leading before our big empty box, but allow a page
+ % break, since the best break might be right here.
+ \allowbreak
+ \nointerlineskip
+ \vtop to #1\mil{\vfil}%
+ %
+ % TeX does not even consider page breaks if a penalty added to the
+ % main vertical list is 10000 or more. But in order to see if the
+ % empty box we just added fits on the page, we must make it consider
+ % page breaks. On the other hand, we don't want to actually break the
+ % page after the empty box. So we use a penalty of 9999.
+ %
+ % There is an extremely small chance that TeX will actually break the
+ % page at this \penalty, if there are no other feasible breakpoints in
+ % sight. (If the user is using lots of big @group commands, which
+ % almost-but-not-quite fill up a page, TeX will have a hard time doing
+ % good page breaking, for example.) However, I could not construct an
+ % example where a page broke at this \penalty; if it happens in a real
+ % document, then we can reconsider our strategy.
+ \penalty9999
+ %
+ % Back up by the size of the box, whether we did a page break or not.
+ \kern -#1\mil
+ %
+ % Do not allow a page break right after this kern.
+ \nobreak
+}
+
+% @br forces paragraph break
+
+\let\br = \par
+
+% @dots{} output some dots
+
+\def\dots{$\ldots$}
+
+% @page forces the start of a new page
+
+\def\page{\par\vfill\supereject}
+
+% @exdent text....
+% outputs text on separate line in roman font, starting at standard page margin
+
+% This records the amount of indent in the innermost environment.
+% That's how much \exdent should take out.
+\newskip\exdentamount
+
+% This defn is used inside fill environments such as @defun.
+\def\exdent{\parsearg\exdentyyy}
+\def\exdentyyy #1{{\hfil\break\hbox{\kern -\exdentamount{\rm#1}}\hfil\break}}
+
+% This defn is used inside nofill environments such as @example.
+\def\nofillexdent{\parsearg\nofillexdentyyy}
+\def\nofillexdentyyy #1{{\advance \leftskip by -\exdentamount
+\leftline{\hskip\leftskip{\rm#1}}}}
+
+% @inmargin{TEXT} puts TEXT in the margin next to the current paragraph.
+
+\def\inmargin#1{%
+\strut\vadjust{\nobreak\kern-\strutdepth
+ \vtop to \strutdepth{\baselineskip\strutdepth\vss
+ \llap{\rightskip=\inmarginspacing \vbox{\noindent #1}}\null}}}
+\newskip\inmarginspacing \inmarginspacing=1cm
+\def\strutdepth{\dp\strutbox}
+
+%\hbox{{\rm#1}}\hfil\break}}
+
+% @include file insert text of that file as input.
+% Allow normal characters that we make active in the argument (a file name).
+\def\include{\begingroup
+ \catcode`\\=12
+ \catcode`~=12
+ \catcode`^=12
+ \catcode`_=12
+ \catcode`|=12
+ \catcode`<=12
+ \catcode`>=12
+ \catcode`+=12
+ \parsearg\includezzz}
+% Restore active chars for included file.
+\def\includezzz#1{\endgroup\begingroup
+ % Read the included file in a group so nested @include's work.
+ \def\thisfile{#1}%
+ \input\thisfile
+\endgroup}
+
+\def\thisfile{}
+
+% @center line outputs that line, centered
+
+\def\center{\parsearg\centerzzz}
+\def\centerzzz #1{{\advance\hsize by -\leftskip
+\advance\hsize by -\rightskip
+\centerline{#1}}}
+
+% @sp n outputs n lines of vertical space
+
+\def\sp{\parsearg\spxxx}
+\def\spxxx #1{\vskip #1\baselineskip}
+
+% @comment ...line which is ignored...
+% @c is the same as @comment
+% @ignore ... @end ignore is another way to write a comment
+
+\def\comment{\catcode 64=\other \catcode 123=\other \catcode 125=\other%
+\parsearg \commentxxx}
+
+\def\commentxxx #1{\catcode 64=0 \catcode 123=1 \catcode 125=2 }
+
+\let\c=\comment
+
+% @paragraphindent is defined for the Info formatting commands only.
+\let\paragraphindent=\comment
+
+% Prevent errors for section commands.
+% Used in @ignore and in failing conditionals.
+\def\ignoresections{%
+\let\chapter=\relax
+\let\unnumbered=\relax
+\let\top=\relax
+\let\unnumberedsec=\relax
+\let\unnumberedsection=\relax
+\let\unnumberedsubsec=\relax
+\let\unnumberedsubsection=\relax
+\let\unnumberedsubsubsec=\relax
+\let\unnumberedsubsubsection=\relax
+\let\section=\relax
+\let\subsec=\relax
+\let\subsubsec=\relax
+\let\subsection=\relax
+\let\subsubsection=\relax
+\let\appendix=\relax
+\let\appendixsec=\relax
+\let\appendixsection=\relax
+\let\appendixsubsec=\relax
+\let\appendixsubsection=\relax
+\let\appendixsubsubsec=\relax
+\let\appendixsubsubsection=\relax
+\let\contents=\relax
+\let\smallbook=\relax
+\let\titlepage=\relax
+}
+
+% Used in nested conditionals, where we have to parse the Texinfo source
+% and so want to turn off most commands, in case they are used
+% incorrectly.
+%
+\def\ignoremorecommands{%
+ \let\defcodeindex = \relax
+ \let\defcv = \relax
+ \let\deffn = \relax
+ \let\deffnx = \relax
+ \let\defindex = \relax
+ \let\defivar = \relax
+ \let\defmac = \relax
+ \let\defmethod = \relax
+ \let\defop = \relax
+ \let\defopt = \relax
+ \let\defspec = \relax
+ \let\deftp = \relax
+ \let\deftypefn = \relax
+ \let\deftypefun = \relax
+ \let\deftypevar = \relax
+ \let\deftypevr = \relax
+ \let\defun = \relax
+ \let\defvar = \relax
+ \let\defvr = \relax
+ \let\ref = \relax
+ \let\xref = \relax
+ \let\printindex = \relax
+ \let\pxref = \relax
+ \let\settitle = \relax
+ \let\setchapternewpage = \relax
+ \let\setchapterstyle = \relax
+ \let\everyheading = \relax
+ \let\evenheading = \relax
+ \let\oddheading = \relax
+ \let\everyfooting = \relax
+ \let\evenfooting = \relax
+ \let\oddfooting = \relax
+ \let\headings = \relax
+ \let\include = \relax
+ \let\lowersections = \relax
+ \let\down = \relax
+ \let\raisesections = \relax
+ \let\up = \relax
+ \let\set = \relax
+ \let\clear = \relax
+ \let\item = \relax
+}
+
+% Ignore @ignore ... @end ignore.
+%
+\def\ignore{\doignore{ignore}}
+
+% Also ignore @ifinfo, @ifhtml, @html, @menu, and @direntry text.
+%
+\def\ifinfo{\doignore{ifinfo}}
+\def\ifhtml{\doignore{ifhtml}}
+\def\html{\doignore{html}}
+\def\menu{\doignore{menu}}
+\def\direntry{\doignore{direntry}}
+
+% Also ignore @macro ... @end macro. The user must run texi2dvi,
+% which runs makeinfo to do macro expansion. Ignore @unmacro, too.
+\def\macro{\doignore{macro}}
+\let\unmacro = \comment
+
+
+% @dircategory CATEGORY -- specify a category of the dir file
+% which this file should belong to. Ignore this in TeX.
+\let\dircategory = \comment
+
+% Ignore text until a line `@end #1'.
+%
+\def\doignore#1{\begingroup
+ % Don't complain about control sequences we have declared \outer.
+ \ignoresections
+ %
+ % Define a command to swallow text until we reach `@end #1'.
+ \long\def\doignoretext##1\end #1{\enddoignore}%
+ %
+ % Make sure that spaces turn into tokens that match what \doignoretext wants.
+ \catcode32 = 10
+ %
+ % And now expand that command.
+ \doignoretext
+}
+
+% What we do to finish off ignored text.
+%
+\def\enddoignore{\endgroup\ignorespaces}%
+
+\newif\ifwarnedobs\warnedobsfalse
+\def\obstexwarn{%
+ \ifwarnedobs\relax\else
+ % We need to warn folks that they may have trouble with TeX 3.0.
+ % This uses \immediate\write16 rather than \message to get newlines.
+ \immediate\write16{}
+ \immediate\write16{***WARNING*** for users of Unix TeX 3.0!}
+ \immediate\write16{This manual trips a bug in TeX version 3.0 (tex hangs).}
+ \immediate\write16{If you are running another version of TeX, relax.}
+ \immediate\write16{If you are running Unix TeX 3.0, kill this TeX process.}
+ \immediate\write16{ Then upgrade your TeX installation if you can.}
+ \immediate\write16{ (See ftp://ftp.gnu.ai.mit.edu/pub/gnu/TeX.README.)}
+ \immediate\write16{If you are stuck with version 3.0, run the}
+ \immediate\write16{ script ``tex3patch'' from the Texinfo distribution}
+ \immediate\write16{ to use a workaround.}
+ \immediate\write16{}
+ \global\warnedobstrue
+ \fi
+}
+
+% **In TeX 3.0, setting text in \nullfont hangs tex. For a
+% workaround (which requires the file ``dummy.tfm'' to be installed),
+% uncomment the following line:
+%%%%%\font\nullfont=dummy\let\obstexwarn=\relax
+
+% Ignore text, except that we keep track of conditional commands for
+% purposes of nesting, up to an `@end #1' command.
+%
+\def\nestedignore#1{%
+ \obstexwarn
+ % We must actually expand the ignored text to look for the @end
+ % command, so that nested ignore constructs work. Thus, we put the
+ % text into a \vbox and then do nothing with the result. To minimize
+ % the change of memory overflow, we follow the approach outlined on
+ % page 401 of the TeXbook: make the current font be a dummy font.
+ %
+ \setbox0 = \vbox\bgroup
+ % Don't complain about control sequences we have declared \outer.
+ \ignoresections
+ %
+ % Define `@end #1' to end the box, which will in turn undefine the
+ % @end command again.
+ \expandafter\def\csname E#1\endcsname{\egroup\ignorespaces}%
+ %
+ % We are going to be parsing Texinfo commands. Most cause no
+ % trouble when they are used incorrectly, but some commands do
+ % complicated argument parsing or otherwise get confused, so we
+ % undefine them.
+ %
+ % We can't do anything about stray @-signs, unfortunately;
+ % they'll produce `undefined control sequence' errors.
+ \ignoremorecommands
+ %
+ % Set the current font to be \nullfont, a TeX primitive, and define
+ % all the font commands to also use \nullfont. We don't use
+ % dummy.tfm, as suggested in the TeXbook, because not all sites
+ % might have that installed. Therefore, math mode will still
+ % produce output, but that should be an extremely small amount of
+ % stuff compared to the main input.
+ %
+ \nullfont
+ \let\tenrm = \nullfont \let\tenit = \nullfont \let\tensl = \nullfont
+ \let\tenbf = \nullfont \let\tentt = \nullfont \let\smallcaps = \nullfont
+ \let\tensf = \nullfont
+ % Similarly for index fonts (mostly for their use in
+ % smallexample)
+ \let\indrm = \nullfont \let\indit = \nullfont \let\indsl = \nullfont
+ \let\indbf = \nullfont \let\indtt = \nullfont \let\indsc = \nullfont
+ \let\indsf = \nullfont
+ %
+ % Don't complain when characters are missing from the fonts.
+ \tracinglostchars = 0
+ %
+ % Don't bother to do space factor calculations.
+ \frenchspacing
+ %
+ % Don't report underfull hboxes.
+ \hbadness = 10000
+ %
+ % Do minimal line-breaking.
+ \pretolerance = 10000
+ %
+ % Do not execute instructions in @tex
+ \def\tex{\doignore{tex}}
+}
+
+% @set VAR sets the variable VAR to an empty value.
+% @set VAR REST-OF-LINE sets VAR to the value REST-OF-LINE.
+%
+% Since we want to separate VAR from REST-OF-LINE (which might be
+% empty), we can't just use \parsearg; we have to insert a space of our
+% own to delimit the rest of the line, and then take it out again if we
+% didn't need it. Make sure the catcode of space is correct to avoid
+% losing inside @example, for instance.
+%
+\def\set{\begingroup\catcode` =10 \parsearg\setxxx}
+\def\setxxx#1{\setyyy#1 \endsetyyy}
+\def\setyyy#1 #2\endsetyyy{%
+ \def\temp{#2}%
+ \ifx\temp\empty \global\expandafter\let\csname SET#1\endcsname = \empty
+ \else \setzzz{#1}#2\endsetzzz % Remove the trailing space \setxxx inserted.
+ \fi
+ \endgroup
+}
+% Can't use \xdef to pre-expand #2 and save some time, since \temp or
+% \next or other control sequences that we've defined might get us into
+% an infinite loop. Consider `@set foo @cite{bar}'.
+\def\setzzz#1#2 \endsetzzz{\expandafter\gdef\csname SET#1\endcsname{#2}}
+
+% @clear VAR clears (i.e., unsets) the variable VAR.
+%
+\def\clear{\parsearg\clearxxx}
+\def\clearxxx#1{\global\expandafter\let\csname SET#1\endcsname=\relax}
+
+% @value{foo} gets the text saved in variable foo.
+%
+\def\value#1{\expandafter
+ \ifx\csname SET#1\endcsname\relax
+ {\{No value for ``#1''\}}
+ \else \csname SET#1\endcsname \fi}
+
+% @ifset VAR ... @end ifset reads the `...' iff VAR has been defined
+% with @set.
+%
+\def\ifset{\parsearg\ifsetxxx}
+\def\ifsetxxx #1{%
+ \expandafter\ifx\csname SET#1\endcsname\relax
+ \expandafter\ifsetfail
+ \else
+ \expandafter\ifsetsucceed
+ \fi
+}
+\def\ifsetsucceed{\conditionalsucceed{ifset}}
+\def\ifsetfail{\nestedignore{ifset}}
+\defineunmatchedend{ifset}
+
+% @ifclear VAR ... @end ifclear reads the `...' iff VAR has never been
+% defined with @set, or has been undefined with @clear.
+%
+\def\ifclear{\parsearg\ifclearxxx}
+\def\ifclearxxx #1{%
+ \expandafter\ifx\csname SET#1\endcsname\relax
+ \expandafter\ifclearsucceed
+ \else
+ \expandafter\ifclearfail
+ \fi
+}
+\def\ifclearsucceed{\conditionalsucceed{ifclear}}
+\def\ifclearfail{\nestedignore{ifclear}}
+\defineunmatchedend{ifclear}
+
+% @iftex always succeeds; we read the text following, through @end
+% iftex). But `@end iftex' should be valid only after an @iftex.
+%
+\def\iftex{\conditionalsucceed{iftex}}
+\defineunmatchedend{iftex}
+
+% We can't just want to start a group at @iftex (for example) and end it
+% at @end iftex, since then @set commands inside the conditional have no
+% effect (they'd get reverted at the end of the group). So we must
+% define \Eiftex to redefine itself to be its previous value. (We can't
+% just define it to fail again with an ``unmatched end'' error, since
+% the @ifset might be nested.)
+%
+\def\conditionalsucceed#1{%
+ \edef\temp{%
+ % Remember the current value of \E#1.
+ \let\nece{prevE#1} = \nece{E#1}%
+ %
+ % At the `@end #1', redefine \E#1 to be its previous value.
+ \def\nece{E#1}{\let\nece{E#1} = \nece{prevE#1}}%
+ }%
+ \temp
+}
+
+% We need to expand lots of \csname's, but we don't want to expand the
+% control sequences after we've constructed them.
+%
+\def\nece#1{\expandafter\noexpand\csname#1\endcsname}
+
+% @asis just yields its argument. Used with @table, for example.
+%
+\def\asis#1{#1}
+
+% @math means output in math mode.
+% We don't use $'s directly in the definition of \math because control
+% sequences like \math are expanded when the toc file is written. Then,
+% we read the toc file back, the $'s will be normal characters (as they
+% should be, according to the definition of Texinfo). So we must use a
+% control sequence to switch into and out of math mode.
+%
+% This isn't quite enough for @math to work properly in indices, but it
+% seems unlikely it will ever be needed there.
+%
+\let\implicitmath = $
+\def\math#1{\implicitmath #1\implicitmath}
+
+% @bullet and @minus need the same treatment as @math, just above.
+\def\bullet{\implicitmath\ptexbullet\implicitmath}
+\def\minus{\implicitmath-\implicitmath}
+
+\def\node{\ENVcheck\parsearg\nodezzz}
+\def\nodezzz#1{\nodexxx [#1,]}
+\def\nodexxx[#1,#2]{\gdef\lastnode{#1}}
+\let\nwnode=\node
+\let\lastnode=\relax
+
+\def\donoderef{\ifx\lastnode\relax\else
+\expandafter\expandafter\expandafter\setref{\lastnode}\fi
+\global\let\lastnode=\relax}
+
+\def\unnumbnoderef{\ifx\lastnode\relax\else
+\expandafter\expandafter\expandafter\unnumbsetref{\lastnode}\fi
+\global\let\lastnode=\relax}
+
+\def\appendixnoderef{\ifx\lastnode\relax\else
+\expandafter\expandafter\expandafter\appendixsetref{\lastnode}\fi
+\global\let\lastnode=\relax}
+
+% @refill is a no-op.
+\let\refill=\relax
+
+% @setfilename is done at the beginning of every texinfo file.
+% So open here the files we need to have open while reading the input.
+% This makes it possible to make a .fmt file for texinfo.
+\def\setfilename{%
+ \readauxfile
+ \opencontents
+ \openindices
+ \fixbackslash % Turn off hack to swallow `\input texinfo'.
+ \global\let\setfilename=\comment % Ignore extra @setfilename cmds.
+ \comment % Ignore the actual filename.
+}
+
+% @bye.
+\outer\def\bye{\pagealignmacro\tracingstats=1\ptexend}
+
+% \def\macro#1{\begingroup\ignoresections\catcode`\#=6\def\macrotemp{#1}\parsearg\macroxxx}
+% \def\macroxxx#1#2 \end macro{%
+% \expandafter\gdef\macrotemp#1{#2}%
+% \endgroup}
+
+%\def\linemacro#1{\begingroup\ignoresections\catcode`\#=6\def\macrotemp{#1}\parsearg\linemacroxxx}
+%\def\linemacroxxx#1#2 \end linemacro{%
+%\let\parsearg=\relax
+%\edef\macrotempx{\csname M\butfirst\expandafter\string\macrotemp\endcsname}%
+%\expandafter\xdef\macrotemp{\parsearg\macrotempx}%
+%\expandafter\gdef\macrotempx#1{#2}%
+%\endgroup}
+
+%\def\butfirst#1{}
+
+
+\message{fonts,}
+
+% Font-change commands.
+
+% Texinfo supports the sans serif font style, which plain TeX does not.
+% So we set up a \sf analogous to plain's \rm, etc.
+\newfam\sffam
+\def\sf{\fam=\sffam \tensf}
+\let\li = \sf % Sometimes we call it \li, not \sf.
+
+% We don't need math for this one.
+\def\ttsl{\tenttsl}
+
+%% Try out Computer Modern fonts at \magstephalf
+\let\mainmagstep=\magstephalf
+
+% Set the font macro #1 to the font named #2, adding on the
+% specified font prefix (normally `cm').
+% #3 is the font's design size, #4 is a scale factor
+\def\setfont#1#2#3#4{\font#1=\fontprefix#2#3 scaled #4}
+
+% Use cm as the default font prefix.
+% To specify the font prefix, you must define \fontprefix
+% before you read in texinfo.tex.
+\ifx\fontprefix\undefined
+\def\fontprefix{cm}
+\fi
+% Support font families that don't use the same naming scheme as CM.
+\def\rmshape{r}
+\def\rmbshape{bx} %where the normal face is bold
+\def\bfshape{b}
+\def\bxshape{bx}
+\def\ttshape{tt}
+\def\ttbshape{tt}
+\def\ttslshape{sltt}
+\def\itshape{ti}
+\def\itbshape{bxti}
+\def\slshape{sl}
+\def\slbshape{bxsl}
+\def\sfshape{ss}
+\def\sfbshape{ss}
+\def\scshape{csc}
+\def\scbshape{csc}
+
+\ifx\bigger\relax
+\let\mainmagstep=\magstep1
+\setfont\textrm\rmshape{12}{1000}
+\setfont\texttt\ttshape{12}{1000}
+\else
+\setfont\textrm\rmshape{10}{\mainmagstep}
+\setfont\texttt\ttshape{10}{\mainmagstep}
+\fi
+% Instead of cmb10, you many want to use cmbx10.
+% cmbx10 is a prettier font on its own, but cmb10
+% looks better when embedded in a line with cmr10.
+\setfont\textbf\bfshape{10}{\mainmagstep}
+\setfont\textit\itshape{10}{\mainmagstep}
+\setfont\textsl\slshape{10}{\mainmagstep}
+\setfont\textsf\sfshape{10}{\mainmagstep}
+\setfont\textsc\scshape{10}{\mainmagstep}
+\setfont\textttsl\ttslshape{10}{\mainmagstep}
+\font\texti=cmmi10 scaled \mainmagstep
+\font\textsy=cmsy10 scaled \mainmagstep
+
+% A few fonts for @defun, etc.
+\setfont\defbf\bxshape{10}{\magstep1} %was 1314
+\setfont\deftt\ttshape{10}{\magstep1}
+\def\df{\let\tentt=\deftt \let\tenbf = \defbf \bf}
+
+% Fonts for indices and small examples (9pt).
+% We actually use the slanted font rather than the italic,
+% because texinfo normally uses the slanted fonts for that.
+% Do not make many font distinctions in general in the index, since they
+% aren't very useful.
+\setfont\ninett\ttshape{9}{1000}
+\setfont\indrm\rmshape{9}{1000}
+\setfont\indit\slshape{9}{1000}
+\let\indsl=\indit
+\let\indtt=\ninett
+\let\indttsl=\ninett
+\let\indsf=\indrm
+\let\indbf=\indrm
+\setfont\indsc\scshape{10}{900}
+\font\indi=cmmi9
+\font\indsy=cmsy9
+
+% Chapter (and unnumbered) fonts (17.28pt).
+\setfont\chaprm\rmbshape{12}{\magstep2}
+\setfont\chapit\itbshape{10}{\magstep3}
+\setfont\chapsl\slbshape{10}{\magstep3}
+\setfont\chaptt\ttbshape{12}{\magstep2}
+\setfont\chapttsl\ttslshape{10}{\magstep3}
+\setfont\chapsf\sfbshape{12}{\magstep2}
+\let\chapbf=\chaprm
+\setfont\chapsc\scbshape{10}{\magstep3}
+\font\chapi=cmmi12 scaled \magstep2
+\font\chapsy=cmsy10 scaled \magstep3
+
+% Section fonts (14.4pt).
+\setfont\secrm\rmbshape{12}{\magstep1}
+\setfont\secit\itbshape{10}{\magstep2}
+\setfont\secsl\slbshape{10}{\magstep2}
+\setfont\sectt\ttbshape{12}{\magstep1}
+\setfont\secttsl\ttslshape{10}{\magstep2}
+\setfont\secsf\sfbshape{12}{\magstep1}
+\let\secbf\secrm
+\setfont\secsc\scbshape{10}{\magstep2}
+\font\seci=cmmi12 scaled \magstep1
+\font\secsy=cmsy10 scaled \magstep2
+
+% \setfont\ssecrm\bxshape{10}{\magstep1} % This size an font looked bad.
+% \setfont\ssecit\itshape{10}{\magstep1} % The letters were too crowded.
+% \setfont\ssecsl\slshape{10}{\magstep1}
+% \setfont\ssectt\ttshape{10}{\magstep1}
+% \setfont\ssecsf\sfshape{10}{\magstep1}
+
+%\setfont\ssecrm\bfshape{10}{1315} % Note the use of cmb rather than cmbx.
+%\setfont\ssecit\itshape{10}{1315} % Also, the size is a little larger than
+%\setfont\ssecsl\slshape{10}{1315} % being scaled magstep1.
+%\setfont\ssectt\ttshape{10}{1315}
+%\setfont\ssecsf\sfshape{10}{1315}
+
+%\let\ssecbf=\ssecrm
+
+% Subsection fonts (13.15pt).
+\setfont\ssecrm\rmbshape{12}{\magstephalf}
+\setfont\ssecit\itbshape{10}{1315}
+\setfont\ssecsl\slbshape{10}{1315}
+\setfont\ssectt\ttbshape{12}{\magstephalf}
+\setfont\ssecttsl\ttslshape{10}{\magstep1}
+\setfont\ssecsf\sfbshape{12}{\magstephalf}
+\let\ssecbf\ssecrm
+\setfont\ssecsc\scbshape{10}{\magstep1}
+\font\sseci=cmmi12 scaled \magstephalf
+\font\ssecsy=cmsy10 scaled \magstep1
+% The smallcaps and symbol fonts should actually be scaled \magstep1.5,
+% but that is not a standard magnification.
+
+% Fonts for title page:
+\setfont\titlerm\rmbshape{12}{\magstep3}
+\let\authorrm = \secrm
+
+% In order for the font changes to affect most math symbols and letters,
+% we have to define the \textfont of the standard families. Since
+% texinfo doesn't allow for producing subscripts and superscripts, we
+% don't bother to reset \scriptfont and \scriptscriptfont (which would
+% also require loading a lot more fonts).
+%
+\def\resetmathfonts{%
+ \textfont0 = \tenrm \textfont1 = \teni \textfont2 = \tensy
+ \textfont\itfam = \tenit \textfont\slfam = \tensl \textfont\bffam = \tenbf
+ \textfont\ttfam = \tentt \textfont\sffam = \tensf
+}
+
+
+% The font-changing commands redefine the meanings of \tenSTYLE, instead
+% of just \STYLE. We do this so that font changes will continue to work
+% in math mode, where it is the current \fam that is relevant in most
+% cases, not the current font. Plain TeX does \def\bf{\fam=\bffam
+% \tenbf}, for example. By redefining \tenbf, we obviate the need to
+% redefine \bf itself.
+\def\textfonts{%
+ \let\tenrm=\textrm \let\tenit=\textit \let\tensl=\textsl
+ \let\tenbf=\textbf \let\tentt=\texttt \let\smallcaps=\textsc
+ \let\tensf=\textsf \let\teni=\texti \let\tensy=\textsy \let\tenttsl=\textttsl
+ \resetmathfonts}
+\def\chapfonts{%
+ \let\tenrm=\chaprm \let\tenit=\chapit \let\tensl=\chapsl
+ \let\tenbf=\chapbf \let\tentt=\chaptt \let\smallcaps=\chapsc
+ \let\tensf=\chapsf \let\teni=\chapi \let\tensy=\chapsy \let\tenttsl=\chapttsl
+ \resetmathfonts \setleading{19pt}}
+\def\secfonts{%
+ \let\tenrm=\secrm \let\tenit=\secit \let\tensl=\secsl
+ \let\tenbf=\secbf \let\tentt=\sectt \let\smallcaps=\secsc
+ \let\tensf=\secsf \let\teni=\seci \let\tensy=\secsy \let\tenttsl=\secttsl
+ \resetmathfonts \setleading{16pt}}
+\def\subsecfonts{%
+ \let\tenrm=\ssecrm \let\tenit=\ssecit \let\tensl=\ssecsl
+ \let\tenbf=\ssecbf \let\tentt=\ssectt \let\smallcaps=\ssecsc
+ \let\tensf=\ssecsf \let\teni=\sseci \let\tensy=\ssecsy \let\tenttsl=\ssecttsl
+ \resetmathfonts \setleading{15pt}}
+\let\subsubsecfonts = \subsecfonts % Maybe make sssec fonts scaled magstephalf?
+\def\indexfonts{%
+ \let\tenrm=\indrm \let\tenit=\indit \let\tensl=\indsl
+ \let\tenbf=\indbf \let\tentt=\indtt \let\smallcaps=\indsc
+ \let\tensf=\indsf \let\teni=\indi \let\tensy=\indsy \let\tenttsl=\indttsl
+ \resetmathfonts \setleading{12pt}}
+
+% Set up the default fonts, so we can use them for creating boxes.
+%
+\textfonts
+
+% Count depth in font-changes, for error checks
+\newcount\fontdepth \fontdepth=0
+
+% Fonts for short table of contents.
+\setfont\shortcontrm\rmshape{12}{1000}
+\setfont\shortcontbf\bxshape{12}{1000}
+\setfont\shortcontsl\slshape{12}{1000}
+
+%% Add scribe-like font environments, plus @l for inline lisp (usually sans
+%% serif) and @ii for TeX italic
+
+% \smartitalic{ARG} outputs arg in italics, followed by an italic correction
+% unless the following character is such as not to need one.
+\def\smartitalicx{\ifx\next,\else\ifx\next-\else\ifx\next.\else\/\fi\fi\fi}
+\def\smartitalic#1{{\sl #1}\futurelet\next\smartitalicx}
+
+\let\i=\smartitalic
+\let\var=\smartitalic
+\let\dfn=\smartitalic
+\let\emph=\smartitalic
+\let\cite=\smartitalic
+
+\def\b#1{{\bf #1}}
+\let\strong=\b
+
+% We can't just use \exhyphenpenalty, because that only has effect at
+% the end of a paragraph. Restore normal hyphenation at the end of the
+% group within which \nohyphenation is presumably called.
+%
+\def\nohyphenation{\hyphenchar\font = -1 \aftergroup\restorehyphenation}
+\def\restorehyphenation{\hyphenchar\font = `- }
+
+\def\t#1{%
+ {\tt \rawbackslash \frenchspacing #1}%
+ \null
+}
+\let\ttfont=\t
+\def\samp #1{`\tclose{#1}'\null}
+\setfont\smallrm\rmshape{8}{1000}
+\font\smallsy=cmsy9
+\def\key#1{{\smallrm\textfont2=\smallsy \leavevmode\hbox{%
+ \raise0.4pt\hbox{$\langle$}\kern-.08em\vtop{%
+ \vbox{\hrule\kern-0.4pt
+ \hbox{\raise0.4pt\hbox{\vphantom{$\langle$}}#1}}%
+ \kern-0.4pt\hrule}%
+ \kern-.06em\raise0.4pt\hbox{$\rangle$}}}}
+% The old definition, with no lozenge:
+%\def\key #1{{\ttsl \nohyphenation \uppercase{#1}}\null}
+\def\ctrl #1{{\tt \rawbackslash \hat}#1}
+
+\let\file=\samp
+\let\url=\samp % perhaps include a hypertex \special eventually
+\def\email#1{$\langle${\tt #1}$\rangle$}
+
+% @code is a modification of @t,
+% which makes spaces the same size as normal in the surrounding text.
+\def\tclose#1{%
+ {%
+ % Change normal interword space to be same as for the current font.
+ \spaceskip = \fontdimen2\font
+ %
+ % Switch to typewriter.
+ \tt
+ %
+ % But `\ ' produces the large typewriter interword space.
+ \def\ {{\spaceskip = 0pt{} }}%
+ %
+ % Turn off hyphenation.
+ \nohyphenation
+ %
+ \rawbackslash
+ \frenchspacing
+ #1%
+ }%
+ \null
+}
+
+% We *must* turn on hyphenation at `-' and `_' in \code.
+% Otherwise, it is too hard to avoid overfull hboxes
+% in the Emacs manual, the Library manual, etc.
+
+% Unfortunately, TeX uses one parameter (\hyphenchar) to control
+% both hyphenation at - and hyphenation within words.
+% We must therefore turn them both off (\tclose does that)
+% and arrange explicitly to hyphenate at a dash.
+% -- rms.
+{
+\catcode`\-=\active
+\catcode`\_=\active
+\global\def\code{\begingroup \catcode`\-=\active \let-\codedash \catcode`\_=\active \let_\codeunder \codex}
+% The following is used by \doprintindex to insure that long function names
+% wrap around. It is necessary for - and _ to be active before the index is
+% read from the file, as \entry parses the arguments long before \code is
+% ever called. -- mycroft
+\global\def\indexbreaks{\catcode`\-=\active \let-\realdash \catcode`\_=\active \let_\realunder}
+}
+
+\def\realdash{-}
+\def\realunder{_}
+\def\codedash{-\discretionary{}{}{}}
+\def\codeunder{\normalunderscore\discretionary{}{}{}}
+\def\codex #1{\tclose{#1}\endgroup}
+
+%\let\exp=\tclose %Was temporary
+
+% @kbd is like @code, except that if the argument is just one @key command,
+% then @kbd has no effect.
+%
+\def\xkey{\key}
+\def\kbdfoo#1#2#3\par{\def\one{#1}\def\three{#3}\def\threex{??}%
+\ifx\one\xkey\ifx\threex\three \key{#2}%
+\else{\tclose{\ttsl\look}}\fi
+\else{\tclose{\ttsl\look}}\fi}
+
+% Check if we are currently using a typewriter font. Since all the
+% Computer Modern typewriter fonts have zero interword stretch (and
+% shrink), and it is reasonable to expect all typewriter fonts to have
+% this property, we can check that font parameter.
+%
+\def\ifmonospace{\ifdim\fontdimen3\font=0pt }
+
+% Typeset a dimension, e.g., `in' or `pt'. The only reason for the
+% argument is to make the input look right: @dmn{pt} instead of
+% @dmn{}pt.
+%
+\def\dmn#1{\thinspace #1}
+
+\def\kbd#1{\def\look{#1}\expandafter\kbdfoo\look??\par}
+
+% @l was never documented to mean ``switch to the Lisp font'',
+% and it is not used as such in any manual I can find. We need it for
+% Polish suppressed-l. --karl, 22sep96.
+%\def\l#1{{\li #1}\null}
+
+\def\r#1{{\rm #1}} % roman font
+% Use of \lowercase was suggested.
+\def\sc#1{{\smallcaps#1}} % smallcaps font
+\def\ii#1{{\it #1}} % italic font
+
+% @pounds{} is a sterling sign.
+\def\pounds{{\it\$}}
+
+
+\message{page headings,}
+
+\newskip\titlepagetopglue \titlepagetopglue = 1.5in
+\newskip\titlepagebottomglue \titlepagebottomglue = 2pc
+
+% First the title page. Must do @settitle before @titlepage.
+\def\titlefont#1{{\titlerm #1}}
+
+\newif\ifseenauthor
+\newif\iffinishedtitlepage
+
+\def\shorttitlepage{\parsearg\shorttitlepagezzz}
+\def\shorttitlepagezzz #1{\begingroup\hbox{}\vskip 1.5in \chaprm \centerline{#1}%
+ \endgroup\page\hbox{}\page}
+
+\def\titlepage{\begingroup \parindent=0pt \textfonts
+ \let\subtitlerm=\tenrm
+% I deinstalled the following change because \cmr12 is undefined.
+% This change was not in the ChangeLog anyway. --rms.
+% \let\subtitlerm=\cmr12
+ \def\subtitlefont{\subtitlerm \normalbaselineskip = 13pt \normalbaselines}%
+ %
+ \def\authorfont{\authorrm \normalbaselineskip = 16pt \normalbaselines}%
+ %
+ % Leave some space at the very top of the page.
+ \vglue\titlepagetopglue
+ %
+ % Now you can print the title using @title.
+ \def\title{\parsearg\titlezzz}%
+ \def\titlezzz##1{\leftline{\titlefont{##1}}
+ % print a rule at the page bottom also.
+ \finishedtitlepagefalse
+ \vskip4pt \hrule height 4pt width \hsize \vskip4pt}%
+ % No rule at page bottom unless we print one at the top with @title.
+ \finishedtitlepagetrue
+ %
+ % Now you can put text using @subtitle.
+ \def\subtitle{\parsearg\subtitlezzz}%
+ \def\subtitlezzz##1{{\subtitlefont \rightline{##1}}}%
+ %
+ % @author should come last, but may come many times.
+ \def\author{\parsearg\authorzzz}%
+ \def\authorzzz##1{\ifseenauthor\else\vskip 0pt plus 1filll\seenauthortrue\fi
+ {\authorfont \leftline{##1}}}%
+ %
+ % Most title ``pages'' are actually two pages long, with space
+ % at the top of the second. We don't want the ragged left on the second.
+ \let\oldpage = \page
+ \def\page{%
+ \iffinishedtitlepage\else
+ \finishtitlepage
+ \fi
+ \oldpage
+ \let\page = \oldpage
+ \hbox{}}%
+% \def\page{\oldpage \hbox{}}
+}
+
+\def\Etitlepage{%
+ \iffinishedtitlepage\else
+ \finishtitlepage
+ \fi
+ % It is important to do the page break before ending the group,
+ % because the headline and footline are only empty inside the group.
+ % If we use the new definition of \page, we always get a blank page
+ % after the title page, which we certainly don't want.
+ \oldpage
+ \endgroup
+ \HEADINGSon
+}
+
+\def\finishtitlepage{%
+ \vskip4pt \hrule height 2pt width \hsize
+ \vskip\titlepagebottomglue
+ \finishedtitlepagetrue
+}
+
+%%% Set up page headings and footings.
+
+\let\thispage=\folio
+
+\newtoks \evenheadline % Token sequence for heading line of even pages
+\newtoks \oddheadline % Token sequence for heading line of odd pages
+\newtoks \evenfootline % Token sequence for footing line of even pages
+\newtoks \oddfootline % Token sequence for footing line of odd pages
+
+% Now make Tex use those variables
+\headline={{\textfonts\rm \ifodd\pageno \the\oddheadline
+ \else \the\evenheadline \fi}}
+\footline={{\textfonts\rm \ifodd\pageno \the\oddfootline
+ \else \the\evenfootline \fi}\HEADINGShook}
+\let\HEADINGShook=\relax
+
+% Commands to set those variables.
+% For example, this is what @headings on does
+% @evenheading @thistitle|@thispage|@thischapter
+% @oddheading @thischapter|@thispage|@thistitle
+% @evenfooting @thisfile||
+% @oddfooting ||@thisfile
+
+\def\evenheading{\parsearg\evenheadingxxx}
+\def\oddheading{\parsearg\oddheadingxxx}
+\def\everyheading{\parsearg\everyheadingxxx}
+
+\def\evenfooting{\parsearg\evenfootingxxx}
+\def\oddfooting{\parsearg\oddfootingxxx}
+\def\everyfooting{\parsearg\everyfootingxxx}
+
+{\catcode`\@=0 %
+
+\gdef\evenheadingxxx #1{\evenheadingyyy #1@|@|@|@|\finish}
+\gdef\evenheadingyyy #1@|#2@|#3@|#4\finish{%
+\global\evenheadline={\rlap{\centerline{#2}}\line{#1\hfil#3}}}
+
+\gdef\oddheadingxxx #1{\oddheadingyyy #1@|@|@|@|\finish}
+\gdef\oddheadingyyy #1@|#2@|#3@|#4\finish{%
+\global\oddheadline={\rlap{\centerline{#2}}\line{#1\hfil#3}}}
+
+\gdef\everyheadingxxx #1{\everyheadingyyy #1@|@|@|@|\finish}
+\gdef\everyheadingyyy #1@|#2@|#3@|#4\finish{%
+\global\evenheadline={\rlap{\centerline{#2}}\line{#1\hfil#3}}
+\global\oddheadline={\rlap{\centerline{#2}}\line{#1\hfil#3}}}
+
+\gdef\evenfootingxxx #1{\evenfootingyyy #1@|@|@|@|\finish}
+\gdef\evenfootingyyy #1@|#2@|#3@|#4\finish{%
+\global\evenfootline={\rlap{\centerline{#2}}\line{#1\hfil#3}}}
+
+\gdef\oddfootingxxx #1{\oddfootingyyy #1@|@|@|@|\finish}
+\gdef\oddfootingyyy #1@|#2@|#3@|#4\finish{%
+\global\oddfootline={\rlap{\centerline{#2}}\line{#1\hfil#3}}}
+
+\gdef\everyfootingxxx #1{\everyfootingyyy #1@|@|@|@|\finish}
+\gdef\everyfootingyyy #1@|#2@|#3@|#4\finish{%
+\global\evenfootline={\rlap{\centerline{#2}}\line{#1\hfil#3}}
+\global\oddfootline={\rlap{\centerline{#2}}\line{#1\hfil#3}}}
+%
+}% unbind the catcode of @.
+
+% @headings double turns headings on for double-sided printing.
+% @headings single turns headings on for single-sided printing.
+% @headings off turns them off.
+% @headings on same as @headings double, retained for compatibility.
+% @headings after turns on double-sided headings after this page.
+% @headings doubleafter turns on double-sided headings after this page.
+% @headings singleafter turns on single-sided headings after this page.
+% By default, they are off at the start of a document,
+% and turned `on' after @end titlepage.
+
+\def\headings #1 {\csname HEADINGS#1\endcsname}
+
+\def\HEADINGSoff{
+\global\evenheadline={\hfil} \global\evenfootline={\hfil}
+\global\oddheadline={\hfil} \global\oddfootline={\hfil}}
+\HEADINGSoff
+% When we turn headings on, set the page number to 1.
+% For double-sided printing, put current file name in lower left corner,
+% chapter name on inside top of right hand pages, document
+% title on inside top of left hand pages, and page numbers on outside top
+% edge of all pages.
+\def\HEADINGSdouble{
+\global\pageno=1
+\global\evenfootline={\hfil}
+\global\oddfootline={\hfil}
+\global\evenheadline={\line{\folio\hfil\thistitle}}
+\global\oddheadline={\line{\thischapter\hfil\folio}}
+\global\let\contentsalignmacro = \chapoddpage
+}
+\let\contentsalignmacro = \chappager
+
+% For single-sided printing, chapter title goes across top left of page,
+% page number on top right.
+\def\HEADINGSsingle{
+\global\pageno=1
+\global\evenfootline={\hfil}
+\global\oddfootline={\hfil}
+\global\evenheadline={\line{\thischapter\hfil\folio}}
+\global\oddheadline={\line{\thischapter\hfil\folio}}
+\global\let\contentsalignmacro = \chappager
+}
+\def\HEADINGSon{\HEADINGSdouble}
+
+\def\HEADINGSafter{\let\HEADINGShook=\HEADINGSdoublex}
+\let\HEADINGSdoubleafter=\HEADINGSafter
+\def\HEADINGSdoublex{%
+\global\evenfootline={\hfil}
+\global\oddfootline={\hfil}
+\global\evenheadline={\line{\folio\hfil\thistitle}}
+\global\oddheadline={\line{\thischapter\hfil\folio}}
+\global\let\contentsalignmacro = \chapoddpage
+}
+
+\def\HEADINGSsingleafter{\let\HEADINGShook=\HEADINGSsinglex}
+\def\HEADINGSsinglex{%
+\global\evenfootline={\hfil}
+\global\oddfootline={\hfil}
+\global\evenheadline={\line{\thischapter\hfil\folio}}
+\global\oddheadline={\line{\thischapter\hfil\folio}}
+\global\let\contentsalignmacro = \chappager
+}
+
+% Subroutines used in generating headings
+% Produces Day Month Year style of output.
+\def\today{\number\day\space
+\ifcase\month\or
+January\or February\or March\or April\or May\or June\or
+July\or August\or September\or October\or November\or December\fi
+\space\number\year}
+
+% Use this if you want the Month Day, Year style of output.
+%\def\today{\ifcase\month\or
+%January\or February\or March\or April\or May\or June\or
+%July\or August\or September\or October\or November\or December\fi
+%\space\number\day, \number\year}
+
+% @settitle line... specifies the title of the document, for headings
+% It generates no output of its own
+
+\def\thistitle{No Title}
+\def\settitle{\parsearg\settitlezzz}
+\def\settitlezzz #1{\gdef\thistitle{#1}}
+
+
+\message{tables,}
+
+% @tabs -- simple alignment
+
+% These don't work. For one thing, \+ is defined as outer.
+% So these macros cannot even be defined.
+
+%\def\tabs{\parsearg\tabszzz}
+%\def\tabszzz #1{\settabs\+#1\cr}
+%\def\tabline{\parsearg\tablinezzz}
+%\def\tablinezzz #1{\+#1\cr}
+%\def\&{&}
+
+% Tables -- @table, @ftable, @vtable, @item(x), @kitem(x), @xitem(x).
+
+% default indentation of table text
+\newdimen\tableindent \tableindent=.8in
+% default indentation of @itemize and @enumerate text
+\newdimen\itemindent \itemindent=.3in
+% margin between end of table item and start of table text.
+\newdimen\itemmargin \itemmargin=.1in
+
+% used internally for \itemindent minus \itemmargin
+\newdimen\itemmax
+
+% Note @table, @vtable, and @vtable define @item, @itemx, etc., with
+% these defs.
+% They also define \itemindex
+% to index the item name in whatever manner is desired (perhaps none).
+
+\newif\ifitemxneedsnegativevskip
+
+\def\itemxpar{\par\ifitemxneedsnegativevskip\nobreak\vskip-\parskip\nobreak\fi}
+
+\def\internalBitem{\smallbreak \parsearg\itemzzz}
+\def\internalBitemx{\itemxpar \parsearg\itemzzz}
+
+\def\internalBxitem "#1"{\def\xitemsubtopix{#1} \smallbreak \parsearg\xitemzzz}
+\def\internalBxitemx "#1"{\def\xitemsubtopix{#1} \itemxpar \parsearg\xitemzzz}
+
+\def\internalBkitem{\smallbreak \parsearg\kitemzzz}
+\def\internalBkitemx{\itemxpar \parsearg\kitemzzz}
+
+\def\kitemzzz #1{\dosubind {kw}{\code{#1}}{for {\bf \lastfunction}}%
+ \itemzzz {#1}}
+
+\def\xitemzzz #1{\dosubind {kw}{\code{#1}}{for {\bf \xitemsubtopic}}%
+ \itemzzz {#1}}
+
+\def\itemzzz #1{\begingroup %
+ \advance\hsize by -\rightskip
+ \advance\hsize by -\tableindent
+ \setbox0=\hbox{\itemfont{#1}}%
+ \itemindex{#1}%
+ \nobreak % This prevents a break before @itemx.
+ %
+ % Be sure we are not still in the middle of a paragraph.
+ %{\parskip = 0in
+ %\par
+ %}%
+ %
+ % If the item text does not fit in the space we have, put it on a line
+ % by itself, and do not allow a page break either before or after that
+ % line. We do not start a paragraph here because then if the next
+ % command is, e.g., @kindex, the whatsit would get put into the
+ % horizontal list on a line by itself, resulting in extra blank space.
+ \ifdim \wd0>\itemmax
+ %
+ % Make this a paragraph so we get the \parskip glue and wrapping,
+ % but leave it ragged-right.
+ \begingroup
+ \advance\leftskip by-\tableindent
+ \advance\hsize by\tableindent
+ \advance\rightskip by0pt plus1fil
+ \leavevmode\unhbox0\par
+ \endgroup
+ %
+ % We're going to be starting a paragraph, but we don't want the
+ % \parskip glue -- logically it's part of the @item we just started.
+ \nobreak \vskip-\parskip
+ %
+ % Stop a page break at the \parskip glue coming up. Unfortunately
+ % we can't prevent a possible page break at the following
+ % \baselineskip glue.
+ \nobreak
+ \endgroup
+ \itemxneedsnegativevskipfalse
+ \else
+ % The item text fits into the space. Start a paragraph, so that the
+ % following text (if any) will end up on the same line. Since that
+ % text will be indented by \tableindent, we make the item text be in
+ % a zero-width box.
+ \noindent
+ \rlap{\hskip -\tableindent\box0}\ignorespaces%
+ \endgroup%
+ \itemxneedsnegativevskiptrue%
+ \fi
+}
+
+\def\item{\errmessage{@item while not in a table}}
+\def\itemx{\errmessage{@itemx while not in a table}}
+\def\kitem{\errmessage{@kitem while not in a table}}
+\def\kitemx{\errmessage{@kitemx while not in a table}}
+\def\xitem{\errmessage{@xitem while not in a table}}
+\def\xitemx{\errmessage{@xitemx while not in a table}}
+
+%% Contains a kludge to get @end[description] to work
+\def\description{\tablez{\dontindex}{1}{}{}{}{}}
+
+\def\table{\begingroup\inENV\obeylines\obeyspaces\tablex}
+{\obeylines\obeyspaces%
+\gdef\tablex #1^^M{%
+\tabley\dontindex#1 \endtabley}}
+
+\def\ftable{\begingroup\inENV\obeylines\obeyspaces\ftablex}
+{\obeylines\obeyspaces%
+\gdef\ftablex #1^^M{%
+\tabley\fnitemindex#1 \endtabley
+\def\Eftable{\endgraf\afterenvbreak\endgroup}%
+\let\Etable=\relax}}
+
+\def\vtable{\begingroup\inENV\obeylines\obeyspaces\vtablex}
+{\obeylines\obeyspaces%
+\gdef\vtablex #1^^M{%
+\tabley\vritemindex#1 \endtabley
+\def\Evtable{\endgraf\afterenvbreak\endgroup}%
+\let\Etable=\relax}}
+
+\def\dontindex #1{}
+\def\fnitemindex #1{\doind {fn}{\code{#1}}}%
+\def\vritemindex #1{\doind {vr}{\code{#1}}}%
+
+{\obeyspaces %
+\gdef\tabley#1#2 #3 #4 #5 #6 #7\endtabley{\endgroup%
+\tablez{#1}{#2}{#3}{#4}{#5}{#6}}}
+
+\def\tablez #1#2#3#4#5#6{%
+\aboveenvbreak %
+\begingroup %
+\def\Edescription{\Etable}% Necessary kludge.
+\let\itemindex=#1%
+\ifnum 0#3>0 \advance \leftskip by #3\mil \fi %
+\ifnum 0#4>0 \tableindent=#4\mil \fi %
+\ifnum 0#5>0 \advance \rightskip by #5\mil \fi %
+\def\itemfont{#2}%
+\itemmax=\tableindent %
+\advance \itemmax by -\itemmargin %
+\advance \leftskip by \tableindent %
+\exdentamount=\tableindent
+\parindent = 0pt
+\parskip = \smallskipamount
+\ifdim \parskip=0pt \parskip=2pt \fi%
+\def\Etable{\endgraf\afterenvbreak\endgroup}%
+\let\item = \internalBitem %
+\let\itemx = \internalBitemx %
+\let\kitem = \internalBkitem %
+\let\kitemx = \internalBkitemx %
+\let\xitem = \internalBxitem %
+\let\xitemx = \internalBxitemx %
+}
+
+% This is the counter used by @enumerate, which is really @itemize
+
+\newcount \itemno
+
+\def\itemize{\parsearg\itemizezzz}
+
+\def\itemizezzz #1{%
+ \begingroup % ended by the @end itemsize
+ \itemizey {#1}{\Eitemize}
+}
+
+\def\itemizey #1#2{%
+\aboveenvbreak %
+\itemmax=\itemindent %
+\advance \itemmax by -\itemmargin %
+\advance \leftskip by \itemindent %
+\exdentamount=\itemindent
+\parindent = 0pt %
+\parskip = \smallskipamount %
+\ifdim \parskip=0pt \parskip=2pt \fi%
+\def#2{\endgraf\afterenvbreak\endgroup}%
+\def\itemcontents{#1}%
+\let\item=\itemizeitem}
+
+% Set sfcode to normal for the chars that usually have another value.
+% These are `.?!:;,'
+\def\frenchspacing{\sfcode46=1000 \sfcode63=1000 \sfcode33=1000
+ \sfcode58=1000 \sfcode59=1000 \sfcode44=1000 }
+
+% \splitoff TOKENS\endmark defines \first to be the first token in
+% TOKENS, and \rest to be the remainder.
+%
+\def\splitoff#1#2\endmark{\def\first{#1}\def\rest{#2}}%
+
+% Allow an optional argument of an uppercase letter, lowercase letter,
+% or number, to specify the first label in the enumerated list. No
+% argument is the same as `1'.
+%
+\def\enumerate{\parsearg\enumeratezzz}
+\def\enumeratezzz #1{\enumeratey #1 \endenumeratey}
+\def\enumeratey #1 #2\endenumeratey{%
+ \begingroup % ended by the @end enumerate
+ %
+ % If we were given no argument, pretend we were given `1'.
+ \def\thearg{#1}%
+ \ifx\thearg\empty \def\thearg{1}\fi
+ %
+ % Detect if the argument is a single token. If so, it might be a
+ % letter. Otherwise, the only valid thing it can be is a number.
+ % (We will always have one token, because of the test we just made.
+ % This is a good thing, since \splitoff doesn't work given nothing at
+ % all -- the first parameter is undelimited.)
+ \expandafter\splitoff\thearg\endmark
+ \ifx\rest\empty
+ % Only one token in the argument. It could still be anything.
+ % A ``lowercase letter'' is one whose \lccode is nonzero.
+ % An ``uppercase letter'' is one whose \lccode is both nonzero, and
+ % not equal to itself.
+ % Otherwise, we assume it's a number.
+ %
+ % We need the \relax at the end of the \ifnum lines to stop TeX from
+ % continuing to look for a <number>.
+ %
+ \ifnum\lccode\expandafter`\thearg=0\relax
+ \numericenumerate % a number (we hope)
+ \else
+ % It's a letter.
+ \ifnum\lccode\expandafter`\thearg=\expandafter`\thearg\relax
+ \lowercaseenumerate % lowercase letter
+ \else
+ \uppercaseenumerate % uppercase letter
+ \fi
+ \fi
+ \else
+ % Multiple tokens in the argument. We hope it's a number.
+ \numericenumerate
+ \fi
+}
+
+% An @enumerate whose labels are integers. The starting integer is
+% given in \thearg.
+%
+\def\numericenumerate{%
+ \itemno = \thearg
+ \startenumeration{\the\itemno}%
+}
+
+% The starting (lowercase) letter is in \thearg.
+\def\lowercaseenumerate{%
+ \itemno = \expandafter`\thearg
+ \startenumeration{%
+ % Be sure we're not beyond the end of the alphabet.
+ \ifnum\itemno=0
+ \errmessage{No more lowercase letters in @enumerate; get a bigger
+ alphabet}%
+ \fi
+ \char\lccode\itemno
+ }%
+}
+
+% The starting (uppercase) letter is in \thearg.
+\def\uppercaseenumerate{%
+ \itemno = \expandafter`\thearg
+ \startenumeration{%
+ % Be sure we're not beyond the end of the alphabet.
+ \ifnum\itemno=0
+ \errmessage{No more uppercase letters in @enumerate; get a bigger
+ alphabet}
+ \fi
+ \char\uccode\itemno
+ }%
+}
+
+% Call itemizey, adding a period to the first argument and supplying the
+% common last two arguments. Also subtract one from the initial value in
+% \itemno, since @item increments \itemno.
+%
+\def\startenumeration#1{%
+ \advance\itemno by -1
+ \itemizey{#1.}\Eenumerate\flushcr
+}
+
+% @alphaenumerate and @capsenumerate are abbreviations for giving an arg
+% to @enumerate.
+%
+\def\alphaenumerate{\enumerate{a}}
+\def\capsenumerate{\enumerate{A}}
+\def\Ealphaenumerate{\Eenumerate}
+\def\Ecapsenumerate{\Eenumerate}
+
+% Definition of @item while inside @itemize.
+
+\def\itemizeitem{%
+\advance\itemno by 1
+{\let\par=\endgraf \smallbreak}%
+\ifhmode \errmessage{\in hmode at itemizeitem}\fi
+{\parskip=0in \hskip 0pt
+\hbox to 0pt{\hss \itemcontents\hskip \itemmargin}%
+\vadjust{\penalty 1200}}%
+\flushcr}
+
+% @multitable macros
+% Amy Hendrickson, 8/18/94, 3/6/96
+%
+% @multitable ... @end multitable will make as many columns as desired.
+% Contents of each column will wrap at width given in preamble. Width
+% can be specified either with sample text given in a template line,
+% or in percent of \hsize, the current width of text on page.
+
+% Table can continue over pages but will only break between lines.
+
+% To make preamble:
+%
+% Either define widths of columns in terms of percent of \hsize:
+% @multitable @columnfractions .25 .3 .45
+% @item ...
+%
+% Numbers following @columnfractions are the percent of the total
+% current hsize to be used for each column. You may use as many
+% columns as desired.
+
+
+% Or use a template:
+% @multitable {Column 1 template} {Column 2 template} {Column 3 template}
+% @item ...
+% using the widest term desired in each column.
+%
+% For those who want to use more than one line's worth of words in
+% the preamble, break the line within one argument and it
+% will parse correctly, i.e.,
+%
+% @multitable {Column 1 template} {Column 2 template} {Column 3
+% template}
+% Not:
+% @multitable {Column 1 template} {Column 2 template}
+% {Column 3 template}
+
+% Each new table line starts with @item, each subsequent new column
+% starts with @tab. Empty columns may be produced by supplying @tab's
+% with nothing between them for as many times as empty columns are needed,
+% ie, @tab@tab@tab will produce two empty columns.
+
+% @item, @tab, @multitable or @end multitable do not need to be on their
+% own lines, but it will not hurt if they are.
+
+% Sample multitable:
+
+% @multitable {Column 1 template} {Column 2 template} {Column 3 template}
+% @item first col stuff @tab second col stuff @tab third col
+% @item
+% first col stuff
+% @tab
+% second col stuff
+% @tab
+% third col
+% @item first col stuff @tab second col stuff
+% @tab Many paragraphs of text may be used in any column.
+%
+% They will wrap at the width determined by the template.
+% @item@tab@tab This will be in third column.
+% @end multitable
+
+% Default dimensions may be reset by user.
+% @multitableparskip is vertical space between paragraphs in table.
+% @multitableparindent is paragraph indent in table.
+% @multitablecolmargin is horizontal space to be left between columns.
+% @multitablelinespace is space to leave between table items, baseline
+% to baseline.
+% 0pt means it depends on current normal line spacing.
+
+%%%%
+% Dimensions
+
+\newskip\multitableparskip
+\newskip\multitableparindent
+\newdimen\multitablecolspace
+\newskip\multitablelinespace
+\multitableparskip=0pt
+\multitableparindent=6pt
+\multitablecolspace=12pt
+\multitablelinespace=0pt
+
+%%%%
+% Macros used to set up halign preamble:
+\let\endsetuptable\relax
+\def\xendsetuptable{\endsetuptable}
+\let\columnfractions\relax
+\def\xcolumnfractions{\columnfractions}
+\newif\ifsetpercent
+
+%% 2/1/96, to allow fractions to be given with more than one digit.
+\def\pickupwholefraction#1 {\global\advance\colcount by1 %
+\expandafter\xdef\csname col\the\colcount\endcsname{.#1\hsize}%
+\setuptable}
+
+\newcount\colcount
+\def\setuptable#1{\def\firstarg{#1}%
+\ifx\firstarg\xendsetuptable\let\go\relax%
+\else
+ \ifx\firstarg\xcolumnfractions\global\setpercenttrue%
+ \else
+ \ifsetpercent
+ \let\go\pickupwholefraction % In this case arg of setuptable
+ % is the decimal point before the
+ % number given in percent of hsize.
+ % We don't need this so we don't use it.
+ \else
+ \global\advance\colcount by1
+ \setbox0=\hbox{#1 }% Add a normal word space as a separator;
+ % typically that is always in the input, anyway.
+ \expandafter\xdef\csname col\the\colcount\endcsname{\the\wd0}%
+ \fi%
+ \fi%
+\ifx\go\pickupwholefraction\else\let\go\setuptable\fi%
+\fi\go}
+
+%%%%
+% multitable syntax
+\def\tab{&\hskip1sp\relax} % 2/2/96
+ % tiny skip here makes sure this column space is
+ % maintained, even if it is never used.
+
+
+%%%%
+% @multitable ... @end multitable definitions:
+
+\def\multitable{\parsearg\dotable}
+
+\def\dotable#1{\bgroup
+\let\item\cr
+\tolerance=9500
+\hbadness=9500
+\setmultitablespacing
+\parskip=\multitableparskip
+\parindent=\multitableparindent
+\overfullrule=0pt
+\global\colcount=0\relax%
+\def\Emultitable{\global\setpercentfalse\global\everycr{}\cr\egroup\egroup}%
+ % To parse everything between @multitable and @item :
+\setuptable#1 \endsetuptable
+ % Need to reset this to 0 after \setuptable.
+\global\colcount=0\relax%
+ %
+ % This preamble sets up a generic column definition, which will
+ % be used as many times as user calls for columns.
+ % \vtop will set a single line and will also let text wrap and
+ % continue for many paragraphs if desired.
+\halign\bgroup&\global\advance\colcount by 1\relax%
+\multistrut\vtop{\hsize=\expandafter\csname col\the\colcount\endcsname
+ % In order to keep entries from bumping into each other
+ % we will add a \leftskip of \multitablecolspace to all columns after
+ % the first one.
+ % If a template has been used, we will add \multitablecolspace
+ % to the width of each template entry.
+ % If user has set preamble in terms of percent of \hsize
+ % we will use that dimension as the width of the column, and
+ % the \leftskip will keep entries from bumping into each other.
+ % Table will start at left margin and final column will justify at
+ % right margin.
+\ifnum\colcount=1
+\else
+ \ifsetpercent
+ \else
+ % If user has <not> set preamble in terms of percent of \hsize
+ % we will advance \hsize by \multitablecolspace
+ \advance\hsize by \multitablecolspace
+ \fi
+ % In either case we will make \leftskip=\multitablecolspace:
+\leftskip=\multitablecolspace
+\fi
+\noindent##\multistrut}\cr%
+ % \everycr will reset column counter, \colcount, at the end of
+ % each line. Every column entry will cause \colcount to advance by one.
+ % The table preamble
+ % looks at the current \colcount to find the correct column width.
+\global\everycr{\noalign{%
+\filbreak%% keeps underfull box messages off when table breaks over pages.
+\global\colcount=0\relax}}
+}
+
+\def\setmultitablespacing{% test to see if user has set \multitablelinespace.
+% If so, do nothing. If not, give it an appropriate dimension based on
+% current baselineskip.
+\ifdim\multitablelinespace=0pt
+%% strut to put in table in case some entry doesn't have descenders,
+%% to keep lines equally spaced
+\let\multistrut = \strut
+%% Test to see if parskip is larger than space between lines of
+%% table. If not, do nothing.
+%% If so, set to same dimension as multitablelinespace.
+\else
+\gdef\multistrut{\vrule height\multitablelinespace depth\dp0
+width0pt\relax} \fi
+\ifdim\multitableparskip>\multitablelinespace
+\global\multitableparskip=\multitablelinespace
+\global\advance\multitableparskip-7pt %% to keep parskip somewhat smaller
+ %% than skip between lines in the table.
+\fi%
+\ifdim\multitableparskip=0pt
+\global\multitableparskip=\multitablelinespace
+\global\advance\multitableparskip-7pt %% to keep parskip somewhat smaller
+ %% than skip between lines in the table.
+\fi}
+
+
+\message{indexing,}
+% Index generation facilities
+
+% Define \newwrite to be identical to plain tex's \newwrite
+% except not \outer, so it can be used within \newindex.
+{\catcode`\@=11
+\gdef\newwrite{\alloc@7\write\chardef\sixt@@n}}
+
+% \newindex {foo} defines an index named foo.
+% It automatically defines \fooindex such that
+% \fooindex ...rest of line... puts an entry in the index foo.
+% It also defines \fooindfile to be the number of the output channel for
+% the file that accumulates this index. The file's extension is foo.
+% The name of an index should be no more than 2 characters long
+% for the sake of vms.
+
+\def\newindex #1{
+\expandafter\newwrite \csname#1indfile\endcsname% Define number for output file
+\openout \csname#1indfile\endcsname \jobname.#1 % Open the file
+\expandafter\xdef\csname#1index\endcsname{% % Define \xxxindex
+\noexpand\doindex {#1}}
+}
+
+% @defindex foo == \newindex{foo}
+
+\def\defindex{\parsearg\newindex}
+
+% Define @defcodeindex, like @defindex except put all entries in @code.
+
+\def\newcodeindex #1{
+\expandafter\newwrite \csname#1indfile\endcsname% Define number for output file
+\openout \csname#1indfile\endcsname \jobname.#1 % Open the file
+\expandafter\xdef\csname#1index\endcsname{% % Define \xxxindex
+\noexpand\docodeindex {#1}}
+}
+
+\def\defcodeindex{\parsearg\newcodeindex}
+
+% @synindex foo bar makes index foo feed into index bar.
+% Do this instead of @defindex foo if you don't want it as a separate index.
+\def\synindex #1 #2 {%
+\expandafter\let\expandafter\synindexfoo\expandafter=\csname#2indfile\endcsname
+\expandafter\let\csname#1indfile\endcsname=\synindexfoo
+\expandafter\xdef\csname#1index\endcsname{% % Define \xxxindex
+\noexpand\doindex {#2}}%
+}
+
+% @syncodeindex foo bar similar, but put all entries made for index foo
+% inside @code.
+\def\syncodeindex #1 #2 {%
+\expandafter\let\expandafter\synindexfoo\expandafter=\csname#2indfile\endcsname
+\expandafter\let\csname#1indfile\endcsname=\synindexfoo
+\expandafter\xdef\csname#1index\endcsname{% % Define \xxxindex
+\noexpand\docodeindex {#2}}%
+}
+
+% Define \doindex, the driver for all \fooindex macros.
+% Argument #1 is generated by the calling \fooindex macro,
+% and it is "foo", the name of the index.
+
+% \doindex just uses \parsearg; it calls \doind for the actual work.
+% This is because \doind is more useful to call from other macros.
+
+% There is also \dosubind {index}{topic}{subtopic}
+% which makes an entry in a two-level index such as the operation index.
+
+\def\doindex#1{\edef\indexname{#1}\parsearg\singleindexer}
+\def\singleindexer #1{\doind{\indexname}{#1}}
+
+% like the previous two, but they put @code around the argument.
+\def\docodeindex#1{\edef\indexname{#1}\parsearg\singlecodeindexer}
+\def\singlecodeindexer #1{\doind{\indexname}{\code{#1}}}
+
+\def\indexdummies{%
+% Take care of the plain tex accent commands.
+\def\"{\realbackslash "}%
+\def\`{\realbackslash `}%
+\def\'{\realbackslash '}%
+\def\^{\realbackslash ^}%
+\def\~{\realbackslash ~}%
+\def\={\realbackslash =}%
+\def\b{\realbackslash b}%
+\def\c{\realbackslash c}%
+\def\d{\realbackslash d}%
+\def\u{\realbackslash u}%
+\def\v{\realbackslash v}%
+\def\H{\realbackslash H}%
+% Take care of the plain tex special European modified letters.
+\def\oe{\realbackslash oe}%
+\def\ae{\realbackslash ae}%
+\def\aa{\realbackslash aa}%
+\def\OE{\realbackslash OE}%
+\def\AE{\realbackslash AE}%
+\def\AA{\realbackslash AA}%
+\def\o{\realbackslash o}%
+\def\O{\realbackslash O}%
+\def\l{\realbackslash l}%
+\def\L{\realbackslash L}%
+\def\ss{\realbackslash ss}%
+% Take care of texinfo commands likely to appear in an index entry.
+% (Must be a way to avoid doing expansion at all, and thus not have to
+% laboriously list every single command here.)
+\def\@{@}% will be @@ when we switch to @ as escape char.
+%\let\{ = \lbracecmd
+%\let\} = \rbracecmd
+\def\_{{\realbackslash _}}%
+\def\w{\realbackslash w }%
+\def\bf{\realbackslash bf }%
+%\def\rm{\realbackslash rm }%
+\def\sl{\realbackslash sl }%
+\def\sf{\realbackslash sf}%
+\def\tt{\realbackslash tt}%
+\def\gtr{\realbackslash gtr}%
+\def\less{\realbackslash less}%
+\def\hat{\realbackslash hat}%
+%\def\char{\realbackslash char}%
+\def\TeX{\realbackslash TeX}%
+\def\dots{\realbackslash dots }%
+\def\copyright{\realbackslash copyright }%
+\def\tclose##1{\realbackslash tclose {##1}}%
+\def\code##1{\realbackslash code {##1}}%
+\def\dotless##1{\realbackslash dotless {##1}}%
+\def\samp##1{\realbackslash samp {##1}}%
+\def\,##1{\realbackslash ,{##1}}%
+\def\t##1{\realbackslash t {##1}}%
+\def\r##1{\realbackslash r {##1}}%
+\def\i##1{\realbackslash i {##1}}%
+\def\b##1{\realbackslash b {##1}}%
+\def\cite##1{\realbackslash cite {##1}}%
+\def\key##1{\realbackslash key {##1}}%
+\def\file##1{\realbackslash file {##1}}%
+\def\var##1{\realbackslash var {##1}}%
+\def\kbd##1{\realbackslash kbd {##1}}%
+\def\dfn##1{\realbackslash dfn {##1}}%
+\def\emph##1{\realbackslash emph {##1}}%
+\unsepspaces
+}
+
+% If an index command is used in an @example environment, any spaces
+% therein should become regular spaces in the raw index file, not the
+% expansion of \tie (\\leavevmode \penalty \@M \ ).
+{\obeyspaces
+ \gdef\unsepspaces{\obeyspaces\let =\space}}
+
+% \indexnofonts no-ops all font-change commands.
+% This is used when outputting the strings to sort the index by.
+\def\indexdummyfont#1{#1}
+\def\indexdummytex{TeX}
+\def\indexdummydots{...}
+
+\def\indexnofonts{%
+% Just ignore accents.
+\let\,=\indexdummyfont
+\let\"=\indexdummyfont
+\let\`=\indexdummyfont
+\let\'=\indexdummyfont
+\let\^=\indexdummyfont
+\let\~=\indexdummyfont
+\let\==\indexdummyfont
+\let\b=\indexdummyfont
+\let\c=\indexdummyfont
+\let\d=\indexdummyfont
+\let\u=\indexdummyfont
+\let\v=\indexdummyfont
+\let\H=\indexdummyfont
+\let\dotless=\indexdummyfont
+% Take care of the plain tex special European modified letters.
+\def\oe{oe}%
+\def\ae{ae}%
+\def\aa{aa}%
+\def\OE{OE}%
+\def\AE{AE}%
+\def\AA{AA}%
+\def\o{o}%
+\def\O{O}%
+\def\l{l}%
+\def\L{L}%
+\def\ss{ss}%
+\let\w=\indexdummyfont
+\let\t=\indexdummyfont
+\let\r=\indexdummyfont
+\let\i=\indexdummyfont
+\let\b=\indexdummyfont
+\let\emph=\indexdummyfont
+\let\strong=\indexdummyfont
+\let\cite=\indexdummyfont
+\let\sc=\indexdummyfont
+%Don't no-op \tt, since it isn't a user-level command
+% and is used in the definitions of the active chars like <, >, |...
+%\let\tt=\indexdummyfont
+\let\tclose=\indexdummyfont
+\let\code=\indexdummyfont
+\let\file=\indexdummyfont
+\let\samp=\indexdummyfont
+\let\kbd=\indexdummyfont
+\let\key=\indexdummyfont
+\let\var=\indexdummyfont
+\let\TeX=\indexdummytex
+\let\dots=\indexdummydots
+\def\@{@}%
+}
+
+% To define \realbackslash, we must make \ not be an escape.
+% We must first make another character (@) an escape
+% so we do not become unable to do a definition.
+
+{\catcode`\@=0 \catcode`\\=\other
+@gdef@realbackslash{\}}
+
+\let\indexbackslash=0 %overridden during \printindex.
+
+\let\SETmarginindex=\relax %initialize!
+% workhorse for all \fooindexes
+% #1 is name of index, #2 is stuff to put there
+\def\doind #1#2{%
+ % Put the index entry in the margin if desired.
+ \ifx\SETmarginindex\relax\else
+ \insert\margin{\hbox{\vrule height8pt depth3pt width0pt #2}}%
+ \fi
+ {%
+ \count255=\lastpenalty
+ {%
+ \indexdummies % Must do this here, since \bf, etc expand at this stage
+ \escapechar=`\\
+ {%
+ \let\folio=0 % We will expand all macros now EXCEPT \folio.
+ \def\rawbackslashxx{\indexbackslash}% \indexbackslash isn't defined now
+ % so it will be output as is; and it will print as backslash.
+ %
+ % First process the index-string with all font commands turned off
+ % to get the string to sort by.
+ {\indexnofonts \xdef\indexsorttmp{#2}}%
+ %
+ % Now produce the complete index entry, with both the sort key and the
+ % original text, including any font commands.
+ \toks0 = {#2}%
+ \edef\temp{%
+ \write\csname#1indfile\endcsname{%
+ \realbackslash entry{\indexsorttmp}{\folio}{\the\toks0}}%
+ }%
+ \temp
+ }%
+ }%
+ \penalty\count255
+ }%
+}
+
+\def\dosubind #1#2#3{%
+{\count10=\lastpenalty %
+{\indexdummies % Must do this here, since \bf, etc expand at this stage
+\escapechar=`\\%
+{\let\folio=0%
+\def\rawbackslashxx{\indexbackslash}%
+%
+% Now process the index-string once, with all font commands turned off,
+% to get the string to sort the index by.
+{\indexnofonts
+\xdef\temp1{#2 #3}%
+}%
+% Now produce the complete index entry. We process the index-string again,
+% this time with font commands expanded, to get what to print in the index.
+\edef\temp{%
+\write \csname#1indfile\endcsname{%
+\realbackslash entry {\temp1}{\folio}{#2}{#3}}}%
+\temp }%
+}\penalty\count10}}
+
+% The index entry written in the file actually looks like
+% \entry {sortstring}{page}{topic}
+% or
+% \entry {sortstring}{page}{topic}{subtopic}
+% The texindex program reads in these files and writes files
+% containing these kinds of lines:
+% \initial {c}
+% before the first topic whose initial is c
+% \entry {topic}{pagelist}
+% for a topic that is used without subtopics
+% \primary {topic}
+% for the beginning of a topic that is used with subtopics
+% \secondary {subtopic}{pagelist}
+% for each subtopic.
+
+% Define the user-accessible indexing commands
+% @findex, @vindex, @kindex, @cindex.
+
+\def\findex {\fnindex}
+\def\kindex {\kyindex}
+\def\cindex {\cpindex}
+\def\vindex {\vrindex}
+\def\tindex {\tpindex}
+\def\pindex {\pgindex}
+
+\def\cindexsub {\begingroup\obeylines\cindexsub}
+{\obeylines %
+\gdef\cindexsub "#1" #2^^M{\endgroup %
+\dosubind{cp}{#2}{#1}}}
+
+% Define the macros used in formatting output of the sorted index material.
+
+% This is what you call to cause a particular index to get printed.
+% Write
+% @unnumbered Function Index
+% @printindex fn
+
+\def\printindex{\parsearg\doprintindex}
+
+\def\doprintindex#1{\begingroup
+ \dobreak \chapheadingskip{10000}%
+ %
+ \indexfonts \rm
+ \tolerance = 9500
+ \indexbreaks
+ \def\indexbackslash{\rawbackslashxx}%
+ % Index files are almost Texinfo source, but we use \ as the escape
+ % character. It would be better to use @, but that's too big a change
+ % to make right now.
+ \catcode`\\ = 0
+ \catcode`\@ = 11
+ \escapechar = `\\
+ \begindoublecolumns
+ %
+ % See if the index file exists and is nonempty.
+ \openin 1 \jobname.#1s
+ \ifeof 1
+ % \enddoublecolumns gets confused if there is no text in the index,
+ % and it loses the chapter title and the aux file entries for the
+ % index. The easiest way to prevent this problem is to make sure
+ % there is some text.
+ (Index is nonexistent)
+ \else
+ %
+ % If the index file exists but is empty, then \openin leaves \ifeof
+ % false. We have to make TeX try to read something from the file, so
+ % it can discover if there is anything in it.
+ \read 1 to \temp
+ \ifeof 1
+ (Index is empty)
+ \else
+ \input \jobname.#1s
+ \fi
+ \fi
+ \closein 1
+ \enddoublecolumns
+\endgroup}
+
+% These macros are used by the sorted index file itself.
+% Change them to control the appearance of the index.
+
+% Same as \bigskipamount except no shrink.
+% \balancecolumns gets confused if there is any shrink.
+\newskip\initialskipamount \initialskipamount 12pt plus4pt
+
+\def\initial #1{%
+{\let\tentt=\sectt \let\tt=\sectt \let\sf=\sectt
+\ifdim\lastskip<\initialskipamount
+\removelastskip \penalty-200 \vskip \initialskipamount\fi
+\line{\secbf#1\hfill}\kern 2pt\penalty10000}}
+
+% This typesets a paragraph consisting of #1, dot leaders, and then #2
+% flush to the right margin. It is used for index and table of contents
+% entries. The paragraph is indented by \leftskip.
+%
+\def\entry #1#2{\begingroup
+ %
+ % Start a new paragraph if necessary, so our assignments below can't
+ % affect previous text.
+ \par
+ %
+ % Do not fill out the last line with white space.
+ \parfillskip = 0in
+ %
+ % No extra space above this paragraph.
+ \parskip = 0in
+ %
+ % Do not prefer a separate line ending with a hyphen to fewer lines.
+ \finalhyphendemerits = 0
+ %
+ % \hangindent is only relevant when the entry text and page number
+ % don't both fit on one line. In that case, bob suggests starting the
+ % dots pretty far over on the line. Unfortunately, a large
+ % indentation looks wrong when the entry text itself is broken across
+ % lines. So we use a small indentation and put up with long leaders.
+ %
+ % \hangafter is reset to 1 (which is the value we want) at the start
+ % of each paragraph, so we need not do anything with that.
+ \hangindent=2em
+ %
+ % When the entry text needs to be broken, just fill out the first line
+ % with blank space.
+ \rightskip = 0pt plus1fil
+ %
+ % Start a ``paragraph'' for the index entry so the line breaking
+ % parameters we've set above will have an effect.
+ \noindent
+ %
+ % Insert the text of the index entry. TeX will do line-breaking on it.
+ #1%
+ % The following is kludged to not output a line of dots in the index if
+ % there are no page numbers. The next person who breaks this will be
+ % cursed by a Unix daemon.
+ \def\tempa{{\rm }}%
+ \def\tempb{#2}%
+ \edef\tempc{\tempa}%
+ \edef\tempd{\tempb}%
+ \ifx\tempc\tempd\ \else%
+ %
+ % If we must, put the page number on a line of its own, and fill out
+ % this line with blank space. (The \hfil is overwhelmed with the
+ % fill leaders glue in \indexdotfill if the page number does fit.)
+ \hfil\penalty50
+ \null\nobreak\indexdotfill % Have leaders before the page number.
+ %
+ % The `\ ' here is removed by the implicit \unskip that TeX does as
+ % part of (the primitive) \par. Without it, a spurious underfull
+ % \hbox ensues.
+ \ #2% The page number ends the paragraph.
+ \fi%
+ \par
+\endgroup}
+
+% Like \dotfill except takes at least 1 em.
+\def\indexdotfill{\cleaders
+ \hbox{$\mathsurround=0pt \mkern1.5mu ${\it .}$ \mkern1.5mu$}\hskip 1em plus 1fill}
+
+\def\primary #1{\line{#1\hfil}}
+
+\newskip\secondaryindent \secondaryindent=0.5cm
+
+\def\secondary #1#2{
+{\parfillskip=0in \parskip=0in
+\hangindent =1in \hangafter=1
+\noindent\hskip\secondaryindent\hbox{#1}\indexdotfill #2\par
+}}
+
+% Define two-column mode, which we use to typeset indexes.
+% Adapted from the TeXbook, page 416, which is to say,
+% the manmac.tex format used to print the TeXbook itself.
+\catcode`\@=11
+
+\newbox\partialpage
+\newdimen\doublecolumnhsize
+
+\def\begindoublecolumns{\begingroup % ended by \enddoublecolumns
+ % Grab any single-column material above us.
+ \output = {\global\setbox\partialpage
+ =\vbox{\unvbox255\kern -\topskip \kern \baselineskip}}%
+ \eject
+ %
+ % Now switch to the double-column output routine.
+ \output={\doublecolumnout}%
+ %
+ % Change the page size parameters. We could do this once outside this
+ % routine, in each of @smallbook, @afourpaper, and the default 8.5x11
+ % format, but then we repeat the same computation. Repeating a couple
+ % of assignments once per index is clearly meaningless for the
+ % execution time, so we may as well do it once.
+ %
+ % First we halve the line length, less a little for the gutter between
+ % the columns. We compute the gutter based on the line length, so it
+ % changes automatically with the paper format. The magic constant
+ % below is chosen so that the gutter has the same value (well, +- <
+ % 1pt) as it did when we hard-coded it.
+ %
+ % We put the result in a separate register, \doublecolumhsize, so we
+ % can restore it in \pagesofar, after \hsize itself has (potentially)
+ % been clobbered.
+ %
+ \doublecolumnhsize = \hsize
+ \advance\doublecolumnhsize by -.04154\hsize
+ \divide\doublecolumnhsize by 2
+ \hsize = \doublecolumnhsize
+ %
+ % Double the \vsize as well. (We don't need a separate register here,
+ % since nobody clobbers \vsize.)
+ \vsize = 2\vsize
+}
+\def\doublecolumnout{%
+ \splittopskip=\topskip \splitmaxdepth=\maxdepth
+ % Get the available space for the double columns -- the normal
+ % (undoubled) page height minus any material left over from the
+ % previous page.
+ \dimen@=\pageheight \advance\dimen@ by-\ht\partialpage
+ % box0 will be the left-hand column, box1 the right.
+ \setbox0=\vsplit255 to\dimen@ \setbox2=\vsplit255 to\dimen@
+ \onepageout\pagesofar
+ \unvbox255 \penalty\outputpenalty
+}
+\def\pagesofar{%
+ % The contents of the output page -- any previous material,
+ % followed by the two boxes we just split.
+ \unvbox\partialpage
+ \hsize = \doublecolumnhsize
+ \wd0=\hsize \wd2=\hsize \hbox to\pagewidth{\box0\hfil\box2}%
+}
+\def\enddoublecolumns{%
+ \output={\balancecolumns}\eject % split what we have
+ \endgroup
+ % Back to normal single-column typesetting, but take account of the
+ % fact that we just accumulated some stuff on the output page.
+ \pagegoal=\vsize
+}
+\def\balancecolumns{%
+ % Called on the last page of the double column material.
+ \setbox0=\vbox{\unvbox255}%
+ \dimen@ = \ht0
+ \advance\dimen@ by \topskip
+ \advance\dimen@ by-\baselineskip
+ \divide\dimen@ by 2
+ \splittopskip = \topskip
+ % Loop until we get a decent breakpoint.
+ {\vbadness=10000 \loop \global\setbox3=\copy0
+ \global\setbox1=\vsplit3 to\dimen@
+ \ifdim\ht3>\dimen@ \global\advance\dimen@ by1pt \repeat}%
+ \setbox0=\vbox to\dimen@{\unvbox1}%
+ \setbox2=\vbox to\dimen@{\unvbox3}%
+ \pagesofar
+}
+\catcode `\@=\other
+
+
+\message{sectioning,}
+% Define chapters, sections, etc.
+
+\newcount \chapno
+\newcount \secno \secno=0
+\newcount \subsecno \subsecno=0
+\newcount \subsubsecno \subsubsecno=0
+
+% This counter is funny since it counts through charcodes of letters A, B, ...
+\newcount \appendixno \appendixno = `\@
+\def\appendixletter{\char\the\appendixno}
+
+\newwrite \contentsfile
+% This is called from \setfilename.
+\def\opencontents{\openout \contentsfile = \jobname.toc}
+
+% Each @chapter defines this as the name of the chapter.
+% page headings and footings can use it. @section does likewise
+
+\def\thischapter{} \def\thissection{}
+\def\seccheck#1{\if \pageno<0 %
+\errmessage{@#1 not allowed after generating table of contents}\fi
+%
+}
+
+\def\chapternofonts{%
+\let\rawbackslash=\relax%
+\let\frenchspacing=\relax%
+\def\result{\realbackslash result}
+\def\equiv{\realbackslash equiv}
+\def\expansion{\realbackslash expansion}
+\def\print{\realbackslash print}
+\def\TeX{\realbackslash TeX}
+\def\dots{\realbackslash dots}
+\def\copyright{\realbackslash copyright}
+\def\tt{\realbackslash tt}
+\def\bf{\realbackslash bf }
+\def\w{\realbackslash w}
+\def\less{\realbackslash less}
+\def\gtr{\realbackslash gtr}
+\def\hat{\realbackslash hat}
+\def\char{\realbackslash char}
+\def\tclose##1{\realbackslash tclose {##1}}
+\def\code##1{\realbackslash code {##1}}
+\def\samp##1{\realbackslash samp {##1}}
+\def\r##1{\realbackslash r {##1}}
+\def\b##1{\realbackslash b {##1}}
+\def\key##1{\realbackslash key {##1}}
+\def\file##1{\realbackslash file {##1}}
+\def\kbd##1{\realbackslash kbd {##1}}
+% These are redefined because @smartitalic wouldn't work inside xdef.
+\def\i##1{\realbackslash i {##1}}
+\def\cite##1{\realbackslash cite {##1}}
+\def\var##1{\realbackslash var {##1}}
+\def\emph##1{\realbackslash emph {##1}}
+\def\dfn##1{\realbackslash dfn {##1}}
+}
+
+\newcount\absseclevel % used to calculate proper heading level
+\newcount\secbase\secbase=0 % @raise/lowersections modify this count
+
+% @raisesections: treat @section as chapter, @subsection as section, etc.
+\def\raisesections{\global\advance\secbase by -1}
+\let\up=\raisesections % original BFox name
+
+% @lowersections: treat @chapter as section, @section as subsection, etc.
+\def\lowersections{\global\advance\secbase by 1}
+\let\down=\lowersections % original BFox name
+
+% Choose a numbered-heading macro
+% #1 is heading level if unmodified by @raisesections or @lowersections
+% #2 is text for heading
+\def\numhead#1#2{\absseclevel=\secbase\advance\absseclevel by #1
+\ifcase\absseclevel
+ \chapterzzz{#2}
+\or
+ \seczzz{#2}
+\or
+ \numberedsubseczzz{#2}
+\or
+ \numberedsubsubseczzz{#2}
+\else
+ \ifnum \absseclevel<0
+ \chapterzzz{#2}
+ \else
+ \numberedsubsubseczzz{#2}
+ \fi
+\fi
+}
+
+% like \numhead, but chooses appendix heading levels
+\def\apphead#1#2{\absseclevel=\secbase\advance\absseclevel by #1
+\ifcase\absseclevel
+ \appendixzzz{#2}
+\or
+ \appendixsectionzzz{#2}
+\or
+ \appendixsubseczzz{#2}
+\or
+ \appendixsubsubseczzz{#2}
+\else
+ \ifnum \absseclevel<0
+ \appendixzzz{#2}
+ \else
+ \appendixsubsubseczzz{#2}
+ \fi
+\fi
+}
+
+% like \numhead, but chooses numberless heading levels
+\def\unnmhead#1#2{\absseclevel=\secbase\advance\absseclevel by #1
+\ifcase\absseclevel
+ \unnumberedzzz{#2}
+\or
+ \unnumberedseczzz{#2}
+\or
+ \unnumberedsubseczzz{#2}
+\or
+ \unnumberedsubsubseczzz{#2}
+\else
+ \ifnum \absseclevel<0
+ \unnumberedzzz{#2}
+ \else
+ \unnumberedsubsubseczzz{#2}
+ \fi
+\fi
+}
+
+
+\def\thischaptername{No Chapter Title}
+\outer\def\chapter{\parsearg\chapteryyy}
+\def\chapteryyy #1{\numhead0{#1}} % normally numhead0 calls chapterzzz
+\def\chapterzzz #1{\seccheck{chapter}%
+\secno=0 \subsecno=0 \subsubsecno=0
+\global\advance \chapno by 1 \message{\putwordChapter \the\chapno}%
+\chapmacro {#1}{\the\chapno}%
+\gdef\thissection{#1}%
+\gdef\thischaptername{#1}%
+% We don't substitute the actual chapter name into \thischapter
+% because we don't want its macros evaluated now.
+\xdef\thischapter{\putwordChapter{} \the\chapno: \noexpand\thischaptername}%
+{\chapternofonts%
+\edef\temp{{\realbackslash chapentry {#1}{\the\chapno}{\noexpand\folio}}}%
+\escapechar=`\\%
+\write \contentsfile \temp %
+\donoderef %
+\global\let\section = \numberedsec
+\global\let\subsection = \numberedsubsec
+\global\let\subsubsection = \numberedsubsubsec
+}}
+
+\outer\def\appendix{\parsearg\appendixyyy}
+\def\appendixyyy #1{\apphead0{#1}} % normally apphead0 calls appendixzzz
+\def\appendixzzz #1{\seccheck{appendix}%
+\secno=0 \subsecno=0 \subsubsecno=0
+\global\advance \appendixno by 1 \message{Appendix \appendixletter}%
+\chapmacro {#1}{\putwordAppendix{} \appendixletter}%
+\gdef\thissection{#1}%
+\gdef\thischaptername{#1}%
+\xdef\thischapter{\putwordAppendix{} \appendixletter: \noexpand\thischaptername}%
+{\chapternofonts%
+\edef\temp{{\realbackslash chapentry
+ {#1}{\putwordAppendix{} \appendixletter}{\noexpand\folio}}}%
+\escapechar=`\\%
+\write \contentsfile \temp %
+\appendixnoderef %
+\global\let\section = \appendixsec
+\global\let\subsection = \appendixsubsec
+\global\let\subsubsection = \appendixsubsubsec
+}}
+
+% @centerchap is like @unnumbered, but the heading is centered.
+\outer\def\centerchap{\parsearg\centerchapyyy}
+\def\centerchapyyy #1{{\let\unnumbchapmacro=\centerchapmacro \unnumberedyyy{#1}}}
+
+\outer\def\top{\parsearg\unnumberedyyy}
+\outer\def\unnumbered{\parsearg\unnumberedyyy}
+\def\unnumberedyyy #1{\unnmhead0{#1}} % normally unnmhead0 calls unnumberedzzz
+\def\unnumberedzzz #1{\seccheck{unnumbered}%
+\secno=0 \subsecno=0 \subsubsecno=0
+%
+% This used to be simply \message{#1}, but TeX fully expands the
+% argument to \message. Therefore, if #1 contained @-commands, TeX
+% expanded them. For example, in `@unnumbered The @cite{Book}', TeX
+% expanded @cite (which turns out to cause errors because \cite is meant
+% to be executed, not expanded).
+%
+% Anyway, we don't want the fully-expanded definition of @cite to appear
+% as a result of the \message, we just want `@cite' itself. We use
+% \the<toks register> to achieve this: TeX expands \the<toks> only once,
+% simply yielding the contents of the <toks register>.
+\toks0 = {#1}\message{(\the\toks0)}%
+%
+\unnumbchapmacro {#1}%
+\gdef\thischapter{#1}\gdef\thissection{#1}%
+{\chapternofonts%
+\edef\temp{{\realbackslash unnumbchapentry {#1}{\noexpand\folio}}}%
+\escapechar=`\\%
+\write \contentsfile \temp %
+\unnumbnoderef %
+\global\let\section = \unnumberedsec
+\global\let\subsection = \unnumberedsubsec
+\global\let\subsubsection = \unnumberedsubsubsec
+}}
+
+\outer\def\numberedsec{\parsearg\secyyy}
+\def\secyyy #1{\numhead1{#1}} % normally calls seczzz
+\def\seczzz #1{\seccheck{section}%
+\subsecno=0 \subsubsecno=0 \global\advance \secno by 1 %
+\gdef\thissection{#1}\secheading {#1}{\the\chapno}{\the\secno}%
+{\chapternofonts%
+\edef\temp{{\realbackslash secentry %
+{#1}{\the\chapno}{\the\secno}{\noexpand\folio}}}%
+\escapechar=`\\%
+\write \contentsfile \temp %
+\donoderef %
+\penalty 10000 %
+}}
+
+\outer\def\appendixsection{\parsearg\appendixsecyyy}
+\outer\def\appendixsec{\parsearg\appendixsecyyy}
+\def\appendixsecyyy #1{\apphead1{#1}} % normally calls appendixsectionzzz
+\def\appendixsectionzzz #1{\seccheck{appendixsection}%
+\subsecno=0 \subsubsecno=0 \global\advance \secno by 1 %
+\gdef\thissection{#1}\secheading {#1}{\appendixletter}{\the\secno}%
+{\chapternofonts%
+\edef\temp{{\realbackslash secentry %
+{#1}{\appendixletter}{\the\secno}{\noexpand\folio}}}%
+\escapechar=`\\%
+\write \contentsfile \temp %
+\appendixnoderef %
+\penalty 10000 %
+}}
+
+\outer\def\unnumberedsec{\parsearg\unnumberedsecyyy}
+\def\unnumberedsecyyy #1{\unnmhead1{#1}} % normally calls unnumberedseczzz
+\def\unnumberedseczzz #1{\seccheck{unnumberedsec}%
+\plainsecheading {#1}\gdef\thissection{#1}%
+{\chapternofonts%
+\edef\temp{{\realbackslash unnumbsecentry{#1}{\noexpand\folio}}}%
+\escapechar=`\\%
+\write \contentsfile \temp %
+\unnumbnoderef %
+\penalty 10000 %
+}}
+
+\outer\def\numberedsubsec{\parsearg\numberedsubsecyyy}
+\def\numberedsubsecyyy #1{\numhead2{#1}} % normally calls numberedsubseczzz
+\def\numberedsubseczzz #1{\seccheck{subsection}%
+\gdef\thissection{#1}\subsubsecno=0 \global\advance \subsecno by 1 %
+\subsecheading {#1}{\the\chapno}{\the\secno}{\the\subsecno}%
+{\chapternofonts%
+\edef\temp{{\realbackslash subsecentry %
+{#1}{\the\chapno}{\the\secno}{\the\subsecno}{\noexpand\folio}}}%
+\escapechar=`\\%
+\write \contentsfile \temp %
+\donoderef %
+\penalty 10000 %
+}}
+
+\outer\def\appendixsubsec{\parsearg\appendixsubsecyyy}
+\def\appendixsubsecyyy #1{\apphead2{#1}} % normally calls appendixsubseczzz
+\def\appendixsubseczzz #1{\seccheck{appendixsubsec}%
+\gdef\thissection{#1}\subsubsecno=0 \global\advance \subsecno by 1 %
+\subsecheading {#1}{\appendixletter}{\the\secno}{\the\subsecno}%
+{\chapternofonts%
+\edef\temp{{\realbackslash subsecentry %
+{#1}{\appendixletter}{\the\secno}{\the\subsecno}{\noexpand\folio}}}%
+\escapechar=`\\%
+\write \contentsfile \temp %
+\appendixnoderef %
+\penalty 10000 %
+}}
+
+\outer\def\unnumberedsubsec{\parsearg\unnumberedsubsecyyy}
+\def\unnumberedsubsecyyy #1{\unnmhead2{#1}} %normally calls unnumberedsubseczzz
+\def\unnumberedsubseczzz #1{\seccheck{unnumberedsubsec}%
+\plainsubsecheading {#1}\gdef\thissection{#1}%
+{\chapternofonts%
+\edef\temp{{\realbackslash unnumbsubsecentry{#1}{\noexpand\folio}}}%
+\escapechar=`\\%
+\write \contentsfile \temp %
+\unnumbnoderef %
+\penalty 10000 %
+}}
+
+\outer\def\numberedsubsubsec{\parsearg\numberedsubsubsecyyy}
+\def\numberedsubsubsecyyy #1{\numhead3{#1}} % normally numberedsubsubseczzz
+\def\numberedsubsubseczzz #1{\seccheck{subsubsection}%
+\gdef\thissection{#1}\global\advance \subsubsecno by 1 %
+\subsubsecheading {#1}
+ {\the\chapno}{\the\secno}{\the\subsecno}{\the\subsubsecno}%
+{\chapternofonts%
+\edef\temp{{\realbackslash subsubsecentry %
+ {#1}
+ {\the\chapno}{\the\secno}{\the\subsecno}{\the\subsubsecno}
+ {\noexpand\folio}}}%
+\escapechar=`\\%
+\write \contentsfile \temp %
+\donoderef %
+\penalty 10000 %
+}}
+
+\outer\def\appendixsubsubsec{\parsearg\appendixsubsubsecyyy}
+\def\appendixsubsubsecyyy #1{\apphead3{#1}} % normally appendixsubsubseczzz
+\def\appendixsubsubseczzz #1{\seccheck{appendixsubsubsec}%
+\gdef\thissection{#1}\global\advance \subsubsecno by 1 %
+\subsubsecheading {#1}
+ {\appendixletter}{\the\secno}{\the\subsecno}{\the\subsubsecno}%
+{\chapternofonts%
+\edef\temp{{\realbackslash subsubsecentry{#1}%
+ {\appendixletter}
+ {\the\secno}{\the\subsecno}{\the\subsubsecno}{\noexpand\folio}}}%
+\escapechar=`\\%
+\write \contentsfile \temp %
+\appendixnoderef %
+\penalty 10000 %
+}}
+
+\outer\def\unnumberedsubsubsec{\parsearg\unnumberedsubsubsecyyy}
+\def\unnumberedsubsubsecyyy #1{\unnmhead3{#1}} %normally unnumberedsubsubseczzz
+\def\unnumberedsubsubseczzz #1{\seccheck{unnumberedsubsubsec}%
+\plainsubsubsecheading {#1}\gdef\thissection{#1}%
+{\chapternofonts%
+\edef\temp{{\realbackslash unnumbsubsubsecentry{#1}{\noexpand\folio}}}%
+\escapechar=`\\%
+\write \contentsfile \temp %
+\unnumbnoderef %
+\penalty 10000 %
+}}
+
+% These are variants which are not "outer", so they can appear in @ifinfo.
+% Actually, they should now be obsolete; ordinary section commands should work.
+\def\infotop{\parsearg\unnumberedzzz}
+\def\infounnumbered{\parsearg\unnumberedzzz}
+\def\infounnumberedsec{\parsearg\unnumberedseczzz}
+\def\infounnumberedsubsec{\parsearg\unnumberedsubseczzz}
+\def\infounnumberedsubsubsec{\parsearg\unnumberedsubsubseczzz}
+
+\def\infoappendix{\parsearg\appendixzzz}
+\def\infoappendixsec{\parsearg\appendixseczzz}
+\def\infoappendixsubsec{\parsearg\appendixsubseczzz}
+\def\infoappendixsubsubsec{\parsearg\appendixsubsubseczzz}
+
+\def\infochapter{\parsearg\chapterzzz}
+\def\infosection{\parsearg\sectionzzz}
+\def\infosubsection{\parsearg\subsectionzzz}
+\def\infosubsubsection{\parsearg\subsubsectionzzz}
+
+% These macros control what the section commands do, according
+% to what kind of chapter we are in (ordinary, appendix, or unnumbered).
+% Define them by default for a numbered chapter.
+\global\let\section = \numberedsec
+\global\let\subsection = \numberedsubsec
+\global\let\subsubsection = \numberedsubsubsec
+
+% Define @majorheading, @heading and @subheading
+
+% NOTE on use of \vbox for chapter headings, section headings, and
+% such:
+% 1) We use \vbox rather than the earlier \line to permit
+% overlong headings to fold.
+% 2) \hyphenpenalty is set to 10000 because hyphenation in a
+% heading is obnoxious; this forbids it.
+% 3) Likewise, headings look best if no \parindent is used, and
+% if justification is not attempted. Hence \raggedright.
+
+
+\def\majorheading{\parsearg\majorheadingzzz}
+\def\majorheadingzzz #1{%
+{\advance\chapheadingskip by 10pt \chapbreak }%
+{\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000
+ \parindent=0pt\raggedright
+ \rm #1\hfill}}\bigskip \par\penalty 200}
+
+\def\chapheading{\parsearg\chapheadingzzz}
+\def\chapheadingzzz #1{\chapbreak %
+{\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000
+ \parindent=0pt\raggedright
+ \rm #1\hfill}}\bigskip \par\penalty 200}
+
+% @heading, @subheading, @subsubheading.
+\def\heading{\parsearg\plainsecheading}
+\def\subheading{\parsearg\plainsubsecheading}
+\def\subsubheading{\parsearg\plainsubsubsecheading}
+
+% These macros generate a chapter, section, etc. heading only
+% (including whitespace, linebreaking, etc. around it),
+% given all the information in convenient, parsed form.
+
+%%% Args are the skip and penalty (usually negative)
+\def\dobreak#1#2{\par\ifdim\lastskip<#1\removelastskip\penalty#2\vskip#1\fi}
+
+\def\setchapterstyle #1 {\csname CHAPF#1\endcsname}
+
+%%% Define plain chapter starts, and page on/off switching for it
+% Parameter controlling skip before chapter headings (if needed)
+
+\newskip\chapheadingskip
+
+\def\chapbreak{\dobreak \chapheadingskip {-4000}}
+\def\chappager{\par\vfill\supereject}
+\def\chapoddpage{\chappager \ifodd\pageno \else \hbox to 0pt{} \chappager\fi}
+
+\def\setchapternewpage #1 {\csname CHAPPAG#1\endcsname}
+
+\def\CHAPPAGoff{
+\global\let\contentsalignmacro = \chappager
+\global\let\pchapsepmacro=\chapbreak
+\global\let\pagealignmacro=\chappager}
+
+\def\CHAPPAGon{
+\global\let\contentsalignmacro = \chappager
+\global\let\pchapsepmacro=\chappager
+\global\let\pagealignmacro=\chappager
+\global\def\HEADINGSon{\HEADINGSsingle}}
+
+\def\CHAPPAGodd{
+\global\let\contentsalignmacro = \chapoddpage
+\global\let\pchapsepmacro=\chapoddpage
+\global\let\pagealignmacro=\chapoddpage
+\global\def\HEADINGSon{\HEADINGSdouble}}
+
+\CHAPPAGon
+
+\def\CHAPFplain{
+\global\let\chapmacro=\chfplain
+\global\let\unnumbchapmacro=\unnchfplain
+\global\let\centerchapmacro=\centerchfplain}
+
+% Plain chapter opening.
+% #1 is the text, #2 the chapter number or empty if unnumbered.
+\def\chfplain#1#2{%
+ \pchapsepmacro
+ {%
+ \chapfonts \rm
+ \def\chapnum{#2}%
+ \setbox0 = \hbox{#2\ifx\chapnum\empty\else\enspace\fi}%
+ \vbox{\hyphenpenalty=10000 \tolerance=5000 \parindent=0pt \raggedright
+ \hangindent = \wd0 \centerparametersmaybe
+ \unhbox0 #1\par}%
+ }%
+ \nobreak\bigskip % no page break after a chapter title
+ \nobreak
+}
+
+% Plain opening for unnumbered.
+\def\unnchfplain#1{\chfplain{#1}{}}
+
+% @centerchap -- centered and unnumbered.
+\let\centerparametersmaybe = \relax
+\def\centerchfplain#1{{%
+ \def\centerparametersmaybe{%
+ \advance\rightskip by 3\rightskip
+ \leftskip = \rightskip
+ \parfillskip = 0pt
+ }%
+ \chfplain{#1}{}%
+}}
+
+\CHAPFplain % The default
+
+\def\unnchfopen #1{%
+\chapoddpage {\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000
+ \parindent=0pt\raggedright
+ \rm #1\hfill}}\bigskip \par\penalty 10000 %
+}
+
+\def\chfopen #1#2{\chapoddpage {\chapfonts
+\vbox to 3in{\vfil \hbox to\hsize{\hfil #2} \hbox to\hsize{\hfil #1} \vfil}}%
+\par\penalty 5000 %
+}
+
+\def\centerchfopen #1{%
+\chapoddpage {\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000
+ \parindent=0pt
+ \hfill {\rm #1}\hfill}}\bigskip \par\penalty 10000 %
+}
+
+\def\CHAPFopen{
+\global\let\chapmacro=\chfopen
+\global\let\unnumbchapmacro=\unnchfopen
+\global\let\centerchapmacro=\centerchfopen}
+
+
+% Section titles.
+\newskip\secheadingskip
+\def\secheadingbreak{\dobreak \secheadingskip {-1000}}
+\def\secheading#1#2#3{\sectionheading{sec}{#2.#3}{#1}}
+\def\plainsecheading#1{\sectionheading{sec}{}{#1}}
+
+% Subsection titles.
+\newskip \subsecheadingskip
+\def\subsecheadingbreak{\dobreak \subsecheadingskip {-500}}
+\def\subsecheading#1#2#3#4{\sectionheading{subsec}{#2.#3.#4}{#1}}
+\def\plainsubsecheading#1{\sectionheading{subsec}{}{#1}}
+
+% Subsubsection titles.
+\let\subsubsecheadingskip = \subsecheadingskip
+\let\subsubsecheadingbreak = \subsecheadingbreak
+\def\subsubsecheading#1#2#3#4#5{\sectionheading{subsubsec}{#2.#3.#4.#5}{#1}}
+\def\plainsubsubsecheading#1{\sectionheading{subsubsec}{}{#1}}
+
+
+% Print any size section title.
+%
+% #1 is the section type (sec/subsec/subsubsec), #2 is the section
+% number (maybe empty), #3 the text.
+\def\sectionheading#1#2#3{%
+ {%
+ \expandafter\advance\csname #1headingskip\endcsname by \parskip
+ \csname #1headingbreak\endcsname
+ }%
+ {%
+ % Switch to the right set of fonts.
+ \csname #1fonts\endcsname \rm
+ %
+ % Only insert the separating space if we have a section number.
+ \def\secnum{#2}%
+ \setbox0 = \hbox{#2\ifx\secnum\empty\else\enspace\fi}%
+ %
+ \vbox{\hyphenpenalty=10000 \tolerance=5000 \parindent=0pt \raggedright
+ \hangindent = \wd0 % zero if no section number
+ \unhbox0 #3}%
+ }%
+ \ifdim\parskip<10pt \nobreak\kern10pt\nobreak\kern-\parskip\fi \nobreak
+}
+
+
+\message{toc printing,}
+% Finish up the main text and prepare to read what we've written
+% to \contentsfile.
+
+\newskip\contentsrightmargin \contentsrightmargin=1in
+\def\startcontents#1{%
+ % If @setchapternewpage on, and @headings double, the contents should
+ % start on an odd page, unlike chapters. Thus, we maintain
+ % \contentsalignmacro in parallel with \pagealignmacro.
+ % From: Torbjorn Granlund <tege@matematik.su.se>
+ \contentsalignmacro
+ \immediate\closeout \contentsfile
+ \ifnum \pageno>0
+ \pageno = -1 % Request roman numbered pages.
+ \fi
+ % Don't need to put `Contents' or `Short Contents' in the headline.
+ % It is abundantly clear what they are.
+ \unnumbchapmacro{#1}\def\thischapter{}%
+ \begingroup % Set up to handle contents files properly.
+ \catcode`\\=0 \catcode`\{=1 \catcode`\}=2 \catcode`\@=11
+ \catcode`\^=7 % to see ^^e4 as \"a etc. juha@piuha.ydi.vtt.fi
+ \raggedbottom % Worry more about breakpoints than the bottom.
+ \advance\hsize by -\contentsrightmargin % Don't use the full line length.
+}
+
+
+% Normal (long) toc.
+\outer\def\contents{%
+ \startcontents{\putwordTableofContents}%
+ \input \jobname.toc
+ \endgroup
+ \vfill \eject
+}
+
+% And just the chapters.
+\outer\def\summarycontents{%
+ \startcontents{\putwordShortContents}%
+ %
+ \let\chapentry = \shortchapentry
+ \let\unnumbchapentry = \shortunnumberedentry
+ % We want a true roman here for the page numbers.
+ \secfonts
+ \let\rm=\shortcontrm \let\bf=\shortcontbf \let\sl=\shortcontsl
+ \rm
+ \hyphenpenalty = 10000
+ \advance\baselineskip by 1pt % Open it up a little.
+ \def\secentry ##1##2##3##4{}
+ \def\unnumbsecentry ##1##2{}
+ \def\subsecentry ##1##2##3##4##5{}
+ \def\unnumbsubsecentry ##1##2{}
+ \def\subsubsecentry ##1##2##3##4##5##6{}
+ \def\unnumbsubsubsecentry ##1##2{}
+ \input \jobname.toc
+ \endgroup
+ \vfill \eject
+}
+\let\shortcontents = \summarycontents
+
+% These macros generate individual entries in the table of contents.
+% The first argument is the chapter or section name.
+% The last argument is the page number.
+% The arguments in between are the chapter number, section number, ...
+
+% Chapter-level things, for both the long and short contents.
+\def\chapentry#1#2#3{\dochapentry{#2\labelspace#1}{#3}}
+
+% See comments in \dochapentry re vbox and related settings
+\def\shortchapentry#1#2#3{%
+ \tocentry{\shortchaplabel{#2}\labelspace #1}{\doshortpageno{#3}}%
+}
+
+% Typeset the label for a chapter or appendix for the short contents.
+% The arg is, e.g. `Appendix A' for an appendix, or `3' for a chapter.
+% We could simplify the code here by writing out an \appendixentry
+% command in the toc file for appendices, instead of using \chapentry
+% for both, but it doesn't seem worth it.
+\setbox0 = \hbox{\shortcontrm \putwordAppendix }
+\newdimen\shortappendixwidth \shortappendixwidth = \wd0
+
+\def\shortchaplabel#1{%
+ % We typeset #1 in a box of constant width, regardless of the text of
+ % #1, so the chapter titles will come out aligned.
+ \setbox0 = \hbox{#1}%
+ \dimen0 = \ifdim\wd0 > \shortappendixwidth \shortappendixwidth \else 0pt \fi
+ %
+ % This space should be plenty, since a single number is .5em, and the
+ % widest letter (M) is 1em, at least in the Computer Modern fonts.
+ % (This space doesn't include the extra space that gets added after
+ % the label; that gets put in by \shortchapentry above.)
+ \advance\dimen0 by 1.1em
+ \hbox to \dimen0{#1\hfil}%
+}
+
+\def\unnumbchapentry#1#2{\dochapentry{#1}{#2}}
+\def\shortunnumberedentry#1#2{\tocentry{#1}{\doshortpageno{#2}}}
+
+% Sections.
+\def\secentry#1#2#3#4{\dosecentry{#2.#3\labelspace#1}{#4}}
+\def\unnumbsecentry#1#2{\dosecentry{#1}{#2}}
+
+% Subsections.
+\def\subsecentry#1#2#3#4#5{\dosubsecentry{#2.#3.#4\labelspace#1}{#5}}
+\def\unnumbsubsecentry#1#2{\dosubsecentry{#1}{#2}}
+
+% And subsubsections.
+\def\subsubsecentry#1#2#3#4#5#6{%
+ \dosubsubsecentry{#2.#3.#4.#5\labelspace#1}{#6}}
+\def\unnumbsubsubsecentry#1#2{\dosubsubsecentry{#1}{#2}}
+
+% This parameter controls the indentation of the various levels.
+\newdimen\tocindent \tocindent = 3pc
+
+% Now for the actual typesetting. In all these, #1 is the text and #2 is the
+% page number.
+%
+% If the toc has to be broken over pages, we want it to be at chapters
+% if at all possible; hence the \penalty.
+\def\dochapentry#1#2{%
+ \penalty-300 \vskip1\baselineskip plus.33\baselineskip minus.25\baselineskip
+ \begingroup
+ \chapentryfonts
+ \tocentry{#1}{\dopageno{#2}}%
+ \endgroup
+ \nobreak\vskip .25\baselineskip plus.1\baselineskip
+}
+
+\def\dosecentry#1#2{\begingroup
+ \secentryfonts \leftskip=\tocindent
+ \tocentry{#1}{\dopageno{#2}}%
+\endgroup}
+
+\def\dosubsecentry#1#2{\begingroup
+ \subsecentryfonts \leftskip=2\tocindent
+ \tocentry{#1}{\dopageno{#2}}%
+\endgroup}
+
+\def\dosubsubsecentry#1#2{\begingroup
+ \subsubsecentryfonts \leftskip=3\tocindent
+ \tocentry{#1}{\dopageno{#2}}%
+\endgroup}
+
+% Final typesetting of a toc entry; we use the same \entry macro as for
+% the index entries, but we want to suppress hyphenation here. (We
+% can't do that in the \entry macro, since index entries might consist
+% of hyphenated-identifiers-that-do-not-fit-on-a-line-and-nothing-else.)
+%
+% \turnoffactive is for the sake of @" used for umlauts.
+\def\tocentry#1#2{\begingroup
+ \vskip 0pt plus1pt % allow a little stretch for the sake of nice page breaks
+ \entry{\turnoffactive #1}{\turnoffactive #2}%
+\endgroup}
+
+% Space between chapter (or whatever) number and the title.
+\def\labelspace{\hskip1em \relax}
+
+\def\dopageno#1{{\rm #1}}
+\def\doshortpageno#1{{\rm #1}}
+
+\def\chapentryfonts{\secfonts \rm}
+\def\secentryfonts{\textfonts}
+\let\subsecentryfonts = \textfonts
+\let\subsubsecentryfonts = \textfonts
+
+
+\message{environments,}
+
+% Since these characters are used in examples, it should be an even number of
+% \tt widths. Each \tt character is 1en, so two makes it 1em.
+% Furthermore, these definitions must come after we define our fonts.
+\newbox\dblarrowbox \newbox\longdblarrowbox
+\newbox\pushcharbox \newbox\bullbox
+\newbox\equivbox \newbox\errorbox
+
+%{\tentt
+%\global\setbox\dblarrowbox = \hbox to 1em{\hfil$\Rightarrow$\hfil}
+%\global\setbox\longdblarrowbox = \hbox to 1em{\hfil$\mapsto$\hfil}
+%\global\setbox\pushcharbox = \hbox to 1em{\hfil$\dashv$\hfil}
+%\global\setbox\equivbox = \hbox to 1em{\hfil$\ptexequiv$\hfil}
+% Adapted from the manmac format (p.420 of TeXbook)
+%\global\setbox\bullbox = \hbox to 1em{\kern.15em\vrule height .75ex width .85ex
+% depth .1ex\hfil}
+%}
+
+% @point{}, @result{}, @expansion{}, @print{}, @equiv{}.
+\def\point{$\star$}
+\def\result{\leavevmode\raise.15ex\hbox to 1em{\hfil$\Rightarrow$\hfil}}
+\def\expansion{\leavevmode\raise.1ex\hbox to 1em{\hfil$\mapsto$\hfil}}
+\def\print{\leavevmode\lower.1ex\hbox to 1em{\hfil$\dashv$\hfil}}
+\def\equiv{\leavevmode\lower.1ex\hbox to 1em{\hfil$\ptexequiv$\hfil}}
+
+% Adapted from the TeXbook's \boxit.
+{\tentt \global\dimen0 = 3em}% Width of the box.
+\dimen2 = .55pt % Thickness of rules
+% The text. (`r' is open on the right, `e' somewhat less so on the left.)
+\setbox0 = \hbox{\kern-.75pt \tensf error\kern-1.5pt}
+
+\global\setbox\errorbox=\hbox to \dimen0{\hfil
+ \hsize = \dimen0 \advance\hsize by -5.8pt % Space to left+right.
+ \advance\hsize by -2\dimen2 % Rules.
+ \vbox{
+ \hrule height\dimen2
+ \hbox{\vrule width\dimen2 \kern3pt % Space to left of text.
+ \vtop{\kern2.4pt \box0 \kern2.4pt}% Space above/below.
+ \kern3pt\vrule width\dimen2}% Space to right.
+ \hrule height\dimen2}
+ \hfil}
+
+% The @error{} command.
+\def\error{\leavevmode\lower.7ex\copy\errorbox}
+
+% @tex ... @end tex escapes into raw Tex temporarily.
+% One exception: @ is still an escape character, so that @end tex works.
+% But \@ or @@ will get a plain tex @ character.
+
+\def\tex{\begingroup
+\catcode `\\=0 \catcode `\{=1 \catcode `\}=2
+\catcode `\$=3 \catcode `\&=4 \catcode `\#=6
+\catcode `\^=7 \catcode `\_=8 \catcode `\~=13 \let~=\tie
+\catcode `\%=14
+\catcode 43=12 % plus
+\catcode`\"=12
+\catcode`\==12
+\catcode`\|=12
+\catcode`\<=12
+\catcode`\>=12
+\escapechar=`\\
+%
+\let\,=\ptexcomma
+\let\~=\ptextilde
+\let\{=\ptexlbrace
+\let\}=\ptexrbrace
+\let\.=\ptexdot
+\let\*=\ptexstar
+\let\dots=\ptexdots
+\def\endldots{\mathinner{\ldots\ldots\ldots\ldots}}
+\def\enddots{\relax\ifmmode\endldots\else$\mathsurround=0pt \endldots\,$\fi}
+\def\@{@}%
+\let\bullet=\ptexbullet
+\let\b=\ptexb \let\c=\ptexc \let\i=\ptexi \let\t=\ptext
+%
+\let\Etex=\endgroup}
+
+% Define @lisp ... @endlisp.
+% @lisp does a \begingroup so it can rebind things,
+% including the definition of @endlisp (which normally is erroneous).
+
+% Amount to narrow the margins by for @lisp.
+\newskip\lispnarrowing \lispnarrowing=0.4in
+
+% This is the definition that ^^M gets inside @lisp, @example, and other
+% such environments. \null is better than a space, since it doesn't
+% have any width.
+\def\lisppar{\null\endgraf}
+
+% Make each space character in the input produce a normal interword
+% space in the output. Don't allow a line break at this space, as this
+% is used only in environments like @example, where each line of input
+% should produce a line of output anyway.
+%
+{\obeyspaces %
+\gdef\sepspaces{\obeyspaces\let =\tie}}
+
+% Define \obeyedspace to be our active space, whatever it is. This is
+% for use in \parsearg.
+{\sepspaces%
+\global\let\obeyedspace= }
+
+% This space is always present above and below environments.
+\newskip\envskipamount \envskipamount = 0pt
+
+% Make spacing and below environment symmetrical. We use \parskip here
+% to help in doing that, since in @example-like environments \parskip
+% is reset to zero; thus the \afterenvbreak inserts no space -- but the
+% start of the next paragraph will insert \parskip
+%
+\def\aboveenvbreak{{\advance\envskipamount by \parskip
+\endgraf \ifdim\lastskip<\envskipamount
+\removelastskip \penalty-50 \vskip\envskipamount \fi}}
+
+\let\afterenvbreak = \aboveenvbreak
+
+% \nonarrowing is a flag. If "set", @lisp etc don't narrow margins.
+\let\nonarrowing=\relax
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \cartouche: draw rectangle w/rounded corners around argument
+\font\circle=lcircle10
+\newdimen\circthick
+\newdimen\cartouter\newdimen\cartinner
+\newskip\normbskip\newskip\normpskip\newskip\normlskip
+\circthick=\fontdimen8\circle
+%
+\def\ctl{{\circle\char'013\hskip -6pt}}% 6pt from pl file: 1/2charwidth
+\def\ctr{{\hskip 6pt\circle\char'010}}
+\def\cbl{{\circle\char'012\hskip -6pt}}
+\def\cbr{{\hskip 6pt\circle\char'011}}
+\def\carttop{\hbox to \cartouter{\hskip\lskip
+ \ctl\leaders\hrule height\circthick\hfil\ctr
+ \hskip\rskip}}
+\def\cartbot{\hbox to \cartouter{\hskip\lskip
+ \cbl\leaders\hrule height\circthick\hfil\cbr
+ \hskip\rskip}}
+%
+\newskip\lskip\newskip\rskip
+
+\long\def\cartouche{%
+\begingroup
+ \lskip=\leftskip \rskip=\rightskip
+ \leftskip=0pt\rightskip=0pt %we want these *outside*.
+ \cartinner=\hsize \advance\cartinner by-\lskip
+ \advance\cartinner by-\rskip
+ \cartouter=\hsize
+ \advance\cartouter by 18pt % allow for 3pt kerns on either
+% side, and for 6pt waste from
+% each corner char
+ \normbskip=\baselineskip \normpskip=\parskip \normlskip=\lineskip
+ % Flag to tell @lisp, etc., not to narrow margin.
+ \let\nonarrowing=\comment
+ \vbox\bgroup
+ \baselineskip=0pt\parskip=0pt\lineskip=0pt
+ \carttop
+ \hbox\bgroup
+ \hskip\lskip
+ \vrule\kern3pt
+ \vbox\bgroup
+ \hsize=\cartinner
+ \kern3pt
+ \begingroup
+ \baselineskip=\normbskip
+ \lineskip=\normlskip
+ \parskip=\normpskip
+ \vskip -\parskip
+\def\Ecartouche{%
+ \endgroup
+ \kern3pt
+ \egroup
+ \kern3pt\vrule
+ \hskip\rskip
+ \egroup
+ \cartbot
+ \egroup
+\endgroup
+}}
+
+
+% This macro is called at the beginning of all the @example variants,
+% inside a group.
+\def\nonfillstart{%
+ \aboveenvbreak
+ \inENV % This group ends at the end of the body
+ \hfuzz = 12pt % Don't be fussy
+ \sepspaces % Make spaces be word-separators rather than space tokens.
+ \singlespace
+ \let\par = \lisppar % don't ignore blank lines
+ \obeylines % each line of input is a line of output
+ \parskip = 0pt
+ \parindent = 0pt
+ \emergencystretch = 0pt % don't try to avoid overfull boxes
+ % @cartouche defines \nonarrowing to inhibit narrowing
+ % at next level down.
+ \ifx\nonarrowing\relax
+ \advance \leftskip by \lispnarrowing
+ \exdentamount=\lispnarrowing
+ \let\exdent=\nofillexdent
+ \let\nonarrowing=\relax
+ \fi
+}
+
+% To ending an @example-like environment, we first end the paragraph
+% (via \afterenvbreak's vertical glue), and then the group. That way we
+% keep the zero \parskip that the environments set -- \parskip glue
+% will be inserted at the beginning of the next paragraph in the
+% document, after the environment.
+%
+\def\nonfillfinish{\afterenvbreak\endgroup}%
+
+% This macro is
+\def\lisp{\begingroup
+ \nonfillstart
+ \let\Elisp = \nonfillfinish
+ \tt
+ \rawbackslash % have \ input char produce \ char from current font
+ \gobble
+}
+
+% Define the \E... control sequence only if we are inside the
+% environment, so the error checking in \end will work.
+%
+% We must call \lisp last in the definition, since it reads the
+% return following the @example (or whatever) command.
+%
+\def\example{\begingroup \def\Eexample{\nonfillfinish\endgroup}\lisp}
+\def\smallexample{\begingroup \def\Esmallexample{\nonfillfinish\endgroup}\lisp}
+\def\smalllisp{\begingroup \def\Esmalllisp{\nonfillfinish\endgroup}\lisp}
+
+% @smallexample and @smalllisp. This is not used unless the @smallbook
+% command is given. Originally contributed by Pavel@xerox.
+%
+\def\smalllispx{\begingroup
+ \nonfillstart
+ \let\Esmalllisp = \nonfillfinish
+ \let\Esmallexample = \nonfillfinish
+ %
+ % Smaller fonts for small examples.
+ \indexfonts \tt
+ \rawbackslash % make \ output the \ character from the current font (tt)
+ \gobble
+}
+
+% This is @display; same as @lisp except use roman font.
+%
+\def\display{\begingroup
+ \nonfillstart
+ \let\Edisplay = \nonfillfinish
+ \gobble
+}
+
+% This is @format; same as @display except don't narrow margins.
+%
+\def\format{\begingroup
+ \let\nonarrowing = t
+ \nonfillstart
+ \let\Eformat = \nonfillfinish
+ \gobble
+}
+
+% @flushleft (same as @format) and @flushright.
+%
+\def\flushleft{\begingroup
+ \let\nonarrowing = t
+ \nonfillstart
+ \let\Eflushleft = \nonfillfinish
+ \gobble
+}
+\def\flushright{\begingroup
+ \let\nonarrowing = t
+ \nonfillstart
+ \let\Eflushright = \nonfillfinish
+ \advance\leftskip by 0pt plus 1fill
+ \gobble}
+
+% @quotation does normal linebreaking (hence we can't use \nonfillstart)
+% and narrows the margins.
+%
+\def\quotation{%
+ \begingroup\inENV %This group ends at the end of the @quotation body
+ {\parskip=0pt \aboveenvbreak}% because \aboveenvbreak inserts \parskip
+ \singlespace
+ \parindent=0pt
+ % We have retained a nonzero parskip for the environment, since we're
+ % doing normal filling. So to avoid extra space below the environment...
+ \def\Equotation{\parskip = 0pt \nonfillfinish}%
+ %
+ % @cartouche defines \nonarrowing to inhibit narrowing at next level down.
+ \ifx\nonarrowing\relax
+ \advance\leftskip by \lispnarrowing
+ \advance\rightskip by \lispnarrowing
+ \exdentamount = \lispnarrowing
+ \let\nonarrowing = \relax
+ \fi
+}
+
+\message{defuns,}
+% Define formatter for defuns
+% First, allow user to change definition object font (\df) internally
+\def\setdeffont #1 {\csname DEF#1\endcsname}
+
+\newskip\defbodyindent \defbodyindent=.4in
+\newskip\defargsindent \defargsindent=50pt
+\newskip\deftypemargin \deftypemargin=12pt
+\newskip\deflastargmargin \deflastargmargin=18pt
+
+\newcount\parencount
+% define \functionparens, which makes ( and ) and & do special things.
+% \functionparens affects the group it is contained in.
+\def\activeparens{%
+\catcode`\(=\active \catcode`\)=\active \catcode`\&=\active
+\catcode`\[=\active \catcode`\]=\active}
+
+% Make control sequences which act like normal parenthesis chars.
+\let\lparen = ( \let\rparen = )
+
+{\activeparens % Now, smart parens don't turn on until &foo (see \amprm)
+
+% Be sure that we always have a definition for `(', etc. For example,
+% if the fn name has parens in it, \boldbrax will not be in effect yet,
+% so TeX would otherwise complain about undefined control sequence.
+\global\let(=\lparen \global\let)=\rparen
+\global\let[=\lbrack \global\let]=\rbrack
+
+\gdef\functionparens{\boldbrax\let&=\amprm\parencount=0 }
+\gdef\boldbrax{\let(=\opnr\let)=\clnr\let[=\lbrb\let]=\rbrb}
+% This is used to turn on special parens
+% but make & act ordinary (given that it's active).
+\gdef\boldbraxnoamp{\let(=\opnr\let)=\clnr\let[=\lbrb\let]=\rbrb\let&=\ampnr}
+
+% Definitions of (, ) and & used in args for functions.
+% This is the definition of ( outside of all parentheses.
+\gdef\oprm#1 {{\rm\char`\(}#1 \bf \let(=\opnested %
+\global\advance\parencount by 1 }
+%
+% This is the definition of ( when already inside a level of parens.
+\gdef\opnested{\char`\(\global\advance\parencount by 1 }
+%
+\gdef\clrm{% Print a paren in roman if it is taking us back to depth of 0.
+% also in that case restore the outer-level definition of (.
+\ifnum \parencount=1 {\rm \char `\)}\sl \let(=\oprm \else \char `\) \fi
+\global\advance \parencount by -1 }
+% If we encounter &foo, then turn on ()-hacking afterwards
+\gdef\amprm#1 {{\rm\&#1}\let(=\oprm \let)=\clrm\ }
+%
+\gdef\normalparens{\boldbrax\let&=\ampnr}
+} % End of definition inside \activeparens
+%% These parens (in \boldbrax) actually are a little bolder than the
+%% contained text. This is especially needed for [ and ]
+\def\opnr{{\sf\char`\(}} \def\clnr{{\sf\char`\)}} \def\ampnr{\&}
+\def\lbrb{{\bf\char`\[}} \def\rbrb{{\bf\char`\]}}
+
+% First, defname, which formats the header line itself.
+% #1 should be the function name.
+% #2 should be the type of definition, such as "Function".
+
+\def\defname #1#2{%
+% Get the values of \leftskip and \rightskip as they were
+% outside the @def...
+\dimen2=\leftskip
+\advance\dimen2 by -\defbodyindent
+\dimen3=\rightskip
+\advance\dimen3 by -\defbodyindent
+\noindent %
+\setbox0=\hbox{\hskip \deflastargmargin{\rm #2}\hskip \deftypemargin}%
+\dimen0=\hsize \advance \dimen0 by -\wd0 % compute size for first line
+\dimen1=\hsize \advance \dimen1 by -\defargsindent %size for continuations
+\parshape 2 0in \dimen0 \defargsindent \dimen1 %
+% Now output arg 2 ("Function" or some such)
+% ending at \deftypemargin from the right margin,
+% but stuck inside a box of width 0 so it does not interfere with linebreaking
+{% Adjust \hsize to exclude the ambient margins,
+% so that \rightline will obey them.
+\advance \hsize by -\dimen2 \advance \hsize by -\dimen3
+\rlap{\rightline{{\rm #2}\hskip \deftypemargin}}}%
+% Make all lines underfull and no complaints:
+\tolerance=10000 \hbadness=10000
+\advance\leftskip by -\defbodyindent
+\exdentamount=\defbodyindent
+{\df #1}\enskip % Generate function name
+}
+
+% Actually process the body of a definition
+% #1 should be the terminating control sequence, such as \Edefun.
+% #2 should be the "another name" control sequence, such as \defunx.
+% #3 should be the control sequence that actually processes the header,
+% such as \defunheader.
+
+\def\defparsebody #1#2#3{\begingroup\inENV% Environment for definitionbody
+\medbreak %
+% Define the end token that this defining construct specifies
+% so that it will exit this group.
+\def#1{\endgraf\endgroup\medbreak}%
+\def#2{\begingroup\obeylines\activeparens\spacesplit#3}%
+\parindent=0in
+\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindent
+\exdentamount=\defbodyindent
+\begingroup %
+\catcode 61=\active % 61 is `='
+\obeylines\activeparens\spacesplit#3}
+
+\def\defmethparsebody #1#2#3#4 {\begingroup\inENV %
+\medbreak %
+% Define the end token that this defining construct specifies
+% so that it will exit this group.
+\def#1{\endgraf\endgroup\medbreak}%
+\def#2##1 {\begingroup\obeylines\activeparens\spacesplit{#3{##1}}}%
+\parindent=0in
+\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindent
+\exdentamount=\defbodyindent
+\begingroup\obeylines\activeparens\spacesplit{#3{#4}}}
+
+\def\defopparsebody #1#2#3#4#5 {\begingroup\inENV %
+\medbreak %
+% Define the end token that this defining construct specifies
+% so that it will exit this group.
+\def#1{\endgraf\endgroup\medbreak}%
+\def#2##1 ##2 {\def#4{##1}%
+\begingroup\obeylines\activeparens\spacesplit{#3{##2}}}%
+\parindent=0in
+\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindent
+\exdentamount=\defbodyindent
+\begingroup\obeylines\activeparens\spacesplit{#3{#5}}}
+
+% These parsing functions are similar to the preceding ones
+% except that they do not make parens into active characters.
+% These are used for "variables" since they have no arguments.
+
+\def\defvarparsebody #1#2#3{\begingroup\inENV% Environment for definitionbody
+\medbreak %
+% Define the end token that this defining construct specifies
+% so that it will exit this group.
+\def#1{\endgraf\endgroup\medbreak}%
+\def#2{\begingroup\obeylines\spacesplit#3}%
+\parindent=0in
+\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindent
+\exdentamount=\defbodyindent
+\begingroup %
+\catcode 61=\active %
+\obeylines\spacesplit#3}
+
+% This is used for \def{tp,vr}parsebody. It could probably be used for
+% some of the others, too, with some judicious conditionals.
+%
+\def\parsebodycommon#1#2#3{%
+ \begingroup\inENV %
+ \medbreak %
+ % Define the end token that this defining construct specifies
+ % so that it will exit this group.
+ \def#1{\endgraf\endgroup\medbreak}%
+ \def#2##1 {\begingroup\obeylines\spacesplit{#3{##1}}}%
+ \parindent=0in
+ \advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindent
+ \exdentamount=\defbodyindent
+ \begingroup\obeylines
+}
+
+\def\defvrparsebody#1#2#3#4 {%
+ \parsebodycommon{#1}{#2}{#3}%
+ \spacesplit{#3{#4}}%
+}
+
+% This loses on `@deftp {Data Type} {struct termios}' -- it thinks the
+% type is just `struct', because we lose the braces in `{struct
+% termios}' when \spacesplit reads its undelimited argument. Sigh.
+% \let\deftpparsebody=\defvrparsebody
+%
+% So, to get around this, we put \empty in with the type name. That
+% way, TeX won't find exactly `{...}' as an undelimited argument, and
+% won't strip off the braces.
+%
+\def\deftpparsebody #1#2#3#4 {%
+ \parsebodycommon{#1}{#2}{#3}%
+ \spacesplit{\parsetpheaderline{#3{#4}}}\empty
+}
+
+% Fine, but then we have to eventually remove the \empty *and* the
+% braces (if any). That's what this does, putting the result in \tptemp.
+%
+\def\removeemptybraces\empty#1\relax{\def\tptemp{#1}}%
+
+% After \spacesplit has done its work, this is called -- #1 is the final
+% thing to call, #2 the type name (which starts with \empty), and #3
+% (which might be empty) the arguments.
+%
+\def\parsetpheaderline#1#2#3{%
+ \removeemptybraces#2\relax
+ #1{\tptemp}{#3}%
+}%
+
+\def\defopvarparsebody #1#2#3#4#5 {\begingroup\inENV %
+\medbreak %
+% Define the end token that this defining construct specifies
+% so that it will exit this group.
+\def#1{\endgraf\endgroup\medbreak}%
+\def#2##1 ##2 {\def#4{##1}%
+\begingroup\obeylines\spacesplit{#3{##2}}}%
+\parindent=0in
+\advance\leftskip by \defbodyindent \advance \rightskip by \defbodyindent
+\exdentamount=\defbodyindent
+\begingroup\obeylines\spacesplit{#3{#5}}}
+
+% Split up #2 at the first space token.
+% call #1 with two arguments:
+% the first is all of #2 before the space token,
+% the second is all of #2 after that space token.
+% If #2 contains no space token, all of it is passed as the first arg
+% and the second is passed as empty.
+
+{\obeylines
+\gdef\spacesplit#1#2^^M{\endgroup\spacesplitfoo{#1}#2 \relax\spacesplitfoo}%
+\long\gdef\spacesplitfoo#1#2 #3#4\spacesplitfoo{%
+\ifx\relax #3%
+#1{#2}{}\else #1{#2}{#3#4}\fi}}
+
+% So much for the things common to all kinds of definitions.
+
+% Define @defun.
+
+% First, define the processing that is wanted for arguments of \defun
+% Use this to expand the args and terminate the paragraph they make up
+
+\def\defunargs #1{\functionparens \sl
+% Expand, preventing hyphenation at `-' chars.
+% Note that groups don't affect changes in \hyphenchar.
+\hyphenchar\tensl=0
+#1%
+\hyphenchar\tensl=45
+\ifnum\parencount=0 \else \errmessage{unbalanced parens in @def arguments}\fi%
+\interlinepenalty=10000
+\advance\rightskip by 0pt plus 1fil
+\endgraf\penalty 10000\vskip -\parskip\penalty 10000%
+}
+
+\def\deftypefunargs #1{%
+% Expand, preventing hyphenation at `-' chars.
+% Note that groups don't affect changes in \hyphenchar.
+% Use \boldbraxnoamp, not \functionparens, so that & is not special.
+\boldbraxnoamp
+\tclose{#1}% avoid \code because of side effects on active chars
+\interlinepenalty=10000
+\advance\rightskip by 0pt plus 1fil
+\endgraf\penalty 10000\vskip -\parskip\penalty 10000%
+}
+
+% Do complete processing of one @defun or @defunx line already parsed.
+
+% @deffn Command forward-char nchars
+
+\def\deffn{\defmethparsebody\Edeffn\deffnx\deffnheader}
+
+\def\deffnheader #1#2#3{\doind {fn}{\code{#2}}%
+\begingroup\defname {#2}{#1}\defunargs{#3}\endgroup %
+\catcode 61=\other % Turn off change made in \defparsebody
+}
+
+% @defun == @deffn Function
+
+\def\defun{\defparsebody\Edefun\defunx\defunheader}
+
+\def\defunheader #1#2{\doind {fn}{\code{#1}}% Make entry in function index
+\begingroup\defname {#1}{Function}%
+\defunargs {#2}\endgroup %
+\catcode 61=\other % Turn off change made in \defparsebody
+}
+
+% @deftypefun int foobar (int @var{foo}, float @var{bar})
+
+\def\deftypefun{\defparsebody\Edeftypefun\deftypefunx\deftypefunheader}
+
+% #1 is the data type. #2 is the name and args.
+\def\deftypefunheader #1#2{\deftypefunheaderx{#1}#2 \relax}
+% #1 is the data type, #2 the name, #3 the args.
+\def\deftypefunheaderx #1#2 #3\relax{%
+\doind {fn}{\code{#2}}% Make entry in function index
+\begingroup\defname {\defheaderxcond#1\relax$$$#2}{Function}%
+\deftypefunargs {#3}\endgroup %
+\catcode 61=\other % Turn off change made in \defparsebody
+}
+
+% @deftypefn {Library Function} int foobar (int @var{foo}, float @var{bar})
+
+\def\deftypefn{\defmethparsebody\Edeftypefn\deftypefnx\deftypefnheader}
+
+% \defheaderxcond#1\relax$$$
+% puts #1 in @code, followed by a space, but does nothing if #1 is null.
+\def\defheaderxcond#1#2$$${\ifx#1\relax\else\code{#1#2} \fi}
+
+% #1 is the classification. #2 is the data type. #3 is the name and args.
+\def\deftypefnheader #1#2#3{\deftypefnheaderx{#1}{#2}#3 \relax}
+% #1 is the classification, #2 the data type, #3 the name, #4 the args.
+\def\deftypefnheaderx #1#2#3 #4\relax{%
+\doind {fn}{\code{#3}}% Make entry in function index
+\begingroup
+\normalparens % notably, turn off `&' magic, which prevents
+% at least some C++ text from working
+\defname {\defheaderxcond#2\relax$$$#3}{#1}%
+\deftypefunargs {#4}\endgroup %
+\catcode 61=\other % Turn off change made in \defparsebody
+}
+
+% @defmac == @deffn Macro
+
+\def\defmac{\defparsebody\Edefmac\defmacx\defmacheader}
+
+\def\defmacheader #1#2{\doind {fn}{\code{#1}}% Make entry in function index
+\begingroup\defname {#1}{Macro}%
+\defunargs {#2}\endgroup %
+\catcode 61=\other % Turn off change made in \defparsebody
+}
+
+% @defspec == @deffn Special Form
+
+\def\defspec{\defparsebody\Edefspec\defspecx\defspecheader}
+
+\def\defspecheader #1#2{\doind {fn}{\code{#1}}% Make entry in function index
+\begingroup\defname {#1}{Special Form}%
+\defunargs {#2}\endgroup %
+\catcode 61=\other % Turn off change made in \defparsebody
+}
+
+% This definition is run if you use @defunx
+% anywhere other than immediately after a @defun or @defunx.
+
+\def\deffnx #1 {\errmessage{@deffnx in invalid context}}
+\def\defunx #1 {\errmessage{@defunx in invalid context}}
+\def\defmacx #1 {\errmessage{@defmacx in invalid context}}
+\def\defspecx #1 {\errmessage{@defspecx in invalid context}}
+\def\deftypefnx #1 {\errmessage{@deftypefnx in invalid context}}
+\def\deftypeunx #1 {\errmessage{@deftypeunx in invalid context}}
+
+% @defmethod, and so on
+
+% @defop {Funny Method} foo-class frobnicate argument
+
+\def\defop #1 {\def\defoptype{#1}%
+\defopparsebody\Edefop\defopx\defopheader\defoptype}
+
+\def\defopheader #1#2#3{%
+\dosubind {fn}{\code{#2}}{on #1}% Make entry in function index
+\begingroup\defname {#2}{\defoptype{} on #1}%
+\defunargs {#3}\endgroup %
+}
+
+% @defmethod == @defop Method
+
+\def\defmethod{\defmethparsebody\Edefmethod\defmethodx\defmethodheader}
+
+\def\defmethodheader #1#2#3{%
+\dosubind {fn}{\code{#2}}{on #1}% entry in function index
+\begingroup\defname {#2}{Method on #1}%
+\defunargs {#3}\endgroup %
+}
+
+% @defcv {Class Option} foo-class foo-flag
+
+\def\defcv #1 {\def\defcvtype{#1}%
+\defopvarparsebody\Edefcv\defcvx\defcvarheader\defcvtype}
+
+\def\defcvarheader #1#2#3{%
+\dosubind {vr}{\code{#2}}{of #1}% Make entry in var index
+\begingroup\defname {#2}{\defcvtype{} of #1}%
+\defvarargs {#3}\endgroup %
+}
+
+% @defivar == @defcv {Instance Variable}
+
+\def\defivar{\defvrparsebody\Edefivar\defivarx\defivarheader}
+
+\def\defivarheader #1#2#3{%
+\dosubind {vr}{\code{#2}}{of #1}% Make entry in var index
+\begingroup\defname {#2}{Instance Variable of #1}%
+\defvarargs {#3}\endgroup %
+}
+
+% These definitions are run if you use @defmethodx, etc.,
+% anywhere other than immediately after a @defmethod, etc.
+
+\def\defopx #1 {\errmessage{@defopx in invalid context}}
+\def\defmethodx #1 {\errmessage{@defmethodx in invalid context}}
+\def\defcvx #1 {\errmessage{@defcvx in invalid context}}
+\def\defivarx #1 {\errmessage{@defivarx in invalid context}}
+
+% Now @defvar
+
+% First, define the processing that is wanted for arguments of @defvar.
+% This is actually simple: just print them in roman.
+% This must expand the args and terminate the paragraph they make up
+\def\defvarargs #1{\normalparens #1%
+\interlinepenalty=10000
+\endgraf\penalty 10000\vskip -\parskip\penalty 10000}
+
+% @defvr Counter foo-count
+
+\def\defvr{\defvrparsebody\Edefvr\defvrx\defvrheader}
+
+\def\defvrheader #1#2#3{\doind {vr}{\code{#2}}%
+\begingroup\defname {#2}{#1}\defvarargs{#3}\endgroup}
+
+% @defvar == @defvr Variable
+
+\def\defvar{\defvarparsebody\Edefvar\defvarx\defvarheader}
+
+\def\defvarheader #1#2{\doind {vr}{\code{#1}}% Make entry in var index
+\begingroup\defname {#1}{Variable}%
+\defvarargs {#2}\endgroup %
+}
+
+% @defopt == @defvr {User Option}
+
+\def\defopt{\defvarparsebody\Edefopt\defoptx\defoptheader}
+
+\def\defoptheader #1#2{\doind {vr}{\code{#1}}% Make entry in var index
+\begingroup\defname {#1}{User Option}%
+\defvarargs {#2}\endgroup %
+}
+
+% @deftypevar int foobar
+
+\def\deftypevar{\defvarparsebody\Edeftypevar\deftypevarx\deftypevarheader}
+
+% #1 is the data type. #2 is the name.
+\def\deftypevarheader #1#2{%
+\doind {vr}{\code{#2}}% Make entry in variables index
+\begingroup\defname {\defheaderxcond#1\relax$$$#2}{Variable}%
+\interlinepenalty=10000
+\endgraf\penalty 10000\vskip -\parskip\penalty 10000
+\endgroup}
+
+% @deftypevr {Global Flag} int enable
+
+\def\deftypevr{\defvrparsebody\Edeftypevr\deftypevrx\deftypevrheader}
+
+\def\deftypevrheader #1#2#3{\doind {vr}{\code{#3}}%
+\begingroup\defname {\defheaderxcond#2\relax$$$#3}{#1}
+\interlinepenalty=10000
+\endgraf\penalty 10000\vskip -\parskip\penalty 10000
+\endgroup}
+
+% This definition is run if you use @defvarx
+% anywhere other than immediately after a @defvar or @defvarx.
+
+\def\defvrx #1 {\errmessage{@defvrx in invalid context}}
+\def\defvarx #1 {\errmessage{@defvarx in invalid context}}
+\def\defoptx #1 {\errmessage{@defoptx in invalid context}}
+\def\deftypevarx #1 {\errmessage{@deftypevarx in invalid context}}
+\def\deftypevrx #1 {\errmessage{@deftypevrx in invalid context}}
+
+% Now define @deftp
+% Args are printed in bold, a slight difference from @defvar.
+
+\def\deftpargs #1{\bf \defvarargs{#1}}
+
+% @deftp Class window height width ...
+
+\def\deftp{\deftpparsebody\Edeftp\deftpx\deftpheader}
+
+\def\deftpheader #1#2#3{\doind {tp}{\code{#2}}%
+\begingroup\defname {#2}{#1}\deftpargs{#3}\endgroup}
+
+% This definition is run if you use @deftpx, etc
+% anywhere other than immediately after a @deftp, etc.
+
+\def\deftpx #1 {\errmessage{@deftpx in invalid context}}
+
+
+\message{cross reference,}
+% Define cross-reference macros
+\newwrite \auxfile
+
+\newif\ifhavexrefs % True if xref values are known.
+\newif\ifwarnedxrefs % True if we warned once that they aren't known.
+
+% @inforef is simple.
+\def\inforef #1{\inforefzzz #1,,,,**}
+\def\inforefzzz #1,#2,#3,#4**{\putwordSee{} \putwordInfo{} \putwordfile{} \file{\ignorespaces #3{}},
+ node \samp{\ignorespaces#1{}}}
+
+% \setref{foo} defines a cross-reference point named foo.
+
+\def\setref#1{%
+\dosetq{#1-title}{Ytitle}%
+\dosetq{#1-pg}{Ypagenumber}%
+\dosetq{#1-snt}{Ysectionnumberandtype}}
+
+\def\unnumbsetref#1{%
+\dosetq{#1-title}{Ytitle}%
+\dosetq{#1-pg}{Ypagenumber}%
+\dosetq{#1-snt}{Ynothing}}
+
+\def\appendixsetref#1{%
+\dosetq{#1-title}{Ytitle}%
+\dosetq{#1-pg}{Ypagenumber}%
+\dosetq{#1-snt}{Yappendixletterandtype}}
+
+% \xref, \pxref, and \ref generate cross-references to specified points.
+% For \xrefX, #1 is the node name, #2 the name of the Info
+% cross-reference, #3 the printed node name, #4 the name of the Info
+% file, #5 the name of the printed manual. All but the node name can be
+% omitted.
+%
+\def\pxref#1{\putwordsee{} \xrefX[#1,,,,,,,]}
+\def\xref#1{\putwordSee{} \xrefX[#1,,,,,,,]}
+\def\ref#1{\xrefX[#1,,,,,,,]}
+\def\xrefX[#1,#2,#3,#4,#5,#6]{\begingroup
+ \def\printedmanual{\ignorespaces #5}%
+ \def\printednodename{\ignorespaces #3}%
+ \setbox1=\hbox{\printedmanual}%
+ \setbox0=\hbox{\printednodename}%
+ \ifdim \wd0 = 0pt
+ % No printed node name was explicitly given.
+ \expandafter\ifx\csname SETxref-automatic-section-title\endcsname\relax
+ % Use the node name inside the square brackets.
+ \def\printednodename{\ignorespaces #1}%
+ \else
+ % Use the actual chapter/section title appear inside
+ % the square brackets. Use the real section title if we have it.
+ \ifdim \wd1>0pt%
+ % It is in another manual, so we don't have it.
+ \def\printednodename{\ignorespaces #1}%
+ \else
+ \ifhavexrefs
+ % We know the real title if we have the xref values.
+ \def\printednodename{\refx{#1-title}{}}%
+ \else
+ % Otherwise just copy the Info node name.
+ \def\printednodename{\ignorespaces #1}%
+ \fi%
+ \fi
+ \fi
+ \fi
+ %
+ % If we use \unhbox0 and \unhbox1 to print the node names, TeX does not
+ % insert empty discretionaries after hyphens, which means that it will
+ % not find a line break at a hyphen in a node names. Since some manuals
+ % are best written with fairly long node names, containing hyphens, this
+ % is a loss. Therefore, we give the text of the node name again, so it
+ % is as if TeX is seeing it for the first time.
+ \ifdim \wd1 > 0pt
+ \putwordsection{} ``\printednodename'' in \cite{\printedmanual}%
+ \else
+ % _ (for example) has to be the character _ for the purposes of the
+ % control sequence corresponding to the node, but it has to expand
+ % into the usual \leavevmode...\vrule stuff for purposes of
+ % printing. So we \turnoffactive for the \refx-snt, back on for the
+ % printing, back off for the \refx-pg.
+ {\turnoffactive \refx{#1-snt}{}}%
+ \space [\printednodename],\space
+ \turnoffactive \putwordpage\tie\refx{#1-pg}{}%
+ \fi
+\endgroup}
+
+% \dosetq is the interface for calls from other macros
+
+% Use \turnoffactive so that punctuation chars such as underscore
+% work in node names.
+\def\dosetq #1#2{{\let\folio=0 \turnoffactive \auxhat%
+\edef\next{\write\auxfile{\internalsetq {#1}{#2}}}%
+\next}}
+
+% \internalsetq {foo}{page} expands into
+% CHARACTERS 'xrdef {foo}{...expansion of \Ypage...}
+% When the aux file is read, ' is the escape character
+
+\def\internalsetq #1#2{'xrdef {#1}{\csname #2\endcsname}}
+
+% Things to be expanded by \internalsetq
+
+\def\Ypagenumber{\folio}
+
+\def\Ytitle{\thissection}
+
+\def\Ynothing{}
+
+\def\Ysectionnumberandtype{%
+\ifnum\secno=0 \putwordChapter\xreftie\the\chapno %
+\else \ifnum \subsecno=0 \putwordSection\xreftie\the\chapno.\the\secno %
+\else \ifnum \subsubsecno=0 %
+\putwordSection\xreftie\the\chapno.\the\secno.\the\subsecno %
+\else %
+\putwordSection\xreftie\the\chapno.\the\secno.\the\subsecno.\the\subsubsecno %
+\fi \fi \fi }
+
+\def\Yappendixletterandtype{%
+\ifnum\secno=0 \putwordAppendix\xreftie'char\the\appendixno{}%
+\else \ifnum \subsecno=0 \putwordSection\xreftie'char\the\appendixno.\the\secno %
+\else \ifnum \subsubsecno=0 %
+\putwordSection\xreftie'char\the\appendixno.\the\secno.\the\subsecno %
+\else %
+\putwordSection\xreftie'char\the\appendixno.\the\secno.\the\subsecno.\the\subsubsecno %
+\fi \fi \fi }
+
+\gdef\xreftie{'tie}
+
+% Use TeX 3.0's \inputlineno to get the line number, for better error
+% messages, but if we're using an old version of TeX, don't do anything.
+%
+\ifx\inputlineno\thisisundefined
+ \let\linenumber = \empty % Non-3.0.
+\else
+ \def\linenumber{\the\inputlineno:\space}
+\fi
+
+% Define \refx{NAME}{SUFFIX} to reference a cross-reference string named NAME.
+% If its value is nonempty, SUFFIX is output afterward.
+
+\def\refx#1#2{%
+ \expandafter\ifx\csname X#1\endcsname\relax
+ % If not defined, say something at least.
+ $\langle$un\-de\-fined$\rangle$%
+ \ifhavexrefs
+ \message{\linenumber Undefined cross reference `#1'.}%
+ \else
+ \ifwarnedxrefs\else
+ \global\warnedxrefstrue
+ \message{Cross reference values unknown; you must run TeX again.}%
+ \fi
+ \fi
+ \else
+ % It's defined, so just use it.
+ \csname X#1\endcsname
+ \fi
+ #2% Output the suffix in any case.
+}
+
+% Read the last existing aux file, if any. No error if none exists.
+
+% This is the macro invoked by entries in the aux file.
+\def\xrdef #1#2{
+{\catcode`\'=\other\expandafter \gdef \csname X#1\endcsname {#2}}}
+
+\def\readauxfile{%
+\begingroup
+\catcode `\^^@=\other
+\catcode `\=\other
+\catcode `\=\other
+\catcode `\^^C=\other
+\catcode `\^^D=\other
+\catcode `\^^E=\other
+\catcode `\^^F=\other
+\catcode `\^^G=\other
+\catcode `\^^H=\other
+\catcode `\ =\other
+\catcode `\^^L=\other
+\catcode `\=\other
+\catcode `\=\other
+\catcode `\=\other
+\catcode `\=\other
+\catcode `\=\other
+\catcode `\=\other
+\catcode `\=\other
+\catcode `\=\other
+\catcode `\=\other
+\catcode `\=\other
+\catcode `\=\other
+\catcode `\=\other
+\catcode 26=\other
+\catcode `\^^[=\other
+\catcode `\^^\=\other
+\catcode `\^^]=\other
+\catcode `\^^^=\other
+\catcode `\^^_=\other
+\catcode `\@=\other
+\catcode `\^=\other
+\catcode `\~=\other
+\catcode `\[=\other
+\catcode `\]=\other
+\catcode`\"=\other
+\catcode`\_=\other
+\catcode`\|=\other
+\catcode`\<=\other
+\catcode`\>=\other
+\catcode `\$=\other
+\catcode `\#=\other
+\catcode `\&=\other
+% `\+ does not work, so use 43.
+\catcode 43=\other
+% Make the characters 128-255 be printing characters
+{%
+ \count 1=128
+ \def\loop{%
+ \catcode\count 1=\other
+ \advance\count 1 by 1
+ \ifnum \count 1<256 \loop \fi
+ }%
+}%
+% the aux file uses ' as the escape.
+% Turn off \ as an escape so we do not lose on
+% entries which were dumped with control sequences in their names.
+% For example, 'xrdef {$\leq $-fun}{page ...} made by @defun ^^
+% Reference to such entries still does not work the way one would wish,
+% but at least they do not bomb out when the aux file is read in.
+\catcode `\{=1 \catcode `\}=2
+\catcode `\%=\other
+\catcode `\'=0
+\catcode`\^=7 % to make ^^e4 etc usable in xref tags
+\catcode `\\=\other
+\openin 1 \jobname.aux
+\ifeof 1 \else \closein 1 \input \jobname.aux \global\havexrefstrue
+\global\warnedobstrue
+\fi
+% Open the new aux file. Tex will close it automatically at exit.
+\openout \auxfile=\jobname.aux
+\endgroup}
+
+
+% Footnotes.
+
+\newcount \footnoteno
+
+% The trailing space in the following definition for supereject is
+% vital for proper filling; pages come out unaligned when you do a
+% pagealignmacro call if that space before the closing brace is
+% removed. (Generally, numeric constants should always be followed by a
+% space to prevent strange expansion errors.)
+\def\supereject{\par\penalty -20000\footnoteno =0 }
+
+% @footnotestyle is meaningful for info output only..
+\let\footnotestyle=\comment
+
+\let\ptexfootnote=\footnote
+
+{\catcode `\@=11
+%
+% Auto-number footnotes. Otherwise like plain.
+\gdef\footnote{%
+ \global\advance\footnoteno by \@ne
+ \edef\thisfootno{$^{\the\footnoteno}$}%
+ %
+ % In case the footnote comes at the end of a sentence, preserve the
+ % extra spacing after we do the footnote number.
+ \let\@sf\empty
+ \ifhmode\edef\@sf{\spacefactor\the\spacefactor}\/\fi
+ %
+ % Remove inadvertent blank space before typesetting the footnote number.
+ \unskip
+ \thisfootno\@sf
+ \footnotezzz
+}%
+
+% Don't bother with the trickery in plain.tex to not require the
+% footnote text as a parameter. Our footnotes don't need to be so general.
+%
+\long\gdef\footnotezzz#1{\insert\footins{%
+ % We want to typeset this text as a normal paragraph, even if the
+ % footnote reference occurs in (for example) a display environment.
+ % So reset some parameters.
+ \interlinepenalty\interfootnotelinepenalty
+ \splittopskip\ht\strutbox % top baseline for broken footnotes
+ \splitmaxdepth\dp\strutbox
+ \floatingpenalty\@MM
+ \leftskip\z@skip
+ \rightskip\z@skip
+ \spaceskip\z@skip
+ \xspaceskip\z@skip
+ \parindent\defaultparindent
+ %
+ % Hang the footnote text off the number.
+ \hang
+ \textindent{\thisfootno}%
+ %
+ % Don't crash into the line above the footnote text. Since this
+ % expands into a box, it must come within the paragraph, lest it
+ % provide a place where TeX can split the footnote.
+ \footstrut
+ #1\strut}%
+}
+
+}%end \catcode `\@=11
+
+% Set the baselineskip to #1, and the lineskip and strut size
+% correspondingly. There is no deep meaning behind these magic numbers
+% used as factors; they just match (closely enough) what Knuth defined.
+%
+\def\lineskipfactor{.08333}
+\def\strutheightpercent{.70833}
+\def\strutdepthpercent {.29167}
+%
+\def\setleading#1{%
+ \normalbaselineskip = #1\relax
+ \normallineskip = \lineskipfactor\normalbaselineskip
+ \normalbaselines
+ \setbox\strutbox =\hbox{%
+ \vrule width0pt height\strutheightpercent\baselineskip
+ depth \strutdepthpercent \baselineskip
+ }%
+}
+
+% @| inserts a changebar to the left of the current line. It should
+% surround any changed text. This approach does *not* work if the
+% change spans more than two lines of output. To handle that, we would
+% have adopt a much more difficult approach (putting marks into the main
+% vertical list for the beginning and end of each change).
+%
+\def\|{%
+ % \vadjust can only be used in horizontal mode.
+ \leavevmode
+ %
+ % Append this vertical mode material after the current line in the output.
+ \vadjust{%
+ % We want to insert a rule with the height and depth of the current
+ % leading; that is exactly what \strutbox is supposed to record.
+ \vskip-\baselineskip
+ %
+ % \vadjust-items are inserted at the left edge of the type. So
+ % the \llap here moves out into the left-hand margin.
+ \llap{%
+ %
+ % For a thicker or thinner bar, change the `1pt'.
+ \vrule height\baselineskip width1pt
+ %
+ % This is the space between the bar and the text.
+ \hskip 12pt
+ }%
+ }%
+}
+
+% For a final copy, take out the rectangles
+% that mark overfull boxes (in case you have decided
+% that the text looks ok even though it passes the margin).
+%
+\def\finalout{\overfullrule=0pt}
+
+
+% End of control word definitions.
+
+\message{and turning on texinfo input format.}
+
+\def\openindices{%
+ \newindex{cp}%
+ \newcodeindex{fn}%
+ \newcodeindex{vr}%
+ \newcodeindex{tp}%
+ \newcodeindex{ky}%
+ \newcodeindex{pg}%
+}
+
+% Set some numeric style parameters, for 8.5 x 11 format.
+
+\hsize = 6in
+\hoffset = .25in
+\newdimen\defaultparindent \defaultparindent = 15pt
+\parindent = \defaultparindent
+\parskip 3pt plus 2pt minus 1pt
+\setleading{13.2pt}
+\advance\topskip by 1.2cm
+
+\chapheadingskip = 15pt plus 4pt minus 2pt
+\secheadingskip = 12pt plus 3pt minus 2pt
+\subsecheadingskip = 9pt plus 2pt minus 2pt
+
+% Prevent underfull vbox error messages.
+\vbadness=10000
+
+% Following George Bush, just get rid of widows and orphans.
+\widowpenalty=10000
+\clubpenalty=10000
+
+% Use TeX 3.0's \emergencystretch to help line breaking, but if we're
+% using an old version of TeX, don't do anything. We want the amount of
+% stretch added to depend on the line length, hence the dependence on
+% \hsize. This makes it come to about 9pt for the 8.5x11 format.
+%
+\ifx\emergencystretch\thisisundefined
+ % Allow us to assign to \emergencystretch anyway.
+ \def\emergencystretch{\dimen0}%
+\else
+ \emergencystretch = \hsize
+ \divide\emergencystretch by 45
+\fi
+
+% Use @smallbook to reset parameters for 7x9.5 format (or else 7x9.25)
+\def\smallbook{
+ \global\chapheadingskip = 15pt plus 4pt minus 2pt
+ \global\secheadingskip = 12pt plus 3pt minus 2pt
+ \global\subsecheadingskip = 9pt plus 2pt minus 2pt
+ %
+ \global\lispnarrowing = 0.3in
+ \setleading{12pt}
+ \advance\topskip by -1cm
+ \global\parskip 2pt plus 1pt
+ \global\hsize = 5in
+ \global\vsize=7.5in
+ \global\tolerance=700
+ \global\hfuzz=1pt
+ \global\contentsrightmargin=0pt
+ \global\deftypemargin=0pt
+ \global\defbodyindent=.5cm
+ %
+ \global\pagewidth=\hsize
+ \global\pageheight=\vsize
+ %
+ \global\let\smalllisp=\smalllispx
+ \global\let\smallexample=\smalllispx
+ \global\def\Esmallexample{\Esmalllisp}
+}
+
+% Use @afourpaper to print on European A4 paper.
+\def\afourpaper{
+\global\tolerance=700
+\global\hfuzz=1pt
+\setleading{12pt}
+\global\parskip 15pt plus 1pt
+
+\global\vsize= 53\baselineskip
+\advance\vsize by \topskip
+%\global\hsize= 5.85in % A4 wide 10pt
+\global\hsize= 6.5in
+\global\outerhsize=\hsize
+\global\advance\outerhsize by 0.5in
+\global\outervsize=\vsize
+\global\advance\outervsize by 0.6in
+
+\global\pagewidth=\hsize
+\global\pageheight=\vsize
+}
+
+\bindingoffset=0pt
+\normaloffset=\hoffset
+\pagewidth=\hsize
+\pageheight=\vsize
+
+% Allow control of the text dimensions. Parameters in order: textheight;
+% textwidth; voffset; hoffset; binding offset; topskip.
+% All require a dimension;
+% header is additional; added length extends the bottom of the page.
+
+\def\changepagesizes#1#2#3#4#5#6{
+ \global\vsize= #1
+ \global\topskip= #6
+ \advance\vsize by \topskip
+ \global\voffset= #3
+ \global\hsize= #2
+ \global\outerhsize=\hsize
+ \global\advance\outerhsize by 0.5in
+ \global\outervsize=\vsize
+ \global\advance\outervsize by 0.6in
+ \global\pagewidth=\hsize
+ \global\pageheight=\vsize
+ \global\normaloffset= #4
+ \global\bindingoffset= #5}
+
+% A specific text layout, 24x15cm overall, intended for A4 paper. Top margin
+% 29mm, hence bottom margin 28mm, nominal side margin 3cm.
+\def\afourlatex
+ {\global\tolerance=700
+ \global\hfuzz=1pt
+ \setleading{12pt}
+ \global\parskip 15pt plus 1pt
+ \advance\baselineskip by 1.6pt
+ \changepagesizes{237mm}{150mm}{3.6mm}{3.6mm}{3mm}{7mm}
+ }
+
+% Use @afourwide to print on European A4 paper in wide format.
+\def\afourwide{\afourpaper
+\changepagesizes{9.5in}{6.5in}{\hoffset}{\normaloffset}{\bindingoffset}{7mm}}
+
+% Define macros to output various characters with catcode for normal text.
+\catcode`\"=\other
+\catcode`\~=\other
+\catcode`\^=\other
+\catcode`\_=\other
+\catcode`\|=\other
+\catcode`\<=\other
+\catcode`\>=\other
+\catcode`\+=\other
+\def\normaldoublequote{"}
+\def\normaltilde{~}
+\def\normalcaret{^}
+\def\normalunderscore{_}
+\def\normalverticalbar{|}
+\def\normalless{<}
+\def\normalgreater{>}
+\def\normalplus{+}
+
+% This macro is used to make a character print one way in ttfont
+% where it can probably just be output, and another way in other fonts,
+% where something hairier probably needs to be done.
+%
+% #1 is what to print if we are indeed using \tt; #2 is what to print
+% otherwise. Since all the Computer Modern typewriter fonts have zero
+% interword stretch (and shrink), and it is reasonable to expect all
+% typewriter fonts to have this, we can check that font parameter.
+%
+\def\ifusingtt#1#2{\ifdim \fontdimen3\the\font=0pt #1\else #2\fi}
+
+% Turn off all special characters except @
+% (and those which the user can use as if they were ordinary).
+% Most of these we simply print from the \tt font, but for some, we can
+% use math or other variants that look better in normal text.
+
+\catcode`\"=\active
+\def\activedoublequote{{\tt \char '042}}
+\let"=\activedoublequote
+\catcode`\~=\active
+\def~{{\tt \char '176}}
+\chardef\hat=`\^
+\catcode`\^=\active
+\def\auxhat{\def^{'hat}}
+\def^{{\tt \hat}}
+
+\catcode`\_=\active
+\def_{\ifusingtt\normalunderscore\_}
+% Subroutine for the previous macro.
+\def\_{\leavevmode \kern.06em \vbox{\hrule width.3em height.1ex}}
+
+\catcode`\|=\active
+\def|{{\tt \char '174}}
+\chardef \less=`\<
+\catcode`\<=\active
+\def<{{\tt \less}}
+\chardef \gtr=`\>
+\catcode`\>=\active
+\def>{{\tt \gtr}}
+\catcode`\+=\active
+\def+{{\tt \char 43}}
+%\catcode 27=\active
+%\def^^[{$\diamondsuit$}
+
+% Set up an active definition for =, but don't enable it most of the time.
+{\catcode`\==\active
+\global\def={{\tt \char 61}}}
+
+\catcode`+=\active
+\catcode`\_=\active
+
+% If a .fmt file is being used, characters that might appear in a file
+% name cannot be active until we have parsed the command line.
+% So turn them off again, and have \everyjob (or @setfilename) turn them on.
+% \otherifyactive is called near the end of this file.
+\def\otherifyactive{\catcode`+=\other \catcode`\_=\other}
+
+\catcode`\@=0
+
+% \rawbackslashxx output one backslash character in current font
+\global\chardef\rawbackslashxx=`\\
+%{\catcode`\\=\other
+%@gdef@rawbackslashxx{\}}
+
+% \rawbackslash redefines \ as input to do \rawbackslashxx.
+{\catcode`\\=\active
+@gdef@rawbackslash{@let\=@rawbackslashxx }}
+
+% \normalbackslash outputs one backslash in fixed width font.
+\def\normalbackslash{{\tt\rawbackslashxx}}
+
+% Say @foo, not \foo, in error messages.
+\escapechar=`\@
+
+% \catcode 17=0 % Define control-q
+\catcode`\\=\active
+
+% Used sometimes to turn off (effectively) the active characters
+% even after parsing them.
+@def@turnoffactive{@let"=@normaldoublequote
+@let\=@realbackslash
+@let~=@normaltilde
+@let^=@normalcaret
+@let_=@normalunderscore
+@let|=@normalverticalbar
+@let<=@normalless
+@let>=@normalgreater
+@let+=@normalplus}
+
+@def@normalturnoffactive{@let"=@normaldoublequote
+@let\=@normalbackslash
+@let~=@normaltilde
+@let^=@normalcaret
+@let_=@normalunderscore
+@let|=@normalverticalbar
+@let<=@normalless
+@let>=@normalgreater
+@let+=@normalplus}
+
+% Make _ and + \other characters, temporarily.
+% This is canceled by @fixbackslash.
+@otherifyactive
+
+% If a .fmt file is being used, we don't want the `\input texinfo' to show up.
+% That is what \eatinput is for; after that, the `\' should revert to printing
+% a backslash.
+%
+@gdef@eatinput input texinfo{@fixbackslash}
+@global@let\ = @eatinput
+
+% On the other hand, perhaps the file did not have a `\input texinfo'. Then
+% the first `\{ in the file would cause an error. This macro tries to fix
+% that, assuming it is called before the first `\' could plausibly occur.
+% Also back turn on active characters that might appear in the input
+% file name, in case not using a pre-dumped format.
+%
+@gdef@fixbackslash{@ifx\@eatinput @let\ = @normalbackslash @fi
+ @catcode`+=@active @catcode`@_=@active}
+
+%% These look ok in all fonts, so just make them not special. The @rm below
+%% makes sure that the current font starts out as the newly loaded cmr10
+@catcode`@$=@other @catcode`@%=@other @catcode`@&=@other @catcode`@#=@other
+
+@textfonts
+@rm
+
+@c Local variables:
+@c page-delimiter: "^\\\\message"
+@c End:
diff --git a/contrib/texinfo/texinfo.texi b/contrib/texinfo/texinfo.texi
new file mode 100644
index 0000000..8d67d86
--- /dev/null
+++ b/contrib/texinfo/texinfo.texi
@@ -0,0 +1,16886 @@
+\input texinfo.tex @c -*-texinfo-*-
+@comment %**start of header
+@setfilename texinfo
+@settitle Texinfo @value{edition}
+@c Define a new index for options.
+@defcodeindex op
+@c Put everything except function (command, in this case) names in one
+index (arbitrarily chosen to be the concept index).
+@syncodeindex op cp
+@syncodeindex vr cp
+@syncodeindex pg cp
+@footnotestyle separate
+@paragraphindent 2
+@finalout
+@comment %**end of header
+@comment $Id: texinfo.texi,v 1.22 1996/10/03 23:24:24 karl Exp $
+
+@c Before release, run C-u C-c C-u C-a (texinfo-all-menus-update with a
+@c prefix arg). This updates the node pointers, which texinfmt.el needs.
+
+@dircategory Texinfo documentation system
+@direntry
+* Texinfo: (texinfo). The GNU documentation format.
+* install-info: (texinfo)Invoking install-info. Updating info/dir entries.
+* texi2dvi: (texinfo)Format with texi2dvi. Printing Texinfo documentation.
+* texindex: (texinfo)Format with tex/texindex. Sorting Texinfo index files.
+@end direntry
+
+@c Set smallbook if printing in smallbook format so the example of the
+@c smallbook font is actually written using smallbook; in bigbook, a kludge
+@c is used for TeX output.
+@smallbook
+@set smallbook
+@c @@clear smallbook
+
+@set edition 2.23
+@set update-month October 1996
+@set update-date 1 @value{update-month}
+
+@c Currently undocumented command, 5 December 1993:
+@c
+@c nwnode (Same as node, but no warnings; for `makeinfo'.)
+
+@ifinfo
+This file documents Texinfo, a documentation system that can produce
+both on-line information and a printed manual from a single source file.
+
+Copyright (C) 1988, 90, 91, 92, 93, 95, 1996 Free Software Foundation, Inc.
+
+This is the second edition of the Texinfo documentation,@*
+and is consistent with version 2 of @file{texinfo.tex}.
+
+Permission is granted to make and distribute verbatim copies of
+this manual provided the copyright notice and this permission notice
+are preserved on all copies.
+
+@ignore
+Permission is granted to process this file through TeX and print the
+results, provided the printed document carries copying permission
+notice identical to this one except for the removal of this paragraph
+(this paragraph not being relevant to the printed manual).
+
+@end ignore
+Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, provided that the entire
+resulting derived work is distributed under the terms of a permission
+notice identical to this one.
+
+Permission is granted to copy and distribute translations of this manual
+into another language, under the above conditions for modified versions,
+except that this permission notice may be stated in a translation approved
+by the Free Software Foundation.
+@end ifinfo
+
+@setchapternewpage odd
+
+@shorttitlepage Texinfo
+
+@titlepage
+@c use the new format for titles
+@title Texinfo
+@subtitle The GNU Documentation Format
+@subtitle Edition @value{edition}, for Texinfo Version Three
+@subtitle @value{update-month}
+
+@author Robert J.@: Chassell
+@author Richard M.@: Stallman
+
+@c Include the Distribution inside the titlepage so
+@c that headings are turned off.
+
+@page
+@vskip 0pt plus 1filll
+Copyright @copyright{} 1988, 1990, 1991, 1992, 1993, 1995, 1996 Free Software Foundation, Inc.
+
+@sp 2
+This is the second edition of the Texinfo documentation,@*
+and is consistent with version 2 of @file{texinfo.tex}.
+@sp 2
+
+Published by the Free Software Foundation @*
+59 Temple Place Suite 330, @*
+Boston, MA 02111-1307 USA @*
+Printed copies are available for $15 each.@*
+ISBN 1-882114-64-7
+@c ISBN 1-882114-63-9 is for edition 2.20 of 28 February 1995
+@c ISBN 1-882114-64-7 is for edition 2.23 of 1 October 1996.
+
+Permission is granted to make and distribute verbatim copies of
+this manual provided the copyright notice and this permission notice
+are preserved on all copies.
+
+Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, provided that the entire
+resulting derived work is distributed under the terms of a permission
+notice identical to this one.
+
+Permission is granted to copy and distribute translations of this manual
+into another language, under the above conditions for modified versions,
+except that this permission notice may be stated in a translation approved
+by the Free Software Foundation.
+@sp 2
+Cover art by Etienne Suvasa.
+@end titlepage
+
+@ifinfo
+@node Top, Copying, (dir), (dir)
+@top Texinfo
+
+Texinfo is a documentation system that uses a single source file to
+produce both on-line information and printed output.@refill
+
+The first part of this master menu lists the major nodes in this Info
+document, including the @@-command and concept indices. The rest of
+the menu lists all the lower level nodes in the document.@refill
+
+This is Edition @value{edition} of the Texinfo documentation,
+@w{@value{update-date},} for Texinfo Version Three.
+@end ifinfo
+
+@c Here is a spare copy of the chapter menu entry descriptions,
+@c in case they are accidently deleted
+@ignore
+Your rights.
+Texinfo in brief.
+How to use Texinfo mode.
+What is at the beginning of a Texinfo file?
+What is at the end of a Texinfo file?
+How to create chapters, sections, subsections,
+ appendices, and other parts.
+How to provide structure for a document.
+How to write nodes.
+How to write menus.
+How to write cross references.
+How to mark words and phrases as code,
+ keyboard input, meta-syntactic
+ variables, and the like.
+How to write quotations, examples, etc.
+How to write lists and tables.
+How to create indices.
+How to insert @@-signs, braces, etc.
+How to indicate results of evaluation,
+ expansion of macros, errors, etc.
+How to force and prevent line and page breaks.
+How to describe functions and the like in a uniform manner.
+How to write footnotes.
+How to specify text for either @TeX{} or Info.
+How to print hardcopy.
+How to create an Info file.
+How to install an Info file
+A list of all the Texinfo @@-commands.
+Hints on how to write a Texinfo document.
+A sample Texinfo file to look at.
+Tell readers they have the right to copy
+ and distribute.
+How to incorporate other Texinfo files.
+How to write page headings and footings.
+How to find formatting mistakes.
+All about paragraph refilling.
+A description of @@-Command syntax.
+Texinfo second edition features.
+A menu containing commands and variables.
+A menu covering many topics.
+@end ignore
+
+@menu
+* Copying:: Your rights.
+* Overview:: Texinfo in brief.
+* Texinfo Mode:: How to use Texinfo mode.
+* Beginning a File:: What is at the beginning of a Texinfo file?
+* Ending a File:: What is at the end of a Texinfo file?
+* Structuring:: How to create chapters, sections, subsections,
+ appendices, and other parts.
+* Nodes:: How to write nodes.
+* Menus:: How to write menus.
+* Cross References:: How to write cross references.
+* Marking Text:: How to mark words and phrases as code,
+ keyboard input, meta-syntactic
+ variables, and the like.
+* Quotations and Examples:: How to write quotations, examples, etc.
+* Lists and Tables:: How to write lists and tables.
+* Indices:: How to create indices.
+* Insertions:: How to insert @@-signs, braces, etc.
+* Glyphs:: How to indicate results of evaluation,
+ expansion of macros, errors, etc.
+* Breaks:: How to force and prevent line and page breaks.
+* Definition Commands:: How to describe functions and the like
+ in a uniform manner.
+* Footnotes:: How to write footnotes.
+* Conditionals:: How to specify text for either @TeX{} or Info.
+* Macros:: Defining new Texinfo commands.
+* Format/Print Hardcopy:: How to convert a Texinfo file to a file
+ for printing and how to print that file.
+* Create an Info File:: Convert a Texinfo file into an Info file.
+* Install an Info File:: Make an Info file accessible to users.
+* Command List:: All the Texinfo @@-commands.
+* Tips:: Hints on how to write a Texinfo document.
+* Sample Texinfo File:: A sample Texinfo file to look at.
+* Sample Permissions:: Tell readers they have the right to copy
+ and distribute.
+* Include Files:: How to incorporate other Texinfo files.
+* Headings:: How to write page headings and footings.
+* Catching Mistakes:: How to find formatting mistakes.
+* Refilling Paragraphs:: All about paragraph refilling.
+* Command Syntax:: A description of @@-Command syntax.
+* Obtaining TeX:: How to Obtain @TeX{}.
+* New Features:: Texinfo second edition features.
+* Command and Variable Index:: A menu containing commands and variables.
+* Concept Index:: A menu covering many topics.
+
+@detailmenu
+
+ --- The Detailed Node Listing ---
+
+Overview of Texinfo
+
+* Using Texinfo:: Create a conventional printed book
+ or an Info file.
+* Info Files:: What is an Info file?
+* Printed Books:: Characteristics of a printed book or manual.
+* Formatting Commands:: @@-commands are used for formatting.
+* Conventions:: General rules for writing a Texinfo file.
+* Comments:: How to write comments and mark regions that
+ the formatting commands will ignore.
+* Minimum:: What a Texinfo file must have.
+* Six Parts:: Usually, a Texinfo file has six parts.
+* Short Sample:: A short sample Texinfo file.
+* Acknowledgements::
+
+Using Texinfo Mode
+
+* Texinfo Mode Overview:: How Texinfo mode can help you.
+* Emacs Editing:: Texinfo mode adds to GNU Emacs' general
+ purpose editing features.
+* Inserting:: How to insert frequently used @@-commands.
+* Showing the Structure:: How to show the structure of a file.
+* Updating Nodes and Menus:: How to update or create new nodes and menus.
+* Info Formatting:: How to format for Info.
+* Printing:: How to format and print part or all of a file.
+* Texinfo Mode Summary:: Summary of all the Texinfo mode commands.
+
+Updating Nodes and Menus
+
+* Updating Commands:: Five major updating commands.
+* Updating Requirements:: How to structure a Texinfo file for
+ using the updating command.
+* Other Updating Commands:: How to indent descriptions, insert
+ missing nodes lines, and update
+ nodes in sequence.
+
+Beginning a Texinfo File
+
+* Four Parts:: Four parts begin a Texinfo file.
+* Sample Beginning:: Here is a sample beginning for a Texinfo file.
+* Header:: The very beginning of a Texinfo file.
+* Info Summary and Permissions:: Summary and copying permissions for Info.
+* Titlepage & Copyright Page:: Creating the title and copyright pages.
+* The Top Node:: Creating the `Top' node and master menu.
+* Software Copying Permissions:: Ensure that you and others continue to
+ have the right to use and share software.
+
+The Texinfo File Header
+
+* First Line:: The first line of a Texinfo file.
+* Start of Header:: Formatting a region requires this.
+* setfilename:: Tell Info the name of the Info file.
+* settitle:: Create a title for the printed work.
+* setchapternewpage:: Start chapters on right-hand pages.
+* paragraphindent:: An option to specify paragraph indentation.
+* End of Header:: Formatting a region requires this.
+
+The Title and Copyright Pages
+
+* titlepage:: Create a title for the printed document.
+* titlefont center sp:: The @code{@@titlefont}, @code{@@center},
+ and @code{@@sp} commands.
+* title subtitle author:: The @code{@@title}, @code{@@subtitle},
+ and @code{@@author} commands.
+* Copyright & Permissions:: How to write the copyright notice and
+ include copying permissions.
+* end titlepage:: Turn on page headings after the title and
+ copyright pages.
+* headings on off:: An option for turning headings on and off
+ and double or single sided printing.
+
+The `Top' Node and Master Menu
+
+* Title of Top Node:: Sketch what the file is about.
+* Master Menu Parts:: A master menu has three or more parts.
+
+Ending a Texinfo File
+
+* Printing Indices & Menus:: How to print an index in hardcopy and
+ generate index menus in Info.
+* Contents:: How to create a table of contents.
+* File End:: How to mark the end of a file.
+
+Chapter Structuring
+
+* Tree Structuring:: A manual is like an upside down tree @dots{}
+* Structuring Command Types:: How to divide a manual into parts.
+* makeinfo top:: The @code{@@top} command, part of the `Top' node.
+* chapter::
+* unnumbered & appendix::
+* majorheading & chapheading::
+* section::
+* unnumberedsec appendixsec heading::
+* subsection::
+* unnumberedsubsec appendixsubsec subheading::
+* subsubsection:: Commands for the lowest level sections.
+* Raise/lower sections:: How to change commands' hierarchical level.
+
+Nodes
+
+* Two Paths:: Different commands to structure
+ Info output and printed output.
+* Node Menu Illustration:: A diagram, and sample nodes and menus.
+* node:: How to write a node, in detail.
+* makeinfo Pointer Creation:: How to create node pointers with @code{makeinfo}.
+
+The @code{@@node} Command
+
+* Node Names:: How to choose node and pointer names.
+* Writing a Node:: How to write an @code{@@node} line.
+* Node Line Tips:: Keep names short.
+* Node Line Requirements:: Keep names unique, without @@-commands.
+* First Node:: How to write a `Top' node.
+* makeinfo top command:: How to use the @code{@@top} command.
+* Top Node Summary:: Write a brief description for readers.
+
+Menus
+
+* Menu Location:: Put a menu in a short node.
+* Writing a Menu:: What is a menu?
+* Menu Parts:: A menu entry has three parts.
+* Less Cluttered Menu Entry:: Two part menu entry.
+* Menu Example:: Two and three part menu entries.
+* Other Info Files:: How to refer to a different Info file.
+
+Cross References
+
+* References:: What cross references are for.
+* Cross Reference Commands:: A summary of the different commands.
+* Cross Reference Parts:: A cross reference has several parts.
+* xref:: Begin a reference with `See' @dots{}
+* Top Node Naming:: How to refer to the beginning of another file.
+* ref:: A reference for the last part of a sentence.
+* pxref:: How to write a parenthetical cross reference.
+* inforef:: How to refer to an Info-only file.
+
+@code{@@xref}
+
+* Reference Syntax:: What a reference looks like and requires.
+* One Argument:: @code{@@xref} with one argument.
+* Two Arguments:: @code{@@xref} with two arguments.
+* Three Arguments:: @code{@@xref} with three arguments.
+* Four and Five Arguments:: @code{@@xref} with four and five arguments.
+
+Marking Words and Phrases
+
+* Indicating:: How to indicate definitions, files, etc.
+* Emphasis:: How to emphasize text.
+
+Indicating Definitions, Commands, etc.
+
+* Useful Highlighting:: Highlighting provides useful information.
+* code:: How to indicate code.
+* kbd:: How to show keyboard input.
+* key:: How to specify keys.
+* samp:: How to show a literal sequence of characters.
+* var:: How to indicate a metasyntactic variable.
+* file:: How to indicate the name of a file.
+* dfn:: How to specify a definition.
+* cite:: How to refer to a book that is not in Info.
+* url:: How to indicate a world wide web reference.
+* email:: How to indicate an electronic mail address.
+
+Emphasizing Text
+
+* emph & strong:: How to emphasize text in Texinfo.
+* Smallcaps:: How to use the small caps font.
+* Fonts:: Various font commands for printed output.
+* Customized Highlighting:: How to define highlighting commands.
+
+Quotations and Examples
+
+* Block Enclosing Commands:: Use different constructs for
+ different purposes.
+* quotation:: How to write a quotation.
+* example:: How to write an example in a fixed-width font.
+* noindent:: How to prevent paragraph indentation.
+* Lisp Example:: How to illustrate Lisp code.
+* smallexample & smalllisp:: Forms for the @code{@@smallbook} option.
+* display:: How to write an example in the current font.
+* format:: How to write an example that does not narrow
+ the margins.
+* exdent:: How to undo the indentation of a line.
+* flushleft & flushright:: How to push text flushleft or flushright.
+* cartouche:: How to draw cartouches around examples.
+
+Making Lists and Tables
+
+* Introducing Lists:: Texinfo formats lists for you.
+* itemize:: How to construct a simple list.
+* enumerate:: How to construct a numbered list.
+* Two-column Tables:: How to construct a two-column table.
+* Multi-column Tables:: How to construct generalized tables.
+
+Making a Two-column Table
+
+* table:: How to construct a two-column table.
+* ftable vtable:: How to construct a two-column table
+ with automatic indexing.
+* itemx:: How to put more entries in the first column.
+
+Multi-column Tables
+
+* Multitable Column Widths:: Defining multitable column widths.
+* Multitable Rows:: Defining multitable rows, with examples.
+
+Creating Indices
+
+* Index Entries:: Choose different words for index entries.
+* Predefined Indices:: Use different indices for different kinds
+ of entry.
+* Indexing Commands:: How to make an index entry.
+* Combining Indices:: How to combine indices.
+* New Indices:: How to define your own indices.
+
+Combining Indices
+
+* syncodeindex:: How to merge two indices, using @code{@@code}
+ font for the merged-from index.
+* synindex:: How to merge two indices, using the
+ default font of the merged-to index.
+
+Special Insertions
+
+* Braces Atsigns:: How to insert braces, @samp{@@}.
+* Inserting Space:: How to insert the right amount of space
+ within a sentence.
+* Inserting Accents:: How to insert accents and special characters.
+* Dots Bullets:: How to insert dots and bullets.
+* TeX and copyright:: How to insert the @TeX{} logo
+ and the copyright symbol.
+* pounds:: How to insert the pounds currency symbol.
+* minus:: How to insert a minus sign.
+* math:: How to format a mathematical expression.
+
+Inserting @@ and Braces
+
+* Inserting An Atsign:: How to insert @samp{@@}.
+* Inserting Braces:: How to insert @samp{@{} and @samp{@}}.
+
+Inserting Space
+
+* Not Ending a Sentence:: Sometimes a . doesn't end a sentence.
+* Ending a Sentence:: Sometimes it does.
+* Multiple Spaces:: Inserting multiple spaces.
+* dmn:: How to format a dimension.
+
+Inserting Ellipsis, Dots, and Bullets
+
+* dots:: How to insert dots @dots{}
+* bullet:: How to insert a bullet.
+
+Inserting @TeX{} and the Copyright Symbol
+
+* tex:: How to insert the @TeX{} logo.
+* copyright symbol:: How to use @code{@@copyright}@{@}.
+
+Glyphs for Examples
+
+* Glyphs Summary::
+* result:: How to show the result of expression.
+* expansion:: How to indicate an expansion.
+* Print Glyph:: How to indicate printed output.
+* Error Glyph:: How to indicate an error message.
+* Equivalence:: How to indicate equivalence.
+* Point Glyph:: How to indicate the location of point.
+
+Making and Preventing Breaks
+
+* Break Commands:: Cause and prevent splits.
+* Line Breaks:: How to force a single line to use two lines.
+* - and hyphenation:: How to tell TeX about hyphenation points.
+* w:: How to prevent unwanted line breaks.
+* sp:: How to insert blank lines.
+* page:: How to force the start of a new page.
+* group:: How to prevent unwanted page breaks.
+* need:: Another way to prevent unwanted page breaks.
+
+Definition Commands
+
+* Def Cmd Template:: How to structure a description using a
+ definition command.
+* Optional Arguments:: How to handle optional and repeated arguments.
+* deffnx:: How to group two or more `first' lines.
+* Def Cmds in Detail:: All the definition commands.
+* Def Cmd Conventions:: Conventions for writing definitions.
+* Sample Function Definition::
+
+The Definition Commands
+
+* Functions Commands:: Commands for functions and similar entities.
+* Variables Commands:: Commands for variables and similar entities.
+* Typed Functions:: Commands for functions in typed languages.
+* Typed Variables:: Commands for variables in typed languages.
+* Abstract Objects:: Commands for object-oriented programming.
+* Data Types:: The definition command for data types.
+
+Footnotes
+
+* Footnote Commands:: How to write a footnote in Texinfo.
+* Footnote Styles:: Controlling how footnotes appear in Info.
+
+Conditionally Visible Text
+
+* Conditional Commands:: How to specify text for HTML, Info, or @TeX{}.
+* Using Ordinary TeX Commands:: You can use any and all @TeX{} commands.
+* set clear value:: How to designate which text to format (for
+ both Info and @TeX{}); and how to set a
+ flag to a string that you can insert.
+
+@code{@@set}, @code{@@clear}, and @code{@@value}
+
+* ifset ifclear:: Format a region if a flag is set.
+* value:: Replace a flag with a string.
+* value Example:: An easy way to update edition information.
+
+Macros: Defining New Texinfo Commands
+
+* Defining Macros:: Both defining and undefining new commands.
+* Invoking Macros:: Using a macro, once you've defined it.
+
+Format and Print Hardcopy
+
+* Use TeX:: Use @TeX{} to format for hardcopy.
+* Format with tex/texindex:: How to format in a shell.
+* Format with texi2dvi:: A simpler way to use the shell.
+* Print with lpr:: How to print.
+* Within Emacs:: How to format and print from an Emacs shell.
+* Texinfo Mode Printing:: How to format and print in Texinfo mode.
+* Compile-Command:: How to print using Emacs's compile command.
+* Requirements Summary:: @TeX{} formatting requirements summary.
+* Preparing for TeX:: What you need to do to use @TeX{}.
+* Overfull hboxes:: What are and what to do with overfull hboxes.
+* smallbook:: How to print small format books and manuals.
+* A4 Paper:: How to print on European A4 paper.
+* Cropmarks and Magnification:: How to print marks to indicate the size
+ of pages and how to print scaled up output.
+
+Creating an Info File
+
+* makeinfo advantages:: @code{makeinfo} provides better error checking.
+* Invoking makeinfo:: How to run @code{makeinfo} from a shell.
+* makeinfo options:: Specify fill-column and other options.
+* Pointer Validation:: How to check that pointers point somewhere.
+* makeinfo in Emacs:: How to run @code{makeinfo} from Emacs.
+* texinfo-format commands:: Two Info formatting commands written
+ in Emacs Lisp are an alternative
+ to @code{makeinfo}.
+* Batch Formatting:: How to format for Info in Emacs Batch mode.
+* Tag and Split Files:: How tagged and split files help Info
+ to run better.
+
+Installing an Info File
+
+* Directory file:: The top level menu for all Info files.
+* New Info File:: Listing a new info file.
+* Other Info Directories:: How to specify Info files that are
+ located in other directories.
+* Installing Dir Entries:: How to specify what menu entry to add
+ to the Info directory.
+* Invoking install-info:: @code{install-info} options.
+
+Sample Permissions
+
+* Inserting Permissions:: How to put permissions in your document.
+* ifinfo Permissions:: Sample @samp{ifinfo} copying permissions.
+* Titlepage Permissions:: Sample Titlepage copying permissions.
+
+Include Files
+
+* Using Include Files:: How to use the @code{@@include} command.
+* texinfo-multiple-files-update:: How to create and update nodes and
+ menus when using included files.
+* Include File Requirements:: What @code{texinfo-multiple-files-update} expects.
+* Sample Include File:: A sample outer file with included files
+ within it; and a sample included file.
+* Include Files Evolution:: How use of the @code{@@include} command
+ has changed over time.
+
+Page Headings
+
+* Headings Introduced:: Conventions for using page headings.
+* Heading Format:: Standard page heading formats.
+* Heading Choice:: How to specify the type of page heading.
+* Custom Headings:: How to create your own headings and footings.
+
+Formatting Mistakes
+
+* makeinfo preferred:: @code{makeinfo} finds errors.
+* Debugging with Info:: How to catch errors with Info formatting.
+* Debugging with TeX:: How to catch errors with @TeX{} formatting.
+* Using texinfo-show-structure:: How to use @code{texinfo-show-structure}.
+* Using occur:: How to list all lines containing a pattern.
+* Running Info-Validate:: How to find badly referenced nodes.
+
+Finding Badly Referenced Nodes
+
+* Using Info-validate:: How to run @code{Info-validate}.
+* Unsplit:: How to create an unsplit file.
+* Tagifying:: How to tagify a file.
+* Splitting:: How to split a file manually.
+
+Second Edition Features
+
+* New Texinfo Mode Commands:: The updating commands are especially useful.
+* New Commands:: Many newly described @@-commands.
+@end detailmenu
+@end menu
+
+@node Copying, Overview, Top, Top
+@comment node-name, next, previous, up
+@unnumbered Texinfo Copying Conditions
+@cindex Copying conditions
+@cindex Conditions for copying Texinfo
+
+The programs currently being distributed that relate to Texinfo include
+portions of GNU Emacs, plus other separate programs (including
+@code{makeinfo}, @code{info}, @code{texindex}, and @file{texinfo.tex}).
+These programs are @dfn{free}; this means that everyone is free to use
+them and free to redistribute them on a free basis. The Texinfo-related
+programs are not in the public domain; they are copyrighted and there
+are restrictions on their distribution, but these restrictions are
+designed to permit everything that a good cooperating citizen would want
+to do. What is not allowed is to try to prevent others from further
+sharing any version of these programs that they might get from
+you.@refill
+
+ Specifically, we want to make sure that you have the right to give
+away copies of the programs that relate to Texinfo, that you receive
+source code or else can get it if you want it, that you can change these
+programs or use pieces of them in new free programs, and that you know
+you can do these things.@refill
+
+ To make sure that everyone has such rights, we have to forbid you to
+deprive anyone else of these rights. For example, if you distribute
+copies of the Texinfo related programs, 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 tell them their rights.@refill
+
+ Also, for our own protection, we must make certain that everyone finds
+out that there is no warranty for the programs that relate to Texinfo.
+If these programs are modified by someone else and passed on, we want
+their recipients to know that what they have is not what we distributed,
+so that any problems introduced by others will not reflect on our
+reputation.@refill
+
+ The precise conditions of the licenses for the programs currently
+being distributed that relate to Texinfo are found in the General Public
+Licenses that accompany them.@refill
+
+@node Overview, Texinfo Mode, Copying, Top
+@comment node-name, next, previous, up
+@chapter Overview of Texinfo
+@cindex Overview of Texinfo
+@cindex Texinfo overview
+
+@dfn{Texinfo}@footnote{Note that the first syllable of ``Texinfo'' is
+pronounced like ``speck'', not ``hex''. This odd pronunciation is
+derived from, but is not the same as, the pronunciation of @TeX{}. In
+the word @TeX{}, the @samp{X} is actually the Greek letter ``chi''
+rather than the English letter ``ex''. Pronounce @TeX{} as if the
+@samp{X} were the last sound in the name `Bach'; but pronounce Texinfo
+as if the @samp{x} were a `k'. Spell ``Texinfo'' with a capital ``T''
+and write the other letters in lower case.}
+is a documentation system that uses a single source file to produce both
+on-line information and printed output. This means that instead of
+writing two different documents, one for the on-line help or other on-line
+information and the other for a typeset manual or other printed work, you
+need write only one document. When the work is revised, you need revise
+only one document. (You can read the on-line information, known as an
+@dfn{Info file}, with an Info documentation-reading program.)@refill
+
+@menu
+* Using Texinfo:: Create a conventional printed book
+ or an Info file.
+* Info Files:: What is an Info file?
+* Printed Books:: Characteristics of a printed book or manual.
+* Formatting Commands:: @@-commands are used for formatting.
+* Conventions:: General rules for writing a Texinfo file.
+* Comments:: How to write comments and mark regions that
+ the formatting commands will ignore.
+* Minimum:: What a Texinfo file must have.
+* Six Parts:: Usually, a Texinfo file has six parts.
+* Short Sample:: A short sample Texinfo file.
+* Acknowledgements::
+@end menu
+
+@node Using Texinfo, Info Files, Overview, Overview
+@ifinfo
+@heading Using Texinfo
+@end ifinfo
+
+Using Texinfo, you can create a printed document with the normal
+features of a book, including chapters, sections, cross references,
+and indices. From the same Texinfo source file, you can create a
+menu-driven, on-line Info file with nodes, menus, cross references,
+and indices. You can, if you wish, make the chapters and sections of
+the printed document correspond to the nodes of the on-line
+information; and you use the same cross references and indices for
+both the Info file and the printed work. @cite{The GNU
+Emacs Manual} is a good example of a Texinfo file, as is this manual.@refill
+
+To make a printed document, you process a Texinfo source file with the
+@TeX{} typesetting program. This creates a @sc{dvi} file that you can
+typeset and print as a book or report. (Note that the Texinfo language
+is completely different from @TeX{}'s usual language, plain @TeX{}.) If
+you do not have @TeX{}, but do have @code{troff} or @code{nroff}, you
+can use the @code{texi2roff} program instead.@refill
+
+To make an Info file, you process a Texinfo source file with the
+@code{makeinfo} utility or Emacs's @code{texinfo-format-buffer} command;
+this creates an Info file that you can install on-line.@refill
+
+@TeX{} and @code{texi2roff} work with many types of printer; similarly,
+Info works with almost every type of computer terminal. This power
+makes Texinfo a general purpose system, but brings with it a constraint,
+which is that a Texinfo file may contain only the customary
+``typewriter'' characters (letters, numbers, spaces, and punctuation
+marks) but no special graphics.@refill
+
+A Texinfo file is a plain @sc{ascii} file containing text and
+@dfn{@@-commands} (words preceded by an @samp{@@}) that tell the
+typesetting and formatting programs what to do. You may edit a
+Texinfo file with any text editor; but it is especially convenient to
+use GNU Emacs since that editor has a special mode, called Texinfo
+mode, that provides various Texinfo-related features. (@xref{Texinfo
+Mode}.)@refill
+
+Before writing a Texinfo source file, you should become familiar with
+the Info documentation reading program and learn about nodes,
+menus, cross references, and the rest. (@inforef{Top, info, info},
+for more information.)@refill
+
+You can use Texinfo to create both on-line help and printed manuals;
+moreover, Texinfo is freely redistributable. For these reasons, Texinfo
+is the format in which documentation for GNU utilities and libraries is
+written.@refill
+
+@node Info Files, Printed Books, Using Texinfo, Overview
+@comment node-name, next, previous, up
+@section Info files
+@cindex Info files
+
+An Info file is a Texinfo file formatted so that the Info documentation
+reading program can operate on it. (@code{makeinfo}
+and @code{texinfo-format-buffer} are two commands that convert a Texinfo file
+into an Info file.)@refill
+
+Info files are divided into pieces called @dfn{nodes}, each of which
+contains the discussion of one topic. Each node has a name, and
+contains both text for the user to read and pointers to other nodes,
+which are identified by their names. The Info program displays one node
+at a time, and provides commands with which the user can move to other
+related nodes.@refill
+
+@ifinfo
+@inforef{Top, info, info}, for more information about using Info.@refill
+@end ifinfo
+
+Each node of an Info file may have any number of child nodes that
+describe subtopics of the node's topic. The names of child
+nodes are listed in a @dfn{menu} within the parent node; this
+allows you to use certain Info commands to move to one of the child
+nodes. Generally, an Info file is organized like a book. If a node
+is at the logical level of a chapter, its child nodes are at the level
+of sections; likewise, the child nodes of sections are at the level
+of subsections.@refill
+
+All the children of any one parent are linked together in a
+bidirectional chain of `Next' and `Previous' pointers. The `Next'
+pointer provides a link to the next section, and the `Previous' pointer
+provides a link to the previous section. This means that all the nodes
+that are at the level of sections within a chapter are linked together.
+Normally the order in this chain is the same as the order of the
+children in the parent's menu. Each child node records the parent node
+name as its `Up' pointer. The last child has no `Next' pointer, and the
+first child has the parent both as its `Previous' and as its `Up'
+pointer.@footnote{In some documents, the first child has no `Previous'
+pointer. Occasionally, the last child has the node name of the next
+following higher level node as its `Next' pointer.}@refill
+
+The book-like structuring of an Info file into nodes that correspond
+to chapters, sections, and the like is a matter of convention, not a
+requirement. The `Up', `Previous', and `Next' pointers of a node can
+point to any other nodes, and a menu can contain any other nodes.
+Thus, the node structure can be any directed graph. But it is usually
+more comprehensible to follow a structure that corresponds to the
+structure of chapters and sections in a printed book or report.@refill
+
+In addition to menus and to `Next', `Previous', and `Up' pointers, Info
+provides pointers of another kind, called references, that can be
+sprinkled throughout the text. This is usually the best way to
+represent links that do not fit a hierarchical structure.@refill
+
+Usually, you will design a document so that its nodes match the
+structure of chapters and sections in the printed output. But there
+are times when this is not right for the material being discussed.
+Therefore, Texinfo uses separate commands to specify the node
+structure for the Info file and the section structure for the printed
+output.@refill
+
+Generally, you enter an Info file through a node that by convention is
+called @samp{Top}. This node normally contains just a brief summary
+of the file's purpose, and a large menu through which the rest of the
+file is reached. From this node, you can either traverse the file
+systematically by going from node to node, or you can go to a specific
+node listed in the main menu, or you can search the index menus and
+then go directly to the node that has the information you want.@refill
+@c !!! With the standalone Info system you may go to specific nodes
+@c directly..
+
+If you want to read through an Info file in sequence, as if it were a
+printed manual, you can get the whole file with the advanced Info
+command @kbd{g* @key{RET}}. (@inforef{Expert, Advanced Info commands,
+info}.)@refill
+
+@c !!! dir file may be located in one of many places:
+@c /usr/local/emacs/info mentioned in info.c DEFAULT_INFOPATH
+@c /usr/local/lib/emacs/info mentioned in info.c DEFAULT_INFOPATH
+@c /usr/gnu/info mentioned in info.c DEFAULT_INFOPATH
+@c /usr/local/info
+@c /usr/local/lib/info
+The @file{dir} file in the @file{info} directory serves as the
+departure point for the whole Info system. From it, you can reach the
+`Top' nodes of each of the documents in a complete Info system.@refill
+
+@node Printed Books, Formatting Commands, Info Files, Overview
+@comment node-name, next, previous, up
+@section Printed Books
+@cindex Printed book and manual characteristics
+@cindex Manual characteristics, printed
+@cindex Book characteristics, printed
+@cindex Texinfo printed book characteristics
+@cindex Characteristics, printed books or manuals
+
+@cindex Knuth, Donald
+A Texinfo file can be formatted and typeset as a printed book or manual.
+To do this, you need @TeX{}, a powerful, sophisticated typesetting
+program written by Donald Knuth.@footnote{You can also use the
+@code{texi2roff} program if you do not have @TeX{}; since Texinfo is
+designed for use with @TeX{}, @code{texi2roff} is not described here.
+@code{texi2roff} is part of the standard GNU distribution.}@refill
+
+A Texinfo-based book is similar to any other typeset, printed work: it
+can have a title page, copyright page, table of contents, and preface,
+as well as chapters, numbered or unnumbered sections and subsections,
+page headers, cross references, footnotes, and indices.@refill
+
+You can use Texinfo to write a book without ever having the intention
+of converting it into on-line information. You can use Texinfo for
+writing a printed novel, and even to write a printed memo, although
+this latter application is not recommended since electronic mail is so
+much easier.@refill
+
+@TeX{} is a general purpose typesetting program. Texinfo provides a
+file called @file{texinfo.tex} that contains information (definitions or
+@dfn{macros}) that @TeX{} uses when it typesets a Texinfo file.
+(@file{texinfo.tex} tells @TeX{} how to convert the Texinfo @@-commands
+to @TeX{} commands, which @TeX{} can then process to create the typeset
+document.) @file{texinfo.tex} contains the specifications for printing
+a document.@refill
+
+Most often, documents are printed on 8.5 inch by 11 inch
+pages (216@dmn{mm} by 280@dmn{mm}; this is the default size), but you
+can also print for 7 inch by 9.25 inch pages (178@dmn{mm} by
+235@dmn{mm}; the @code{@@smallbook} size) or on European A4 size paper
+(@code{@@afourpaper}). (@xref{smallbook, , Printing ``Small'' Books}.
+Also, see @ref{A4 Paper, ,Printing on A4 Paper}.)@refill
+
+By changing the parameters in @file{texinfo.tex}, you can change the
+size of the printed document. In addition, you can change the style in
+which the printed document is formatted; for example, you can change the
+sizes and fonts used, the amount of indentation for each paragraph, the
+degree to which words are hyphenated, and the like. By changing the
+specifications, you can make a book look dignified, old and serious, or
+light-hearted, young and cheery.@refill
+
+@TeX{} is freely distributable. It is written in a dialect of Pascal
+called WEB and can be compiled either in Pascal or (by using a
+conversion program that comes with the @TeX{} distribution) in C.
+(@xref{TeX Mode, ,@TeX{} Mode, emacs, The GNU Emacs Manual}, for information
+about @TeX{}.)@refill
+
+@TeX{} is very powerful and has a great many features. Because a
+Texinfo file must be able to present information both on a
+character-only terminal in Info form and in a typeset book, the
+formatting commands that Texinfo supports are necessarily
+limited.@refill
+
+@xref{Obtaining TeX, , How to Obtain @TeX{}}.
+
+
+@node Formatting Commands, Conventions, Printed Books, Overview
+@comment node-name, next, previous, up
+@section @@-commands
+@cindex @@-commands
+@cindex Formatting commands
+
+In a Texinfo file, the commands that tell @TeX{} how to typeset the
+printed manual and tell @code{makeinfo} and
+@code{texinfo-format-buffer} how to create an Info file are preceded
+by @samp{@@}; they are called @dfn{@@-commands}. For example,
+@code{@@node} is the command to indicate a node and @code{@@chapter}
+is the command to indicate the start of a chapter.@refill
+
+@quotation
+@strong{Please note:} All the @@-commands, with the exception of the
+@code{@@TeX@{@}} command, must be written entirely in lower
+case.@refill
+@end quotation
+
+The Texinfo @@-commands are a strictly limited set of constructs. The
+strict limits make it possible for Texinfo files to be understood both
+by @TeX{} and by the code that converts them into Info files. You can
+display Info files on any terminal that displays alphabetic and
+numeric characters. Similarly, you can print the output generated by
+@TeX{} on a wide variety of printers.@refill
+
+Depending on what they do or what arguments@footnote{The word
+@dfn{argument} comes from the way it is used in mathematics and does
+not refer to a disputation between two people; it refers to the
+information presented to the command. According to the @cite{Oxford
+English Dictionary}, the word derives from the Latin for @dfn{to make
+clear, prove}; thus it came to mean `the evidence offered as proof',
+which is to say, `the information offered', which led to its
+mathematical meaning. In its other thread of derivation, the word
+came to mean `to assert in a manner against which others may make
+counter assertions', which led to the meaning of `argument' as a
+disputation.} they take, you need to write @@-commands on lines of
+their own or as part of sentences:@refill
+
+@itemize @bullet
+@item
+Write a command such as @code{@@noindent} at the beginning of a line as
+the only text on the line. (@code{@@noindent} prevents the beginning of
+the next line from being indented as the beginning of a
+paragraph.)@refill
+
+@item
+Write a command such as @code{@@chapter} at the beginning of a line
+followed by the command's arguments, in this case the chapter title, on
+the rest of the line. (@code{@@chapter} creates chapter titles.)@refill
+
+@item
+Write a command such as @code{@@dots@{@}} wherever you wish but usually
+within a sentence. (@code{@@dots@{@}} creates dots @dots{})@refill
+
+@item
+Write a command such as @code{@@code@{@var{sample-code}@}} wherever you
+wish (but usually within a sentence) with its argument,
+@var{sample-code} in this example, between the braces. (@code{@@code}
+marks text as being code.)@refill
+
+@item
+Write a command such as @code{@@example} at the beginning of a line of
+its own; write the body-text on following lines; and write the matching
+@code{@@end} command, @code{@@end example} in this case, at the
+beginning of a line of its own after the body-text. (@code{@@example}
+@dots{} @code{@@end example} indents and typesets body-text as an
+example.)@refill
+@end itemize
+
+@noindent
+@cindex Braces, when to use
+As a general rule, a command requires braces if it mingles among other
+text; but it does not need braces if it starts a line of its own. The
+non-alphabetic commands, such as @code{@@:}, are exceptions to the rule;
+they do not need braces.@refill
+
+As you gain experience with Texinfo, you will rapidly learn how to
+write the different commands: the different ways to write commands
+make it easier to write and read Texinfo files than if all commands
+followed exactly the same syntax. (For details about @@-command
+syntax, see @ref{Command Syntax, , @@-Command Syntax}.)@refill
+
+@node Conventions, Comments, Formatting Commands, Overview
+@comment node-name, next, previous, up
+@section General Syntactic Conventions
+@cindex General syntactic conventions
+@cindex Syntactic conventions
+@cindex Conventions, syntactic
+
+All printable @sc{ascii} characters except @samp{@@}, @samp{@{} and
+@samp{@}} can appear in a Texinfo file and stand for themselves.
+@samp{@@} is the escape character which introduces commands.
+@samp{@{} and @samp{@}} should be used only to surround arguments to
+certain commands. To put one of these special characters into the
+document, put an @samp{@@} character in front of it, like this:
+@samp{@@@@}, @samp{@@@{}, and @samp{@@@}}.@refill
+
+@ifinfo
+It is customary in @TeX{} to use doubled single-quote characters to
+begin and end quotations: ` ` and ' ' (but without a space between the
+two single-quote characters). This convention should be followed in
+Texinfo files. @TeX{} converts doubled single-quote characters to
+left- and right-hand doubled quotation marks and Info converts doubled
+single-quote characters to @sc{ascii} double-quotes: ` ` and ' ' to " .@refill
+@end ifinfo
+@iftex
+It is customary in @TeX{} to use doubled single-quote characters to
+begin and end quotations: @w{@tt{ `` }} and @w{@tt{ '' }}. This
+convention should be followed in Texinfo files. @TeX{} converts
+doubled single-quote characters to left- and right-hand doubled
+quotation marks, ``like this'', and Info converts doubled single-quote
+characters to @sc{ascii} double-quotes: @w{@tt{ `` }} and
+@w{@tt{ '' }} to @w{@tt{ " }}.@refill
+@end iftex
+
+Use three hyphens in a row, @samp{---}, for a dash---like this. In
+@TeX{}, a single or even a double hyphen produces a printed dash that
+is shorter than the usual typeset dash. Info reduces three hyphens to two for
+display on the screen.@refill
+
+To prevent a paragraph from being indented in the printed manual, put
+the command @code{@@noindent} on a line by itself before the
+paragraph.@refill
+
+If you mark off a region of the Texinfo file with the @code{@@iftex}
+and @w{@code{@@end iftex}} commands, that region will appear only in
+the printed copy; in that region, you can use certain commands
+borrowed from plain @TeX{} that you cannot use in Info. Likewise, if
+you mark off a region with the @code{@@ifinfo} and @code{@@end ifinfo}
+commands, that region will appear only in the Info file; in that
+region, you can use Info commands that you cannot use in @TeX{}.
+Similarly for @code{@@ifhtml} and @code{@@end ifhtml}.
+@xref{Conditionals}.
+
+@cindex Tabs; don't use!
+@quotation
+@strong{Caution:} Do not use tabs in a Texinfo file! @TeX{} uses
+variable-width fonts, which means that it cannot predefine a tab to work
+in all circumstances. Consequently, @TeX{} treats tabs like single
+spaces, and that is not what they look like.@refill
+
+@noindent
+To avoid this problem, Texinfo mode causes GNU Emacs to insert multiple
+spaces when you press the @key{TAB} key.@refill
+
+@noindent
+Also, you can run @code{untabify} in Emacs to convert tabs in a region
+to multiple spaces.@refill
+@end quotation
+
+@node Comments, Minimum, Conventions, Overview
+@comment node-name, next, previous, up
+@section Comments
+
+You can write comments in a Texinfo file that will not appear in
+either the Info file or the printed manual by using the
+@code{@@comment} command (which may be abbreviated to @code{@@c}).
+Such comments are for the person who reads the Texinfo file. All the
+text on a line that follows either @code{@@comment} or @code{@@c} is a
+comment; the rest of the line does not appear in either the Info file
+or the printed manual. (Often, you can write the @code{@@comment} or
+@code{@@c} in the middle of a line, and only the text that follows after
+the @code{@@comment} or @code{@@c} command does not appear; but some
+commands, such as @code{@@settitle} and @code{@@setfilename}, work on a
+whole line. You cannot use @code{@@comment} or @code{@@c} in a line
+beginning with such a command.)@refill
+@cindex Comments
+@findex comment
+@findex c @r{(comment)}
+
+You can write long stretches of text that will not appear in either
+the Info file or the printed manual by using the @code{@@ignore} and
+@code{@@end ignore} commands. Write each of these commands on a line
+of its own, starting each command at the beginning of the line. Text
+between these two commands does not appear in the processed output.
+You can use @code{@@ignore} and @code{@@end ignore} for writing
+comments. Often, @code{@@ignore} and @code{@@end ignore} is used
+to enclose a part of the copying permissions that applies to the
+Texinfo source file of a document, but not to the Info or printed
+version of the document.@refill
+@cindex Ignored text
+@cindex Unprocessed text
+@findex ignore
+@c !!! Perhaps include this comment about ignore and ifset:
+@ignore
+Text enclosed by @code{@@ignore} or by failing @code{@@ifset} or
+@code{@@ifclear} conditions is ignored in the sense that it will not
+contribute to the formatted output. However, TeX and makeinfo must
+still parse the ignored text, in order to understand when to
+@emph{stop} ignoring text from the source file; that means that you
+will still get error messages if you have invalid Texinfo markup
+within ignored text.
+@end ignore
+
+@node Minimum, Six Parts, Comments, Overview
+@comment node-name, next, previous, up
+@section What a Texinfo File Must Have
+@cindex Minimal Texinfo file (requirements)
+@cindex Must have in Texinfo file
+@cindex Required in Texinfo file
+@cindex Texinfo file minimum
+
+By convention, the names of Texinfo files end with one of the
+extensions @file{.texinfo}, @file{.texi}, or @file{.tex}. The longer
+extension is preferred since it describes more clearly to a human
+reader the nature of the file. The shorter extensions are for
+operating systems that cannot handle long file names.@refill
+
+In order to be made into a printed manual and an Info file, a Texinfo
+file @strong{must} begin with lines like this:@refill
+
+@example
+@group
+\input texinfo
+@@setfilename @var{info-file-name}
+@@settitle @var{name-of-manual}
+@end group
+@end example
+
+@noindent
+The contents of the file follow this beginning, and then you @strong{must} end
+a Texinfo file with a line like this:@refill
+
+@example
+@@bye
+@end example
+
+@findex input @r{(@TeX{} command)}
+@noindent
+The @samp{\input texinfo} line tells @TeX{} to use the
+@file{texinfo.tex} file, which tells @TeX{} how to translate the Texinfo
+@@-commands into @TeX{} typesetting commands. (Note the use of the
+backslash, @samp{\}; this is correct for @TeX{}.) The
+@samp{@@setfilename} line provides a name for the Info file and tells
+@TeX{} to open auxiliary files. The @samp{@@settitle} line specifies a
+title for the page headers (or footers) of the printed manual.@refill
+
+The @code{@@bye} line at the end of the file on a line of its own tells
+the formatters that the file is ended and to stop formatting.@refill
+
+Usually, you will not use quite such a spare format, but will include
+mode setting and start-of-header and end-of-header lines at the
+beginning of a Texinfo file, like this:@refill
+
+@example
+@group
+\input texinfo @@c -*-texinfo-*-
+@@c %**start of header
+@@setfilename @var{info-file-name}
+@@settitle @var{name-of-manual}
+@@c %**end of header
+@end group
+@end example
+
+@noindent
+In the first line, @samp{-*-texinfo-*-} causes Emacs to switch into
+Texinfo mode when you edit the file.
+
+The @code{@@c} lines which surround the @samp{@@setfilename} and
+@samp{@@settitle} lines are optional, but you need them in order to
+run @TeX{} or Info on just part of the file. (@xref{Start of Header},
+for more information.)@refill
+
+Furthermore, you will usually provide a Texinfo file with a title
+page, indices, and the like. But the minimum, which can be useful
+for short documents, is just the three lines at the beginning and the
+one line at the end.@refill
+
+@node Six Parts, Short Sample, Minimum, Overview
+@comment node-name, next, previous, up
+@section Six Parts of a Texinfo File
+
+Generally, a Texinfo file contains more than the minimal
+beginning and end---it usually contains six parts:@refill
+
+@table @r
+@item 1. Header
+The @dfn{Header} names the file, tells @TeX{} which definitions' file to
+use, and performs other ``housekeeping'' tasks.@refill
+
+@item 2. Summary Description and Copyright
+The @dfn{Summary Description and Copyright} segment describes the document
+and contains the copyright notice and copying permissions for the Info
+file. The segment must be enclosed between @code{@@ifinfo} and
+@code{@@end ifinfo} commands so that the formatters place it only in the Info
+file.@refill
+
+@item 3. Title and Copyright
+The @dfn{Title and Copyright} segment contains the title and copyright pages
+and copying permissions for the printed manual. The segment must be
+enclosed between @code{@@titlepage} and @code{@@end titlepage} commands.
+The title and copyright page appear only in the printed @w{manual}.@refill
+
+@item 4. `Top' Node and Master Menu
+The @dfn{Master Menu} contains a complete menu of all the nodes in the whole
+Info file. It appears only in the Info file, in the `Top' node.@refill
+
+@item 5. Body
+The @dfn{Body} of the document may be structured like a traditional book or
+encyclopedia or it may be free form.@refill
+
+@item 6. End
+The @dfn{End} contains commands for printing indices and generating
+the table of contents, and the @code{@@bye} command on a line of its
+own.@refill
+@end table
+
+@node Short Sample, Acknowledgements, Six Parts, Overview
+@comment node-name, next, previous, up
+@section A Short Sample Texinfo File
+@cindex Sample Texinfo file
+
+Here is a complete but very short Texinfo file, in 6 parts. The first
+three parts of the file, from @samp{\input texinfo} through to
+@samp{@@end titlepage}, look more intimidating than they are. Most of
+the material is standard boilerplate; when you write a manual, simply
+insert the names for your own manual in this segment. (@xref{Beginning a
+File}.)@refill
+
+@noindent
+In the following, the sample text is @emph{indented}; comments on it are
+not. The complete file, without any comments, is shown in
+@ref{Sample Texinfo File}.
+
+@subheading Part 1: Header
+
+@noindent
+The header does not appear in either the Info file or the@*
+printed output. It sets various parameters, including the@*
+name of the Info file and the title used in the header.
+
+@example
+@group
+\input texinfo @@c -*-texinfo-*-
+@@c %**start of header
+@@setfilename sample.info
+@@settitle Sample Document
+@@c %**end of header
+
+@@setchapternewpage odd
+@end group
+@end example
+
+@subheading Part 2: Summary Description and Copyright
+
+@noindent
+The summary description and copyright segment does not@*
+appear in the printed document.
+
+@example
+@group
+@@ifinfo
+This is a short example of a complete Texinfo file.
+
+Copyright @@copyright@{@} 1990 Free Software Foundation, Inc.
+@@end ifinfo
+@end group
+@end example
+
+@subheading Part 3: Titlepage and Copyright
+
+@noindent
+The titlepage segment does not appear in the Info file.
+
+@example
+@group
+@@titlepage
+@@sp 10
+@@comment The title is printed in a large font.
+@@center @@titlefont@{Sample Title@}
+@end group
+
+@group
+@@c The following two commands start the copyright page.
+@@page
+@@vskip 0pt plus 1filll
+Copyright @@copyright@{@} 1990 Free Software Foundation, Inc.
+@@end titlepage
+@end group
+@end example
+
+@subheading Part 4: `Top' Node and Master Menu
+
+@noindent
+The `Top' node contains the master menu for the Info file.@*
+Since a printed manual uses a table of contents rather than@*
+a menu, the master menu appears only in the Info file.
+
+@example
+@group
+@@node Top, First Chapter, (dir), (dir)
+@@comment node-name, next, previous, up
+@end group
+@end example
+
+@example
+@group
+@@menu
+* First Chapter:: The first chapter is the
+ only chapter in this sample.
+* Concept Index:: This index has two entries.
+@@end menu
+@end group
+@end example
+
+@subheading Part 5: The Body of the Document
+
+@noindent
+The body segment contains all the text of the document, but not the
+indices or table of contents. This example illustrates a node and a
+chapter containing an enumerated list.@refill
+
+@example
+@group
+@@node First Chapter, Concept Index, Top, Top
+@@comment node-name, next, previous, up
+@@chapter First Chapter
+@@cindex Sample index entry
+@end group
+
+@group
+This is the contents of the first chapter.
+@@cindex Another sample index entry
+@end group
+
+@group
+Here is a numbered list.
+
+@@enumerate
+@@item
+This is the first item.
+
+@@item
+This is the second item.
+@@end enumerate
+@end group
+
+@group
+The @@code@{makeinfo@} and @@code@{texinfo-format-buffer@}
+commands transform a Texinfo file such as this into
+an Info file; and @@TeX@{@} typesets it for a printed
+manual.
+@end group
+@end example
+
+@subheading Part 6: The End of the Document
+
+@noindent
+The end segment contains commands both for generating an index in a node
+and unnumbered chapter of its own and for generating the table of
+contents; and it contains the @code{@@bye} command that marks the end of
+the document.@refill
+
+@example
+@group
+@@node Concept Index, , First Chapter, Top
+@@comment node-name, next, previous, up
+@@unnumbered Concept Index
+@end group
+
+@group
+@@printindex cp
+
+@@contents
+@@bye
+@end group
+@end example
+
+@subheading The Results
+
+Here is what the contents of the first chapter of the sample look like:
+
+@sp 1
+@need 700
+@quotation
+This is the contents of the first chapter.
+
+Here is a numbered list.
+
+@enumerate
+@item
+This is the first item.
+
+@item
+This is the second item.
+@end enumerate
+
+The @code{makeinfo} and @code{texinfo-format-buffer}
+commands transform a Texinfo file such as this into
+an Info file; and @TeX{} typesets it for a printed
+manual.
+@end quotation
+
+@node Acknowledgements, , Short Sample, Overview
+@comment node-name, next, previous, up
+@section Acknowledgements
+
+@cindex Stallman, Richard M.
+@cindex Chassell, Robert J.
+@cindex Berry, Karl
+Richard M.@: Stallman wrote Edition 1.0 of this manual. @w{Robert J.@:
+Chassell} revised and extended it, starting with Edition 1.1. Karl
+Berry made updates for the Texinfo 3.8 and subsequent releases, starting
+with Edition 2.22.
+
+@cindex Pinard, Fran@,{c}ois
+@cindex Zuhn, David D.
+@cindex Weisshaus, Melissa
+Our thanks go out to all who helped improve this work, particularly to
+Fran@,{c}ois Pinard and @w{David D.@: Zuhn}, who tirelessly recorded and
+reported mistakes and obscurities; our special thanks go to Melissa
+Weisshaus for her frequent and often tedious reviews of nearly similar
+editions. Our mistakes are our own.
+
+Please send suggestions and corrections to:
+
+@example
+@group
+@r{Internet address:}
+ bug-texinfo@@prep.ai.mit.edu
+@end group
+@end example
+
+@noindent
+Please include the manual's edition number and update date in your messages.
+
+@node Texinfo Mode, Beginning a File, Overview, Top
+@comment node-name, next, previous, up
+@chapter Using Texinfo Mode
+@cindex Texinfo mode
+@cindex Mode, using Texinfo
+@cindex GNU Emacs
+@cindex Emacs
+
+You may edit a Texinfo file with any text editor you choose. A Texinfo
+file is no different from any other @sc{ascii} file. However, GNU Emacs
+comes with a special mode, called Texinfo
+mode, that provides Emacs commands and tools to help ease your work.@refill
+
+This chapter describes features of GNU Emacs' Texinfo mode but not any
+features of the Texinfo formatting language. If you are reading this
+manual straight through from the beginning, you may want to skim through
+this chapter briefly and come back to it after reading succeeding
+chapters which describe the Texinfo formatting language in
+detail.@refill
+
+@menu
+* Texinfo Mode Overview:: How Texinfo mode can help you.
+* Emacs Editing:: Texinfo mode adds to GNU Emacs' general
+ purpose editing features.
+* Inserting:: How to insert frequently used @@-commands.
+* Showing the Structure:: How to show the structure of a file.
+* Updating Nodes and Menus:: How to update or create new nodes and menus.
+* Info Formatting:: How to format for Info.
+* Printing:: How to format and print part or all of a file.
+* Texinfo Mode Summary:: Summary of all the Texinfo mode commands.
+@end menu
+
+@node Texinfo Mode Overview, Emacs Editing, Texinfo Mode, Texinfo Mode
+@ifinfo
+@heading Texinfo Mode Overview
+@end ifinfo
+
+Texinfo mode provides special features for working with Texinfo
+files:@refill
+
+@itemize @bullet
+@item
+Insert frequently used @@-commands. @refill
+
+@item
+Automatically create @code{@@node} lines.
+
+@item
+Show the structure of a Texinfo source file.@refill
+
+@item
+Automatically create or update the `Next',@*
+`Previous', and `Up' pointers of a node.
+
+@item
+Automatically create or update menus.@refill
+
+@item
+Automatically create a master menu.@refill
+
+@item
+Format a part or all of a file for Info.@refill
+
+@item
+Typeset and print part or all of a file.@refill
+@end itemize
+
+Perhaps the two most helpful features are those for inserting frequently
+used @@-commands and for creating node pointers and menus.@refill
+
+@node Emacs Editing, Inserting, Texinfo Mode Overview, Texinfo Mode
+@section The Usual GNU Emacs Editing Commands
+
+In most cases, the usual Text mode commands work the same in Texinfo
+mode as they do in Text mode. Texinfo mode adds new editing commands
+and tools to GNU Emacs' general purpose editing features. The major
+difference concerns filling. In Texinfo mode, the paragraph
+separation variable and syntax table are redefined so that Texinfo
+commands that should be on lines of their own are not inadvertently
+included in paragraphs. Thus, the @kbd{M-q} (@code{fill-paragraph})
+command will refill a paragraph but not mix an indexing command on a
+line adjacent to it into the paragraph.@refill
+
+In addition, Texinfo mode sets the @code{page-delimiter} variable to
+the value of @code{texinfo-chapter-level-regexp}; by default, this is
+a regular expression matching the commands for chapters and their
+equivalents, such as appendices. With this value for the page
+delimiter, you can jump from chapter title to chapter title with the
+@kbd{C-x ]} (@code{forward-page}) and @kbd{C-x [}
+(@code{backward-page}) commands and narrow to a chapter with the
+@kbd{C-x p} (@code{narrow-to-page}) command. (@xref{Pages, , ,emacs,
+The GNU Emacs Manual}, for details about the page commands.)@refill
+
+You may name a Texinfo file however you wish, but the convention is to
+end a Texinfo file name with one of the three extensions
+@file{.texinfo}, @file{.texi}, or @file{.tex}. A longer extension is
+preferred, since it is explicit, but a shorter extension may be
+necessary for operating systems that limit the length of file names.
+GNU Emacs automatically enters Texinfo mode when you visit a file with
+a @file{.texinfo} or @file{.texi}
+extension. Also, Emacs switches to Texinfo mode
+when you visit a
+file that has @samp{-*-texinfo-*-} in its first line. If ever you are
+in another mode and wish to switch to Texinfo mode, type @code{M-x
+texinfo-mode}.@refill
+
+Like all other Emacs features, you can customize or enhance Texinfo
+mode as you wish. In particular, the keybindings are very easy to
+change. The keybindings described here are the default or standard
+ones.@refill
+
+@node Inserting, Showing the Structure, Emacs Editing, Texinfo Mode
+@comment node-name, next, previous, up
+@section Inserting Frequently Used Commands
+@cindex Inserting frequently used commands
+@cindex Frequently used commands, inserting
+@cindex Commands, inserting them
+
+Texinfo mode provides commands to insert various frequently used
+@@-commands into the buffer. You can use these commands to save
+keystrokes.@refill
+
+The insert commands are invoked by typing @kbd{C-c} twice and then the
+first letter of the @@-command:@refill
+
+@table @kbd
+@item C-c C-c c
+@itemx M-x texinfo-insert-@@code
+@findex texinfo-insert-@@code
+Insert @code{@@code@{@}} and put the
+cursor between the braces.@refill
+
+@item C-c C-c d
+@itemx M-x texinfo-insert-@@dfn
+@findex texinfo-insert-@@dfn
+Insert @code{@@dfn@{@}} and put the
+cursor between the braces.@refill
+
+@item C-c C-c e
+@itemx M-x texinfo-insert-@@end
+@findex texinfo-insert-@@end
+Insert @code{@@end} and attempt to insert the correct following word,
+such as @samp{example} or @samp{table}. (This command does not handle
+nested lists correctly, but inserts the word appropriate to the
+immediately preceding list.)@refill
+
+@item C-c C-c i
+@itemx M-x texinfo-insert-@@item
+@findex texinfo-insert-@@item
+Insert @code{@@item} and put the
+cursor at the beginning of the next line.@refill
+
+@item C-c C-c k
+@itemx M-x texinfo-insert-@@kbd
+@findex texinfo-insert-@@kbd
+Insert @code{@@kbd@{@}} and put the
+cursor between the braces.@refill
+
+@item C-c C-c n
+@itemx M-x texinfo-insert-@@node
+@findex texinfo-insert-@@node
+Insert @code{@@node} and a comment line
+listing the sequence for the `Next',
+`Previous', and `Up' nodes.
+Leave point after the @code{@@node}.@refill
+
+@item C-c C-c o
+@itemx M-x texinfo-insert-@@noindent
+@findex texinfo-insert-@@noindent
+Insert @code{@@noindent} and put the
+cursor at the beginning of the next line.@refill
+
+@item C-c C-c s
+@itemx M-x texinfo-insert-@@samp
+@findex texinfo-insert-@@samp
+Insert @code{@@samp@{@}} and put the
+cursor between the braces.@refill
+
+@item C-c C-c t
+@itemx M-x texinfo-insert-@@table
+@findex texinfo-insert-@@table
+Insert @code{@@table} followed by a @key{SPC}
+and leave the cursor after the @key{SPC}.@refill
+
+@item C-c C-c v
+@itemx M-x texinfo-insert-@@var
+@findex texinfo-insert-@@var
+Insert @code{@@var@{@}} and put the
+cursor between the braces.@refill
+
+@item C-c C-c x
+@itemx M-x texinfo-insert-@@example
+@findex texinfo-insert-@@example
+Insert @code{@@example} and put the
+cursor at the beginning of the next line.@refill
+
+@c M-@{ was the binding for texinfo-insert-braces;
+@c in Emacs 19, backward-paragraph will take this binding.
+@item C-c C-c @{
+@itemx M-x texinfo-insert-braces
+@findex texinfo-insert-braces
+Insert @code{@{@}} and put the cursor between the braces.@refill
+
+@item C-c C-c @}
+@itemx C-c C-c ]
+@itemx M-x up-list
+@findex up-list
+Move from between a pair of braces forward past the closing brace.
+Typing @kbd{C-c C-c ]} is easier than typing @kbd{C-c C-c @}}, which
+is, however, more mnemonic; hence the two keybindings. (Also, you can
+move out from between braces by typing @kbd{C-f}.)@refill
+@end table
+
+To put a command such as @w{@code{@@code@{@dots{}@}}} around an
+@emph{existing} word, position the cursor in front of the word and type
+@kbd{C-u 1 C-c C-c c}. This makes it easy to edit existing plain text.
+The value of the prefix argument tells Emacs how many words following
+point to include between braces---1 for one word, 2 for two words, and
+so on. Use a negative argument to enclose the previous word or words.
+If you do not specify a prefix argument, Emacs inserts the @@-command
+string and positions the cursor between the braces. This feature works
+only for those @@-commands that operate on a word or words within one
+line, such as @code{@@kbd} and @code{@@var}.@refill
+
+This set of insert commands was created after analyzing the frequency
+with which different @@-commands are used in the @cite{GNU Emacs
+Manual} and the @cite{GDB Manual}. If you wish to add your own insert
+commands, you can bind a keyboard macro to a key, use abbreviations,
+or extend the code in @file{texinfo.el}.@refill
+
+@findex texinfo-start-menu-description
+@cindex Menu description, start
+@cindex Description for menu, start
+@kbd{C-c C-c C-d} (@code{texinfo-start-menu-description}) is an insert
+command that works differently from the other insert commands. It
+inserts a node's section or chapter title in the space for the
+description in a menu entry line. (A menu entry has three parts, the
+entry name, the node name, and the description. Only the node name is
+required, but a description helps explain what the node is about.
+@xref{Menu Parts, , The Parts of a Menu}.)@refill
+
+To use @code{texinfo-start-menu-description}, position point in a menu
+entry line and type @kbd{C-c C-c C-d}. The command looks for and copies
+the title that goes with the node name, and inserts the title as a
+description; it positions point at beginning of the inserted text so you
+can edit it. The function does not insert the title if the menu entry
+line already contains a description.@refill
+
+This command is only an aid to writing descriptions; it does not do the
+whole job. You must edit the inserted text since a title tends to use
+the same words as a node name but a useful description uses different
+words.@refill
+
+@node Showing the Structure, Updating Nodes and Menus, Inserting, Texinfo Mode
+@comment node-name, next, previous, up
+@section Showing the Section Structure of a File
+@cindex Showing the section structure of a file
+@cindex Section structure of a file, showing it
+@cindex Structure of a file, showing it
+@cindex Outline of file structure, showing it
+@cindex Contents-like outline of file structure
+@cindex File section structure, showing it
+@cindex Texinfo file section structure, showing it
+
+You can show the section structure of a Texinfo file by using the
+@kbd{C-c C-s} command (@code{texinfo-show-structure}). This command
+shows the section structure of a Texinfo file by listing the lines
+that begin with the @@-commands for @code{@@chapter},
+@code{@@section}, and the like. It constructs what amounts
+to a table of contents. These lines are displayed in another buffer
+called the @samp{*Occur*} buffer. In that buffer, you can position
+the cursor over one of the lines and use the @kbd{C-c C-c} command
+(@code{occur-mode-goto-occurrence}), to jump to the corresponding spot
+in the Texinfo file.@refill
+
+@table @kbd
+@item C-c C-s
+@itemx M-x texinfo-show-structure
+@findex texinfo-show-structure
+Show the @code{@@chapter}, @code{@@section}, and such lines of a
+Texinfo file.@refill
+
+@item C-c C-c
+@itemx M-x occur-mode-goto-occurrence
+@findex occur-mode-goto-occurrence
+Go to the line in the Texinfo file corresponding to the line under the
+cursor in the @file{*Occur*} buffer.@refill
+@end table
+
+If you call @code{texinfo-show-structure} with a prefix argument by
+typing @w{@kbd{C-u C-c C-s}}, it will list not only those lines with the
+@@-commands for @code{@@chapter}, @code{@@section}, and the like,
+but also the @code{@@node} lines. (This is how the
+@code{texinfo-show-structure} command worked without an argument in
+the first version of Texinfo. It was changed because @code{@@node}
+lines clutter up the @samp{*Occur*} buffer and are usually not
+needed.) You can use @code{texinfo-show-structure} with a prefix
+argument to check whether the `Next', `Previous', and `Up' pointers of
+an @code{@@node} line are correct.@refill
+
+Often, when you are working on a manual, you will be interested only
+in the structure of the current chapter. In this case, you can mark
+off the region of the buffer that you are interested in by using the
+@kbd{C-x n n} (@code{narrow-to-region}) command and
+@code{texinfo-show-structure} will work on only that region. To see
+the whole buffer again, use @w{@kbd{C-x n w}} (@code{widen}).
+(@xref{Narrowing, , , emacs, The GNU Emacs Manual}, for more
+information about the narrowing commands.)@refill
+
+@vindex page-delimiter
+@cindex Page delimiter in Texinfo mode
+In addition to providing the @code{texinfo-show-structure} command,
+Texinfo mode sets the value of the page delimiter variable to match
+the chapter-level @@-commands. This enables you to use the @kbd{C-x
+]} (@code{forward-page}) and @kbd{C-x [} (@code{backward-page})
+commands to move forward and backward by chapter, and to use the
+@kbd{C-x p} (@code{narrow-to-page}) command to narrow to a chapter.
+@xref{Pages, , , emacs, The GNU Emacs Manual}, for more information
+about the page commands.@refill
+
+@node Updating Nodes and Menus, Info Formatting, Showing the Structure, Texinfo Mode
+@comment node-name, next, previous, up
+@section Updating Nodes and Menus
+@cindex Updating nodes and menus
+@cindex Create nodes, menus automatically
+@cindex Insert nodes, menus automatically
+@cindex Automatically insert nodes, menus
+
+Texinfo mode provides commands for automatically creating or updating
+menus and node pointers. The commands are called ``update'' commands
+because their most frequent use is for updating a Texinfo file after
+you have worked on it; but you can use them to insert the `Next',
+`Previous', and `Up' pointers into an @code{@@node} line that has none and to
+create menus in a file that has none.@refill
+
+If you do not use the updating commands, you need to write menus and
+node pointers by hand, which is a tedious task.@refill
+
+@menu
+* Updating Commands:: Five major updating commands.
+* Updating Requirements:: How to structure a Texinfo file for
+ using the updating command.
+* Other Updating Commands:: How to indent descriptions, insert
+ missing nodes lines, and update
+ nodes in sequence.
+@end menu
+
+@node Updating Commands, Updating Requirements, Updating Nodes and Menus, Updating Nodes and Menus
+@ifinfo
+@subheading The Updating Commands
+@end ifinfo
+
+You can use the updating commands@refill
+
+@itemize @bullet
+@item
+to insert or update the `Next', `Previous', and `Up' pointers of a
+node,@refill
+
+@item
+to insert or update the menu for a section, and@refill
+
+@item
+to create a master menu for a Texinfo source file.@refill
+@end itemize
+
+You can also use the commands to update all the nodes and menus in a
+region or in a whole Texinfo file.@refill
+
+The updating commands work only with conventional Texinfo files, which
+are structured hierarchically like books. In such files, a structuring
+command line must follow closely after each @code{@@node} line, except
+for the `Top' @code{@@node} line. (A @dfn{structuring command line} is
+a line beginning with @code{@@chapter}, @code{@@section}, or other
+similar command.)
+
+You can write the structuring command line on the line that follows
+immediately after an @code{@@node} line or else on the line that
+follows after a single @code{@@comment} line or a single
+@code{@@ifinfo} line. You cannot interpose more than one line between
+the @code{@@node} line and the structuring command line; and you may
+interpose only an @code{@@comment} line or an @code{@@ifinfo} line.
+
+Commands which work on a whole buffer require that the `Top' node be
+followed by a node with an @code{@@chapter} or equivalent-level command.
+Note that the menu updating commands will not create a main or master
+menu for a Texinfo file that has only @code{@@chapter}-level nodes! The
+menu updating commands only create menus @emph{within} nodes for lower level
+nodes. To create a menu of chapters, you must provide a `Top'
+node.@refill
+
+The menu updating commands remove menu entries that refer to other Info
+files since they do not refer to nodes within the current buffer. This
+is a deficiency. Rather than use menu entries, you can use cross
+references to refer to other Info files. None of the updating commands
+affect cross references.@refill
+
+Texinfo mode has five updating commands that are used most often: two
+are for updating the node pointers or menu of a single node (or a
+region); two are for updating every node pointer and menu in a file;
+and one, the @code{texinfo-master-menu} command, is for creating a
+master menu for a complete file, and optionally, for updating every
+node and menu in the whole Texinfo file.@refill
+
+The @code{texinfo-master-menu} command is the primary command:@refill
+
+@table @kbd
+@item C-c C-u m
+@itemx M-x texinfo-master-menu
+@findex texinfo-master-menu
+Create or update a master menu that includes all the other menus
+(incorporating the descriptions from pre-existing menus, if
+any).@refill
+
+With an argument (prefix argument, @kbd{C-u,} if interactive), first create or
+update all the nodes and all the regular menus in the buffer before
+constructing the master menu. (@xref{The Top Node, , The Top Node and
+Master Menu}, for more about a master menu.)@refill
+
+For @code{texinfo-master-menu} to work, the Texinfo file must have a
+`Top' node and at least one subsequent node.@refill
+
+After extensively editing a Texinfo file, you can type the following:
+
+@example
+C-u M-x texinfo-master-menu
+@exdent or
+C-u C-c C-u m
+@end example
+
+@noindent
+This updates all the nodes and menus completely and all at once.@refill
+@end table
+
+The other major updating commands do smaller jobs and are designed for
+the person who updates nodes and menus as he or she writes a Texinfo
+file.@refill
+
+@need 1000
+The commands are:@refill
+
+@table @kbd
+@item C-c C-u C-n
+@itemx M-x texinfo-update-node
+@findex texinfo-update-node
+Insert the `Next', `Previous', and `Up' pointers for the node that point is
+within (i.e., for the @code{@@node} line preceding point). If the
+@code{@@node} line has pre-existing `Next', `Previous', or `Up'
+pointers in it, the old pointers are removed and new ones inserted.
+With an argument (prefix argument, @kbd{C-u}, if interactive), this command
+updates all @code{@@node} lines in the region (which is the text
+between point and mark).@refill
+
+@item C-c C-u C-m
+@itemx M-x texinfo-make-menu
+@findex texinfo-make-menu
+Create or update the menu in the node that point is within.
+With an argument (@kbd{C-u} as prefix argument, if
+interactive), the command makes or updates menus for the
+nodes which are either within or a part of the
+region.@refill
+
+Whenever @code{texinfo-make-menu} updates an existing menu, the
+descriptions from that menu are incorporated into the new menu. This
+is done by copying descriptions from the existing menu to the entries
+in the new menu that have the same node names. If the node names are
+different, the descriptions are not copied to the new menu.@refill
+
+@item C-c C-u C-e
+@itemx M-x texinfo-every-node-update
+@findex texinfo-every-node-update
+Insert or update the `Next', `Previous', and `Up' pointers for every
+node in the buffer.@refill
+
+@item C-c C-u C-a
+@itemx M-x texinfo-all-menus-update
+@findex texinfo-all-menus-update
+Create or update all the menus in the buffer. With an argument
+(@kbd{C-u} as prefix argument, if interactive), first insert
+or update all the node
+pointers before working on the menus.@refill
+
+If a master menu exists, the @code{texinfo-all-menus-update} command
+updates it; but the command does not create a new master menu if none
+already exists. (Use the @code{texinfo-master-menu} command for
+that.)@refill
+
+When working on a document that does not merit a master menu, you can
+type the following:
+
+@example
+C-u C-c C-u C-a
+@exdent or
+C-u M-x texinfo-all-menus-update
+@end example
+
+@noindent
+This updates all the nodes and menus.@refill
+@end table
+
+The @code{texinfo-column-for-description} variable specifies the
+column to which menu descriptions are indented. By default, the value
+is 32 although it is often useful to reduce it to as low as 24. You
+can set the variable with the @kbd{M-x edit-options} command
+(@pxref{Edit Options, , Editing Variable Values, emacs, The GNU Emacs
+Manual}) or with the @kbd{M-x set-variable} command (@pxref{Examining,
+, Examining and Setting Variables, emacs, The GNU Emacs
+Manual}).@refill
+
+Also, the @code{texinfo-indent-menu-description} command may be used to
+indent existing menu descriptions to a specified column. Finally, if
+you wish, you can use the @code{texinfo-insert-node-lines} command to
+insert missing @code{@@node} lines into a file. (@xref{Other Updating
+Commands}, for more information.)@refill
+
+@node Updating Requirements, Other Updating Commands, Updating Commands, Updating Nodes and Menus
+@comment node-name, next, previous, up
+@subsection Updating Requirements
+@cindex Updating requirements
+@cindex Requirements for updating commands
+
+To use the updating commands, you must organize the Texinfo file
+hierarchically with chapters, sections, subsections, and the like.
+When you construct the hierarchy of the manual, do not `jump down'
+more than one level at a time: you can follow the `Top' node with a
+chapter, but not with a section; you can follow a chapter with a
+section, but not with a subsection. However, you may `jump up' any
+number of levels at one time---for example, from a subsection to a
+chapter.@refill
+
+Each @code{@@node} line, with the exception of the line for the `Top'
+node, must be followed by a line with a structuring command such as
+@code{@@chapter}, @code{@@section}, or
+@code{@@unnumberedsubsec}.@refill
+
+Each @code{@@node} line/structuring-command line combination
+must look either like this:@refill
+
+@example
+@group
+@@node Comments, Minimum, Conventions, Overview
+@@comment node-name, next, previous, up
+@@section Comments
+@end group
+@end example
+
+or like this (without the @code{@@comment} line):
+
+@example
+@group
+@@node Comments, Minimum, Conventions, Overview
+@@section Comments
+@end group
+@end example
+
+@noindent
+In this example, `Comments' is the name of both the node and the
+section. The next node is called `Minimum' and the previous node is
+called `Conventions'. The `Comments' section is within the `Overview'
+node, which is specified by the `Up' pointer. (Instead of an
+@code{@@comment} line, you can write an @code{@@ifinfo} line.)@refill
+
+If a file has a `Top' node, it must be called @samp{top} or @samp{Top}
+and be the first node in the file.@refill
+
+The menu updating commands create a menu of sections within a chapter,
+a menu of subsections within a section, and so on. This means that
+you must have a `Top' node if you want a menu of chapters.@refill
+
+Incidentally, the @code{makeinfo} command will create an Info file for
+a hierarchically organized Texinfo file that lacks `Next', `Previous'
+and `Up' pointers. Thus, if you can be sure that your Texinfo file
+will be formatted with @code{makeinfo}, you have no need for the
+`update node' commands. (@xref{Create an Info File, , Creating an
+Info File}, for more information about @code{makeinfo}.) However,
+both @code{makeinfo} and the @code{texinfo-format-@dots{}} commands
+require that you insert menus in the file.@refill
+
+@node Other Updating Commands, , Updating Requirements, Updating Nodes and Menus
+@comment node-name, next, previous, up
+@subsection Other Updating Commands
+
+In addition to the five major updating commands, Texinfo mode
+possesses several less frequently used updating commands:@refill
+
+@table @kbd
+@item M-x texinfo-insert-node-lines
+@findex texinfo-insert-node-lines
+Insert @code{@@node} lines before the @code{@@chapter},
+@code{@@section}, and other sectioning commands wherever they are
+missing throughout a region in a Texinfo file.@refill
+
+With an argument (@kbd{C-u} as prefix argument, if interactive), the
+@code{texinfo-insert-node-lines} command not only inserts
+@code{@@node} lines but also inserts the chapter or section titles as
+the names of the corresponding nodes. In addition, it inserts the
+titles as node names in pre-existing @code{@@node} lines that lack
+names. Since node names should be more concise than section or
+chapter titles, you must manually edit node names so inserted.@refill
+
+For example, the following marks a whole buffer as a region and inserts
+@code{@@node} lines and titles throughout:@refill
+
+@example
+C-x h C-u M-x texinfo-insert-node-lines
+@end example
+
+(Note that this command inserts titles as node names in @code{@@node}
+lines; the @code{texinfo-start-menu-description} command
+(@pxref{Inserting, Inserting Frequently Used Commands}) inserts titles
+as descriptions in menu entries, a different action. However, in both
+cases, you need to edit the inserted text.)@refill
+
+@item M-x texinfo-multiple-files-update
+@findex texinfo-multiple-files-update @r{(in brief)}
+Update nodes and menus in a document built from several separate files.
+With @kbd{C-u} as a prefix argument, create and insert a master menu in
+the outer file. With a numeric prefix argument, such as @kbd{C-u 2}, first
+update all the menus and all the `Next', `Previous', and `Up' pointers
+of all the included files before creating and inserting a master menu in
+the outer file. The @code{texinfo-multiple-files-update} command is
+described in the appendix on @code{@@include} files.
+@ifinfo
+@xref{texinfo-multiple-files-update}.@refill
+@end ifinfo
+@iftex
+@xref{texinfo-multiple-files-update, ,
+@code{texinfo-multiple-files-update}}.@refill
+@end iftex
+
+@item M-x texinfo-indent-menu-description
+@findex texinfo-indent-menu-description
+Indent every description in the menu following point to the specified
+column. You can use this command to give yourself more space for
+descriptions. With an argument (@kbd{C-u} as prefix argument, if
+interactive), the @code{texinfo-indent-menu-description} command indents
+every description in every menu in the region. However, this command
+does not indent the second and subsequent lines of a multi-line
+description.@refill
+
+@item M-x texinfo-sequential-node-update
+@findex texinfo-sequential-node-update
+Insert the names of the nodes immediately following and preceding the
+current node as the `Next' or `Previous' pointers regardless of those
+nodes' hierarchical level. This means that the `Next' node of a
+subsection may well be the next chapter. Sequentially ordered nodes are
+useful for novels and other documents that you read through
+sequentially. (However, in Info, the @code{g* @key{RET}} command lets
+you look through the file sequentially, so sequentially ordered nodes
+are not strictly necessary.) With an argument (prefix argument, if
+interactive), the @code{texinfo-sequential-node-update} command
+sequentially updates all the nodes in the region.@refill
+@end table
+
+@node Info Formatting, Printing, Updating Nodes and Menus, Texinfo Mode
+@comment node-name, next, previous, up
+@section Formatting for Info
+@cindex Formatting for Info
+@cindex Running an Info formatter
+@cindex Info formatting
+
+Texinfo mode provides several commands for formatting part or all of a
+Texinfo file for Info. Often, when you are writing a document, you
+want to format only part of a file---that is, a region.@refill
+
+You can use either the @code{texinfo-format-region} or the
+@code{makeinfo-region} command to format a region:@refill
+
+@table @kbd
+@findex texinfo-format-region
+@item C-c C-e C-r
+@itemx M-x texinfo-format-region
+@itemx C-c C-m C-r
+@itemx M-x makeinfo-region
+Format the current region for Info.@refill
+@end table
+
+You can use either the @code{texinfo-format-buffer} or the
+@code{makeinfo-buffer} command to format a whole buffer:@refill
+
+@table @kbd
+@findex texinfo-format-buffer
+@item C-c C-e C-b
+@itemx M-x texinfo-format-buffer
+@itemx C-c C-m C-b
+@itemx M-x makeinfo-buffer
+Format the current buffer for Info.@refill
+@end table
+
+@need 1000
+For example, after writing a Texinfo file, you can type the following:
+
+@example
+C-u C-c C-u m
+@exdent or
+C-u M-x texinfo-master-menu
+@end example
+
+@noindent
+This updates all the nodes and menus. Then type the following to create
+an Info file:
+
+@example
+C-c C-m C-b
+@exdent or
+M-x makeinfo-buffer
+@end example
+
+For @TeX{} or the Info formatting commands to work, the file @emph{must}
+include a line that has @code{@@setfilename} in its header.@refill
+
+@xref{Create an Info File}, for details about Info formatting.@refill
+
+@node Printing, Texinfo Mode Summary, Info Formatting, Texinfo Mode
+@comment node-name, next, previous, up
+@section Formatting and Printing
+@cindex Formatting for printing
+@cindex Printing a region or buffer
+@cindex Region formatting and printing
+@cindex Buffer formatting and printing
+@cindex Part of file formatting and printing
+
+Typesetting and printing a Texinfo file is a multi-step process in which
+you first create a file for printing (called a @sc{dvi} file), and then
+print the file. Optionally, you may also create indices. To do this,
+you must run the @code{texindex} command after first running the
+@code{tex} typesetting command; and then you must run the @code{tex}
+command again. Or else run the @code{texi2dvi} command which
+automatically creates indices as needed.@refill
+
+Often, when you are writing a document, you want to typeset and print
+only part of a file to see what it will look like. You can use the
+@code{texinfo-tex-region} and related commands for this purpose. Use
+the @code{texinfo-tex-buffer} command to format all of a
+buffer.@refill
+
+@table @kbd
+@item C-c C-t C-b
+@itemx M-x texinfo-tex-buffer
+@findex texinfo-tex-buffer
+Run @code{texi2dvi} on the buffer. In addition to running @TeX{} on the
+buffer, this command automatically creates or updates indices as
+needed.@refill
+
+@item C-c C-t C-r
+@itemx M-x texinfo-tex-region
+@findex texinfo-tex-region
+Run @TeX{} on the region.@refill
+
+@item C-c C-t C-i
+@itemx M-x texinfo-texindex
+Run @code{texindex} to sort the indices of a Texinfo file formatted with
+@code{texinfo-tex-region}. The @code{texinfo-tex-region} command does
+not run @code{texindex} automatically; it only runs the @code{tex}
+typesetting command. You must run the @code{texinfo-tex-region} command
+a second time after sorting the raw index files with the @code{texindex}
+command. (Usually, you do not format an index when you format a region,
+only when you format a buffer. Now that the @code{texi2dvi} command
+exists, there is no little need for this command.)@refill
+
+@item C-c C-t C-p
+@itemx M-x texinfo-tex-print
+@findex texinfo-tex-print
+Print the file (or the part of the file) previously formatted with
+@code{texinfo-tex-buffer} or @code{texinfo-tex-region}.@refill
+@end table
+
+For @code{texinfo-tex-region} or @code{texinfo-tex-buffer} to work, the
+file @emph{must} start with a @samp{\input texinfo} line and must
+include an @code{@@settitle} line. The file must end with @code{@@bye}
+on a line by itself. (When you use @code{texinfo-tex-region}, you must
+surround the @code{@@settitle} line with start-of-header and
+end-of-header lines.)@refill
+
+@xref{Format/Print Hardcopy}, for a description of the other @TeX{} related
+commands, such as @code{tex-show-print-queue}.@refill
+
+@node Texinfo Mode Summary, , Printing, Texinfo Mode
+@comment node-name, next, previous, up
+@section Texinfo Mode Summary
+
+In Texinfo mode, each set of commands has default keybindings that
+begin with the same keys. All the commands that are custom-created
+for Texinfo mode begin with @kbd{C-c}. The keys are somewhat
+mnemonic.@refill
+
+@subheading Insert Commands
+
+The insert commands are invoked by typing @kbd{C-c} twice and then the
+first letter of the @@-command to be inserted. (It might make more
+sense mnemonically to use @kbd{C-c C-i}, for `custom insert', but
+@kbd{C-c C-c} is quick to type.)@refill
+
+@example
+C-c C-c c @r{Insert} @samp{@@code}.
+C-c C-c d @r{Insert} @samp{@@dfn}.
+C-c C-c e @r{Insert} @samp{@@end}.
+C-c C-c i @r{Insert} @samp{@@item}.
+C-c C-c n @r{Insert} @samp{@@node}.
+C-c C-c s @r{Insert} @samp{@@samp}.
+C-c C-c v @r{Insert} @samp{@@var}.
+C-c C-c @{ @r{Insert braces.}
+C-c C-c ]
+C-c C-c @} @r{Move out of enclosing braces.}
+
+@group
+C-c C-c C-d @r{Insert a node's section title}
+ @r{in the space for the description}
+ @r{in a menu entry line.}
+@end group
+@end example
+
+@subheading Show Structure
+
+The @code{texinfo-show-structure} command is often used within a
+narrowed region.@refill
+
+@example
+C-c C-s @r{List all the headings.}
+@end example
+
+@subheading The Master Update Command
+
+The @code{texinfo-master-menu} command creates a master menu; and can
+be used to update every node and menu in a file as well.@refill
+
+@example
+@group
+C-c C-u m
+M-x texinfo-master-menu
+ @r{Create or update a master menu.}
+@end group
+
+@group
+C-u C-c C-u m @r{With @kbd{C-u} as a prefix argument, first}
+ @r{create or update all nodes and regular}
+ @r{menus, and then create a master menu.}
+@end group
+@end example
+
+@subheading Update Pointers
+
+The update pointer commands are invoked by typing @kbd{C-c C-u} and
+then either @kbd{C-n} for @code{texinfo-update-node} or @kbd{C-e} for
+@code{texinfo-every-node-update}.@refill
+
+@example
+C-c C-u C-n @r{Update a node.}
+C-c C-u C-e @r{Update every node in the buffer.}
+@end example
+
+@subheading Update Menus
+
+Invoke the update menu commands by typing @kbd{C-c C-u}
+and then either @kbd{C-m} for @code{texinfo-make-menu} or
+@kbd{C-a} for @code{texinfo-all-menus-update}. To update
+both nodes and menus at the same time, precede @kbd{C-c C-u
+C-a} with @kbd{C-u}.@refill
+
+@example
+C-c C-u C-m @r{Make or update a menu.}
+
+@group
+C-c C-u C-a @r{Make or update all}
+ @r{menus in a buffer.}
+@end group
+
+@group
+C-u C-c C-u C-a @r{With @kbd{C-u} as a prefix argument,}
+ @r{first create or update all nodes and}
+ @r{then create or update all menus.}
+@end group
+@end example
+
+@subheading Format for Info
+
+The Info formatting commands that are written in Emacs Lisp are
+invoked by typing @kbd{C-c C-e} and then either @kbd{C-r} for a region
+or @kbd{C-b} for the whole buffer.@refill
+
+The Info formatting commands that are written in C and based on the
+@code{makeinfo} program are invoked by typing @kbd{C-c C-m} and then
+either @kbd{C-r} for a region or @kbd{C-b} for the whole buffer.@refill
+
+@need 800
+@noindent
+Use the @code{texinfo-format@dots{}} commands:
+
+@example
+@group
+C-c C-e C-r @r{Format the region.}
+C-c C-e C-b @r{Format the buffer.}
+@end group
+@end example
+
+@need 750
+@noindent
+Use @code{makeinfo}:
+
+@example
+C-c C-m C-r @r{Format the region.}
+C-c C-m C-b @r{Format the buffer.}
+C-c C-m C-l @r{Recenter the @code{makeinfo} output buffer.}
+C-c C-m C-k @r{Kill the @code{makeinfo} formatting job.}
+@end example
+
+@subheading Typeset and Print
+
+The @TeX{} typesetting and printing commands are invoked by typing
+@kbd{C-c C-t} and then another control command: @kbd{C-r} for
+@code{texinfo-tex-region}, @kbd{C-b} for @code{texinfo-tex-buffer},
+and so on.@refill
+
+@example
+C-c C-t C-r @r{Run @TeX{} on the region.}
+C-c C-t C-b @r{Run} @code{texi2dvi} @r{on the buffer.}
+C-c C-t C-i @r{Run} @code{texindex}.
+C-c C-t C-p @r{Print the @sc{dvi} file.}
+C-c C-t C-q @r{Show the print queue.}
+C-c C-t C-d @r{Delete a job from the print queue.}
+C-c C-t C-k @r{Kill the current @TeX{} formatting job.}
+C-c C-t C-x @r{Quit a currently stopped @TeX{} formatting job.}
+C-c C-t C-l @r{Recenter the output buffer.}
+@end example
+
+@subheading Other Updating Commands
+
+The `other updating commands' do not have standard keybindings because
+they are rarely used.
+
+@example
+@group
+M-x texinfo-insert-node-lines
+ @r{Insert missing @code{@@node} lines in region.}
+ @r{With @kbd{C-u} as a prefix argument,}
+ @r{use section titles as node names.}
+@end group
+
+@group
+M-x texinfo-multiple-files-update
+ @r{Update a multi-file document.}
+ @r{With @kbd{C-u 2} as a prefix argument,}
+ @r{create or update all nodes and menus}
+ @r{in all included files first.}
+@end group
+
+@group
+M-x texinfo-indent-menu-description
+ @r{Indent descriptions.}
+@end group
+
+@group
+M-x texinfo-sequential-node-update
+ @r{Insert node pointers in strict sequence.}
+@end group
+@end example
+
+@node Beginning a File, Ending a File, Texinfo Mode, Top
+@comment node-name, next, previous, up
+@chapter Beginning a Texinfo File
+@cindex Beginning a Texinfo file
+@cindex Texinfo file beginning
+@cindex File beginning
+
+Certain pieces of information must be provided at the beginning of a
+Texinfo file, such as the name of the file and the title of the
+document.@refill
+
+@menu
+* Four Parts:: Four parts begin a Texinfo file.
+* Sample Beginning:: Here is a sample beginning for a Texinfo file.
+* Header:: The very beginning of a Texinfo file.
+* Info Summary and Permissions:: Summary and copying permissions for Info.
+* Titlepage & Copyright Page:: Creating the title and copyright pages.
+* The Top Node:: Creating the `Top' node and master menu.
+* Software Copying Permissions:: Ensure that you and others continue to
+ have the right to use and share software.
+@end menu
+
+@node Four Parts, Sample Beginning, Beginning a File, Beginning a File
+@ifinfo
+@heading Four Parts Begin a File
+@end ifinfo
+
+Generally, the beginning of a Texinfo file has four parts:@refill
+
+@enumerate
+@item
+The header, delimited by special comment lines, that includes the
+commands for naming the Texinfo file and telling @TeX{} what
+definitions' file to use when processing the Texinfo file.@refill
+
+@item
+A short statement of what the file is about, with a copyright notice
+and copying permissions. This is enclosed in @code{@@ifinfo} and
+@code{@@end ifinfo} commands so that the formatters place it only
+in the Info file.@refill
+
+@item
+A title page and copyright page, with a copyright notice and copying
+permissions. This is enclosed between @code{@@titlepage} and
+@code{@@end titlepage} commands. The title and copyright page appear
+only in the printed @w{manual}.@refill
+
+@item
+The `Top' node that contains a menu for the whole Info file. The
+contents of this node appear only in the Info file.@refill
+@end enumerate
+
+Also, optionally, you may include the copying conditions for a program
+and a warranty disclaimer. The copying section will be followed by an
+introduction or else by the first chapter of the manual.@refill
+
+Since the copyright notice and copying permissions for the Texinfo
+document (in contrast to the copying permissions for a program) are in
+parts that appear only in the Info file or only in the printed manual,
+this information must be given twice.@refill
+
+@node Sample Beginning, Header, Four Parts, Beginning a File
+@comment node-name, next, previous, up
+@section Sample Texinfo File Beginning
+
+The following sample shows what is needed.@refill
+
+@example
+\input texinfo @@c -*-texinfo-*-
+@@c %**start of header
+@@setfilename @var{name-of-info-file}
+@@settitle @var{name-of-manual}
+@@setchapternewpage odd
+@@c %**end of header
+
+@@ifinfo
+This file documents @dots{}
+
+Copyright @var{year} @var{copyright-owner}
+
+@group
+Permission is granted to @dots{}
+@@end ifinfo
+@end group
+
+@group
+@@c This title page illustrates only one of the
+@@c two methods of forming a title page.
+@end group
+
+@group
+@@titlepage
+@@title @var{name-of-manual-when-printed}
+@@subtitle @var{subtitle-if-any}
+@@subtitle @var{second-subtitle}
+@@author @var{author}
+@end group
+
+@group
+@@c The following two commands
+@@c start the copyright page.
+@@page
+@@vskip 0pt plus 1filll
+Copyright @@copyright@{@} @var{year} @var{copyright-owner}
+@end group
+
+Published by @dots{}
+
+Permission is granted to @dots{}
+@@end titlepage
+
+@@node Top, Overview, (dir), (dir)
+
+@@ifinfo
+This document describes @dots{}
+
+This document applies to version @dots{}
+of the program named @dots{}
+@@end ifinfo
+
+@group
+@@menu
+* Copying:: Your rights and freedoms.
+* First Chapter:: Getting started @dots{}
+* Second Chapter:: @dots{}
+ @dots{}
+ @dots{}
+@@end menu
+@end group
+
+@group
+@@node First Chapter, Second Chapter, top, top
+@@comment node-name, next, previous, up
+@@chapter First Chapter
+@@cindex Index entry for First Chapter
+@end group
+@end example
+
+@node Header, Info Summary and Permissions, Sample Beginning, Beginning a File
+@comment node-name, next, previous, up
+@section The Texinfo File Header
+@cindex Header for Texinfo files
+@cindex Texinfo file header
+
+Texinfo files start with at least three lines that provide Info and
+@TeX{} with necessary information. These are the @code{\input
+texinfo} line, the @code{@@settitle} line, and the
+@code{@@setfilename} line. If you want to run @TeX{} on just a part
+of the Texinfo File, you must write the @code{@@settitle}
+and @code{@@setfilename} lines between start-of-header and end-of-header
+lines.@refill
+
+Thus, the beginning of a Texinfo file looks like this:
+
+@example
+@group
+\input texinfo @@c -*-texinfo-*-
+@@setfilename sample.info
+@@settitle Sample Document
+@end group
+@end example
+
+@noindent
+or else like this:
+
+@example
+@group
+\input texinfo @@c -*-texinfo-*-
+@@c %**start of header
+@@setfilename sample.info
+@@settitle Sample Document
+@@c %**end of header
+@end group
+@end example
+
+@menu
+* First Line:: The first line of a Texinfo file.
+* Start of Header:: Formatting a region requires this.
+* setfilename:: Tell Info the name of the Info file.
+* settitle:: Create a title for the printed work.
+* setchapternewpage:: Start chapters on right-hand pages.
+* paragraphindent:: An option to specify paragraph indentation.
+* End of Header:: Formatting a region requires this.
+@end menu
+
+@node First Line, Start of Header, Header, Header
+@comment node-name, next, previous, up
+@subsection The First Line of a Texinfo File
+@cindex First line of a Texinfo file
+@cindex Beginning line of a Texinfo file
+@cindex Header of a Texinfo file
+
+Every Texinfo file that is to be the top-level input to @TeX{} must begin
+with a line that looks like this:@refill
+
+@example
+\input texinfo @@c -*-texinfo-*-
+@end example
+
+@noindent
+This line serves two functions:
+
+@enumerate
+@item
+When the file is processed by @TeX{}, the @code{\input texinfo} command
+tells @TeX{} to load the macros needed for processing a Texinfo file.
+These are in a file called @file{texinfo.tex}, which is usually located
+in the @file{/usr/lib/tex/macros} directory. @TeX{} uses the backslash,
+@samp{\}, to mark the beginning of a command, just as Texinfo uses
+@code{@@}. The @file{texinfo.tex} file causes the switch from @samp{\}
+to @samp{@@}; before the switch occurs, @TeX{} requires @samp{\}, which
+is why it appears at the beginning of the file.@refill
+
+@item
+When the file is edited in GNU Emacs, the @samp{-*-texinfo-*-} mode
+specification tells Emacs to use Texinfo mode.@refill
+@end enumerate
+
+@node Start of Header, setfilename, First Line, Header
+@comment node-name, next, previous, up
+@subsection Start of Header
+@cindex Start of header line
+
+Write a start-of-header line on the second line of a Texinfo file.
+Follow the start-of-header line with @code{@@setfilename} and
+@code{@@settitle} lines and, optionally, with other command lines, such
+as @code{@@smallbook} or @code{@@footnotestyle}; and then by an
+end-of-header line (@pxref{End of Header}).@refill
+
+With these lines, you can format part of a Texinfo file for Info or
+typeset part for printing.@refill
+
+A start-of-header line looks like this:@refill
+
+@example
+@@c %**start of header
+@end example
+
+The odd string of characters, @samp{%**}, is to ensure that no other
+comment is accidentally taken for a start-of-header line.@refill
+
+@node setfilename, settitle, Start of Header, Header
+@comment node-name, next, previous, up
+@subsection @code{@@setfilename}
+@cindex Info file requires @code{@@setfilename}
+@findex setfilename
+
+In order to serve as the primary input file for either @code{makeinfo}
+or @TeX{}, a Texinfo file must contain a line that looks like this:
+
+@example
+@@setfilename @var{info-file-name}
+@end example
+
+Write the @code{@@setfilename} command at the beginning of a line and
+follow it on the same line by the Info file name. Do not write
+anything else on the line; anything on the line after the command is
+considered part of the file name, including a comment.@refill
+
+The @code{@@setfilename} line specifies the name of the Info file to be
+generated. This name should be different from the name of the Texinfo
+file. There are two conventions for choosing the name: you can either
+remove the @samp{.tex} extension from the input file name, or replace it
+with the @samp{.info} extension.
+
+Some operating systems cannot handle long file names. You can run into
+a problem even when the file name you specify is itself short enough.
+This occurs because the Info formatters split a long Info file into
+short indirect subfiles, and name them by appending `-1', `-2', @dots{},
+`-10', `-11', and so on, to the original file name. (@xref{Tag and
+Split Files, , Tag Files and Split Files}.) The subfile name
+@file{texinfo.info-10}, for example, is too long for some systems; so
+the Info file name for this document is @file{texinfo} rather than
+@file{texinfo.info}.@refill
+
+The Info formatting commands ignore everything written before the
+@code{@@setfilename} line, which is why the very first line of
+the file (the @code{\input} line) does not need to be commented out.
+
+The @code{@@setfilename} line produces no output when you typeset a
+printed manual, but is does an essential job: it opens the index,
+cross-reference, and other auxiliary files used by Texinfo.
+
+@node settitle, setchapternewpage, setfilename, Header
+@comment node-name, next, previous, up
+@subsection @code{@@settitle}
+@findex settitle
+
+In order to be made into a printed manual, a Texinfo file must contain
+a line that looks like this:@refill
+
+@example
+@@settitle @var{title}
+@end example
+
+Write the @code{@@settitle} command at the beginning of a line and
+follow it on the same line by the title. This tells @TeX{} the title
+to use in a header or footer. Do not write anything else on the line;
+anything on the line after the command is considered part of the
+title, including a comment.@refill
+
+Conventionally, when @TeX{} formats a Texinfo file for double-sided
+output, the title is printed in the left-hand (even-numbered) page
+headings and the current chapter title is printed in the right-hand
+(odd-numbered) page headings. (@TeX{} learns the title of each chapter
+from each @code{@@chapter} command.) Page footers are not
+printed.@refill
+
+Even if you are printing in a single-sided style, @TeX{} looks for an
+@code{@@settitle} command line, in case you include the manual title
+in the heading. @refill
+
+The @code{@@settitle} command should precede everything that generates
+actual output in @TeX{}.@refill
+
+Although the title in the @code{@@settitle} command is usually the
+same as the title on the title page, it does not affect the title as
+it appears on the title page. Thus, the two do not need not match
+exactly; and the title in the @code{@@settitle} command can be a
+shortened or expanded version of the title as it appears on the title
+page. (@xref{titlepage, , @code{@@titlepage}}.)@refill
+
+@TeX{} prints page headings only for that text that comes after the
+@code{@@end titlepage} command in the Texinfo file, or that comes
+after an @code{@@headings} command that turns on headings.
+(@xref{headings on off, , The @code{@@headings} Command}, for more
+information.)@refill
+
+You may, if you wish, create your own, customized headings and
+footings. @xref{Headings, , Page Headings}, for a detailed discussion
+of this process.@refill
+
+@node setchapternewpage, paragraphindent, settitle, Header
+@comment node-name, next, previous, up
+@subsection @code{@@setchapternewpage}
+@cindex Starting chapters
+@cindex Pages, starting odd
+@findex setchapternewpage
+
+In a book or a manual, text is usually printed on both sides of the
+paper, chapters start on right-hand pages, and right-hand pages have
+odd numbers. But in short reports, text often is printed only on one
+side of the paper. Also in short reports, chapters sometimes do not
+start on new pages, but are printed on the same page as the end of the
+preceding chapter, after a small amount of vertical whitespace.@refill
+
+You can use the @code{@@setchapternewpage} command with various
+arguments to specify how @TeX{} should start chapters and whether it
+should typeset pages for printing on one or both sides of the paper
+(single-sided or double-sided printing).@refill
+
+Write the @code{@@setchapternewpage} command at the beginning of a
+line followed by its argument.@refill
+
+For example, you would write the following to cause each chapter to
+start on a fresh odd-numbered page:@refill
+
+@example
+@@setchapternewpage odd
+@end example
+
+You can specify one of three alternatives with the
+@code{@@setchapternewpage} command:@refill
+
+@table @asis
+@ignore
+@item No @code{@@setchapternewpage} command
+If the Texinfo file does not contain an @code{@@setchapternewpage}
+command before the @code{@@titlepage} command, @TeX{} automatically
+begins chapters on new pages and prints headings in the standard
+format for single-sided printing. This is the conventional format for
+single-sided printing.@refill
+
+The result is exactly the same as when you write
+@code{@@setchapternewpage on}.@refill
+@end ignore
+@item @code{@@setchapternewpage off}
+Cause @TeX{} to typeset a new chapter on the same page as the last
+chapter, after skipping some vertical whitespace. Also, cause @TeX{} to
+format page headers for single-sided printing. (You can override the
+headers format with the @code{@@headings double} command; see
+@ref{headings on off, , The @code{@@headings} Command}.)@refill
+
+@item @code{@@setchapternewpage on}
+Cause @TeX{} to start new chapters on new pages and to typeset page
+headers for single-sided printing. This is the form most often
+used for short reports.@refill
+
+This alternative is the default.@refill
+
+@item @code{@@setchapternewpage odd}
+Cause @TeX{} to start new chapters on new, odd-numbered pages
+(right-handed pages) and to typeset for double-sided printing. This is
+the form most often used for books and manuals.@refill
+@end table
+
+@noindent
+Texinfo does not have an @code{@@setchapternewpage even} command.@refill
+
+@noindent
+(You can countermand or modify an @code{@@setchapternewpage} command
+with an @code{@@headings} command. @xref{headings on off, , The
+@code{@@headings} Command}.)@refill
+
+At the beginning of a manual or book, pages are not numbered---for
+example, the title and copyright pages of a book are not numbered.
+By convention, table of contents pages are numbered with roman
+numerals and not in sequence with the rest of the document.@refill
+
+Since an Info file does not have pages, the @code{@@setchapternewpage}
+command has no effect on it.@refill
+
+Usually, you do not write an @code{@@setchapternewpage} command for
+single-sided printing, but accept the default which is to typeset for
+single-sided printing and to start new chapters on new pages. Usually,
+you write an @code{@@setchapternewpage odd} command for double-sided
+printing.@refill
+
+@node paragraphindent, End of Header, setchapternewpage, Header
+@comment node-name, next, previous, up
+@subsection Paragraph Indenting
+@cindex Indenting paragraphs
+@cindex Paragraph indentation
+@findex paragraphindent
+
+The Info formatting commands may insert spaces at the beginning of the
+first line of each paragraph, thereby indenting that paragraph. You
+can use the @code{@@paragraphindent} command to specify the
+indentation. Write an @code{@@paragraphindent} command at the
+beginning of a line followed by either @samp{asis} or a number. The
+template is:@refill
+
+@example
+@@paragraphindent @var{indent}
+@end example
+
+The Info formatting commands indent according to the value of
+@var{indent}:@refill
+
+@itemize @bullet
+@item
+If the value of @var{indent} is @samp{asis}, the Info formatting
+commands do not change the existing indentation.@refill
+
+@item
+If the value of @var{indent} is 0, the Info formatting commands delete
+existing indentation.@refill
+
+@item
+If the value of @var{indent} is greater than 0, the Info formatting
+commands indent the paragraph by that number of spaces.@refill
+@end itemize
+
+The default value of @var{indent} is @samp{asis}.@refill
+
+Write the @code{@@paragraphindent} command before or shortly after the
+end-of-header line at the beginning of a Texinfo file. (If you write
+the command between the start-of-header and end-of-header lines, the
+region formatting commands indent paragraphs as specified.)@refill
+
+A peculiarity of the @code{texinfo-format-buffer} and
+@code{texinfo-format-region} commands is that they do not indent (nor
+fill) paragraphs that contain @code{@@w} or @code{@@*} commands.
+@xref{Refilling Paragraphs}, for a detailed description of what goes
+on.@refill
+
+@node End of Header, , paragraphindent, Header
+@comment node-name, next, previous, up
+@subsection End of Header
+@cindex End of header line
+
+Follow the header lines with an @w{end-of-header} line.
+An end-of-header line looks like this:@refill
+
+@example
+@@c %**end of header
+@end example
+
+If you include the @code{@@setchapternewpage} command between the
+start-of-header and end-of-header lines, @TeX{} will typeset a region as
+that command specifies. Similarly, if you include an @code{@@smallbook}
+command between the start-of-header and end-of-header lines, @TeX{} will
+typeset a region in the ``small'' book format.@refill
+
+@ifinfo
+The reason for the odd string of characters (@samp{%**}) is so that the
+@code{texinfo-tex-region} command does not accidentally find
+something that it should not when it is looking for the header.@refill
+
+The start-of-header line and the end-of-header line are Texinfo mode
+variables that you can change.@refill
+@end ifinfo
+
+@iftex
+@xref{Start of Header}.
+@end iftex
+
+@node Info Summary and Permissions, Titlepage & Copyright Page, Header, Beginning a File
+@comment node-name, next, previous, up
+@section Summary and Copying Permissions for Info
+
+The title page and the copyright page appear only in the printed copy of
+the manual; therefore, the same information must be inserted in a
+section that appears only in the Info file. This section usually
+contains a brief description of the contents of the Info file, a
+copyright notice, and copying permissions.@refill
+
+The copyright notice should read:@refill
+
+@example
+Copyright @var{year} @var{copyright-owner}
+@end example
+
+@noindent
+and be put on a line by itself.@refill
+
+Standard text for the copyright permissions is contained in an appendix
+to this manual; see @ref{ifinfo Permissions, , @samp{ifinfo} Copying
+Permissions}, for the complete text.@refill
+
+The permissions text appears in an Info file @emph{before} the first
+node. This mean that a reader does @emph{not} see this text when
+reading the file using Info, except when using the advanced Info command
+@kbd{g *}.
+
+@node Titlepage & Copyright Page, The Top Node, Info Summary and Permissions, Beginning a File
+@comment node-name, next, previous, up
+@section The Title and Copyright Pages
+
+A manual's name and author are usually printed on a title page.
+Sometimes copyright information is printed on the title page as well;
+more often, copyright information is printed on the back of the title
+page.
+
+The title and copyright pages appear in the printed manual, but not in the
+Info file. Because of this, it is possible to use several slightly
+obscure @TeX{} typesetting commands that cannot be used in an Info file.
+In addition, this part of the beginning of a Texinfo file contains the text
+of the copying permissions that will appear in the printed manual.@refill
+
+@xref{Titlepage Permissions, , Titlepage Copying Permissions}, for the
+standard text for the copyright permissions.@refill
+
+@menu
+* titlepage:: Create a title for the printed document.
+* titlefont center sp:: The @code{@@titlefont}, @code{@@center},
+ and @code{@@sp} commands.
+* title subtitle author:: The @code{@@title}, @code{@@subtitle},
+ and @code{@@author} commands.
+* Copyright & Permissions:: How to write the copyright notice and
+ include copying permissions.
+* end titlepage:: Turn on page headings after the title and
+ copyright pages.
+* headings on off:: An option for turning headings on and off
+ and double or single sided printing.
+@end menu
+
+@node titlepage, titlefont center sp, Titlepage & Copyright Page, Titlepage & Copyright Page
+@comment node-name, next, previous, up
+@subsection @code{@@titlepage}
+@cindex Title page
+@findex titlepage
+
+Start the material for the title page and following copyright page
+with @code{@@titlepage} on a line by itself and end it with
+@code{@@end titlepage} on a line by itself.@refill
+
+The @code{@@end titlepage} command starts a new page and turns on page
+numbering. (@xref{Headings, , Page Headings}, for details about how to
+generate page headings.) All the material that you want to
+appear on unnumbered pages should be put between the
+@code{@@titlepage} and @code{@@end titlepage} commands. By using the
+@code{@@page} command you can force a page break within the region
+delineated by the @code{@@titlepage} and @code{@@end titlepage}
+commands and thereby create more than one unnumbered page. This is
+how the copyright page is produced. (The @code{@@titlepage} command
+might perhaps have been better named the
+@code{@@titleandadditionalpages} command, but that would have been
+rather long!)@refill
+
+@c !!! append refill to footnote when makeinfo can handle it.
+When you write a manual about a computer program, you should write the
+version of the program to which the manual applies on the title
+page. If the manual changes more frequently than the program or is
+independent of it, you should also include an edition
+number@footnote{We have found that it is helpful to refer to versions
+of manuals as `editions' and versions of programs as `versions';
+otherwise, we find we are liable to confuse each other in conversation
+by referring to both the documentation and the software with the same
+words.} for the manual. This helps readers keep track of which manual
+is for which version of the program. (The `Top' node
+should also contain this information; see @ref{makeinfo top, ,
+@code{@@top}}.)@refill
+
+Texinfo provides two main methods for creating a title page. One method
+uses the @code{@@titlefont}, @code{@@sp}, and @code{@@center} commands
+to generate a title page in which the words on the page are
+centered.@refill
+
+The second method uses the @code{@@title}, @code{@@subtitle}, and
+@code{@@author} commands to create a title page with black rules under
+the title and author lines and the subtitle text set flush to the
+right hand side of the page. With this method, you do not specify any
+of the actual formatting of the title page. You specify the text
+you want, and Texinfo does the formatting. You may use either
+method.@refill
+
+@findex shorttitlepage
+For extremely simple applications, Texinfo also provides a command
+@code{@@shorttitlepage} which takes a single argument as the title.
+The argument is typeset on a page by itself and followed by a blank
+page.
+
+
+@node titlefont center sp, title subtitle author, titlepage, Titlepage & Copyright Page
+@comment node-name, next, previous, up
+@subsection @code{@@titlefont}, @code{@@center}, and @code{@@sp}
+@findex titlefont
+@findex center
+@findex sp @r{(titlepage line spacing)}
+
+You can use the @code{@@titlefont}, @code{@@sp}, and @code{@@center}
+commands to create a title page for a printed document. (This is the
+first of the two methods for creating a title page in Texinfo.)@refill
+
+Use the @code{@@titlefont} command to select a large font suitable for
+the title itself.@refill
+
+@need 700
+For example:
+
+@example
+@@titlefont@{Texinfo@}
+@end example
+
+Use the @code{@@center} command at the beginning of a line to center
+the remaining text on that line. Thus,@refill
+
+@example
+@@center @@titlefont@{Texinfo@}
+@end example
+
+@noindent
+centers the title, which in this example is ``Texinfo'' printed
+in the title font.@refill
+
+Use the @code{@@sp} command to insert vertical space. For example:@refill
+
+@example
+@@sp 2
+@end example
+
+@noindent
+This inserts two blank lines on the printed page. (@xref{sp, ,
+@code{@@sp}}, for more information about the @code{@@sp}
+command.)@refill
+
+A template for this method looks like this:@refill
+
+@example
+@group
+@@titlepage
+@@sp 10
+@@center @@titlefont@{@var{name-of-manual-when-printed}@}
+@@sp 2
+@@center @var{subtitle-if-any}
+@@sp 2
+@@center @var{author}
+@dots{}
+@@end titlepage
+@end group
+@end example
+
+The spacing of the example fits an 8 1/2 by 11 inch manual.@refill
+
+@node title subtitle author, Copyright & Permissions, titlefont center sp, Titlepage & Copyright Page
+@comment node-name, next, previous, up
+@subsection @code{@@title}, @code{@@subtitle}, and @code{@@author}
+@findex title
+@findex subtitle
+@findex author
+
+You can use the @code{@@title}, @code{@@subtitle}, and @code{@@author}
+commands to create a title page in which the vertical and horizontal
+spacing is done for you automatically. This contrasts with the method
+described in
+the previous section, in which the @code{@@sp} command is needed to
+adjust vertical spacing.@refill
+
+Write the @code{@@title}, @code{@@subtitle}, or @code{@@author}
+commands at the beginning of a line followed by the title, subtitle,
+or author.@refill
+
+The @code{@@title} command produces a line in which the title is set
+flush to the left-hand side of the page in a larger than normal font.
+The title is underlined with a black rule.@refill
+
+The @code{@@subtitle} command sets subtitles in a normal-sized font
+flush to the right-hand side of the page.@refill
+
+The @code{@@author} command sets the names of the author or authors in
+a middle-sized font flush to the left-hand side of the page on a line
+near the bottom of the title page. The names are underlined with a
+black rule that is thinner than the rule that underlines the title.
+(The black rule only occurs if the @code{@@author} command line is
+followed by an @code{@@page} command line.)@refill
+
+There are two ways to use the @code{@@author} command: you can write
+the name or names on the remaining part of the line that starts with
+an @code{@@author} command:@refill
+
+@example
+@@author by Jane Smith and John Doe
+@end example
+
+@noindent
+or you can write the names one above each other by using two (or more)
+@code{@@author} commands:@refill
+
+@example
+@group
+@@author Jane Smith
+@@author John Doe
+@end group
+@end example
+
+@noindent
+(Only the bottom name is underlined with a black rule.)@refill
+
+@need 950
+A template for this method looks like this:@refill
+
+@example
+@group
+@@titlepage
+@@title @var{name-of-manual-when-printed}
+@@subtitle @var{subtitle-if-any}
+@@subtitle @var{second-subtitle}
+@@author @var{author}
+@@page
+@dots{}
+@@end titlepage
+@end group
+@end example
+
+@ifinfo
+@noindent
+Contrast this form with the form of a title page written using the
+@code{@@sp}, @code{@@center}, and @code{@@titlefont} commands:@refill
+
+@example
+@@titlepage
+@@sp 10
+@@center @@titlefont@{Name of Manual When Printed@}
+@@sp 2
+@@center Subtitle, If Any
+@@sp 1
+@@center Second subtitle
+@@sp 2
+@@center Author
+@@page
+@dots{}
+@@end titlepage
+@end example
+@end ifinfo
+
+@node Copyright & Permissions, end titlepage, title subtitle author, Titlepage & Copyright Page
+@comment node-name, next, previous, up
+@subsection Copyright Page and Permissions
+@cindex Copyright page
+@cindex Printed permissions
+@cindex Permissions, printed
+
+By international treaty, the copyright notice for a book should be
+either on the title page or on the back of the title page. The
+copyright notice should include the year followed by the name of the
+organization or person who owns the copyright.@refill
+
+When the copyright notice is on the back of the title page, that page
+is customarily not numbered. Therefore, in Texinfo, the information
+on the copyright page should be within @code{@@titlepage} and
+@code{@@end titlepage} commands.@refill
+
+@findex vskip
+@findex filll
+@cindex Vertical whitespace (@samp{vskip})
+Use the @code{@@page} command to cause a page break. To push the
+copyright notice and the other text on the copyright page towards the
+bottom of the page, you can write a somewhat mysterious line after the
+@code{@@page} command that reads like this:@refill
+
+@example
+@@vskip 0pt plus 1filll
+@end example
+
+@noindent
+This is a @TeX{} command that is not supported by the Info formatting
+commands. The @code{@@vskip} command inserts whitespace. The
+@samp{0pt plus 1filll} means to put in zero points of mandatory whitespace,
+and as much optional whitespace as needed to push the
+following text to the bottom of the page. Note the use of three
+@samp{l}s in the word @samp{filll}; this is the correct usage in
+@TeX{}.@refill
+
+@findex copyright
+In a printed manual, the @code{@@copyright@{@}} command generates a
+@samp{c} inside a circle. (In Info, it generates @samp{(C)}.) The
+copyright notice itself has the following legally defined sequence:@refill
+
+@example
+Copyright @copyright{} @var{year} @var{copyright-owner}
+@end example
+
+It is customary to put information on how to get a manual after the
+copyright notice, followed by the copying permissions for the
+manual.@refill
+
+Note that permissions must be given here as well as in the summary
+segment within @code{@@ifinfo} and @code{@@end ifinfo} that
+immediately follows the header since this text appears only in the
+printed manual and the @samp{ifinfo} text appears only in the Info
+file.@refill
+
+@xref{Sample Permissions}, for the standard text.@refill
+
+@node end titlepage, headings on off, Copyright & Permissions, Titlepage & Copyright Page
+@comment node-name, next, previous, up
+@subsection Heading Generation
+@findex end titlepage
+@cindex Headings, page, begin to appear
+@cindex Titlepage end starts headings
+@cindex End titlepage starts headings
+
+An @code{@@end titlepage} command on a line by itself not only marks
+the end of the title and copyright pages, but also causes @TeX{} to start
+generating page headings and page numbers.
+
+To repeat what is said elsewhere, Texinfo has two standard page heading
+formats, one for documents which are printed on one side of each sheet of paper
+(single-sided printing), and the other for documents which are printed on both
+sides of each sheet (double-sided printing).
+(@xref{setchapternewpage, ,@code{@@setchapternewpage}}.)
+You can specify these formats in different ways:@refill
+
+@itemize @bullet
+@item
+The conventional way is to write an @code{@@setchapternewpage} command
+before the title page commands, and then have the @code{@@end
+titlepage} command start generating page headings in the manner desired.
+(@xref{setchapternewpage, , @code{@@setchapternewpage}}.)@refill
+
+@item
+Alternatively, you can use the @code{@@headings} command to prevent page
+headings from being generated or to start them for either single or
+double-sided printing. (Write an @code{@@headings} command immediately
+after the @code{@@end titlepage} command. @xref{headings on off, , The
+@code{@@headings} Command}, for more information.)@refill
+
+@item
+Or, you may specify your own page heading and footing format.
+@xref{Headings, , Page Headings}, for detailed
+information about page headings and footings.@refill
+@end itemize
+
+Most documents are formatted with the standard single-sided or
+double-sided format, using @code{@@setchapternewpage odd} for
+double-sided printing and no @code{@@setchapternewpage} command for
+single-sided printing.@refill
+
+@node headings on off, , end titlepage, Titlepage & Copyright Page
+@comment node-name, next, previous, up
+@subsection The @code{@@headings} Command
+@findex headings
+
+The @code{@@headings} command is rarely used. It specifies what kind of
+page headings and footings to print on each page. Usually, this is
+controlled by the @code{@@setchapternewpage} command. You need the
+@code{@@headings} command only if the @code{@@setchapternewpage} command
+does not do what you want, or if you want to turn off pre-defined page
+headings prior to defining your own. Write an @code{@@headings} command
+immediately after the @code{@@end titlepage} command.@refill
+
+You can use @code{@@headings} as follows:@refill
+
+@table @code
+@item @@headings off
+Turn off printing of page headings.@refill
+
+@item @@headings single
+Turn on page headings appropriate for single-sided printing.
+@refill
+
+@item @@headings double
+Turn on page headings appropriate for double-sided printing. The two
+commands, @code{@@headings on} and @code{@@headings double}, are
+synonymous.@refill
+
+@item @@headings singleafter
+@itemx @@headings doubleafter
+Turn on @code{single} or @code{double} headings, respectively, after the
+current page is output.
+
+@item @@headings on
+Turn on page headings: @code{single} if @samp{@@setchapternewpage
+on}, @code{double} otherwise.
+@end table
+
+For example, suppose you write @code{@@setchapternewpage off} before the
+@code{@@titlepage} command to tell @TeX{} to start a new chapter on the
+same page as the end of the last chapter. This command also causes
+@TeX{} to typeset page headers for single-sided printing. To cause
+@TeX{} to typeset for double sided printing, write @code{@@headings
+double} after the @code{@@end titlepage} command.
+
+You can stop @TeX{} from generating any page headings at all by
+writing @code{@@headings off} on a line of its own immediately after the
+line containing the @code{@@end titlepage} command, like this:@refill
+
+@example
+@@end titlepage
+@@headings off
+@end example
+
+@noindent
+The @code{@@headings off} command overrides the @code{@@end titlepage}
+command, which would otherwise cause @TeX{} to print page
+headings.@refill
+
+You can also specify your own style of page heading and footing.
+@xref{Headings, , Page Headings}, for more information.@refill
+
+@node The Top Node, Software Copying Permissions, Titlepage & Copyright Page, Beginning a File
+@comment node-name, next, previous, up
+@section The `Top' Node and Master Menu
+@cindex @samp{@r{Top}} node
+@cindex Master menu
+@cindex Node, `Top'
+
+The `Top' node is the node from which you enter an Info file.@refill
+
+A `Top' node should contain a brief description of the Info file and an
+extensive, master menu for the whole Info file.
+This helps the reader understand what the Info file is
+about. Also, you should write the version number of the program to
+which the Info file applies; or, at least, the edition number.@refill
+
+The contents of the `Top' node should appear only in the Info file; none
+of it should appear in printed output, so enclose it between
+@code{@@ifinfo} and @code{@@end ifinfo} commands. (@TeX{} does not
+print either an @code{@@node} line or a menu; they appear only in Info;
+strictly speaking, you are not required to enclose these parts between
+@code{@@ifinfo} and @code{@@end ifinfo}, but it is simplest to do so.
+@xref{Conditionals, , Conditionally Visible Text}.)@refill
+
+@menu
+* Title of Top Node:: Sketch what the file is about.
+* Master Menu Parts:: A master menu has three or more parts.
+@end menu
+
+@node Title of Top Node, Master Menu Parts, The Top Node, The Top Node
+@ifinfo
+@subheading `Top' Node Title
+@end ifinfo
+
+Sometimes, you will want to place an @code{@@top} sectioning command
+line containing the title of the document immediately after the
+@code{@@node Top} line (@pxref{makeinfo top command, , The @code{@@top}
+Sectioning Command}, for more information).@refill
+
+For example, the beginning of the Top node of this manual contains an
+@code{@@top} sectioning command, a short description, and edition and
+version information. It looks like this:@refill
+
+@example
+@group
+@dots{}
+@@end titlepage
+
+@@ifinfo
+@@node Top, Copying, (dir), (dir)
+@@top Texinfo
+
+Texinfo is a documentation system@dots{}
+@end group
+
+@group
+This is edition@dots{}
+@dots{}
+@@end ifinfo
+@end group
+
+@group
+@@menu
+* Copying:: Texinfo is freely
+ redistributable.
+* Overview:: What is Texinfo?
+@dots{}
+@end group
+@@end menu
+@end example
+
+In a `Top' node, the `Previous', and `Up' nodes usually refer to the top
+level directory of the whole Info system, which is called @samp{(dir)}.
+The `Next' node refers to the first node that follows the main or master
+menu, which is usually the copying permissions, introduction, or first
+chapter.@refill
+
+@node Master Menu Parts, , Title of Top Node, The Top Node
+@subsection Parts of a Master Menu
+@cindex Master menu parts
+@cindex Parts of a master menu
+
+A @dfn{master menu} is a detailed main menu listing all the nodes in a
+file.
+
+A master menu is enclosed in @code{@@menu} and @code{@@end menu}
+commands and does not appear in the printed document.@refill
+
+Generally, a master menu is divided into parts.@refill
+
+@itemize @bullet
+@item
+The first part contains the major nodes in the Texinfo file: the nodes
+for the chapters, chapter-like sections, and the appendices.@refill
+
+@item
+The second part contains nodes for the indices.@refill
+
+@item
+The third and subsequent parts contain a listing of the other, lower
+level nodes, often ordered by chapter. This way, rather than go
+through an intermediary menu, an inquirer can go directly to a
+particular node when searching for specific information. These menu
+items are not required; add them if you think they are a
+convenience. If you do use them, put @code{@@detailmenu} before the
+first one, and @code{@@end detailmenu} after the last; otherwise,
+@code{makeinfo} will get confused.
+@end itemize
+
+Each section in the menu can be introduced by a descriptive line. So
+long as the line does not begin with an asterisk, it will not be
+treated as a menu entry. (@xref{Writing a Menu}, for more
+information.)@refill
+
+For example, the master menu for this manual looks like the following
+(but has many more entries):@refill
+
+@example
+@group
+@@menu
+* Copying:: Texinfo is freely
+ redistributable.
+* Overview:: What is Texinfo?
+* Texinfo Mode:: Special features in GNU Emacs.
+@dots{}
+@dots{}
+@end group
+@group
+* Command and Variable Index::
+ An entry for each @@-command.
+* Concept Index:: An entry for each concept.
+@end group
+
+@group
+@@detailmenu
+ --- The Detailed Node Listing ---
+
+Overview of Texinfo
+
+* Info Files:: What is an Info file?
+* Printed Manuals:: Characteristics of
+ a printed manual.
+@dots{}
+@dots{}
+@end group
+
+@group
+Using Texinfo Mode
+
+* Info on a Region:: Formatting part of a file
+ for Info.
+@dots{}
+@dots{}
+@@end detailmenu
+@@end menu
+@end group
+@end example
+
+@node Software Copying Permissions, , The Top Node, Beginning a File
+@comment node-name, next, previous, up
+@section Software Copying Permissions
+@cindex Software copying permissions
+@cindex Copying software
+@cindex Distribution
+@cindex License agreement
+
+If the Texinfo file has a section containing the ``General Public
+License'' and the distribution information and a warranty disclaimer
+for the software that is documented, this section usually follows the
+`Top' node. The General Public License is very important to Project
+GNU software. It ensures that you and others will continue to have a
+right to use and share the software.@refill
+
+The copying and distribution information and the disclaimer are
+followed by an introduction or else by the first chapter of the
+manual.@refill
+
+@cindex Introduction, as part of file
+Although an introduction is not a required part of a Texinfo file, it
+is very helpful. Ideally, it should state clearly and concisely what
+the file is about and who would be interested in reading it. In
+general, an introduction would follow the licensing and distribution
+information, although sometimes people put it earlier in the document.
+Usually, an introduction is put in an @code{@@unnumbered} section.
+(@xref{unnumbered & appendix, , The @code{@@unnumbered} and
+@code{@@appendix} Commands}.)@refill
+
+@node Ending a File, Structuring, Beginning a File, Top
+@comment node-name, next, previous, up
+@chapter Ending a Texinfo File
+@cindex Ending a Texinfo file
+@cindex Texinfo file ending
+@cindex File ending
+@findex bye
+
+The end of a Texinfo file should include the commands that create
+indices and generate detailed and summary tables of contents.
+And it must include the @code{@@bye} command that marks the last line
+processed by @TeX{}.@refill
+
+@need 700
+For example:
+
+@example
+@@node Concept Index, , Variables Index, Top
+@@c node-name, next, previous, up
+@@unnumbered Concept Index
+
+@@printindex cp
+
+@@contents
+@@bye
+@end example
+
+@menu
+* Printing Indices & Menus:: How to print an index in hardcopy and
+ generate index menus in Info.
+* Contents:: How to create a table of contents.
+* File End:: How to mark the end of a file.
+@end menu
+
+@node Printing Indices & Menus, Contents, Ending a File, Ending a File
+@comment node-name, next, previous, up
+@section Index Menus and Printing an Index
+@findex printindex
+@cindex Printing an index
+@cindex Indices, printing and menus
+@cindex Generating menus with indices
+@cindex Menus generated with indices
+
+To print an index means to include it as part of a manual or Info
+file. This does not happen automatically just because you use
+@code{@@cindex} or other index-entry generating commands in the
+Texinfo file; those just cause the raw data for the index to be
+accumulated. To generate an index, you must include the
+@code{@@printindex} command at the place in the document where you
+want the index to appear. Also, as part of the process of creating a
+printed manual, you must run a program called @code{texindex}
+(@pxref{Format/Print Hardcopy}) to sort the raw data to produce a sorted
+index file. The sorted index file is what is actually used to
+print the index.@refill
+
+Texinfo offers six different types of predefined index: the concept
+index, the function index, the variables index, the keystroke index, the
+program index, and the data type index (@pxref{Predefined Indices}). Each
+index type has a two-letter name: @samp{cp}, @samp{fn}, @samp{vr},
+@samp{ky}, @samp{pg}, and @samp{tp}. You may merge indices, or put them
+into separate sections (@pxref{Combining Indices}); or you may define
+your own indices (@pxref{New Indices, , Defining New Indices}).@refill
+
+The @code{@@printindex} command takes a two-letter index name, reads
+the corresponding sorted index file and formats it appropriately into
+an index.@refill
+
+@ignore
+The two-letter index names are:
+
+@table @samp
+@item cp
+concept index
+@item fn
+function index
+@item vr
+variable index
+@item ky
+key index
+@item pg
+program index
+@item tp
+data type index
+@end table
+@end ignore
+The @code{@@printindex} command does not generate a chapter heading
+for the index. Consequently, you should precede the
+@code{@@printindex} command with a suitable section or chapter command
+(usually @code{@@unnumbered}) to supply the chapter heading and put
+the index into the table of contents. Precede the @code{@@unnumbered}
+command with an @code{@@node} line.@refill
+
+@need 1200
+For example:
+
+@smallexample
+@group
+@@node Variable Index, Concept Index, Function Index, Top
+@@comment node-name, next, previous, up
+@@unnumbered Variable Index
+
+@@printindex vr
+@end group
+
+@group
+@@node Concept Index, , Variable Index, Top
+@@comment node-name, next, previous, up
+@@unnumbered Concept Index
+
+@@printindex cp
+@end group
+
+@group
+@@summarycontents
+@@contents
+@@bye
+@end group
+@end smallexample
+
+@noindent
+(Readers often prefer that the concept index come last in a book,
+since that makes it easiest to find.)@refill
+
+@ignore
+In @TeX{}, the @code{@@printindex} command needs a sorted index file
+to work from. @TeX{} does not know how to do sorting; this is a
+deficiency. @TeX{} writes output files of raw index data; use the
+@code{texindex} program to convert these files to sorted index files.
+(@xref{Format/Print Hardcopy}, for more information.)@refill
+@end ignore
+@node Contents, File End, Printing Indices & Menus, Ending a File
+@comment node-name, next, previous, up
+@section Generating a Table of Contents
+@cindex Table of contents
+@cindex Contents, Table of
+@findex contents
+@findex summarycontents
+@findex shortcontents
+
+The @code{@@chapter}, @code{@@section}, and other structuring commands
+supply the information to make up a table of contents, but they do not
+cause an actual table to appear in the manual. To do this, you must
+use the @code{@@contents} and @code{@@summarycontents}
+commands:@refill
+
+@table @code
+@item @@contents
+Generate a table of contents in a printed manual, including all
+chapters, sections, subsections, etc., as well as appendices and
+unnumbered chapters. (Headings generated by the @code{@@heading}
+series of commands do not appear in the table of contents.) The
+@code{@@contents} command should be written on a line by
+itself.@refill
+
+@item @@shortcontents
+@itemx @@summarycontents
+(@code{@@summarycontents} is a synonym for @code{@@shortcontents}; the
+two commands are exactly the same.)@refill
+
+Generate a short or summary table of contents that lists only the
+chapters (and appendices and unnumbered chapters). Omit sections, subsections
+and subsubsections. Only a long manual needs a short table
+of contents in addition to the full table of contents.@refill
+
+Write the @code{@@shortcontents} command on a line by itself right
+@emph{before} the @code{@@contents} command.@refill
+@end table
+
+The table of contents commands automatically generate a chapter-like
+heading at the top of the first table of contents page. Write the table
+of contents commands at the very end of a Texinfo file, just before the
+@code{@@bye} command, following any index sections---anything in the
+Texinfo file after the table of contents commands will be omitted from
+the table of contents.@refill
+
+When you print a manual with a table of contents, the table of
+contents are printed last and numbered with roman numerals. You need
+to place those pages in their proper place, after the title page,
+yourself. (This is the only collating you need to do for a printed
+manual. The table of contents is printed last because it is generated
+after the rest of the manual is typeset.)@refill
+
+@need 700
+Here is an example of where to write table of contents commands:@refill
+
+@example
+@group
+@var{indices}@dots{}
+@@shortcontents
+@@contents
+@@bye
+@end group
+@end example
+
+Since an Info file uses menus instead of tables of contents, the Info
+formatting commands ignore the @code{@@contents} and
+@code{@@shortcontents} commands.@refill
+
+@node File End, , Contents, Ending a File
+@comment node-name, next, previous, up
+@section @code{@@bye} File Ending
+@findex bye
+
+An @code{@@bye} command terminates @TeX{} or Info formatting. None of
+the formatting commands see any of the file following @code{@@bye}.
+The @code{@@bye} command should be on a line by itself.@refill
+
+If you wish, you may follow the @code{@@bye} line with notes. These notes
+will not be formatted and will not appear in either Info or a printed
+manual; it is as if text after @code{@@bye} were within @code{@@ignore}
+@dots{} @code{@@end ignore}. Also, you may follow the @code{@@bye} line
+with a local variables list. @xref{Compile-Command, , Using Local
+Variables and the Compile Command}, for more information.@refill
+
+@node Structuring, Nodes, Ending a File, Top
+@comment node-name, next, previous, up
+@chapter Chapter Structuring
+@cindex Chapter structuring
+@cindex Structuring of chapters
+
+The @dfn{chapter structuring} commands divide a document into a hierarchy of
+chapters, sections, subsections, and subsubsections. These commands
+generate large headings; they also provide information for the table
+of contents of a printed manual (@pxref{Contents, , Generating a Table
+of Contents}).@refill
+
+The chapter structuring commands do not create an Info node structure,
+so normally you should put an @code{@@node} command immediately before
+each chapter structuring command (@pxref{Nodes}). The only time you
+are likely to use the chapter structuring commands without using the
+node structuring commands is if you are writing a document that
+contains no cross references and will never be transformed into Info
+format.@refill
+
+It is unlikely that you will ever write a Texinfo file that is
+intended only as an Info file and not as a printable document. If you
+do, you might still use chapter structuring commands to create a
+heading at the top of each node---but you don't need to.@refill
+
+@menu
+* Tree Structuring:: A manual is like an upside down tree @dots{}
+* Structuring Command Types:: How to divide a manual into parts.
+* makeinfo top:: The @code{@@top} command, part of the `Top' node.
+* chapter::
+* unnumbered & appendix::
+* majorheading & chapheading::
+* section::
+* unnumberedsec appendixsec heading::
+* subsection::
+* unnumberedsubsec appendixsubsec subheading::
+* subsubsection:: Commands for the lowest level sections.
+* Raise/lower sections:: How to change commands' hierarchical level.
+@end menu
+
+@node Tree Structuring, Structuring Command Types, Structuring, Structuring
+@comment node-name, next, previous, up
+@section Tree Structure of Sections
+@cindex Tree structuring
+
+A Texinfo file is usually structured like a book with chapters,
+sections, subsections, and the like. This structure can be visualized
+as a tree (or rather as an upside-down tree) with the root at the top
+and the levels corresponding to chapters, sections, subsection, and
+subsubsections.@refill
+
+Here is a diagram that shows a Texinfo file with three chapters,
+each of which has two sections.@refill
+
+@example
+@group
+ Top
+ |
+ -------------------------------------
+ | | |
+ Chapter 1 Chapter 2 Chapter 3
+ | | |
+ -------- -------- --------
+ | | | | | |
+ Section Section Section Section Section Section
+ 1.1 1.2 2.1 2.2 3.1 3.2
+
+@end group
+@end example
+
+In a Texinfo file that has this structure, the beginning of Chapter 2
+looks like this:@refill
+
+@example
+@group
+@@node Chapter 2, Chapter 3, Chapter 1, top
+@@chapter Chapter 2
+@end group
+@end example
+
+The chapter structuring commands are described in the sections that
+follow; the @code{@@node} and @code{@@menu} commands are described in
+following chapters. (@xref{Nodes}, and see @ref{Menus}.)@refill
+
+@node Structuring Command Types, makeinfo top, Tree Structuring, Structuring
+@comment node-name, next, previous, up
+@section Types of Structuring Command
+
+The chapter structuring commands fall into four groups or series, each
+of which contains structuring commands corresponding to the
+hierarchical levels of chapters, sections, subsections, and
+subsubsections.@refill
+
+The four groups are the @code{@@chapter} series, the
+@code{@@unnumbered} series, the @code{@@appendix} series, and the
+@code{@@heading} series.@refill
+
+Each command produces titles that have a different appearance on the
+printed page or Info file; only some of the commands produce
+titles that are listed in the table of contents of a printed book or
+manual.@refill
+
+@itemize @bullet
+@item
+The @code{@@chapter} and @code{@@appendix} series of commands produce
+numbered or lettered entries both in the body of a printed work and in
+its table of contents.@refill
+
+@item
+The @code{@@unnumbered} series of commands produce unnumbered entries
+both in the body of a printed work and in its table of contents. The
+@code{@@top} command, which has a special use, is a member of this
+series (@pxref{makeinfo top, , @code{@@top}}).@refill
+
+@item
+The @code{@@heading} series of commands produce unnumbered headings
+that do not appear in a table of contents. The heading commands never
+start a new page.@refill
+
+@item
+The @code{@@majorheading} command produces results similar to using
+the @code{@@chapheading} command but generates a larger vertical
+whitespace before the heading.@refill
+
+@item
+When an @code{@@setchapternewpage} command says to do so, the
+@code{@@chapter}, @code{@@unnumbered}, and @code{@@appendix} commands
+start new pages in the printed manual; the @code{@@heading} commands
+do not.@refill
+@end itemize
+
+@need 1000
+Here are the four groups of chapter structuring commands:@refill
+
+@c Slightly different formatting for regular sized books and smallbooks.
+@ifset smallbook
+@sp 1
+@tex
+{\let\rm=\indrm \let\tt=\indtt
+\halign{\hskip\itemindent#\hfil& \hskip.5em#\hfil& \hskip.5em#\hfil&
+\hskip.5em#\hfil\cr
+
+& & & \rm No new pages\cr
+\rm Numbered& \rm Unnumbered& \rm Lettered and numbered& \rm Unnumbered\cr
+\rm In contents& \rm In contents& \rm In contents& \rm Not in contents\cr
+
+& & & \cr
+ & \tt @@top& & \tt @@majorheading\cr
+\tt @@chapter& \tt @@unnumbered& \tt @@appendix& \tt @@chapheading\cr
+\tt @@section& \tt @@unnumberedsec& \tt @@appendixsec& \tt @@heading\cr
+\tt @@subsection&\tt @@unnumberedsubsec&\tt @@appendixsubsec&
+\tt @@subheading\cr
+\tt @@subsubsection& \tt @@unnumberedsubsubsec& \tt @@appendixsubsubsec&
+\tt @@subsubheading\cr}}
+@end tex
+@end ifset
+@ifclear smallbook
+@sp 1
+@tex
+\vbox{
+\halign{\hskip\itemindent\hskip.5em#\hfil& \hskip.5em#\hfil&
+\hskip.5em#\hfil& \hskip.5em #\hfil\cr
+
+& & & \cr
+& & & \rm No new pages\cr
+\rm Numbered& \rm Unnumbered& \rm Lettered and numbered& \rm Unnumbered\cr
+\rm In contents& \rm In contents& \rm In contents& \rm Not in contents\cr
+
+& & & \cr
+ & \tt @@top& & \tt @@majorheading\cr
+\tt @@chapter& \tt @@unnumbered& \tt @@appendix& \tt @@chapheading\cr
+\tt @@section& \tt @@unnumberedsec& \tt @@appendixsec& \tt @@heading\cr
+\tt @@subsection&\tt @@unnumberedsubsec&\tt @@appendixsubsec&
+\tt @@subheading\cr
+\tt @@subsubsection& \tt @@unnumberedsubsubsec& \tt @@appendixsubsubsec&
+\tt @@subsubheading\cr}}
+@end tex
+@end ifclear
+@ifinfo
+@example
+@group
+ @r{No new pages}
+@r{Numbered} @r{Unnumbered} @r{Lettered and numbered} @r{Unnumbered}
+@r{In contents} @r{In contents} @r{In contents} @r{Not in contents}
+
+ @@top @@majorheading
+@@chapter @@unnumbered @@appendix @@chapheading
+@@section @@unnumberedsec @@appendixsec @@heading
+@@subsection @@unnumberedsubsec @@appendixsubsec @@subheading
+@@subsubsection @@unnumberedsubsubsec @@appendixsubsubsec @@subsubheading
+@end group
+@end example
+@end ifinfo
+
+@c Cannot line up columns properly inside of an example because of roman
+@c proportional fonts.
+@ignore
+@ifset smallbook
+@iftex
+@smallexample
+@group
+ @r{No new pages}
+@r{Numbered} @r{Unnumbered} @r{Lettered and numbered} @r{Unnumbered}
+@r{In contents} @r{In contents} @r{In contents} @r{Not in contents}
+
+ @@top @@majorheading
+@@chapter @@unnumbered @@appendix @@chapheading
+@@section @@unnumberedsec @@appendixsec @@heading
+@@subsection @@unnumberedsubsec @@appendixsubsec @@subheading
+@@subsubsection @@unnumberedsubsubsec @@appendixsubsubsec @@subsubheading
+@end group
+@end smallexample
+@end iftex
+@end ifset
+@ifclear smallbook
+@iftex
+@smallexample
+@group
+ @r{No new pages}
+@r{Numbered} @r{Unnumbered} @r{Lettered and numbered} @r{Unnumbered}
+@r{In contents} @r{In contents} @r{In contents} @r{Not in contents}
+
+ @@top @@majorheading
+@@chapter @@unnumbered @@appendix @@chapheading
+@@section @@unnumberedsec @@appendixsec @@heading
+@@subsection @@unnumberedsubsec @@appendixsubsec @@subheading
+@@subsubsection @@unnumberedsubsubsec @@appendixsubsubsec @@subsubheading
+@end group
+@end smallexample
+@end iftex
+@end ignore
+
+@node makeinfo top, chapter, Structuring Command Types, Structuring
+@comment node-name, next, previous, up
+@section @code{@@top}
+
+The @code{@@top} command is a special sectioning command that you use
+only after an @code{@@node Top} line at the beginning of a Texinfo file.
+The @code{@@top} command tells the @code{makeinfo} formatter
+which node is the `Top'
+node. It has the same typesetting effect as @code{@@unnumbered}
+(@pxref{unnumbered & appendix, , @code{@@unnumbered}, @code{@@appendix}}).
+For detailed information, see
+@ref{makeinfo top command, , The @code{@@top} Command}.@refill
+
+@node chapter, unnumbered & appendix, makeinfo top, Structuring
+@comment node-name, next, previous, up
+@section @code{@@chapter}
+@findex chapter
+
+@code{@@chapter} identifies a chapter in the document. Write the
+command at the beginning of a line and follow it on the same line by
+the title of the chapter.@refill
+
+For example, this chapter in this manual is entitled ``Chapter
+Structuring''; the @code{@@chapter} line looks like this:@refill
+
+@example
+@@chapter Chapter Structuring
+@end example
+
+In @TeX{}, the @code{@@chapter} command creates a chapter in the
+document, specifying the chapter title. The chapter is numbered
+automatically.@refill
+
+In Info, the @code{@@chapter} command causes the title to appear on a
+line by itself, with a line of asterisks inserted underneath. Thus,
+in Info, the above example produces the following output:@refill
+
+@example
+Chapter Structuring
+*******************
+@end example
+
+@findex centerchap
+Texinfo also provides a command @code{@@centerchap}, which is analogous
+to @code{@@unnumbered}, but centers its argument in the printed output.
+This kind of stylistic choice is not usually offered by Texinfo.
+@c but the Hacker's Dictionary wanted it ...
+
+
+@node unnumbered & appendix, majorheading & chapheading, chapter, Structuring
+@comment node-name, next, previous, up
+@section @code{@@unnumbered}, @code{@@appendix}
+@findex unnumbered
+@findex appendix
+
+Use the @code{@@unnumbered} command to create a chapter that appears
+in a printed manual without chapter numbers of any kind. Use the
+@code{@@appendix} command to create an appendix in a printed manual
+that is labelled by letter instead of by number.@refill
+
+For Info file output, the @code{@@unnumbered} and @code{@@appendix}
+commands are equivalent to @code{@@chapter}: the title is printed on a
+line by itself with a line of asterisks underneath. (@xref{chapter, ,
+@code{@@chapter}}.)@refill
+
+To create an appendix or an unnumbered chapter, write an
+@code{@@appendix} or @code{@@unnumbered} command at the beginning of a
+line and follow it on the same line by the title, as you would if you
+were creating a chapter.@refill
+
+
+@node majorheading & chapheading, section, unnumbered & appendix, Structuring
+@section @code{@@majorheading}, @code{@@chapheading}
+@findex majorheading
+@findex chapheading
+
+The @code{@@majorheading} and @code{@@chapheading} commands put
+chapter-like headings in the body of a document.@refill
+
+However, neither command causes @TeX{} to produce a numbered heading
+or an entry in the table of contents; and neither command causes
+@TeX{} to start a new page in a printed manual.@refill
+
+In @TeX{}, an @code{@@majorheading} command generates a larger vertical
+whitespace before the heading than an @code{@@chapheading} command but
+is otherwise the same.@refill
+
+In Info,
+the @code{@@majorheading} and
+@code{@@chapheading} commands are equivalent to
+@code{@@chapter}: the title is printed on a line by itself with a line
+of asterisks underneath. (@xref{chapter, , @code{@@chapter}}.)@refill
+
+@node section, unnumberedsec appendixsec heading, majorheading & chapheading, Structuring
+@comment node-name, next, previous, up
+@section @code{@@section}
+@findex section
+
+In a printed manual, an @code{@@section} command identifies a
+numbered section within a chapter. The section title appears in the
+table of contents. In Info, an @code{@@section} command provides a
+title for a segment of text, underlined with @samp{=}.@refill
+
+This section is headed with an @code{@@section} command and looks like
+this in the Texinfo file:@refill
+
+@example
+@@section @@code@{@@@@section@}
+@end example
+
+To create a section, write the @code{@@section} command at the
+beginning of a line and follow it on the same line by the section
+title.@refill
+
+Thus,
+
+@example
+@@section This is a section
+@end example
+
+@noindent
+produces
+
+@example
+@group
+This is a section
+=================
+@end group
+@end example
+
+@noindent
+in Info.
+
+@node unnumberedsec appendixsec heading, subsection, section, Structuring
+@comment node-name, next, previous, up
+@section @code{@@unnumberedsec}, @code{@@appendixsec}, @code{@@heading}
+@findex unnumberedsec
+@findex appendixsec
+@findex heading
+
+The @code{@@unnumberedsec}, @code{@@appendixsec}, and @code{@@heading}
+commands are, respectively, the unnumbered, appendix-like, and
+heading-like equivalents of the @code{@@section} command.
+(@xref{section, , @code{@@section}}.)@refill
+
+@table @code
+@item @@unnumberedsec
+The @code{@@unnumberedsec} command may be used within an
+unnumbered chapter or within a regular chapter or appendix to
+provide an unnumbered section.@refill
+
+@item @@appendixsec
+@itemx @@appendixsection
+@code{@@appendixsection} is a longer spelling of the
+@code{@@appendixsec} command; the two are synonymous.@refill
+@findex appendixsection
+
+Conventionally, the @code{@@appendixsec} or @code{@@appendixsection}
+command is used only within appendices.@refill
+
+@item @@heading
+You may use the @code{@@heading} command anywhere you wish for a
+section-style heading that will not appear in the table of contents.@refill
+@end table
+
+@node subsection, unnumberedsubsec appendixsubsec subheading, unnumberedsec appendixsec heading, Structuring
+@comment node-name, next, previous, up
+@section The @code{@@subsection} Command
+@findex subsection
+
+Subsections are to sections as sections are to chapters.
+(@xref{section, , @code{@@section}}.) In Info, subsection titles are
+underlined with @samp{-}. For example,@refill
+
+@example
+@@subsection This is a subsection
+@end example
+
+@noindent
+produces
+
+@example
+@group
+This is a subsection
+--------------------
+@end group
+@end example
+
+In a printed manual, subsections are listed in the table of contents
+and are numbered three levels deep.@refill
+
+@node unnumberedsubsec appendixsubsec subheading, subsubsection, subsection, Structuring
+@comment node-name, next, previous, up
+@section The @code{@@subsection}-like Commands
+@cindex Subsection-like commands
+@findex unnumberedsubsec
+@findex appendixsubsec
+@findex subheading
+
+The @code{@@unnumberedsubsec}, @code{@@appendixsubsec}, and
+@code{@@subheading} commands are, respectively, the unnumbered,
+appendix-like, and heading-like equivalents of the @code{@@subsection}
+command. (@xref{subsection, , @code{@@subsection}}.)@refill
+
+In Info, the @code{@@subsection}-like commands generate a title
+underlined with hyphens. In a printed manual, an @code{@@subheading}
+command produces a heading like that of a subsection except that it is
+not numbered and does not appear in the table of contents. Similarly,
+an @code{@@unnumberedsubsec} command produces an unnumbered heading like
+that of a subsection and an @code{@@appendixsubsec} command produces a
+subsection-like heading labelled with a letter and numbers; both of
+these commands produce headings that appear in the table of
+contents.@refill
+
+@node subsubsection, Raise/lower sections, unnumberedsubsec appendixsubsec subheading, Structuring
+@comment node-name, next, previous, up
+@section The `subsub' Commands
+@cindex Subsub commands
+@findex subsubsection
+@findex unnumberedsubsubsec
+@findex appendixsubsubsec
+@findex subsubheading
+
+The fourth and lowest level sectioning commands in Texinfo are the
+`subsub' commands. They are:@refill
+
+@table @code
+@item @@subsubsection
+Subsubsections are to subsections as subsections are to sections.
+(@xref{subsection, , @code{@@subsection}}.) In a printed manual,
+subsubsection titles appear in the table of contents and are numbered
+four levels deep.@refill
+
+@item @@unnumberedsubsubsec
+Unnumbered subsubsection titles appear in the table of contents of a
+printed manual, but lack numbers. Otherwise, unnumbered
+subsubsections are the same as subsubsections. In Info, unnumbered
+subsubsections look exactly like ordinary subsubsections.@refill
+
+@item @@appendixsubsubsec
+Conventionally, appendix commands are used only for appendices and are
+lettered and numbered appropriately in a printed manual. They also
+appear in the table of contents. In Info, appendix subsubsections look
+exactly like ordinary subsubsections.@refill
+
+@item @@subsubheading
+The @code{@@subsubheading} command may be used anywhere that you need
+a small heading that will not appear in the table of contents. In
+Info, subsubheadings look exactly like ordinary subsubsection
+headings.@refill
+@end table
+
+In Info, `subsub' titles are underlined with periods.
+For example,@refill
+
+@example
+@@subsubsection This is a subsubsection
+@end example
+
+@noindent
+produces
+
+@example
+@group
+This is a subsubsection
+.......................
+@end group
+@end example
+
+@node Raise/lower sections, , subsubsection, Structuring
+@comment node-name, next, previous, up
+@section @code{@@raisesections} and @code{@@lowersections}
+@findex raisesections
+@findex lowersections
+@cindex Raising and lowering sections
+@cindex Sections, raising and lowering
+
+The @code{@@raisesections} and @code{@@lowersections} commands raise and
+lower the hierarchical level of chapters, sections, subsections and the
+like. The @code{@@raisesections} command changes sections to chapters,
+subsections to sections, and so on. The @code{@@lowersections} command
+changes chapters to sections, sections to subsections, and so on.
+
+An @code{@@lowersections} command is useful if you wish to include text
+that is written as an outer or standalone Texinfo file in another
+Texinfo file as an inner, included file. If you write the command at
+the beginning of the file, all your @code{@@chapter} commands are
+formatted as if they were @code{@@section} commands, all your
+@code{@@section} command are formatted as if they were
+@code{@@subsection} commands, and so on.
+
+@need 1000
+@code{@@raisesections} raises a command one level in the chapter
+structuring hierarchy:@refill
+
+@example
+@group
+ @r{Change} @r{To}
+
+@@subsection @@section,
+@@section @@chapter,
+@@heading @@chapheading,
+ @r{etc.}
+@end group
+@end example
+
+@need 1000
+@code{@@lowersections} lowers a command one level in the chapter
+structuring hierarchy:@refill
+
+@example
+@group
+ @r{Change} @r{To}
+
+@@chapter @@section,
+@@subsection @@subsubsection,
+@@heading @@subheading,
+ @r{etc.}
+@end group
+@end example
+
+An @code{@@raisesections} or @code{@@lowersections} command changes only
+those structuring commands that follow the command in the Texinfo file.
+Write an @code{@@raisesections} or @code{@@lowersections} command on a
+line of its own.
+
+An @code{@@lowersections} command cancels an @code{@@raisesections}
+command, and vice versa.
+
+Repeated use of the commands continue to raise or lower the hierarchical
+level a step at a time.
+
+An attempt to raise above `chapters' reproduces chapter commands; an
+attempt to lower below `subsubsections' reproduces subsubsection
+commands.
+
+@node Nodes, Menus, Structuring, Top
+@comment node-name, next, previous, up
+@chapter Nodes
+
+@dfn{Nodes} are the primary segments of a Texinfo file. They do not
+themselves impose a hierarchic or any other kind of structure on a file.
+Nodes contain @dfn{node pointers} that name other nodes, and can contain
+@dfn{menus} which are lists of nodes. In Info, the movement commands
+can carry you to a pointed-to node or to a node listed in a menu. Node
+pointers and menus provide structure for Info files just as chapters,
+sections, subsections, and the like, provide structure for printed
+books.@refill
+
+@menu
+* Two Paths:: Different commands to structure
+ Info output and printed output.
+* Node Menu Illustration:: A diagram, and sample nodes and menus.
+* node:: How to write a node, in detail.
+* makeinfo Pointer Creation:: How to create node pointers with @code{makeinfo}.
+@end menu
+
+@node Two Paths, Node Menu Illustration, Nodes, Nodes
+@ifinfo
+@heading Two Paths
+@end ifinfo
+
+The node and menu commands and the chapter structuring commands are
+independent of each other:
+
+@itemize @bullet
+@item
+In Info, node and menu commands provide structure. The chapter
+structuring commands generate headings with different kinds of
+underlining---asterisks for chapters, hyphens for sections, and so on;
+they do nothing else.@refill
+
+@item
+In @TeX{}, the chapter structuring commands generate chapter and section
+numbers and tables of contents. The node and menu commands provide
+information for cross references; they do nothing else.@refill
+@end itemize
+
+You can use node pointers and menus to structure an Info file any way
+you want; and you can write a Texinfo file so that its Info output has a
+different structure than its printed output. However, most Texinfo
+files are written such that the structure for the Info output
+corresponds to the structure for the printed output. It is not
+convenient to do otherwise.@refill
+
+Generally, printed output is structured in a tree-like hierarchy in
+which the chapters are the major limbs from which the sections branch
+out. Similarly, node pointers and menus are organized to create a
+matching structure in the Info output.@refill
+
+@node Node Menu Illustration, node, Two Paths, Nodes
+@comment node-name, next, previous, up
+@section Node and Menu Illustration
+
+Here is a copy of the diagram shown earlier that illustrates a Texinfo
+file with three chapters, each of which contains two sections.@refill
+
+Note that the ``root'' is at the top of the diagram and the ``leaves''
+are at the bottom. This is how such a diagram is drawn conventionally;
+it illustrates an upside-down tree. For this reason, the root node is
+called the `Top' node, and `Up' node pointers carry you closer to the
+root.@refill
+
+@example
+@group
+ Top
+ |
+ -------------------------------------
+ | | |
+ Chapter 1 Chapter 2 Chapter 3
+ | | |
+ -------- -------- --------
+ | | | | | |
+ Section Section Section Section Section Section
+ 1.1 1.2 2.1 2.2 3.1 3.2
+
+@end group
+@end example
+
+Write the beginning of the node for Chapter 2 like this:@refill
+
+@example
+@group
+@@node Chapter 2, Chapter 3, Chapter 1, top
+@@comment node-name, next, previous, up
+@end group
+@end example
+
+@noindent
+This @code{@@node} line says that the name of this node is ``Chapter 2'', the
+name of the `Next' node is ``Chapter 3'', the name of the `Previous'
+node is ``Chapter 1'', and the name of the `Up' node is ``Top''.
+
+@quotation
+@strong{Please Note:} `Next' refers to the next node at the same
+hierarchical level in the manual, not necessarily to the next node
+within the Texinfo file. In the Texinfo file, the subsequent node may
+be at a lower level---a section-level node may follow a chapter-level
+node, and a subsection-level node may follow a section-level node.
+`Next' and `Previous' refer to nodes at the @emph{same} hierarchical
+level. (The `Top' node contains the exception to this rule. Since the
+`Top' node is the only node at that level, `Next' refers to the first
+following node, which is almost always a chapter or chapter-level
+node.)@refill
+@end quotation
+
+To go to Sections 2.1 and 2.2 using Info, you need a menu inside Chapter
+2. (@xref{Menus}.) You would write the menu just
+before the beginning of Section 2.1, like this:@refill
+
+@example
+@group
+ @@menu
+ * Sect. 2.1:: Description of this section.
+ * Sect. 2.2::
+ @@end menu
+@end group
+@end example
+
+Write the node for Sect. 2.1 like this:@refill
+
+@example
+@group
+ @@node Sect. 2.1, Sect. 2.2, Chapter 2, Chapter 2
+ @@comment node-name, next, previous, up
+@end group
+@end example
+
+In Info format, the `Next' and `Previous' pointers of a node usually
+lead to other nodes at the same level---from chapter to chapter or from
+section to section (sometimes, as shown, the `Previous' pointer points
+up); an `Up' pointer usually leads to a node at the level above (closer
+to the `Top' node); and a `Menu' leads to nodes at a level below (closer
+to `leaves'). (A cross reference can point to a node at any level;
+see @ref{Cross References}.)@refill
+
+Usually, an @code{@@node} command and a chapter structuring command are
+used in sequence, along with indexing commands. (You may follow the
+@code{@@node} line with a comment line that reminds you which pointer is
+which.)@refill
+
+Here is the beginning of the chapter in this manual called ``Ending a
+Texinfo File''. This shows an @code{@@node} line followed by a comment
+line, an @code{@@chapter} line, and then by indexing lines.@refill
+
+@example
+@group
+@@node Ending a File, Structuring, Beginning a File, Top
+@@comment node-name, next, previous, up
+@@chapter Ending a Texinfo File
+@@cindex Ending a Texinfo file
+@@cindex Texinfo file ending
+@@cindex File ending
+@end group
+@end example
+
+@node node, makeinfo Pointer Creation, Node Menu Illustration, Nodes
+@comment node-name, next, previous, up
+@section The @code{@@node} Command
+
+@cindex Node, defined
+A @dfn{node} is a segment of text that begins at an @code{@@node}
+command and continues until the next @code{@@node} command. The
+definition of node is different from that for chapter or section. A
+chapter may contain sections and a section may contain subsections;
+but a node cannot contain subnodes; the text of a node continues only
+until the next @code{@@node} command in the file. A node usually
+contains only one chapter structuring command, the one that follows
+the @code{@@node} line. On the other hand, in printed output nodes
+are used only for cross references, so a chapter or section may
+contain any number of nodes. Indeed, a chapter usually contains
+several nodes, one for each section, subsection, and
+subsubsection.@refill
+
+To create a node, write an @code{@@node} command at the beginning of a
+line, and follow it with four arguments, separated by commas, on the
+rest of the same line. These arguments are the name of the node, and
+the names of the `Next', `Previous', and `Up' pointers, in that order.
+You may insert spaces before each pointer if you wish; the spaces are
+ignored. You must write the name of the node, and the names of the
+`Next', `Previous', and `Up' pointers, all on the same line. Otherwise,
+the formatters fail. (@inforef{Top, info, info}, for more information
+about nodes in Info.)@refill
+
+Usually, you write one of the chapter-structuring command lines
+immediately after an @code{@@node} line---for example, an
+@code{@@section} or @code{@@subsection} line. (@xref{Structuring
+Command Types, , Types of Structuring Command}.)@refill
+
+@quotation
+@strong{Please note:} The GNU Emacs Texinfo mode updating commands work
+only with Texinfo files in which @code{@@node} lines are followed by chapter
+structuring lines. @xref{Updating Requirements}.@refill
+@end quotation
+
+@TeX{} uses @code{@@node} lines to identify the names to use for cross
+references. For this reason, you must write @code{@@node} lines in a
+Texinfo file that you intend to format for printing, even if you do not
+intend to format it for Info. (Cross references, such as the one at the
+end of this sentence, are made with @code{@@xref} and its related
+commands; see @ref{Cross References}.)@refill
+
+@menu
+* Node Names:: How to choose node and pointer names.
+* Writing a Node:: How to write an @code{@@node} line.
+* Node Line Tips:: Keep names short.
+* Node Line Requirements:: Keep names unique, without @@-commands.
+* First Node:: How to write a `Top' node.
+* makeinfo top command:: How to use the @code{@@top} command.
+* Top Node Summary:: Write a brief description for readers.
+@end menu
+
+@node Node Names, Writing a Node, node, node
+@ifinfo
+@subheading Choosing Node and Pointer Names
+@end ifinfo
+
+The name of a node identifies the node. The pointers enable
+you to reach other nodes and consist of the names of those nodes.@refill
+
+Normally, a node's `Up' pointer contains the name of the node whose menu
+mentions that node. The node's `Next' pointer contains the name of the
+node that follows that node in that menu and its `Previous' pointer
+contains the name of the node that precedes it in that menu. When a
+node's `Previous' node is the same as its `Up' node, both node pointers
+name the same node.@refill
+
+Usually, the first node of a Texinfo file is the `Top' node, and its
+`Up' and `Previous' pointers point to the @file{dir} file, which
+contains the main menu for all of Info.@refill
+
+The `Top' node itself contains the main or master menu for the manual.
+Also, it is helpful to include a brief description of the manual in the
+`Top' node. @xref{First Node}, for information on how to write the
+first node of a Texinfo file.@refill
+
+@node Writing a Node, Node Line Tips, Node Names, node
+@comment node-name, next, previous, up
+@subsection How to Write an @code{@@node} Line
+@cindex Writing an @code{@@node} line
+@cindex @code{@@node} line writing
+@cindex Node line writing
+
+The easiest way to write an @code{@@node} line is to write @code{@@node}
+at the beginning of a line and then the name of the node, like
+this:@refill
+
+@example
+@@node @var{node-name}
+@end example
+
+If you are using GNU Emacs, you can use the update node commands
+provided by Texinfo mode to insert the names of the pointers; or you
+can leave the pointers out of the Texinfo file and let @code{makeinfo}
+insert node pointers into the Info file it creates. (@xref{Texinfo
+Mode}, and @ref{makeinfo Pointer Creation}.)@refill
+
+Alternatively, you can insert the `Next', `Previous', and `Up'
+pointers yourself. If you do this, you may find it helpful to use the
+Texinfo mode keyboard command @kbd{C-c C-c n}. This command inserts
+@samp{@@node} and a comment line listing the names of the pointers in
+their proper order. The comment line helps you keep track of which
+arguments are for which pointers. This comment line is especially useful
+if you are not familiar with Texinfo.@refill
+
+The template for a node line with `Next', `Previous', and `Up' pointers
+looks like this:@refill
+
+@example
+@@node @var{node-name}, @var{next}, @var{previous}, @var{up}
+@end example
+
+If you wish, you can ignore @code{@@node} lines altogether in your first
+draft and then use the @code{texinfo-insert-node-lines} command to
+create @code{@@node} lines for you. However, we do not
+recommend this practice. It is better to name the node itself
+at the same time that you
+write a segment so you can easily make cross references. A large number
+of cross references are an especially important feature of a good Info
+file.@refill
+
+After you have inserted an @code{@@node} line, you should immediately
+write an @@-command for the chapter or section and insert its name.
+Next (and this is important!), put in several index entries. Usually,
+you will find at least two and often as many as four or five ways of
+referring to the node in the index. Use them all. This will make it
+much easier for people to find the node.@refill
+
+@node Node Line Tips, Node Line Requirements, Writing a Node, node
+@comment node-name, next, previous, up
+@subsection @code{@@node} Line Tips
+
+Here are three suggestions:
+
+@itemize @bullet
+@item
+Try to pick node names that are informative but short.@refill
+
+In the Info file, the file name, node name, and pointer names are all
+inserted on one line, which may run into the right edge of the window.
+(This does not cause a problem with Info, but is ugly.)@refill
+
+@item
+Try to pick node names that differ from each other near the beginnings
+of their names. This way, it is easy to use automatic name completion in
+Info.@refill
+
+@item
+By convention, node names are capitalized just as they would be for
+section or chapter titles---initial and significant words are
+capitalized; others are not.@refill
+@end itemize
+
+@node Node Line Requirements, First Node, Node Line Tips, node
+@comment node-name, next, previous, up
+@subsection @code{@@node} Line Requirements
+
+@cindex Node line requirements
+Here are several requirements for @code{@@node} lines:
+
+@itemize @bullet
+@cindex Unique nodename requirement
+@cindex Nodename must be unique
+@item
+All the node names for a single Info file must be unique.@refill
+
+Duplicates confuse the Info movement commands. This means, for
+example, that if you end every chapter with a summary, you must name
+each summary node differently. You cannot just call each one
+``Summary''. You may, however, duplicate the titles of chapters, sections,
+and the like. Thus you can end each chapter in a book with a section
+called ``Summary'', so long as the node names for those sections are all
+different.@refill
+
+@item
+A pointer name must be the name of a node.@refill
+
+The node to which a pointer points may come before or after the
+node containing the pointer.@refill
+
+@cindex @@-command in nodename
+@cindex Nodename, cannot contain
+@item
+You cannot use any of the Texinfo @@-commands in a node name;
+@w{@@-commands} confuse Info.@refill
+
+@need 750
+Thus, the beginning of the section called @code{@@chapter} looks like
+this:@refill
+
+@smallexample
+@group
+@@node chapter, unnumbered & appendix, makeinfo top, Structuring
+@@comment node-name, next, previous, up
+@@section @@code@{@@@@chapter@}
+@@findex chapter
+@end group
+@end smallexample
+
+@cindex Comma in nodename
+@cindex Colon in nodename
+@cindex Apostrophe in nodename
+@item
+You cannot use commas, colons, or apostrophes within a node name; these
+confuse @TeX{} or the Info formatters.@refill
+
+@need 700
+For example, the following is a section title:
+
+@smallexample
+@@code@{@@@@unnumberedsec@}, @@code@{@@@@appendixsec@}, @@code@{@@@@heading@}
+@end smallexample
+
+@noindent
+The corresponding node name is:
+
+@smallexample
+unnumberedsec appendixsec heading
+@end smallexample
+
+@cindex Case in nodename
+@item
+Case is significant.
+@end itemize
+
+@node First Node, makeinfo top command, Node Line Requirements, node
+@comment node-name, next, previous, up
+@subsection The First Node
+@cindex @samp{@r{Top}} node is first
+@cindex First node
+
+The first node of a Texinfo file is the `Top' node, except in an
+included file (@pxref{Include Files}).
+
+The `Top' node (which must be named @samp{top} or @samp{Top}) should
+have as its `Up' and `Previous' nodes the name of a node in another
+file, where there is a menu that leads to this file. Specify the file
+name in parentheses. If the file is to be installed directly in the
+Info directory file, use @samp{(dir)} as the parent of the `Top' node;
+this is short for @samp{(dir)top}, and specifies the `Top' node in the
+@file{dir} file, which contains the main menu for Info. For example,
+the @code{@@node Top} line of this manual looks like this:@refill
+
+@example
+@@node Top, Overview, (dir), (dir)
+@end example
+
+@noindent
+(You may use the Texinfo updating commands or the @code{makeinfo}
+utility to insert these `Next' and @samp{(dir)} pointers
+automatically.)@refill
+
+@xref{Install an Info File}, for more information about installing
+an Info file in the @file{info} directory.@refill
+
+The `Top' node contains the main or master menu for the document.
+
+@node makeinfo top command, Top Node Summary, First Node, node
+@comment node-name, next, previous, up
+@subsection The @code{@@top} Sectioning Command
+@findex top @r{(@@-command)}
+
+A special sectioning command, @code{@@top}, has been created for use
+with the @code{@@node Top} line. The @code{@@top} sectioning command tells
+@code{makeinfo} that it marks the `Top' node in the file. It provides
+the information that @code{makeinfo} needs to insert node
+pointers automatically. Write the @code{@@top} command at the
+beginning of the line immediately following the @code{@@node Top}
+line. Write the title on the remaining part of the same line as the
+@code{@@top} command.@refill
+
+In Info, the @code{@@top} sectioning command causes the title to appear on a
+line by itself, with a line of asterisks inserted underneath.@refill
+
+In @TeX{} and @code{texinfo-format-buffer}, the @code{@@top}
+sectioning command is merely a synonym for @code{@@unnumbered}.
+Neither of these formatters require an @code{@@top} command, and do
+nothing special with it. You can use @code{@@chapter} or
+@code{@@unnumbered} after the @code{@@node Top} line when you use
+these formatters. Also, you can use @code{@@chapter} or
+@code{@@unnumbered} when you use the Texinfo updating commands to
+create or update pointers and menus.@refill
+
+@node Top Node Summary, , makeinfo top command, node
+@subsection The `Top' Node Summary
+@cindex @samp{@r{Top}} node summary
+
+You can help readers by writing a summary in the `Top' node, after the
+@code{@@top} line, before the main or master menu. The summary should
+briefly describe the document. In Info, this summary will appear just
+before the master menu. In a printed manual, this summary will appear
+on a page of its own.@refill
+
+If you do not want the summary to appear on a page of its own in a
+printed manual, you can enclose the whole of the `Top' node, including
+the @code{@@node Top} line and the @code{@@top} sectioning command line
+or other sectioning command line between @code{@@ifinfo} and @code{@@end
+ifinfo}. This prevents any of the text from appearing in the printed
+output. (@pxref{Conditionals, , Conditionally Visible Text}). You can
+repeat the brief description from the `Top' node within @code{@@iftex}
+@dots{} @code{@@end iftex} at the beginning of the first chapter, for
+those who read the printed manual. This saves paper and may look
+neater.@refill
+
+You should write the version number of the program to which the manual
+applies in the summary. This helps the reader keep track of which
+manual is for which version of the program. If the manual changes more
+frequently than the program or is independent of it, you should also
+include an edition number for the manual. (The title page should also
+contain this information: see @ref{titlepage, ,
+@code{@@titlepage}}.)@refill
+
+@node makeinfo Pointer Creation, , node, Nodes
+@section Creating Pointers with @code{makeinfo}
+@cindex Creating pointers with @code{makeinfo}
+@cindex Pointer creation with @code{makeinfo}
+@cindex Automatic pointer creation with @code{makeinfo}
+
+The @code{makeinfo} program has a feature for automatically creating
+node pointers for a hierarchically organized file that lacks
+them.@refill
+
+When you take advantage of this feature, you do not need to write the
+`Next', `Previous', and `Up' pointers after the name of a node.
+However, you must write a sectioning command, such as @code{@@chapter}
+or @code{@@section}, on the line immediately following each truncated
+@code{@@node} line. You cannot write a comment line after a node
+line; the section line must follow it immediately.@refill
+
+In addition, you must follow the `Top' @code{@@node} line with a line beginning
+with @code{@@top} to mark the `Top' node in the file. @xref{makeinfo
+top, , @code{@@top}}.
+
+Finally, you must write the name of each node (except for the `Top'
+node) in a menu that is one or more hierarchical levels above the
+node's hierarchical level.@refill
+
+This node pointer insertion feature in @code{makeinfo} is an
+alternative to the menu and pointer creation and update commands in
+Texinfo mode. (@xref{Updating Nodes and Menus}.) It is especially
+helpful to people who do not use GNU Emacs for writing Texinfo
+documents.@refill
+
+@node Menus, Cross References, Nodes, Top
+@comment node-name, next, previous, up
+@chapter Menus
+@cindex Menus
+@findex menu
+
+@dfn{Menus} contain pointers to subordinate
+nodes.@footnote{Menus can carry you to any node, regardless
+of the hierarchical structure; even to nodes in a different
+Info file. However, the GNU Emacs Texinfo mode updating
+commands work only to create menus of subordinate nodes.
+Conventionally, cross references are used to refer to other
+nodes.} In Info, you use menus to go to such nodes. Menus
+have no effect in printed manuals and do not appear in
+them.@refill
+
+By convention, a menu is put at the end of a node since a reader who
+uses the menu may not see text that follows it.@refill
+
+@ifinfo
+A node that has a menu should @emph{not} contain much text. If you
+have a lot of text and a menu, move most of the text into a new
+subnode---all but a few lines.@refill
+@end ifinfo
+@iftex
+@emph{A node that has a menu should not contain much text.} If you
+have a lot of text and a menu, move most of the text into a new
+subnode---all but a few lines. Otherwise, a reader with a terminal
+that displays only a few lines may miss the menu and its associated
+text. As a practical matter, you should locate a menu within 20 lines
+of the beginning of the node.@refill
+@end iftex
+
+@menu
+* Menu Location:: Put a menu in a short node.
+* Writing a Menu:: What is a menu?
+* Menu Parts:: A menu entry has three parts.
+* Less Cluttered Menu Entry:: Two part menu entry.
+* Menu Example:: Two and three part menu entries.
+* Other Info Files:: How to refer to a different Info file.
+@end menu
+
+@node Menu Location, Writing a Menu, Menus, Menus
+@ifinfo
+@heading Menus Need Short Nodes
+@end ifinfo
+@cindex Menu location
+@cindex Location of menus
+@cindex Nodes for menus are short
+@cindex Short nodes for menus
+
+@ifinfo
+A reader can easily see a menu that is close to the beginning of the
+node. The node should be short. As a practical matter, you should
+locate a menu within 20 lines of the beginning of the node.
+Otherwise, a reader with a terminal that displays only a few lines may
+miss the menu and its associated text.@refill
+@end ifinfo
+
+The short text before a menu may look awkward in a printed manual. To
+avoid this, you can write a menu near the beginning of its node and
+follow the menu by an @code{@@node} line, and then an @code{@@heading}
+line located within @code{@@ifinfo} and @code{@@end ifinfo}. This way,
+the menu, @code{@@node} line, and title appear only in the Info file,
+not the printed document.@refill
+
+For example, the preceding two paragraphs follow an Info-only menu,
+@code{@@node} line, and heading, and look like this:@refill
+
+@example
+@group
+@@menu
+* Menu Location:: Put a menu in a short node.
+* Writing a Menu:: What is a menu?
+* Menu Parts:: A menu entry has three parts.
+* Less Cluttered Menu Entry:: Two part menu entry.
+* Menu Example:: Two and three part entries.
+* Other Info Files:: How to refer to a different
+ Info file.
+@@end menu
+
+@@node Menu Location, Writing a Menu, , Menus
+@@ifinfo
+@@heading Menus Need Short Nodes
+@@end ifinfo
+@end group
+@end example
+
+The Texinfo file for this document contains more than a dozen
+examples of this procedure. One is at the beginning of this chapter;
+another is at the beginning of the ``Cross References'' chapter.@refill
+
+@node Writing a Menu, Menu Parts, Menu Location, Menus
+@section Writing a Menu
+@cindex Writing a menu
+@cindex Menu writing
+
+A menu consists of an @code{@@menu} command on a line by
+itself followed by menu entry lines or menu comment lines
+and then by an @code{@@end menu} command on a line by
+itself.@refill
+
+A menu looks like this:@refill
+
+@example
+@group
+@@menu
+Larger Units of Text
+
+* Files:: All about handling files.
+* Multiples: Buffers. Multiple buffers; editing
+ several files at once.
+@@end menu
+@end group
+@end example
+
+In a menu, every line that begins with an @w{@samp{* }} is a
+@dfn{menu entry}. (Note the space after the asterisk.) A
+line that does not start with an @w{@samp{* }} may also
+appear in a menu. Such a line is not a menu entry but is a
+menu comment line that appears in the Info file. In
+the example above, the line @samp{Larger Units of Text} is a
+menu comment line; the two lines starting with @w{@samp{* }}
+are menu entries.
+
+@node Menu Parts, Less Cluttered Menu Entry, Writing a Menu, Menus
+@section The Parts of a Menu
+@cindex Parts of a menu
+@cindex Menu parts
+@cindex @code{@@menu} parts
+
+A menu entry has three parts, only the second of which is
+required:@refill
+
+@enumerate
+@item
+The menu entry name.
+
+@item
+The name of the node (required).
+
+@item
+A description of the item.
+@end enumerate
+
+The template for a menu entry looks like this:@refill
+
+@example
+* @var{menu-entry-name}: @var{node-name}. @var{description}
+@end example
+
+Follow the menu entry name with a single colon and follow the node name
+with tab, comma, period, or newline.@refill
+
+In Info, a user selects a node with the @kbd{m} (@code{Info-menu})
+command. The menu entry name is what the user types after the @kbd{m}
+command.@refill
+
+The third part of a menu entry is a descriptive phrase or
+sentence. Menu entry names and node names are often short; the
+description explains to the reader what the node is about. The
+description, which is optional, can spread over two or more lines. A
+useful description complements the node name rather than repeats
+it.@refill
+
+@node Less Cluttered Menu Entry, Menu Example, Menu Parts, Menus
+@comment node-name, next, previous, up
+@section Less Cluttered Menu Entry
+@cindex Two part menu entry
+@cindex Double-colon menu entries
+@cindex Menu entries with two colons
+@cindex Less cluttered menu entry
+@cindex Uncluttered menu entry
+
+When the menu entry name and node name are the same, you can write
+the name immediately after the asterisk and space at the beginning of
+the line and follow the name with two colons.@refill
+
+@need 800
+For example, write
+
+@example
+* Name:: @var{description}
+@end example
+
+@need 800
+@noindent
+instead of
+
+@example
+* Name: Name. @var{description}
+@end example
+
+You should use the node name for the menu entry name whenever possible,
+since it reduces visual clutter in the menu.@refill
+
+@node Menu Example, Other Info Files, Less Cluttered Menu Entry, Menus
+@comment node-name, next, previous, up
+@section A Menu Example
+@cindex Menu example
+@cindex Example menu
+
+A menu looks like this in Texinfo:@refill
+
+@example
+@group
+@@menu
+* menu entry name: Node name. A short description.
+* Node name:: This form is preferred.
+@@end menu
+@end group
+@end example
+
+@need 800
+@noindent
+This produces:
+
+@example
+@group
+* menu:
+
+* menu entry name: Node name. A short description.
+* Node name:: This form is preferred.
+@end group
+@end example
+
+@need 700
+Here is an example as you might see it in a Texinfo file:@refill
+
+@example
+@group
+@@menu
+Larger Units of Text
+
+* Files:: All about handling files.
+* Multiples: Buffers. Multiple buffers; editing
+ several files at once.
+@@end menu
+@end group
+@end example
+
+@need 800
+@noindent
+This produces:
+
+@example
+@group
+* menu:
+Larger Units of Text
+
+* Files:: All about handling files.
+* Multiples: Buffers. Multiple buffers; editing
+ several files at once.
+@end group
+@end example
+
+In this example, the menu has two entries. @samp{Files} is both a menu
+entry name and the name of the node referred to by that name.
+@samp{Multiples} is the menu entry name; it refers to the node named
+@samp{Buffers}. The line @samp{Larger Units of Text} is a comment; it
+appears in the menu, but is not an entry.@refill
+
+Since no file name is specified with either @samp{Files} or
+@samp{Buffers}, they must be the names of nodes in the same Info file
+(@pxref{Other Info Files, , Referring to Other Info Files}).@refill
+
+@node Other Info Files, , Menu Example, Menus
+@comment node-name, next, previous, up
+@section Referring to Other Info Files
+@cindex Referring to other Info files
+@cindex Nodes in other Info files
+@cindex Other Info files' nodes
+@cindex Going to other Info files' nodes
+@cindex Info; other files' nodes
+
+You can create a menu entry that enables a reader in Info to go to a
+node in another Info file by writing the file name in parentheses just
+before the node name. In this case, you should use the three-part menu
+entry format, which saves the reader from having to type the file
+name.@refill
+
+@need 800
+The format looks like this:@refill
+
+@example
+@group
+@@menu
+* @var{first-entry-name}:(@var{filename})@var{nodename}. @var{description}
+* @var{second-entry-name}:(@var{filename})@var{second-node}. @var{description}
+@@end menu
+@end group
+@end example
+
+For example, to refer directly to the @samp{Outlining} and
+@samp{Rebinding} nodes in the @cite{Emacs Manual}, you would write a
+menu like this:@refill
+
+@example
+@group
+@@menu
+* Outlining: (emacs)Outline Mode. The major mode for
+ editing outlines.
+* Rebinding: (emacs)Rebinding. How to redefine the
+ meaning of a key.
+@@end menu
+@end group
+@end example
+
+If you do not list the node name, but only name the file, then Info
+presumes that you are referring to the `Top' node.@refill
+
+The @file{dir} file that contains the main menu for Info has menu
+entries that list only file names. These take you directly to the `Top'
+nodes of each Info document. (@xref{Install an Info File}.)@refill
+
+@need 700
+For example:
+
+@example
+@group
+* Info: (info). Documentation browsing system.
+* Emacs: (emacs). The extensible, self-documenting
+ text editor.
+@end group
+@end example
+
+@noindent
+(The @file{dir} top level directory for the Info system is an Info file,
+not a Texinfo file, but a menu entry looks the same in both types of
+file.)@refill
+
+Note that the GNU Emacs Texinfo mode menu updating commands only work
+with nodes within the current buffer, so you cannot use them to create
+menus that refer to other files. You must write such menus by hand.@refill
+
+@node Cross References, Marking Text, Menus, Top
+@comment node-name, next, previous, up
+@chapter Cross References
+@cindex Making cross references
+@cindex Cross references
+@cindex References
+
+@dfn{Cross references} are used to refer the reader to other parts of the
+same or different Texinfo files. In Texinfo, nodes are the
+places to which cross references can refer.@refill
+
+@menu
+* References:: What cross references are for.
+* Cross Reference Commands:: A summary of the different commands.
+* Cross Reference Parts:: A cross reference has several parts.
+* xref:: Begin a reference with `See' @dots{}
+* Top Node Naming:: How to refer to the beginning of another file.
+* ref:: A reference for the last part of a sentence.
+* pxref:: How to write a parenthetical cross reference.
+* inforef:: How to refer to an Info-only file.
+@end menu
+
+@node References, Cross Reference Commands, Cross References, Cross References
+@ifinfo
+@heading What References Are For
+@end ifinfo
+
+Often, but not always, a printed document should be designed so that
+it can be read sequentially. People tire of flipping back and forth
+to find information that should be presented to them as they need
+it.@refill
+
+However, in any document, some information will be too detailed for
+the current context, or incidental to it; use cross references to
+provide access to such information. Also, an on-line help system or a
+reference manual is not like a novel; few read such documents in
+sequence from beginning to end. Instead, people look up what they
+need. For this reason, such creations should contain many cross
+references to help readers find other information that they may not
+have read.@refill
+
+In a printed manual, a cross reference results in a page reference,
+unless it is to another manual altogether, in which case the cross
+reference names that manual.@refill
+
+In Info, a cross reference results in an entry that you can follow using
+the Info @samp{f} command. (@inforef{Help-Adv, Some advanced Info
+commands, info}.)@refill
+
+The various cross reference commands use nodes to define cross
+reference locations. This is evident in Info, in which a cross
+reference takes you to the specified node. @TeX{} also uses nodes to
+define cross reference locations, but the action is less obvious. When
+@TeX{} generates a @sc{dvi} file, it records nodes' page numbers and
+uses the page numbers in making references. Thus, if you are writing
+a manual that will only be printed, and will not be used on-line, you
+must nonetheless write @code{@@node} lines to name the places to which
+you make cross references.@refill
+
+@need 800
+@node Cross Reference Commands, Cross Reference Parts, References, Cross References
+@comment node-name, next, previous, up
+@section Different Cross Reference Commands
+@cindex Different cross reference commands
+
+There are four different cross reference commands:@refill
+
+@table @code
+@item @@xref
+Used to start a sentence in the printed manual saying @w{`See @dots{}'}
+or an Info cross-reference saying @samp{*Note @var{name}: @var{node}.}.
+
+@item @@ref
+Used within or, more often, at the end of a sentence; same as
+@code{@@xref} for Info; produces just the reference in the printed
+manual without a preceding `See'.@refill
+
+@item @@pxref
+Used within parentheses to make a reference that suits both an Info
+file and a printed book. Starts with a lower case `see' within the
+printed manual. (@samp{p} is for `parenthesis'.)@refill
+
+@item @@inforef
+Used to make a reference to an Info file for which there is no printed
+manual.@refill
+@end table
+
+@noindent
+(The @code{@@cite} command is used to make references to books and
+manuals for which there is no corresponding Info file and, therefore,
+no node to which to point. @xref{cite, , @code{@@cite}}.)@refill
+
+@node Cross Reference Parts, xref, Cross Reference Commands, Cross References
+@comment node-name, next, previous, up
+@section Parts of a Cross Reference
+@cindex Cross reference parts
+@cindex Parts of a cross reference
+
+A cross reference command requires only one argument, which is the
+name of the node to which it refers. But a cross reference command
+may contain up to four additional arguments. By using these
+arguments, you can provide a cross reference name for Info, a topic
+description or section title for the printed output, the name of a
+different Info file, and the name of a different printed
+manual.@refill
+
+Here is a simple cross reference example:@refill
+
+@example
+@@xref@{Node name@}.
+@end example
+
+@noindent
+which produces
+
+@example
+*Note Node name::.
+@end example
+
+@noindent
+and
+
+@quotation
+See Section @var{nnn} [Node name], page @var{ppp}.
+@end quotation
+
+@need 700
+Here is an example of a full five-part cross reference:@refill
+
+@example
+@group
+@@xref@{Node name, Cross Reference Name, Particular Topic,
+info-file-name, A Printed Manual@}, for details.
+@end group
+@end example
+
+@noindent
+which produces
+
+@example
+*Note Cross Reference Name: (info-file-name)Node name,
+for details.
+@end example
+
+@noindent
+in Info and
+
+@quotation
+See section ``Particular Topic'' in @i{A Printed Manual}, for details.
+@end quotation
+
+@noindent
+in a printed book.
+
+The five possible arguments for a cross reference are:@refill
+
+@enumerate
+@item
+The node name (required). This is the node to which the
+cross reference takes you. In a printed document, the location of the
+node provides the page reference only for references within the same
+document.@refill
+
+@item
+The cross reference name for the Info reference, if it is to be different
+from the node name. If you include this argument, it argument becomes
+the first part of the cross reference. It is usually omitted.@refill
+
+@item
+A topic description or section name. Often, this is the title of the
+section. This is used as the name of the reference in the printed
+manual. If omitted, the node name is used.@refill
+
+@item
+The name of the Info file in which the reference is located, if it is
+different from the current file.@refill
+
+@item
+The name of a printed manual from a different Texinfo file.@refill
+@end enumerate
+
+The template for a full five argument cross reference looks like
+this:@refill
+
+@example
+@group
+@@xref@{@var{node-name}, @var{cross-reference-name}, @var{title-or-topic},
+@var{info-file-name}, @var{printed-manual-title}@}.
+@end group
+@end example
+
+Cross references with one, two, three, four, and five arguments are
+described separately following the description of @code{@@xref}.@refill
+
+Write a node name in a cross reference in exactly the same way as in
+the @code{@@node} line, including the same capitalization; otherwise, the
+formatters may not find the reference.@refill
+
+You can write cross reference commands within a paragraph, but note
+how Info and @TeX{} format the output of each of the various commands:
+write @code{@@xref} at the beginning of a sentence; write
+@code{@@pxref} only within parentheses, and so on.@refill
+
+@node xref, Top Node Naming, Cross Reference Parts, Cross References
+@comment node-name, next, previous, up
+@section @code{@@xref}
+@findex xref
+@cindex Cross references using @code{@@xref}
+@cindex References using @code{@@xref}
+
+The @code{@@xref} command generates a cross reference for the
+beginning of a sentence. The Info formatting commands convert it into
+an Info cross reference, which the Info @samp{f} command can use to
+bring you directly to another node. The @TeX{} typesetting commands
+convert it into a page reference, or a reference to another book or
+manual.@refill
+
+@menu
+* Reference Syntax:: What a reference looks like and requires.
+* One Argument:: @code{@@xref} with one argument.
+* Two Arguments:: @code{@@xref} with two arguments.
+* Three Arguments:: @code{@@xref} with three arguments.
+* Four and Five Arguments:: @code{@@xref} with four and five arguments.
+@end menu
+
+@node Reference Syntax, One Argument, xref, xref
+@ifinfo
+@subheading What a Reference Looks Like and Requires
+@end ifinfo
+
+Most often, an Info cross reference looks like this:@refill
+
+@example
+*Note @var{node-name}::.
+@end example
+
+@noindent
+or like this
+
+@example
+*Note @var{cross-reference-name}: @var{node-name}.
+@end example
+
+@noindent
+In @TeX{}, a cross reference looks like this:
+
+@example
+See Section @var{section-number} [@var{node-name}], page @var{page}.
+@end example
+
+@noindent
+or like this
+
+@example
+See Section @var{section-number} [@var{title-or-topic}], page @var{page}.
+@end example
+
+The @code{@@xref} command does not generate a period or comma to end
+the cross reference in either the Info file or the printed output.
+You must write that period or comma yourself; otherwise, Info will not
+recognize the end of the reference. (The @code{@@pxref} command works
+differently. @xref{pxref, , @code{@@pxref}}.)@refill
+
+@quotation
+@strong{Please note:} A period or comma @strong{must} follow the closing
+brace of an @code{@@xref}. It is required to terminate the cross
+reference. This period or comma will appear in the output, both in
+the Info file and in the printed manual.@refill
+@end quotation
+
+@code{@@xref} must refer to an Info node by name. Use @code{@@node}
+to define the node (@pxref{Writing a Node}).@refill
+
+@code{@@xref} is followed by several arguments inside braces, separated by
+commas. Whitespace before and after these commas is ignored.@refill
+
+A cross reference requires only the name of a node; but it may contain
+up to four additional arguments. Each of these variations produces a
+cross reference that looks somewhat different.@refill
+
+@quotation
+@strong{Please note:} Commas separate arguments in a cross reference;
+avoid including them in the title or other part lest the formatters
+mistake them for separators.@refill
+@end quotation
+
+@node One Argument, Two Arguments, Reference Syntax, xref
+@subsection @code{@@xref} with One Argument
+
+The simplest form of @code{@@xref} takes one argument, the name of
+another node in the same Info file. The Info formatters produce
+output that the Info readers can use to jump to the reference; @TeX{}
+produces output that specifies the page and section number for you.@refill
+
+@need 700
+@noindent
+For example,
+
+@example
+@@xref@{Tropical Storms@}.
+@end example
+
+@noindent
+produces
+
+@example
+*Note Tropical Storms::.
+@end example
+
+@noindent
+and
+
+@quotation
+See Section 3.1 [Tropical Storms], page 24.
+@end quotation
+
+@noindent
+(Note that in the preceding example the closing brace is followed by a
+period.)@refill
+
+You can write a clause after the cross reference, like this:@refill
+
+@example
+@@xref@{Tropical Storms@}, for more info.
+@end example
+
+@noindent
+which produces
+
+@example
+*Note Tropical Storms::, for more info.
+@end example
+
+@quotation
+See Section 3.1 [Tropical Storms], page 24, for more info.
+@end quotation
+
+@noindent
+(Note that in the preceding example the closing brace is followed by a
+comma, and then by the clause, which is followed by a period.)@refill
+
+@node Two Arguments, Three Arguments, One Argument, xref
+@subsection @code{@@xref} with Two Arguments
+
+With two arguments, the second is used as the name of the Info cross
+reference, while the first is still the name of the node to which the
+cross reference points.@refill
+
+@need 750
+@noindent
+The template is like this:
+
+@example
+@@xref@{@var{node-name}, @var{cross-reference-name}@}.
+@end example
+
+@need 700
+@noindent
+For example,
+
+@example
+@@xref@{Electrical Effects, Lightning@}.
+@end example
+
+@noindent
+produces:
+
+@example
+*Note Lightning: Electrical Effects.
+@end example
+
+@noindent
+and
+
+@quotation
+See Section 5.2 [Electrical Effects], page 57.
+@end quotation
+
+@noindent
+(Note that in the preceding example the closing brace is followed by a
+period; and that the node name is printed, not the cross reference name.)@refill
+
+You can write a clause after the cross reference, like this:@refill
+
+@example
+@@xref@{Electrical Effects, Lightning@}, for more info.
+@end example
+
+@noindent
+which produces
+@example
+*Note Lightning: Electrical Effects, for more info.
+@end example
+
+@noindent
+and
+
+@quotation
+See Section 5.2 [Electrical Effects], page 57, for more info.
+@end quotation
+
+@noindent
+(Note that in the preceding example the closing brace is followed by a
+comma, and then by the clause, which is followed by a period.)@refill
+
+@node Three Arguments, Four and Five Arguments, Two Arguments, xref
+@subsection @code{@@xref} with Three Arguments
+
+A third argument replaces the node name in the @TeX{} output. The third
+argument should be the name of the section in the printed output, or
+else state the topic discussed by that section. Often, you will want to
+use initial upper case letters so it will be easier to read when the
+reference is printed. Use a third argument when the node name is
+unsuitable because of syntax or meaning.@refill
+
+Remember to avoid placing a comma within the title or topic section of
+a cross reference, or within any other section. The formatters divide
+cross references into arguments according to the commas; a comma
+within a title or other section will divide it into two arguments. In
+a reference, you need to write a title such as ``Clouds, Mist, and
+Fog'' without the commas.@refill
+
+Also, remember to write a comma or period after the closing brace of a
+@code{@@xref} to terminate the cross reference. In the following
+examples, a clause follows a terminating comma.@refill
+
+
+@need 750
+@noindent
+The template is like this:
+
+@example
+@group
+@@xref@{@var{node-name}, @var{cross-reference-name}, @var{title-or-topic}@}.
+@end group
+@end example
+
+@need 700
+@noindent
+For example,
+
+@example
+@group
+@@xref@{Electrical Effects, Lightning, Thunder and Lightning@},
+for details.
+@end group
+@end example
+
+@noindent
+produces
+
+@example
+*Note Lightning: Electrical Effects, for details.
+@end example
+
+@noindent
+and
+
+@quotation
+See Section 5.2 [Thunder and Lightning], page 57, for details.
+@end quotation
+
+If a third argument is given and the second one is empty, then the
+third argument serves both. (Note how two commas, side by side, mark
+the empty second argument.)@refill
+
+@example
+@group
+@@xref@{Electrical Effects, , Thunder and Lightning@},
+for details.
+@end group
+@end example
+
+@noindent
+produces
+
+@example
+*Note Thunder and Lightning: Electrical Effects, for details.
+@end example
+
+@noindent
+and
+
+@quotation
+See Section 5.2 [Thunder and Lightning], page 57, for details.
+@end quotation
+
+As a practical matter, it is often best to write cross references with
+just the first argument if the node name and the section title are the
+same, and with the first and third arguments if the node name and title
+are different.@refill
+
+Here are several examples from @cite{The GAWK Manual}:@refill
+
+@smallexample
+@@xref@{Sample Program@}.
+@@xref@{Glossary@}.
+@@xref@{Case-sensitivity, ,Case-sensitivity in Matching@}.
+@@xref@{Close Output, , Closing Output Files and Pipes@},
+ for more information.
+@@xref@{Regexp, , Regular Expressions as Patterns@}.
+@end smallexample
+
+@node Four and Five Arguments, , Three Arguments, xref
+@subsection @code{@@xref} with Four and Five Arguments
+
+In a cross reference, a fourth argument specifies the name of another
+Info file, different from the file in which the reference appears, and
+a fifth argument specifies its title as a printed manual.@refill
+
+Remember that a comma or period must follow the closing brace of an
+@code{@@xref} command to terminate the cross reference. In the
+following examples, a clause follows a terminating comma.@refill
+
+@need 800
+@noindent
+The template is:
+
+@example
+@group
+@@xref@{@var{node-name}, @var{cross-reference-name}, @var{title-or-topic},
+@var{info-file-name}, @var{printed-manual-title}@}.
+@end group
+@end example
+
+@need 700
+@noindent
+For example,
+
+@example
+@@xref@{Electrical Effects, Lightning, Thunder and Lightning,
+weather, An Introduction to Meteorology@}, for details.
+@end example
+
+@noindent
+produces
+
+@example
+*Note Lightning: (weather)Electrical Effects, for details.
+@end example
+
+@noindent
+The name of the Info file is enclosed in parentheses and precedes
+the name of the node.
+
+@noindent
+In a printed manual, the reference looks like this:@refill
+
+@quotation
+See section ``Thunder and Lightning'' in @i{An Introduction to
+Meteorology}, for details.
+@end quotation
+
+@noindent
+The title of the printed manual is typeset in italics; and the
+reference lacks a page number since @TeX{} cannot know to which page a
+reference refers when that reference is to another manual.@refill
+
+Often, you will leave out the second argument when you use the long
+version of @code{@@xref}. In this case, the third argument, the topic
+description, will be used as the cross reference name in Info.@refill
+
+@noindent
+The template looks like this:
+
+@example
+@@xref@{@var{node-name}, , @var{title-or-topic}, @var{info-file-name},
+@var{printed-manual-title}@}, for details.
+@end example
+
+@noindent
+which produces
+
+@example
+*Note @var{title-or-topic}: (@var{info-file-name})@var{node-name}, for details.
+@end example
+
+@noindent
+and
+
+@quotation
+See section @var{title-or-topic} in @var{printed-manual-title}, for details.
+@end quotation
+
+@need 700
+@noindent
+For example,
+
+@example
+@@xref@{Electrical Effects, , Thunder and Lightning,
+weather, An Introduction to Meteorology@}, for details.
+@end example
+
+@noindent
+produces
+
+@example
+@group
+*Note Thunder and Lightning: (weather)Electrical Effects,
+for details.
+@end group
+@end example
+
+@noindent
+and
+
+@quotation
+See section ``Thunder and Lightning'' in @i{An Introduction to
+Meteorology}, for details.
+@end quotation
+
+On rare occasions, you may want to refer to another Info file that
+is within a single printed manual---when multiple Texinfo files are
+incorporated into the same @TeX{} run but make separate Info files.
+In this case, you need to specify only the fourth argument, and not
+the fifth.@refill
+
+@node Top Node Naming, ref, xref, Cross References
+@section Naming a `Top' Node
+@cindex Naming a `Top' Node in references
+@cindex @samp{@r{Top}} node naming for references
+
+In a cross reference, you must always name a node. This means that in
+order to refer to a whole manual, you must identify the `Top' node by
+writing it as the first argument to the @code{@@xref} command. (This
+is different from the way you write a menu entry; see @ref{Other Info
+Files, , Referring to Other Info Files}.) At the same time, to
+provide a meaningful section topic or title in the printed cross
+reference (instead of the word `Top'), you must write an appropriate
+entry for the third argument to the @code{@@xref} command.
+@refill
+
+@noindent
+Thus, to make a cross reference to @cite{The GNU Make Manual},
+write:@refill
+
+@example
+@@xref@{Top, , Overview, make, The GNU Make Manual@}.
+@end example
+
+@noindent
+which produces
+
+@example
+*Note Overview: (make)Top.
+@end example
+
+@noindent
+and
+
+@quotation
+See section ``Overview'' in @i{The GNU Make Manual}.
+@end quotation
+
+@noindent
+In this example, @samp{Top} is the name of the first node, and
+@samp{Overview} is the name of the first section of the manual.@refill
+@node ref, pxref, Top Node Naming, Cross References
+@comment node-name, next, previous, up
+@section @code{@@ref}
+@cindex Cross references using @code{@@ref}
+@cindex References using @code{@@ref}
+@findex ref
+
+@code{@@ref} is nearly the same as @code{@@xref} except that it does
+not generate a `See' in the printed output, just the reference itself.
+This makes it useful as the last part of a sentence.@refill
+
+@need 700
+@noindent
+For example,
+
+@example
+For more information, see @@ref@{Hurricanes@}.
+@end example
+
+@noindent
+produces
+
+@example
+For more information, see *Note Hurricanes.
+@end example
+
+@noindent
+and
+
+@quotation
+For more information, see Section 8.2 [Hurricanes], page 123.
+@end quotation
+
+The @code{@@ref} command sometimes leads writers to express themselves
+in a manner that is suitable for a printed manual but looks awkward
+in the Info format. Bear in mind that your audience will be using
+both the printed and the Info format.@refill
+
+@need 800
+@noindent
+For example,
+
+@example
+@group
+Sea surges are described in @@ref@{Hurricanes@}.
+@end group
+@end example
+
+@need 800
+@noindent
+produces
+
+@quotation
+Sea surges are described in Section 6.7 [Hurricanes], page 72.
+@end quotation
+
+@need 800
+@noindent
+in a printed document, and the following in Info:
+
+@example
+Sea surges are described in *Note Hurricanes::.
+@end example
+
+@quotation
+@strong{Caution:} You @emph{must} write a period or comma immediately
+after an @code{@@ref} command with two or more arguments. Otherwise,
+Info will not find the end of the cross reference entry and its
+attempt to follow the cross reference will fail. As a general rule,
+you should write a period or comma after every @code{@@ref} command.
+This looks best in both the printed and the Info output.@refill
+@end quotation
+
+@node pxref, inforef, ref, Cross References
+@comment node-name, next, previous, up
+@section @code{@@pxref}
+@cindex Cross references using @code{@@pxref}
+@cindex References using @code{@@pxref}
+@findex pxref
+
+The parenthetical reference command, @code{@@pxref}, is nearly the
+same as @code{@@xref}, but you use it @emph{only} inside parentheses
+and you do @emph{not} type a comma or period after the command's
+closing brace. The command differs from @code{@@xref} in two
+ways:@refill
+
+@enumerate
+@item
+@TeX{} typesets the reference for the printed manual with a lower case
+`see' rather than an upper case `See'.@refill
+
+@item
+The Info formatting commands automatically end the reference with a
+closing colon or period.@refill
+@end enumerate
+
+Because one type of formatting automatically inserts closing
+punctuation and the other does not, you should use @code{@@pxref}
+@emph{only} inside parentheses as part of another sentence. Also, you
+yourself should not insert punctuation after the reference, as you do
+with @code{@@xref}.@refill
+
+@code{@@pxref} is designed so that the output looks right and works
+right between parentheses both in printed output and in an Info file.
+In a printed manual, a closing comma or period should not follow a
+cross reference within parentheses; such punctuation is wrong. But in
+an Info file, suitable closing punctuation must follow the cross
+reference so Info can recognize its end. @code{@@pxref} spares you
+the need to use complicated methods to put a terminator into one form
+of the output and not the other.@refill
+
+@noindent
+With one argument, a parenthetical cross reference looks like
+this:@refill
+
+@example
+@dots{} storms cause flooding (@@pxref@{Hurricanes@}) @dots{}
+@end example
+
+@need 800
+@noindent
+which produces
+
+@example
+@group
+@dots{} storms cause flooding (*Note Hurricanes::) @dots{}
+@end group
+@end example
+
+@noindent
+and
+
+@quotation
+@dots{} storms cause flooding (see Section 6.7 [Hurricanes], page 72) @dots{}
+@end quotation
+
+With two arguments, a parenthetical cross reference has this
+template:@refill
+
+@example
+@dots{} (@@pxref@{@var{node-name}, @var{cross-reference-name}@}) @dots{}
+@end example
+
+@noindent
+which produces
+
+@example
+@dots{} (*Note @var{cross-reference-name}: @var{node-name}.) @dots{}
+@end example
+
+@noindent
+and
+
+@need 1500
+@quotation
+@dots{} (see Section @var{nnn} [@var{node-name}], page @var{ppp}) @dots{}
+@end quotation
+
+@code{@@pxref} can be used with up to five arguments just like
+@code{@@xref} (@pxref{xref, , @code{@@xref}}).@refill
+
+@quotation
+@strong{Please note:} Use @code{@@pxref} only as a parenthetical
+reference. Do not try to use @code{@@pxref} as a clause in a sentence.
+It will look bad in either the Info file, the printed output, or
+both.@refill
+
+Also, parenthetical cross references look best at the ends of sentences.
+Although you may write them in the middle of a sentence, that location
+breaks up the flow of text.@refill
+@end quotation
+
+@node inforef, , pxref, Cross References
+@comment node-name, next, previous, up
+@section @code{@@inforef}
+@cindex Cross references using @code{@@inforef}
+@cindex References using @code{@@inforef}
+@findex inforef
+
+@code{@@inforef} is used for cross references to Info files for which
+there are no printed manuals. Even in a printed manual,
+@code{@@inforef} generates a reference directing the user to look in
+an Info file.@refill
+
+The command takes either two or three arguments, in the following
+order:@refill
+
+@enumerate
+@item
+The node name.
+
+@item
+The cross reference name (optional).
+
+@item
+The Info file name.
+@end enumerate
+
+@noindent
+Separate the arguments with commas, as with @code{@@xref}. Also, you
+must terminate the reference with a comma or period after the
+@samp{@}}, as you do with @code{@@xref}.@refill
+
+@noindent
+The template is:
+
+@example
+@@inforef@{@var{node-name}, @var{cross-reference-name}, @var{info-file-name}@},
+@end example
+
+@need 800
+@noindent
+Thus,
+
+@example
+@group
+@@inforef@{Expert, Advanced Info commands, info@},
+for more information.
+@end group
+@end example
+
+@need 800
+@noindent
+produces
+
+@example
+@group
+*Note Advanced Info commands: (info)Expert,
+for more information.
+@end group
+@end example
+
+@need 800
+@noindent
+and
+
+@quotation
+See Info file @file{info}, node @samp{Expert}, for more information.
+@end quotation
+
+@need 800
+@noindent
+Similarly,
+
+@example
+@group
+@@inforef@{Expert, , info@}, for more information.
+@end group
+@end example
+
+@need 800
+@noindent
+produces
+
+@example
+*Note (info)Expert::, for more information.
+@end example
+
+@need 800
+@noindent
+and
+
+@quotation
+See Info file @file{info}, node @samp{Expert}, for more information.
+@end quotation
+
+The converse of @code{@@inforef} is @code{@@cite}, which is used to
+refer to printed works for which no Info form exists. @xref{cite, ,
+@code{@@cite}}.@refill
+
+@node Marking Text, Quotations and Examples, Cross References, Top
+@comment node-name, next, previous, up
+@chapter Marking Words and Phrases
+@cindex Paragraph, marking text within
+@cindex Marking words and phrases
+@cindex Words and phrases, marking them
+@cindex Marking text within a paragraph
+
+In Texinfo, you can mark words and phrases in a variety of ways.
+The Texinfo formatters use this information to determine how to
+highlight the text.
+You can specify, for example, whether a word or phrase is a
+defining occurrence, a metasyntactic variable, or a symbol used in a
+program. Also, you can emphasize text.@refill
+
+@menu
+* Indicating:: How to indicate definitions, files, etc.
+* Emphasis:: How to emphasize text.
+@end menu
+
+@node Indicating, Emphasis, Marking Text, Marking Text
+@comment node-name, next, previous, up
+@section Indicating Definitions, Commands, etc.
+@cindex Highlighting text
+@cindex Indicating commands, definitions, etc.
+
+Texinfo has commands for indicating just what kind of object a piece of
+text refers to. For example, metasyntactic variables are marked by
+@code{@@var}, and code by @code{@@code}. Since the pieces of text are
+labelled by commands that tell what kind of object they are, it is easy
+to change the way the Texinfo formatters prepare such text. (Texinfo is
+an @emph{intentional} formatting language rather than a @emph{typesetting}
+formatting language.)@refill
+
+For example, in a printed manual,
+code is usually illustrated in a typewriter font;
+@code{@@code} tells @TeX{} to typeset this text in this font. But it
+would be easy to change the way @TeX{} highlights code to use another
+font, and this change would not effect how keystroke examples are
+highlighted. If straight typesetting commands were used in the body
+of the file and you wanted to make a change, you would need to check
+every single occurrence to make sure that you were changing code and
+not something else that should not be changed.@refill
+
+@menu
+* Useful Highlighting:: Highlighting provides useful information.
+* code:: How to indicate code.
+* kbd:: How to show keyboard input.
+* key:: How to specify keys.
+* samp:: How to show a literal sequence of characters.
+* var:: How to indicate a metasyntactic variable.
+* file:: How to indicate the name of a file.
+* dfn:: How to specify a definition.
+* cite:: How to refer to a book that is not in Info.
+* url:: How to indicate a world wide web reference.
+* email:: How to indicate an electronic mail address.
+@end menu
+
+@node Useful Highlighting, code, Indicating, Indicating
+@ifinfo
+@subheading Highlighting Commands are Useful
+@end ifinfo
+
+The highlighting commands can be used to generate useful information
+from the file, such as lists of functions or file names. It is
+possible, for example, to write a program in Emacs Lisp (or a keyboard
+macro) to insert an index entry after every paragraph that contains
+words or phrases marked by a specified command. You could do this to
+construct an index of functions if you had not already made the
+entries.@refill
+
+The commands serve a variety of purposes:@refill
+
+@table @code
+@item @@code@{@var{sample-code}@}
+Indicate text that is a literal example of a piece of a program.@refill
+
+@item @@kbd@{@var{keyboard-characters}@}
+Indicate keyboard input.@refill
+
+@item @@key@{@var{key-name}@}
+Indicate the conventional name for a key on a keyboard.@refill
+
+@item @@samp@{@var{text}@}
+Indicate text that is a literal example of a sequence of characters.@refill
+
+@item @@var@{@var{metasyntactic-variable}@}
+Indicate a metasyntactic variable.@refill
+
+@item @@url@{@var{uniform-resource-locator}@}
+Indicate a uniform resource locator for the World Wide Web.
+
+@item @@file@{@var{file-name}@}
+Indicate the name of a file.@refill
+
+@item @@email@{@var{email-address}@}
+Indicate an electronic mail address.
+
+@item @@dfn@{@var{term}@}
+Indicate the introductory or defining use of a term.@refill
+
+@item @@cite@{@var{reference}@}
+Indicate the name of a book.@refill
+
+@ignore
+@item @@ctrl@{@var{ctrl-char}@}
+Use for an @sc{ascii} control character.@refill
+@end ignore
+@end table
+
+@node code, kbd, Useful Highlighting, Indicating
+@comment node-name, next, previous, up
+@subsection @code{@@code}@{@var{sample-code}@}
+@findex code
+
+Use the @code{@@code} command to indicate text that is a piece of a
+program and which consists of entire syntactic tokens. Enclose the
+text in braces.@refill
+
+Thus, you should use @code{@@code} for an expression in a program, for
+the name of a variable or function used in a program, or for a
+keyword. Also, you should use @code{@@code} for the name of a
+program, such as @code{diff}, that is a name used in the machine. (You
+should write the name of a program in the ordinary text font if you
+regard it as a new English word, such as `Emacs' or `Bison'.)@refill
+
+Use @code{@@code} for environment variables such as @code{TEXINPUTS},
+and other variables.@refill
+
+Use @code{@@code} for command names in command languages that
+resemble programming languages, such as Texinfo or the shell.
+For example, @code{@@code} and @code{@@samp} are produced by writing
+@samp{@@code@{@@@@code@}} and @samp{@@code@{@@@@samp@}} in the Texinfo
+source, respectively.@refill
+
+Note, however, that you should not use @code{@@code} for shell options
+such as @samp{-c} when such options stand alone. (Use @code{@@samp}.)
+Also, an entire shell command often looks better if written using
+@code{@@samp} rather than @code{@@code}. In this case, the rule is to
+choose the more pleasing format.@refill
+
+It is incorrect to alter the case of a word inside an @code{@@code}
+command when it appears at the beginning of a sentence. Most computer
+languages are case sensitive. In C, for example, @code{Printf} is
+different from the identifier @code{printf}, and most likely is a
+misspelling of it. Even in languages which are not case sensitive, it
+is confusing to a human reader to see identifiers spelled in different
+ways. Pick one spelling and always use that. If you do not want to
+start a sentence with a command written all in lower case, you should
+rearrange the sentence.@refill
+
+Do not use the @code{@@code} command for a string of characters shorter
+than a syntactic token. If you are writing about @samp{TEXINPU}, which
+is just a part of the name for the @code{TEXINPUTS} environment
+variable, you should use @code{@@samp}.@refill
+
+In particular, you should not use the @code{@@code} command when writing
+about the characters used in a token; do not, for example, use
+@code{@@code} when you are explaining what letters or printable symbols
+can be used in the names of functions. (Use @code{@@samp}.) Also, you
+should not use @code{@@code} to mark text that is considered input to
+programs unless the input is written in a language that is like a
+programming language. For example, you should not use @code{@@code} for
+the keystroke commands of GNU Emacs (use @code{@@kbd} instead) although
+you may use @code{@@code} for the names of the Emacs Lisp functions that
+the keystroke commands invoke.@refill
+
+In the printed manual, @code{@@code} causes @TeX{} to typeset the
+argument in a typewriter face. In the Info file, it causes the Info
+formatting commands to use single quotation marks around the text.
+
+@need 700
+For example,
+
+@example
+Use @@code@{diff@} to compare two files.
+@end example
+
+@noindent
+produces this in the printed manual:@refill
+
+@quotation
+Use @code{diff} to compare two files.
+@end quotation
+@iftex
+
+@noindent
+and this in the Info file:@refill
+
+@example
+Use `diff' to compare two files.
+@end example
+@end iftex
+
+@node kbd, key, code, Indicating
+@comment node-name, next, previous, up
+@subsection @code{@@kbd}@{@var{keyboard-characters}@}
+@findex kbd
+
+Use the @code{@@kbd} command for characters of input to be typed by
+users. For example, to refer to the characters @kbd{M-a},
+write@refill
+
+@example
+@@kbd@{M-a@}
+@end example
+
+@noindent
+and to refer to the characters @kbd{M-x shell}, write@refill
+
+@example
+@@kbd@{M-x shell@}
+@end example
+
+The @code{@@kbd} command has the same effect as @code{@@code} in Info,
+but may produce a different font in a printed manual.@refill
+
+You can embed another @@-command inside the braces of an @code{@@kbd}
+command. Here, for example, is the way to describe a command that
+would be described more verbosely as ``press an @samp{r} and then
+press the @key{RET} key'':@refill
+
+@example
+@@kbd@{r @@key@{RET@}@}
+@end example
+
+@noindent
+This produces: @kbd{r @key{RET}}
+
+You also use the @code{@@kbd} command if you are spelling out the letters
+you type; for example:@refill
+
+@example
+To give the @@code@{logout@} command,
+type the characters @@kbd@{l o g o u t @@key@{RET@}@}.
+@end example
+
+@noindent
+This produces:
+
+@quotation
+To give the @code{logout} command,
+type the characters @kbd{l o g o u t @key{RET}}.
+@end quotation
+
+(Also, this example shows that you can add spaces for clarity. If you
+really want to mention a space character as one of the characters of
+input, write @kbd{@@key@{SPC@}} for it.)@refill
+
+@node key, samp, kbd, Indicating
+@comment node-name, next, previous, up
+@subsection @code{@@key}@{@var{key-name}@}
+@findex key
+
+Use the @code{@@key} command for the conventional name for a key on a
+keyboard, as in:@refill
+
+@example
+@@key@{RET@}
+@end example
+
+You can use the @code{@@key} command within the argument of an
+@code{@@kbd} command when the sequence of characters to be typed
+includes one or more keys that are described by name.@refill
+
+@need 700
+For example, to produce @kbd{C-x @key{ESC}} you would type:@refill
+
+@example
+@@kbd@{C-x @@key@{ESC@}@}
+@end example
+
+Here is a list of the recommended names for keys:
+@cindex Recommended names for keys
+@cindex Keys, recommended names
+@cindex Names recommended for keys
+@cindex Abbreviations for keys
+
+@quotation
+@table @t
+@item SPC
+Space
+@item RET
+Return
+@item LFD
+Linefeed (however, since most keyboards nowadays do not have a Linefeed key,
+it might be better to call this character @kbd{C-j}.
+@item TAB
+Tab
+@item BS
+Backspace
+@item ESC
+Escape
+@item DEL
+Delete
+@item SHIFT
+Shift
+@item CTRL
+Control
+@item META
+Meta
+@end table
+@end quotation
+
+@cindex META key
+There are subtleties to handling words like `meta' or `ctrl' that are
+names of shift keys. When mentioning a character in which the shift key
+is used, such as @kbd{Meta-a}, use the @code{@@kbd} command alone; do
+not use the @code{@@key} command; but when you are referring to the
+shift key in isolation, use the @code{@@key} command. For example,
+write @samp{@@kbd@{Meta-a@}} to produce @kbd{Meta-a} and
+@samp{@@key@{META@}} to produce @key{META}.
+
+@c I don't think this is a good explanation.
+@c I think it will puzzle readers more than it clarifies matters. -- rms.
+@c In other words, use @code{@@kbd} for what you do, and use @code{@@key}
+@c for what you talk about: ``Press @code{@@kbd@{M-a@}} to move point to
+@c the beginning of the sentence. The @code{@@key@{META@}} key is often in
+@c the lower left of the keyboard.''@refill
+
+@node samp, var, key, Indicating
+@comment node-name, next, previous, up
+@subsection @code{@@samp}@{@var{text}@}
+@findex samp
+
+Use the @code{@@samp} command to indicate text that is a literal example
+or `sample' of a sequence of characters in a file, string, pattern, etc.
+Enclose the text in braces. The argument appears within single
+quotation marks in both the Info file and the printed manual; in
+addition, it is printed in a fixed-width font.@refill
+
+@example
+To match @@samp@{foo@} at the end of the line,
+use the regexp @@samp@{foo$@}.
+@end example
+
+@noindent
+produces
+
+@quotation
+To match @samp{foo} at the end of the line, use the regexp
+@samp{foo$}.@refill
+@end quotation
+
+Any time you are referring to single characters, you should use
+@code{@@samp} unless @code{@@kbd} is more appropriate. Use
+@code{@@samp} for the names of command-line options. Also, you may use
+@code{@@samp} for entire statements in C and for entire shell
+commands---in this case, @code{@@samp} often looks better than
+@code{@@code}. Basically, @code{@@samp} is a catchall for whatever is
+not covered by @code{@@code}, @code{@@kbd}, or @code{@@key}.@refill
+
+Only include punctuation marks within braces if they are part of the
+string you are specifying. Write punctuation marks outside the braces
+if those punctuation marks are part of the English text that surrounds
+the string. In the following sentence, for example, the commas and
+period are outside of the braces:@refill
+
+@example
+@group
+In English, the vowels are @@samp@{a@}, @@samp@{e@},
+@@samp@{i@}, @@samp@{o@}, @@samp@{u@}, and sometimes
+@@samp@{y@}.
+@end group
+@end example
+
+@noindent
+This produces:
+
+@quotation
+In English, the vowels are @samp{a}, @samp{e},
+@samp{i}, @samp{o}, @samp{u}, and sometimes
+@samp{y}.
+@end quotation
+
+@node var, file, samp, Indicating
+@comment node-name, next, previous, up
+@subsection @code{@@var}@{@var{metasyntactic-variable}@}
+@findex var
+
+Use the @code{@@var} command to indicate metasyntactic variables. A
+@dfn{metasyntactic variable} is something that stands for another piece of
+text. For example, you should use a metasyntactic variable in the
+documentation of a function to describe the arguments that are passed
+to that function.@refill
+
+Do not use @code{@@var} for the names of particular variables in
+programming languages. These are specific names from a program, so
+@code{@@code} is correct for them. For example, the Lisp variable
+@code{texinfo-tex-command} is not a metasyntactic variable; it is
+properly formatted using @code{@@code}.@refill
+
+The effect of @code{@@var} in the Info file is to change the case of
+the argument to all upper case; in the printed manual, to italicize it.
+
+@need 700
+For example,
+
+@example
+To delete file @@var@{filename@},
+type @@code@{rm @@var@{filename@}@}.
+@end example
+
+@noindent
+produces
+
+@quotation
+To delete file @var{filename}, type @code{rm @var{filename}}.
+@end quotation
+
+@noindent
+(Note that @code{@@var} may appear inside @code{@@code},
+@code{@@samp}, @code{@@file}, etc.)@refill
+
+Write a metasyntactic variable all in lower case without spaces, and
+use hyphens to make it more readable. Thus, the Texinfo source for
+the illustration of how to begin a Texinfo manual looks like
+this:@refill
+
+@example
+@group
+\input texinfo
+@@@@setfilename @@var@{info-file-name@}
+@@@@settitle @@var@{name-of-manual@}
+@end group
+@end example
+
+@noindent
+This produces:
+
+@example
+@group
+\input texinfo
+@@setfilename @var{info-file-name}
+@@settitle @var{name-of-manual}
+@end group
+@end example
+
+In some documentation styles, metasyntactic variables are shown with
+angle brackets, for example:@refill
+
+@example
+@dots{}, type rm <filename>
+@end example
+
+@noindent
+However, that is not the style that Texinfo uses. (You can, of
+course, modify the sources to @TeX{} and the Info formatting commands
+to output the @code{<@dots{}>} format if you wish.)@refill
+
+@node file, dfn, var, Indicating
+@comment node-name, next, previous, up
+@subsection @code{@@file}@{@var{file-name}@}
+@findex file
+
+Use the @code{@@file} command to indicate text that is the name of a
+file, buffer, or directory, or is the name of a node in Info. You can
+also use the command for file name suffixes. Do not use @code{@@file}
+for symbols in a programming language; use @code{@@code}.
+
+Currently, @code{@@file} is equivalent to @code{@@samp} in its effects.
+For example,@refill
+
+@example
+The @@file@{.el@} files are in
+the @@file@{/usr/local/emacs/lisp@} directory.
+@end example
+
+@noindent
+produces
+
+@quotation
+The @file{.el} files are in
+the @file{/usr/local/emacs/lisp} directory.
+@end quotation
+
+@node dfn, cite, file, Indicating
+@comment node-name, next, previous, up
+@subsection @code{@@dfn}@{@var{term}@}
+@findex dfn
+
+Use the @code{@@dfn} command to identify the introductory or defining
+use of a technical term. Use the command only in passages whose
+purpose is to introduce a term which will be used again or which the
+reader ought to know. Mere passing mention of a term for the first
+time does not deserve @code{@@dfn}. The command generates italics in
+the printed manual, and double quotation marks in the Info file. For
+example:@refill
+
+@example
+Getting rid of a file is called @@dfn@{deleting@} it.
+@end example
+
+@noindent
+produces
+
+@quotation
+Getting rid of a file is called @dfn{deleting} it.
+@end quotation
+
+As a general rule, a sentence containing the defining occurrence of a
+term should be a definition of the term. The sentence does not need
+to say explicitly that it is a definition, but it should contain the
+information of a definition---it should make the meaning clear.
+
+@node cite, url, dfn, Indicating
+@comment node-name, next, previous, up
+@subsection @code{@@cite}@{@var{reference}@}
+@findex cite
+
+Use the @code{@@cite} command for the name of a book that lacks a
+companion Info file. The command produces italics in the printed
+manual, and quotation marks in the Info file.@refill
+
+(If a book is written in Texinfo, it is better to use a cross reference
+command since a reader can easily follow such a reference in Info.
+@xref{xref, , @code{@@xref}}.)@refill
+
+@ignore
+@c node ctrl, , cite, Indicating
+@comment node-name, next, previous, up
+@c subsection @code{@@ctrl}@{@var{ctrl-char}@}
+@findex ctrl
+
+The @code{@@ctrl} command is seldom used. It describes an @sc{ascii}
+control character by inserting the actual character into the Info
+file.
+
+Usually, in Texinfo, you talk what you type as keyboard entry by
+describing it with @code{@@kbd}: thus, @samp{@@kbd@{C-a@}} for
+@kbd{C-a}. Use @code{@@kbd} in this way when talking about a control
+character that is typed on the keyboard by the user. When talking
+about a control character appearing in a file or a string, do not use
+@code{@@kbd} since the control character is not typed. Also, do not
+use @samp{C-} but spell out @code{control-}, as in @samp{control-a},
+to make it easier for a reader to understand.@refill
+
+@code{@@ctrl} is an idea from the beginnings of Texinfo which may not
+really fit in to the scheme of things. But there may be times when
+you want to use the command. The pattern is
+@code{@@ctrl@{@var{ch}@}}, where @var{ch} is an @sc{ascii} character
+whose control-equivalent is wanted. For example, to specify
+@samp{control-f}, you would enter@refill
+
+@example
+@@ctrl@{f@}
+@end example
+
+@noindent
+produces
+
+@quotation
+@ctrl{f}
+@end quotation
+
+In the Info file, this generates the specified control character, output
+literally into the file. This is done so a user can copy the specified
+control character (along with whatever else he or she wants) into another
+Emacs buffer and use it. Since the `control-h',`control-i', and
+`control-j' characters are formatting characters, they should not be
+indicated with @code{@@ctrl}.@refill
+
+In a printed manual, @code{@@ctrl} generates text to describe or
+identify that control character: an uparrow followed by the character
+@var{ch}.@refill
+@end ignore
+
+@node url, email, cite, Indicating
+@subsection @code{@@url}@{@var{uniform-resource-locator}@}
+@findex url
+
+Use the @code{@@url} command to indicate a uniform resource locator on
+the World Wide Web. For example:
+
+@c Two lines because one is too long for smallbook format.
+@example
+The official GNU ftp site is
+@@url@{ftp://ftp.gnu.ai.mit.edu/pub/gnu@}.
+@end example
+
+In Info and @TeX{}, this acts like @code{@@samp}. When
+Texinfo is converted to HTML, this produces a link you can follow.
+
+@node email, , url, Indicating
+@subsection @code{@@email}@{@var{email-address}@}
+@findex email
+
+Use the @code{@@email} command to indicate an electronic mail address.
+For example:
+
+@example
+Send bug reports to @email{bug-texinfo@@prep.ai.mit.edu}.
+@end example
+
+In Info and @TeX{}, this acts like @code{@@samp}. When we have support
+for conversion of Texinfo to HTML, this will produce a link you can
+follow to bring up a mail composition window initialized with
+@var{email-address}.
+
+@node Emphasis, , Indicating, Marking Text
+@comment node-name, next, previous, up
+@section Emphasizing Text
+@cindex Emphasizing text
+
+Usually, Texinfo changes the font to mark words in the text according to
+what category the words belong to; an example is the @code{@@code} command.
+Most often, this is the best way to mark words.
+However, sometimes you will want to emphasize text without indicating a
+category. Texinfo has two commands to do this. Also, Texinfo has
+several commands that specify the font in which @TeX{} will typeset
+text. These commands have no affect on Info and only one of them,
+the @code{@@r} command, has any regular use.@refill
+
+@menu
+* emph & strong:: How to emphasize text in Texinfo.
+* Smallcaps:: How to use the small caps font.
+* Fonts:: Various font commands for printed output.
+* Customized Highlighting:: How to define highlighting commands.
+@end menu
+
+@node emph & strong, Smallcaps, Emphasis, Emphasis
+@comment node-name, next, previous, up
+@subsection @code{@@emph}@{@var{text}@} and @code{@@strong}@{@var{text}@}
+@cindex Emphasizing text, font for
+@findex emph
+@findex strong
+
+The @code{@@emph} and @code{@@strong} commands are for emphasis;
+@code{@@strong} is stronger. In printed output, @code{@@emph}
+produces @emph{italics} and @code{@@strong} produces
+@strong{bold}.@refill
+
+@need 800
+For example,
+
+@example
+@group
+@@quotation
+@@strong@{Caution:@} @@code@{rm * .[^.]*@} removes @@emph@{all@}
+files in the directory.
+@@end quotation
+@end group
+@end example
+
+@iftex
+@noindent
+produces the following in printed output:
+
+@quotation
+@strong{Caution}: @code{rm * .[^.]*} removes @emph{all}
+files in the directory.
+@end quotation
+
+@noindent
+and the following in Info:
+@end iftex
+@ifinfo
+@noindent
+produces:
+@end ifinfo
+
+@example
+ *Caution*: `rm * .[^.]*' removes *all*
+ files in the directory.
+@end example
+
+The @code{@@strong} command is seldom used except to mark what is, in
+effect, a typographical element, such as the word `Caution' in the
+preceding example.
+
+In the Info file, both @code{@@emph} and @code{@@strong} put asterisks
+around the text.@refill
+
+@quotation
+@strong{Caution:} Do not use @code{@@emph} or @code{@@strong} with the
+word @samp{Note}; Info will mistake the combination for a cross
+reference. Use a phrase such as @strong{Please note} or
+@strong{Caution} instead.@refill
+@end quotation
+
+@node Smallcaps, Fonts, emph & strong, Emphasis
+@subsection @code{@@sc}@{@var{text}@}: The Small Caps Font
+@cindex Small caps font
+@findex sc @r{(small caps font)}
+
+@iftex
+Use the @samp{@@sc} command to set text in the printed output in @sc{a
+small caps font} and set text in the Info file in upper case letters.@refill
+@end iftex
+@ifinfo
+Use the @samp{@@sc} command to set text in the printed output in a
+small caps font and set text in the Info file in upper case letters.@refill
+@end ifinfo
+
+Write the text between braces in lower case, like this:@refill
+
+@example
+The @@sc@{acm@} and @@sc@{ieee@} are technical societies.
+@end example
+
+@noindent
+This produces:
+
+@display
+The @sc{acm} and @sc{ieee} are technical societies.
+@end display
+
+@TeX{} typesets the small caps font in a manner that prevents the
+letters from `jumping out at you on the page'. This makes small caps
+text easier to read than text in all upper case. The Info formatting
+commands set all small caps text in upper case.@refill
+
+@ifinfo
+If the text between the braces of an @code{@@sc} command is upper case,
+@TeX{} typesets in full-size capitals. Use full-size capitals
+sparingly.@refill
+@end ifinfo
+@iftex
+If the text between the braces of an @code{@@sc} command is upper case,
+@TeX{} typesets in @sc{FULL-SIZE CAPITALS}. Use full-size capitals
+sparingly.@refill
+@end iftex
+
+You may also use the small caps font for a jargon word such as
+@sc{ato} (a @sc{nasa} word meaning `abort to orbit').@refill
+
+There are subtleties to using the small caps font with a jargon word
+such as @sc{cdr}, a word used in Lisp programming. In this case, you
+should use the small caps font when the word refers to the second and
+subsequent elements of a list (the @sc{cdr} of the list), but you
+should use @samp{@@code} when the word refers to the Lisp function of
+the same spelling.@refill
+
+@node Fonts, Customized Highlighting, Smallcaps, Emphasis
+@comment node-name, next, previous, up
+@subsection Fonts for Printing, Not Info
+@cindex Fonts for printing, not for Info
+@findex i @r{(italic font)}
+@findex b @r{(bold font)}
+@findex t @r{(typewriter font)}
+@findex r @r{(Roman font)}
+
+Texinfo provides four font commands that specify font changes in the
+printed manual but have no effect in the Info file. @code{@@i}
+requests @i{italic} font (in some versions of @TeX{}, a slanted font
+is used), @code{@@b} requests @b{bold} face, @code{@@t} requests the
+@t{fixed-width}, typewriter-style font used by @code{@@code}, and @code{@@r} requests a
+@r{roman} font, which is the usual font in which text is printed. All
+four commands apply to an argument that follows, surrounded by
+braces.@refill
+
+Only the @code{@@r} command has much use: in example programs, you
+can use the @code{@@r} command to convert code comments from the
+fixed-width font to a roman font. This looks better in printed
+output.@refill
+
+@need 700
+For example,
+
+@example
+@group
+@@lisp
+(+ 2 2) ; @@r@{Add two plus two.@}
+@@end lisp
+@end group
+@end example
+
+@noindent
+produces
+
+@lisp
+(+ 2 2) ; @r{Add two plus two.}
+@end lisp
+
+If possible, you should avoid using the other three font commands. If
+you need to use one, it probably indicates a gap in the Texinfo
+language.@refill
+
+@node Customized Highlighting, , Fonts, Emphasis
+@comment node-name, next, previous, up
+@subsection Customized Highlighting
+@cindex Highlighting, customized
+@cindex Customized highlighting
+
+@c I think this whole section is obsolete with the advent of macros
+@c --karl, 15sep96.
+You can use regular @TeX{} commands inside of @code{@@iftex} @dots{}
+@code{@@end iftex} to create your own customized highlighting commands
+for Texinfo. The easiest way to do this is to equate your customized
+commands with pre-existing commands, such as those for italics. Such
+new commands work only with @TeX{}.@refill
+
+@findex definfoenclose
+@cindex Enclosure command for Info
+You can use the @code{@@definfoenclose} command inside of
+@code{@@ifinfo} @dots{} @code{@@end ifinfo} to define commands for Info
+with the same names as new commands for @TeX{}.
+@code{@@definfoenclose} creates new commands for Info that mark text by
+enclosing it in strings that precede and follow the text.
+@footnote{Currently, @code{@@definfoenclose} works only with
+@code{texinfo-format-buffer} and @code{texinfo-format-region}, not with
+@code{makeinfo}.}@refill
+
+Here is how to create a new @@-command called @code{@@phoo} that causes
+@TeX{} to typeset its argument in italics and causes Info to display the
+argument between @samp{//} and @samp{\\}.@refill
+
+@need 1300
+For @TeX{}, write the following to equate the @code{@@phoo} command with
+the existing @code{@@i} italics command:@refill
+
+@example
+@group
+@@iftex
+@@global@@let@@phoo=@@i
+@@end iftex
+@end group
+@end example
+
+@noindent
+This defines @code{@@phoo} as a command that causes @TeX{} to typeset
+the argument to @code{@@phoo} in italics. @code{@@global@@let} tells
+@TeX{} to equate the next argument with the argument that follows the
+equals sign.
+
+@need 1300
+For Info, write the following to tell the Info formatters to enclose the
+argument between @samp{//} and @samp{\\}:
+
+@example
+@group
+@@ifinfo
+@@definfoenclose phoo, //, \\
+@@end ifinfo
+@end group
+@end example
+
+@noindent
+Write the @code{@@definfoenclose} command on a line and follow it with
+three arguments separated by commas (commas are used as separators in an
+@code{@@node} line in the same way).@refill
+
+@itemize @bullet
+@item
+The first argument to @code{@@definfoenclose} is the @@-command name
+@strong{without} the @samp{@@};
+
+@item
+the second argument is the Info start delimiter string; and,
+
+@item
+the third argument is the Info end delimiter string.
+@end itemize
+
+@noindent
+The latter two arguments enclose the highlighted text in the Info file.
+A delimiter string may contain spaces. Neither the start nor end
+delimiter is required. However, if you do not provide a start
+delimiter, you must follow the command name with two commas in a row;
+otherwise, the Info formatting commands will misinterpret the end
+delimiter string as a start delimiter string.@refill
+
+After you have defined @code{@@phoo} both for @TeX{} and for Info, you
+can then write @code{@@phoo@{bar@}} to see @samp{//bar\\}
+in Info and see
+@ifinfo
+@samp{bar} in italics in printed output.
+@end ifinfo
+@iftex
+@i{bar} in italics in printed output.
+@end iftex
+
+Note that each definition applies to its own formatter: one for @TeX{},
+the other for Info.
+
+@need 1200
+Here is another example:
+
+@example
+@group
+@@ifinfo
+@@definfoenclose headword, , :
+@@end ifinfo
+@@iftex
+@@global@@let@@headword=@@b
+@@end iftex
+@end group
+@end example
+
+@noindent
+This defines @code{@@headword} as an Info formatting command that
+inserts nothing before and a colon after the argument and as a @TeX{}
+formatting command to typeset its argument in bold.
+
+@node Quotations and Examples, Lists and Tables, Marking Text, Top
+@comment node-name, next, previous, up
+@chapter Quotations and Examples
+
+Quotations and examples are blocks of text consisting of one or more
+whole paragraphs that are set off from the bulk of the text and
+treated differently. They are usually indented.@refill
+
+In Texinfo, you always begin a quotation or example by writing an
+@@-command at the beginning of a line by itself, and end it by writing
+an @code{@@end} command that is also at the beginning of a line by
+itself. For instance, you begin an example by writing @code{@@example}
+by itself at the beginning of a line and end the example by writing
+@code{@@end example} on a line by itself, at the beginning of that
+line.@refill
+@findex end
+
+@menu
+* Block Enclosing Commands:: Use different constructs for
+ different purposes.
+* quotation:: How to write a quotation.
+* example:: How to write an example in a fixed-width font.
+* noindent:: How to prevent paragraph indentation.
+* Lisp Example:: How to illustrate Lisp code.
+* smallexample & smalllisp:: Forms for the @code{@@smallbook} option.
+* display:: How to write an example in the current font.
+* format:: How to write an example that does not narrow
+ the margins.
+* exdent:: How to undo the indentation of a line.
+* flushleft & flushright:: How to push text flushleft or flushright.
+* cartouche:: How to draw cartouches around examples.
+@end menu
+
+@node Block Enclosing Commands, quotation, Quotations and Examples, Quotations and Examples
+@section The Block Enclosing Commands
+
+Here are commands for quotations and examples:@refill
+
+@table @code
+@item @@quotation
+Indicate text that is quoted. The text is filled, indented, and
+printed in a roman font by default.@refill
+
+@item @@example
+Illustrate code, commands, and the like. The text is printed
+in a fixed-width font, and indented but not filled.@refill
+
+@item @@lisp
+Illustrate Lisp code. The text is printed in a fixed-width font,
+and indented but not filled.@refill
+
+@item @@smallexample
+Illustrate code, commands, and the like. Similar to
+@code{@@example}, except that in @TeX{} this command typesets text in
+a smaller font for the smaller @code{@@smallbook} format than for the
+8.5 by 11 inch format.@refill
+
+@item @@smalllisp
+Illustrate Lisp code. Similar to @code{@@lisp}, except that
+in @TeX{} this command typesets text in a smaller font for the smaller
+@code{@@smallbook} format than for the 8.5 by 11 inch format.@refill
+
+@item @@display
+Display illustrative text. The text is indented but not filled, and
+no font is specified (so, by default, the font is roman).@refill
+
+@item @@format
+Print illustrative text. The text is not indented and not filled
+and no font is specified (so, by default, the font is roman).@refill
+@end table
+
+The @code{@@exdent} command is used within the above constructs to
+undo the indentation of a line.
+
+The @code{@@flushleft} and @code{@@flushright} commands are used to line
+up the left or right margins of unfilled text.@refill
+
+The @code{@@noindent} command may be used after one of the above
+constructs to prevent the following text from being indented as a new
+paragraph.@refill
+
+You can use the @code{@@cartouche} command within one of the above
+constructs to highlight the example or quotation by drawing a box with
+rounded corners around it. (The @code{@@cartouche} command affects
+only the printed manual; it has no effect in the Info file; see
+@ref{cartouche, , Drawing Cartouches Around Examples}.)@refill
+
+@node quotation, example, Block Enclosing Commands, Quotations and Examples
+@comment node-name, next, previous, up
+@section @code{@@quotation}
+@cindex Quotations
+@findex quotation
+
+The text of a quotation is
+processed normally except that:@refill
+
+@itemize @bullet
+@item
+the margins are closer to the center of the page, so the whole of the
+quotation is indented;@refill
+
+@item
+the first lines of paragraphs are indented no more than other
+lines;@refill
+
+@item
+in the printed output, interparagraph spacing is reduced.@refill
+@end itemize
+
+@quotation
+This is an example of text written between an @code{@@quotation}
+command and an @code{@@end quotation} command. An @code{@@quotation}
+command is most often used to indicate text that is excerpted from
+another (real or hypothetical) printed work.@refill
+@end quotation
+
+Write an @code{@@quotation} command as text on a line by itself. This
+line will disappear from the output. Mark the end of the quotation
+with a line beginning with and containing only @code{@@end quotation}.
+The @code{@@end quotation} line will likewise disappear from the
+output. Thus, the following,@refill
+
+@example
+@@quotation
+This is
+a foo.
+@@end quotation
+@end example
+
+@noindent
+produces
+
+@quotation
+This is a foo.
+@end quotation
+
+@node example, noindent, quotation, Quotations and Examples
+@comment node-name, next, previous, up
+@section @code{@@example}
+@cindex Examples, formatting them
+@cindex Formatting examples
+@findex example
+
+The @code{@@example} command is used to indicate an example that is
+not part of the running text, such as computer input or output.@refill
+
+@example
+@group
+This is an example of text written between an
+@code{@@example} command
+and an @code{@@end example} command.
+The text is indented but not filled.
+@end group
+
+@group
+In the printed manual, the text is typeset in a
+fixed-width font, and extra spaces and blank lines are
+significant. In the Info file, an analogous result is
+obtained by indenting each line with five spaces.
+@end group
+@end example
+
+Write an @code{@@example} command at the beginning of a line by itself.
+This line will disappear from the output. Mark the end of the example
+with an @code{@@end example} command, also written at the beginning of a
+line by itself. The @code{@@end example} will disappear from the
+output.@refill
+
+@need 700
+For example,
+
+@example
+@@example
+mv foo bar
+@@end example
+@end example
+
+@noindent
+produces
+
+@example
+mv foo bar
+@end example
+
+Since the lines containing @code{@@example} and @code{@@end example}
+will disappear, you should put a blank line before the
+@code{@@example} and another blank line after the @code{@@end
+example}. (Remember that blank lines between the beginning
+@code{@@example} and the ending @code{@@end example} will appear in
+the output.)@refill
+
+@quotation
+@strong{Caution:} Do not use tabs in the lines of an example (or anywhere
+else in Texinfo, for that matter)! @TeX{} treats tabs as single
+spaces, and that is not what they look like. This is a problem with
+@TeX{}. (If necessary, in Emacs, you can use @kbd{M-x untabify} to
+convert tabs in a region to multiple spaces.)@refill
+@end quotation
+
+Examples are often, logically speaking, ``in the middle'' of a
+paragraph, and the text continues after an example should not be
+indented. The @code{@@noindent} command prevents a piece of text from
+being indented as if it were a new paragraph.
+@ifinfo
+(@xref{noindent}.)
+@end ifinfo
+
+(The @code{@@code} command is used for examples of code that are
+embedded within sentences, not set off from preceding and following
+text. @xref{code, , @code{@@code}}.)
+
+@node noindent, Lisp Example, example, Quotations and Examples
+@comment node-name, next, previous, up
+@section @code{@@noindent}
+@findex noindent
+
+An example or other inclusion can break a paragraph into segments.
+Ordinarily, the formatters indent text that follows an example as a new
+paragraph. However, you can prevent this by writing @code{@@noindent}
+at the beginning of a line by itself preceding the continuation
+text.@refill
+
+@need 1500
+For example:
+
+@example
+@group
+@@example
+This is an example
+@@end example
+
+@@noindent
+This line is not indented. As you can see, the
+beginning of the line is fully flush left with the line
+that follows after it. (This whole example is between
+@@code@{@@@@display@} and @@code@{@@@@end display@}.)
+@end group
+@end example
+
+@noindent
+produces
+
+@display
+@example
+This is an example
+@end example
+@tex
+% Remove extra vskip; this is a kludge to counter the effect of display
+\vskip-3.5\baselineskip
+@end tex
+
+@noindent
+This line is not indented. As you can see, the
+beginning of the line is fully flush left with the line
+that follows after it. (This whole example is between
+@code{@@display} and @code{@@end display}.)
+@end display
+
+To adjust the number of blank lines properly in the Info file output,
+remember that the line containing @code{@@noindent} does not generate a
+blank line, and neither does the @code{@@end example} line.@refill
+
+In the Texinfo source file for this manual, each line that says
+`produces' is preceded by a line containing @code{@@noindent}.@refill
+
+Do not put braces after an @code{@@noindent} command; they are not
+necessary, since @code{@@noindent} is a command used outside of
+paragraphs (@pxref{Command Syntax}).@refill
+
+@node Lisp Example, smallexample & smalllisp, noindent, Quotations and Examples
+@comment node-name, next, previous, up
+@section @code{@@lisp}
+@cindex Lisp example
+@findex lisp
+
+The @code{@@lisp} command is used for Lisp code. It is synonymous
+with the @code{@@example} command.
+
+@lisp
+This is an example of text written between an
+@code{@@lisp} command and an @code{@@end lisp} command.
+@end lisp
+
+Use @code{@@lisp} instead of @code{@@example} so as to preserve
+information regarding the nature of the example. This is useful, for
+example, if you write a function that evaluates only and all the Lisp
+code in a Texinfo file. Then you can use the Texinfo file as a Lisp
+library.@footnote{It would be straightforward to extend Texinfo to
+work in a similar fashion for C, @sc{fortran}, or other languages.}@refill
+
+Mark the end of @code{@@lisp} with @code{@@end lisp} on a line by
+itself.@refill
+
+@node smallexample & smalllisp, display, Lisp Example, Quotations and Examples
+@comment node-name, next, previous, up
+@section @code{@@smallexample} and @code{@@smalllisp}
+@cindex Small book example
+@cindex Example for a small book
+@cindex Lisp example for a small book
+@findex smallexample
+@findex smalllisp
+
+In addition to the regular @code{@@example} and @code{@@lisp} commands,
+Texinfo has two other ``example-style'' commands. These are the
+@code{@@smallexample} and @code{@@smalllisp} commands. Both these
+commands are designed for use with the @code{@@smallbook} command that
+causes @TeX{} to produce a printed manual in a 7 by 9.25 inch format
+rather than the regular 8.5 by 11 inch format.@refill
+
+In @TeX{}, the @code{@@smallexample} and @code{@@smalllisp} commands
+typeset text in a smaller font for the smaller @code{@@smallbook}
+format than for the 8.5 by 11 inch format. Consequently, many examples
+containing long lines fit in a narrower, @code{@@smallbook} page
+without needing to be shortened. Both commands typeset in the normal
+font size when you format for the 8.5 by 11 inch size; indeed,
+in this situation, the @code{@@smallexample} and @code{@@smalllisp}
+commands are defined to be the @code{@@example} and @code{@@lisp}
+commands.@refill
+
+In Info, the @code{@@smallexample} and @code{@@smalllisp} commands are
+equivalent to the @code{@@example} and @code{@@lisp} commands, and work
+exactly the same.@refill
+
+Mark the end of @code{@@smallexample} or @code{@@smalllisp} with
+@code{@@end smallexample} or @code{@@end smalllisp},
+respectively.@refill
+
+@iftex
+Here is an example written in the small font used by the
+@code{@@smallexample} and @code{@@smalllisp} commands:
+
+@ifclear smallbook
+@display
+@tex
+% Remove extra vskip; this is a kludge to counter the effect of display
+\vskip-3\baselineskip
+{\ninett
+\dots{} 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.}
+@end tex
+@end display
+@end ifclear
+@end iftex
+@ifset smallbook
+@iftex
+@smallexample
+This is an example of text written between @code{@@smallexample} and
+@code{@@end smallexample}. In Info and in an 8.5 by 11 inch manual,
+this text appears in its normal size; but in a 7 by 9.25 inch manual,
+this text appears in a smaller font.
+@end smallexample
+@end iftex
+@end ifset
+@ifinfo
+@smallexample
+This is an example of text written between @code{@@smallexample} and
+@code{@@end smallexample}. In Info and in an 8.5 by 11 inch manual,
+this text appears in its normal size; but in a 7 by 9.25 inch manual,
+this text appears in a smaller font.
+@end smallexample
+@end ifinfo
+
+The @code{@@smallexample} and @code{@@smalllisp} commands make it
+easier to prepare smaller format manuals without forcing you to edit
+examples by hand to fit them onto narrower pages.@refill
+
+As a general rule, a printed document looks better if you write all the
+examples in a chapter consistently in @code{@@example} or in
+@code{@@smallexample}. Only occasionally should you mix the two
+formats.@refill
+
+@xref{smallbook, , Printing ``Small'' Books}, for more information
+about the @code{@@smallbook} command.@refill
+
+@node display, format, smallexample & smalllisp, Quotations and Examples
+@comment node-name, next, previous, up
+@section @code{@@display}
+@cindex Display formatting
+@findex display
+
+The @code{@@display} command begins a kind of example. It is like the
+@code{@@example} command
+except that, in
+a printed manual, @code{@@display} does not select the fixed-width
+font. In fact, it does not specify the font at all, so that the text
+appears in the same font it would have appeared in without the
+@code{@@display} command.@refill
+
+@display
+This is an example of text written between an @code{@@display} command
+and an @code{@@end display} command. The @code{@@display} command
+indents the text, but does not fill it.
+@end display
+
+@node format, exdent, display, Quotations and Examples
+@comment node-name, next, previous, up
+@section @code{@@format}
+@findex format
+
+The @code{@@format} command is similar to @code{@@example} except
+that, in the printed manual, @code{@@format} does not select the
+fixed-width font and does not narrow the margins.@refill
+
+@format
+This is an example of text written between an @code{@@format} command
+and an @code{@@end format} command. As you can see
+from this example,
+the @code{@@format} command does not fill the text.
+@end format
+
+@node exdent, flushleft & flushright, format, Quotations and Examples
+@section @code{@@exdent}: Undoing a Line's Indentation
+@cindex Indentation undoing
+@findex exdent
+
+The @code{@@exdent} command removes any indentation a line might have.
+The command is written at the beginning of a line and applies only to
+the text that follows the command that is on the same line. Do not use
+braces around the text. In a printed manual, the text on an
+@code{@@exdent} line is printed in the roman font.@refill
+
+@code{@@exdent} is usually used within examples. Thus,@refill
+
+@example
+@group
+@@example
+This line follows an @@@@example command.
+@@exdent This line is exdented.
+This line follows the exdented line.
+The @@@@end example comes on the next line.
+@@end group
+@end group
+@end example
+
+@noindent
+produces
+
+@example
+@group
+This line follows an @@example command.
+@exdent This line is exdented.
+This line follows the exdented line.
+The @@end example comes on the next line.
+@end group
+@end example
+
+In practice, the @code{@@exdent} command is rarely used.
+Usually, you un-indent text by ending the example and
+returning the page to its normal width.@refill
+
+@node flushleft & flushright, cartouche, exdent, Quotations and Examples
+@section @code{@@flushleft} and @code{@@flushright}
+@findex flushleft
+@findex flushright
+
+The @code{@@flushleft} and @code{@@flushright} commands line up the
+ends of lines on the left and right margins of a page,
+but do not fill the text. The commands are written on lines of their
+own, without braces. The @code{@@flushleft} and @code{@@flushright}
+commands are ended by @code{@@end flushleft} and @code{@@end
+flushright} commands on lines of their own.@refill
+
+@need 1500
+For example,
+
+@example
+@group
+@@flushleft
+This text is
+written flushleft.
+@@end flushleft
+@end group
+@end example
+
+@noindent
+produces
+
+@quotation
+@flushleft
+This text is
+written flushleft.
+@end flushleft
+@end quotation
+
+
+Flushright produces the type of indentation often used in the return
+address of letters.@refill
+
+@need 1500
+@noindent
+For example,
+
+@example
+@group
+@@flushright
+Here is an example of text written
+flushright. The @@code@{@@flushright@} command
+right justifies every line but leaves the
+left end ragged.
+@@end flushright
+@end group
+@end example
+
+@noindent
+produces
+
+@flushright
+Here is an example of text written
+flushright. The @code{@@flushright} command
+right justifies every line but leaves the
+left end ragged.
+@end flushright
+
+@node cartouche, , flushleft & flushright, Quotations and Examples
+@section Drawing Cartouches Around Examples
+@findex cartouche
+@cindex Box with rounded corners
+
+In a printed manual, the @code{@@cartouche} command draws a box with
+rounded corners around its contents. You can use this command to
+further highlight an example or quotation. For instance, you could
+write a manual in which one type of example is surrounded by a cartouche
+for emphasis.@refill
+
+The @code{@@cartouche} command affects only the printed manual; it has
+no effect in the Info file.@refill
+
+@need 1500
+For example,
+
+@example
+@group
+@@example
+@@cartouche
+% pwd
+/usr/local/lib/emacs/info
+@@end cartouche
+@@end example
+@end group
+@end example
+
+@noindent
+surrounds the two-line example with a box with rounded corners, in the
+printed manual.
+
+@iftex
+In a printed manual, the example looks like this:@refill
+
+@example
+@group
+@cartouche
+% pwd
+/usr/local/lib/emacs/info
+@end cartouche
+@end group
+@end example
+@end iftex
+
+@node Lists and Tables, Indices, Quotations and Examples, Top
+@comment node-name, next, previous, up
+@chapter Making Lists and Tables
+@cindex Making lists and tables
+@cindex Lists and tables, making them
+@cindex Tables and lists, making them
+
+Texinfo has several ways of making lists and two-column tables. Lists can
+be bulleted or numbered, while two-column tables can highlight the items in
+the first column.@refill
+
+@menu
+* Introducing Lists:: Texinfo formats lists for you.
+* itemize:: How to construct a simple list.
+* enumerate:: How to construct a numbered list.
+* Two-column Tables:: How to construct a two-column table.
+* Multi-column Tables:: How to construct generalized tables.
+@end menu
+
+@ifinfo
+@node Introducing Lists, itemize, Lists and Tables, Lists and Tables
+@heading Introducing Lists
+@end ifinfo
+
+Texinfo automatically indents the text in lists or tables, and numbers
+an enumerated list. This last feature is useful if you modify the
+list, since you do not need to renumber it yourself.@refill
+
+Numbered lists and tables begin with the appropriate @@-command at the
+beginning of a line, and end with the corresponding @code{@@end}
+command on a line by itself. The table and itemized-list commands
+also require that you write formatting information on the same line as
+the beginning @@-command.@refill
+
+Begin an enumerated list, for example, with an @code{@@enumerate}
+command and end the list with an @code{@@end enumerate} command.
+Begin an itemized list with an @code{@@itemize} command, followed on
+the same line by a formatting command such as @code{@@bullet}, and end
+the list with an @code{@@end itemize} command.@refill
+@findex end
+
+Precede each element of a list with an @code{@@item} or @code{@@itemx}
+command.@refill
+
+@sp 1
+@noindent
+Here is an itemized list of the different kinds of table and lists:@refill
+
+@itemize @bullet
+@item
+Itemized lists with and without bullets.
+
+@item
+Enumerated lists, using numbers or letters.
+
+@item
+Two-column tables with highlighting.
+@end itemize
+
+@sp 1
+@noindent
+Here is an enumerated list with the same items:@refill
+
+@enumerate
+@item
+Itemized lists with and without bullets.
+
+@item
+Enumerated lists, using numbers or letters.
+
+@item
+Two-column tables with highlighting.
+@end enumerate
+
+@sp 1
+@noindent
+And here is a two-column table with the same items and their
+@w{@@-commands}:@refill
+
+@table @code
+@item @@itemize
+Itemized lists with and without bullets.
+
+@item @@enumerate
+Enumerated lists, using numbers or letters.
+
+@item @@table
+@itemx @@ftable
+@itemx @@vtable
+Two-column tables with indexing.
+@end table
+
+@node itemize, enumerate, Introducing Lists, Lists and Tables
+@comment node-name, next, previous, up
+@section Making an Itemized List
+@cindex Itemization
+@findex itemize
+
+The @code{@@itemize} command produces sequences of indented
+paragraphs, with a bullet or other mark inside the left margin
+at the beginning of each paragraph for which such a mark is desired.@refill
+
+Begin an itemized list by writing @code{@@itemize} at the beginning of
+a line. Follow the command, on the same line, with a character or a
+Texinfo command that generates a mark. Usually, you will write
+@code{@@bullet} after @code{@@itemize}, but you can use
+@code{@@minus}, or any character or any special symbol that results in
+a single character in the Info file. (When you write @code{@@bullet}
+or @code{@@minus} after an @code{@@itemize} command, you may omit the
+@samp{@{@}}.)@refill
+
+Write the text of the indented paragraphs themselves after the
+@code{@@itemize}, up to another line that says @code{@@end
+itemize}.@refill
+
+Before each paragraph for which a mark in the margin is desired, write
+a line that says just @code{@@item}. Do not write any other text on this
+line.@refill
+@findex item
+
+Usually, you should put a blank line before an @code{@@item}. This
+puts a blank line in the Info file. (@TeX{} inserts the proper
+interline whitespace in either case.) Except when the entries are
+very brief, these blank lines make the list look better.@refill
+
+Here is an example of the use of @code{@@itemize}, followed by the
+output it produces. Note that @code{@@bullet} produces an @samp{*} in
+Info and a round dot in @TeX{}.@refill
+
+@example
+@group
+@@itemize @@bullet
+@@item
+Some text for foo.
+
+@@item
+Some text
+for bar.
+@@end itemize
+@end group
+@end example
+
+@noindent
+This produces:
+
+@quotation
+@itemize @bullet
+@item
+Some text for foo.
+
+@item
+Some text
+for bar.
+@end itemize
+@end quotation
+
+Itemized lists may be embedded within other itemized lists. Here is a
+list marked with dashes embedded in a list marked with bullets:@refill
+
+@example
+@group
+@@itemize @@bullet
+@@item
+First item.
+
+@@itemize @@minus
+@@item
+Inner item.
+
+@@item
+Second inner item.
+@@end itemize
+
+@@item
+Second outer item.
+@@end itemize
+@end group
+@end example
+
+@noindent
+This produces:
+
+@quotation
+@itemize @bullet
+@item
+First item.
+
+@itemize @minus
+@item
+Inner item.
+
+@item
+Second inner item.
+@end itemize
+
+@item
+Second outer item.
+@end itemize
+@end quotation
+
+@node enumerate, Two-column Tables, itemize, Lists and Tables
+@comment node-name, next, previous, up
+@section Making a Numbered or Lettered List
+@cindex Enumeration
+@findex enumerate
+
+@code{@@enumerate} is like @code{@@itemize} except that the marks in
+the left margin contain successive integers or letters.
+(@xref{itemize, , @code{@@itemize}}.)@refill
+
+Write the @code{@@enumerate} command at the beginning of a line.
+The command does not require an argument, but accepts either a number or
+a letter as an option.
+Without an argument, @code{@@enumerate} starts the list
+with the number 1. With a numeric argument, such as 3,
+the command starts the list with that number.
+With an upper or lower case letter, such as @kbd{a} or @kbd{A},
+the command starts the list with that letter.@refill
+
+Write the text of the enumerated list in the same way you write an
+itemized list: put @code{@@item} on a line of its own before the start of
+each paragraph that you want enumerated. Do not write any other text on
+the line beginning with @code{@@item}.@refill
+
+You should put a blank line between entries in the list.
+This generally makes it easier to read the Info file.@refill
+
+@need 1500
+Here is an example of @code{@@enumerate} without an argument:@refill
+
+@example
+@group
+@@enumerate
+@@item
+Underlying causes.
+
+@@item
+Proximate causes.
+@@end enumerate
+@end group
+@end example
+
+@noindent
+This produces:
+
+@enumerate
+@item
+Underlying causes.
+
+@item
+Proximate causes.
+@end enumerate
+@sp 1
+Here is an example with an argument of @kbd{3}:@refill
+@sp 1
+@example
+@group
+@@enumerate 3
+@@item
+Predisposing causes.
+
+@@item
+Precipitating causes.
+
+@@item
+Perpetuating causes.
+@@end enumerate
+@end group
+@end example
+
+@noindent
+This produces:
+
+@enumerate 3
+@item
+Predisposing causes.
+
+@item
+Precipitating causes.
+
+@item
+Perpetuating causes.
+@end enumerate
+@sp 1
+Here is a brief summary of the alternatives. The summary is constructed
+using @code{@@enumerate} with an argument of @kbd{a}.@refill
+@sp 1
+@enumerate a
+@item
+@code{@@enumerate}
+
+Without an argument, produce a numbered list, starting with the number
+1.@refill
+
+@item
+@code{@@enumerate @var{positive-integer}}
+
+With a (positive) numeric argument, start a numbered list with that
+number. You can use this to continue a list that you interrupted with
+other text.@refill
+
+@item
+@code{@@enumerate @var{upper-case-letter}}
+
+With an upper case letter as argument, start a list
+in which each item is marked
+by a letter, beginning with that upper case letter.@refill
+
+@item
+@code{@@enumerate @var{lower-case-letter}}
+
+With a lower case letter as argument, start a list
+in which each item is marked by
+a letter, beginning with that lower case letter.@refill
+@end enumerate
+
+You can also nest enumerated lists, as in an outline.@refill
+
+@node Two-column Tables, Multi-column Tables, enumerate, Lists and Tables
+@section Making a Two-column Table
+@cindex Tables, making two-column
+@findex table
+
+@code{@@table} is similar to @code{@@itemize}, but the command allows
+you to specify a name or heading line for each item. (@xref{itemize,
+, @code{@@itemize}}.) The @code{@@table} command is used to produce
+two-column tables, and is especially useful for glossaries and
+explanatory exhibits.@refill
+
+@menu
+* table:: How to construct a two-column table.
+* ftable vtable:: How to construct a two-column table
+ with automatic indexing.
+* itemx:: How to put more entries in the first column.
+@end menu
+
+@ifinfo
+@node table, ftable vtable, Two-column Tables, Two-column Tables
+@subheading Using the @code{@@table} Command
+
+Use the @code{@@table} command to produce two-column tables.@refill
+@end ifinfo
+
+Write the @code{@@table} command at the beginning of a line and follow
+it on the same line with an argument that is a Texinfo command such as
+@code{@@code}, @code{@@samp}, @code{@@var}, or @code{@@kbd}.
+Although these commands are usually followed by arguments in braces,
+in this case you use the command name without an argument because
+@code{@@item} will supply the argument. This command will be applied
+to the text that goes into the first column of each item and
+determines how it will be highlighted. For example, @code{@@samp}
+will cause the text in the first column to be highlighted with an
+@code{@@samp} command.@refill
+
+You may also choose to use the @code{@@asis} command as an argument to
+@code{@@table}. @code{@@asis} is a command that does nothing; if you use this
+command after @code{@@table}, @TeX{} and the Info formatting commands
+output the first column entries without added highlighting (`as
+is').@refill
+
+(The @code{@@table} command may work with other commands besides those
+listed here. However, you can only use commands
+that normally take arguments in braces.)@refill
+
+Begin each table entry with an @code{@@item} command at the beginning
+of a line. Write the first column text on the same line as the
+@code{@@item} command. Write the second column text on the line
+following the @code{@@item} line and on subsequent lines. (You do not
+need to type anything for an empty second column entry.) You may
+write as many lines of supporting text as you wish, even several
+paragraphs. But only text on the same line as the @code{@@item} will
+be placed in the first column.@refill
+@findex item
+
+Normally, you should put a blank line before an @code{@@item} line.
+This puts a blank like in the Info file. Except when the entries are
+very brief, a blank line looks better.@refill
+
+@need 1500
+The following table, for example, highlights the text in the first
+column with an @code{@@samp} command:@refill
+
+@example
+@group
+@@table @@samp
+@@item foo
+This is the text for
+@@samp@{foo@}.
+
+@@item bar
+Text for @@samp@{bar@}.
+@@end table
+@end group
+@end example
+
+@noindent
+This produces:
+
+@table @samp
+@item foo
+This is the text for
+@samp{foo}.
+@item bar
+Text for @samp{bar}.
+@end table
+
+If you want to list two or more named items with a single block of
+text, use the @code{@@itemx} command. (@xref{itemx, ,
+@code{@@itemx}}.)@refill
+
+@node ftable vtable, itemx, table, Two-column Tables
+@comment node-name, next, previous, up
+@subsection @code{@@ftable} and @code{@@vtable}
+@cindex Tables with indexes
+@cindex Indexing table entries automatically
+@findex ftable
+@findex vtable
+
+The @code{@@ftable} and @code{@@vtable} commands are the same as the
+@code{@@table} command except that @code{@@ftable} automatically enters
+each of the items in the first column of the table into the index of
+functions and @code{@@vtable} automatically enters each of the items in
+the first column of the table into the index of variables. This
+simplifies the task of creating indices. Only the items on the same
+line as the @code{@@item} commands are indexed, and they are indexed in
+exactly the form that they appear on that line. @xref{Indices, ,
+Creating Indices}, for more information about indices.@refill
+
+Begin a two-column table using @code{@@ftable} or @code{@@vtable} by
+writing the @@-command at the beginning of a line, followed on the same
+line by an argument that is a Texinfo command such as @code{@@code},
+exactly as you would for an @code{@@table} command; and end the table
+with an @code{@@end ftable} or @code{@@end vtable} command on a line by
+itself.
+
+See the example for @code{@@table} in the previous section.
+
+@node itemx, , ftable vtable, Two-column Tables
+@comment node-name, next, previous, up
+@subsection @code{@@itemx}
+@cindex Two named items for @code{@@table}
+@findex itemx
+
+Use the @code{@@itemx} command inside a table when you have two or
+more first column entries for the same item, each of which should
+appear on a line of its own. Use @code{@@itemx} for all but the first
+entry. The @code{@@itemx} command works exactly like @code{@@item}
+except that it does not generate extra vertical space above the first
+column text.@refill
+
+@need 1000
+For example,
+
+@example
+@group
+@@table @@code
+@@item upcase
+@@itemx downcase
+These two functions accept a character or a string as
+argument, and return the corresponding upper case (lower
+case) character or string.
+@@end table
+@end group
+@end example
+
+@noindent
+This produces:
+
+@table @code
+@item upcase
+@itemx downcase
+These two functions accept a character or a string as
+argument, and return the corresponding upper case (lower
+case) character or string.@refill
+@end table
+
+@noindent
+(Note also that this example illustrates multi-line supporting text in
+a two-column table.)@refill
+
+
+@node Multi-column Tables, , Two-column Tables, Lists and Tables
+@section Multi-column Tables
+@cindex Tables, making multi-column
+@findex multitable
+
+@code{@@multitable} allows you to construct tables with any number of
+columns, with each column having any width you like.
+
+You define the column widths on the @code{@@multitable} line itself, and
+write each row of the actual table following an @code{@@item} command,
+with columns separated by an @code{@@tab} command. Finally, @code{@@end
+multitable} completes the table. Details in the sections below.
+
+@menu
+* Multitable Column Widths:: Defining multitable column widths.
+* Multitable Rows:: Defining multitable rows, with examples.
+@end menu
+
+@node Multitable Column Widths, Multitable Rows, Multi-column Tables, Multi-column Tables
+@subsection Multitable Column Widths
+@cindex Multitable column widths
+@cindex Column widths, defining for multitables
+@cindex Widths, defining multitable column
+
+You can define the column widths for a multitable in two ways: as
+fractions of the line length; or with a prototype row. Mixing the two
+methods is not supported. In either case, the widths are defined
+entirely on the same line as the @code{@@multitable} command.
+
+@enumerate
+@item
+@findex columnfractions
+@cindex Line length, column widths as fraction of
+To specify column widths as fractions of the line length, write
+@code{@@columnfractions} and the decimal numbers (presumably less than
+1) after the @code{@@multitable} command, as in:
+
+@example
+@@multitable @@columnfractions .33 .33 .33
+@end example
+
+@noindent The fractions need not add up exactly to 1.0, as these do
+not. This allows you to produce tables that do not need the full line
+length.
+
+@item
+@cindex Prototype row, column widths defined by
+To specify a prototype row, write the longest entry for each column
+enclosed in braces after the @code{@@multitable} command. For example:
+
+@example
+@@multitable @{some text for column one@} @{for column two@}
+@end example
+
+@noindent
+The first column will then have the width of the typeset `some text for
+column one', and the second column the width of `for column two'.
+
+The prototype entries need not appear in the table itself.
+
+Although we used simple text in this example, the prototype entries can
+contain Texinfo commands; markup commands such as @code{@@code} are
+particularly likely to be useful.
+
+@end enumerate
+
+
+@node Multitable Rows, , Multitable Column Widths, Multi-column Tables
+@subsection Multitable Rows
+@cindex Multitable rows
+@cindex Rows, of a multitable
+
+@findex item
+@cindex tab
+After the @code{@@multitable} command defining the column widths (see
+the previous section), you begin each row in the body of a multitable
+with @code{@@item}, and separate the column entries with @code{@@tab}.
+Line breaks are not special within the table body, and you may break
+input lines in your source file as necessary.
+
+Here is a complete example of a multi-column table (the text is from
+the GNU Emacs manual):
+
+@example
+@@multitable @@columnfractions .15 .45 .4
+@@item Key @@tab Command @@tab Description
+@@item C-x 2
+@@tab @@code@{split-window-vertically@}
+@@tab Split the selected window into two windows,
+with one above the other.
+@@item C-x 3
+@@tab @@code@{split-window-horizontally@}
+@@tab Split the selected window into two windows
+positioned side by side.
+@@item C-Mouse-2
+@@tab
+@@tab In the mode line or scroll bar of a window,
+split that window.
+@@end multitable
+@end example
+
+@noindent produces:
+
+@multitable @columnfractions .15 .45 .4
+@item Key @tab Command @tab Description
+@item C-x 2
+@tab @code{split-window-vertically}
+@tab Split the selected window into two windows,
+with one above the other.
+@item C-x 3
+@tab @code{split-window-horizontally}
+@tab Split the selected window into two windows
+positioned side by side.
+@item C-Mouse-2
+@tab
+@tab In the mode line or scroll bar of a window,
+split that window.
+@end multitable
+
+
+@node Indices, Insertions, Lists and Tables, Top
+@comment node-name, next, previous, up
+@chapter Creating Indices
+@cindex Indices
+@cindex Creating indices
+
+Using Texinfo, you can generate indices without having to sort and
+collate entries manually. In an index, the entries are listed in
+alphabetical order, together with information on how to find the
+discussion of each entry. In a printed manual, this information
+consists of page numbers. In an Info file, this information is a menu
+entry leading to the first node referenced.@refill
+
+Texinfo provides several predefined kinds of index: an index
+for functions, an index for variables, an index for concepts, and so
+on. You can combine indices or use them for other than their
+canonical purpose. If you wish, you can define your own indices.@refill
+
+@menu
+* Index Entries:: Choose different words for index entries.
+* Predefined Indices:: Use different indices for different kinds
+ of entry.
+* Indexing Commands:: How to make an index entry.
+* Combining Indices:: How to combine indices.
+* New Indices:: How to define your own indices.
+@end menu
+
+@node Index Entries, Predefined Indices, Indices, Indices
+@comment node-name, next, previous, up
+@section Making Index Entries
+@cindex Index entries, making
+@cindex Entries, making index
+
+When you are making index entries, it is good practice to think of the
+different ways people may look for something. Different people
+@emph{do not} think of the same words when they look something up. A
+helpful index will have items indexed under all the different words
+that people may use. For example, one reader may think it obvious that
+the two-letter names for indices should be listed under ``Indices,
+two-letter names'', since the word ``Index'' is the general concept.
+But another reader may remember the specific concept of two-letter
+names and search for the entry listed as ``Two letter names for
+indices''. A good index will have both entries and will help both
+readers.@refill
+
+Like typesetting, the construction of an index is a highly skilled,
+professional art, the subtleties of which are not appreciated until you
+need to do it yourself.@refill
+
+@xref{Printing Indices & Menus}, for information about printing an index
+at the end of a book or creating an index menu in an Info file.@refill
+
+@node Predefined Indices, Indexing Commands, Index Entries, Indices
+@comment node-name, next, previous, up
+@section Predefined Indices
+
+Texinfo provides six predefined indices:@refill
+
+@itemize @bullet
+@item
+A @dfn{concept index} listing concepts that are discussed.@refill
+
+@item
+A @dfn{function index} listing functions (such as entry points of
+libraries).@refill
+
+@item
+A @dfn{variables index} listing variables (such as global variables
+of libraries).@refill
+
+@item
+A @dfn{keystroke index} listing keyboard commands.@refill
+
+@item
+A @dfn{program index} listing names of programs.@refill
+
+@item
+A @dfn{data type index} listing data types (such as structures defined in
+header files).@refill
+@end itemize
+
+@noindent
+Not every manual needs all of these, and most manuals use two or three
+of them. This manual has two indices: a
+concept index and an @@-command index (that is actually the function
+index but is called a command index in the chapter heading). Two or
+more indices can be combined into one using the @code{@@synindex} or
+@code{@@syncodeindex} commands. @xref{Combining Indices}.@refill
+
+@node Indexing Commands, Combining Indices, Predefined Indices, Indices
+@comment node-name, next, previous, up
+@section Defining the Entries of an Index
+@cindex Defining indexing entries
+@cindex Index entries
+@cindex Entries for an index
+@cindex Specifying index entries
+@cindex Creating index entries
+
+The data to make an index come from many individual indexing commands
+scattered throughout the Texinfo source file. Each command says to add
+one entry to a particular index; after formatting, the index will give
+the current page number or node name as the reference.@refill
+
+An index entry consists of an indexing command at the beginning of a
+line followed, on the rest of the line, by the entry.@refill
+
+For example, this section begins with the following five entries for
+the concept index:@refill
+
+@example
+@@cindex Defining indexing entries
+@@cindex Index entries
+@@cindex Entries for an index
+@@cindex Specifying index entries
+@@cindex Creating index entries
+@end example
+
+Each predefined index has its own indexing command---@code{@@cindex}
+for the concept index, @code{@@findex} for the function index, and so
+on.@refill
+
+@cindex Writing index entries
+@cindex Index entry writing
+Concept index entries consist of text. The best way to write an index
+is to choose entries that are terse yet clear. If you can do this,
+the index often looks better if the entries are not capitalized, but
+written just as they would appear in the middle of a sentence.
+(Capitalize proper names and acronyms that always call for upper case
+letters.) This is the case convention we use in most GNU manuals'
+indices.
+
+If you don't see how to make an entry terse yet clear, make it longer
+and clear---not terse and confusing. If many of the entries are several
+words long, the index may look better if you use a different convention:
+to capitalize the first word of each entry. But do not capitalize a
+case-sensitive name such as a C or Lisp function name or a shell
+command; that would be a spelling error.
+
+Whichever case convention you use, please use it consistently!
+
+@ignore
+Concept index entries consist of English text. The usual convention
+is to capitalize the first word of each such index entry, unless that
+word is the name of a function, variable, or other such entity that
+should not be capitalized. However, if your concept index entries are
+consistently short (one or two words each) it may look better for each
+regular entry to start with a lower case letter, aside from proper
+names and acronyms that always call for upper case letters. Whichever
+convention you adapt, please be consistent!
+@end ignore
+
+Entries in indices other than the concept index are symbol names in
+programming languages, or program names; these names are usually
+case-sensitive, so use upper and lower case as required for them.
+
+By default, entries for a concept index are printed in a small roman
+font and entries for the other indices are printed in a small
+@code{@@code} font. You may change the way part of an entry is
+printed with the usual Texinfo commands, such as @code{@@file} for
+file names and @code{@@emph} for emphasis (@pxref{Marking
+Text}).@refill
+@cindex Index font types
+
+@cindex Predefined indexing commands
+@cindex Indexing commands, predefined
+The six indexing commands for predefined indices are:
+
+@table @code
+@item @@cindex @var{concept}
+@findex cindex
+Make an entry in the concept index for @var{concept}.@refill
+
+@item @@findex @var{function}
+@findex findex
+Make an entry in the function index for @var{function}.@refill
+
+@item @@vindex @var{variable}
+@findex vindex
+Make an entry in the variable index for @var{variable}.@refill
+
+@item @@kindex @var{keystroke}
+@findex kindex
+Make an entry in the key index for @var{keystroke}.@refill
+
+@item @@pindex @var{program}
+@findex pindex
+Make an entry in the program index for @var{program}.@refill
+
+@item @@tindex @var{data type}
+@findex tindex
+Make an entry in the data type index for @var{data type}.@refill
+@end table
+
+@quotation
+@strong{Caution:} Do not use a colon in an index entry. In Info, a
+colon separates the menu entry name from the node name. An extra
+colon confuses Info.
+@xref{Menu Parts, , The Parts of a Menu},
+for more information about the structure of a menu entry.@refill
+@end quotation
+
+If you write several identical index entries in different places in a
+Texinfo file, the index in the printed manual will list all the pages to
+which those entries refer. However, the index in the Info file will
+list @strong{only} the node that references the @strong{first} of those
+index entries. Therefore, it is best to write indices in which each
+entry refers to only one place in the Texinfo file. Fortunately, this
+constraint is a feature rather than a loss since it means that the index
+will be easy to use. Otherwise, you could create an index that lists
+several pages for one entry and your reader would not know to which page
+to turn. If you have two identical entries for one topic, change the
+topics slightly, or qualify them to indicate the difference.@refill
+
+You are not actually required to use the predefined indices for their
+canonical purposes. For example, suppose you wish to index some C
+preprocessor macros. You could put them in the function index along
+with actual functions, just by writing @code{@@findex} commands for
+them; then, when you print the ``Function Index'' as an unnumbered
+chapter, you could give it the title `Function and Macro Index' and
+all will be consistent for the reader. Or you could put the macros in
+with the data types by writing @code{@@tindex} commands for them, and
+give that index a suitable title so the reader will understand.
+(@xref{Printing Indices & Menus}.)@refill
+
+@node Combining Indices, New Indices, Indexing Commands, Indices
+@comment node-name, next, previous, up
+@section Combining Indices
+@cindex Combining indices
+@cindex Indices, combining them
+
+Sometimes you will want to combine two disparate indices such as functions
+and concepts, perhaps because you have few enough of one of them that
+a separate index for them would look silly.@refill
+
+You could put functions into the concept index by writing
+@code{@@cindex} commands for them instead of @code{@@findex} commands,
+and produce a consistent manual by printing the concept index with the
+title `Function and Concept Index' and not printing the `Function
+Index' at all; but this is not a robust procedure. It works only if
+your document is never included as part of another
+document that is designed to have a separate function index; if your
+document were to be included with such a document, the functions from
+your document and those from the other would not end up together.
+Also, to make your function names appear in the right font in the
+concept index, you would need to enclose every one of them between
+the braces of @code{@@code}.@refill
+
+@menu
+* syncodeindex:: How to merge two indices, using @code{@@code}
+ font for the merged-from index.
+* synindex:: How to merge two indices, using the
+ default font of the merged-to index.
+@end menu
+
+@node syncodeindex, synindex, Combining Indices, Combining Indices
+@subsection @code{@@syncodeindex}
+@findex syncodeindex
+
+When you want to combine functions and concepts into one index, you
+should index the functions with @code{@@findex} and index the concepts
+with @code{@@cindex}, and use the @code{@@syncodeindex} command to
+redirect the function index entries into the concept index.@refill
+@findex syncodeindex
+
+The @code{@@syncodeindex} command takes two arguments; they are the name
+of the index to redirect, and the name of the index to redirect it to.
+The template looks like this:@refill
+
+@example
+@@syncodeindex @var{from} @var{to}
+@end example
+
+@cindex Predefined names for indices
+@cindex Two letter names for indices
+@cindex Indices, two letter names
+@cindex Names for indices
+For this purpose, the indices are given two-letter names:@refill
+
+@table @samp
+@item cp
+concept index
+@item fn
+function index
+@item vr
+variable index
+@item ky
+key index
+@item pg
+program index
+@item tp
+data type index
+@end table
+
+Write an @code{@@syncodeindex} command before or shortly after the
+end-of-header line at the beginning of a Texinfo file. For example,
+to merge a function index with a concept index, write the
+following:@refill
+
+@example
+@@syncodeindex fn cp
+@end example
+
+@noindent
+This will cause all entries designated for the function index to merge
+in with the concept index instead.@refill
+
+To merge both a variables index and a function index into a concept
+index, write the following:@refill
+
+@example
+@group
+@@syncodeindex vr cp
+@@syncodeindex fn cp
+@end group
+@end example
+
+@cindex Fonts for indices
+The @code{@@syncodeindex} command puts all the entries from the `from'
+index (the redirected index) into the @code{@@code} font, overriding
+whatever default font is used by the index to which the entries are
+now directed. This way, if you direct function names from a function
+index into a concept index, all the function names are printed in the
+@code{@@code} font as you would expect.@refill
+
+@node synindex, , syncodeindex, Combining Indices
+@subsection @code{@@synindex}
+@findex synindex
+
+The @code{@@synindex} command is nearly the same as the
+@code{@@syncodeindex} command, except that it does not put the
+`from' index entries into the @code{@@code} font; rather it puts
+them in the roman font. Thus, you use @code{@@synindex} when you
+merge a concept index into a function index.@refill
+
+@xref{Printing Indices & Menus}, for information about printing an index
+at the end of a book or creating an index menu in an Info file.@refill
+
+@node New Indices, , Combining Indices, Indices
+@section Defining New Indices
+@cindex Defining new indices
+@cindex Indices, defining new
+@cindex New index defining
+@findex defindex
+@findex defcodeindex
+
+In addition to the predefined indices, you may use the
+@code{@@defindex} and @code{@@defcodeindex} commands to define new
+indices. These commands create new indexing @@-commands with which
+you mark index entries. The @code{@@defindex }command is used like
+this:@refill
+
+@example
+@@defindex @var{name}
+@end example
+
+The name of an index should be a two letter word, such as @samp{au}.
+For example:@refill
+
+@example
+@@defindex au
+@end example
+
+This defines a new index, called the @samp{au} index. At the same
+time, it creates a new indexing command, @code{@@auindex}, that you
+can use to make index entries. Use the new indexing command just as
+you would use a predefined indexing command.@refill
+
+For example, here is a section heading followed by a concept index
+entry and two @samp{au} index entries.@refill
+
+@example
+@@section Cognitive Semantics
+@@cindex kinesthetic image schemas
+@@auindex Johnson, Mark
+@@auindex Lakoff, George
+@end example
+
+@noindent
+(Evidently, @samp{au} serves here as an abbreviation for ``author''.)
+Texinfo constructs the new indexing command by concatenating the name
+of the index with @samp{index}; thus, defining an @samp{au} index
+leads to the automatic creation of an @code{@@auindex} command.@refill
+
+Use the @code{@@printindex} command to print the index, as you do with
+the predefined indices. For example:@refill
+
+@example
+@group
+@@node Author Index, Subject Index, , Top
+@@unnumbered Author Index
+
+@@printindex au
+@end group
+@end example
+
+The @code{@@defcodeindex} is like the @code{@@defindex} command, except
+that, in the printed output, it prints entries in an @code{@@code} font
+instead of a roman font. Thus, it parallels the @code{@@findex} command
+rather than the @code{@@cindex} command.@refill
+
+You should define new indices within or right after the end-of-header
+line of a Texinfo file, before any @code{@@synindex} or
+@code{@@syncodeindex} commands (@pxref{Header}).@refill
+
+@node Insertions, Glyphs, Indices, Top
+@comment node-name, next, previous, up
+@chapter Special Insertions
+@cindex Inserting special characters and symbols
+@cindex Special insertions
+
+Texinfo provides several commands for formatting dimensions, for
+inserting single characters that have special meaning in Texinfo, such
+as braces, and for inserting special graphic symbols that do not
+correspond to characters, such as dots and bullets.@refill
+
+@iftex
+These are:
+
+@itemize @bullet
+@item
+Braces, @samp{@@} and periods.
+
+@item
+Format a dimension, such as @samp{12@dmn{pt}}.
+
+@item
+Dots and bullets.
+
+@item
+The @TeX{} logo and the copyright symbol.
+
+@item
+A minus sign.
+@end itemize
+@end iftex
+
+@menu
+* Braces Atsigns:: How to insert braces, @samp{@@}.
+* Inserting Space:: How to insert the right amount of space
+ within a sentence.
+* Inserting Accents:: How to insert accents and special characters.
+* Dots Bullets:: How to insert dots and bullets.
+* TeX and copyright:: How to insert the @TeX{} logo
+ and the copyright symbol.
+* pounds:: How to insert the pounds currency symbol.
+* minus:: How to insert a minus sign.
+* math:: How to format a mathematical expression.
+@end menu
+
+
+@node Braces Atsigns, Inserting Space, Insertions, Insertions
+@section Inserting @@ and Braces
+@cindex Inserting @@, braces
+@cindex Braces, inserting
+@cindex Special characters, commands to insert
+@cindex Commands to insert special characters
+
+@samp{@@} and curly braces are special characters in Texinfo. To insert
+these characters so they appear in text, you must put an @samp{@@} in
+front of these characters to prevent Texinfo from misinterpreting
+them.
+
+Do not put braces after any of these commands; they are not
+necessary.
+
+@menu
+* Inserting An Atsign:: How to insert @samp{@@}.
+* Inserting Braces:: How to insert @samp{@{} and @samp{@}}.
+@end menu
+
+@node Inserting An Atsign, Inserting Braces, Braces Atsigns, Braces Atsigns
+@subsection Inserting @samp{@@} with @@@@
+@findex @@ @r{(single @samp{@@})}
+
+@code{@@@@} stands for a single @samp{@@} in either printed or Info
+output.
+
+Do not put braces after an @code{@@@@} command.
+
+@node Inserting Braces, , Inserting An Atsign, Braces Atsigns
+@subsection Inserting @samp{@{} and @samp{@}}with @@@{ and @@@}
+@findex @{ @r{(single @samp{@{})}
+@findex @} @r{(single @samp{@}})}
+
+@code{@@@{} stands for a single @samp{@{} in either printed or Info
+output.
+
+@code{@@@}} stands for a single @samp{@}} in either printed or Info
+output.
+
+Do not put braces after either an @code{@@@{} or an @code{@@@}}
+command.
+
+
+@node Inserting Space, Inserting Accents, Braces Atsigns, Insertions
+@section Inserting Space
+
+@cindex Inserting space
+@cindex Spacing, inserting
+@cindex Whitespace, inserting
+The following sections describe commands that control spacing of various
+kinds within and after sentences.
+
+@menu
+* Not Ending a Sentence:: Sometimes a . doesn't end a sentence.
+* Ending a Sentence:: Sometimes it does.
+* Multiple Spaces:: Inserting multiple spaces.
+* dmn:: How to format a dimension.
+@end menu
+
+@node Not Ending a Sentence, Ending a Sentence, Inserting Space, Inserting Space
+@subsection Not Ending a Sentence
+
+@cindex Not ending a sentence
+@cindex Sentence non-ending punctuation
+@cindex Periods, inserting
+Depending on whether a period or exclamation point or question mark is
+inside or at the end of a sentence, less or more space is inserted after
+a period in a typeset manual. Since it is not always possible for
+Texinfo to determine when a period ends a sentence and when it is used
+in an abbreviation, special commands are needed in some circumstances.
+(Usually, Texinfo can guess how to handle periods, so you do not need to
+use the special commands; you just enter a period as you would if you
+were using a typewriter, which means you put two spaces after the
+period, question mark, or exclamation mark that ends a sentence.)
+
+@findex : @r{(suppress widening)}
+Use the @code{@@:}@: command after a period, question mark,
+exclamation mark, or colon that should not be followed by extra space.
+For example, use @code{@@:}@: after periods that end abbreviations
+which are not at the ends of sentences. @code{@@:}@: has no effect on
+the Info file output.
+
+@need 700
+For example,
+
+@example
+The s.o.p.@@: has three parts @dots{}
+The s.o.p. has three parts @dots{}
+@end example
+
+@noindent
+@ifinfo
+produces
+@end ifinfo
+@iftex
+produces the following. If you look carefully at this printed output,
+you will see a little more whitespace after @samp{s.o.p.} in the second
+line.@refill
+@end iftex
+
+@quotation
+The s.o.p.@: has three parts @dots{}@*
+The s.o.p. has three parts @dots{}
+@end quotation
+
+@noindent
+@kbd{@@:} has no effect on the Info output. (@samp{s.o.p.} is an
+abbreviation for ``Standard Operating Procedure''.)
+
+Do not put braces after @code{@@:}.
+
+
+@node Ending a Sentence, Multiple Spaces, Not Ending a Sentence, Inserting Space
+@subsection Ending a Sentence
+
+@cindex Ending a Sentence
+@cindex Sentence ending punctuation
+
+@findex . @r{(end of sentence)}
+@findex ! @r{(end of sentence)}
+@findex ? @r{(end of sentence)}
+Use @code{@@.}@: instead of a period, @code{@@!}@: instead of an
+exclamation point, and @code{@@?}@: instead of a question mark at the end
+of a sentence that ends with a single capital letter. Otherwise, @TeX{}
+will think the letter is an abbreviation and will not insert the correct
+end-of-sentence spacing. Here is an example:
+
+@example
+Give it to M.I.B. and to M.E.W@@. Also, give it to R.J.C@@.
+Give it to M.I.B. and to M.E.W. Also, give it to R.J.C.
+@end example
+
+@noindent
+@ifinfo
+produces
+@end ifinfo
+@iftex
+produces the following. If you look carefully at this printed output,
+you will see a little more whitespace after the @samp{W} in the first
+line.
+@end iftex
+
+@quotation
+Give it to M.I.B. and to M.E.W@. Also, give it to R.J.C@.@*
+Give it to M.I.B. and to M.E.W. Also, give it to R.J.C.
+@end quotation
+
+In the Info file output, @code{@@.}@: is equivalent to a simple
+@samp{.}; likewise for @code{@@!}@: and @code{@@?}@:.
+
+The meanings of @code{@@:} and @code{@@.}@: in Texinfo are designed to
+work well with the Emacs sentence motion commands (@pxref{Sentences,,,
+emacs, GNU Emacs}). This made it necessary for them to be incompatible
+with some other formatting systems that use @@-commands.
+
+Do not put braces after any of these commands.
+
+
+@node Multiple Spaces, dmn, Ending a Sentence, Inserting Space
+@subsection Multiple Spaces
+
+@cindex Multiple spaces
+@cindex Whitespace, inserting
+@findex (space)
+@findex (tab)
+@findex (newline)
+
+Ordinarily, @TeX{} collapses multiple whitespace characters (space, tab,
+and newline) into a single space. (Info output, on the other hand,
+preserves whitespace as you type it, except for changing a newline into
+a space; this is why it is important to put two spaces at the end of
+sentences in Texinfo documents.)
+
+Occasionally, you may want to actually insert several consecutive
+spaces, either for purposes of example (what your program does with
+multiple spaces as input), or merely for purposes of appearance in
+headings or lists. Texinfo supports three commands: @code{@@ },
+@code{@@@kbd{TAB}}, and @code{@@@kbd{NL}}, all of which insert a single
+space into the output. (Here, @kbd{TAB} and @kbd{NL} represent the tab
+character and end-of-line, i.e., when @samp{@@} is the last character on
+a line.)
+
+For example,
+@example
+Spacey@@ @@ @@ @@
+example.
+@end example
+
+@noindent produces
+
+@example
+Spacey@ @ @ @
+example.
+@end example
+
+Other possible uses of @code{@@ } have been subsumed by @code{@@multitable}
+(@pxref{Multi-column Tables}).
+
+Do not follow any of these commands with braces.
+
+
+@node dmn, , Multiple Spaces, Inserting Space
+@subsection @code{@@dmn}@{@var{dimension}@}: Format a Dimension
+@cindex Thin space between number, dimension
+@cindex Dimension formatting
+@cindex Format a dimension
+@findex dmn
+
+At times, you may want to write @samp{12@dmn{pt}} or
+@samp{8.5@dmn{in}} with little or no space between the number and the
+abbreviation for the dimension. You can use the @code{@@dmn} command
+to do this. On seeing the command, @TeX{} inserts just enough space
+for proper typesetting; the Info formatting commands insert no space
+at all, since the Info file does not require it.@refill
+
+To use the @code{@@dmn} command, write the number and then follow it
+immediately, with no intervening space, by @code{@@dmn}, and then by
+the dimension within braces.@refill
+
+@need 700
+@noindent
+For example,
+
+@example
+A4 paper is 8.27@@dmn@{in@} wide.
+@end example
+
+@noindent
+produces
+
+@quotation
+A4 paper is 8.27@dmn{in} wide.
+@end quotation
+
+Not everyone uses this style. Instead of writing
+@w{@samp{8.27@@dmn@{in@}}} in the Texinfo file, you may write
+@w{@samp{8.27 in.}} or @w{@samp{8.27 inches}}. (In these cases, the
+formatters may insert a line break between the number and the
+dimension. Also, if you write a period after an abbreviation within a
+sentence, you should write @samp{@@:} after the period to prevent
+@TeX{} from inserting extra whitespace. @xref{Inserting Space}.
+
+
+@node Inserting Accents, Dots Bullets, Inserting Space, Insertions
+@section Inserting Accents
+
+@cindex Inserting accents
+@cindex Accents, inserting
+@cindex Floating accents, inserting
+
+Here is a table with the commands Texinfo provides for inserting
+floating accents. The commands with non-alphabetic names do not take
+braces around their argument (which is taken to be the next character).
+(Exception: @code{@@,} @emph{does} take braces around its argument.)
+This is so as to make the source as convenient to type and read as
+possible, since accented characters are very common in some languages.
+
+@findex "
+@cindex Umlaut accent
+@findex '
+@cindex Acute accent
+@findex =
+@cindex Macron accent
+@findex ^
+@cindex Circumflex accent
+@findex `
+@cindex Grave accent
+@findex ~
+@cindex Tilde accent
+@findex ,
+@cindex Cedilla accent
+@findex dotaccent
+@cindex Dot accent
+@findex H
+@cindex Hungariam umlaut accent
+@findex ringaccent
+@cindex Ring accent
+@findex tieaccent
+@cindex Tie-after accent
+@findex u
+@cindex Breve accent
+@findex ubaraccent
+@cindex Underbar accent
+@findex udotaccent
+@cindex Underdot accent
+@findex v
+@cindex Check accent
+@multitable {@@questiondown@{@}} {Output} {macron/overbar accent}
+@item Command @tab Output @tab What
+@item @t{@@"o} @tab @"o @tab umlaut accent
+@item @t{@@'o} @tab @'o @tab acute accent
+@item @t{@@,@{c@}} @tab @,{c} @tab cedilla accent
+@item @t{@@=o} @tab @=o @tab macron/overbar accent
+@item @t{@@^o} @tab @^o @tab circumflex accent
+@item @t{@@`o} @tab @`o @tab grave accent
+@item @t{@@~o} @tab @~o @tab tilde accent
+@item @t{@@dotaccent@{o@}} @tab @dotaccent{o} @tab overdot accent
+@item @t{@@H@{o@}} @tab @H{o} @tab long Hungarian umlaut
+@item @t{@@ringaccent@{o@}} @tab @ringaccent{o} @tab ring accent
+@item @t{@@tieaccent@{oo@}} @tab @tieaccent{oo} @tab tie-after accent
+@item @t{@@u@{o@}} @tab @u{o} @tab breve accent
+@item @t{@@ubaraccent@{o@}} @tab @ubaraccent{o} @tab underbar accent
+@item @t{@@udotaccent@{o@}} @tab @udotaccent{o} @tab underdot accent
+@item @t{@@v@{o@}} @tab @v{o} @tab hacek or check accent
+@end multitable
+
+This table lists the Texinfo commands for inserting other characters
+commonly used in languages other than English.
+
+@findex questiondown
+@cindex @questiondown{}
+@findex exclamdown
+@cindex @exclamdown{}
+@findex aa
+@cindex @aa{}
+@findex AA
+@cindex @AA{}
+@findex ae
+@cindex @ae{}
+@findex AE
+@cindex @AE{}
+@findex dotless
+@cindex @dotless{i}
+@cindex @dotless{j}
+@cindex Dotless i, j
+@findex l
+@cindex @l{}
+@findex L
+@cindex @L{}
+@findex o
+@cindex @o{}
+@findex O
+@cindex @O{}
+@findex oe
+@cindex @oe{}
+@findex OE
+@cindex @OE{}
+@findex ss
+@cindex @ss{}
+@cindex Es-zet
+@cindex Sharp S
+@cindex German S
+@multitable {@@questiondown@{@}} {oe,OE} {es-zet or sharp S}
+@item @t{@@exclamdown@{@}} @tab @exclamdown{} @tab upside-down !
+@item @t{@@questiondown@{@}} @tab @questiondown{} @tab upside-down ?
+@item @t{@@aa@{@},@@AA@{@}} @tab @aa{},@AA{} @tab A,a with circle
+@item @t{@@ae@{@},@@AE@{@}} @tab @ae{},@AE{} @tab ae,AE ligatures
+@item @t{@@dotless@{i@}} @tab @dotless{i} @tab dotless i
+@item @t{@@dotless@{j@}} @tab @dotless{j} @tab dotless j
+@item @t{@@l@{@},@@L@{@}} @tab @l{},@L{} @tab suppressed-L,l
+@item @t{@@o@{@},@@O@{@}} @tab @o{},@O{} @tab O,o with slash
+@item @t{@@oe@{@},@@OE@{@}} @tab @oe{},@OE{} @tab OE,oe ligatures
+@item @t{@@ss@{@}} @tab @ss{} @tab es-zet or sharp S
+@end multitable
+
+
+@node Dots Bullets, TeX and copyright, Inserting Accents, Insertions
+@section Inserting Ellipsis, Dots, and Bullets
+@cindex Dots, inserting
+@cindex Bullets, inserting
+@cindex Ellipsis, inserting
+@cindex Inserting ellipsis
+@cindex Inserting dots
+@cindex Special typesetting commands
+@cindex Typesetting commands for dots, etc.
+
+An @dfn{ellipsis} (a line of dots) is not typeset as a string of
+periods, so a special command is used for ellipsis in Texinfo. The
+@code{@@bullet} command is special, too. Each of these commands is
+followed by a pair of braces, @samp{@{@}}, without any whitespace
+between the name of the command and the braces. (You need to use braces
+with these commands because you can use them next to other text; without
+the braces, the formatters would be confused. @xref{Command Syntax, ,
+@@-Command Syntax}, for further information.)@refill
+
+@menu
+* dots:: How to insert dots @dots{}
+* bullet:: How to insert a bullet.
+@end menu
+
+@node dots, bullet, Dots Bullets, Dots Bullets
+@comment node-name, next, previous, up
+@subsection @code{@@dots}@{@}
+@findex dots
+@cindex Inserting dots
+@cindex Dots, inserting
+
+Use the @code{@@dots@{@}} command to generate an ellipsis, which is
+three dots in a row, appropriately spaced, like this: `@dots{}'. Do
+not simply write three periods in the input file; that would work for
+the Info file output, but would produce the wrong amount of space
+between the periods in the printed manual.
+
+Similarly, the @code{@@enddots@{@}} command generates an
+end-of-sentence ellipsis (four dots) @enddots{}
+
+@iftex
+Here is an ellipsis: @dots{}
+Here are three periods in a row: ...
+
+In printed output, the three periods in a row are closer together than
+the dots in the ellipsis.
+@end iftex
+
+@node bullet, , dots, Dots Bullets
+@comment node-name, next, previous, up
+@subsection @code{@@bullet}@{@}
+@findex bullet
+
+Use the @code{@@bullet@{@}} command to generate a large round dot, or
+the closest possible thing to one. In Info, an asterisk is used.@refill
+
+Here is a bullet: @bullet{}
+
+When you use @code{@@bullet} in @code{@@itemize}, you do not need to
+type the braces, because @code{@@itemize} supplies them.
+(@xref{itemize, , @code{@@itemize}}.)@refill
+
+@node TeX and copyright, pounds, Dots Bullets, Insertions
+@comment node-name, next, previous, up
+@section Inserting @TeX{} and the Copyright Symbol
+
+The logo `@TeX{}' is typeset in a special fashion and it needs an
+@@-command. The copyright symbol, `@copyright{}', is also special.
+Each of these commands is followed by a pair of braces, @samp{@{@}},
+without any whitespace between the name of the command and the
+braces.@refill
+
+@menu
+* tex:: How to insert the @TeX{} logo.
+* copyright symbol:: How to use @code{@@copyright}@{@}.
+@end menu
+
+@node tex, copyright symbol, TeX and copyright, TeX and copyright
+@comment node-name, next, previous, up
+@subsection @code{@@TeX}@{@}
+@findex tex (command)
+
+Use the @code{@@TeX@{@}} command to generate `@TeX{}'. In a printed
+manual, this is a special logo that is different from three ordinary
+letters. In Info, it just looks like @samp{TeX}. The
+@code{@@TeX@{@}} command is unique among Texinfo commands in that the
+@kbd{T} and the @kbd{X} are in upper case.@refill
+
+@node copyright symbol, , tex, TeX and copyright
+@comment node-name, next, previous, up
+@subsection @code{@@copyright}@{@}
+@findex copyright
+
+Use the @code{@@copyright@{@}} command to generate `@copyright{}'. In
+a printed manual, this is a @samp{c} inside a circle, and in Info,
+this is @samp{(C)}.@refill
+
+@node pounds, minus, TeX and copyright, Insertions
+@section @code{@@pounds}@{@}
+@findex pounds
+
+Use the @code{@@pounds@{@}} command to generate `@pounds{}'. In a
+printed manual, this is the symbol for the currency pounds sterling.
+In Info, it is a @samp{#}. Other currency symbols are unfortunately not
+available.
+
+@node minus, math, pounds, Insertions
+@section @code{@@minus}@{@}: Inserting a Minus Sign
+@findex minus
+
+Use the @code{@@minus@{@}} command to generate a minus sign. In a
+fixed-width font, this is a single hyphen, but in a proportional font,
+the symbol is the customary length for a minus sign---a little longer
+than a hyphen.@refill
+
+You can compare the two forms:
+
+@display
+@samp{@minus{}} is a minus sign generated with @samp{@@minus@{@}},
+
+`-' is a hyphen generated with the character @samp{-}.
+@end display
+
+@noindent
+In the fixed-width font used by Info, @code{@@minus@{@}} is the same
+as a hyphen.@refill
+
+You should not use @code{@@minus@{@}} inside @code{@@code} or
+@code{@@example} because the width distinction is not made in the
+fixed-width font they use.@refill
+
+When you use @code{@@minus} to specify the mark beginning each entry in
+an itemized list, you do not need to type the braces
+(@pxref{itemize, , @code{@@itemize}}.)@refill
+
+@node math, , minus, Insertions
+@comment node-name, next, previous, up
+@section @code{@@math}: Inserting Mathematical Expressions
+@findex math
+@cindex Mathematical expressions
+
+You can write a short mathematical expression with the @code{@@math}
+command. Write the mathematical expression between braces, like this:
+
+@example
+@@math@{(a + b)(a + b) = a^2 + 2ab + b^2@}
+@end example
+
+@iftex
+@need 1000
+@noindent
+This produces the following in @TeX{}:
+
+@display
+@math{(a + b)(a + b) = a^2 + 2ab + b^2}
+@end display
+
+@noindent
+and the following in Info:
+@end iftex
+@ifinfo
+@noindent
+This produces the following in Info:
+@end ifinfo
+
+@example
+(a + b)(a + b) = a^2 + 2ab + b^2
+@end example
+
+The @code{@@math} command has no effect on the Info output. Currently,
+it has limited effect on typeset output. However, this may change since
+@TeX{} itself is designed for mathematical typesetting and does a
+splendid job.
+
+Certainly, for complex mathematical expressions, you could use @TeX{}
+directly. @xref{Using Ordinary TeX Commands, , Using Ordinary @TeX{}
+Commands}. When you use @TeX{} directly, remember to write the
+mathematical expression between one or two @samp{$} (dollar-signs) as
+appropriate.
+
+@node Glyphs, Breaks, Insertions, Top
+@comment node-name, next, previous, up
+@chapter Glyphs for Examples
+@cindex Glyphs
+
+In Texinfo, code is often illustrated in examples that are delimited
+by @code{@@example} and @code{@@end example}, or by @code{@@lisp} and
+@code{@@end lisp}. In such examples, you can indicate the results of
+evaluation or an expansion using @samp{@result{}} or
+@samp{@expansion{}}. Likewise, there are commands to insert glyphs
+to indicate
+printed output, error messages, equivalence of expressions, and the
+location of point.@refill
+
+The glyph-insertion commands do not need to be used within an example, but
+most often they are. Every glyph-insertion command is followed by a pair of
+left- and right-hand braces.@refill
+
+@menu
+* Glyphs Summary::
+* result:: How to show the result of expression.
+* expansion:: How to indicate an expansion.
+* Print Glyph:: How to indicate printed output.
+* Error Glyph:: How to indicate an error message.
+* Equivalence:: How to indicate equivalence.
+* Point Glyph:: How to indicate the location of point.
+@end menu
+
+@node Glyphs Summary, result, Glyphs, Glyphs
+@ifinfo
+@heading Glyphs Summary
+
+Here are the different glyph commands:@refill
+@end ifinfo
+
+@table @asis
+@item @result{}
+@code{@@result@{@}} points to the result of an expression.@refill
+
+@item @expansion{}
+@code{@@expansion@{@}} shows the results of a macro expansion.@refill
+
+@item @print{}
+@code{@@print@{@}} indicates printed output.@refill
+
+@item @error{}
+@code{@@error@{@}} indicates that the following text is an error
+message.@refill
+
+@item @equiv{}
+@code{@@equiv@{@}} indicates the exact equivalence of two forms.@refill
+
+@item @point{}
+@code{@@point@{@}} shows the location of point.@refill
+@end table
+
+@node result, expansion, Glyphs Summary, Glyphs
+@section @result{}: Indicating Evaluation
+@cindex Result of an expression
+@cindex Indicating evaluation
+@cindex Evaluation glyph
+@cindex Value of an expression, indicating
+
+Use the @code{@@result@{@}} command to indicate the result of
+evaluating an expression.@refill
+
+@iftex
+The @code{@@result@{@}} command is displayed as @samp{=>} in Info and
+as @samp{@result{}} in the printed output.
+@end iftex
+@ifinfo
+The @code{@@result@{@}} command is displayed as @samp{@result{}} in Info
+and as a double stemmed arrow in the printed output.@refill
+@end ifinfo
+
+Thus, the following,
+
+@lisp
+(cdr '(1 2 3))
+ @result{} (2 3)
+@end lisp
+
+@noindent
+may be read as ``@code{(cdr '(1 2 3))} evaluates to @code{(2 3)}''.
+
+@node expansion, Print Glyph, result, Glyphs
+@section @expansion{}: Indicating an Expansion
+@cindex Expansion, indicating it
+
+When an expression is a macro call, it expands into a new expression.
+You can indicate the result of the expansion with the
+@code{@@expansion@{@}} command.@refill
+
+@iftex
+The @code{@@expansion@{@}} command is displayed as @samp{==>} in Info and
+as @samp{@expansion{}} in the printed output.
+@end iftex
+@ifinfo
+The @code{@@expansion@{@}} command is displayed as @samp{@expansion{}}
+in Info and as a long arrow with a flat base in the printed output.@refill
+@end ifinfo
+
+@need 700
+For example, the following
+
+@example
+@group
+@@lisp
+(third '(a b c))
+ @@expansion@{@} (car (cdr (cdr '(a b c))))
+ @@result@{@} c
+@@end lisp
+@end group
+@end example
+
+@noindent
+produces
+
+@lisp
+@group
+(third '(a b c))
+ @expansion{} (car (cdr (cdr '(a b c))))
+ @result{} c
+@end group
+@end lisp
+
+@noindent
+which may be read as:
+
+@quotation
+@code{(third '(a b c))} expands to @code{(car (cdr (cdr '(a b c))))};
+the result of evaluating the expression is @code{c}.
+@end quotation
+
+@noindent
+Often, as in this case, an example looks better if the
+@code{@@expansion@{@}} and @code{@@result@{@}} commands are indented
+five spaces.@refill
+
+@node Print Glyph, Error Glyph, expansion, Glyphs
+@section @print{}: Indicating Printed Output
+@cindex Printed output, indicating it
+
+Sometimes an expression will print output during its execution. You
+can indicate the printed output with the @code{@@print@{@}} command.@refill
+
+@iftex
+The @code{@@print@{@}} command is displayed as @samp{-|} in Info and
+as @samp{@print{}} in the printed output.
+@end iftex
+@ifinfo
+The @code{@@print@{@}} command is displayed as @samp{@print{}} in Info
+and similarly, as a horizontal dash butting against a vertical bar, in
+the printed output.@refill
+@end ifinfo
+
+In the following example, the printed text is indicated with
+@samp{@print{}}, and the value of the expression follows on the
+last line.@refill
+
+@lisp
+@group
+(progn (print 'foo) (print 'bar))
+ @print{} foo
+ @print{} bar
+ @result{} bar
+@end group
+@end lisp
+
+@noindent
+In a Texinfo source file, this example is written as follows:
+
+@lisp
+@group
+@@lisp
+(progn (print 'foo) (print 'bar))
+ @@print@{@} foo
+ @@print@{@} bar
+ @@result@{@} bar
+@@end lisp
+@end group
+@end lisp
+
+@node Error Glyph, Equivalence, Print Glyph, Glyphs
+@section @error{}: Indicating an Error Message
+@cindex Error message, indicating it
+
+A piece of code may cause an error when you evaluate it. You can
+designate the error message with the @code{@@error@{@}} command.@refill
+
+@iftex
+The @code{@@error@{@}} command is displayed as @samp{error-->} in Info
+and as @samp{@error{}} in the printed output.
+@end iftex
+@ifinfo
+The @code{@@error@{@}} command is displayed as @samp{@error{}} in Info
+and as the word `error' in a box in the printed output.@refill
+@end ifinfo
+
+@need 700
+Thus,
+
+@example
+@@lisp
+(+ 23 'x)
+@@error@{@} Wrong type argument: integer-or-marker-p, x
+@@end lisp
+@end example
+
+@noindent
+produces
+
+@lisp
+(+ 23 'x)
+@error{} Wrong type argument: integer-or-marker-p, x
+@end lisp
+
+@noindent
+This indicates that the following error message is printed
+when you evaluate the expression:
+
+@lisp
+Wrong type argument: integer-or-marker-p, x
+@end lisp
+
+Note that @samp{@error{}} itself is not part of the error
+message.
+
+@node Equivalence, Point Glyph, Error Glyph, Glyphs
+@section @equiv{}: Indicating Equivalence
+@cindex Equivalence, indicating it
+
+Sometimes two expressions produce identical results. You can indicate the
+exact equivalence of two forms with the @code{@@equiv@{@}} command.@refill
+
+@iftex
+The @code{@@equiv@{@}} command is displayed as @samp{==} in Info and
+as @samp{@equiv{}} in the printed output.
+@end iftex
+@ifinfo
+The @code{@@equiv@{@}} command is displayed as @samp{@equiv{}} in Info
+and as a three parallel horizontal lines in the printed output.@refill
+@end ifinfo
+
+Thus,
+
+@example
+@@lisp
+(make-sparse-keymap) @@equiv@{@} (list 'keymap)
+@@end lisp
+@end example
+
+@noindent
+produces
+
+@lisp
+(make-sparse-keymap) @equiv{} (list 'keymap)
+@end lisp
+
+@noindent
+This indicates that evaluating @code{(make-sparse-keymap)} produces
+identical results to evaluating @code{(list 'keymap)}.
+
+@c Cannot write point command here because it causes trouble with TOC.
+@node Point Glyph, , Equivalence, Glyphs
+@section Indicating Point in a Buffer
+@cindex Point, indicating it in a buffer
+
+Sometimes you need to show an example of text in an Emacs buffer. In
+such examples, the convention is to include the entire contents of the
+buffer in question between two lines of dashes containing the buffer
+name.@refill
+
+You can use the @samp{@@point@{@}} command to show the location of point
+in the text in the buffer. (The symbol for point, of course, is not
+part of the text in the buffer; it indicates the place @emph{between}
+two characters where point is located.)@refill
+
+@iftex
+The @code{@@point@{@}} command is displayed as @samp{-!-} in Info and
+as @samp{@point{}} in the printed output.
+@end iftex
+@ifinfo
+The @code{@@point@{@}} command is displayed as @samp{@point{}} in Info
+and as a small five pointed star in the printed output.@refill
+@end ifinfo
+
+The following example shows the contents of buffer @file{foo} before
+and after evaluating a Lisp command to insert the word @code{changed}.@refill
+
+@example
+@group
+---------- Buffer: foo ----------
+This is the @point{}contents of foo.
+---------- Buffer: foo ----------
+
+@end group
+@end example
+
+@example
+@group
+(insert "changed ")
+ @result{} nil
+---------- Buffer: foo ----------
+This is the changed @point{}contents of foo.
+---------- Buffer: foo ----------
+
+@end group
+@end example
+
+In a Texinfo source file, the example is written like this:@refill
+
+@example
+@@example
+---------- Buffer: foo ----------
+This is the @@point@{@}contents of foo.
+---------- Buffer: foo ----------
+
+(insert "changed ")
+ @@result@{@} nil
+---------- Buffer: foo ----------
+This is the changed @@point@{@}contents of foo.
+---------- Buffer: foo ----------
+@@end example
+@end example
+
+@node Breaks, Definition Commands, Glyphs, Top
+@comment node-name, next, previous, up
+@chapter Making and Preventing Breaks
+@cindex Making line and page breaks
+@cindex Preventing line and page breaks
+
+Usually, a Texinfo file is processed both by @TeX{} and by one of the
+Info formatting commands. Line, paragraph, or page breaks sometimes
+occur in the `wrong' place in one or other form of output. You must
+ensure that text looks right both in the printed manual and in the
+Info file.@refill
+
+For example, in a printed manual, page breaks may occur awkwardly in
+the middle of an example; to prevent this, you can hold text together
+using a grouping command that keeps the text from being split across
+two pages. Conversely, you may want to force a page break where none
+would occur normally. Fortunately, problems like these do not often
+arise. When they do, use the break, break prevention, or pagination
+commands.@refill
+
+@menu
+* Break Commands:: Cause and prevent splits.
+* Line Breaks:: How to force a single line to use two lines.
+* - and hyphenation:: How to tell TeX about hyphenation points.
+* w:: How to prevent unwanted line breaks.
+* sp:: How to insert blank lines.
+* page:: How to force the start of a new page.
+* group:: How to prevent unwanted page breaks.
+* need:: Another way to prevent unwanted page breaks.
+@end menu
+
+@ifinfo
+@node Break Commands, Line Breaks, Breaks, Breaks
+@heading The Break Commands
+@end ifinfo
+@iftex
+@sp 1
+@end iftex
+
+The break commands create or allow line and paragraph breaks:@refill
+
+@table @code
+@item @@*
+Force a line break.
+
+@item @@sp @var{n}
+Skip @var{n} blank lines.@refill
+
+@item @@-
+Insert a discretionary hyphen.
+
+@item @@hyphenation@{@var{hy-phen-a-ted words}@}
+Define hyphen points in @var{hy-phen-a-ted words}.
+@end table
+
+The line-break-prevention command holds text together all on one
+line:@refill
+
+@table @code
+@item @@w@{@var{text}@}
+Prevent @var{text} from being split and hyphenated across two lines.@refill
+@end table
+@iftex
+@sp 1
+@end iftex
+
+The pagination commands apply only to printed output, since Info
+files do not have pages.@refill
+
+@table @code
+@item @@page
+Start a new page in the printed manual.@refill
+
+@item @@group
+Hold text together that must appear on one printed page.@refill
+
+@item @@need @var{mils}
+Start a new printed page if not enough space on this one.@refill
+@end table
+
+@node Line Breaks, - and hyphenation, Break Commands, Breaks
+@comment node-name, next, previous, up
+@section @code{@@*}: Generate Line Breaks
+@findex * @r{(force line break)}
+@cindex Line breaks
+@cindex Breaks in a line
+
+The @code{@@*} command forces a line break in both the printed manual and
+in Info.@refill
+
+@need 700
+For example,
+
+@example
+This line @@* is broken @@*in two places.
+@end example
+
+@noindent
+produces
+
+@example
+@group
+This line
+ is broken
+in two places.
+@end group
+@end example
+
+@noindent
+(Note that the space after the first @code{@@*} command is faithfully
+carried down to the next line.)@refill
+
+@need 800
+The @code{@@*} command is often used in a file's copyright page:@refill
+
+@example
+@group
+This is edition 2.0 of the Texinfo documentation,@@*
+and is for @dots{}
+@end group
+@end example
+
+@noindent
+In this case, the @code{@@*} command keeps @TeX{} from stretching the
+line across the whole page in an ugly manner.@refill
+
+@quotation
+@strong{Please note:} Do not write braces after an @code{@@*} command;
+they are not needed.@refill
+
+Do not write an @code{@@refill} command at the end of a paragraph
+containing an @code{@@*} command; it will cause the paragraph to be
+refilled after the line break occurs, negating the effect of the line
+break.@refill
+@end quotation
+
+@node - and hyphenation, w, Line Breaks, Breaks
+@section @code{@@-} and @code{@@hyphenation}: Helping @TeX{} hyphenate
+
+@findex -
+@findex hyphenation
+@cindex Hyphenation, helping @TeX{} do
+@cindex Fine-tuning, and hyphenation
+
+Although @TeX{}'s hyphenation algorithm is generally pretty good, it
+does miss useful hyphenation points from time to time. (Or, far more
+rarely, insert an incorrect hyphenation.) So, for documents with an
+unusual vocabulary or when fine-tuning for a printed edition, you may
+wish to help @TeX{} out. Texinfo supports two commands for this:
+
+@table @code
+@item @@-
+Insert a discretionary hyphen, i.e., a place where @TeX{} can (but does
+not have to) hyphenate. This is especially useful when you notice
+an overfull hbox is due to @TeX{} missing a hyphenation (@pxref{Overfull
+hboxes}). @TeX{} will not insert any hyphenation points in a word
+containing @code{@@-}.
+
+@item @@hyphenation@{@var{hy-phen-a-ted words}@}
+Tell @TeX{} how to hyphenate @var{hy-phen-a-ted words}. As shown, you
+put a @samp{-} at each hyphenation point. For example:
+@example
+@@hyphenation@{man-u-script man-u-scripts@}
+@end example
+@noindent @TeX{} only uses the specified hyphenation points when the
+words match exactly, so give all necessary variants.
+@end table
+
+Info output is not hyphenated, so these commands have no effect there.
+
+@node w, sp, - and hyphenation, Breaks
+@comment node-name, next, previous, up
+@section @code{@@w}@{@var{text}@}: Prevent Line Breaks
+@findex w @r{(prevent line break)}
+@cindex Line breaks, preventing
+@cindex Hyphenation, preventing
+
+@code{@@w@{@var{text}@}} outputs @var{text} and prohibits line breaks
+within @var{text}.@refill
+
+You can use the @code{@@w} command to prevent @TeX{} from automatically
+hyphenating a long name or phrase that accidentally falls near the end
+of a line.@refill
+
+@example
+You can copy GNU software from @@w@{@@file@{prep.ai.mit.edu@}@}.
+@end example
+
+@noindent
+produces
+
+@quotation
+You can copy GNU software from @w{@file{prep.ai.mit.edu}}.
+@end quotation
+
+@quotation
+@strong{Caution:} Do not write an @code{@@refill} command at the end
+of a paragraph containing an @code{@@w} command; it will cause the
+paragraph to be refilled and may thereby negate the effect of the
+@code{@@w} command.@refill
+@end quotation
+
+@node sp, page, w, Breaks
+@comment node-name, next, previous, up
+@section @code{@@sp} @var{n}: Insert Blank Lines
+@findex sp @r{(line spacing)}
+@cindex Spaces (blank lines)
+@cindex Blank lines
+@cindex Line spacing
+
+A line beginning with and containing only @code{@@sp @var{n}}
+generates @var{n} blank lines of space in both the printed manual and
+the Info file. @code{@@sp} also forces a paragraph break. For
+example,@refill
+
+@example
+@@sp 2
+@end example
+
+@noindent
+generates two blank lines.
+
+The @code{@@sp} command is most often used in the title page.@refill
+
+@ignore
+@c node br, page, sp, Breaks
+@comment node-name, next, previous, up
+@c section @code{@@br}: Generate Paragraph Breaks
+@findex br @r{(paragraph breaks)}
+@cindex Paragraph breaks
+@cindex Breaks in a paragraph
+
+The @code{@@br} command forces a paragraph break. It inserts a blank
+line. You can use the command within or at the end of a line. If
+used within a line, the @code{@@br@{@}} command must be followed by
+left and right braces (as shown here) to mark the end of the
+command.@refill
+
+@need 700
+For example,
+
+@example
+@group
+This line @@br@{@}contains and is ended by paragraph breaks@@br
+and is followed by another line.
+@end group
+@end example
+
+@noindent
+produces
+
+@example
+@group
+This line
+
+contains and is ended by paragraph breaks
+
+and is followed by another line.
+@end group
+@end example
+
+The @code{@@br} command is seldom used.
+@end ignore
+
+@node page, group, sp, Breaks
+@comment node-name, next, previous, up
+@section @code{@@page}: Start a New Page
+@cindex Page breaks
+@findex page
+
+A line containing only @code{@@page} starts a new page in a printed
+manual. The command has no effect on Info files since they are not
+paginated. An @code{@@page} command is often used in the @code{@@titlepage}
+section of a Texinfo file to start the copyright page.@refill
+
+@node group, need, page, Breaks
+@comment node-name, next, previous, up
+@section @code{@@group}: Prevent Page Breaks
+@cindex Group (hold text together vertically)
+@cindex Holding text together vertically
+@cindex Vertically holding text together
+@findex group
+
+The @code{@@group} command (on a line by itself) is used inside an
+@code{@@example} or similar construct to begin an unsplittable vertical
+group, which will appear entirely on one page in the printed output.
+The group is terminated by a line containing only @code{@@end group}.
+These two lines produce no output of their own, and in the Info file
+output they have no effect at all.@refill
+
+@c Once said that these environments
+@c turn off vertical spacing between ``paragraphs''.
+@c Also, quotation used to work, but doesn't in texinfo-2.72
+Although @code{@@group} would make sense conceptually in a wide
+variety of contexts, its current implementation works reliably only
+within @code{@@example} and variants, and within @code{@@display},
+@code{@@format}, @code{@@flushleft} and @code{@@flushright}.
+@xref{Quotations and Examples}. (What all these commands have in
+common is that each line of input produces a line of output.) In
+other contexts, @code{@@group} can cause anomalous vertical
+spacing.@refill
+
+@need 750
+This formatting requirement means that you should write:
+
+@example
+@group
+@@example
+@@group
+@dots{}
+@@end group
+@@end example
+@end group
+@end example
+
+@noindent
+with the @code{@@group} and @code{@@end group} commands inside the
+@code{@@example} and @code{@@end example} commands.
+
+The @code{@@group} command is most often used to hold an example
+together on one page. In this Texinfo manual, more than 100 examples
+contain text that is enclosed between @code{@@group} and @code{@@end
+group}.
+
+If you forget to end a group, you may get strange and unfathomable
+error messages when you run @TeX{}. This is because @TeX{} keeps
+trying to put the rest of the Texinfo file onto the one page and does
+not start to generate error messages until it has processed
+considerable text. It is a good rule of thumb to look for a missing
+@code{@@end group} if you get incomprehensible error messages in
+@TeX{}.@refill
+
+@node need, , group, Breaks
+@comment node-name, next, previous, up
+@section @code{@@need @var{mils}}: Prevent Page Breaks
+@cindex Need space at page bottom
+@findex need
+
+A line containing only @code{@@need @var{n}} starts
+a new page in a printed manual if fewer than @var{n} mils (thousandths
+of an inch) remain on the current page. Do not use
+braces around the argument @var{n}. The @code{@@need} command has no
+effect on Info files since they are not paginated.@refill
+
+@need 800
+This paragraph is preceded by an @code{@@need} command that tells
+@TeX{} to start a new page if fewer than 800 mils (eight-tenths
+inch) remain on the page. It looks like this:@refill
+
+@example
+@group
+@@need 800
+This paragraph is preceded by @dots{}
+@end group
+@end example
+
+The @code{@@need} command is useful for preventing orphans (single
+lines at the bottoms of printed pages).@refill
+
+@node Definition Commands, Footnotes, Breaks, Top
+@chapter Definition Commands
+@cindex Definition commands
+
+The @code{@@deffn} command and the other @dfn{definition commands}
+enable you to describe functions, variables, macros, commands, user
+options, special forms and other such artifacts in a uniform
+format.@refill
+
+In the Info file, a definition causes the entity
+category---`Function', `Variable', or whatever---to appear at the
+beginning of the first line of the definition, followed by the
+entity's name and arguments. In the printed manual, the command
+causes @TeX{} to print the entity's name and its arguments on the left
+margin and print the category next to the right margin. In both
+output formats, the body of the definition is indented. Also, the
+name of the entity is entered into the appropriate index:
+@code{@@deffn} enters the name into the index of functions,
+@code{@@defvr} enters it into the index of variables, and so
+on.@refill
+
+A manual need not and should not contain more than one definition for
+a given name. An appendix containing a summary should use
+@code{@@table} rather than the definition commands.@refill
+
+@menu
+* Def Cmd Template:: How to structure a description using a
+ definition command.
+* Optional Arguments:: How to handle optional and repeated arguments.
+* deffnx:: How to group two or more `first' lines.
+* Def Cmds in Detail:: All the definition commands.
+* Def Cmd Conventions:: Conventions for writing definitions.
+* Sample Function Definition::
+@end menu
+
+@node Def Cmd Template, Optional Arguments, Definition Commands, Definition Commands
+@section The Template for a Definition
+@cindex Definition template
+@cindex Template for a definition
+
+The @code{@@deffn} command is used for definitions of entities that
+resemble functions. To write a definition using the @code{@@deffn}
+command, write the @code{@@deffn} command at the beginning of a line
+and follow it on the same line by the category of the entity, the name
+of the entity itself, and its arguments (if any). Then write the body
+of the definition on succeeding lines. (You may embed examples in the
+body.) Finally, end the definition with an @code{@@end deffn} command
+written on a line of its own. (The other definition commands follow
+the same format.)@refill
+
+The template for a definition looks like this:
+
+@example
+@group
+@@deffn @var{category} @var{name} @var{arguments}@dots{}
+@var{body-of-definition}
+@@end deffn
+@end group
+@end example
+
+@need 700
+@noindent
+For example,
+
+@example
+@group
+@@deffn Command forward-word count
+This command moves point forward @@var@{count@} words
+(or backward if @@var@{count@} is negative). @dots{}
+@@end deffn
+@end group
+@end example
+
+@noindent
+produces
+
+@quotation
+@deffn Command forward-word count
+This function moves point forward @var{count} words
+(or backward if @var{count} is negative). @dots{}
+@end deffn
+@end quotation
+
+Capitalize the category name like a title. If the name of the
+category contains spaces, as in the phrase `Interactive Command',
+write braces around it. For example:@refill
+
+@example
+@group
+@@deffn @{Interactive Command@} isearch-forward
+@dots{}
+@@end deffn
+@end group
+@end example
+
+@noindent
+Otherwise, the second word will be mistaken for the name of the
+entity.@refill
+
+Some of the definition commands are more general than others. The
+@code{@@deffn} command, for example, is the general definition command
+for functions and the like---for entities that may take arguments. When
+you use this command, you specify the category to which the entity
+belongs. The @code{@@deffn} command possesses three predefined,
+specialized variations, @code{@@defun}, @code{@@defmac}, and
+@code{@@defspec}, that specify the category for you: ``Function'',
+``Macro'', and ``Special Form'' respectively. The @code{@@defvr}
+command also is accompanied by several predefined, specialized
+variations for describing particular kinds of variables.@refill
+
+The template for a specialized definition, such as @code{@@defun}, is
+similar to the template for a generalized definition, except that you
+do not need to specify the category:@refill
+
+@example
+@group
+@@defun @var{name} @var{arguments}@dots{}
+@var{body-of-definition}
+@@end defun
+@end group
+@end example
+
+@noindent
+Thus,
+
+@example
+@group
+@@defun buffer-end flag
+This function returns @@code@{(point-min)@} if @@var@{flag@}
+is less than 1, @@code@{(point-max)@} otherwise.
+@dots{}
+@@end defun
+@end group
+@end example
+
+@noindent
+produces
+
+@quotation
+@defun buffer-end flag
+This function returns @code{(point-min)} if @var{flag} is less than 1,
+@code{(point-max)} otherwise. @dots{}
+@end defun
+@end quotation
+
+@noindent
+@xref{Sample Function Definition, Sample Function Definition, A Sample
+Function Definition}, for a more detailed example of a function
+definition, including the use of @code{@@example} inside the
+definition.@refill
+
+The other specialized commands work like @code{@@defun}.@refill
+
+@node Optional Arguments, deffnx, Def Cmd Template, Definition Commands
+@section Optional and Repeated Arguments
+@cindex Optional and repeated arguments
+@cindex Repeated and optional arguments
+@cindex Arguments, repeated and optional
+@cindex Syntax, optional & repeated arguments
+@cindex Meta-syntactic chars for arguments
+
+Some entities take optional or repeated arguments, which may be
+specified by a distinctive glyph that uses square brackets and
+ellipses. For @w{example}, a special form often breaks its argument list
+into separate arguments in more complicated ways than a
+straightforward function.@refill
+
+@iftex
+An argument enclosed within square brackets is optional.
+Thus, the phrase
+@samp{@code{@r{[}@var{optional-arg}@r{]}}} means that
+@var{optional-arg} is optional.
+An argument followed by an ellipsis is optional
+and may be repeated more than once.
+@c This is consistent with Emacs Lisp Reference manual
+Thus, @samp{@var{repeated-args}@dots{}} stands for zero or more arguments.
+Parentheses are used when several arguments are grouped
+into additional levels of list structure in Lisp.
+@end iftex
+@c The following looks better in Info (no `r', `samp' and `code'):
+@ifinfo
+An argument enclosed within square brackets is optional.
+Thus, [@var{optional-arg}] means that @var{optional-arg} is optional.
+An argument followed by an ellipsis is optional
+and may be repeated more than once.
+@c This is consistent with Emacs Lisp Reference manual
+Thus, @var{repeated-args}@dots{} stands for zero or more arguments.
+Parentheses are used when several arguments are grouped
+into additional levels of list structure in Lisp.
+@end ifinfo
+
+Here is the @code{@@defspec} line of an example of an imaginary
+special form:@refill
+
+@quotation
+@defspec foobar (@var{var} [@var{from} @var{to} [@var{inc}]]) @var{body}@dots{}
+@end defspec
+@tex
+\vskip \parskip
+@end tex
+@end quotation
+
+@noindent
+In this example, the arguments @var{from} and @var{to} are optional,
+but must both be present or both absent. If they are present,
+@var{inc} may optionally be specified as well. These arguments are
+grouped with the argument @var{var} into a list, to distinguish them
+from @var{body}, which includes all remaining elements of the
+form.@refill
+
+In a Texinfo source file, this @code{@@defspec} line is written like
+this (except it would not be split over two lines, as it is in this
+example).@refill
+
+@example
+@group
+@@defspec foobar (@@var@{var@} [@@var@{from@} @@var@{to@}
+ [@@var@{inc@}]]) @@var@{body@}@@dots@{@}
+@end group
+@end example
+
+@noindent
+The function is listed in the Command and Variable Index under
+@samp{foobar}.@refill
+
+@node deffnx, Def Cmds in Detail, Optional Arguments, Definition Commands
+@section Two or More `First' Lines
+@cindex Two `First' Lines for @code{@@deffn}
+@cindex Grouping two definitions together
+@cindex Definitions grouped together
+@findex deffnx
+
+To create two or more `first' or header lines for a definition, follow
+the first @code{@@deffn} line by a line beginning with @code{@@deffnx}.
+The @code{@@deffnx} command works exactly like @code{@@deffn}
+except that it does not generate extra vertical white space between it
+and the preceding line.@refill
+
+@need 1000
+For example,
+
+@example
+@group
+@@deffn @{Interactive Command@} isearch-forward
+@@deffnx @{Interactive Command@} isearch-backward
+These two search commands are similar except @dots{}
+@@end deffn
+@end group
+@end example
+
+@noindent
+produces
+
+@deffn {Interactive Command} isearch-forward
+@deffnx {Interactive Command} isearch-backward
+These two search commands are similar except @dots{}
+@end deffn
+
+Each of the other definition commands has an `x' form: @code{@@defunx},
+@code{@@defvrx}, @code{@@deftypefunx}, etc.
+
+The `x' forms work just like @code{@@itemx}; see @ref{itemx, , @code{@@itemx}}.
+
+@node Def Cmds in Detail, Def Cmd Conventions, deffnx, Definition Commands
+@section The Definition Commands
+
+Texinfo provides more than a dozen definition commands, all of which
+are described in this section.@refill
+
+The definition commands automatically enter the name of the entity in
+the appropriate index: for example, @code{@@deffn}, @code{@@defun},
+and @code{@@defmac} enter function names in the index of functions;
+@code{@@defvr} and @code{@@defvar} enter variable names in the index
+of variables.@refill
+
+Although the examples that follow mostly illustrate Lisp, the commands
+can be used for other programming languages.@refill
+
+@menu
+* Functions Commands:: Commands for functions and similar entities.
+* Variables Commands:: Commands for variables and similar entities.
+* Typed Functions:: Commands for functions in typed languages.
+* Typed Variables:: Commands for variables in typed languages.
+* Abstract Objects:: Commands for object-oriented programming.
+* Data Types:: The definition command for data types.
+@end menu
+
+@node Functions Commands, Variables Commands, Def Cmds in Detail, Def Cmds in Detail
+@subsection Functions and Similar Entities
+
+This section describes the commands for describing functions and similar
+entities:@refill
+
+@table @code
+@findex deffn
+@item @@deffn @var{category} @var{name} @var{arguments}@dots{}
+The @code{@@deffn} command is the general definition command for
+functions, interactive commands, and similar entities that may take
+arguments. You must choose a term to describe the category of entity
+being defined; for example, ``Function'' could be used if the entity is
+a function. The @code{@@deffn} command is written at the beginning of a
+line and is followed on the same line by the category of entity being
+described, the name of this particular entity, and its arguments, if
+any. Terminate the definition with @code{@@end deffn} on a line of its
+own.@refill
+
+@need 750
+For example, here is a definition:
+
+@example
+@group
+@@deffn Command forward-char nchars
+Move point forward @@var@{nchars@} characters.
+@@end deffn
+@end group
+@end example
+
+@noindent
+This shows a rather terse definition for a ``command'' named
+@code{forward-char} with one argument, @var{nchars}.
+
+@code{@@deffn} prints argument names such as @var{nchars} in italics or
+upper case, as if @code{@@var} had been used, because we think of these
+names as metasyntactic variables---they stand for the actual argument
+values. Within the text of the description, write an argument name
+explicitly with @code{@@var} to refer to the value of the argument. In
+the example above, we used @samp{@@var@{nchars@}} in this way.
+
+The template for @code{@@deffn} is:
+
+@example
+@group
+@@deffn @var{category} @var{name} @var{arguments}@dots{}
+@var{body-of-definition}
+@@end deffn
+@end group
+@end example
+
+@findex defun
+@item @@defun @var{name} @var{arguments}@dots{}
+The @code{@@defun} command is the definition command for functions.
+@code{@@defun} is equivalent to @samp{@@deffn Function
+@dots{}}.@refill
+
+@need 800
+@noindent
+For example,
+
+@example
+@group
+@@defun set symbol new-value
+Change the value of the symbol @@var@{symbol@}
+to @@var@{new-value@}.
+@@end defun
+@end group
+@end example
+
+@noindent
+shows a rather terse definition for a function @code{set} whose
+arguments are @var{symbol} and @var{new-value}. The argument names on
+the @code{@@defun} line automatically appear in italics or upper case as
+if they were enclosed in @code{@@var}. Terminate the definition with
+@code{@@end defun} on a line of its own.@refill
+
+The template is:
+
+@example
+@group
+@@defun @var{function-name} @var{arguments}@dots{}
+@var{body-of-definition}
+@@end defun
+@end group
+@end example
+
+@code{@@defun} creates an entry in the index of functions.
+
+@findex defmac
+@item @@defmac @var{name} @var{arguments}@dots{}
+The @code{@@defmac} command is the definition command for macros.
+@code{@@defmac} is equivalent to @samp{@@deffn Macro @dots{}} and
+works like @code{@@defun}.@refill
+
+@findex defspec
+@item @@defspec @var{name} @var{arguments}@dots{}
+The @code{@@defspec} command is the definition command for special
+forms. (In Lisp, a special form is an entity much like a function.)
+@code{@@defspec} is equivalent to @samp{@@deffn @{Special Form@}
+@dots{}} and works like @code{@@defun}.@refill
+@end table
+
+@node Variables Commands, Typed Functions, Functions Commands, Def Cmds in Detail
+@subsection Variables and Similar Entities
+
+Here are the commands for defining variables and similar
+entities:@refill
+
+@table @code
+@findex defvr
+@item @@defvr @var{category} @var{name}
+The @code{@@defvr} command is a general definition command for
+something like a variable---an entity that records a value. You must
+choose a term to describe the category of entity being defined; for
+example, ``Variable'' could be used if the entity is a variable.
+Write the @code{@@defvr} command at the beginning of a line and
+followed it on the same line by the category of the entity and the
+name of the entity.@refill
+
+Capitalize the category name like a title. If the name of the
+category contains spaces, as in the name `User Option', write braces
+around it. Otherwise, the second word will be mistaken for the name
+of the entity, for example:
+
+@example
+@group
+@@defvr @{User Option@} fill-column
+This buffer-local variable specifies
+the maximum width of filled lines.
+@dots{}
+@@end defvr
+@end group
+@end example
+
+Terminate the definition with @code{@@end defvr} on a line of its
+own.@refill
+
+The template is:
+
+@example
+@group
+@@defvr @var{category} @var{name}
+@var{body-of-definition}
+@@end defvr
+@end group
+@end example
+
+@code{@@defvr} creates an entry in the index of variables for @var{name}.
+
+@findex defvar
+@item @@defvar @var{name}
+The @code{@@defvar} command is the definition command for variables.
+@code{@@defvar} is equivalent to @samp{@@defvr Variable
+@dots{}}.@refill
+
+@need 750
+For example:
+
+@example
+@group
+@@defvar kill-ring
+@dots{}
+@@end defvar
+@end group
+@end example
+
+The template is:
+
+@example
+@group
+@@defvar @var{name}
+@var{body-of-definition}
+@@end defvar
+@end group
+@end example
+
+@code{@@defvar} creates an entry in the index of variables for
+@var{name}.@refill
+
+@findex defopt
+@item @@defopt @var{name}
+The @code{@@defopt} command is the definition command for user
+options. @code{@@defopt} is equivalent to @samp{@@defvr @{User
+Option@} @dots{}} and works like @code{@@defvar}.@refill
+@end table
+
+@node Typed Functions, Typed Variables, Variables Commands, Def Cmds in Detail
+@subsection Functions in Typed Languages
+
+The @code{@@deftypefn} command and its variations are for describing
+functions in C or any other language in which you must declare types
+of variables and functions.@refill
+
+@table @code
+@findex deftypefn
+@item @@deftypefn @var{category} @var{data-type} @var{name} @var{arguments}@dots{}
+The @code{@@deftypefn} command is the general definition command for
+functions and similar entities that may take arguments and that are
+typed. The @code{@@deftypefn} command is written at the beginning of
+a line and is followed on the same line by the category of entity
+being described, the type of the returned value, the name of this
+particular entity, and its arguments, if any.@refill
+
+@need 800
+@noindent
+For example,
+
+@example
+@group
+@@deftypefn @{Library Function@} int foobar
+ (int @@var@{foo@}, float @@var@{bar@})
+@dots{}
+@@end deftypefn
+@end group
+@end example
+
+@need 1000
+@noindent
+(where the text before the ``@dots{}'', shown above as two lines, would
+actually be a single line in a real Texinfo file) produces the following
+in Info:
+
+@smallexample
+@group
+-- Library Function: int foobar (int FOO, float BAR)
+@dots{}
+@end group
+@end smallexample
+@iftex
+
+In a printed manual, it produces:
+
+@quotation
+@deftypefn {Library Function} int foobar (int @var{foo}, float @var{bar})
+@dots{}
+@end deftypefn
+@end quotation
+@end iftex
+
+This means that @code{foobar} is a ``library function'' that returns an
+@code{int}, and its arguments are @var{foo} (an @code{int}) and
+@var{bar} (a @code{float}).@refill
+
+The argument names that you write in @code{@@deftypefn} are not subject
+to an implicit @code{@@var}---since the actual names of the arguments in
+@code{@@deftypefn} are typically scattered among data type names and
+keywords, Texinfo cannot find them without help. Instead, you must write
+@code{@@var} explicitly around the argument names. In the example
+above, the argument names are @samp{foo} and @samp{bar}.@refill
+
+The template for @code{@@deftypefn} is:@refill
+
+@example
+@group
+@@deftypefn @var{category} @var{data-type} @var{name} @var{arguments} @dots{}
+@var{body-of-description}
+@@end deftypefn
+@end group
+@end example
+
+@noindent
+Note that if the @var{category} or @var{data type} is more than one
+word then it must be enclosed in braces to make it a single argument.@refill
+
+If you are describing a procedure in a language that has packages,
+such as Ada, you might consider using @code{@@deftypefn} in a manner
+somewhat contrary to the convention described in the preceding
+paragraphs.@refill
+
+@need 800
+@noindent
+For example:
+
+@example
+@group
+@@deftypefn stacks private push
+ (@@var@{s@}:in out stack;
+ @@var@{n@}:in integer)
+@dots{}
+@@end deftypefn
+@end group
+@end example
+
+@noindent
+(The @code{@@deftypefn} arguments are shown split into three lines, but
+would be a single line in a real Texinfo file.)
+
+In this instance, the procedure is classified as belonging to the
+package @code{stacks} rather than classified as a `procedure' and its
+data type is described as @code{private}. (The name of the procedure
+is @code{push}, and its arguments are @var{s} and @var{n}.)@refill
+
+@code{@@deftypefn} creates an entry in the index of functions for
+@var{name}.@refill
+
+@findex deftypefun
+@item @@deftypefun @var{data-type} @var{name} @var{arguments}@dots{}
+The @code{@@deftypefun} command is the specialized definition command
+for functions in typed languages. The command is equivalent to
+@samp{@@deftypefn Function @dots{}}.@refill
+
+@need 800
+@noindent
+Thus,
+
+@smallexample
+@group
+@@deftypefun int foobar (int @@var@{foo@}, float @@var@{bar@})
+@dots{}
+@@end deftypefun
+@end group
+@end smallexample
+
+@noindent
+produces the following in Info:
+
+@example
+@group
+-- Function: int foobar (int FOO, float BAR)
+@dots{}
+@end group
+@end example
+@iftex
+
+@need 800
+@noindent
+and the following in a printed manual:
+
+@quotation
+@deftypefun int foobar (int @var{foo}, float @var{bar})
+@dots{}
+@end deftypefun
+@end quotation
+@end iftex
+
+@need 800
+The template is:
+
+@example
+@group
+@@deftypefun @var{type} @var{name} @var{arguments}@dots{}
+@var{body-of-description}
+@@end deftypefun
+@end group
+@end example
+
+@code{@@deftypefun} creates an entry in the index of functions for
+@var{name}.@refill
+@end table
+
+@node Typed Variables, Abstract Objects, Typed Functions, Def Cmds in Detail
+@subsection Variables in Typed Languages
+
+Variables in typed languages are handled in a manner similar to
+functions in typed languages. @xref{Typed Functions}. The general
+definition command @code{@@deftypevr} corresponds to
+@code{@@deftypefn} and the specialized definition command
+@code{@@deftypevar} corresponds to @code{@@deftypefun}.@refill
+
+@table @code
+@findex deftypevr
+@item @@deftypevr @var{category} @var{data-type} @var{name}
+The @code{@@deftypevr} command is the general definition command for
+something like a variable in a typed language---an entity that records
+a value. You must choose a term to describe the category of the
+entity being defined; for example, ``Variable'' could be used if the
+entity is a variable.@refill
+
+The @code{@@deftypevr} command is written at the beginning of a line
+and is followed on the same line by the category of the entity
+being described, the data type, and the name of this particular
+entity.@refill
+
+@need 800
+@noindent
+For example:
+
+@example
+@group
+@@deftypevr @{Global Flag@} int enable
+@dots{}
+@@end deftypevr
+@end group
+@end example
+
+@noindent
+produces the following in Info:
+
+@example
+@group
+-- Global Flag: int enable
+@dots{}
+@end group
+@end example
+@iftex
+
+@noindent
+and the following in a printed manual:
+
+@quotation
+@deftypevr {Global Flag} int enable
+@dots{}
+@end deftypevr
+@end quotation
+@end iftex
+
+@need 800
+The template is:
+
+@example
+@@deftypevr @var{category} @var{data-type} @var{name}
+@var{body-of-description}
+@@end deftypevr
+@end example
+
+@code{@@deftypevr} creates an entry in the index of variables for
+@var{name}.@refill
+
+@findex deftypevar
+@item @@deftypevar @var{data-type} @var{name}
+The @code{@@deftypevar} command is the specialized definition command
+for variables in typed languages. @code{@@deftypevar} is equivalent
+to @samp{@@deftypevr Variable @dots{}}.@refill
+
+@need 800
+@noindent
+For example:
+
+@example
+@group
+@@deftypevar int fubar
+@dots{}
+@@end deftypevar
+@end group
+@end example
+
+@noindent
+produces the following in Info:
+
+@example
+@group
+-- Variable: int fubar
+@dots{}
+@end group
+@end example
+@iftex
+
+@need 800
+@noindent
+and the following in a printed manual:
+
+@quotation
+@deftypevar int fubar
+@dots{}
+@end deftypevar
+@end quotation
+@end iftex
+
+@need 800
+@noindent
+The template is:
+
+@example
+@group
+@@deftypevar @var{data-type} @var{name}
+@var{body-of-description}
+@@end deftypevar
+@end group
+@end example
+
+@code{@@deftypevar} creates an entry in the index of variables for
+@var{name}.@refill
+@end table
+
+@node Abstract Objects, Data Types, Typed Variables, Def Cmds in Detail
+@subsection Object-Oriented Programming
+
+Here are the commands for formatting descriptions about abstract
+objects, such as are used in object-oriented programming. A class is
+a defined type of abstract object. An instance of a class is a
+particular object that has the type of the class. An instance
+variable is a variable that belongs to the class but for which each
+instance has its own value.@refill
+
+In a definition, if the name of a class is truly a name defined in the
+programming system for a class, then you should write an @code{@@code}
+around it. Otherwise, it is printed in the usual text font.@refill
+
+@table @code
+@findex defcv
+@item @@defcv @var{category} @var{class} @var{name}
+The @code{@@defcv} command is the general definition command for
+variables associated with classes in object-oriented programming. The
+@code{@@defcv} command is followed by three arguments: the category of
+thing being defined, the class to which it belongs, and its
+name. Thus,@refill
+
+@example
+@group
+@@defcv @{Class Option@} Window border-pattern
+@dots{}
+@@end defcv
+@end group
+@end example
+
+@noindent
+illustrates how you would write the first line of a definition of the
+@code{border-pattern} class option of the class @code{Window}.@refill
+
+The template is
+
+@example
+@group
+@@defcv @var{category} @var{class} @var{name}
+@dots{}
+@@end defcv
+@end group
+@end example
+
+@code{@@defcv} creates an entry in the index of variables.
+
+@findex defivar
+@item @@defivar @var{class} @var{name}
+The @code{@@defivar} command is the definition command for instance
+variables in object-oriented programming. @code{@@defivar} is
+equivalent to @samp{@@defcv @{Instance Variable@} @dots{}}@refill
+
+The template is:
+
+@example
+@group
+@@defivar @var{class} @var{instance-variable-name}
+@var{body-of-definition}
+@@end defivar
+@end group
+@end example
+
+@code{@@defivar} creates an entry in the index of variables.
+
+@findex defop
+@item @@defop @var{category} @var{class} @var{name} @var{arguments}@dots{}
+The @code{@@defop} command is the general definition command for
+entities that may resemble methods in object-oriented programming.
+These entities take arguments, as functions do, but are associated
+with particular classes of objects.@refill
+
+For example, some systems have constructs called @dfn{wrappers} that
+are associated with classes as methods are, but that act more like
+macros than like functions. You could use @code{@@defop Wrapper} to
+describe one of these.@refill
+
+Sometimes it is useful to distinguish methods and @dfn{operations}.
+You can think of an operation as the specification for a method.
+Thus, a window system might specify that all window classes have a
+method named @code{expose}; we would say that this window system
+defines an @code{expose} operation on windows in general. Typically,
+the operation has a name and also specifies the pattern of arguments;
+all methods that implement the operation must accept the same
+arguments, since applications that use the operation do so without
+knowing which method will implement it.@refill
+
+Often it makes more sense to document operations than methods. For
+example, window application developers need to know about the
+@code{expose} operation, but need not be concerned with whether a
+given class of windows has its own method to implement this operation.
+To describe this operation, you would write:@refill
+
+@example
+@@defop Operation windows expose
+@end example
+
+The @code{@@defop} command is written at the beginning of a line and
+is followed on the same line by the overall name of the category of
+operation, the name of the class of the operation, the name of the
+operation, and its arguments, if any.@refill
+
+@need 800
+@noindent
+The template is:
+
+@example
+@group
+@@defop @var{category} @var{class} @var{name} @var{arguments}@dots{}
+@var{body-of-definition}
+@@end defop
+@end group
+@end example
+
+@code{@@defop} creates an entry, such as `@code{expose} on
+@code{windows}', in the index of functions.@refill
+
+@findex defmethod
+@item @@defmethod @var{class} @var{name} @var{arguments}@dots{}
+The @code{@@defmethod} command is the definition command for methods
+in object-oriented programming. A method is a kind of function that
+implements an operation for a particular class of objects and its
+subclasses. In the Lisp Machine, methods actually were functions, but
+they were usually defined with @code{defmethod}.
+
+@code{@@defmethod} is equivalent to @samp{@@defop Method @dots{}}.
+The command is written at the beginning of a line and is followed by
+the name of the class of the method, the name of the method, and its
+arguments, if any.@refill
+
+@need 800
+@noindent
+For example,
+
+@example
+@group
+@@defmethod @code{bar-class} bar-method argument
+@dots{}
+@@end defmethod
+@end group
+@end example
+
+@noindent
+illustrates the definition for a method called @code{bar-method} of
+the class @code{bar-class}. The method takes an argument.@refill
+
+The template is:
+
+@example
+@group
+@@defmethod @var{class} @var{method-name} @var{arguments}@dots{}
+@var{body-of-definition}
+@@end defmethod
+@end group
+@end example
+
+@code{@@defmethod} creates an entry, such as `@code{bar-method} on
+@code{bar-class}', in the index of functions.@refill
+@end table
+
+@node Data Types, , Abstract Objects, Def Cmds in Detail
+@subsection Data Types
+
+Here is the command for data types:@refill
+
+@table @code
+@findex deftp
+@item @@deftp @var{category} @var{name} @var{attributes}@dots{}
+The @code{@@deftp} command is the generic definition command for data
+types. The command is written at the beginning of a line and is
+followed on the same line by the category, by the name of the type
+(which is a word like @code{int} or @code{float}), and then by names of
+attributes of objects of that type. Thus, you could use this command
+for describing @code{int} or @code{float}, in which case you could use
+@code{data type} as the category. (A data type is a category of
+certain objects for purposes of deciding which operations can be
+performed on them.)@refill
+
+In Lisp, for example, @dfn{pair} names a particular data
+type, and an object of that type has two slots called the
+@sc{car} and the @sc{cdr}. Here is how you would write the first line
+of a definition of @code{pair}.@refill
+
+@example
+@group
+@@deftp @{Data type@} pair car cdr
+@dots{}
+@@end deftp
+@end group
+@end example
+
+@need 950
+The template is:
+
+@example
+@group
+@@deftp @var{category} @var{name-of-type} @var{attributes}@dots{}
+@var{body-of-definition}
+@@end deftp
+@end group
+@end example
+
+@code{@@deftp} creates an entry in the index of data types.
+@end table
+
+@node Def Cmd Conventions, Sample Function Definition, Def Cmds in Detail, Definition Commands
+@section Conventions for Writing Definitions
+@cindex Definition conventions
+@cindex Conventions for writing definitions
+
+When you write a definition using @code{@@deffn}, @code{@@defun}, or
+one of the other definition commands, please take care to use
+arguments that indicate the meaning, as with the @var{count} argument
+to the @code{forward-word} function. Also, if the name of an argument
+contains the name of a type, such as @var{integer}, take care that the
+argument actually is of that type.@refill
+
+@node Sample Function Definition, , Def Cmd Conventions, Definition Commands
+@section A Sample Function Definition
+@cindex Function definitions
+@cindex Command definitions
+@cindex Macro definitions
+@cindex Sample function definition
+
+A function definition uses the @code{@@defun} and @code{@@end defun}
+commands. The name of the function follows immediately after the
+@code{@@defun} command and it is followed, on the same line, by the
+parameter list.@refill
+
+Here is a definition from @cite{The GNU Emacs Lisp Reference Manual}.
+(@xref{Calling Functions, , Calling Functions, elisp, The GNU Emacs
+Lisp Reference Manual}.)
+
+@quotation
+@defun apply function &rest arguments
+@code{apply} calls @var{function} with @var{arguments}, just
+like @code{funcall} but with one difference: the last of
+@var{arguments} is a list of arguments to give to
+@var{function}, rather than a single argument. We also say
+that this list is @dfn{appended} to the other arguments.
+
+@code{apply} returns the result of calling @var{function}.
+As with @code{funcall}, @var{function} must either be a Lisp
+function or a primitive function; special forms and macros
+do not make sense in @code{apply}.
+
+@example
+(setq f 'list)
+ @result{} list
+(apply f 'x 'y 'z)
+@error{} Wrong type argument: listp, z
+(apply '+ 1 2 '(3 4))
+ @result{} 10
+(apply '+ '(1 2 3 4))
+ @result{} 10
+
+(apply 'append '((a b c) nil (x y z) nil))
+ @result{} (a b c x y z)
+@end example
+
+An interesting example of using @code{apply} is found in the description
+of @code{mapcar}.@refill
+@end defun
+@end quotation
+
+@need 1200
+In the Texinfo source file, this example looks like this:
+
+@example
+@group
+@@defun apply function &rest arguments
+
+@@code@{apply@} calls @@var@{function@} with
+@@var@{arguments@}, just like @@code@{funcall@} but with one
+difference: the last of @@var@{arguments@} is a list of
+arguments to give to @@var@{function@}, rather than a single
+argument. We also say that this list is @@dfn@{appended@}
+to the other arguments.
+@end group
+
+@group
+@@code@{apply@} returns the result of calling
+@@var@{function@}. As with @@code@{funcall@},
+@@var@{function@} must either be a Lisp function or a
+primitive function; special forms and macros do not make
+sense in @@code@{apply@}.
+@end group
+
+@group
+@@example
+(setq f 'list)
+ @@result@{@} list
+(apply f 'x 'y 'z)
+@@error@{@} Wrong type argument: listp, z
+(apply '+ 1 2 '(3 4))
+ @@result@{@} 10
+(apply '+ '(1 2 3 4))
+ @@result@{@} 10
+
+(apply 'append '((a b c) nil (x y z) nil))
+ @@result@{@} (a b c x y z)
+@@end example
+@end group
+
+@group
+An interesting example of using @@code@{apply@} is found
+in the description of @@code@{mapcar@}.@@refill
+@@end defun
+@end group
+@end example
+
+@noindent
+In this manual, this function is listed in the Command and Variable
+Index under @code{apply}.@refill
+
+Ordinary variables and user options are described using a format like
+that for functions except that variables do not take arguments.
+
+@node Footnotes, Conditionals, Definition Commands, Top
+@comment node-name, next, previous, up
+@chapter Footnotes
+@cindex Footnotes
+@findex footnote
+
+A @dfn{footnote} is for a reference that documents or elucidates the
+primary text.@footnote{A footnote should complement or expand upon
+the primary text, but a reader should not need to read a footnote to
+understand the primary text. For a thorough discussion of footnotes,
+see @cite{The Chicago Manual of Style}, which is published by the
+University of Chicago Press.}@refill
+
+@menu
+* Footnote Commands:: How to write a footnote in Texinfo.
+* Footnote Styles:: Controlling how footnotes appear in Info.
+@end menu
+
+@node Footnote Commands, Footnote Styles, Footnotes, Footnotes
+@section Footnote Commands
+
+In Texinfo, footnotes are created with the @code{@@footnote} command.
+This command is followed immediately by a left brace, then by the text
+of the footnote, and then by a terminating right brace. The template
+is:
+
+@example
+@@footnote@{@var{text}@}
+@end example
+
+Footnotes may be of any length, but are usually short.@refill
+
+For example, this clause is followed by a sample
+footnote@footnote{Here is the sample footnote.}; in the Texinfo
+source, it looks like this:@refill
+
+@example
+@dots{}a sample footnote @@footnote@{Here is the sample
+footnote.@}; in the Texinfo source@dots{}
+@end example
+
+@strong{Warning:} Don't use footnotes in the argument of the
+@code{@@item} command for a @code{@@table} table. This doesn't work;
+because of limitations of @TeX{}, there is no way to fix it. To avoid
+the problem, move the footnote into the body text of the table.
+
+In a printed manual or book, the reference mark for a footnote is a
+small, superscripted number; the text of the footnote appears at the
+bottom of the page, below a horizontal line.@refill
+
+In Info, the reference mark for a footnote is a pair of parentheses
+with the footnote number between them, like this: @samp{(1)}.@refill
+
+@node Footnote Styles, , Footnote Commands, Footnotes
+@section Footnote Styles
+
+Info has two footnote styles, which determine where the text of the
+footnote is located:@refill
+
+@itemize @bullet
+@cindex @samp{@r{End}} node footnote style
+@item
+In the `End' node style, all the footnotes for a single node
+are placed at the end of that node. The footnotes are separated from
+the rest of the node by a line of dashes with the word
+@samp{Footnotes} within it. Each footnote begins with an
+@samp{(@var{n})} reference mark.@refill
+
+@need 700
+@noindent
+Here is an example of a single footnote in the end of node style:@refill
+
+@example
+@group
+ --------- Footnotes ---------
+
+(1) Here is a sample footnote.
+@end group
+@end example
+
+@cindex @samp{@r{Separate}} footnote style
+@item
+In the `Separate' node style, all the footnotes for a single
+node are placed in an automatically constructed node of
+their own. In this style, a ``footnote reference'' follows
+each @samp{(@var{n})} reference mark in the body of the
+node. The footnote reference is actually a cross reference
+which you use to reach the footnote node.@refill
+
+The name of the node containing the footnotes is constructed
+by appending @w{@samp{-Footnotes}} to the name of the node
+that contains the footnotes. (Consequently, the footnotes'
+node for the @file{Footnotes} node is
+@w{@file{Footnotes-Footnotes}}!) The footnotes' node has an
+`Up' node pointer that leads back to its parent node.@refill
+
+@noindent
+Here is how the first footnote in this manual looks after being
+formatted for Info in the separate node style:@refill
+
+@smallexample
+@group
+File: texinfo.info Node: Overview-Footnotes, Up: Overview
+
+(1) Note that the first syllable of "Texinfo" is
+pronounced like "speck", not "hex". @dots{}
+@end group
+@end smallexample
+@end itemize
+
+A Texinfo file may be formatted into an Info file with either footnote
+style.@refill
+
+@findex footnotestyle
+Use the @code{@@footnotestyle} command to specify an Info file's
+footnote style. Write this command at the beginning of a line followed
+by an argument, either @samp{end} for the end node style or
+@samp{separate} for the separate node style.
+
+@need 700
+For example,
+
+@example
+@@footnotestyle end
+@end example
+@noindent
+or
+@example
+@@footnotestyle separate
+@end example
+
+Write an @code{@@footnotestyle} command before or shortly after the
+end-of-header line at the beginning of a Texinfo file. (If you
+include the @code{@@footnotestyle} command between the start-of-header
+and end-of-header lines, the region formatting commands will format
+footnotes as specified.)@refill
+
+If you do not specify a footnote style, the formatting commands use
+their default style. Currently, @code{texinfo-format-buffer} and
+@code{texinfo-format-region} use the `separate' style and
+@code{makeinfo} uses the `end' style.@refill
+
+@c !!! note: makeinfo's --footnote-style option overrides footnotestyle
+@ignore
+If you use @code{makeinfo} to create the Info file, the
+@samp{--footnote-style} option determines which style is used,
+@samp{end} for the end of node style or @samp{separate} for the
+separate node style. Thus, to format the Texinfo manual in the
+separate node style, you would use the following shell command:@refill
+
+@example
+makeinfo --footnote-style=separate texinfo.texi
+@end example
+
+@noindent
+To format the Texinfo manual in the end of node style, you would
+type:@refill
+
+@example
+makeinfo --footnote-style=end texinfo.texi
+@end example
+@end ignore
+@ignore
+If you use @code{texinfo-format-buffer} or
+@code{texinfo-format-region} to create the Info file, the value of the
+@code{texinfo-footnote-style} variable controls the footnote style.
+It can be either @samp{"separate"} for the separate node style or
+@samp{"end"} for the end of node style. (You can change the value of
+this variable with the @kbd{M-x edit-options} command (@pxref{Edit
+Options, , Editing Variable Values, emacs, The GNU Emacs Manual}), or
+with the @kbd{M-x set-variable} command (@pxref{Examining, , Examining
+and Setting Variables, emacs, The GNU Emacs Manual}).@refill
+
+The @code{texinfo-footnote-style} variable also controls the style if
+you use the @kbd{M-x makeinfo-region} or @kbd{M-x makeinfo-buffer}
+command in Emacs.@refill
+@end ignore
+This chapter contains two footnotes.@refill
+
+@node Conditionals, Macros, Footnotes, Top
+@comment node-name, next, previous, up
+@chapter Conditionally Visible Text
+@cindex Conditionally visible text
+@cindex Text, conditionally visible
+@cindex Visibility of conditional text
+@cindex If text conditionally visible
+@findex ifhtml
+@findex ifinfo
+@findex iftex
+
+Sometimes it is good to use different text for a printed manual and
+its corresponding Info file. In this case, you can use the
+@dfn{conditional commands} to specify which text is for the printed manual
+and which is for the Info file.@refill
+
+@menu
+* Conditional Commands:: How to specify text for HTML, Info, or @TeX{}.
+* Using Ordinary TeX Commands:: You can use any and all @TeX{} commands.
+* set clear value:: How to designate which text to format (for
+ both Info and @TeX{}); and how to set a
+ flag to a string that you can insert.
+@end menu
+
+@node Conditional Commands, Using Ordinary TeX Commands, Conditionals, Conditionals
+@ifinfo
+@heading Using @code{@@ifinfo} and @code{@@iftex}
+@end ifinfo
+
+@code{@@ifinfo} begins segments of text that should be ignored
+by @TeX{} when it
+typesets the printed manual. The segment of text appears only
+in the Info file.
+The @code{@@ifinfo} command should appear on a line by itself; end
+the Info-only text with a line containing @code{@@end ifinfo} by
+itself. At the beginning of a Texinfo file, the Info permissions are
+contained within a region marked by @code{@@ifinfo} and @code{@@end
+ifinfo}. (@xref{Info Summary and Permissions}.)@refill
+
+The @code{@@iftex} and @code{@@end iftex} commands are similar to the
+@code{@@ifinfo} and @code{@@end ifinfo} commands, except that they
+specify text that will appear in the printed manual but not in the Info
+file. Likewise for @code{@@ifhtml} and @code{@@end ifhtml}, which
+specify text to appear only in HTML output.@refill
+
+@need 700
+For example,
+
+@example
+@@iftex
+This text will appear only in the printed manual.
+@@end iftex
+
+@@ifinfo
+However, this text will appear only in Info.
+@@end ifinfo
+@end example
+
+@noindent
+The preceding example produces the following line:
+
+@iftex
+This text will appear only in the printed manual.
+@end iftex
+
+@ifinfo
+However, this text will appear only in Info.
+@end ifinfo
+
+@noindent
+Note how you only see one of the two lines, depending on whether you
+are reading the Info version or the printed version of this
+manual.@refill
+
+The @code{@@titlepage} command is a special variant of @code{@@iftex} that
+is used for making the title and copyright pages of the printed
+manual. (@xref{titlepage, , @code{@@titlepage}}.) @refill
+
+@node Using Ordinary TeX Commands, set clear value, Conditional Commands, Conditionals
+@comment node-name, next, previous, up
+@section Using Ordinary @TeX{} Commands
+@cindex @TeX{} commands, using ordinary
+@cindex Ordinary @TeX{} commands, using
+@cindex Commands using ordinary @TeX{}
+@cindex plain @TeX{}
+
+Inside a region delineated by @code{@@iftex} and @code{@@end iftex},
+you can embed some plain @TeX{} commands. Info will ignore these
+commands since they are only in that part of the file which is seen by
+@TeX{}. You can write the @TeX{} commands as you would write them in
+a normal @TeX{} file, except that you must replace the @samp{\} used
+by @TeX{} with an @samp{@@}. For example, in the @code{@@titlepage}
+section of a Texinfo file, you can use the @TeX{} command
+@code{@@vskip} to format the copyright page. (The @code{@@titlepage}
+command causes Info to ignore the region automatically, as it does
+with the @code{@@iftex} command.)@refill
+
+However, many features of plain @TeX{} will not work, as they are
+overridden by features of Texinfo.
+
+@findex tex
+You can enter plain @TeX{} completely, and use @samp{\} in the @TeX{}
+commands, by delineating a region with the @code{@@tex} and @code{@@end
+tex} commands. (The @code{@@tex} command also causes Info to ignore the
+region, like the @code{@@iftex}
+command.)@refill
+
+@cindex Mathematical expressions
+For example, here is a mathematical expression written in
+plain @TeX{}:@refill
+
+@example
+@@tex
+$$ \chi^2 = \sum_@{i=1@}^N
+ \left (y_i - (a + b x_i)
+ \over \sigma_i\right)^2 $$
+@@end tex
+@end example
+
+@noindent
+The output of this example will appear only in a printed manual. If
+you are reading this in Info, you will not see anything after this
+paragraph.
+@iftex
+In a printed manual, the above expression looks like
+this:
+@end iftex
+
+@tex
+$$ \chi^2 = \sum_{i=1}^N
+ \left(y_i - (a + b x_i)
+ \over \sigma_i\right)^2 $$
+@end tex
+
+@node set clear value, , Using Ordinary TeX Commands, Conditionals
+@comment node-name, next, previous, up
+@section @code{@@set}, @code{@@clear}, and @code{@@value}
+
+You can direct the Texinfo formatting commands to format or ignore parts
+of a Texinfo file with the @code{@@set}, @code{@@clear}, @code{@@ifset},
+and @code{@@ifclear} commands.@refill
+
+In addition, you can use the @code{@@set @var{flag}} command to set the
+value of @var{flag} to a string of characters; and use
+@code{@@value@{@var{flag}@}} to insert that string. You can use
+@code{@@set}, for example, to set a date and use @code{@@value} to
+insert the date in several places in the Texinfo file.@refill
+
+@menu
+* ifset ifclear:: Format a region if a flag is set.
+* value:: Replace a flag with a string.
+* value Example:: An easy way to update edition information.
+@end menu
+
+@node ifset ifclear, value, set clear value, set clear value
+@subsection @code{@@ifset} and @code{@@ifclear}
+
+@findex ifset
+When a @var{flag} is set, the Texinfo formatting commands format text
+between subsequent pairs of @code{@@ifset @var{flag}} and @code{@@end
+ifset} commands. When the @var{flag} is cleared, the Texinfo formatting
+commands do @emph{not} format the text.
+
+Use the @code{@@set @var{flag}} command to turn on, or @dfn{set}, a
+@var{flag}; a @dfn{flag} can be any single word. The format for the
+command looks like this:@refill
+@findex set
+
+@example
+@@set @var{flag}
+@end example
+
+Write the conditionally formatted text between @code{@@ifset @var{flag}}
+and @code{@@end ifset} commands, like this:@refill
+
+@example
+@group
+@@ifset @var{flag}
+@var{conditional-text}
+@@end ifset
+@end group
+@end example
+
+For example, you can create one document that has two variants, such as
+a manual for a `large' and `small' model:@refill
+
+@example
+You can use this machine to dig up shrubs
+without hurting them.
+
+@@set large
+
+@@ifset large
+It can also dig up fully grown trees.
+@@end ifset
+
+Remember to replant promptly @dots{}
+@end example
+
+@noindent
+In the example, the formatting commands will format the text between
+@code{@@ifset large} and @code{@@end ifset} because the @code{large}
+flag is set.@refill
+
+@findex clear
+Use the @code{@@clear @var{flag}} command to turn off, or @dfn{clear},
+a flag. Clearing a flag is the opposite of setting a flag. The
+command looks like this:@refill
+
+@example
+@@clear @var{flag}
+@end example
+
+@noindent
+Write the command on a line of its own.
+
+When @var{flag} is cleared, the Texinfo formatting commands do
+@emph{not} format the text between @code{@@ifset @var{flag}} and
+@code{@@end ifset}; that text is ignored and does not appear in either
+printed or Info output.@refill
+
+For example, if you clear the flag of the preceding example by writing
+an @code{@@clear large} command after the @code{@@set large} command
+(but before the conditional text), then the Texinfo formatting commands
+ignore the text between the @code{@@ifset large} and @code{@@end ifset}
+commands. In the formatted output, that text does not appear; in both
+printed and Info output, you see only the lines that say, ``You can use
+this machine to dig up shrubs without hurting them. Remember to replant
+promptly @dots{}''.
+
+@findex ifclear
+If a flag is cleared with an @code{@@clear @var{flag}} command, then
+the formatting commands format text between subsequent pairs of
+@code{@@ifclear} and @code{@@end ifclear} commands. But if the flag
+is set with @code{@@set @var{flag}}, then the formatting commands do
+@emph{not} format text between an @code{@@ifclear} and an @code{@@end
+ifclear} command; rather, they ignore that text. An @code{@@ifclear}
+command looks like this:@refill
+
+@example
+@@ifclear @var{flag}
+@end example
+
+@need 700
+In brief, the commands are:@refill
+
+@table @code
+@item @@set @var{flag}
+Tell the Texinfo formatting commands that @var{flag} is set.@refill
+
+@item @@clear @var{flag}
+Tell the Texinfo formatting commands that @var{flag} is cleared.@refill
+
+@item @@ifset @var{flag}
+If @var{flag} is set, tell the Texinfo formatting commands to format
+the text up to the following @code{@@end ifset} command.@refill
+
+If @var{flag} is cleared, tell the Texinfo formatting commands to
+ignore text up to the following @code{@@end ifset} command.@refill
+
+@item @@ifclear @var{flag}
+If @var{flag} is set, tell the Texinfo formatting commands to ignore
+the text up to the following @code{@@end ifclear} command.@refill
+
+If @var{flag} is cleared, tell the Texinfo formatting commands to
+format the text up to the following @code{@@end ifclear}
+command.@refill
+@end table
+
+@node value, value Example, ifset ifclear, set clear value
+@subsection @code{@@value}
+@findex value
+
+You can use the @code{@@set} command to specify a value for a flag,
+which is expanded by the @code{@@value} command. The value is a string
+a characters.
+
+Write the @code{@@set} command like this:
+
+@example
+@@set foo This is a string.
+@end example
+
+@noindent
+This sets the value of @code{foo} to ``This is a string.''
+
+The Texinfo formatters replace an @code{@@value@{@var{flag}@}} command with
+the string to which @var{flag} is set.@refill
+
+Thus, when @code{foo} is set as shown above, the Texinfo formatters convert
+
+@example
+@group
+@@value@{foo@}
+@exdent @r{to}
+This is a string.
+@end group
+@end example
+
+You can write an @code{@@value} command within a paragraph; but you
+must write an @code{@@set} command on a line of its own.
+
+If you write the @code{@@set} command like this:
+
+@example
+@@set foo
+@end example
+
+@noindent
+without specifying a string, the value of @code{foo} is an empty string.
+
+If you clear a previously set flag with an @code{@@clear @var{flag}}
+command, a subsequent @code{@@value@{flag@}} command is invalid and the
+string is replaced with an error message that says @samp{@{No value for
+"@var{flag}"@}}.
+
+For example, if you set @code{foo} as follows:@refill
+
+@example
+@@set how-much very, very, very
+@end example
+
+@noindent
+then the formatters transform
+
+@example
+@group
+It is a @@value@{how-much@} wet day.
+@exdent @r{into}
+It is a very, very, very wet day.
+@end group
+@end example
+
+If you write
+
+@example
+@@clear how-much
+@end example
+
+@noindent
+then the formatters transform
+
+@example
+@group
+It is a @@value@{how-much@} wet day.
+@exdent @r{into}
+It is a @{No value for "how-much"@} wet day.
+@end group
+@end example
+
+@node value Example, , value, set clear value
+@subsection @code{@@value} Example
+
+You can use the @code{@@value} command to limit the number of places you
+need to change when you record an update to a manual.
+Here is how it is done in @cite{The GNU Make Manual}:
+
+@need 1000
+@noindent
+Set the flags:
+
+@example
+@group
+@@set EDITION 0.35 Beta
+@@set VERSION 3.63 Beta
+@@set UPDATED 14 August 1992
+@@set UPDATE-MONTH August 1992
+@end group
+@end example
+
+@need 750
+@noindent
+Write text for the first @code{@@ifinfo} section, for people reading the
+Texinfo file:
+
+@example
+@group
+This is Edition @@value@{EDITION@},
+last updated @@value@{UPDATED@},
+of @@cite@{The GNU Make Manual@},
+for @@code@{make@}, Version @@value@{VERSION@}.
+@end group
+@end example
+
+@need 1000
+@noindent
+Write text for the title page, for people reading the printed manual:
+@c List only the month and the year since that looks less fussy on a
+@c printed cover than a date that lists the day as well.
+
+@example
+@group
+@@title GNU Make
+@@subtitle A Program for Directing Recompilation
+@@subtitle Edition @@value@{EDITION@}, @dots{}
+@@subtitle @@value@{UPDATE-MONTH@}
+@end group
+@end example
+
+@noindent
+(On a printed cover, a date listing the month and the year looks less
+fussy than a date listing the day as well as the month and year.)
+
+@need 750
+@noindent
+Write text for the Top node, for people reading the Info file:
+
+@example
+@group
+This is Edition @@value@{EDITION@}
+of the @@cite@{GNU Make Manual@},
+last updated @@value@{UPDATED@}
+for @@code@{make@} Version @@value@{VERSION@}.
+@end group
+@end example
+
+@need 950
+After you format the manual, the text in the first @code{@@ifinfo}
+section looks like this:
+
+@example
+@group
+This is Edition 0.35 Beta, last updated 14 August 1992,
+of `The GNU Make Manual', for `make', Version 3.63 Beta.
+@end group
+@end example
+
+When you update the manual, change only the values of the flags; you do
+not need to rewrite the three sections.
+
+
+@node Macros, Format/Print Hardcopy, Conditionals, Top
+@chapter Macros: Defining New Texinfo Commands
+@cindex Macros
+@cindex Defining new Texinfo commands
+@cindex New Texinfo commands, defining
+@cindex Texinfo commands, defining new
+@cindex User-defined Texinfo commands
+
+A Texinfo @dfn{macro} allows you to define a new Texinfo command as any
+sequence of text and/or existing commands (including other macros). The
+macro can have any number of @dfn{parameters}---text you supply each
+time you use the macro. (This has nothing to do with the
+@code{@@defmac} command, which is for documenting macros in the subject
+of the manual; @pxref{Def Cmd Template}.)
+
+@menu
+* Defining Macros:: Both defining and undefining new commands.
+* Invoking Macros:: Using a macro, once you've defined it.
+@end menu
+
+
+@node Defining Macros, Invoking Macros, Macros, Macros
+@section Defining Macros
+@cindex Defining macros
+@cindex Macro definitions
+
+@findex macro
+You use the Texinfo @code{@@macro} command to define a macro. For example:
+
+@example
+@@macro @var{macro-name}@{@var{param1}, @var{param2}, @dots{}@}
+@var{text} @dots{} \@var{param1}\ @dots{}
+@@end macro
+@end example
+
+The @dfn{parameters} @var{param1}, @var{param2}, @dots{} correspond to
+arguments supplied when the macro is subsequently used in the document
+(see the next section).
+
+If a macro needs no parameters, you can define it either with an empty
+list (@samp{@@macro foo @{@}}) or with no braces at all (@samp{@@macro
+foo}).
+
+@cindex Body of a macro
+@cindex Mutually recursive macros
+@cindex Recursion, mutual
+The definition or @dfn{body} of the macro can contain any Texinfo
+commands, including previously-defined macros. (It is not possible to
+have mutually recursive Texinfo macros.) In the body, instances of a
+parameter name surrounded by backslashes, as in @samp{\@var{param1}\} in
+the example above, are replaced by the corresponding argument from the
+macro invocation.
+
+@findex unmacro
+@cindex Macros, undefining
+@cindex Undefining macros
+You can undefine a macro @var{foo} with @code{@@unmacro @var{foo}}.
+It is not an error to undefine a macro that is already undefined.
+For example:
+
+@example
+@@unmacro foo
+@end example
+
+
+@node Invoking Macros, , Defining Macros, Macros
+@section Invoking Macros
+@cindex Invoking macros
+@cindex Macro invocation
+
+After a macro is defined (see the previous section), you can use
+(@dfn{invoke}) it in your document like this:
+
+@example
+@@@var{macro-name} @{@var{arg1}, @var{arg2}, @dots{}@}
+@end example
+
+@noindent and the result will be just as if you typed the body of
+@var{macro-name} at that spot. For example:
+
+@example
+@@macro foo @{p, q@}
+Together: \p\ & \q\.
+@@end macro
+@@foo@{a, b@}
+@end example
+
+@noindent produces:
+
+@display
+Together: a & b.
+@end display
+
+@cindex Backslash, and macros
+Thus, the arguments and parameters are separated by commas and delimited
+by braces; any whitespace after (but not before) a comma is ignored. To
+insert a comma, brace, or backslash in an argument, prepend a backslash,
+as in
+
+@example
+@@@var{macro-name} @{\\\@{\@}\,@}
+@end example
+
+@noindent
+which will pass the (almost certainly error-producing) argument
+@samp{\@{@},} to @var{macro-name}.
+
+If the macro is defined to take a single argument, and is invoked
+without any braces, the entire rest of the line after the macro name is
+supplied as the argument. For example:
+
+@example
+@@macro bar @{p@}
+Twice: \p\, \p\.
+@@end macro
+@@bar aah
+@end example
+
+@noindent produces:
+
+@display
+Twice: aah, aah.
+@end display
+
+
+@node Format/Print Hardcopy, Create an Info File, Macros, Top
+@comment node-name, next, previous, up
+@chapter Format and Print Hardcopy
+@cindex Format and print hardcopy
+@cindex Hardcopy, printing it
+@cindex Making a printed manual
+@cindex Sorting indices
+@cindex Indices, sorting
+@cindex @TeX{} index sorting
+@pindex texindex
+
+There are three major shell commands for making a printed manual from a
+Texinfo file: one for converting the Texinfo file into a file that will be
+printed, a second for sorting indices, and a third for printing the
+formatted document. When you use the shell commands, you can either
+work directly in the operating system shell or work within a shell
+inside GNU Emacs.@refill
+
+If you are using GNU Emacs, you can use commands provided by Texinfo
+mode instead of shell commands. In addition to the three commands to
+format a file, sort the indices, and print the result, Texinfo mode
+offers key bindings for commands to recenter the output buffer, show the
+print queue, and delete a job from the print queue.@refill
+
+@menu
+* Use TeX:: Use @TeX{} to format for hardcopy.
+* Format with tex/texindex:: How to format in a shell.
+* Format with texi2dvi:: A simpler way to use the shell.
+* Print with lpr:: How to print.
+* Within Emacs:: How to format and print from an Emacs shell.
+* Texinfo Mode Printing:: How to format and print in Texinfo mode.
+* Compile-Command:: How to print using Emacs's compile command.
+* Requirements Summary:: @TeX{} formatting requirements summary.
+* Preparing for TeX:: What you need to do to use @TeX{}.
+* Overfull hboxes:: What are and what to do with overfull hboxes.
+* smallbook:: How to print small format books and manuals.
+* A4 Paper:: How to print on European A4 paper.
+* Cropmarks and Magnification:: How to print marks to indicate the size
+ of pages and how to print scaled up output.
+@end menu
+
+@node Use TeX, Format with tex/texindex, Format/Print Hardcopy, Format/Print Hardcopy
+@ifinfo
+@heading Use @TeX{}
+@end ifinfo
+
+The typesetting program called @TeX{} is used for formatting a Texinfo
+file. @TeX{} is a very powerful typesetting program and, if used right,
+does an exceptionally good job. @xref{Obtaining TeX, , How to Obtain
+@TeX{}}, for information on how to obtain @TeX{}.@refill
+
+The @code{makeinfo}, @code{texinfo-format-region}, and
+@code{texinfo-format-buffer} commands read the very same @@-commands
+in the Texinfo file as does @TeX{}, but process them differently to
+make an Info file; see @ref{Create an Info File}.@refill
+
+@node Format with tex/texindex, Format with texi2dvi, Use TeX, Format/Print Hardcopy
+@comment node-name, next, previous, up
+@section Format using @code{tex} and @code{texindex}
+@cindex Shell formatting with @code{tex} and @code{texindex}
+@cindex Formatting with @code{tex} and @code{texindex}
+@cindex DVI file
+
+Format the Texinfo file with the shell command @code{tex} followed by
+the name of the Texinfo file. This command produces a formatted
+@sc{dvi} file as well as several auxiliary files containing indices,
+cross references, etc. The @sc{dvi} file (for @dfn{DeVice Independent}
+file) can be printed on a wide variety of printers.@refill
+
+The @code{tex} formatting command itself does not sort the indices; it
+writes an output file of unsorted index data. This is a misfeature of
+@TeX{}. (The @code{texi2dvi} command automatically generates indices;
+see @ref{Format with texi2dvi, , Format using @code{texi2dvi}}.) To
+generate a printed index after running the @code{tex} command, you first
+need a sorted index to work from. The @code{texindex} command sorts
+indices. (The source file @file{texindex.c} comes as part of the
+standard GNU distribution and is usually installed when Emacs is
+installed.)@refill
+@pindex texindex
+@ignore
+Usage: texindex [-k] [-T tempdir] infile [-o outfile] ...
+
+Each infile arg can optionally be followed by a `-o outfile' arg;
+for each infile that is not followed by a -o arg, the infile name with
+`s' (for `sorted') appended is used for the outfile.
+
+-T dir is the directory to put temp files in, instead of /tmp.
+-k means `keep tempfiles', for debugging.
+@end ignore
+
+The @code{tex} formatting command outputs unsorted index files under
+names that obey a standard convention. These names are the name of
+your main input file to the @code{tex} formatting command, with
+everything after the first period thrown away, and the two letter
+names of indices added at the end. For example, the raw index output
+files for the input file @file{foo.texinfo} would be @file{foo.cp},
+@file{foo.vr}, @file{foo.fn}, @file{foo.tp}, @file{foo.pg} and
+@file{foo.ky}. Those are exactly the arguments to give to
+@code{texindex}.@refill
+
+@need 1000
+Or else, you can use @samp{??} as ``wild-cards'' and give the command in
+this form:@refill
+
+@example
+texindex foo.??
+@end example
+
+@noindent
+This command will run @code{texindex} on all the unsorted index files,
+including any that you have defined yourself using @code{@@defindex}
+or @code{@@defcodeindex}. (You may execute @samp{texindex foo.??}
+even if there are similarly named files with two letter extensions
+that are not index files, such as @samp{foo.el}. The @code{texindex}
+command reports but otherwise ignores such files.)@refill
+
+For each file specified, @code{texindex} generates a sorted index file
+whose name is made by appending @samp{s} to the input file name. The
+@code{@@printindex} command knows to look for a file of that name.
+@code{texindex} does not alter the raw index output file.@refill
+
+After you have sorted the indices, you need to rerun the @code{tex}
+formatting command on the Texinfo file. This regenerates a formatted
+@sc{dvi} file with up-to-date index entries.@footnote{If you use more
+than one index and have cross references to an index other than the
+first, you must run @code{tex} @emph{three times} to get correct output:
+once to generate raw index data; again (after @code{texindex}) to output
+the text of the indices and determine their true page numbers; and a
+third time to output correct page numbers in cross references to them.
+However, cross references to indices are rare.}@refill
+
+To summarize, this is a three step process:
+
+@enumerate
+@item
+Run the @code{tex} formatting command on the Texinfo file. This
+generates the formatted @sc{dvi} file as well as the raw index files
+with two letter extensions.@refill
+
+@item
+Run the shell command @code{texindex} on the raw index files to sort
+them. This creates the corresponding sorted index files.@refill
+
+@item
+Rerun the @code{tex} formatting command on the Texinfo file. This
+regenerates a formatted @sc{dvi} file with the index entries in the
+correct order. This second run also corrects the page numbers for
+the cross references. (The tables of contents are always correct.)@refill
+@end enumerate
+
+You need not run @code{texindex} each time after you run the
+@code{tex} formatting. If you do not, on the next run, the @code{tex}
+formatting command will use whatever sorted index files happen to
+exist from the previous use of @code{texindex}. This is usually
+@sc{ok} while you are debugging.@refill
+
+@node Format with texi2dvi, Print with lpr, Format with tex/texindex, Format/Print Hardcopy
+@comment node-name, next, previous, up
+@section Format using @code{texi2dvi}
+@pindex texi2dvi @r{(shell script)}
+
+The @code{texi2dvi} command is a shell script that automatically runs
+both @code{tex} and @code{texindex} as many times as necessary to
+produce a @sc{dvi} file with up-to-date, sorted indices. It simplifies
+the @code{tex}---@code{texindex}---@code{tex} sequence described in the
+previous section.
+
+@need 1000
+The syntax for @code{texi2dvi} is like this (where @samp{prompt$} is the
+shell prompt):@refill
+
+@example
+prompt$ @kbd{texi2dvi @var{filename}@dots{}}
+@end example
+
+@node Print with lpr, Within Emacs, Format with texi2dvi, Format/Print Hardcopy
+@comment node-name, next, previous, up
+@section Shell Print Using @code{lpr -d}
+@pindex lpr @r{(@sc{dvi} print command)}
+
+You can print a @sc{dvi} file with the @sc{dvi} print command. The
+precise printing command to use depends on your system; @samp{lpr -d} is
+common. The @sc{dvi} print command may require a file name without any
+extension or with a @samp{.dvi} extension.@refill
+
+@need 1200
+The following commands, for example, sort the indices, format, and
+print the @cite{Bison Manual} (where @samp{%} is the shell
+prompt):@refill
+
+@example
+@group
+% tex bison.texinfo
+% texindex bison.??
+% tex bison.texinfo
+% lpr -d bison.dvi
+@end group
+@end example
+
+@noindent
+(Remember that the shell commands may be different at your site; but
+these are commonly used versions.)@refill
+
+@need 1000
+Using the @code{texi2dvi} shell script, you simply need type:@refill
+
+@example
+@group
+% texi2dvi bison.texinfo
+% lpr -d bison.dvi
+@end group
+@end example
+
+@node Within Emacs, Texinfo Mode Printing, Print with lpr, Format/Print Hardcopy
+@comment node-name, next, previous, up
+@section From an Emacs Shell @dots{}
+@cindex Print, format from Emacs shell
+@cindex Format, print from Emacs shell
+@cindex Shell, format, print from
+@cindex Emacs shell, format, print from
+@cindex GNU Emacs shell, format, print from
+
+You can give formatting and printing commands from a shell within GNU
+Emacs. To create a shell within Emacs, type @kbd{M-x shell}. In this
+shell, you can format and print the document. @xref{Format/Print
+Hardcopy, , Format and Print Hardcopy}, for details.@refill
+
+You can switch to and from the shell buffer while @code{tex} is
+running and do other editing. If you are formatting a long document
+on a slow machine, this can be very convenient.@refill
+
+You can also use @code{texi2dvi} from an Emacs shell. For example,
+here is how to use @code{texi2dvi} to format and print @cite{Using and
+Porting GNU CC} from a shell within Emacs (where @samp{%} is the shell
+prompt):@refill
+
+@example
+@group
+% texi2dvi gcc.texinfo
+% lpr -d gcc.dvi
+@end group
+@end example
+@ifinfo
+
+@xref{Texinfo Mode Printing}, for more information about formatting
+and printing in Texinfo mode.@refill
+@end ifinfo
+
+@node Texinfo Mode Printing, Compile-Command, Within Emacs, Format/Print Hardcopy
+@section Formatting and Printing in Texinfo Mode
+@cindex Region printing in Texinfo mode
+@cindex Format and print in Texinfo mode
+@cindex Print and format in Texinfo mode
+
+Texinfo mode provides several predefined key commands for @TeX{}
+formatting and printing. These include commands for sorting indices,
+looking at the printer queue, killing the formatting job, and
+recentering the display of the buffer in which the operations
+occur.@refill
+
+@table @kbd
+@item C-c C-t C-b
+@itemx M-x texinfo-tex-buffer
+Run @code{texi2dvi} on the current buffer.@refill
+
+@item C-c C-t C-r
+@itemx M-x texinfo-tex-region
+Run @TeX{} on the current region.@refill
+
+@item C-c C-t C-i
+@itemx M-x texinfo-texindex
+Sort the indices of a Texinfo file formatted with
+@code{texinfo-tex-region}.@refill
+
+@item C-c C-t C-p
+@itemx M-x texinfo-tex-print
+Print a @sc{dvi} file that was made with @code{texinfo-tex-region} or
+@code{texinfo-tex-buffer}.@refill
+
+@item C-c C-t C-q
+@itemx M-x tex-show-print-queue
+Show the print queue.@refill
+
+@item C-c C-t C-d
+@itemx M-x texinfo-delete-from-print-queue
+Delete a job from the print queue; you will be prompted for the job
+number shown by a preceding @kbd{C-c C-t C-q} command
+(@code{texinfo-show-tex-print-queue}).@refill
+
+@item C-c C-t C-k
+@itemx M-x tex-kill-job
+Kill the currently running @TeX{} job started by
+@code{texinfo-tex-region} or @code{texinfo-tex-buffer}, or any other
+process running in the Texinfo shell buffer.@refill
+
+@item C-c C-t C-x
+@itemx M-x texinfo-quit-job
+Quit a @TeX{} formatting job that has stopped because of an error by
+sending an @key{x} to it. When you do this, @TeX{} preserves a record
+of what it did in a @file{.log} file.@refill
+
+@item C-c C-t C-l
+@itemx M-x tex-recenter-output-buffer
+Redisplay the shell buffer in which the @TeX{} printing and formatting
+commands are run to show its most recent output.@refill
+@end table
+
+@need 1000
+Thus, the usual sequence of commands for formatting a buffer is as
+follows (with comments to the right):@refill
+
+@example
+@group
+C-c C-t C-b @r{Run @code{texi2dvi} on the buffer.}
+C-c C-t C-p @r{Print the @sc{dvi} file.}
+C-c C-t C-q @r{Display the printer queue.}
+@end group
+@end example
+
+The Texinfo mode @TeX{} formatting commands start a subshell in Emacs
+called the @file{*tex-shell*}. The @code{texinfo-tex-command},
+@code{texinfo-texindex-command}, and @code{tex-dvi-print-command}
+commands are all run in this shell.
+
+You can watch the commands operate in the @samp{*tex-shell*} buffer,
+and you can switch to and from and use the @samp{*tex-shell*} buffer
+as you would any other shell buffer.@refill
+
+@need 1500
+The formatting and print commands depend on the values of several variables.
+The default values are:@refill
+
+@example
+@group
+ @r{Variable} @r{Default value}
+
+texinfo-texi2dvi-command "texi2dvi"
+texinfo-tex-command "tex"
+texinfo-texindex-command "texindex"
+texinfo-delete-from-print-queue-command "lprm"
+texinfo-tex-trailer "@@bye"
+tex-start-of-header "%**start"
+tex-end-of-header "%**end"
+tex-dvi-print-command "lpr -d"
+tex-show-queue-command "lpq"
+@end group
+@end example
+
+You can change the values of these variables with the @kbd{M-x
+edit-options} command (@pxref{Edit Options, , Editing Variable Values,
+emacs, The GNU Emacs Manual}), with the @kbd{M-x set-variable} command
+(@pxref{Examining, , Examining and Setting Variables, emacs, The GNU
+Emacs Manual}), or with your @file{.emacs} initialization file
+(@pxref{Init File, , , emacs, The GNU Emacs Manual}).@refill
+
+@node Compile-Command, Requirements Summary, Texinfo Mode Printing, Format/Print Hardcopy
+@comment node-name, next, previous, up
+@section Using the Local Variables List
+@cindex Local variables
+@cindex Compile command for formatting
+@cindex Format with the compile command
+
+Yet another way to apply the @TeX{} formatting command to a Texinfo file
+is to put that command in a @dfn{local variables list} at the end of the
+Texinfo file. You can then specify the @code{tex} or @code{texi2dvi}
+commands as a @code{compile-command} and have Emacs run it by typing
+@kbd{M-x compile}. This creates a special shell called the
+@file{*compilation*} buffer in which Emacs runs the compile command.
+For example, at the end of the @file{gdb.texinfo} file, after the
+@code{@@bye}, you could put the following:@refill
+
+@example
+@group
+@@c Local Variables:
+@@c compile-command: "texi2dvi gdb.texinfo"
+@@c End:
+@end group
+@end example
+
+@noindent
+This technique is most often used by programmers who also compile programs
+this way; see @ref{Compilation, , , emacs, The GNU Emacs Manual}.@refill
+
+@node Requirements Summary, Preparing for TeX, Compile-Command, Format/Print Hardcopy
+@comment node-name, next, previous, up
+@section @TeX{} Formatting Requirements Summary
+@cindex Requirements for formatting
+@cindex Formatting requirements
+
+Every Texinfo file that is to be input to @TeX{} must begin with a
+@code{\input} command and must contain an @code{@@setfilename} command and
+an @code{@@settitle} command:@refill
+
+@example
+\input texinfo
+@@setfilename @var{arg-not-used-by-@TeX{}}
+@@settitle @var{name-of-manual}
+@end example
+
+@noindent
+The first command instructs @TeX{} to load the macros it needs to
+process a Texinfo file, the second command opens auxiliary files, and
+the third specifies the title of printed manual.
+
+@need 1000
+Every Texinfo file must end with a line that terminates @TeX{}
+processing and forces out unfinished pages:@refill
+
+@example
+@@bye
+@end example
+
+Strictly speaking, these four lines are all a Texinfo file needs for
+@TeX{}, besides the body. (The @code{@@setfilename} line is the only
+line that a Texinfo file needs for Info formatting.)@refill
+
+Usually, the file's first line contains an @samp{@@c -*-texinfo-*-}
+comment that causes Emacs to switch to Texinfo mode when you edit the
+file. In addition, the beginning usually includes an
+@code{@@setchapternewpage} command, a title page, a copyright page, and
+permissions. Besides an @code{@@bye}, the end of a file usually
+includes indices and a table of contents.@refill
+
+@iftex
+For more information, see
+@ref{setchapternewpage, , @code{@@setchapternewpage}},
+@ref{Headings, ,Page Headings},
+@ref{Titlepage & Copyright Page},
+@ref{Printing Indices & Menus}, and
+@ref{Contents}.
+@end iftex
+@noindent
+@ifinfo
+For more information, see@*
+@ref{setchapternewpage, , @code{@@setchapternewpage}},@*
+@ref{Headings, ,Page Headings},@*
+@ref{Titlepage & Copyright Page},@*
+@ref{Printing Indices & Menus}, and@*
+@ref{Contents}.
+@end ifinfo
+
+@node Preparing for TeX, Overfull hboxes, Requirements Summary, Format/Print Hardcopy
+@comment node-name, next, previous, up
+@section Preparing to Use @TeX{}
+@cindex Preparing to use @TeX{}
+@cindex @TeX{} input initialization
+@cindex @code{TEXINPUTS} environment variable
+@vindex TEXINPUTS
+@cindex @b{.profile} initialization file
+@cindex @b{.cshrc} initialization file
+@cindex Initialization file for @TeX{} input
+
+@TeX{} needs to know where to find the @file{texinfo.tex} file
+that you have told it to input with the @samp{\input texinfo} command
+at the beginning of the first line. The @file{texinfo.tex} file tells
+@TeX{} how to handle @@-commands. (@file{texinfo.tex} is
+included in the standard GNU distributions.)@refill
+
+Usually, the @file{texinfo.tex} file is put in the default directory
+that contains @TeX{} macros (the @file{/usr/lib/tex/macros}
+directory) when GNU Emacs or other GNU software is installed.
+In this case, @TeX{} will
+find the file and you do not need to do anything special.
+Alternatively, you can put @file{texinfo.tex} in the directory in
+which the Texinfo source file is located, and @TeX{} will find it
+there.@refill
+
+However, you may want to specify the location of the @code{\input} file
+yourself. One way to do this is to write the complete path for the file
+after the @code{\input} command. Another way is to set the
+@code{TEXINPUTS} environment variable in your @file{.cshrc} or
+@file{.profile} file. The @code{TEXINPUTS} environment variable will tell
+@TeX{} where to find the @file{texinfo.tex} file and any other file that
+you might want @TeX{} to use.@refill
+
+Whether you use a @file{.cshrc} or @file{.profile} file depends on
+whether you use @code{csh}, @code{sh}, or @code{bash} for your shell
+command interpreter. When you use @code{csh}, it looks to the
+@file{.cshrc} file for initialization information, and when you use
+@code{sh} or @code{bash}, it looks to the @file{.profile} file.@refill
+
+@need 1000
+In a @file{.cshrc} file, you could use the following @code{csh} command
+sequence:@refill
+
+@example
+setenv TEXINPUTS .:/usr/me/mylib:/usr/lib/tex/macros
+@end example
+
+@need 1000
+In a @file{.profile} file, you could use the following @code{sh} command
+sequence:
+
+@example
+@group
+TEXINPUTS=.:/usr/me/mylib:/usr/lib/tex/macros
+export TEXINPUTS
+@end group
+@end example
+
+@noindent
+This would cause @TeX{} to look for @file{\input} file first in the current
+directory, indicated by the @samp{.}, then in a hypothetical user's
+@file{me/mylib} directory, and finally in the system library.@refill
+
+@node Overfull hboxes, smallbook, Preparing for TeX, Format/Print Hardcopy
+@comment node-name, next, previous, up
+@section Overfull ``hboxes''
+@cindex Overfull @samp{hboxes}
+@cindex @samp{hboxes}, overfull
+@cindex Final output
+
+@TeX{} is sometimes unable to typeset a line without extending it into
+the right margin. This can occur when @TeX{} comes upon what it
+interprets as a long word that it cannot hyphenate, such as an
+electronic mail network address or a very long title. When this
+happens, @TeX{} prints an error message like this:@refill
+
+@example
+Overfull \hbox (20.76302pt too wide)
+@end example
+
+@noindent
+(In @TeX{}, lines are in ``horizontal boxes'', hence the term, ``hbox''.
+The backslash, @samp{\}, is the @TeX{} equivalent of @samp{@@}.)@refill
+
+@TeX{} also provides the line number in the Texinfo source file and
+the text of the offending line, which is marked at all the places that
+@TeX{} knows how to hyphenate words.
+@xref{Debugging with TeX, , Catching Errors with @TeX{} Formatting},
+for more information about typesetting errors.@refill
+
+If the Texinfo file has an overfull hbox, you can rewrite the sentence
+so the overfull hbox does not occur, or you can decide to leave it. A
+small excursion into the right margin often does not matter and may not
+even be noticeable.@refill
+
+@cindex Black rectangle in hardcopy
+@cindex Rectangle, ugly, black in hardcopy
+However, unless told otherwise, @TeX{} will print a large, ugly, black
+rectangle beside the line that contains the overfull hbox. This is so
+you will notice the location of the problem if you are correcting a
+draft.@refill
+
+@need 1000
+@findex finalout
+To prevent such a monstrosity from marring your final printout, write
+the following in the beginning of the Texinfo file on a line of its own,
+before the @code{@@titlepage} command:@refill
+
+@example
+@@finalout
+@end example
+
+@node smallbook, A4 Paper, Overfull hboxes, Format/Print Hardcopy
+@comment node-name, next, previous, up
+@section Printing ``Small'' Books
+@findex smallbook
+@cindex Small book size
+@cindex Book, printing small
+@cindex Page sizes for books
+@cindex Size of printed book
+
+By default, @TeX{} typesets pages for printing in an 8.5 by 11 inch
+format. However, you can direct @TeX{} to typeset a document in a 7 by
+9.25 inch format that is suitable for bound books by inserting the
+following command on a line by itself at the beginning of the Texinfo
+file, before the title page:@refill
+
+@example
+@@smallbook
+@end example
+
+@noindent
+(Since regular sized books are often about 7 by 9.25 inches, this
+command might better have been called the @code{@@regularbooksize}
+command, but it came to be called the @code{@@smallbook} command by
+comparison to the 8.5 by 11 inch format.)@refill
+
+If you write the @code{@@smallbook} command between the
+start-of-header and end-of-header lines, the Texinfo mode @TeX{}
+region formatting command, @code{texinfo-tex-region}, will format the
+region in ``small'' book size (@pxref{Start of Header}).@refill
+
+The Free Software Foundation distributes printed copies of @cite{The GNU
+Emacs Manual} and other manuals in the ``small'' book size.
+@xref{smallexample & smalllisp, , @code{@@smallexample} and
+@code{@@smalllisp}}, for information about commands that make it easier
+to produce examples for a smaller manual.@refill
+
+@node A4 Paper, Cropmarks and Magnification, smallbook, Format/Print Hardcopy
+@comment node-name, next, previous, up
+@section Printing on A4 Paper
+@cindex A4 paper, printing on
+@cindex Paper size, European A4
+@cindex European A4 paper
+@findex afourpaper
+
+You can tell @TeX{} to typeset a document for printing on European size
+A4 paper with the @code{@@afourpaper} command. Write the command on a
+line by itself between @code{@@iftex} and @code{@@end iftex} lines near
+the beginning of the Texinfo file, before the title page:@refill
+
+For example, this is how you would write the header for this manual:@refill
+
+@example
+@group
+\input texinfo @@c -*-texinfo-*-
+@@c %**start of header
+@@setfilename texinfo
+@@settitle Texinfo
+@@syncodeindex vr fn
+@@iftex
+@@afourpaper
+@@end iftex
+@@c %**end of header
+@end group
+@end example
+
+@node Cropmarks and Magnification, , A4 Paper, Format/Print Hardcopy
+@comment node-name, next, previous, up
+@section Cropmarks and Magnification
+
+@findex cropmarks
+@cindex Cropmarks for printing
+@cindex Printing cropmarks
+You can attempt to direct @TeX{} to print cropmarks at the corners of
+pages with the @code{@@cropmarks} command. Write the @code{@@cropmarks}
+command on a line by itself between @code{@@iftex} and @code{@@end
+iftex} lines near the beginning of the Texinfo file, before the title
+page, like this:@refill
+
+@example
+@group
+@@iftex
+@@cropmarks
+@@end iftex
+@end group
+@end example
+
+This command is mainly for printers that typeset several pages on one
+sheet of film; but you can attempt to use it to mark the corners of a
+book set to 7 by 9.25 inches with the @code{@@smallbook} command.
+(Printers will not produce cropmarks for regular sized output that is
+printed on regular sized paper.) Since different printing machines work
+in different ways, you should explore the use of this command with a
+spirit of adventure. You may have to redefine the command in the
+@file{texinfo.tex} definitions file.@refill
+
+@findex mag @r{(@TeX{} command)}
+@cindex Magnified printing
+@cindex Larger or smaller pages
+You can attempt to direct @TeX{} to typeset pages larger or smaller than
+usual with the @code{\mag} @TeX{} command. Everything that is typeset
+is scaled proportionally larger or smaller. (@code{\mag} stands for
+``magnification''.) This is @emph{not} a Texinfo @@-command, but is a
+plain @TeX{} command that is prefixed with a backslash. You have to
+write this command between @code{@@tex} and @code{@@end tex}
+(@pxref{Using Ordinary TeX Commands, , Using Ordinary @TeX{}
+Commands}).@refill
+
+Follow the @code{\mag} command with an @samp{=} and then a number that
+is 1000 times the magnification you desire. For example, to print pages
+at 1.2 normal size, write the following near the beginning of the
+Texinfo file, before the title page:@refill
+
+@example
+@group
+@@tex
+\mag=1200
+@@end tex
+@end group
+@end example
+
+With some printing technologies, you can print normal-sized copies that
+look better than usual by using a larger-than-normal master.@refill
+
+Depending on your system, @code{\mag} may not work or may work only at
+certain magnifications. Be prepared to experiment.@refill
+
+@node Create an Info File, Install an Info File, Format/Print Hardcopy, Top
+@comment node-name, next, previous, up
+@chapter Creating an Info File
+@cindex Creating an Info file
+@cindex Info, creating an on-line file
+@cindex Formatting a file for Info
+
+@code{makeinfo} is a utility that converts a Texinfo file into an Info
+file; @code{texinfo-format-region} and @code{texinfo-format-buffer} are
+GNU Emacs functions that do the same.@refill
+
+A Texinfo file must possess an @code{@@setfilename} line near its
+beginning, otherwise the Info formatting commands will fail.@refill
+
+For information on installing the Info file in the Info system, see
+@ref{Install an Info File}.@refill
+
+@menu
+* makeinfo advantages:: @code{makeinfo} provides better error checking.
+* Invoking makeinfo:: How to run @code{makeinfo} from a shell.
+* makeinfo options:: Specify fill-column and other options.
+* Pointer Validation:: How to check that pointers point somewhere.
+* makeinfo in Emacs:: How to run @code{makeinfo} from Emacs.
+* texinfo-format commands:: Two Info formatting commands written
+ in Emacs Lisp are an alternative
+ to @code{makeinfo}.
+* Batch Formatting:: How to format for Info in Emacs Batch mode.
+* Tag and Split Files:: How tagged and split files help Info
+ to run better.
+@end menu
+
+@node makeinfo advantages, Invoking makeinfo, Create an Info File, Create an Info File
+@ifinfo
+@heading @code{makeinfo} Preferred
+@end ifinfo
+
+The @code{makeinfo} utility creates an Info file from a Texinfo source
+file more quickly than either of the Emacs formatting commands and
+provides better error messages. We recommend it. @code{makeinfo} is a
+C program that is independent of Emacs. You do not need to run Emacs to
+use @code{makeinfo}, which means you can use @code{makeinfo} on machines
+that are too small to run Emacs. You can run @code{makeinfo} in
+any one of three ways: from an operating system shell, from a shell
+inside Emacs, or by typing a key command in Texinfo mode in Emacs.
+@refill
+
+The @code{texinfo-format-region} and the @code{texinfo-format-buffer}
+commands are useful if you cannot run @code{makeinfo}. Also, in some
+circumstances, they format short regions or buffers more quickly than
+@code{makeinfo}.@refill
+
+@node Invoking makeinfo, makeinfo options, makeinfo advantages, Create an Info File
+@section Running @code{makeinfo} from a Shell
+
+To create an Info file from a Texinfo file, type @code{makeinfo}
+followed by the name of the Texinfo file. Thus, to create the Info
+file for Bison, type the following at the shell prompt (where @samp{%}
+is the prompt):@refill
+
+@example
+% makeinfo bison.texinfo
+@end example
+
+(You can run a shell inside Emacs by typing @kbd{M-x
+shell}.)@refill
+
+@ifinfo
+Sometimes you will want to specify options. For example, if you wish
+to discover which version of @code{makeinfo} you are using,
+type:@refill
+
+@example
+% makeinfo --version
+@end example
+
+@xref{makeinfo options}, for more information.
+@end ifinfo
+
+@node makeinfo options, Pointer Validation, Invoking makeinfo, Create an Info File
+@comment node-name, next, previous, up
+@section Options for @code{makeinfo}
+@cindex @code{makeinfo} options
+@cindex Options for @code{makeinfo}
+
+The @code{makeinfo} command takes a number of options. Most often,
+options are used to set the value of the fill column and specify the
+footnote style. Each command line option is a word preceded by
+@samp{--}@footnote{@samp{--} has replaced @samp{+}, the old introductory
+character, to maintain POSIX.2 compatibility without losing long-named
+options.} or a letter preceded by @samp{-}. You can use abbreviations
+for the option names as long as they are unique.@refill
+
+For example, you could use the following command to create an Info
+file for @file{bison.texinfo} in which each line is filled to only 68
+columns (where @samp{%} is the prompt):@refill
+
+@example
+% makeinfo --fill-column=68 bison.texinfo
+@end example
+
+You can write two or more options in sequence, like this:@refill
+
+@example
+% makeinfo --no-split --fill-column=70 @dots{}
+@end example
+
+@noindent
+This would keep the Info file together as one possibly very long
+file and would also set the fill column to 70.@refill
+
+@iftex
+If you wish to discover which version of @code{makeinfo}
+you are using, type:@refill
+
+@example
+% makeinfo --version
+@end example
+@end iftex
+
+The options are:@refill
+
+@need 100
+@table @code
+@item -D @var{var}
+Cause @var{var} to be defined. This is equivalent to
+@code{@@set @var{var}} in the Texinfo file.
+
+@need 150
+@item --error-limit @var{limit}
+Set the maximum number of errors that @code{makeinfo} will report
+before exiting (on the assumption that continuing would be useless).
+The default number of errors that can be reported before
+@code{makeinfo} gives up is 100.@refill
+
+@need 150
+@item --fill-column @var{width}
+Specify the maximum number of columns in a line; this is the right-hand
+edge of a line. Paragraphs that are filled will be filled to this
+width. (Filling is the process of breaking up and connecting lines so
+that lines are the same length as or shorter than the number specified
+as the fill column. Lines are broken between words.) The default value
+for @code{fill-column} is 72.
+@refill
+
+@item --footnote-style @var{style}
+Set the footnote style to @var{style}, either @samp{end} for the end
+node style or @samp{separate} for the separate node style. The value
+set by this option overrides the value set in a Texinfo file by an
+@code{@@footnotestyle} command. When the footnote style is
+@samp{separate}, @code{makeinfo} makes a new node containing the
+footnotes found in the current node. When the footnote style is
+@samp{end}, @code{makeinfo} places the footnote references at the end
+of the current node.@refill
+
+@need 150
+@item -I @var{dir}
+Add @code{dir} to the directory search list for finding files that are
+included using the @code{@@include} command. By default,
+@code{makeinfo} searches only the current directory.
+
+@need 150
+@item --no-headers
+Do not include menus or node lines in the output. This results in an
+@sc{ascii} file that you cannot read in Info since it does not contain
+the requisite nodes or menus; but you can print such a file in a
+single, typewriter-like font and produce acceptable output.
+
+@need 150
+@item --no-split
+Suppress the splitting stage of @code{makeinfo}. Normally, large
+output files (where the size is greater than 70k bytes) are split into
+smaller subfiles, each one approximately 50k bytes. If you specify
+@samp{--no-split}, @code{makeinfo} will not split up the output
+file.@refill
+
+@need 100
+@item --no-pointer-validate
+@item --no-validate
+Suppress the pointer-validation phase of @code{makeinfo}. Normally,
+after a Texinfo file is processed, some consistency checks are made to
+ensure that cross references can be resolved, etc.
+@xref{Pointer Validation}.@refill
+
+@need 150
+@item --no-warn
+Suppress the output of warning messages. This does @emph{not}
+suppress the output of error messages, only warnings. You might
+want this if the file you are creating has examples of Texinfo cross
+references within it, and the nodes that are referenced do not actually
+exist.@refill
+
+@item --no-number-footnotes
+Suppress automatic footnote numbering. By default, @code{makeinfo}
+numbers each footnote sequentially in a single node, resetting the
+current footnote number to 1 at the start of each node.
+
+@need 150
+@item --output @var{file}
+@itemx -o @var{file}
+Specify that the output should be directed to @var{file} and not to the
+file name specified in the @code{@@setfilename} command found in the Texinfo
+source. @var{file} can be the special token @samp{-}, which specifies
+standard output.
+
+@need 150
+@item --paragraph-indent @var{indent}
+Set the paragraph indentation style to @var{indent}. The value set by
+this option overrides the value set in a Texinfo file by an
+@code{@@paragraphindent} command. The value of @var{indent} is
+interpreted as follows:@refill
+
+@itemize @bullet
+@item
+If the value of @var{indent} is @samp{asis}, do not change the
+existing indentation at the starts of paragraphs.@refill
+
+@item
+If the value of @var{indent} is zero, delete any existing
+indentation.@refill
+
+@item
+If the value of @var{indent} is greater than zero, indent each
+paragraph by that number of spaces.@refill
+@end itemize
+
+@need 100
+@item --reference-limit @var{limit}
+Set the value of the number of references to a node that
+@code{makeinfo} will make without reporting a warning. If a node has more
+than this number of references in it, @code{makeinfo} will make the
+references but also report a warning.@refill
+
+@need 150
+@item -U @var{var}
+Cause @var{var} to be undefined. This is equivalent to
+@code{@@clear @var{var}} in the Texinfo file.
+
+@need 100
+@item --verbose
+Cause @code{makeinfo} to display messages saying what it is doing.
+Normally, @code{makeinfo} only outputs messages if there are errors or
+warnings.@refill
+
+@need 100
+@item --version
+Report the version number of this copy of @code{makeinfo}.@refill
+@end table
+
+@node Pointer Validation, makeinfo in Emacs, makeinfo options, Create an Info File
+@section Pointer Validation
+@cindex Pointer validation with @code{makeinfo}
+@cindex Validation of pointers
+
+If you do not suppress pointer-validation, @code{makeinfo} will check
+the validity of the final Info file. Mostly, this means ensuring that
+nodes you have referenced really exist. Here is a complete list of what
+is checked:@refill
+
+@enumerate
+@item
+If a `Next', `Previous', or `Up' node reference is a reference to a
+node in the current file and is not an external reference such as to
+@file{(dir)}, then the referenced node must exist.@refill
+
+@item
+In every node, if the `Previous' node is different from the `Up' node,
+then the `Previous' node must also be pointed to by a `Next' node.@refill
+
+@item
+Every node except the `Top' node must have an `Up' pointer.@refill
+
+@item
+The node referenced by an `Up' pointer must contain a reference to the
+current node in some manner other than through a `Next' reference.
+This includes menu entries and cross references.@refill
+
+@item
+If the `Next' reference of a node is not the same as the `Next' reference
+of the `Up' reference, then the node referenced by the `Next' pointer
+must have a `Previous' pointer that points back to the current node.
+This rule allows the last node in a section to point to the first node
+of the next chapter.@refill
+@end enumerate
+
+@node makeinfo in Emacs, texinfo-format commands, Pointer Validation, Create an Info File
+@section Running @code{makeinfo} inside Emacs
+@cindex Running @code{makeinfo} in Emacs
+@cindex @code{makeinfo} inside Emacs
+@cindex Shell, running @code{makeinfo} in
+
+You can run @code{makeinfo} in GNU Emacs Texinfo mode by using either the
+@code{makeinfo-region} or the @code{makeinfo-buffer} commands. In
+Texinfo mode, the commands are bound to @kbd{C-c C-m C-r} and @kbd{C-c
+C-m C-b} by default.@refill
+
+@table @kbd
+@item C-c C-m C-r
+@itemx M-x makeinfo-region
+Format the current region for Info.@refill
+@findex makeinfo-region
+
+@item C-c C-m C-b
+@itemx M-x makeinfo-buffer
+Format the current buffer for Info.@refill
+@findex makeinfo-buffer
+@end table
+
+When you invoke either @code{makeinfo-region} or
+@code{makeinfo-buffer}, Emacs prompts for a file name, offering the
+name of the visited file as the default. You can edit the default
+file name in the minibuffer if you wish, before typing @key{RET} to
+start the @code{makeinfo} process.@refill
+
+The Emacs @code{makeinfo-region} and @code{makeinfo-buffer} commands
+run the @code{makeinfo} program in a temporary shell buffer. If
+@code{makeinfo} finds any errors, Emacs displays the error messages in
+the temporary buffer.@refill
+
+@cindex Errors, parsing
+@cindex Parsing errors
+@findex next-error
+You can parse the error messages by typing @kbd{C-x `}
+(@code{next-error}). This causes Emacs to go to and position the
+cursor on the line in the Texinfo source that @code{makeinfo} thinks
+caused the error. @xref{Compilation, , Running @code{make} or
+Compilers Generally, emacs, The GNU Emacs Manual}, for more
+information about using the @code{next-error} command.@refill
+
+In addition, you can kill the shell in which the @code{makeinfo}
+command is running or make the shell buffer display its most recent
+output.@refill
+
+@table @kbd
+@item C-c C-m C-k
+@itemx M-x makeinfo-kill-job
+@findex makeinfo-kill-job
+Kill the current running @code{makeinfo} job created by
+@code{makeinfo-region} or @code{makeinfo-buffer}.@refill
+
+@item C-c C-m C-l
+@itemx M-x makeinfo-recenter-output-buffer
+@findex makeinfo-recenter-output-buffer
+Redisplay the @code{makeinfo} shell buffer to display its most recent
+output.@refill
+@end table
+
+@noindent
+(Note that the parallel commands for killing and recentering a @TeX{}
+job are @kbd{C-c C-t C-k} and @kbd{C-c C-t C-l}. @xref{Texinfo Mode
+Printing}.)@refill
+
+You can specify options for @code{makeinfo} by setting the
+@code{makeinfo-options} variable with either the @kbd{M-x
+edit-options} or the @kbd{M-x set-variable} command, or by setting the
+variable in your @file{.emacs} initialization file.@refill
+
+For example, you could write the following in your @file{.emacs} file:@refill
+
+@example
+@group
+(setq makeinfo-options
+ "--paragraph-indent=0 --no-split
+ --fill-column=70 --verbose")
+@end group
+@end example
+
+@c If you write these three cross references using xref, you see
+@c three references to the same named manual, which looks strange.
+@iftex
+For more information, see @ref{makeinfo options, , Options for
+@code{makeinfo}}, as well as ``Editing Variable Values,''``Examining and
+Setting Variables,'' and ``Init File'' in the @cite{The GNU Emacs
+Manual}.
+@end iftex
+@noindent
+@ifinfo
+For more information, see@*
+@ref{Edit Options, , Editing Variable Values, emacs, The GNU Emacs Manual},@*
+@ref{Examining, , Examining and Setting Variables, emacs, The GNU Emacs Manual},@*
+@ref{Init File, , , emacs, The GNU Emacs Manual}, and@*
+@ref{makeinfo options, , Options for @code{makeinfo}}.
+@end ifinfo
+
+@node texinfo-format commands, Batch Formatting, makeinfo in Emacs, Create an Info File
+@comment node-name, next, previous, up
+@section The @code{texinfo-format@dots{}} Commands
+@findex texinfo-format-region
+@findex texinfo-format-buffer
+
+In GNU Emacs in Texinfo mode, you can format part or all of a Texinfo
+file with the @code{texinfo-format-region} command. This formats the
+current region and displays the formatted text in a temporary buffer
+called @samp{*Info Region*}.@refill
+
+Similarly, you can format a buffer with the
+@code{texinfo-format-buffer} command. This command creates a new
+buffer and generates the Info file in it. Typing @kbd{C-x C-s} will
+save the Info file under the name specified by the
+@code{@@setfilename} line which must be near the beginning of the
+Texinfo file.@refill
+
+@table @kbd
+@item C-c C-e C-r
+@itemx @code{texinfo-format-region}
+Format the current region for Info.
+@findex texinfo-format-region
+
+@item C-c C-e C-b
+@itemx @code{texinfo-format-buffer}
+Format the current buffer for Info.
+@findex texinfo-format-buffer
+@end table
+
+The @code{texinfo-format-region} and @code{texinfo-format-buffer}
+commands provide you with some error checking, and other functions can
+provide you with further help in finding formatting errors. These
+procedures are described in an appendix; see @ref{Catching Mistakes}.
+However, the @code{makeinfo} program is often faster and
+provides better error checking (@pxref{makeinfo in Emacs}).@refill
+
+@node Batch Formatting, Tag and Split Files, texinfo-format commands, Create an Info File
+@comment node-name, next, previous, up
+@section Batch Formatting
+@cindex Batch formatting for Info
+@cindex Info batch formatting
+
+You can format Texinfo files for Info using @code{batch-texinfo-format}
+and Emacs Batch mode. You can run Emacs in Batch mode from any shell,
+including a shell inside of Emacs. (@xref{Command Switches, , Command
+Line Switches and Arguments, emacs, The GNU Emacs Manual}.)@refill
+
+Here is the command to format all the files that end in @file{.texinfo}
+in the current directory (where @samp{%} is the shell prompt):@refill
+
+@example
+% emacs -batch -funcall batch-texinfo-format *.texinfo
+@end example
+
+@noindent
+Emacs processes all the files listed on the command line, even if an
+error occurs while attempting to format some of them.@refill
+
+Run @code{batch-texinfo-format} only with Emacs in Batch mode as shown;
+it is not interactive. It kills the Batch mode Emacs on completion.@refill
+
+@code{batch-texinfo-format} is convenient if you lack @code{makeinfo}
+and want to format several Texinfo files at once. When you use Batch
+mode, you create a new Emacs process. This frees your current Emacs, so
+you can continue working in it. (When you run
+@code{texinfo-format-region} or @code{texinfo-format-buffer}, you cannot
+use that Emacs for anything else until the command finishes.)@refill
+
+@node Tag and Split Files, , Batch Formatting, Create an Info File
+@comment node-name, next, previous, up
+@section Tag Files and Split Files
+@cindex Making a tag table automatically
+@cindex Tag table, making automatically
+
+If a Texinfo file has more than 30,000 bytes,
+@code{texinfo-format-buffer} automatically creates a tag table
+for its Info file; @code{makeinfo} always creates a tag table. With
+a @dfn{tag table}, Info can jump to new nodes more quickly than it can
+otherwise.@refill
+
+@cindex Indirect subfiles
+In addition, if the Texinfo file contains more than about 70,000
+bytes, @code{texinfo-format-buffer} and @code{makeinfo} split the
+large Info file into shorter @dfn{indirect} subfiles of about 50,000
+bytes each. Big files are split into smaller files so that Emacs does
+not need to make a large buffer to hold the whole of a large Info
+file; instead, Emacs allocates just enough memory for the small, split
+off file that is needed at the time. This way, Emacs avoids wasting
+memory when you run Info. (Before splitting was implemented, Info
+files were always kept short and @dfn{include files} were designed as
+a way to create a single, large printed manual out of the smaller Info
+files. @xref{Include Files}, for more information. Include files are
+still used for very large documents, such as @cite{The Emacs Lisp
+Reference Manual}, in which each chapter is a separate file.)@refill
+
+When a file is split, Info itself makes use of a shortened version of
+the original file that contains just the tag table and references to
+the files that were split off. The split off files are called
+@dfn{indirect} files.@refill
+
+The split off files have names that are created by appending @w{@samp{-1}},
+@w{@samp{-2}}, @w{@samp{-3}} and so on to the file name specified by the
+@code{@@setfilename} command. The shortened version of the original file
+continues to have the name specified by @code{@@setfilename}.@refill
+
+At one stage in writing this document, for example, the Info file was saved
+as @file{test-texinfo} and that file looked like this:@refill
+
+@example
+@group
+Info file: test-texinfo, -*-Text-*-
+produced by texinfo-format-buffer
+from file: new-texinfo-manual.texinfo
+
+^_
+Indirect:
+test-texinfo-1: 102
+test-texinfo-2: 50422
+@end group
+@group
+test-texinfo-3: 101300
+^_^L
+Tag table:
+(Indirect)
+Node: overview^?104
+Node: info file^?1271
+@end group
+@group
+Node: printed manual^?4853
+Node: conventions^?6855
+@dots{}
+@end group
+@end example
+
+@noindent
+(But @file{test-texinfo} had far more nodes than are shown here.) Each of
+the split off, indirect files, @file{test-texinfo-1},
+@file{test-texinfo-2}, and @file{test-texinfo-3}, is listed in this file
+after the line that says @samp{Indirect:}. The tag table is listed after
+the line that says @samp{Tag table:}. @refill
+
+In the list of indirect files, the number following the file name
+records the cumulative number of bytes in the preceding indirect files,
+not counting the file list itself, the tag table, or the permissions
+text in each file. In the tag table, the number following the node name
+records the location of the beginning of the node, in bytes from the
+beginning.@refill
+
+If you are using @code{texinfo-format-buffer} to create Info files,
+you may want to run the @code{Info-validate} command. (The
+@code{makeinfo} command does such a good job on its own, you do not
+need @code{Info-validate}.) However, you cannot run the @kbd{M-x
+Info-validate} node-checking command on indirect files. For
+information on how to prevent files from being split and how to
+validate the structure of the nodes, see @ref{Using
+Info-validate}.@refill
+
+
+@node Install an Info File, Command List, Create an Info File, Top
+@comment node-name, next, previous, up
+@chapter Installing an Info File
+@cindex Installing an Info file
+@cindex Info file installation
+@cindex @file{dir} directory for Info installation
+
+Info files are usually kept in the @file{info} directory. You can read
+Info files using the standalone Info program or the Info reader built
+into Emacs. (@inforef{Top, info, info}, for an introduction to Info.)
+
+@menu
+* Directory file:: The top level menu for all Info files.
+* New Info File:: Listing a new info file.
+* Other Info Directories:: How to specify Info files that are
+ located in other directories.
+* Installing Dir Entries:: How to specify what menu entry to add
+ to the Info directory.
+* Invoking install-info:: @code{install-info} options.
+@end menu
+
+@node Directory file, New Info File, Install an Info File, Install an Info File
+@ifinfo
+@heading The @file{dir} File
+@end ifinfo
+
+For Info to work, the @file{info} directory must contain a file that
+serves as a top level directory for the Info system. By convention,
+this file is called @file{dir}. (You can find the location of this file
+within Emacs by typing @kbd{C-h i} to enter Info and then typing
+@kbd{C-x C-f} to see the pathname to the @file{info} directory.)
+
+The @file{dir} file is itself an Info file. It contains the top level
+menu for all the Info files in the system. The menu looks like
+this:@refill
+
+@example
+@group
+* Menu:
+
+* Info: (info). Documentation browsing system.
+* Emacs: (emacs). The extensible, self-documenting
+ text editor.
+* Texinfo: (texinfo). With one source file, make
+ either a printed manual using
+ TeX or an Info file.
+@dots{}
+@end group
+@end example
+
+Each of these menu entries points to the `Top' node of the Info file
+that is named in parentheses. (The menu entry does not need to
+specify the `Top' node, since Info goes to the `Top' node if no node
+name is mentioned. @xref{Other Info Files, , Nodes in Other Info
+Files}.)@refill
+
+Thus, the @samp{Info} entry points to the `Top' node of the
+@file{info} file and the @samp{Emacs} entry points to the `Top' node
+of the @file{emacs} file.@refill
+
+In each of the Info files, the `Up' pointer of the `Top' node refers
+back to the @code{dir} file. For example, the line for the `Top'
+node of the Emacs manual looks like this in Info:@refill
+
+@example
+File: emacs Node: Top, Up: (DIR), Next: Distrib
+@end example
+
+@noindent
+(Note that in this case, the @file{dir} file name is written in upper
+case letters---it can be written in either upper or lower case. Info
+has a feature that it will change the case of the file name to lower
+case if it cannot find the name as written.)@refill
+@c !!! Can any file name be written in upper or lower case,
+@c or is dir a special case?
+@c Yes, apparently so, at least with Gillespie's Info. --rjc 24mar92
+
+
+@node New Info File, Other Info Directories, Directory file, Install an Info File
+@section Listing a New Info File
+@cindex Adding a new info file
+@cindex Listing a new info file
+@cindex New info file, listing it in @file{dir} file
+@cindex Info file, listing new one
+@cindex @file{dir} file listing
+
+To add a new Info file to your system, you must write a menu entry to
+add to the menu in the @file{dir} file in the @file{info} directory.
+For example, if you were adding documentation for GDB, you would write
+the following new entry:@refill
+
+@example
+* GDB: (gdb). The source-level C debugger.
+@end example
+
+@noindent
+The first part of the menu entry is the menu entry name, followed by a
+colon. The second part is the name of the Info file, in parentheses,
+followed by a period. The third part is the description.
+
+The name of an Info file often has a @file{.info} extension. Thus, the
+Info file for GDB might be called either @file{gdb} or @file{gdb.info}.
+The Info reader programs automatically try the file name both with and
+without @file{.info}; so it is better to avoid clutter and not to write
+@samp{.info} explicitly in the menu entry. For example, the GDB menu
+entry should use just @samp{gdb} for the file name, not @samp{gdb.info}.
+
+
+@node Other Info Directories, Installing Dir Entries, New Info File, Install an Info File
+@comment node-name, next, previous, up
+@section Info Files in Other Directories
+@cindex Installing Info in another directory
+@cindex Info installed in another directory
+@cindex Another Info directory
+
+If an Info file is not in the @file{info} directory, there are three
+ways to specify its location:@refill
+
+@itemize @bullet
+@item
+Write the pathname in the @file{dir} file as the second part of the
+menu.@refill
+
+@item
+If you are using Emacs, list the name of the file in a second @file{dir}
+file, in its directory; and then add the name of that directory to the
+@code{Info-directory-list} variable in your personal or site
+initialization file.
+
+This tells Emacs's Info reader where to look for @file{dir}
+files. Emacs merges the files named @file{dir} from each of the listed
+directories. (In Emacs Version 18, you can set the
+@code{Info-directory} variable to the name of only one
+directory.)@refill
+
+@item
+Specify the @file{info} directory name in the @code{INFOPATH}
+environment variable in your @file{.profile} or @file{.cshrc}
+initialization file. (Only you and others who set this environment
+variable will be able to find Info files whose location is specified
+this way.)@refill
+@end itemize
+
+For example, to reach a test file in the @file{~bob/manuals}
+directory, you could add an entry like this to the menu in the
+@file{dir} file:@refill
+
+@example
+* Test: (/home/bob/manuals/info-test). Bob's own test file.
+@end example
+
+@noindent
+In this case, the absolute file name of the @file{info-test} file is
+written as the second part of the menu entry.@refill
+
+@vindex Info-directory-list
+Alternatively, you could write the following in your @file{.emacs}
+file:@refill
+
+@example
+@group
+(setq Info-directory-list
+ '("/home/bob/manuals"
+ "/usr/local/emacs/info"))
+@end group
+@end example
+
+@c reworded to avoid overfill hbox
+This tells Emacs to merge the @file{dir} file from the
+@file{/home/bob/manuals} directory with the @file{dir} file from the
+@file{"/usr/local/emacs/info}" directory. Info will list the
+@file{/home/bob/manuals/info-test} file as a menu entry in the
+@file{/home/bob/manuals/dir} file.@refill
+
+@vindex INFOPATH
+Finally, you can tell Info where to look by setting the
+@code{INFOPATH} environment variable in your @file{.cshrc} or
+@file{.profile} file.@refill
+
+If you use @code{sh} or @code{bash} for your shell command interpreter,
+you must set the @code{INFOPATH} environment variable in the
+@file{.profile} initialization file; but if you use @code{csh}, you must
+set the variable in the @file{.cshrc} initialization file. The two
+files use slightly different command formats.@refill
+
+@itemize @bullet
+@item
+In a @file{.cshrc} file, you could set the @code{INFOPATH}
+variable as follows:@refill
+
+@smallexample
+setenv INFOPATH .:~bob/manuals:/usr/local/emacs/info
+@end smallexample
+
+@item
+In a @file{.profile} file, you would achieve the same effect by
+writing:@refill
+
+@smallexample
+INFOPATH=.:~bob/manuals:/usr/local/emacs/info
+export INFOPATH
+@end smallexample
+@end itemize
+
+@noindent
+The @samp{.} indicates the current directory. Emacs uses the
+@code{INFOPATH} environment variable to initialize the value of Emacs's
+own @code{Info-directory-list} variable.
+
+
+@node Installing Dir Entries, Invoking install-info, Other Info Directories, Install an Info File
+@section Installing Info Directory Files
+
+When you install an Info file onto your system, you can use the program
+@code{install-info} to update the Info directory file @file{dir}.
+Normally the makefile for the package runs @code{install-info}, just
+after copying the Info file into its proper installed location.
+
+@findex dircategory
+@findex direntry
+In order for the Info file to work with @code{install-info}, you should
+use the commands @code{@@dircategory} and @code{@@direntry} in the
+Texinfo source file. Use @code{@@direntry} to specify the menu entry to
+add to the Info directory file, and use @code{@@dircategory} to specify
+which part of the Info directory to put it in. Here is how these
+commands are used in this manual:
+
+@smallexample
+@@dircategory Texinfo documentation system
+@@direntry
+* Texinfo: (texinfo). The GNU documentation format.
+* install-info: (texinfo)Invoking install-info. @dots{}
+@dots{}
+@@end direntry
+@end smallexample
+
+Here's what this produces in the Info file:
+
+@smallexample
+INFO-DIR-SECTION Texinfo documentation system
+START-INFO-DIR-ENTRY
+* Texinfo: (texinfo). The GNU documentation format.
+* install-info: (texinfo)Invoking install-info. @dots{}
+@dots{}
+END-INFO-DIR-ENTRY
+@end smallexample
+
+@noindent
+The @code{install-info} program sees these lines in the Info file, and
+that is how it knows what to do.
+
+Always use the @code{@@direntry} and @code{@@dircategory} commands near
+the beginning of the Texinfo input, before the first @code{@@node}
+command. If you use them later on in the input, @code{install-info}
+will not notice them.
+
+If you use @code{@@dircategory} more than once in the Texinfo source,
+each usage specifies one category; the new menu entry is added to the
+Info directory file in each of the categories you specify. If you use
+@code{@@direntry} more than once, each usage specifies one menu entry;
+each of these menu entries is added to the directory in each of the
+specified categories.
+
+
+@node Invoking install-info, , Installing Dir Entries, Install an Info File
+@section Invoking install-info
+
+@pindex install-info
+
+@code{install-info} inserts menu entries from an Info file into the
+top-level @file{dir} file in the Info system (see the previous sections
+for an explanation of how the @file{dir} file works). It's most often
+run as part of software installation, or when constructing a dir file
+for all manuals on a system. Synopsis:
+
+@example
+install-info [@var{option}]@dots{} [@var{info-file} [@var{dir-file}]]
+@end example
+
+If @var{info-file} or @var{dir-file} are not specified, the various
+options (described below) that define them must be. There are no
+compile-time defaults, and standard input is never used.
+@code{install-info} can read only one info file and write only one dir
+file per invocation.
+
+Options:
+
+@table @samp
+@item --delete
+@opindex --delete
+Only delete existing entries in @var{info-file}; don't insert any new
+entries.
+
+@item --dir-file=@var{name}
+@opindex --dir-file=@var{name}
+Specify file name of the Info directory file. This is equivalent to
+using the @var{dir-file} argument.
+
+@item --entry=@var{text}
+@opindex --entry=@var{text}
+Insert @var{text} as an Info directory entry; @var{text} should have the
+form of an Info menu item line plus zero or more extra lines starting
+with whitespace. If you specify more than one entry, they are all
+added. If you don't specify any entries, they are determined from
+information in the Info file itself.
+
+@item --help
+@opindex --help
+Display a usage message listing basic usage and all available options,
+then exit successfully.
+
+@item --info-file=@var{file}
+@opindex --info-file=@var{file}
+Specify Info file to install in the directory.
+This is equivalent to using the @var{info-file} argument.
+
+@item --info-dir=@var{dir}
+@opindex --info-dir=@var{dir}
+Equivalent to @samp{--dir-file=@var{dir}/dir}.
+
+@item --item=@var{text}
+@opindex --item=@var{text}
+Same as --entry=@var{text}. An Info directory entry is actually a menu
+item.
+
+@item --quiet
+@opindex --quiet
+Suppress warnings.
+
+@item --remove
+@opindex --remove
+Same as --delete.
+
+@item --section=@var{sec}
+@opindex --section=@var{sec}
+Put this file's entries in section @var{sec} of the directory. If you
+specify more than one section, all the entries are added in each of the
+sections. If you don't specify any sections, they are determined from
+information in the Info file itself.
+
+@item --version
+@opindex --version
+@cindex version number, finding
+Display version information and exit successfully.
+
+@end table
+
+
+@c ================ Appendix starts here ================
+
+@node Command List, Tips, Install an Info File, Top
+@appendix @@-Command List
+@cindex Alphabetical @@-command list
+@cindex List of @@-commands
+@cindex @@-command list
+
+Here is an alphabetical list of the @@-commands in Texinfo. Square
+brackets, @t{[}@w{ }@t{]}, indicate optional arguments; an ellipsis,
+@samp{@dots{}}, indicates repeated text.@refill
+
+@sp 1
+@table @code
+@item @@@var{whitespace}
+An @code{@@} followed by a space, tab, or newline produces a normal,
+stretchable, interword space. @xref{Multiple Spaces}.
+
+@item @@!
+Generate an exclamation point that really does end a sentence (usually
+after an end-of-sentence capital letter). @xref{Ending a Sentence}.
+
+@item @@"
+@itemx @@'
+Generate an umlaut or acute accent, respectively, over the next
+character, as in @"o and @'o. @xref{Inserting Accents}.
+
+@item @@*
+Force a line break. Do not end a paragraph that uses @code{@@*} with
+an @code{@@refill} command. @xref{Line Breaks}.@refill
+
+@item @@,@{@var{c}@}
+Generate a cedilla accent under @var{c}, as in @,{c}. @xref{Inserting
+Accents}.
+
+@item @@-
+Insert a discretionary hyphenation point. @xref{- and hyphenation}.
+
+@item @@.
+Produce a period that really does end a sentence (usually after an
+end-of-sentence capital letter). @xref{Ending a Sentence}.
+
+@item @@:
+Indicate to @TeX{} that an immediately preceding period, question
+mark, exclamation mark, or colon does not end a sentence. Prevent
+@TeX{} from inserting extra whitespace as it does at the end of a
+sentence. The command has no effect on the Info file output.
+@xref{Not Ending a Sentence}.@refill
+
+@item @@=
+Generate a macro (bar) accent over the next character, as in @=o.
+@xref{Inserting Accents}.
+
+@item @@?
+Generate a question mark that really does end a sentence (usually after
+an end-of-sentence capital letter). @xref{Ending a Sentence}.
+
+@item @@@@
+Stands for an at sign, @samp{@@}.@*
+@xref{Braces Atsigns, , Inserting @@ and braces}.
+
+@item @@^
+@itemx @@`
+Generate a circumflex (hat) or grave accent, respectively, over the next
+character, as in @^o.
+@xref{Inserting Accents}.
+
+@item @@@{
+Stands for a left brace, @samp{@{}.@*
+@xref{Braces Atsigns, , Inserting @@ and braces}.
+
+@item @@@}
+Stands for a right-hand brace, @samp{@}}.@*
+@xref{Braces Atsigns, , Inserting @@ and braces}.
+
+@item @@=
+Generate a tilde accent over the next character, as in @~N.
+@xref{Inserting Accents}.
+
+@item @@AA@{@}
+@itemx @@aa@{@}
+Generate the uppercase and lowercase Scandinavian A-ring letters,
+respectively: @AA{}, @aa{}. @xref{Inserting Accents}.
+
+@item @@AE@{@}
+@itemx @@ae@{@}
+Generate the uppercase and lowercase AE ligatures, respectively:
+@AE{}, @ae{}. @xref{Inserting Accents}.
+
+@item @@appendix @var{title}
+Begin an appendix. The title appears in the table
+of contents of a printed manual. In Info, the title is
+underlined with asterisks. @xref{unnumbered & appendix, , The
+@code{@@unnumbered} and @code{@@appendix} Commands}.@refill
+
+@item @@appendixsec @var{title}
+@itemx @@appendixsection @var{title}
+Begin an appendix section within an appendix. The section title appears
+in the table of contents of a printed manual. In Info, the title is
+underlined with equal signs. @code{@@appendixsection} is a longer
+spelling of the @code{@@appendixsec} command. @xref{unnumberedsec
+appendixsec heading, , Section Commands}.@refill
+
+@item @@appendixsubsec @var{title}
+Begin an appendix subsection within an appendix. The title appears
+in the table of contents of a printed manual. In Info, the title is
+underlined with hyphens. @xref{unnumberedsubsec appendixsubsec
+subheading, , Subsection Commands}.@refill
+
+@item @@appendixsubsubsec @var{title}
+Begin an appendix subsubsection within a subappendix. The title
+appears in the table of contents of a printed manual. In Info, the
+title is underlined with periods. @xref{subsubsection,, The `subsub'
+Commands}.@refill
+
+@item @@asis
+Used following @code{@@table}, @code{@@ftable}, and @code{@@vtable} to
+print the table's first column without highlighting (``as is'').
+@xref{Two-column Tables, , Making a Two-column Table}.@refill
+
+@item @@author @var{author}
+Typeset @var{author} flushleft and underline it. @xref{title
+subtitle author, , The @code{@@title} and @code{@@author}
+Commands}.@refill
+
+@item @@b@{@var{text}@}
+Print @var{text} in @b{bold} font. No effect in Info. @xref{Fonts}.@refill
+
+@ignore
+@item @@br
+Force a paragraph break. If used within a line, follow @code{@@br}
+with braces. @xref{br, , @code{@@br}}.@refill
+@end ignore
+
+@item @@bullet@{@}
+Generate a large round dot, or the closest possible
+thing to one. @xref{bullet, , @code{@@bullet}}.@refill
+
+@item @@bye
+Stop formatting a file. The formatters do not see the contents of a
+file following an @code{@@bye} command. @xref{Ending a File}.@refill
+
+@item @@c @var{comment}
+Begin a comment in Texinfo. The rest of the line does not appear in
+either the Info file or the printed manual. A synonym for
+@code{@@comment}. @xref{Comments, , Comments}.@refill
+
+@item @@cartouche
+Highlight an example or quotation by drawing a box with rounded
+corners around it. Pair with @code{@@end cartouche}. No effect in
+Info. @xref{cartouche, , Drawing Cartouches Around Examples}.)@refill
+
+@item @@center @var{line-of-text}
+Center the line of text following the command.
+@xref{titlefont center sp, , @code{@@center}}.@refill
+
+@item @@centerchap @var{line-of-text}
+Like @code{@@chapter}, but centers the chapter title. @xref{chapter,,
+@code{@@chapter}}.
+
+@item @@chapheading @var{title}
+Print a chapter-like heading in the text, but not in the table of
+contents of a printed manual. In Info, the title is underlined with
+asterisks. @xref{majorheading & chapheading, , @code{@@majorheading}
+and @code{@@chapheading}}.@refill
+
+@item @@chapter @var{title}
+Begin a chapter. The chapter title appears in the table of
+contents of a printed manual. In Info, the title is underlined with
+asterisks. @xref{chapter, , @code{@@chapter}}.@refill
+
+@item @@cindex @var{entry}
+Add @var{entry} to the index of concepts. @xref{Index Entries, ,
+Defining the Entries of an Index}.@refill
+
+@item @@cite@{@var{reference}@}
+Highlight the name of a book or other reference that lacks a
+companion Info file. @xref{cite, , @code{@@cite}}.@refill
+
+@item @@clear @var{flag}
+Unset @var{flag}, preventing the Texinfo formatting commands from
+formatting text between subsequent pairs of @code{@@ifset @var{flag}}
+and @code{@@end ifset} commands, and preventing
+@code{@@value@{@var{flag}@}} from expanding to the value to which
+@var{flag} is set.
+@xref{set clear value, , @code{@@set} @code{@@clear} @code{@@value}}.@refill
+
+@item @@code@{@var{sample-code}@}
+Highlight text that is an expression, a syntactically complete token
+of a program, or a program name. @xref{code, , @code{@@code}}.@refill
+
+@item @@comment @var{comment}
+Begin a comment in Texinfo. The rest of the line does not appear in
+either the Info file or the printed manual. A synonym for @code{@@c}.
+@xref{Comments, , Comments}.@refill
+
+@item @@contents
+Print a complete table of contents. Has no effect in Info, which uses
+menus instead. @xref{Contents, , Generating a Table of
+Contents}.@refill
+
+@item @@copyright@{@}
+Generate a copyright symbol. @xref{copyright symbol, ,
+@code{@@copyright}}.@refill
+
+@ignore
+@item @@ctrl@{@var{ctrl-char}@}
+Describe an @sc{ascii} control character. Insert actual control character
+into Info file. @xref{ctrl, , @code{@@ctrl}}.@refill
+@end ignore
+
+@item @@defcodeindex @var{index-name}
+Define a new index and its indexing command. Print entries in an
+@code{@@code} font. @xref{New Indices, , Defining New
+Indices}.@refill
+
+@item @@defcv @var{category} @var{class} @var{name}
+@itemx @@defcvx @var{category} @var{class} @var{name}
+Format a description for a variable associated with a class in
+object-oriented programming. Takes three arguments: the category of
+thing being defined, the class to which it belongs, and its name.
+@xref{Definition Commands}, and @ref{deffnx,, Def Cmds in Detail}.
+
+@item @@deffn @var{category} @var{name} @var{arguments}@dots{}
+@itemx @@deffnx @var{category} @var{name} @var{arguments}@dots{}
+Format a description for a function, interactive command, or similar
+entity that may take arguments. @code{@@deffn} takes as arguments the
+category of entity being described, the name of this particular
+entity, and its arguments, if any. @xref{Definition Commands}.@refill
+
+@item @@defindex @var{index-name}
+Define a new index and its indexing command. Print entries in a roman
+font. @xref{New Indices, , Defining New Indices}.@refill
+
+@c Unused so far as I can see and unsupported by makeinfo -- karl, 15sep96.
+@item @@definfoenclose @var{new-command}, @var{before}, @var{after},
+Create new @@-command for Info that marks text by enclosing it in
+strings that precede and follow the text. Write definition inside of
+@code{@@ifinfo} @dots{} @code{@@end ifinfo}. @xref{Customized
+Highlighting}.@refill
+
+@item @@defivar @var{class} @var{instance-variable-name}
+@itemx @@defivarx @var{class} @var{instance-variable-name}
+This command formats a description for an instance variable in
+object-oriented programming. The command is equivalent to @samp{@@defcv
+@{Instance Variable@} @dots{}}. @xref{Definition Commands}, and
+@ref{deffnx,, Def Cmds in Detail}.
+
+@item @@defmac @var{macro-name} @var{arguments}@dots{}
+@itemx @@defmacx @var{macro-name} @var{arguments}@dots{}
+Format a description for a macro. The command is equivalent to
+@samp{@@deffn Macro @dots{}}. @xref{Definition Commands}, and
+@ref{deffnx,, Def Cmds in Detail}.
+
+@item @@defmethod @var{class} @var{method-name} @var{arguments}@dots{}
+@itemx @@defmethodx @var{class} @var{method-name} @var{arguments}@dots{}
+Format a description for a method in object-oriented programming. The
+command is equivalent to @samp{@@defop Method @dots{}}. Takes as
+arguments the name of the class of the method, the name of the
+method, and its arguments, if any. @xref{Definition Commands}, and
+@ref{deffnx,, Def Cmds in Detail}.
+
+@item @@defop @var{category} @var{class} @var{name} @var{arguments}@dots{}
+@itemx @@defopx @var{category} @var{class} @var{name} @var{arguments}@dots{}
+Format a description for an operation in object-oriented programming.
+@code{@@defop} takes as arguments the overall name of the category of
+operation, the name of the class of the operation, the name of the
+operation, and its arguments, if any. @xref{Definition
+Commands}, and @ref{deffnx,, Def Cmds in Detail}.
+
+@item @@defopt @var{option-name}
+@itemx @@defoptx @var{option-name}
+Format a description for a user option. The command is equivalent to
+@samp{@@defvr @{User Option@} @dots{}}. @xref{Definition Commands}, and
+@ref{deffnx,, Def Cmds in Detail}.
+
+@item @@defspec @var{special-form-name} @var{arguments}@dots{}
+@itemx @@defspecx @var{special-form-name} @var{arguments}@dots{}
+Format a description for a special form. The command is equivalent to
+@samp{@@deffn @{Special Form@} @dots{}}. @xref{Definition Commands},
+and @ref{deffnx,, Def Cmds in Detail}.
+
+@item @@deftp @var{category} @var{name-of-type} @var{attributes}@dots{}
+@itemx @@deftpx @var{category} @var{name-of-type} @var{attributes}@dots{}
+Format a description for a data type. @code{@@deftp} takes as arguments
+the category, the name of the type (which is a word like @samp{int} or
+@samp{float}), and then the names of attributes of objects of that type.
+@xref{Definition Commands}, and @ref{deffnx,, Def Cmds in Detail}.
+
+@item @@deftypefn @var{classification} @var{data-type} @var{name} @var{arguments}@dots{}
+@itemx @@deftypefnx @var{classification} @var{data-type} @var{name} @var{arguments}@dots{}
+Format a description for a function or similar entity that may take
+arguments and that is typed. @code{@@deftypefn} takes as arguments the
+classification of entity being described, the type, the name of the
+entity, and its arguments, if any. @xref{Definition Commands}, and
+@ref{deffnx,, Def Cmds in Detail}.
+
+@item @@deftypefun @var{data-type} @var{function-name} @var{arguments}@dots{}
+@itemx @@deftypefunx @var{data-type} @var{function-name} @var{arguments}@dots{}
+Format a description for a function in a typed language.
+The command is equivalent to @samp{@@deftypefn Function @dots{}}.
+@xref{Definition Commands},
+and @ref{deffnx,, Def Cmds in Detail}.
+
+@item @@deftypevr @var{classification} @var{data-type} @var{name}
+@itemx @@deftypevrx @var{classification} @var{data-type} @var{name}
+Format a description for something like a variable in a typed
+language---an entity that records a value. Takes as arguments the
+classification of entity being described, the type, and the name of the
+entity. @xref{Definition Commands}, and @ref{deffnx,, Def Cmds in
+Detail}.
+
+@item @@deftypevar @var{data-type} @var{variable-name}
+@itemx @@deftypevarx @var{data-type} @var{variable-name}
+Format a description for a variable in a typed language. The command is
+equivalent to @samp{@@deftypevr Variable @dots{}}. @xref{Definition
+Commands}, and @ref{deffnx,, Def Cmds in Detail}.
+
+@item @@defun @var{function-name} @var{arguments}@dots{}
+@itemx @@defunx @var{function-name} @var{arguments}@dots{}
+Format a description for functions. The command is equivalent to
+@samp{@@deffn Function @dots{}}. @xref{Definition Commands}, and
+@ref{deffnx,, Def Cmds in Detail}.
+
+@item @@defvar @var{variable-name}
+@itemx @@defvarx @var{variable-name}
+Format a description for variables. The command is equivalent to
+@samp{@@defvr Variable @dots{}}. @xref{Definition Commands}, and
+@ref{deffnx,, Def Cmds in Detail}.
+
+@item @@defvr @var{category} @var{name}
+@itemx @@defvrx @var{category} @var{name}
+Format a description for any kind of variable. @code{@@defvr} takes
+as arguments the category of the entity and the name of the entity.
+@xref{Definition Commands},
+and @ref{deffnx,, Def Cmds in Detail}.
+
+@item @@detailmenu@{@}
+Use to avoid Makeinfo confusion stemming from the detailed node listing
+in a master menu. @xref{Master Menu Parts}.
+
+@item @@dfn@{@var{term}@}
+Highlight the introductory or defining use of a term.
+@xref{dfn, , @code{@@dfn}}.@refill
+
+@item @@dircategory @var{dirpart}
+Specify a part of the Info directory menu where this file's entry should
+go. @xref{Installing Dir Entries}.
+
+@item @@direntry
+Begin the Info directory menu entry for this file.
+@xref{Installing Dir Entries}.
+
+@need 100
+@item @@display
+Begin a kind of example. Indent text, do not fill, do not select a
+new font. Pair with @code{@@end display}. @xref{display, ,
+@code{@@display}}.@refill
+
+@item @@dmn@{@var{dimension}@}
+Format a unit of measure, as in 12@dmn{pt}. Causes @TeX{} to insert a
+thin space before @var{dimension}. No effect in Info.
+@xref{dmn, , @code{@@dmn}}.@refill
+
+@need 100
+@item @@dots@{@}
+Insert an ellipsis: @samp{@dots{}}.
+@xref{dots, , @code{@@dots}}.@refill
+
+@item @@email@{@var{address}@}
+Indicate an electronic mail address.
+@xref{email, , @code{@@email}}.@refill
+
+@need 100
+@item @@emph@{@var{text}@}
+Highlight @var{text}; text is displayed in @emph{italics} in printed
+output, and surrounded by asterisks in Info. @xref{Emphasis, , Emphasizing Text}.@refill
+
+@item @@end @var{environment}
+Ends @var{environment}, as in @samp{@@end example}. @xref{Formatting
+Commands,,@@-commands}.
+
+@item @@enddots@{@}
+Generate an end-of-sentence of ellipsis, like this @enddots{}
+@xref{dots,,@code{@@dots@{@}}}.
+
+@need 100
+@item @@enumerate [@var{number-or-letter}]
+Begin a numbered list, using @code{@@item} for each entry.
+Optionally, start list with @var{number-or-letter}. Pair with
+@code{@@end enumerate}. @xref{enumerate, ,
+@code{@@enumerate}}.@refill
+
+@need 100
+@item @@equiv@{@}
+Indicate to the reader the exact equivalence of two forms with a
+glyph: @samp{@equiv{}}. @xref{Equivalence}.@refill
+
+@item @@error@{@}
+Indicate to the reader with a glyph that the following text is
+an error message: @samp{@error{}}. @xref{Error Glyph}.@refill
+
+@item @@evenfooting [@var{left}] @@| [@var{center}] @@| [@var{right}]
+Specify page footings for even-numbered (left-hand) pages. Not relevant to
+Info. @xref{Custom Headings, , How to Make Your Own Headings}.@refill
+
+@item @@evenheading [@var{left}] @@| [@var{center}] @@| [@var{right}]
+Specify page headings for even-numbered (left-hand) pages. Only
+supported within @code{@@iftex}. @xref{Custom Headings, , How to Make
+Your Own Headings}.@refill
+
+@item @@everyfooting [@var{left}] @@| [@var{center}] @@| [@var{right}]
+@itemx @@everyheading [@var{left}] @@| [@var{center}] @@| [@var{right}]
+Specify page footings resp.@: headings for every page. Not relevant to
+Info. @xref{Custom Headings, , How to Make Your Own Headings}.@refill
+
+@item @@example
+Begin an example. Indent text, do not fill, and select fixed-width font.
+Pair with @code{@@end example}. @xref{example, ,
+@code{@@example}}.@refill
+
+@item @@exclamdown@{@}
+Generate an upside-down exclamation point. @xref{Inserting Accents}.
+
+@item @@exdent @var{line-of-text}
+Remove any indentation a line might have. @xref{exdent, ,
+Undoing the Indentation of a Line}.@refill
+
+@item @@expansion@{@}
+Indicate the result of a macro expansion to the reader with a special
+glyph: @samp{@expansion{}}.
+@xref{expansion, , @expansion{} Indicating an Expansion}.@refill
+
+@item @@file@{@var{filename}@}
+Highlight the name of a file, buffer, node, or directory. @xref{file, ,
+@code{@@file}}.@refill
+
+@item @@finalout
+Prevent @TeX{} from printing large black warning rectangles beside
+over-wide lines. @xref{Overfull hboxes}.@refill
+
+@need 100
+@item @@findex @var{entry}
+Add @var{entry} to the index of functions. @xref{Index Entries, ,
+Defining the Entries of an Index}.@refill
+
+@need 200
+@item @@flushleft
+@itemx @@flushright
+Left justify every line but leave the right end ragged.
+Leave font as is. Pair with @code{@@end flushleft}.
+@code{@@flushright} analogous.
+@xref{flushleft & flushright, , @code{@@flushleft} and
+@code{@@flushright}}.@refill
+
+@need 200
+@item @@footnote@{@var{text-of-footnote}@}
+Enter a footnote. Footnote text is printed at the bottom of the page
+by @TeX{}; Info may format in either `End' node or `Separate' node style.
+@xref{Footnotes}.@refill
+
+@item @@footnotestyle @var{style}
+Specify an Info file's footnote style, either @samp{end} for the end
+node style or @samp{separate} for the separate node style.
+@xref{Footnotes}.@refill
+
+@item @@format
+Begin a kind of example. Like @code{@@example} or @code{@@display},
+but do not narrow the margins and do not select the fixed-width font.
+Pair with @code{@@end format}. @xref{example, ,
+@code{@@example}}.@refill
+
+@item @@ftable @var{formatting-command}
+Begin a two-column table, using @code{@@item} for each entry.
+Automatically enter each of the items in the first column into the
+index of functions. Pair with @code{@@end ftable}. The same as
+@code{@@table}, except for indexing. @xref{ftable vtable, ,
+@code{@@ftable} and @code{@@vtable}}.@refill
+
+@item @@group
+Hold text together that must appear on one printed page. Pair with
+@code{@@end group}. Not relevant to Info. @xref{group, ,
+@code{@@group}}.@refill
+
+@item @@H@{@var{c}@}
+Generate the long Hungarian umlaut accent over @var{c}, as in @H{o}.
+
+@item @@heading @var{title}
+Print an unnumbered section-like heading in the text, but not in the
+table of contents of a printed manual. In Info, the title is
+underlined with equal signs. @xref{unnumberedsec appendixsec heading,
+, Section Commands}.@refill
+
+@item @@headings @var{on-off-single-double}
+Turn page headings on or off, and/or specify single-sided or double-sided
+page headings for printing. @xref{headings on off, , The
+@code{@@headings} Command}.
+
+@item @@i@{@var{text}@}
+Print @var{text} in @i{italic} font. No effect in Info.
+@xref{Fonts}.@refill
+
+@item @@ifclear @var{flag}
+If @var{flag} is cleared, the Texinfo formatting commands format text
+between @code{@@ifclear @var{flag}} and the following @code{@@end
+ifclear} command.
+@xref{set clear value, , @code{@@set} @code{@@clear} @code{@@value}}.@refill
+
+@item @@ifhtml
+@itemx @@ifinfo
+Begin a stretch of text that will be ignored by @TeX{} when it typesets
+the printed manual. The text appears only in the HTML resp.@: Info
+file. Pair with @code{@@end ifhtml} resp.@: @code{@@end ifinfo}.
+@xref{Conditionals, , Conditionally Visible Text}.@refill
+
+@item @@ifset @var{flag}
+If @var{flag} is set, the Texinfo formatting commands format text
+between @code{@@ifset @var{flag}} and the following @code{@@end ifset}
+command.
+@xref{set clear value, , @code{@@set} @code{@@clear} @code{@@value}}.@refill
+
+@item @@iftex
+Begin a stretch of text that will not appear in the Info file, but
+will be processed only by @TeX{}. Pair with @code{@@end iftex}.
+@xref{Conditionals, , Conditionally Visible Text}.@refill
+
+@item @@ignore
+Begin a stretch of text that will not appear in either the Info file
+or the printed output. Pair with @code{@@end ignore}.
+@xref{Comments, , Comments and Ignored Text}.@refill
+
+@item @@include @var{filename}
+Incorporate the contents of the file @var{filename} into the Info file
+or printed document. @xref{Include Files}.@refill
+
+@item @@inforef@{@var{node-name}, [@var{entry-name}], @var{info-file-name}@}
+Make a cross reference to an Info file for which there is no printed
+manual. @xref{inforef, , Cross references using
+@code{@@inforef}}.@refill
+
+@item \input @var{macro-definitions-file}
+Use the specified macro definitions file. This command is used only
+in the first line of a Texinfo file to cause @TeX{} to make use of the
+@file{texinfo} macro definitions file. The backslash in @code{\input}
+is used instead of an @code{@@} because @TeX{} does not
+recognize @code{@@} until after it has read the definitions file.
+@xref{Header, , The Texinfo File Header}.@refill
+
+@item @@item
+Indicate the beginning of a marked paragraph for @code{@@itemize} and
+@code{@@enumerate}; indicate the beginning of the text of a first column
+entry for @code{@@table}, @code{@@ftable}, and @code{@@vtable}.
+@xref{Lists and Tables}.@refill
+
+@item @@itemize @var{mark-generating-character-or-command}
+Produce a sequence of indented paragraphs, with a mark inside the left
+margin at the beginning of each paragraph. Pair with @code{@@end
+itemize}. @xref{itemize, , @code{@@itemize}}.@refill
+
+@item @@itemx
+Like @code{@@item} but do not generate extra vertical space above the
+item text. @xref{itemx, , @code{@@itemx}}.@refill
+
+@item @@kbd@{@var{keyboard-characters}@}
+Indicate text that is characters of input to be typed by
+users. @xref{kbd, , @code{@@kbd}}.@refill
+
+@item @@key@{@var{key-name}@}
+Highlight @var{key-name}, a name for a key on a keyboard.
+@xref{key, , @code{@@key}}.@refill
+
+@item @@kindex @var{entry}
+Add @var{entry} to the index of keys. @xref{Index Entries, , Defining the
+Entries of an Index}.@refill
+
+@item @@L@{@}
+@itemx @@l@{@}
+Generate the uppercase and lowercase Polish suppressed-L letters,
+respectively: @L{}, @l{}.
+
+@c Possibly this can be tossed now that we have macros. --karl, 16sep96.
+@item @@global@@let@var{new-command}=@var{existing-command}
+Equate a new highlighting command with an existing one. Only for
+@TeX{}. Write definition inside of @code{@@iftex} @dots{} @code{@@end
+iftex}. @xref{Customized Highlighting}.@refill
+
+@item @@lisp
+Begin an example of Lisp code. Indent text, do not fill, and select
+fixed-width font. Pair with @code{@@end lisp}. @xref{Lisp Example, ,
+@code{@@lisp}}.@refill
+
+@item @@lowersections
+Change subsequent chapters to sections, sections to subsections, and so
+on. @xref{Raise/lower sections, , @code{@@raisesections} and
+@code{@@lowersections}}.@refill
+
+@item @@macro @var{macro-name} @{@var{params}@}
+Define a new Texinfo command @code{@@@var{macro-name}@{@var{params}@}}.
+Only supported by Makeinfo and Texi2dvi. @xref{Defining Macros}.
+
+@item @@majorheading @var{title}
+Print a chapter-like heading in the text, but not in the table of
+contents of a printed manual. Generate more vertical whitespace before
+the heading than the @code{@@chapheading} command. In Info, the chapter
+heading line is underlined with asterisks. @xref{majorheading &
+chapheading, , @code{@@majorheading} and @code{@@chapheading}}.@refill
+
+@item @@math@{@var{mathematical-expression}@}
+Format a mathematical expression.
+@xref{math, , @code{@@math}: Inserting Mathematical Expressions}.
+
+@item @@menu
+Mark the beginning of a menu of nodes in Info. No effect in a printed
+manual. Pair with @code{@@end menu}. @xref{Menus}.@refill
+
+@item @@minus@{@}
+Generate a minus sign, `@minus{}'. @xref{minus, , @code{@@minus}}.@refill
+
+@item @@multitable @var{column-width-spec}
+Begin a multi-column table. Pair with @code{@@end multitable}.
+@xref{Multitable Column Widths}.
+
+@item @@need @var{n}
+Start a new page in a printed manual if fewer than @var{n} mils
+(thousandths of an inch) remain on the current page. @xref{need, ,
+@code{@@need}}.@refill
+
+@item @@node @var{name, next, previous, up}
+Define the beginning of a new node in Info, and serve as a locator for
+references for @TeX{}. @xref{node, , @code{@@node}}.@refill
+
+@item @@noindent
+Prevent text from being indented as if it were a new paragraph.
+@xref{noindent, , @code{@@noindent}}.@refill
+
+@item @@O@{@}
+@itemx @@o@{@}
+Generate the uppercase and lowercase Owith-slash letters, respectively:
+@O{}, @o{}.
+
+@item @@oddfooting [@var{left}] @@| [@var{center}] @@| [@var{right}]
+@itemx @@oddheading [@var{left}] @@| [@var{center}] @@| [@var{right}]
+Specify page footings resp.@: headings for odd-numbered (right-hand)
+pages. Only allowed inside @code{@@iftex}. @xref{Custom Headings, ,
+How to Make Your Own Headings}.@refill
+
+@item @@OE@{@}
+@itemx @@oe@{@}
+Generate the uppercase and lowercase OE ligatures, respectively:
+@OE{}, @oe{}. @xref{Inserting Accents}.
+
+@item @@page
+Start a new page in a printed manual. No effect in Info.
+@xref{page, , @code{@@page}}.@refill
+
+@item @@paragraphindent @var{indent}
+Indent paragraphs by @var{indent} number of spaces; delete indentation
+if the value of @var{indent} is 0; and do not change indentation if
+@var{indent} is @code{asis}. @xref{paragraphindent, , Paragraph
+Indenting}.@refill
+
+@item @@pindex @var{entry}
+Add @var{entry} to the index of programs. @xref{Index Entries, , Defining
+the Entries of an Index}.@refill
+
+@item @@point@{@}
+Indicate the position of point in a buffer to the reader with a
+glyph: @samp{@point{}}. @xref{Point Glyph, , Indicating
+Point in a Buffer}.@refill
+
+@item @@pounds@{@}
+Generate the pounds sterling currency sign.
+@xref{pounds,,@code{@@pounds@{@}}}.
+
+@item @@print@{@}
+Indicate printed output to the reader with a glyph:
+@samp{@print{}}. @xref{Print Glyph}.@refill
+
+@item @@printindex @var{index-name}
+Print an alphabetized two-column index in a printed manual or generate
+an alphabetized menu of index entries for Info. @xref{Printing
+Indices & Menus}.@refill
+
+@item @@pxref@{@var{node-name}, [@var{entry}], [@var{topic-or-title}], [@var{info-file}], [@var{manual}]@}
+Make a reference that starts with a lower case `see' in a printed
+manual. Use within parentheses only. Do not follow command with a
+punctuation mark---the Info formatting commands automatically insert
+terminating punctuation as needed. Only the first argument is mandatory.
+@xref{pxref, , @code{@@pxref}}.@refill
+
+@item @@questiondown@{@}
+Generate an upside-down question mark. @xref{Inserting Accents}.
+
+@item @@quotation
+Narrow the margins to indicate text that is quoted from another real
+or imaginary work. Write command on a line of its own. Pair with
+@code{@@end quotation}. @xref{quotation, ,
+@code{@@quotation}}.@refill
+
+@need 100
+@item @@r@{@var{text}@}
+Print @var{text} in @r{roman} font. No effect in Info.
+@xref{Fonts}.@refill
+
+@item @@raisesections
+Change subsequent sections to chapters, subsections to sections, and so
+on. @xref{Raise/lower sections, , @code{@@raisesections} and
+@code{@@lowersections}}.@refill
+
+@need 300
+@item @@ref@{@var{node-name}, [@var{entry}], [@var{topic-or-title}], [@var{info-file}], [@var{manual}]@}
+Make a reference. In a printed manual, the reference does not start
+with a `See'. Follow command with a punctuation mark. Only the first
+argument is mandatory. @xref{ref, , @code{@@ref}}.@refill
+
+@need 300
+@item @@refill
+In Info, refill and indent the paragraph after all the other processing
+has been done. No effect on @TeX{}, which always refills. This command
+is no longer needed, since all formatters now automatically refill.
+@xref{Refilling Paragraphs}.@refill
+
+@need 300
+@item @@result@{@}
+Indicate the result of an expression to the reader with a special
+glyph: @samp{@result{}}. @xref{result, , @code{@@result}}.@refill
+
+@item @@ringaccent@{@var{c}@}
+Generate a ring accent over the next character, as in @ringaccent{o}.
+@xref{Inserting Accents}.
+
+@item @@samp@{@var{text}@}
+Highlight @var{text} that is a literal example of a sequence of
+characters. Used for single characters, for statements, and often for
+entire shell commands. @xref{samp, , @code{@@samp}}.@refill
+
+@item @@sc@{@var{text}@}
+Set @var{text} in a printed output in @sc{the small caps font} and
+set text in the Info file in uppercase letters.
+@xref{Smallcaps}.@refill
+
+@item @@section @var{title}
+Begin a section within a chapter. In a printed manual, the section
+title is numbered and appears in the table of contents. In Info, the
+title is underlined with equal signs. @xref{section, ,
+@code{@@section}}.@refill
+
+@item @@set @var{flag} [@var{string}]
+Make @var{flag} active, causing the Texinfo formatting commands to
+format text between subsequent pairs of @code{@@ifset @var{flag}} and
+@code{@@end ifset} commands. Optionally, set value of @var{flag} to
+@var{string}.
+@xref{set clear value, , @code{@@set} @code{@@clear} @code{@@value}}.@refill
+
+@item @@setchapternewpage @var{on-off-odd}
+Specify whether chapters start on new pages, and if so, whether on
+odd-numbered (right-hand) new pages. @xref{setchapternewpage, ,
+@code{@@setchapternewpage}}.@refill
+
+@item @@setfilename @var{info-file-name}
+Provide a name to be used by the Info file. This command is essential
+for @TeX{} formatting as well, even though it produces no output.
+@xref{setfilename, , @code{@@setfilename}}.@refill
+
+@item @@settitle @var{title}
+Provide a title for page headers in a printed manual.
+@xref{settitle, , @code{@@settitle}}.@refill
+
+@item @@shortcontents
+Print a short table of contents. Not relevant to Info, which uses
+menus rather than tables of contents. A synonym for
+@code{@@summarycontents}. @xref{Contents, , Generating a Table of
+Contents}.@refill
+
+@item @@shorttitlepage@{@var{title}@}
+Generate a minimal title page. @xref{titlepage,,@code{@@titlepage}}.
+
+@need 400
+@item @@smallbook
+Cause @TeX{} to produce a printed manual in a 7 by 9.25 inch format
+rather than the regular 8.5 by 11 inch format. @xref{smallbook, ,
+Printing Small Books}. Also, see @ref{smallexample & smalllisp, ,
+@code{@@smallexample} and @code{@@smalllisp}}.@refill
+
+@need 400
+@item @@smallexample
+Indent text to indicate an example. Do not fill, select fixed-width
+font. In @code{@@smallbook} format, print text in a smaller font than
+with @code{@@example}. Pair with @code{@@end smallexample}.
+@xref{smallexample & smalllisp, , @code{@@smallexample} and
+@code{@@smalllisp}}.@refill
+
+@need 400
+@item @@smalllisp
+Begin an example of Lisp code. Indent text, do not fill, select
+fixed-width font. In @code{@@smallbook} format, print text in a
+smaller font. Pair with @code{@@end smalllisp}. @xref{smallexample &
+smalllisp, , @code{@@smallexample} and @code{@@smalllisp}}.@refill
+
+@need 700
+@item @@sp @var{n}
+Skip @var{n} blank lines. @xref{sp, , @code{@@sp}}.@refill
+
+@item @@ss@{@}
+Generate the German sharp-S es-zet letter, @ss{}. @xref{Inserting Accents}.
+
+@need 700
+@item @@strong @var{text}
+Emphasize @var{text} by typesetting it in a @strong{bold} font for the
+printed manual and by surrounding it with asterisks for Info.
+@xref{emph & strong, , Emphasizing Text}.@refill
+
+@item @@subheading @var{title}
+Print an unnumbered subsection-like heading in the text, but not in
+the table of contents of a printed manual. In Info, the title is
+underlined with hyphens. @xref{unnumberedsubsec appendixsubsec
+subheading, , @code{@@unnumberedsubsec} @code{@@appendixsubsec}
+@code{@@subheading}}.@refill
+
+@item @@subsection @var{title}
+Begin a subsection within a section. In a printed manual, the
+subsection title is numbered and appears in the table of contents. In
+Info, the title is underlined with hyphens. @xref{subsection, ,
+@code{@@subsection}}.@refill
+
+@item @@subsubheading @var{title}
+Print an unnumbered subsubsection-like heading in the text, but not in
+the table of contents of a printed manual. In Info, the title is
+underlined with periods. @xref{subsubsection, , The `subsub'
+Commands}.@refill
+
+@item @@subsubsection @var{title}
+Begin a subsubsection within a subsection. In a printed manual,
+the subsubsection title is numbered and appears in the table of
+contents. In Info, the title is underlined with periods.
+@xref{subsubsection, , The `subsub' Commands}.@refill
+
+@item @@subtitle @var{title}
+In a printed manual, set a subtitle in a normal sized font flush to
+the right-hand side of the page. Not relevant to Info, which does not
+have title pages. @xref{title subtitle author, , @code{@@title}
+@code{@@subtitle} and @code{@@author} Commands}.@refill
+
+@item @@summarycontents
+Print a short table of contents. Not relevant to Info, which uses
+menus rather than tables of contents. A synonym for
+@code{@@shortcontents}. @xref{Contents, , Generating a Table of
+Contents}.@refill
+
+@need 300
+@item @@syncodeindex @var{from-index} @var{into-index}
+Merge the index named in the first argument into the index named in
+the second argument, printing the entries from the first index in
+@code{@@code} font. @xref{Combining Indices}.@refill
+
+@need 300
+@item @@synindex @var{from-index} @var{into-index}
+Merge the index named in the first argument into the index named in
+the second argument. Do not change the font of @var{from-index}
+entries. @xref{Combining Indices}.@refill
+
+@need 100
+@item @@t@{@var{text}@}
+Print @var{text} in a @t{fixed-width}, typewriter-like font.
+No effect in Info. @xref{Fonts}.@refill
+
+@item @@tab
+Separate columns in a multitable. @xref{Multitable Rows}.
+
+@need 400
+@item @@table @var{formatting-command}
+Begin a two-column table, using @code{@@item} for each entry. Write
+each first column entry on the same line as @code{@@item}. First
+column entries are printed in the font resulting from
+@var{formatting-command}. Pair with @code{@@end table}.
+@xref{Two-column Tables, , Making a Two-column Table}.
+Also see @ref{ftable vtable, , @code{@@ftable} and @code{@@vtable}},
+and @ref{itemx, , @code{@@itemx}}.@refill
+
+@item @@TeX@{@}
+Insert the logo @TeX{}. @xref{TeX and copyright, , Inserting @TeX{}
+and @copyright{}}.@refill
+
+@item @@tex
+Enter @TeX{} completely. Pair with @code{@@end tex}. @xref{Using
+Ordinary TeX Commands, , Using Ordinary @TeX{} Commands}.@refill
+
+@item @@thischapter
+@itemx @@thischaptername
+@itemx @@thisfile
+@itemx @@thispage
+@itemx @@thistitle
+Only allowed in a heading or footing. Stands for the number and name of
+the current chapter (in the format `Chapter 1: Title'), the chapter name
+only, the filename, the current page number, and the title of the
+document, respectively. @xref{Custom Headings, , How to Make Your Own
+Headings}.@refill
+
+@item @@tindex @var{entry}
+Add @var{entry} to the index of data types. @xref{Index Entries, ,
+Defining the Entries of an Index}.@refill
+
+@item @@title @var{title}
+In a printed manual, set a title flush to the left-hand side of the
+page in a larger than normal font and underline it with a black rule.
+Not relevant to Info, which does not have title pages. @xref{title
+subtitle author, , The @code{@@title} @code{@@subtitle} and
+@code{@@author} Commands}.@refill
+
+@need 400
+@item @@titlefont@{@var{text}@}
+In a printed manual, print @var{text} in a larger than normal font.
+Not relevant to Info, which does not have title pages.
+@xref{titlefont center sp, , The @code{@@titlefont} @code{@@center}
+and @code{@@sp} Commands}.@refill
+
+@need 300
+@item @@titlepage
+Indicate to Texinfo the beginning of the title page. Write command on
+a line of its own. Pair with @code{@@end titlepage}. Nothing between
+@code{@@titlepage} and @code{@@end titlepage} appears in Info.
+@xref{titlepage, , @code{@@titlepage}}.@refill
+
+@need 150
+@item @@today@{@}
+Insert the current date, in `1 Jan 1900' style. @xref{Custom
+Headings, , How to Make Your Own Headings}.@refill
+
+@item @@top @var{title}
+In a Texinfo file to be formatted with @code{makeinfo}, identify the
+topmost @code{@@node} line in the file, which must be written on the line
+immediately preceding the @code{@@top} command. Used for
+@code{makeinfo}'s node pointer insertion feature. The title is
+underlined with asterisks. Both the @code{@@node} line and the @code{@@top}
+line normally should be enclosed by @code{@@ifinfo} and @code{@@end
+ifinfo}. In @TeX{} and @code{texinfo-format-buffer}, the @code{@@top}
+command is merely a synonym for @code{@@unnumbered}. @xref{makeinfo
+Pointer Creation, , Creating Pointers with @code{makeinfo}}.
+
+@item @@u@var{c}
+@itemx @@ubaraccent@var{c}
+@itemx @@udotaccent@var{c}
+Generate a breve, underbar, or underdot accent, respectively, over or
+under the character @var{c}, as in @u{o}, @ubaraccent{o},
+@udotaccent{o}. @xref{Inserting Accents}.
+
+@item @@unnumbered @var{title}
+In a printed manual, begin a chapter that appears without chapter
+numbers of any kind. The title appears in the table of contents of a
+printed manual. In Info, the title is underlined with asterisks.
+@xref{unnumbered & appendix, , @code{@@unnumbered} and
+@code{@@appendix}}.@refill
+
+@item @@unnumberedsec @var{title}
+In a printed manual, begin a section that appears without section
+numbers of any kind. The title appears in the table of contents of a
+printed manual. In Info, the title is underlined with equal signs.
+@xref{unnumberedsec appendixsec heading, , Section Commands}.@refill
+
+@item @@unnumberedsubsec @var{title}
+In a printed manual, begin an unnumbered subsection within a
+chapter. The title appears in the table of contents of a printed
+manual. In Info, the title is underlined with hyphens.
+@xref{unnumberedsubsec appendixsubsec subheading, ,
+@code{@@unnumberedsubsec} @code{@@appendixsubsec}
+@code{@@subheading}}.@refill
+
+@item @@unnumberedsubsubsec @var{title}
+In a printed manual, begin an unnumbered subsubsection within a
+chapter. The title appears in the table of contents of a printed
+manual. In Info, the title is underlined with periods.
+@xref{subsubsection, , The `subsub' Commands}.@refill
+
+@item @@url@{@var{url}@}
+Highlight text that is a uniform resource locator for the World Wide
+Web. @xref{url, , @code{@@url}}.@refill
+
+@item @@v@var{c}
+Generate check accent over the character @var{c}, as in @v{o}.
+@xref{Inserting Accents}.
+
+@item @@value@{@var{flag}@}
+Replace @var{flag} with the value to which it is set by @code{@@set
+@var{flag}}.
+@xref{set clear value, , @code{@@set} @code{@@clear} @code{@@value}}.@refill
+
+@item @@var@{@var{metasyntactic-variable}@}
+Highlight a metasyntactic variable, which is something that stands for
+another piece of text. @xref{var, , Indicating Metasyntactic
+Variables}.@refill
+
+@need 400
+@item @@vindex @var{entry}
+Add @var{entry} to the index of variables. @xref{Index Entries, ,
+Defining the Entries of an Index}.@refill
+
+@need 400
+@item @@vskip @var{amount}
+In a printed manual, insert whitespace so as to push text on the
+remainder of the page towards the bottom of the page. Used in
+formatting the copyright page with the argument @samp{0pt plus
+1filll}. (Note spelling of @samp{filll}.) @code{@@vskip} may be used
+only in contexts ignored for Info. @xref{Copyright & Permissions, ,
+The Copyright Page and Printed Permissions}.@refill
+
+@need 400
+@item @@vtable @var{formatting-command}
+Begin a two-column table, using @code{@@item} for each entry.
+Automatically enter each of the items in the first column into the
+index of variables. Pair with @code{@@end vtable}. The same as
+@code{@@table}, except for indexing. @xref{ftable vtable, ,
+@code{@@ftable} and @code{@@vtable}}.@refill
+
+@need 400
+@item @@w@{@var{text}@}
+Prevent @var{text} from being split across two lines. Do not end a
+paragraph that uses @code{@@w} with an @code{@@refill} command.
+@xref{w, , @code{@@w}}.@refill
+
+@need 400
+@item @@xref@{@var{node-name}, [@var{entry}], [@var{topic-or-title}], [@var{info-file}], [@var{manual}]@}
+Make a reference that starts with `See' in a printed manual. Follow
+command with a punctuation mark. Only the first argument is
+mandatory. @xref{xref, , @code{@@xref}}.@refill
+@end table
+
+@node Tips, Sample Texinfo File, Command List, Top
+@comment node-name, next, previous, up
+@appendix Tips and Hints
+
+Here are some tips for writing Texinfo documentation:@refill
+
+@cindex Tips
+@cindex Usage tips
+@cindex Hints
+@itemize @bullet
+@item
+Write in the present tense, not in the past or the future.
+
+@item
+Write actively! For example, write ``We recommend that @dots{}'' rather
+than ``It is recommended that @dots{}''.
+
+@item
+Use 70 or 72 as your fill column. Longer lines are hard to read.
+
+@item
+Include a copyright notice and copying permissions.
+@end itemize
+
+@subsubheading Index, index, index!
+
+Write many index entries, in different ways.
+Readers like indices; they are helpful and convenient.
+
+Although it is easiest to write index entries as you write the body of
+the text, some people prefer to write entries afterwards. In either
+case, write an entry before the paragraph to which it applies. This
+way, an index entry points to the first page of a paragraph that is
+split across pages.
+
+Here are more hints we have found valuable:
+
+@itemize @bullet
+@item
+Write each index entry differently, so each entry refers to a different
+place in the document.
+
+@item
+Write index entries only where a topic is discussed significantly. For
+example, it is not useful to index ``debugging information'' in a
+chapter on reporting bugs. Someone who wants to know about debugging
+information will certainly not find it in that chapter.
+
+@item
+Consistently capitalize the first word of every concept index entry,
+or else consistently use lower case. Terse entries often call for
+lower case; longer entries for capitalization. Whichever case
+convention you use, please use one or the other consistently! Mixing
+the two styles looks bad.
+
+@item
+Always capitalize or use upper case for those words in an index for
+which this is proper, such as names of countries or acronyms. Always
+use the appropriate case for case-sensitive names, such as those in C or
+Lisp.
+
+@item
+Write the indexing commands that refer to a whole section immediately
+after the section command, and write the indexing commands that refer to
+the paragraph before the paragraph.
+
+@need 1000
+In the example that follows, a blank line comes after the index
+entry for ``Leaping'':
+
+@example
+@group
+@@section The Dog and the Fox
+@@cindex Jumping, in general
+@@cindex Leaping
+
+@@cindex Dog, lazy, jumped over
+@@cindex Lazy dog jumped over
+@@cindex Fox, jumps over dog
+@@cindex Quick fox jumps over dog
+The quick brown fox jumps over the lazy dog.
+@end group
+@end example
+
+@noindent
+(Note that the example shows entries for the same concept that are
+written in different ways---@samp{Lazy dog}, and @samp{Dog, lazy}---so
+readers can look up the concept in different ways.)
+@end itemize
+
+@subsubheading Blank lines
+
+@itemize @bullet
+@item
+Insert a blank line between a sectioning command and the first following
+sentence or paragraph, or between the indexing commands associated with
+the sectioning command and the first following sentence or paragraph, as
+shown in the tip on indexing. Otherwise, a formatter may fold title and
+paragraph together.
+
+@item
+Always insert a blank line before an @code{@@table} command and after an
+@code{@@end table} command; but never insert a blank line after an
+@code{@@table} command or before an @code{@@end table} command.
+
+@need 1000
+For example,
+
+@example
+@group
+Types of fox:
+
+@@table @@samp
+@@item Quick
+Jump over lazy dogs.
+@end group
+
+@group
+@@item Brown
+Also jump over lazy dogs.
+@@end table
+
+@end group
+@group
+@@noindent
+On the other hand, @dots{}
+@end group
+@end example
+
+Insert blank lines before and after @code{@@itemize} @dots{} @code{@@end
+itemize} and @code{@@enumerate} @dots{} @code{@@end enumerate} in the
+same way.
+@end itemize
+
+@subsubheading Complete phrases
+
+Complete phrases are easier to read than @dots{}
+
+@itemize @bullet
+@item
+Write entries in an itemized list as complete sentences; or at least, as
+complete phrases. Incomplete expressions @dots{} awkward @dots{} like
+this.
+
+@item
+Write the prefatory sentence or phrase for a multi-item list or table as
+a complete expression. Do not write ``You can set:''; instead, write
+``You can set these variables:''. The former expression sounds cut off.
+@end itemize
+
+@subsubheading Editions, dates and versions
+
+Write the edition and version numbers and date in three places in every
+manual:
+
+@enumerate
+@item
+In the first @code{@@ifinfo} section, for people reading the Texinfo file.
+
+@item
+In the @code{@@titlepage} section, for people reading the printed manual.
+
+@item
+In the `Top' node, for people reading the Info file.
+@end enumerate
+
+@noindent
+Also, it helps to write a note before the first @code{@@ifinfo}
+section to explain what you are doing.
+
+@need 800
+@noindent
+For example:
+
+@example
+@group
+@@c ===> NOTE! <==
+@@c Specify the edition and version numbers and date
+@@c in *three* places:
+@@c 1. First ifinfo section 2. title page 3. top node
+@@c To find the locations, search for !!set
+@end group
+
+@group
+@@ifinfo
+@@c !!set edition, date, version
+This is Edition 4.03, January 1992,
+of the @@cite@{GDB Manual@} for GDB Version 4.3.
+@dots{}
+@end group
+@end example
+
+@noindent
+---or use @code{@@set} and @code{@@value}
+(@pxref{value Example, , @code{@@value} Example}).
+
+@subsubheading Definition Commands
+
+Definition commands are @code{@@deffn}, @code{@@defun},
+@code{@@defmac}, and the like, and enable you to write descriptions in
+a uniform format.@refill
+
+@itemize @bullet
+@item
+Write just one definition command for each entity you define with a
+definition command. The automatic indexing feature creates an index
+entry that leads the reader to the definition.
+
+@item
+Use @code{@@table} @dots{} @code{@@end table} in an appendix that
+contains a summary of functions, not @code{@@deffn} or other definition
+commands.
+@end itemize
+
+@subsubheading Capitalization
+
+@itemize @bullet
+@item
+Capitalize @samp{Texinfo}; it is a name. Do not write the @samp{x} or
+@samp{i} in upper case.
+
+@item
+Capitalize @samp{Info}; it is a name.
+
+@item
+Write @TeX{} using the @code{@@TeX@{@}} command. Note the uppercase
+@samp{T} and @samp{X}. This command causes the formatters to
+typeset the name according to the wishes of Donald Knuth, who wrote
+@TeX{}.
+@end itemize
+
+@subsubheading Spaces
+
+Do not use spaces to format a Texinfo file, except inside of
+@code{@@example} @dots{} @code{@@end example} and similar commands.
+
+@need 700
+For example, @TeX{} fills the following:
+
+@example
+@group
+ @@kbd@{C-x v@}
+ @@kbd@{M-x vc-next-action@}
+ Perform the next logical operation
+ on the version-controlled file
+ corresponding to the current buffer.
+@end group
+@end example
+
+@need 950
+@noindent
+so it looks like this:
+
+@iftex
+@quotation
+ @kbd{C-x v}
+ @kbd{M-x vc-next-action}
+ Perform the next logical operation on the version-controlled file
+ corresponding to the current buffer.
+@end quotation
+@end iftex
+@ifinfo
+@quotation
+`C-x v' `M-x vc-next-action' Perform the next logical operation on the
+version-controlled file corresponding to the current buffer.
+@end quotation
+@end ifinfo
+
+@noindent
+In this case, the text should be formatted with
+@code{@@table}, @code{@@item}, and @code{@@itemx}, to create a table.
+
+@subsubheading @@code, @@samp, @@var, and @samp{---}
+
+@itemize @bullet
+@item
+Use @code{@@code} around Lisp symbols, including command names.
+For example,
+
+@example
+The main function is @@code@{vc-next-action@}, @dots{}
+@end example
+
+@item
+Avoid putting letters such as @samp{s} immediately after an
+@samp{@@code}. Such letters look bad.
+
+@item
+Use @code{@@var} around meta-variables. Do not write angle brackets
+around them.
+
+@item
+Use three hyphens in a row, @samp{---}, to indicate a long dash. @TeX{}
+typesets these as a long dash and the Info formatters reduce three
+hyphens to two.
+@end itemize
+
+@subsubheading Periods Outside of Quotes
+
+Place periods and other punctuation marks @emph{outside} of quotations,
+unless the punctuation is part of the quotation. This practice goes
+against publishing conventions in the United States, but enables the
+reader to distinguish between the contents of the quotation and the
+whole passage.
+
+For example, you should write the following sentence with the period
+outside the end quotation marks:
+
+@example
+Evidently, @samp{au} is an abbreviation for ``author''.
+@end example
+
+@noindent
+since @samp{au} does @emph{not} serve as an abbreviation for
+@samp{author.} (with a period following the word).
+
+@subsubheading Introducing New Terms
+
+@itemize @bullet
+@item
+Introduce new terms so that a reader who does not know them can
+understand them from context; or write a definition for the term.
+
+For example, in the following, the terms ``check in'', ``register'' and
+``delta'' are all appearing for the first time; the example sentence should be
+rewritten so they are understandable.
+
+@quotation
+The major function assists you in checking in a file to your
+version control system and registering successive sets of changes to
+it as deltas.
+@end quotation
+
+@item
+Use the @code{@@dfn} command around a word being introduced, to indicate
+that the reader should not expect to know the meaning already, and
+should expect to learn the meaning from this passage.
+@end itemize
+
+@subsubheading @@pxref
+
+@c !!! maybe include this in the tips on pxref
+@ignore
+By the way, it is okay to use pxref with something else in front of
+it within the parens, as long as the pxref is followed by the close
+paren, and the material inside the parens is not part of a larger
+sentence. Also, you can use xref inside parens as part of a complete
+sentence so long as you terminate the cross reference with punctuation.
+@end ignore
+Absolutely never use @code{@@pxref} except in the special context for
+which it is designed: inside parentheses, with the closing parenthesis
+following immediately after the closing brace. One formatter
+automatically inserts closing punctuation and the other does not. This
+means that the output looks right both in printed output and in an Info
+file, but only when the command is used inside parentheses.
+
+@subsubheading Invoking from a Shell
+
+You can invoke programs such as Emacs, GCC, and GAWK from a shell.
+The documentation for each program should contain a section that
+describes this. Unfortunately, if the node names and titles for these
+sections are all different, readers find it hard to search for the
+section.@refill
+
+Name such sections with a phrase beginning with the word
+@w{`Invoking @dots{}'}, as in `Invoking Emacs'; this way
+users can find the section easily.
+
+@subsubheading @sc{ansi c} Syntax
+
+When you use @code{@@example} to describe a C function's calling
+conventions, use the @sc{ansi c} syntax, like this:@refill
+
+@example
+void dld_init (char *@@var@{path@});
+@end example
+
+@noindent
+And in the subsequent discussion, refer to the argument values by
+writing the same argument names, again highlighted with
+@code{@@var}.@refill
+
+@need 800
+Avoid the obsolete style that looks like this:@refill
+
+@example
+#include <dld.h>
+
+dld_init (path)
+char *path;
+@end example
+
+Also, it is best to avoid writing @code{#include} above the
+declaration just to indicate that the function is declared in a
+header file. The practice may give the misimpression that the
+@code{#include} belongs near the declaration of the function. Either
+state explicitly which header file holds the declaration or, better
+yet, name the header file used for a group of functions at the
+beginning of the section that describes the functions.@refill
+
+@subsubheading Bad Examples
+
+Here are several examples of bad writing to avoid:
+
+In this example, say, `` @dots{} you must @code{@@dfn}@{check
+in@} the new version.'' That flows better.
+
+@quotation
+When you are done editing the file, you must perform a
+@code{@@dfn}@{check in@}.
+@end quotation
+
+In the following example, say, ``@dots{} makes a unified interface such as VC
+mode possible.''
+
+@quotation
+SCCS, RCS and other version-control systems all perform similar
+functions in broadly similar ways (it is this resemblance which makes
+a unified control mode like this possible).
+@end quotation
+
+And in this example, you should specify what `it' refers to:
+
+@quotation
+If you are working with other people, it assists in coordinating
+everyone's changes so they do not step on each other.
+@end quotation
+
+@subsubheading And Finally @dots{}
+
+@itemize @bullet
+@item
+Pronounce @TeX{} as if the @samp{X} were a Greek `chi', as the last
+sound in the name `Bach'. But pronounce Texinfo as in `speck':
+@samp{teckinfo}.
+
+@item
+Write notes for yourself at the very end of a Texinfo file after the
+@code{@@bye}. None of the formatters process text after the
+@code{@@bye}; it is as if the text were within @code{@@ignore} @dots{}
+@code{@@end ignore}.
+@end itemize
+
+@node Sample Texinfo File, Sample Permissions, Tips, Top
+@comment node-name, next, previous, up
+@appendix A Sample Texinfo File
+@cindex Sample Texinfo file, no comments
+
+Here is a complete, short sample Texinfo file, without any commentary.
+You can see this file, with comments, in the first chapter.
+@xref{Short Sample, , A Short Sample Texinfo File}.
+
+@sp 1
+@example
+\input texinfo @@c -*-texinfo-*-
+@@c %**start of header
+@@setfilename sample.info
+@@settitle Sample Document
+@@c %**end of header
+
+@@setchapternewpage odd
+
+@@ifinfo
+This is a short example of a complete Texinfo file.
+
+Copyright 1990 Free Software Foundation, Inc.
+@@end ifinfo
+
+@@titlepage
+@@sp 10
+@@comment The title is printed in a large font.
+@@center @@titlefont@{Sample Title@}
+
+@@c The following two commands start the copyright page.
+@@page
+@@vskip 0pt plus 1filll
+Copyright @@copyright@{@} 1990 Free Software Foundation, Inc.
+@@end titlepage
+
+@@node Top, First Chapter, (dir), (dir)
+@@comment node-name, next, previous, up
+
+@@menu
+* First Chapter:: The first chapter is the
+ only chapter in this sample.
+* Concept Index:: This index has two entries.
+@@end menu
+
+@@node First Chapter, Concept Index, Top, Top
+@@comment node-name, next, previous, up
+@@chapter First Chapter
+@@cindex Sample index entry
+
+This is the contents of the first chapter.
+@@cindex Another sample index entry
+
+Here is a numbered list.
+
+@@enumerate
+@@item
+This is the first item.
+
+@@item
+This is the second item.
+@@end enumerate
+
+The @@code@{makeinfo@} and @@code@{texinfo-format-buffer@}
+commands transform a Texinfo file such as this into
+an Info file; and @@TeX@{@} typesets it for a printed
+manual.
+
+@@node Concept Index, , First Chapter, Top
+@@comment node-name, next, previous, up
+@@unnumbered Concept Index
+
+@@printindex cp
+
+@@contents
+@@bye
+@end example
+
+@node Sample Permissions, Include Files, Sample Texinfo File, Top
+@appendix Sample Permissions
+@cindex Permissions
+@cindex Copying permissions
+
+Texinfo files should contain sections that tell the readers that they
+have the right to copy and distribute the Texinfo file, the Info file,
+and the printed manual.@refill
+
+Also, if you are writing a manual about software, you should explain
+that the software is free and either include the GNU General Public
+License (GPL) or provide a reference to it. @xref{Distrib, ,
+Distribution, emacs, The GNU Emacs Manual}, for an example of the text
+that could be used in the software ``Distribution'', ``General Public
+License'', and ``NO WARRANTY'' sections of a document. @xref{Copying,
+, Texinfo Copying Conditions}, for an example of a brief explanation
+of how the copying conditions provide you with rights. @refill
+
+@menu
+* Inserting Permissions:: How to put permissions in your document.
+* ifinfo Permissions:: Sample @samp{ifinfo} copying permissions.
+* Titlepage Permissions:: Sample Titlepage copying permissions.
+@end menu
+
+@node Inserting Permissions, ifinfo Permissions, Sample Permissions, Sample Permissions
+@ifinfo
+@appendixsec Inserting Permissions
+@end ifinfo
+
+In a Texinfo file, the first @code{@@ifinfo} section usually begins
+with a line that says what the file documents. This is what a person
+reading the unprocessed Texinfo file or using the advanced Info
+command @kbd{g *} sees first. @inforef{Expert, Advanced Info
+commands, info}, for more information. (A reader using the regular
+Info commands usually starts reading at the first node and skips
+this first section, which is not in a node.)@refill
+
+In the @code{@@ifinfo} section, the summary sentence is followed by a
+copyright notice and then by the copying permission notice. One of
+the copying permission paragraphs is enclosed in @code{@@ignore} and
+@code{@@end ignore} commands. This paragraph states that the Texinfo
+file can be processed through @TeX{} and printed, provided the printed
+manual carries the proper copying permission notice. This paragraph
+is not made part of the Info file since it is not relevant to the Info
+file; but it is a mandatory part of the Texinfo file since it permits
+people to process the Texinfo file in @TeX{} and print the
+results.@refill
+
+In the printed manual, the Free Software Foundation copying permission
+notice follows the copyright notice and publishing information and is
+located within the region delineated by the @code{@@titlepage} and
+@code{@@end titlepage} commands. The copying permission notice is exactly
+the same as the notice in the @code{@@ifinfo} section except that the
+paragraph enclosed in @code{@@ignore} and @code{@@end ignore} commands is
+not part of the notice.@refill
+
+To make it simple to insert a permission notice into each section of
+the Texinfo file, sample permission notices for each section are
+reproduced in full below.@refill
+
+Note that you may need to specify the correct name of a section
+mentioned in the permission notice. For example, in @cite{The GDB
+Manual}, the name of the section referring to the General Public
+License is called the ``GDB General Public License'', but in the
+sample shown below, that section is referred to generically as the
+``GNU General Public License''. If the Texinfo file does not carry a
+copy of the General Public License, leave out the reference to it, but
+be sure to include the rest of the sentence.@refill
+
+@node ifinfo Permissions, Titlepage Permissions, Inserting Permissions, Sample Permissions
+@comment node-name, next, previous, up
+@appendixsec @samp{ifinfo} Copying Permissions
+@cindex @samp{ifinfo} permissions
+
+In the @code{@@ifinfo} section of a Texinfo file, the standard Free
+Software Foundation permission notice reads as follows:@refill
+
+@example
+This file documents @dots{}
+
+Copyright 1992 Free Software Foundation, Inc.
+
+Permission is granted to make and distribute verbatim
+copies of this manual provided the copyright notice and
+this permission notice are preserved on all copies.
+
+@@ignore
+Permission is granted to process this file through TeX
+and print the results, provided the printed document
+carries a copying permission notice identical to this
+one except for the removal of this paragraph (this
+paragraph not being relevant to the printed manual).
+
+@@end ignore
+Permission is granted to copy and distribute modified
+versions of this manual under the conditions for
+verbatim copying, provided also that the sections
+entitled ``Copying'' and ``GNU General Public License''
+are included exactly as in the original, and provided
+that the entire resulting derived work is distributed
+under the terms of a permission notice identical to this
+one.
+
+Permission is granted to copy and distribute
+translations of this manual into another language,
+under the above conditions for modified versions,
+except that this permission notice may be stated in a
+translation approved by the Free Software Foundation.
+@end example
+
+@node Titlepage Permissions, , ifinfo Permissions, Sample Permissions
+@comment node-name, next, previous, up
+@appendixsec Titlepage Copying Permissions
+@cindex Titlepage permissions
+
+In the @code{@@titlepage} section of a Texinfo file, the standard Free
+Software Foundation copying permission notice follows the copyright
+notice and publishing information. The standard phrasing is as
+follows:@refill
+
+@example
+Permission is granted to make and distribute verbatim
+copies of this manual provided the copyright notice and
+this permission notice are preserved on all copies.
+
+Permission is granted to copy and distribute modified
+versions of this manual under the conditions for
+verbatim copying, provided also that the sections
+entitled ``Copying'' and ``GNU General Public License''
+are included exactly as in the original, and provided
+that the entire resulting derived work is distributed
+under the terms of a permission notice identical to this
+one.
+
+Permission is granted to copy and distribute
+translations of this manual into another language,
+under the above conditions for modified versions,
+except that this permission notice may be stated in a
+translation approved by the Free Software Foundation.
+@end example
+
+@node Include Files, Headings, Sample Permissions, Top
+@comment node-name, next, previous, up
+@appendix Include Files
+@cindex Include files
+
+When @TeX{} or an Info formatting command sees an @code{@@include}
+command in a Texinfo file, it processes the contents of the file named
+by the command and incorporates them into the @sc{dvi} or Info file being
+created. Index entries from the included file are incorporated into
+the indices of the output file.@refill
+
+Include files let you keep a single large document as a collection of
+conveniently small parts.@refill
+
+@menu
+* Using Include Files:: How to use the @code{@@include} command.
+* texinfo-multiple-files-update:: How to create and update nodes and
+ menus when using included files.
+* Include File Requirements:: What @code{texinfo-multiple-files-update} expects.
+* Sample Include File:: A sample outer file with included files
+ within it; and a sample included file.
+* Include Files Evolution:: How use of the @code{@@include} command
+ has changed over time.
+@end menu
+
+@node Using Include Files, texinfo-multiple-files-update, Include Files, Include Files
+@appendixsec How to Use Include Files
+@findex include
+
+To include another file within a Texinfo file, write the
+@code{@@include} command at the beginning of a line and follow it on
+the same line by the name of a file to be included. For
+example:@refill
+
+@example
+@@include buffers.texi
+@end example
+
+An included file should simply be a segment of text that you expect to
+be included as is into the overall or @dfn{outer} Texinfo file; it
+should not contain the standard beginning and end parts of a Texinfo
+file. In particular, you should not start an included file with a
+line saying @samp{\input texinfo}; if you do, that phrase is inserted
+into the output file as is. Likewise, you should not end an included
+file with an @code{@@bye} command; nothing after @code{@@bye} is
+formatted.@refill
+
+In the past, you were required to write an @code{@@setfilename} line at the
+beginning of an included file, but no longer. Now, it does not matter
+whether you write such a line. If an @code{@@setfilename} line exists
+in an included file, it is ignored.@refill
+
+Conventionally, an included file begins with an @code{@@node} line that
+is followed by an @code{@@chapter} line. Each included file is one
+chapter. This makes it easy to use the regular node and menu creating
+and updating commands to create the node pointers and menus within the
+included file. However, the simple Emacs node and menu creating and
+updating commands do not work with multiple Texinfo files. Thus you
+cannot use these commands to fill in the `Next', `Previous', and `Up'
+pointers of the @code{@@node} line that begins the included file. Also,
+you cannot use the regular commands to create a master menu for the
+whole file. Either you must insert the menus and the `Next',
+`Previous', and `Up' pointers by hand, or you must use the GNU Emacs
+Texinfo mode command, @code{texinfo-multiple-files-update}, that is
+designed for @code{@@include} files.@refill
+
+@node texinfo-multiple-files-update, Include File Requirements, Using Include Files, Include Files
+@appendixsec @code{texinfo-multiple-files-update}
+@findex texinfo-multiple-files-update
+
+GNU Emacs Texinfo mode provides the @code{texinfo-multiple-files-update}
+command. This command creates or updates `Next', `Previous', and `Up'
+pointers of included files as well as those in the outer or overall
+Texinfo file, and it creates or updates a main menu in the outer file.
+Depending whether you call it with optional arguments, the command
+updates only the pointers in the first @code{@@node} line of the
+included files or all of them:@refill
+
+@table @kbd
+@item M-x texinfo-multiple-files-update
+Called without any arguments:@refill
+
+@itemize @minus
+@item
+Create or update the `Next', `Previous', and `Up' pointers of the
+first @code{@@node} line in each file included in an outer or overall
+Texinfo file.@refill
+
+@item
+Create or update the `Top' level node pointers of the outer or
+overall file.@refill
+
+@item
+Create or update a main menu in the outer file.@refill
+@end itemize
+
+@item C-u M-x texinfo-multiple-files-update
+Called with @kbd{C-u} as a prefix argument:
+
+@itemize @minus{}
+@item
+Create or update pointers in the first @code{@@node} line in each
+included file.
+
+@item
+Create or update the `Top' level node pointers of the outer file.
+
+@item
+Create and insert a master menu in the outer file. The master menu
+is made from all the menus in all the included files.@refill
+@end itemize
+
+@item C-u 8 M-x texinfo-multiple-files-update
+Called with a numeric prefix argument, such as @kbd{C-u 8}:
+
+@itemize @minus
+@item
+Create or update @strong{all} the `Next', `Previous', and `Up' pointers
+of all the included files.@refill
+
+@item
+Create or update @strong{all} the menus of all the included
+files.@refill
+
+@item
+Create or update the `Top' level node pointers of the outer or
+overall file.@refill
+
+@item
+And then create a master menu in the outer file. This is similar to
+invoking @code{texinfo-master-menu} with an argument when you are
+working with just one file.@refill
+@end itemize
+@end table
+
+Note the use of the prefix argument in interactive use: with a regular
+prefix argument, just @w{@kbd{C-u}}, the
+@code{texinfo-multiple-files-update} command inserts a master menu;
+with a numeric prefix argument, such as @kbd{C-u 8}, the command
+updates @strong{every} pointer and menu in @strong{all} the files and then inserts a
+master menu.@refill
+
+@node Include File Requirements, Sample Include File, texinfo-multiple-files-update, Include Files
+@appendixsec Include File Requirements
+@cindex Include file requirements
+@cindex Requirements for include files
+
+If you plan to use the @code{texinfo-multiple-files-update} command,
+the outer Texinfo file that lists included files within it should
+contain nothing but the beginning and end parts of a Texinfo file, and
+a number of @code{@@include} commands listing the included files. It
+should not even include indices, which should be listed in an included
+file of their own.@refill
+
+Moreover, each of the included files must contain exactly one highest
+level node (conventionally, @code{@@chapter} or equivalent),
+and this node must be the first node in the included file.
+Furthermore, each of these highest level nodes in each included file
+must be at the same hierarchical level in the file structure.
+Usually, each is an @code{@@chapter}, an @code{@@appendix}, or an
+@code{@@unnumbered} node. Thus, normally, each included file contains
+one, and only one, chapter or equivalent-level node.@refill
+
+The outer file should contain only @emph{one} node, the `Top' node. It
+should @emph{not} contain any nodes besides the single `Top' node. The
+@code{texinfo-multiple-files-update} command will not process
+them.@refill
+
+@node Sample Include File, Include Files Evolution, Include File Requirements, Include Files
+@appendixsec Sample File with @code{@@include}
+@cindex Sample @code{@@include} file
+@cindex Include file sample
+@cindex @code{@@include} file sample
+
+Here is an example of a complete outer Texinfo file with @code{@@include} files
+within it before running @code{texinfo-multiple-files-update}, which
+would insert a main or master menu:@refill
+
+@example
+@group
+\input texinfo @@c -*-texinfo-*-
+@c %**start of header
+@@setfilename include-example.info
+@@settitle Include Example
+@c %**end of header
+@end group
+
+@group
+@@setchapternewpage odd
+@@titlepage
+@@sp 12
+@@center @@titlefont@{Include Example@}
+@@sp 2
+@@center by Whom Ever
+@end group
+
+@group
+@@page
+@@vskip 0pt plus 1filll
+Copyright @@copyright@{@} 1990 Free Software Foundation, Inc.
+@@end titlepage
+@end group
+
+@group
+@@ifinfo
+@@node Top, First, (dir), (dir)
+@@top Master Menu
+@@end ifinfo
+@end group
+
+@group
+@@include foo.texinfo
+@@include bar.texinfo
+@@include concept-index.texinfo
+@end group
+
+@group
+@@summarycontents
+@@contents
+
+@@bye
+@end group
+@end example
+
+An included file, such as @file{foo.texinfo}, might look like
+this:@refill
+
+@example
+@group
+@@node First, Second, , Top
+@@chapter First Chapter
+
+Contents of first chapter @dots{}
+@end group
+@end example
+
+The full contents of @file{concept-index.texinfo} might be as simple as this:
+
+@example
+@group
+@@node Concept Index, , Second, Top
+@@unnumbered Concept Index
+
+@@printindex cp
+@end group
+@end example
+
+The outer Texinfo source file for @cite{The GNU Emacs Lisp Reference
+Manual} is named @file{elisp.texi}. This outer file contains a master
+menu with 417 entries and a list of 41 @code{@@include}
+files.@refill
+
+@node Include Files Evolution, , Sample Include File, Include Files
+@comment node-name, next, previous, up
+@appendixsec Evolution of Include Files
+
+When Info was first created, it was customary to create many small
+Info files on one subject. Each Info file was formatted from its own
+Texinfo source file. This custom meant that Emacs did not need to
+make a large buffer to hold the whole of a large Info file when
+someone wanted information; instead, Emacs allocated just enough
+memory for the small Info file that contained the particular
+information sought. This way, Emacs could avoid wasting memory.@refill
+
+References from one file to another were made by referring to the file
+name as well as the node name. (@xref{Other Info Files, , Referring to
+Other Info Files}. Also, see @ref{Four and Five Arguments, ,
+@code{@@xref} with Four and Five Arguments}.)@refill
+
+Include files were designed primarily as a way to create a single,
+large printed manual out of several smaller Info files. In a printed
+manual, all the references were within the same document, so @TeX{}
+could automatically determine the references' page numbers. The Info
+formatting commands used include files only for creating joint
+indices; each of the individual Texinfo files had to be formatted for
+Info individually. (Each, therefore, required its own
+@code{@@setfilename} line.)@refill
+
+However, because large Info files are now split automatically, it is
+no longer necessary to keep them small.@refill
+
+Nowadays, multiple Texinfo files are used mostly for large documents,
+such as @cite{The GNU Emacs Lisp Reference Manual}, and for projects
+in which several different people write different sections of a
+document simultaneously.@refill
+
+In addition, the Info formatting commands have been extended to work
+with the @code{@@include} command so as to create a single large Info
+file that is split into smaller files if necessary. This means that
+you can write menus and cross references without naming the different
+Texinfo files.@refill
+
+@node Headings, Catching Mistakes, Include Files, Top
+@comment node-name, next, previous, up
+@appendix Page Headings
+@cindex Headings
+@cindex Footings
+@cindex Page numbering
+@cindex Page headings
+@cindex Formatting headings and footings
+
+Most printed manuals contain headings along the top of every page
+except the title and copyright pages. Some manuals also contain
+footings. (Headings and footings have no meaning to Info, which is
+not paginated.)@refill
+
+@menu
+* Headings Introduced:: Conventions for using page headings.
+* Heading Format:: Standard page heading formats.
+* Heading Choice:: How to specify the type of page heading.
+* Custom Headings:: How to create your own headings and footings.
+@end menu
+
+@node Headings Introduced, Heading Format, Headings, Headings
+@ifinfo
+@heading Headings Introduced
+@end ifinfo
+
+Texinfo provides standard page heading formats for manuals that are printed
+on one side of each sheet of paper and for manuals that are printed on
+both sides of the paper. Usually, you will use one or other of these
+formats, but you can specify your own format, if you wish.@refill
+
+In addition, you can specify whether chapters should begin on a new
+page, or merely continue the same page as the previous chapter; and if
+chapters begin on new pages, you can specify whether they must be
+odd-numbered pages.@refill
+
+By convention, a book is printed on both sides of each sheet of paper.
+When you open a book, the right-hand page is odd-numbered, and
+chapters begin on right-hand pages---a preceding left-hand page is
+left blank if necessary. Reports, however, are often printed on just
+one side of paper, and chapters begin on a fresh page immediately
+following the end of the preceding chapter. In short or informal
+reports, chapters often do not begin on a new page at all, but are
+separated from the preceding text by a small amount of whitespace.@refill
+
+The @code{@@setchapternewpage} command controls whether chapters begin
+on new pages, and whether one of the standard heading formats is used.
+In addition, Texinfo has several heading and footing commands that you
+can use to generate your own heading and footing formats.@refill
+
+In Texinfo, headings and footings are single lines at the tops and
+bottoms of pages; you cannot create multiline headings or footings.
+Each header or footer line is divided into three parts: a left part, a
+middle part, and a right part. Any part, or a whole line, may be left
+blank. Text for the left part of a header or footer line is set
+flushleft; text for the middle part is centered; and, text for the
+right part is set flushright.@refill
+
+@node Heading Format, Heading Choice, Headings Introduced, Headings
+@comment node-name, next, previous, up
+@appendixsec Standard Heading Formats
+
+Texinfo provides two standard heading formats, one for manuals printed
+on one side of each sheet of paper, and the other for manuals printed
+on both sides of the paper.
+
+By default, nothing is specified for the footing of a Texinfo file,
+so the footing remains blank.@refill
+
+The standard format for single-sided printing consists of a header
+line in which the left-hand part contains the name of the chapter, the
+central part is blank, and the right-hand part contains the page
+number.@refill
+
+@need 950
+A single-sided page looks like this:
+
+@example
+@group
+ _______________________
+ | |
+ | chapter page number |
+ | |
+ | Start of text ... |
+ | ... |
+ | |
+
+@end group
+@end example
+
+The standard format for two-sided printing depends on whether the page
+number is even or odd. By convention, even-numbered pages are on the
+left- and odd-numbered pages are on the right. (@TeX{} will adjust the
+widths of the left- and right-hand margins. Usually, widths are
+correct, but during double-sided printing, it is wise to check that
+pages will bind properly---sometimes a printer will produce output in
+which the even-numbered pages have a larger right-hand margin than the
+odd-numbered pages.)@refill
+
+In the standard double-sided format, the left part of the left-hand
+(even-numbered) page contains the page number, the central part is
+blank, and the right part contains the title (specified by the
+@code{@@settitle} command). The left part of the right-hand
+(odd-numbered) page contains the name of the chapter, the central part
+is blank, and the right part contains the page number.@refill
+
+@need 750
+Two pages, side by side as in an open book, look like this:@refill
+
+@example
+@group
+ _______________________ _______________________
+ | | | |
+ | page number title | | chapter page number |
+ | | | |
+ | Start of text ... | | More text ... |
+ | ... | | ... |
+ | | | |
+
+@end group
+@end example
+
+@noindent
+The chapter name is preceded by the word @samp{Chapter}, the chapter
+number and a colon. This makes it easier to keep track of where you
+are in the manual.@refill
+
+@node Heading Choice, Custom Headings, Heading Format, Headings
+@comment node-name, next, previous, up
+@appendixsec Specifying the Type of Heading
+
+@TeX{} does not begin to generate page headings for a standard Texinfo
+file until it reaches the @code{@@end titlepage} command. Thus, the
+title and copyright pages are not numbered. The @code{@@end
+titlepage} command causes @TeX{} to begin to generate page headings
+according to a standard format specified by the
+@code{@@setchapternewpage} command that precedes the
+@code{@@titlepage} section.@refill
+
+@need 1000
+There are four possibilities:@refill
+
+@table @asis
+@item No @code{@@setchapternewpage} command
+Cause @TeX{} to specify the single-sided heading format, with chapters
+on new pages. This is the same as @code{@@setchapternewpage on}.@refill
+
+@item @code{@@setchapternewpage on}
+Specify the single-sided heading format, with chapters on new pages.@refill
+
+@item @code{@@setchapternewpage off}
+Cause @TeX{} to start a new chapter on the same page as the last page of
+the preceding chapter, after skipping some vertical whitespace. Also
+cause @TeX{} to typeset for single-sided printing. (You can override
+the headers format with the @code{@@headings double} command; see
+@ref{headings on off, , The @code{@@headings} Command}.)@refill
+
+@item @code{@@setchapternewpage odd}
+Specify the double-sided heading format, with chapters on new pages.@refill
+@end table
+
+@noindent
+Texinfo lacks an @code{@@setchapternewpage even} command.@refill
+
+@node Custom Headings, , Heading Choice, Headings
+@comment node-name, next, previous, up
+@appendixsec How to Make Your Own Headings
+
+You can use the standard headings provided with Texinfo or specify
+your own.@refill
+
+@c Following paragraph is verbose to prevent overfull hboxes.
+Texinfo provides six commands for specifying headings and
+footings. The @code{@@everyheading} command and
+@code{@@everyfooting} command generate page headers and footers
+that are the same for both even- and odd-numbered pages.
+The @code{@@evenheading} command and @code{@@evenfooting}
+command generate headers and footers for even-numbered
+(left-hand) pages; and the @code{@@oddheading} command and
+@code{@@oddfooting} command generate headers and footers for
+odd-numbered (right-hand) pages.@refill
+
+Write custom heading specifications in the Texinfo file immediately
+after the @code{@@end titlepage} command. Enclose your specifications
+between @code{@@iftex} and @code{@@end iftex} commands since the
+@code{texinfo-format-buffer} command may not recognize them. Also,
+you must cancel the predefined heading commands with the
+@code{@@headings off} command before defining your own
+specifications.@refill
+
+@need 1000
+Here is how to tell @TeX{} to place the chapter name at the left, the
+page number in the center, and the date at the right of every header
+for both even- and odd-numbered pages:@refill
+
+@example
+@group
+@@iftex
+@@headings off
+@@everyheading @@thischapter @@| @@thispage @@| @@today@{@}
+@@end iftex
+@end group
+@end example
+
+@noindent
+You need to divide the left part from the central part and the central
+part from the right had part by inserting @samp{@@|} between parts.
+Otherwise, the specification command will not be able to tell where
+the text for one part ends and the next part begins.@refill
+
+Each part can contain text or @@-commands. The text
+is printed as if the part were within an ordinary paragraph in the
+body of the page. The @@-commands replace
+themselves with the page number, date, chapter name, or
+whatever.@refill
+
+@need 950
+Here are the six heading and footing commands:@refill
+
+@findex everyheading
+@findex everyfooting
+@table @code
+@item @@everyheading @var{left} @@| @var{center} @@| @var{right}
+@itemx @@everyfooting @var{left} @@| @var{center} @@| @var{right}
+
+The `every' commands specify the format for both even- and odd-numbered
+pages. These commands are for documents that are printed on one side
+of each sheet of paper, or for documents in which you want symmetrical
+headers or footers.@refill
+
+@findex evenheading
+@findex evenfooting
+@findex oddheading
+@findex oddfooting
+@item @@evenheading @var{left} @@| @var{center} @@| @var{right}
+@itemx @@oddheading @var{left} @@| @var{center} @@| @var{right}
+
+@itemx @@evenfooting @var{left} @@| @var{center} @@| @var{right}
+@itemx @@oddfooting @var{left} @@| @var{center} @@| @var{right}
+
+The `even' and `odd' commands specify the format for even-numbered
+pages and odd-numbered pages. These commands are for books and
+manuals that are printed on both sides of each sheet of paper.@refill
+@end table
+
+Use the @samp{@@this@dots{}} series of @@-commands to
+provide the names of chapters
+and sections and the page number. You can use the
+@samp{@@this@dots{}} commands in the left, center, or right portions
+of headers and footers, or anywhere else in a Texinfo file so long as
+they are between @code{@@iftex} and @code{@@end iftex} commands.@refill
+
+@need 1000
+Here are the @samp{@@this@dots{}} commands:@refill
+
+@table @code
+@findex thispage
+@item @@thispage
+Expands to the current page number.@refill
+@c !!! Karl Berry says that `thissection' fails on page breaks.
+@ignore
+@item @@thissection
+Expands to the name of the current section.@refill
+@end ignore
+
+@findex thischaptername
+@item @@thischaptername
+Expands to the name of the current chapter.@refill
+
+@findex thischapter
+@item @@thischapter
+Expands to the number and name of the current
+chapter, in the format `Chapter 1: Title'.@refill
+
+@findex thistitle
+@item @@thistitle
+Expands to the name of the document, as specified by the
+@code{@@settitle} command.@refill
+
+@findex thisfile
+@item @@thisfile
+For @code{@@include} files only: expands to the name of the current
+@code{@@include} file. If the current Texinfo source file is not an
+@code{@@include} file, this command has no effect. This command does
+@emph{not} provide the name of the current Texinfo source file unless
+it is an @code{@@include} file. (@xref{Include Files}, for more
+information about @code{@@include} files.)@refill
+@end table
+
+@noindent
+You can also use the @code{@@today@{@}} command, which expands to the
+current date, in `1 Jan 1900' format.@refill
+@findex today
+
+Other @@-commands and text are printed in a header or footer just as
+if they were in the body of a page. It is useful to incorporate text,
+particularly when you are writing drafts:@refill
+
+@example
+@group
+@@iftex
+@@headings off
+@@everyheading @@emph@{Draft!@} @@| @@thispage @@| @@thischapter
+@@everyfooting @@| @@| Version: 0.27: @@today@{@}
+@@end iftex
+@end group
+@end example
+
+Beware of overlong titles: they may overlap another part of the
+header or footer and blot it out.@refill
+
+@node Catching Mistakes, Refilling Paragraphs, Headings, Top
+@comment node-name, next, previous, up
+@appendix Formatting Mistakes
+@cindex Structure, catching mistakes in
+@cindex Nodes, catching mistakes
+@cindex Catching mistakes
+@cindex Correcting mistakes
+@cindex Mistakes, catching
+@cindex Problems, catching
+@cindex Debugging the Texinfo structure
+
+Besides mistakes in the content of your documentation, there
+are two kinds of mistake you can make with Texinfo: you can make mistakes
+with @@-commands, and you can make mistakes with the structure of the
+nodes and chapters.@refill
+
+Emacs has two tools for catching the @@-command mistakes and two for
+catching structuring mistakes.@refill
+
+For finding problems with @@-commands, you can run @TeX{} or a region
+formatting command on the region that has a problem; indeed, you can
+run these commands on each region as you write it.@refill
+
+For finding problems with the structure of nodes and chapters, you can use
+@kbd{C-c C-s} (@code{texinfo-show-structure}) and the related @code{occur}
+command and you can use the @kbd{M-x Info-validate} command.@refill
+
+@menu
+* makeinfo preferred:: @code{makeinfo} finds errors.
+* Debugging with Info:: How to catch errors with Info formatting.
+* Debugging with TeX:: How to catch errors with @TeX{} formatting.
+* Using texinfo-show-structure:: How to use @code{texinfo-show-structure}.
+* Using occur:: How to list all lines containing a pattern.
+* Running Info-Validate:: How to find badly referenced nodes.
+@end menu
+
+@node makeinfo preferred, Debugging with Info, Catching Mistakes, Catching Mistakes
+@ifinfo
+@heading @code{makeinfo} Find Errors
+@end ifinfo
+
+The @code{makeinfo} program does an excellent job of catching errors
+and reporting them---far better than @code{texinfo-format-region} or
+@code{texinfo-format-buffer}. In addition, the various functions for
+automatically creating and updating node pointers and menus remove
+many opportunities for human error.@refill
+
+If you can, use the updating commands to create and insert pointers
+and menus. These prevent many errors. Then use @code{makeinfo} (or
+its Texinfo mode manifestations, @code{makeinfo-region} and
+@code{makeinfo-buffer}) to format your file and check for other
+errors. This is the best way to work with Texinfo. But if you
+cannot use @code{makeinfo}, or your problem is very puzzling, then you
+may want to use the tools described in this appendix.@refill
+
+@node Debugging with Info, Debugging with TeX, makeinfo preferred, Catching Mistakes
+@comment node-name, next, previous, up
+@appendixsec Catching Errors with Info Formatting
+@cindex Catching errors with Info formatting
+@cindex Debugging with Info formatting
+
+After you have written part of a Texinfo file, you can use the
+@code{texinfo-format-region} or the @code{makeinfo-region} command to
+see whether the region formats properly.@refill
+
+Most likely, however, you are reading this section because for some
+reason you cannot use the @code{makeinfo-region} command; therefore, the
+rest of this section presumes that you are using
+@code{texinfo-format-region}.@refill
+
+If you have made a mistake with an @@-command,
+@code{texinfo-format-region} will stop processing at or after the
+error and display an error message. To see where in the buffer the
+error occurred, switch to the @samp{*Info Region*} buffer; the cursor
+will be in a position that is after the location of the error. Also,
+the text will not be formatted after the place where the error
+occurred (or more precisely, where it was detected).@refill
+
+For example, if you accidentally end a menu with the command @code{@@end
+menus} with an `s' on the end, instead of with @code{@@end menu}, you
+will see an error message that says:@refill
+
+@example
+@@end menus is not handled by texinfo
+@end example
+
+@noindent
+The cursor will stop at the point in the buffer where the error
+occurs, or not long after it. The buffer will look like this:@refill
+
+@example
+@group
+---------- Buffer: *Info Region* ----------
+* Menu:
+
+* Using texinfo-show-structure:: How to use
+ `texinfo-show-structure'
+ to catch mistakes.
+* Running Info-Validate:: How to check for
+ unreferenced nodes.
+@@end menus
+@point{}
+---------- Buffer: *Info Region* ----------
+@end group
+@end example
+
+The @code{texinfo-format-region} command sometimes provides slightly
+odd error messages. For example, the following cross reference fails to format:@refill
+
+@example
+(@@xref@{Catching Mistakes, for more info.)
+@end example
+
+@noindent
+In this case, @code{texinfo-format-region} detects the missing closing
+brace but displays a message that says @samp{Unbalanced parentheses}
+rather than @samp{Unbalanced braces}. This is because the formatting
+command looks for mismatches between braces as if they were
+parentheses.@refill
+
+Sometimes @code{texinfo-format-region} fails to detect mistakes. For
+example, in the following, the closing brace is swapped with the
+closing parenthesis:@refill
+
+@example
+(@@xref@{Catching Mistakes), for more info.@}
+@end example
+
+@noindent
+Formatting produces:
+@example
+(*Note for more info.: Catching Mistakes)
+@end example
+
+The only way for you to detect this error is to realize that the
+reference should have looked like this:@refill
+
+@example
+(*Note Catching Mistakes::, for more info.)
+@end example
+
+Incidentally, if you are reading this node in Info and type @kbd{f
+@key{RET}} (@code{Info-follow-reference}), you will generate an error
+message that says:
+
+@example
+No such node: "Catching Mistakes) The only way @dots{}
+@end example
+
+@noindent
+This is because Info perceives the example of the error as the first
+cross reference in this node and if you type a @key{RET} immediately
+after typing the Info @kbd{f} command, Info will attempt to go to the
+referenced node. If you type @kbd{f catch @key{TAB} @key{RET}}, Info
+will complete the node name of the correctly written example and take
+you to the `Catching Mistakes' node. (If you try this, you can return
+from the `Catching Mistakes' node by typing @kbd{l}
+(@code{Info-last}).)
+
+@c !!! section on using Elisp debugger ignored.
+@ignore
+Sometimes @code{texinfo-format-region} will stop long after the
+original error; this is because it does not discover the problem until
+then. In this case, you will need to backtrack.@refill
+
+@c menu
+@c * Using the Emacs Lisp Debugger:: How to use the Emacs Lisp debugger.
+@c end menu
+
+@c node Using the Emacs Lisp Debugger
+@c appendixsubsec Using the Emacs Lisp Debugger
+@c index Using the Emacs Lisp debugger
+@c index Emacs Lisp debugger
+@c index Debugger, using the Emacs Lisp
+
+If an error is especially elusive, you can turn on the Emacs Lisp
+debugger and look at the backtrace; this tells you where in the
+@code{texinfo-format-region} function the problem occurred. You can
+turn on the debugger with the command:@refill
+
+@example
+M-x set-variable @key{RET} debug-on-error @key{RET} t @key{RET}
+@end example
+
+@noindent
+and turn it off with
+
+@example
+M-x set-variable @key{RET} debug-on-error @key{RET} nil @key{RET}
+@end example
+
+Often, when you are using the debugger, it is easier to follow what is
+going on if you use the Emacs Lisp files that are not byte-compiled.
+The byte-compiled sources send octal numbers to the debugger that may
+look mysterious. To use the uncompiled source files, load
+@file{texinfmt.el} and @file{texinfo.el} with the @kbd{M-x load-file}
+command.@refill
+
+The debugger will not catch an error if @code{texinfo-format-region}
+does not detect one. In the example shown above,
+@code{texinfo-format-region} did not find the error when the whole
+list was formatted, but only when part of the list was formatted.
+When @code{texinfo-format-region} did not find an error, the debugger
+did not find one either. @refill
+
+However, when @code{texinfo-format-region} did report an error, it
+invoked the debugger. This is the backtrace it produced:@refill
+
+@example
+---------- Buffer: *Backtrace* ----------
+Signalling: (search-failed "[@},]")
+ re-search-forward("[@},]")
+ (while ...)
+ (let ...)
+ texinfo-format-parse-args()
+ (let ...)
+ texinfo-format-xref()
+ funcall(texinfo-format-xref)
+ (if ...)
+ (let ...)
+ (if ...)
+ (while ...)
+ texinfo-format-scan()
+ (save-excursion ...)
+ (let ...)
+ texinfo-format-region(103370 103631)
+* call-interactively(texinfo-format-region)
+---------- Buffer: *Backtrace* ----------
+@end example
+
+The backtrace is read from the bottom up.
+@code{texinfo-format-region} was called interactively; and it, in
+turn, called various functions, including @code{texinfo-format-scan},
+@code{texinfo-format-xref} and @code{texinfo-format-parse-args}.
+Inside the function @code{texinfo-format-parse-args}, the function
+@code{re-search-forward} was called; it was this function that could
+not find the missing right-hand brace.@refill
+
+@xref{Lisp Debug, , Debugging Emacs Lisp, emacs, The GNU Emacs
+Manual}, for more information.@refill
+@end ignore
+
+@node Debugging with TeX, Using texinfo-show-structure, Debugging with Info, Catching Mistakes
+@comment node-name, next, previous, up
+@appendixsec Catching Errors with @TeX{} Formatting
+@cindex Catching errors with @TeX{} formatting
+@cindex Debugging with @TeX{} formatting
+
+You can also catch mistakes when you format a file with @TeX{}.@refill
+
+Usually, you will want to do this after you have run
+@code{texinfo-format-buffer} (or, better, @code{makeinfo-buffer}) on
+the same file, because @code{texinfo-format-buffer} sometimes displays
+error messages that make more sense than @TeX{}. (@xref{Debugging
+with Info}, for more information.)@refill
+
+For example, @TeX{} was run on a Texinfo file, part of which is shown
+here:@refill
+
+@example
+---------- Buffer: texinfo.texi ----------
+name of the Texinfo file as an extension. The
+@@samp@{??@} are `wildcards' that cause the shell to
+substitute all the raw index files. (@@xref@{sorting
+indices, for more information about sorting
+indices.)@@refill
+---------- Buffer: texinfo.texi ----------
+@end example
+
+@noindent
+(The cross reference lacks a closing brace.)
+@TeX{} produced the following output, after which it stopped:@refill
+
+@example
+---------- Buffer: *tex-shell* ----------
+Runaway argument?
+@{sorting indices, for more information about sorting
+indices.) @@refill @@ETC.
+! Paragraph ended before @@xref was complete.
+<to be read again>
+ @@par
+l.27
+
+?
+---------- Buffer: *tex-shell* ----------
+@end example
+
+In this case, @TeX{} produced an accurate and
+understandable error message:
+
+@example
+Paragraph ended before @@xref was complete.
+@end example
+
+@noindent
+@samp{@@par} is an internal @TeX{} command of no relevance to Texinfo.
+@samp{l.27} means that @TeX{} detected the problem on line 27 of the
+Texinfo file. The @samp{?} is the prompt @TeX{} uses in this
+circumstance.@refill
+
+Unfortunately, @TeX{} is not always so helpful, and sometimes you must
+truly be a Sherlock Holmes to discover what went wrong.@refill
+
+In any case, if you run into a problem like this, you can do one of three
+things.@refill
+
+@enumerate
+@item
+You can tell @TeX{} to continue running and ignore just this error by
+typing @key{RET} at the @samp{?} prompt.@refill
+
+@item
+You can tell @TeX{} to continue running and to ignore all errors as best
+it can by typing @kbd{r @key{RET}} at the @samp{?} prompt.@refill
+
+This is often the best thing to do. However, beware: the one error
+may produce a cascade of additional error messages as its consequences
+are felt through the rest of the file. (To stop @TeX{} when it is
+producing such an avalanche of error messages, type @kbd{C-d} (or
+@kbd{C-c C-d}, if you are running a shell inside Emacs.))@refill
+
+@item
+You can tell @TeX{} to stop this run by typing @kbd{x @key{RET}}
+at the @samp{?} prompt.@refill
+@end enumerate
+
+Please note that if you are running @TeX{} inside Emacs, you need to
+switch to the shell buffer and line at which @TeX{} offers the @samp{?}
+prompt.@refill
+
+Sometimes @TeX{} will format a file without producing error messages even
+though there is a problem. This usually occurs if a command is not ended
+but @TeX{} is able to continue processing anyhow. For example, if you fail
+to end an itemized list with the @code{@@end itemize} command, @TeX{} will
+write a @sc{dvi} file that you can print out. The only error message that
+@TeX{} will give you is the somewhat mysterious comment that@refill
+
+@example
+(@@end occurred inside a group at level 1)
+@end example
+
+@noindent
+However, if you print the @sc{dvi} file, you will find that the text
+of the file that follows the itemized list is entirely indented as if
+it were part of the last item in the itemized list. The error message
+is the way @TeX{} says that it expected to find an @code{@@end}
+command somewhere in the file; but that it could not determine where
+it was needed.@refill
+
+Another source of notoriously hard-to-find errors is a missing
+@code{@@end group} command. If you ever are stumped by
+incomprehensible errors, look for a missing @code{@@end group} command
+first.@refill
+
+If the Texinfo file lacks header lines,
+@TeX{} may stop in the
+beginning of its run and display output that looks like the following.
+The @samp{*} indicates that @TeX{} is waiting for input.@refill
+
+@example
+This is TeX, Version 3.14159 (Web2c 7.0)
+(test.texinfo [1])
+*
+@end example
+
+@noindent
+In this case, simply type @kbd{\end @key{RET}} after the asterisk. Then
+write the header lines in the Texinfo file and run the @TeX{} command
+again. (Note the use of the backslash, @samp{\}. @TeX{} uses @samp{\}
+instead of @samp{@@}; and in this circumstance, you are working
+directly with @TeX{}, not with Texinfo.)@refill
+
+@node Using texinfo-show-structure, Using occur, Debugging with TeX, Catching Mistakes
+@comment node-name, next, previous, up
+@appendixsec Using @code{texinfo-show-structure}
+@cindex Showing the structure of a file
+@findex texinfo-show-structure
+
+It is not always easy to keep track of the nodes, chapters, sections, and
+subsections of a Texinfo file. This is especially true if you are revising
+or adding to a Texinfo file that someone else has written.@refill
+
+In GNU Emacs, in Texinfo mode, the @code{texinfo-show-structure}
+command lists all the lines that begin with the @@-commands that
+specify the structure: @code{@@chapter}, @code{@@section},
+@code{@@appendix}, and so on. With an argument (@w{@kbd{C-u}}
+as prefix argument, if interactive),
+the command also shows the @code{@@node} lines. The
+@code{texinfo-show-structure} command is bound to @kbd{C-c C-s} in
+Texinfo mode, by default.@refill
+
+The lines are displayed in a buffer called the @samp{*Occur*} buffer,
+indented by hierarchical level. For example, here is a part of what was
+produced by running @code{texinfo-show-structure} on this manual:@refill
+
+@example
+@group
+ Lines matching "^@@\\(chapter \\|sect\\|subs\\|subh\\|
+ unnum\\|major\\|chapheading \\|heading \\|appendix\\)"
+ in buffer texinfo.texi.
+ @dots{}
+ 4177:@@chapter Nodes
+ 4198: @@heading Two Paths
+ 4231: @@section Node and Menu Illustration
+ 4337: @@section The @@code@{@@@@node@} Command
+ 4393: @@subheading Choosing Node and Pointer Names
+ 4417: @@subsection How to Write an @@code@{@@@@node@} Line
+ 4469: @@subsection @@code@{@@@@node@} Line Tips
+ @dots{}
+@end group
+@end example
+
+This says that lines 4337, 4393, and 4417 of @file{texinfo.texi} begin
+with the @code{@@section}, @code{@@subheading}, and @code{@@subsection}
+commands respectively. If you move your cursor into the @samp{*Occur*}
+window, you can position the cursor over one of the lines and use the
+@kbd{C-c C-c} command (@code{occur-mode-goto-occurrence}), to jump to
+the corresponding spot in the Texinfo file. @xref{Other Repeating
+Search, , Using Occur, emacs, The GNU Emacs Manual}, for more
+information about @code{occur-mode-goto-occurrence}.@refill
+
+The first line in the @samp{*Occur*} window describes the @dfn{regular
+expression} specified by @var{texinfo-heading-pattern}. This regular
+expression is the pattern that @code{texinfo-show-structure} looks for.
+@xref{Regexps, , Using Regular Expressions, emacs, The GNU Emacs Manual},
+for more information.@refill
+
+When you invoke the @code{texinfo-show-structure} command, Emacs will
+display the structure of the whole buffer. If you want to see the
+structure of just a part of the buffer, of one chapter, for example,
+use the @kbd{C-x n n} (@code{narrow-to-region}) command to mark the
+region. (@xref{Narrowing, , , emacs, The GNU Emacs Manual}.) This is
+how the example used above was generated. (To see the whole buffer
+again, use @kbd{C-x n w} (@code{widen}).)@refill
+
+If you call @code{texinfo-show-structure} with a prefix argument by
+typing @w{@kbd{C-u C-c C-s}}, it will list lines beginning with
+@code{@@node} as well as the lines beginning with the @@-sign commands
+for @code{@@chapter}, @code{@@section}, and the like.@refill
+
+You can remind yourself of the structure of a Texinfo file by looking at
+the list in the @samp{*Occur*} window; and if you have mis-named a node
+or left out a section, you can correct the mistake.@refill
+
+@node Using occur, Running Info-Validate, Using texinfo-show-structure, Catching Mistakes
+@comment node-name, next, previous, up
+@appendixsec Using @code{occur}
+@cindex Occurrences, listing with @code{@@occur}
+@findex occur
+
+Sometimes the @code{texinfo-show-structure} command produces too much
+information. Perhaps you want to remind yourself of the overall structure
+of a Texinfo file, and are overwhelmed by the detailed list produced by
+@code{texinfo-show-structure}. In this case, you can use the @code{occur}
+command directly. To do this, type@refill
+
+@example
+@kbd{M-x occur}
+@end example
+
+@noindent
+and then, when prompted, type a @dfn{regexp}, a regular expression for
+the pattern you want to match. (@xref{Regexps, , Regular Expressions,
+emacs, The GNU Emacs Manual}.) The @code{occur} command works from
+the current location of the cursor in the buffer to the end of the
+buffer. If you want to run @code{occur} on the whole buffer, place
+the cursor at the beginning of the buffer.@refill
+
+For example, to see all the lines that contain the word
+@samp{@@chapter} in them, just type @samp{@@chapter}. This will
+produce a list of the chapters. It will also list all the sentences
+with @samp{@@chapter} in the middle of the line.@refill
+
+If you want to see only those lines that start with the word
+@samp{@@chapter}, type @samp{^@@chapter} when prompted by
+@code{occur}. If you want to see all the lines that end with a word
+or phrase, end the last word with a @samp{$}; for example,
+@samp{catching mistakes$}. This can be helpful when you want to see
+all the nodes that are part of the same chapter or section and
+therefore have the same `Up' pointer.@refill
+
+@xref{Other Repeating Search, , Using Occur, emacs , The GNU Emacs Manual},
+for more information.@refill
+
+@node Running Info-Validate, , Using occur, Catching Mistakes
+@comment node-name, next, previous, up
+@appendixsec Finding Badly Referenced Nodes
+@findex Info-validate
+@cindex Nodes, checking for badly referenced
+@cindex Checking for badly referenced nodes
+@cindex Looking for badly referenced nodes
+@cindex Finding badly referenced nodes
+@cindex Badly referenced nodes
+
+You can use the @code{Info-validate} command to check whether any of
+the `Next', `Previous', `Up' or other node pointers fail to point to a
+node. This command checks that every node pointer points to an
+existing node. The @code{Info-validate} command works only on Info
+files, not on Texinfo files.@refill
+
+The @code{makeinfo} program validates pointers automatically, so you
+do not need to use the @code{Info-validate} command if you are using
+@code{makeinfo}. You only may need to use @code{Info-validate} if you
+are unable to run @code{makeinfo} and instead must create an Info file
+using @code{texinfo-format-region} or @code{texinfo-format-buffer}, or
+if you write an Info file from scratch.@refill
+
+@menu
+* Using Info-validate:: How to run @code{Info-validate}.
+* Unsplit:: How to create an unsplit file.
+* Tagifying:: How to tagify a file.
+* Splitting:: How to split a file manually.
+@end menu
+
+@node Using Info-validate, Unsplit, Running Info-Validate, Running Info-Validate
+@appendixsubsec Running @code{Info-validate}
+@cindex Running @code{Info-validate}
+@cindex Info validating a large file
+@cindex Validating a large file
+
+To use @code{Info-validate}, visit the Info file you wish to check and
+type:@refill
+
+@example
+M-x Info-validate
+@end example
+
+@noindent
+(Note that the @code{Info-validate} command requires an upper case
+`I'. You may also need to create a tag table before running
+@code{Info-validate}. @xref{Tagifying}.)@refill
+
+If your file is valid, you will receive a message that says ``File appears
+valid''. However, if you have a pointer that does not point to a node,
+error messages will be displayed in a buffer called @samp{*problems in
+info file*}.@refill
+
+For example, @code{Info-validate} was run on a test file that contained
+only the first node of this manual. One of the messages said:@refill
+
+@example
+In node "Overview", invalid Next: Texinfo Mode
+@end example
+
+@noindent
+This meant that the node called @samp{Overview} had a `Next' pointer that
+did not point to anything (which was true in this case, since the test file
+had only one node in it).@refill
+
+Now suppose we add a node named @samp{Texinfo Mode} to our test case
+but we do not specify a `Previous' for this node. Then we will get
+the following error message:@refill
+
+@example
+In node "Texinfo Mode", should have Previous: Overview
+@end example
+
+@noindent
+This is because every `Next' pointer should be matched by a
+`Previous' (in the node where the `Next' points) which points back.@refill
+
+@code{Info-validate} also checks that all menu entries and cross references
+point to actual nodes.@refill
+
+Note that @code{Info-validate} requires a tag table and does not work
+with files that have been split. (The @code{texinfo-format-buffer}
+command automatically splits large files.) In order to use
+@code{Info-validate} on a large file, you must run
+@code{texinfo-format-buffer} with an argument so that it does not split
+the Info file; and you must create a tag table for the unsplit
+file.@refill
+
+@node Unsplit, Tagifying, Using Info-validate, Running Info-Validate
+@comment node-name, next, previous, up
+@appendixsubsec Creating an Unsplit File
+@cindex Creating an unsplit file
+@cindex Unsplit file creation
+
+You can run @code{Info-validate} only on a single Info file that has a
+tag table. The command will not work on the indirect subfiles that
+are generated when a master file is split. If you have a large file
+(longer than 70,000 bytes or so), you need to run the
+@code{texinfo-format-buffer} or @code{makeinfo-buffer} command in such
+a way that it does not create indirect subfiles. You will also need
+to create a tag table for the Info file. After you have done this,
+you can run @code{Info-validate} and look for badly referenced
+nodes.@refill
+
+The first step is to create an unsplit Info file. To prevent
+@code{texinfo-format-buffer} from splitting a Texinfo file into
+smaller Info files, give a prefix to the @kbd{M-x
+texinfo-format-buffer} command:@refill
+
+@example
+C-u M-x texinfo-format-buffer
+@end example
+
+@noindent
+or else
+
+@example
+C-u C-c C-e C-b
+@end example
+
+@noindent
+When you do this, Texinfo will not split the file and will not create
+a tag table for it. @refill
+@cindex Making a tag table manually
+@cindex Tag table, making manually
+
+@node Tagifying, Splitting, Unsplit, Running Info-Validate
+@appendixsubsec Tagifying a File
+
+After creating an unsplit Info file, you must create a tag table for
+it. Visit the Info file you wish to tagify and type:@refill
+
+@example
+M-x Info-tagify
+@end example
+
+@noindent
+(Note the upper case @samp{I} in @code{Info-tagify}.) This creates an
+Info file with a tag table that you can validate.@refill
+
+The third step is to validate the Info file:@refill
+
+@example
+M-x Info-validate
+@end example
+
+@noindent
+(Note the upper case @samp{I} in @code{Info-validate}.)
+In brief, the steps are:@refill
+
+@example
+@group
+C-u M-x texinfo-format-buffer
+M-x Info-tagify
+M-x Info-validate
+@end group
+@end example
+
+After you have validated the node structure, you can rerun
+@code{texinfo-format-buffer} in the normal way so it will construct a
+tag table and split the file automatically, or you can make the tag
+table and split the file manually.@refill
+
+@node Splitting, , Tagifying, Running Info-Validate
+@comment node-name, next, previous, up
+@appendixsubsec Splitting a File Manually
+@cindex Splitting an Info file manually
+@cindex Info file, splitting manually
+
+You should split a large file or else let the
+@code{texinfo-format-buffer} or @code{makeinfo-buffer} command do it
+for you automatically. (Generally you will let one of the formatting
+commands do this job for you. @xref{Create an Info File}.)@refill
+
+The split-off files are called the indirect subfiles.@refill
+
+Info files are split to save memory. With smaller files, Emacs does not
+have make such a large buffer to hold the information.@refill
+
+If an Info file has more than 30 nodes, you should also make a tag
+table for it. @xref{Using Info-validate}, for information
+about creating a tag table. (Again, tag tables are usually created
+automatically by the formatting command; you only need to create a tag
+table yourself if you are doing the job manually. Most likely, you
+will do this for a large, unsplit file on which you have run
+@code{Info-validate}.)@refill
+
+@c Info-split is autoloaded in `loaddefs.el' in Emacs 18.51
+@ignore
+Before running @code{Info-split}, you need to load the @code{info} library
+into Emacs by giving the command @kbd{M-x load-library @key{RET} info
+@key{RET}}.
+@end ignore
+
+Visit the Info file you wish to tagify and split and type the two
+commands:@refill
+
+@example
+M-x Info-tagify
+M-x Info-split
+@end example
+
+@noindent
+(Note that the @samp{I} in @samp{Info} is upper case.)@refill
+
+When you use the @code{Info-split} command, the buffer is modified into a
+(small) Info file which lists the indirect subfiles. This file should be
+saved in place of the original visited file. The indirect subfiles are
+written in the same directory the original file is in, with names generated
+by appending @samp{-} and a number to the original file name.@refill
+
+The primary file still functions as an Info file, but it contains just
+the tag table and a directory of subfiles.@refill
+
+@node Refilling Paragraphs, Command Syntax, Catching Mistakes, Top
+@comment node-name, next, previous, up
+@appendix Refilling Paragraphs
+@cindex Refilling paragraphs
+@cindex Filling paragraphs
+@findex refill
+
+The @code{@@refill} command refills and, optionally, indents the first
+line of a paragraph.@footnote{Perhaps the command should have been
+called the @code{@@refillandindent} command, but @code{@@refill} is
+shorter and the name was chosen before indenting was possible.} The
+@code{@@refill} command is no longer important, but we describe it here
+because you once needed it. You will see it in many old Texinfo
+files.@refill
+
+Without refilling, paragraphs containing long @@-constructs may look
+bad after formatting because the formatter removes @@-commands and
+shortens some lines more than others. In the past, neither the
+@code{texinfo-format-region} command nor the
+@code{texinfo-format-buffer} command refilled paragraphs
+automatically. The @code{@@refill} command had to be written at the
+end of every paragraph to cause these formatters to fill them. (Both
+@TeX{} and @code{makeinfo} have always refilled paragraphs
+automatically.) Now, all the Info formatters automatically fill and
+indent those paragraphs that need to be filled and indented.@refill
+
+The @code{@@refill} command causes @code{texinfo-format-region} and
+@code{texinfo-format-buffer} to refill a paragraph in the Info file
+@emph{after} all the other processing has been done. For this reason,
+you can not use @code{@@refill} with a paragraph containing either
+@code{@@*} or @code{@@w@{ @dots{} @}} since the refilling action will
+override those two commands.@refill
+
+The @code{texinfo-format-region} and @code{texinfo-format-buffer}
+commands now automatically append @code{@@refill} to the end of each
+paragraph that should be filled. They do not append @code{@@refill} to
+the ends of paragraphs that contain @code{@@*} or @w{@code{@@w@{ @dots{}@}}}
+and therefore do not refill or indent them.@refill
+
+@node Command Syntax, Obtaining TeX, Refilling Paragraphs, Top
+@comment node-name, next, previous, up
+@appendix @@-Command Syntax
+@cindex @@-command syntax
+
+The character @samp{@@} is used to start special Texinfo commands.
+(It has the same meaning that @samp{\} has in plain @TeX{}.) Texinfo
+has four types of @@-command:@refill
+
+@table @asis
+@item 1. Non-alphabetic commands.
+These commands consist of an @@ followed by a punctuation mark or other
+character that is not part of the alphabet. Non-alphabetic commands
+are almost always part of the text within a paragraph, and never take
+any argument. The two characters (@@ and the other one) are complete
+in themselves; none is followed by braces. The non-alphabetic
+commands are: @code{@@.}, @code{@@:}, @code{@@*}, @code{@@@@},
+@code{@@@{}, and @code{@@@}}.@refill
+
+@item 2. Alphabetic commands that do not require arguments.
+These commands start with @@ followed by a word followed by left- and
+right-hand braces. These commands insert special symbols in the
+document; they do not require arguments. For example,
+@code{@@dots@{@}} @result{} @samp{@dots{}}, @code{@@equiv@{@}}
+@result{} @samp{@equiv{}}, @code{@@TeX@{@}} @result{} `@TeX{}',
+and @code{@@bullet@{@}} @result{} @samp{@bullet{}}.@refill
+
+@item 3. Alphabetic commands that require arguments within braces.
+These commands start with @@ followed by a letter or a word, followed by an
+argument within braces. For example, the command @code{@@dfn} indicates
+the introductory or defining use of a term; it is used as follows: @samp{In
+Texinfo, @@@@-commands are @@dfn@{mark-up@} commands.}@refill
+
+@item 4. Alphabetic commands that occupy an entire line.
+These commands occupy an entire line. The line starts with @@,
+followed by the name of the command (a word); for example, @code{@@center}
+or @code{@@cindex}. If no argument is needed, the word is followed by
+the end of the line. If there is an argument, it is separated from
+the command name by a space. Braces are not used.@refill
+@end table
+
+@cindex Braces and argument syntax
+Thus, the alphabetic commands fall into classes that have
+different argument syntaxes. You cannot tell to which class a command
+belongs by the appearance of its name, but you can tell by the
+command's meaning: if the command stands for a glyph, it is in
+class 2 and does not require an argument; if it makes sense to use the
+command together with other text as part of a paragraph, the command
+is in class 3 and must be followed by an argument in braces;
+otherwise, it is in class 4 and uses the rest of the line as its
+argument.@refill
+
+The purpose of having a different syntax for commands of classes 3 and
+4 is to make Texinfo files easier to read, and also to help the GNU
+Emacs paragraph and filling commands work properly. There is only one
+exception to this rule: the command @code{@@refill}, which is always
+used at the end of a paragraph immediately following the final period
+or other punctuation character. @code{@@refill} takes no argument and
+does @emph{not} require braces. @code{@@refill} never confuses the
+Emacs paragraph commands because it cannot appear at the beginning of
+a line.@refill
+
+@node Obtaining TeX, New Features, Command Syntax, Top
+@appendix How to Obtain @TeX{}
+@cindex Obtaining @TeX{}
+@cindex @TeX{}, how to obtain
+
+@c !!! Here is information about obtaining TeX. Update it whenever.
+@c !!! Also consider updating TeX.README on prep.
+@c Updated by RJC on 1 March 1995, conversation with MacKay.
+@c Updated by kb@cs.umb.edu on 29 July 1996.
+@TeX{} is freely redistributable. You can obtain @TeX{} for Unix
+systems via anonymous ftp or on tape or CD-ROM. The core material
+consists of Karl Berry's Web2c @TeX{} distribution.
+
+On-line retrieval instructions are available from either:
+@example
+@url{ftp://ftp.tug.org/tex/unixtex.ftp}
+@url{http://www.tug.org/unixtex.ftp}
+@end example
+
+The Free Software Foundation provides a core distribution on its Source
+Code CD-ROM suitable for printing Texinfo manuals; the University of
+Washington maintains and supports a tape distribution; the @TeX{} Users
+Group co-sponsors a complete CD-ROM @TeX{} distribution.
+
+For the FSF Source Code CD-ROM, please contact:
+
+@iftex
+@display
+@group
+Free Software Foundation, Inc.
+59 Temple Place Suite 330
+Boston, MA w{ } 02111-1307
+USA
+
+Telephone: @w{@t{+}1--617--542--5942}
+Fax: (including Japan) @w{@t{+}1--617--542--2652}
+Free Dial Fax (in Japan):
+@w{ } @w{ } @w{ } 0031--13--2473 (KDD)
+@w{ } @w{ } @w{ } 0066--3382--0158 (IDC)
+Electronic mail: @code{gnu@@prep.ai.mit.edu}
+@end group
+@end display
+@end iftex
+@ifinfo
+@display
+@group
+Free Software Foundation, Inc.
+59 Temple Place Suite 330
+Boston, MA @w{ } 02111-1307
+USA
+
+Telephone: @w{@t{+}1-617-542-5942}
+Fax: (including Japan) @w{@t{+}1-617-542-2652}
+Free Dial Fax (in Japan):
+@w{ } @w{ } @w{ } 0031-13-2473 (KDD)
+@w{ } @w{ } @w{ } 0066-3382-0158 (IDC)
+Electronic mail: @code{gnu@@prep.ai.mit.edu}
+@end group
+@end display
+@end ifinfo
+
+To order a full distribution on CD-ROM, please see:
+@display
+@url{http://www.tug.org/tex-live.html}
+@end display
+
+@noindent
+(The distribution is also available by FTP; see the URL's above.)
+
+To order a full distribution from the University of Washington on either a
+1/4@dmn{in} 4-track QIC-24 cartridge or a 4@dmn{mm} DAT cartridge, send
+$210 to:
+
+@display
+@group
+Pierre A. MacKay
+Denny Hall, Mail Stop DH-10
+University of Washington
+Seattle, WA @w{ } 98195
+USA
+
+Telephone: @t{+}1--206--543--2268
+Electronic mail: @code{mackay@@cs.washington.edu}
+@end group
+@end display
+
+Please make checks payable to the University of Washington.
+Checks must be in U.S.@: dollars, drawn on a U.S.@: bank.
+
+Prepaid orders are the only orders that can now be handled. Overseas
+sites: please add to the base cost, if desired, $20.00 for shipment
+via air parcel post, or $30.00 for shipment via courier.
+
+Please check with the above for current prices and formats.
+
+
+@node New Features, Command and Variable Index, Obtaining TeX, Top
+@appendix Second Edition Features
+
+@tex
+% Widen the space for the first column so three control-character
+% strings fit in the first column. Switched back to default .8in
+% value at end of chapter.
+\global\tableindent=1.0in
+@end tex
+
+The second edition of the Texinfo manual describes more than 20 new
+Texinfo mode commands and more than 50 previously undocumented Texinfo
+@@-commands. This edition is more than twice the length of the first
+edition.@refill
+
+Here is a brief description of the new commands.@refill
+
+@menu
+* New Texinfo Mode Commands:: The updating commands are especially useful.
+* New Commands:: Many newly described @@-commands.
+@end menu
+
+@node New Texinfo Mode Commands, New Commands, New Features, New Features
+@appendixsec New Texinfo Mode Commands
+
+Texinfo mode provides commands and features especially designed for
+working with Texinfo files. More than 20 new commands have been
+added, including commands for automatically creating and updating
+both nodes and menus. This is a tedious task when done by hand.@refill
+
+The keybindings are intended to be somewhat mnemonic.@refill
+
+@subheading Update all nodes and menus
+
+The @code{texinfo-master-menu} command is the primary command:
+
+@table @kbd
+@item C-c C-u m
+@itemx M-x texinfo-master-menu
+Create or update a master menu.
+With @kbd{C-u} as a prefix argument,
+first create or update all nodes
+and regular menus.
+@end table
+
+@subheading Update Pointers
+
+@noindent
+Create or update `Next', `Previous', and `Up' node pointers.@refill
+
+@noindent
+@xref{Updating Nodes and Menus}.
+
+@table @kbd
+@item C-c C-u C-n
+@itemx M-x texinfo-update-node
+Update a node.
+
+@item C-c C-u C-e
+@itemx M-x texinfo-every-node-update
+Update every node in the buffer.
+@end table
+
+@subheading Update Menus
+
+@noindent
+Create or update menus.@refill
+
+@noindent
+@xref{Updating Nodes and Menus}.
+
+@table @kbd
+@item C-c C-u C-m
+@itemx M-x texinfo-make-menu
+Make or update a menu.
+
+@item C-c C-u C-a
+@itemx M-x texinfo-all-menus-update
+Make or update all the menus in a buffer.
+With @kbd{C-u} as a prefix argument,
+first update all the nodes.
+@end table
+
+@subheading Insert Title as Description
+
+@noindent
+Insert a node's chapter or section title in the space for the
+description in a menu entry line; position point so you can edit the
+insert. (This command works somewhat differently than the other
+insertion commands, which insert only a predefined string.)@refill
+
+@noindent
+@xref{Inserting, Inserting Frequently Used Commands}.
+
+@table @kbd
+@item C-c C-c C-d
+Insert title.
+@end table
+
+@subheading Format for Info
+
+@noindent
+Provide keybindings both for the Info formatting commands that are
+written in Emacs Lisp and for @code{makeinfo} that is written in
+C.@refill
+
+@noindent
+@xref{Info Formatting}.
+
+@noindent
+Use the Emacs lisp @code{texinfo-format@dots{}} commands:
+
+@table @kbd
+@item C-c C-e C-r
+Format the region.
+
+@item C-c C-e C-b
+Format the buffer.
+@end table
+
+@noindent
+Use @code{makeinfo}:
+
+@table @kbd
+@item C-c C-m C-r
+Format the region.
+
+@item C-c C-m C-b
+Format the buffer.
+
+@item C-c C-m C-l
+Recenter the @code{makeinfo} output buffer.
+
+@item C-c C-m C-k
+Kill the @code{makeinfo} formatting job.
+@end table
+
+@subheading Typeset and Print
+
+@noindent
+Typeset and print Texinfo documents from within Emacs.@refill
+
+@ifinfo
+@noindent
+@xref{Printing}.
+@end ifinfo
+@iftex
+@noindent
+@xref{Printing, , Formatting and Printing}.
+@end iftex
+
+@table @kbd
+@item C-c C-t C-b
+Run @code{texi2dvi} on the buffer.
+
+@item C-c C-t C-r
+Run @TeX{} on the region.
+
+@item C-c C-t C-i
+Run @code{texindex}.
+
+@item C-c C-t C-p
+Print the @sc{dvi} file.
+
+@item C-c C-t C-q
+Show the print queue.
+
+@item C-c C-t C-d
+Delete a job from the print queue.
+
+@item C-c C-t C-k
+Kill the current @TeX{} formatting job.
+
+@item C-c C-t C-x
+Quit a currently stopped @TeX{} formatting job.
+
+@item C-c C-t C-l
+Recenter the output buffer.
+@end table
+
+@subheading Other Updating Commands
+
+@noindent
+The ``other updating commands'' do not have standard keybindings because
+they are used less frequently.@refill
+
+@noindent
+@xref{Other Updating Commands}.
+
+@table @kbd
+@item M-x texinfo-insert-node-lines
+Insert missing @code{@@node} lines using
+section titles as node names.
+
+@item M-x texinfo-multiple-files-update
+Update a multi-file document.
+With a numeric prefix, such as @kbd{C-u 8},
+update @strong{every} pointer and
+menu in @strong{all} the files and
+then insert a master menu.
+
+@item M-x texinfo-indent-menu-description
+Indent descriptions in menus.
+
+@item M-x texinfo-sequential-node-update
+Insert node pointers in strict sequence.
+@end table
+
+@node New Commands, , New Texinfo Mode Commands, New Features
+@appendixsec New Texinfo @@-Commands
+
+The second edition of the Texinfo manual describes more than 50
+commands that were not described in the first edition. A third or so
+of these commands existed in Texinfo but were not documented in the
+manual; the others are new. Here is a listing, with brief
+descriptions of them:@refill
+
+@subheading Indexing
+
+@noindent
+Create your own index, and merge indices.@refill
+
+@noindent
+@xref{Indices}.
+
+@table @kbd
+@item @@defindex @var{index-name}
+Define a new index and its indexing command.
+See also the @code{@@defcodeindex} command.
+
+@c written verbosely to avoid overfull hbox
+@item @@synindex @var{from-index} @var{into-index}
+Merge the @var{from-index} index into the @var{into-index} index.
+See also the @code{@@syncodeindex} command.
+@end table
+
+@subheading Definitions
+
+@noindent
+Describe functions, variables, macros,
+commands, user options, special forms, and other such artifacts in a
+uniform format.@refill
+
+@noindent
+@xref{Definition Commands}.
+
+@table @kbd
+@item @@deffn @var{category} @var{name} @var{arguments}@dots{}
+Format a description for functions, interactive
+commands, and similar entities.
+
+@item @@defvr, @@defop, @dots{}
+15 other related commands.
+@end table
+
+@subheading Glyphs
+
+@noindent
+Indicate the results of evaluation, expansion,
+printed output, an error message, equivalence of expressions, and the
+location of point.@refill
+
+@noindent
+@xref{Glyphs}.
+
+@table @kbd
+@item @@equiv@{@}
+@itemx @equiv{}
+Equivalence:
+
+@item @@error@{@}
+@itemx @error{}
+Error message
+
+@item @@expansion@{@}
+@itemx @expansion{}
+Macro expansion
+
+@item @@point@{@}
+@itemx @point{}
+Position of point
+
+@item @@print@{@}
+@itemx @print{}
+Printed output
+
+@item @@result@{@}
+@itemx @result{}
+Result of an expression
+@end table
+
+@subheading Page Headings
+
+@noindent
+Customize page headings.
+
+@noindent
+@xref{Headings}.
+
+@table @kbd
+@item @@headings @var{on-off-single-double}
+Headings on or off, single, or double-sided.
+
+@item @@evenfooting [@var{left}] @@| [@var{center}] @@| [@var{right}]
+Footings for even-numbered (left-hand) pages.
+
+@item @@evenheading, @@everyheading, @@oddheading, @dots{}
+Five other related commands.
+
+@item @@thischapter
+Insert name of chapter and chapter number.
+
+@item @@thischaptername, @@thisfile, @@thistitle, @@thispage
+Related commands.
+@end table
+
+@subheading Formatting
+
+@noindent
+Format blocks of text.
+
+@noindent
+@xref{Quotations and Examples}, and@*
+@ref{Lists and Tables, , Making Lists and Tables}.
+
+@table @kbd
+@item @@cartouche
+Draw rounded box surrounding text (not in Info).
+
+@item @@enumerate @var{optional-arg}
+Enumerate a list with letters or numbers.
+
+@item @@exdent @var{line-of-text}
+Remove indentation.
+
+@item @@flushleft
+Left justify.
+
+@item @@flushright
+Right justify.
+
+@item @@format
+Do not narrow nor change font.
+
+@item @@ftable @var{formatting-command}
+@itemx @@vtable @var{formatting-command}
+Two-column table with indexing.
+
+@item @@lisp
+For an example of Lisp code.
+
+@item @@smallexample
+@itemx @@smalllisp
+Like @@table and @@lisp @r{but for} @@smallbook.
+@end table
+
+@subheading Conditionals
+
+@noindent
+Conditionally format text.
+
+@noindent
+@xref{set clear value, , @code{@@set} @code{@@clear} @code{@@value}}.@refill
+
+@table @kbd
+@item @@set @var{flag} [@var{string}]
+Set a flag. Optionally, set value
+of @var{flag} to @var{string}.
+
+@item @@clear @var{flag}
+Clear a flag.
+
+@item @@value@{@var{flag}@}
+Replace with value to which @var{flag} is set.
+
+@item @@ifset @var{flag}
+Format, if @var{flag} is set.
+
+@item @@ifclear @var{flag}
+Ignore, if @var{flag} is set.
+@end table
+
+@subheading @@heading series for Titles
+
+@noindent
+Produce unnumbered headings that do not appear in a table of contents.
+
+@noindent
+@xref{Structuring}.
+
+@table @kbd
+@item @@heading @var{title}
+Unnumbered section-like heading not listed
+in the table of contents of a printed manual.
+
+@item @@chapheading, @@majorheading, @@subheading, @@subsubheading
+Related commands.
+@end table
+
+@need 1000
+@subheading Font commands
+
+@need 1000
+@noindent
+@xref{Smallcaps}, and @*
+@ref{Fonts}.
+
+@table @kbd
+@item @@r@{@var{text}@}
+Print in roman font.
+
+@item @@sc@{@var{text}@}
+Print in @sc{small caps} font.
+@end table
+
+@subheading Miscellaneous
+
+@noindent
+See @ref{title subtitle author, , @code{@@title} @code{@@subtitle} and @code{@@author} Commands},@*
+see @ref{Customized Highlighting},@*
+see @ref{Overfull hboxes},@*
+see @ref{Footnotes},@*
+see @ref{dmn, , Format a Dimension},@*
+see @ref{Raise/lower sections, , @code{@@raisesections} and @code{@@lowersections}},@*
+see @ref{math, , @code{@@math}: Inserting Mathematical Expressions}.@*
+see @ref{minus, , Inserting a Minus Sign},@*
+see @ref{paragraphindent, , Paragraph Indenting},@*
+see @ref{Cross Reference Commands},@*
+see @ref{title subtitle author, , @code{@@title} @code{@@subtitle} and @code{@@author}}, and@*
+see @ref{Custom Headings, , How to Make Your Own Headings}.
+
+@table @kbd
+@item @@author @var{author}
+Typeset author's name.
+
+@ignore
+@item @@definfoenclose @var{new-command}, @var{before}, @var{after},
+Define a highlighting command for Info. (Info only.)
+@end ignore
+
+@item @@finalout
+Produce cleaner printed output.
+
+@item @@footnotestyle @var{end-or-separate}
+Specify footnote style.
+
+@item @@dmn@{@var{dimension}@}
+Format a dimension.
+
+@item @@global@@let@var{new-cmd}=@var{existing-cmd}
+Define a highlighting command for @TeX{}. (@TeX{} only.)
+
+@item @@lowersections
+Reduce hierarchical level of sectioning commands.
+
+@item @@math@{@var{mathematical-expression}@}
+Format a mathematical expression.
+
+@item @@minus@{@}
+Generate a minus sign.
+
+@item @@paragraphindent @var{asis-or-number}
+Specify paragraph indentation.
+
+@item @@raisesections
+Raise hierarchical level of sectioning commands.
+
+@item @@ref@{@var{node-name}, @r{[}@var{entry}@r{]}, @r{[}@var{topic-or-title}@r{]}, @r{[}@var{info-file}@r{]}, @r{[}@var{manual}@r{]}@}
+Make a reference. In the printed manual, the
+reference does not start with the word `see'.
+
+@item @@title @var{title}
+Typeset @var{title} in the alternative
+title page format.
+
+@item @@subtitle @var{subtitle}
+Typeset @var{subtitle} in the alternative
+title page format.
+
+@item @@today@{@}
+Insert the current date.
+@end table
+@tex
+% Switch width of first column of tables back to default value
+\global\tableindent=.8in
+@end tex
+
+
+@node Command and Variable Index, Concept Index, New Features, Top
+@comment node-name, next, previous, up
+@unnumbered Command and Variable Index
+
+This is an alphabetical list of all the @@-commands, assorted Emacs Lisp
+functions, and several variables. To make the list easier to use, the
+commands are listed without their preceding @samp{@@}.@refill
+
+@printindex fn
+
+
+@node Concept Index, , Command and Variable Index, Top
+@unnumbered Concept Index
+
+@printindex cp
+
+
+@summarycontents
+@contents
+@bye
diff --git a/contrib/texinfo/util/Makefile.in b/contrib/texinfo/util/Makefile.in
new file mode 100644
index 0000000..aa3b85a
--- /dev/null
+++ b/contrib/texinfo/util/Makefile.in
@@ -0,0 +1,101 @@
+# Makefile for GNU Texindex and other utilities.
+# $Id: Makefile.in,v 1.5 1996/09/29 20:07:06 karl Exp $
+#
+# Copyright (C) 1990, 91, 92, 96 Free Software Foundation, Inc.
+
+# 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+#### Start of system configuration section. ####
+
+srcdir = @srcdir@
+VPATH = $(srcdir):$(common)
+
+common = $(srcdir)/../libtxi
+
+CC = @CC@
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_DATA = @INSTALL_DATA@
+
+LN = ln
+RM = rm -f
+MKDIR = mkdir
+
+DEFS = @DEFS@
+LIBS = -L../libtxi -ltxi @LIBS@
+LOADLIBES = $(LIBS)
+
+SHELL = /bin/sh
+
+CFLAGS = @CFLAGS@
+LDFLAGS = @LDFLAGS@
+
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+bindir = $(exec_prefix)/bin
+# Prefix for each installed program, normally empty or `g'.
+binprefix =
+# Prefix for each installed man page, normally empty or `g'.
+manprefix =
+mandir = $(prefix)/man/man1
+manext = 1
+infodir = $(prefix)/info
+
+#### End of system configuration section. ####
+
+all: texindex install-info
+sub-all: all
+
+.c.o:
+ $(CC) -c $(CPPFLAGS) $(DEFS) -I. -I$(srcdir) -I$(common) $(CFLAGS) $<
+
+
+install: all
+ $(INSTALL_PROGRAM) texindex $(bindir)/texindex
+ $(INSTALL_PROGRAM) $(srcdir)/texi2dvi $(bindir)/texi2dvi
+ $(INSTALL_PROGRAM) install-info $(bindir)/install-info
+
+uninstall:
+ rm -f $(bindir)/texindex $(bindir)/texi2dvi $(bindir)/install-info
+
+Makefile: Makefile.in ../config.status
+ cd ..; sh config.status
+
+TAGS:
+ etags *.c *.h $(common)/getopt*.c $(common)/getopt.h
+
+clean:
+ rm -f *.o a.out core core.* texindex install-info
+
+mostlyclean: clean
+
+distclean: clean
+ rm -f Makefile config.status
+
+realclean: distclean
+ rm -f TAGS
+
+texindex: texindex.o ../libtxi/libtxi.a
+ $(CC) $(LDFLAGS) -o texindex texindex.o $(LOADLIBES)
+
+texindex.o: texindex.c $(common)/getopt.h
+
+install-info: install-info.o
+ $(CC) $(LDFLAGS) -o install-info install-info.o $(LOADLIBES)
+
+install-info.o: install-info.c $(common)/getopt.h
+
+# Prevent GNU make v3 from overflowing arg limit on SysV.
+.NOEXPORT:
diff --git a/contrib/texinfo/util/deref.c b/contrib/texinfo/util/deref.c
new file mode 100644
index 0000000..c15bc1a
--- /dev/null
+++ b/contrib/texinfo/util/deref.c
@@ -0,0 +1,238 @@
+/*
+ * deref.c
+
+ * compile command: gcc -g -o deref deref.c
+
+ * execute command: deref filename.texi > newfile.texi
+
+ * To: bob@gnu.ai.mit.edu
+ * Subject: another tool
+ * Date: 18 Dec 91 16:03:13 EST (Wed)
+ * From: gatech!skeeve!arnold@eddie.mit.edu (Arnold D. Robbins)
+ *
+ * Here is deref.c. It turns texinfo cross references back into the
+ * one argument form. It has the same limitations as fixref; one xref per
+ * line and can't cross lines. You can use it to find references that do
+ * cross a line boundary this way:
+ *
+ * deref < manual > /dev/null 2>errs
+ *
+ * (This assumes bash or /bin/sh.) The file errs will have list of lines
+ * where deref could not find matching braces.
+ *
+ * A gawk manual processed by deref goes through makeinfo without complaint.
+ * Compile with gcc and you should be set.
+ *
+ * Enjoy,
+ *
+ * Arnold
+ * -----------
+ */
+
+/*
+ * deref.c
+ *
+ * Make all texinfo references into the one argument form.
+ *
+ * Arnold Robbins
+ * arnold@skeeve.atl.ga.us
+ * December, 1991
+ *
+ * Copyright, 1991, Arnold Robbins
+ */
+
+/*
+ * LIMITATIONS:
+ * One texinfo cross reference per line.
+ * Cross references may not cross newlines.
+ * Use of fgets for input (to be fixed).
+ */
+
+#include <stdio.h>
+#include <ctype.h>
+#include <errno.h>
+
+/* for gcc on the 3B1, delete if this gives you grief */
+extern int fclose (FILE * fp);
+extern int fprintf (FILE * fp, const char *str,...);
+
+extern char *strerror (int errno);
+extern char *strchr (char *cp, int ch);
+extern int strncmp (const char *s1, const char *s2, int count);
+
+extern int errno;
+
+void process (FILE * fp);
+void repair (char *line, char *ref, int toffset);
+
+int Errs = 0;
+char *Name = "stdin";
+int Line = 0;
+char *Me;
+
+/* main --- handle arguments, global vars for errors */
+
+int
+main (int argc, char **argv)
+{
+ FILE *fp;
+
+ Me = argv[0];
+
+ if (argc == 1)
+ process (stdin);
+ else
+ for (argc--, argv++; *argv != NULL; argc--, argv++)
+ {
+ if (argv[0][0] == '-' && argv[0][1] == '\0')
+ {
+ Name = "stdin";
+ Line = 0;
+ process (stdin);
+ }
+ else if ((fp = fopen (*argv, "r")) != NULL)
+ {
+ Name = *argv;
+ Line = 0;
+ process (fp);
+ fclose (fp);
+ }
+ else
+ {
+ fprintf (stderr, "%s: can not open: %s\n",
+ *argv, strerror (errno));
+ Errs++;
+ }
+ }
+ return Errs != 0;
+}
+
+/* isref --- decide if we've seen a texinfo cross reference */
+
+int
+isref (char *cp)
+{
+ if (strncmp (cp, "@ref{", 5) == 0)
+ return 5;
+ if (strncmp (cp, "@xref{", 6) == 0)
+ return 6;
+ if (strncmp (cp, "@pxref{", 7) == 0)
+ return 7;
+ return 0;
+}
+
+/* process --- read files, look for references, fix them up */
+
+void
+process (FILE * fp)
+{
+ char buf[BUFSIZ];
+ char *cp;
+ int count;
+
+ while (fgets (buf, sizeof buf, fp) != NULL)
+ {
+ Line++;
+ cp = strchr (buf, '@');
+ if (cp == NULL)
+ {
+ fputs (buf, stdout);
+ continue;
+ }
+ do
+ {
+ count = isref (cp);
+ if (count == 0)
+ {
+ cp++;
+ cp = strchr (cp, '@');
+ if (cp == NULL)
+ {
+ fputs (buf, stdout);
+ goto next;
+ }
+ continue;
+ }
+ /* got one */
+ repair (buf, cp, count);
+ break;
+ }
+ while (cp != NULL);
+ next:;
+ }
+}
+
+/* repair --- turn all texinfo cross references into the one argument form */
+
+void
+repair (char *line, char *ref, int toffset)
+{
+ int braces = 1; /* have seen first left brace */
+ char *cp;
+
+ ref += toffset;
+
+ /* output line up to and including left brace in reference */
+ for (cp = line; cp <= ref; cp++)
+ putchar (*cp);
+
+ /* output node name */
+ for (; *cp && *cp != '}' && *cp != ',' && *cp != '\n'; cp++)
+ putchar (*cp);
+
+ if (*cp != '}')
+ { /* could have been one arg xref */
+ /* skip to matching right brace */
+ for (; braces > 0; cp++)
+ {
+ switch (*cp)
+ {
+ case '@':
+ cp++; /* blindly skip next character */
+ break;
+ case '{':
+ braces++;
+ break;
+ case '}':
+ braces--;
+ break;
+ case '\n':
+ case '\0':
+ Errs++;
+ fprintf (stderr,
+ "%s: %s: %d: mismatched braces\n",
+ Me, Name, Line);
+ goto out;
+ default:
+ break;
+ }
+ }
+ out:
+ ;
+ }
+
+ putchar ('}');
+ if (*cp == '}')
+ cp++;
+
+ /* now the rest of the line */
+ for (; *cp; cp++)
+ putchar (*cp);
+ return;
+}
+
+/* strerror --- return error string, delete if in your library */
+
+char *
+strerror (int errno)
+{
+ static char buf[100];
+ extern int sys_nerr;
+ extern char *sys_errlist[];
+
+ if (errno < sys_nerr && errno >= 0)
+ return sys_errlist[errno];
+
+ sprintf (buf, "unknown error %d", errno);
+ return buf;
+}
diff --git a/contrib/texinfo/util/fixfonts b/contrib/texinfo/util/fixfonts
new file mode 100755
index 0000000..ee2ea71
--- /dev/null
+++ b/contrib/texinfo/util/fixfonts
@@ -0,0 +1,84 @@
+#!/bin/sh
+# Make links named `lcircle10' for all TFM and GF/PK files, if no
+# lcircle10 files already exist.
+
+# Don't override definition of prefix and/or libdir if they are
+# already defined in the environment.
+if test "z${prefix}" = "z" ; then
+ prefix=/usr/local
+else
+ # prefix may contain references to other variables, thanks to make.
+ eval prefix=\""${prefix}"\"
+fi
+
+if test "z${libdir}" = "z" ; then
+ libdir="${prefix}/lib/tex"
+else
+ # libdir may contain references to other variables, thanks to make.
+ eval libdir=\""${libdir}"\"
+fi
+
+texlibdir="${libdir}"
+texfontdir="${texlibdir}/fonts"
+
+# Directories for the different font formats, in case they're not all
+# stored in one place.
+textfmdir="${textfmdir-${texfontdir}}"
+texpkdir="${texpkdir-${texfontdir}}"
+texgfdir="${texgfdir-${texfontdir}}"
+
+test "z${TMPDIR}" = "z" && TMPDIR="/tmp"
+
+tempfile="${TMPDIR}/circ$$"
+tempfile2="${TMPDIR}/circ2$$"
+
+# EXIT SIGHUP SIGINT SIGQUIT SIGTERM
+#trap 'rm -f "${tempfile}" "${tempfile2}"' 0 1 2 3 15
+
+# Find all the fonts with names that include `circle'.
+(cd "${texfontdir}"; find . -name '*circle*' -print > "${tempfile}")
+
+# If they have lcircle10.tfm, assume everything is there, and quit.
+if grep 'lcircle10\.tfm' "${tempfile}" > /dev/null 2>&1 ; then
+ echo "Found lcircle10.tfm."
+ exit 0
+fi
+
+# No TFM file for lcircle. Make a link to circle10.tfm if it exists,
+# and then make a link to the bitmap files.
+grep 'circle10\.tfm' "${tempfile}" > "${tempfile2}" \
+ || {
+ echo "I can't find any circle fonts in ${texfontdir}.
+If it isn't installed somewhere else, you need to get the Metafont sources
+from somewhere, e.g., labrea.stanford.edu:pub/tex/latex/circle10.mf, and
+run Metafont on them."
+ exit 1
+ }
+
+# We have circle10.tfm. (If we have it more than once, take the first
+# one.) Make the link.
+tempfile2_line1="`sed -ne '1p;q' \"${tempfile2}\"`"
+ln "${tempfile2_line1}" "${textfmdir}/lcircle10.tfm"
+echo "Linked to ${tempfile2_line1}."
+
+# Now make a link for the PK files, if any.
+(cd "${texpkdir}"
+ for f in `grep 'circle10.*pk' "${tempfile}"` ; do
+ set - `echo "$f" \
+ | sed -ne '/\//!s/^/.\//;s/\(.*\)\/\([^\/][^\/]*\)$/\1 \2/;p'`
+ ln "$f" "${1}/l${2}"
+ echo "Linked to $f."
+ done
+)
+
+# And finally for the GF files.
+(cd "${texgfdir}"
+ for f in `grep 'circle10.*gf' "${tempfile}"` ; do
+ set - `echo "$f" \
+ | sed -ne '/\//!s/^/.\//;s/\(.*\)\/\([^\/][^\/]*\)$/\1 \2/;p'`
+ ln "$f" "${1}/l${2}"
+ echo "Linked to $f."
+ done
+)
+
+# eof
diff --git a/contrib/texinfo/util/gen-dir-node b/contrib/texinfo/util/gen-dir-node
new file mode 100755
index 0000000..8f13088
--- /dev/null
+++ b/contrib/texinfo/util/gen-dir-node
@@ -0,0 +1,176 @@
+#!/bin/sh
+# $Id: gen-dir-node,v 1.2 1996/10/03 18:49:48 karl Exp $
+# Generate the top-level Info node, given a directory of Info files
+# and (optionally) a skeleton file. The output will be suitable for a
+# top-level dir file. The skeleton file contains info topic names in the
+# order they should appear in the output. There are three special
+# lines that alter the behavior: a line consisting of just "--" causes
+# the next line to be echoed verbatim to the output. A line
+# containing just "%%" causes all the remaining filenames (wildcards
+# allowed) in the rest of the file to be ignored. A line containing
+# just "!!" exits the script when reached (unless preceded by a line
+# containing just "--"). Once the script reaches the end of the
+# skeleton file, it goes through the remaining files in the directory
+# in order, putting their entries at the end. The script will use the
+# ENTRY information in each info file if it exists. Otherwise it will
+# make a minimal entry.
+
+# sent by Jeffrey Osier <jeffrey@cygnus.com>, who thinks it came from
+# zoo@winternet.com (david d `zoo' zuhn)
+
+# modified 7 April 1995 by Joe Harrington <jh@tecate.gsfc.nasa.gov> to
+# take special flags
+
+INFODIR=$1
+if [ $# = 2 ] ; then
+ SKELETON=$2
+else
+ SKELETON=/dev/null
+fi
+
+skip=
+
+if [ $# -gt 2 ] ; then
+ echo usage: $0 info-directory [ skeleton-file ] 1>&2
+ exit 1
+else
+ true
+fi
+
+if [ ! -d ${INFODIR} ] ; then
+ echo "$0: first argument must specify a directory"
+ exit 1
+fi
+
+### output the dir header
+echo "-*- Text -*-"
+echo "This file was generated automatically by $0."
+echo "This version was generated on `date`"
+echo "by `whoami`@`hostname` for `(cd ${INFODIR}; pwd)`"
+
+cat << moobler
+
+This is the file .../info/dir, which contains the topmost node of the
+Info hierarchy. The first time you invoke Info you start off
+looking at that node, which is (dir)Top.
+
+File: dir Node: Top This is the top of the INFO tree
+ This (the Directory node) gives a menu of major topics.
+ Typing "d" returns here, "q" exits, "?" lists all INFO commands, "h"
+ gives a primer for first-timers, "mTexinfo<Return>" visits Texinfo topic,
+ etc.
+ Or click mouse button 2 on a menu item or cross reference to select it.
+ --- PLEASE ADD DOCUMENTATION TO THIS TREE. (See INFO topic first.) ---
+
+* Menu: The list of major topics begins on the next line.
+
+moobler
+
+### go through the list of files in the skeleton. If an info file
+### exists, grab the ENTRY information from it. If an entry exists
+### use it, otherwise create a minimal dir entry.
+###
+### Then remove that file from the list of existing files. If any
+### additional files remain (ones that don't have a skeleton entry),
+### then generate entries for those in the same way, putting the info for
+### those at the end....
+
+infofiles=`(cd ${INFODIR}; ls | egrep -v '\-|^dir$|^dir\.info$|^dir\.orig$')`
+
+# echoing gets clobbered by backquotes; we do it the hard way...
+lines=`wc $SKELETON | awk '{print $1}'`
+line=1
+while [ $lines -ge $line ] ; do
+ # Read one line from the file. This is so that we can echo lines with
+ # whitespace and quoted characters in them.
+ fileline=`awk NR==$line $SKELETON`
+
+ # flag fancy features
+ if [ ! -z "$echoline" ] ; then # echo line
+ echo "$fileline"
+ fileline=
+ echoline=
+ elif [ "${fileline}" = "--" ] ; then # should we echo the next line?
+ echoline=1
+ elif [ "${fileline}" = "%%" ] ; then # eliminate remaining files from dir?
+ skip=1
+ elif [ "${fileline}" = "!!" ] ; then # quit now
+ exit 0
+ fi
+
+ # handle files if they exist
+ for file in $fileline"" ; do # expand wildcards ("" handles blank lines)
+
+ fname=
+
+ if [ -z "$echoline" -a ! -z "$file" ] ; then
+
+ # Find the file to operate upon. Check both possible names.
+ infoname=`echo $file | sed 's/\.info$//'`
+ noext=
+ ext=
+ if [ -f ${INFODIR}/$infoname ] ; then
+ noext=$infoname
+ fi
+ if [ -f ${INFODIR}/${infoname}.info ] ; then
+ ext=${infoname}.info
+ fi
+
+ # If it exists with both names take what was said in the file.
+ if [ ! -z "$ext" -a ! -z "$noext" ]; then
+ fname=$file
+ warn="### Warning: $ext and $noext both exist! Using ${file}. ###"
+ elif [ ! \( -z "$ext" -a -z "$noext" \) ]; then
+ # just take the name if it exists only once
+ fname=${noext}${ext}
+ fi
+
+ # if we found something and aren't skipping, do the entry
+ if [ ! -z "$fname" ] ; then
+ if [ -z "$skip" ] ; then
+
+ if [ ! -z "$warn" ] ; then # issue any warning
+ echo $warn
+ warn=
+ fi
+
+ entry=`sed -e '1,/START-INFO-DIR-ENTRY/d' \
+ -e '/END-INFO-DIR-ENTRY/,$d' ${INFODIR}/$fname`
+ if [ ! -z "${entry}" ] ; then
+ echo "${entry}"
+ else
+ echo "* ${infoname}: (${fname})."
+ fi
+ fi
+
+ # remove the name from the directory listing
+ infofiles=`echo ${infofiles} | sed -e "s/ ${fname} / /" \
+ -e "s/^${fname} //" \
+ -e "s/ ${fname}$//"`
+
+ fi
+
+ fi
+
+ done
+
+ line=`expr $line + 1`
+done
+
+if [ -z "${infofiles}" ] ; then
+ exit 0
+else
+ echo
+fi
+
+for file in ${infofiles}; do
+ infoname=`echo $file | sed 's/\.info$//'`
+ entry=`sed -e '1,/START-INFO-DIR-ENTRY/d' \
+ -e '/END-INFO-DIR-ENTRY/,$d' ${INFODIR}/${file}`
+
+ if [ ! -z "${entry}" ] ; then
+ echo "${entry}"
+ else
+ echo "* ${infoname}: (${file})."
+ fi
+done
diff --git a/contrib/texinfo/util/install-info.c b/contrib/texinfo/util/install-info.c
new file mode 100644
index 0000000..53fa4aa
--- /dev/null
+++ b/contrib/texinfo/util/install-info.c
@@ -0,0 +1,1111 @@
+/* install-info -- create Info directory entry(ies) for an Info file.
+ Copyright (C) 1996 Free Software Foundation, Inc.
+
+$Id: install-info.c,v 1.12 1996/10/03 23:13:36 karl Exp $
+
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#define INSTALL_INFO_VERSION_STRING "GNU install-info (Texinfo 3.9) 1.2"
+
+#include <stdio.h>
+#include <errno.h>
+#include <getopt.h>
+#include <sys/types.h>
+
+/* Get O_RDONLY. */
+#ifdef HAVE_SYS_FCNTL_H
+#include <sys/fcntl.h>
+#else
+#include <fcntl.h>
+#endif /* !HAVE_SYS_FCNTL_H */
+#ifdef HAVE_SYS_FILE_H
+#include <sys/file.h>
+#endif
+
+/* Name this program was invoked with. */
+char *progname;
+
+char *readfile ();
+struct line_data *findlines ();
+char *my_strerror ();
+void fatal ();
+void insert_entry_here ();
+int compare_section_names ();
+
+struct spec_entry;
+
+/* Data structures. */
+
+/* Record info about a single line from a file
+ as read into core. */
+
+struct line_data
+{
+ /* The start of the line. */
+ char *start;
+ /* The number of characters in the line,
+ excluding the terminating newline. */
+ int size;
+ /* Vector containing pointers to the entries to add before this line.
+ The vector is null-terminated. */
+ struct spec_entry **add_entries_before;
+ /* 1 means output any needed new sections before this line. */
+ int add_sections_before;
+ /* 1 means don't output this line. */
+ int delete;
+};
+
+/* This is used for a list of the specified menu section names
+ in which entries should be added. */
+
+struct spec_section
+{
+ struct spec_section *next;
+ char *name;
+ /* 1 means we have not yet found an existing section with this name
+ in the dir file--so we will need to add a new section. */
+ int missing;
+};
+
+/* This is used for a list of the entries specified to be added. */
+
+struct spec_entry
+{
+ struct spec_entry *next;
+ char *text;
+};
+
+/* This is used for a list of nodes found by parsing the dir file. */
+
+struct node
+{
+ struct node *next;
+ /* The node name. */
+ char *name;
+ /* The line number of the line where the node starts.
+ This is the line that contains control-underscore. */
+ int start_line;
+ /* The line number of the line where the node ends,
+ which is the end of the file or where the next line starts. */
+ int end_line;
+ /* Start of first line in this node's menu
+ (the line after the * Menu: line). */
+ char *menu_start;
+ /* The start of the chain of sections in this node's menu. */
+ struct menu_section *sections;
+ /* The last menu section in the chain. */
+ struct menu_section *last_section;
+};
+
+/* This is used for a list of sections found in a node's menu.
+ Each struct node has such a list in the sections field. */
+
+struct menu_section
+{
+ struct menu_section *next;
+ char *name;
+ /* Line number of start of section. */
+ int start_line;
+ /* Line number of end of section. */
+ int end_line;
+};
+
+/* Memory allocation and string operations. */
+
+/* Like malloc but get fatal error if memory is exhausted. */
+
+void *
+xmalloc (size)
+ unsigned int size;
+{
+ extern void *malloc ();
+ void *result = malloc (size);
+ if (result == NULL)
+ fatal ("virtual memory exhausted", 0);
+ return result;
+}
+
+/* Like malloc but get fatal error if memory is exhausted. */
+
+void *
+xrealloc (obj, size)
+ void *obj;
+ unsigned int size;
+{
+ extern void *realloc ();
+ void *result = realloc (obj, size);
+ if (result == NULL)
+ fatal ("virtual memory exhausted", 0);
+ return result;
+}
+
+/* Return a newly-allocated string whose contents concatenate those of s1, s2, s3. */
+
+char *
+concat (s1, s2, s3)
+ char *s1, *s2, *s3;
+{
+ int len1 = strlen (s1), len2 = strlen (s2), len3 = strlen (s3);
+ char *result = (char *) xmalloc (len1 + len2 + len3 + 1);
+
+ strcpy (result, s1);
+ strcpy (result + len1, s2);
+ strcpy (result + len1 + len2, s3);
+ *(result + len1 + len2 + len3) = 0;
+
+ return result;
+}
+
+/* Return a string containing SIZE characters
+ copied from starting at STRING. */
+
+char *
+copy_string (string, size)
+ char *string;
+ int size;
+{
+ int i;
+ char *copy = (char *) xmalloc (size + 1);
+ for (i = 0; i < size; i++)
+ copy[i] = string[i];
+ copy[size] = 0;
+ return copy;
+}
+
+/* Error message functions. */
+
+/* Print error message. `s1' is printf control string, `s2' is arg for it. */
+
+/* VARARGS1 */
+void
+error (s1, s2, s3)
+ char *s1, *s2, *s3;
+{
+ fprintf (stderr, "%s: ", progname);
+ fprintf (stderr, s1, s2, s3);
+ fprintf (stderr, "\n");
+}
+
+/* VARARGS1 */
+void
+warning (s1, s2, s3)
+ char *s1, *s2, *s3;
+{
+ fprintf (stderr, "%s: Warning: ", progname);
+ fprintf (stderr, s1, s2, s3);
+ fprintf (stderr, "\n");
+}
+
+/* Print error message and exit. */
+
+void
+fatal (s1, s2, s3)
+ char *s1, *s2, *s3;
+{
+ error (s1, s2, s3);
+ exit (1);
+}
+
+/* Print fatal error message based on errno, with file name NAME. */
+
+void
+pfatal_with_name (name)
+ char *name;
+{
+ char *s = concat ("", my_strerror (errno), " for %s");
+ fatal (s, name);
+}
+
+/* Given the full text of a menu entry, null terminated,
+ return just the menu item name (copied). */
+
+char *
+extract_menu_item_name (item_text)
+ char *item_text;
+{
+ char *p;
+
+ if (*item_text == '*')
+ item_text++;
+ while (*item_text == ' ')
+ item_text++;
+
+ p = item_text;
+ while (*p && *p != ':') p++;
+ return copy_string (item_text, p - item_text);
+}
+
+/* Given the full text of a menu entry, terminated by null or newline,
+ return just the menu item file (copied). */
+
+char *
+extract_menu_file_name (item_text)
+ char *item_text;
+{
+ char *p = item_text;
+
+ /* If we have text that looks like * ITEM: (FILE)NODE...,
+ extract just FILE. Otherwise return "(none)". */
+
+ if (*p == '*')
+ p++;
+ while (*p == ' ')
+ p++;
+
+ /* Skip to and past the colon. */
+ while (*p && *p != '\n' && *p != ':') p++;
+ if (*p == ':') p++;
+
+ /* Skip past the open-paren. */
+ while (1)
+ {
+ if (*p == '(')
+ break;
+ else if (*p == ' ' || *p == '\t')
+ p++;
+ else
+ return "(none)";
+ }
+ p++;
+
+ item_text = p;
+
+ /* File name ends just before the close-paren. */
+ while (*p && *p != '\n' && *p != ')') p++;
+ if (*p != ')')
+ return "(none)";
+
+ return copy_string (item_text, p - item_text);
+}
+
+void
+suggest_asking_for_help ()
+{
+ fprintf (stderr, "\tTry `%s --help' for a complete list of options.\n",
+ progname);
+ exit (1);
+}
+
+void
+print_help ()
+{
+ printf ("%s [OPTION]... [INFO-FILE [DIR-FILE]]\n\
+ Install INFO-FILE in the Info directory file DIR-FILE.\n\
+\n\
+Options:\n\
+--delete Delete existing entries in INFO-FILE;\n\
+ don't insert any new entries.\n\
+--dir-file=NAME Specify file name of Info directory file.\n\
+ This is equivalent to using the DIR-FILE argument.\n\
+--entry=TEXT Insert TEXT as an Info directory entry.\n\
+ TEXT should have the form of an Info menu item line\n\
+ plus zero or more extra lines starting with whitespace.\n\
+ If you specify more than one entry, they are all added.\n\
+ If you don't specify any entries, they are determined\n\
+ from information in the Info file itself.\n\
+--help Display this help and exit.\n\
+--info-file=FILE Specify Info file to install in the directory.\n\
+ This is equivalent to using the INFO-FILE argument.\n\
+--info-dir=DIR Same as --dir-file=DIR/dir.\n\
+--item=TEXT Same as --entry TEXT.\n\
+ An Info directory entry is actually a menu item.\n\
+--quiet Suppress warnings.\n\
+--remove Same as --delete.\n\
+--section=SEC Put this file's entries in section SEC of the directory.\n\
+ If you specify more than one section, all the entries\n\
+ are added in each of the sections.\n\
+ If you don't specify any sections, they are determined\n\
+ from information in the Info file itself.\n\
+--version Display version information and exit.\n\
+\n\
+Email bug reports to bug-texinfo@prep.ai.mit.edu.\n\
+", progname);
+}
+
+/* Convert an errno value into a string describing the error.
+ We define this function here rather than using strerror
+ because not all systems have strerror. */
+
+char *
+my_strerror (errnum)
+ int errnum;
+{
+ extern char *sys_errlist[];
+ extern int sys_nerr;
+
+ if (errnum >= 0 && errnum < sys_nerr)
+ return sys_errlist[errnum];
+ return (char *) "Unknown error";
+}
+
+/* This table defines all the long-named options, says whether they
+ use an argument, and maps them into equivalent single-letter options. */
+
+struct option longopts[] =
+{
+ { "delete", no_argument, NULL, 'r' },
+ { "dir-file", required_argument, NULL, 'd' },
+ { "entry", required_argument, NULL, 'e' },
+ { "help", no_argument, NULL, 'h' },
+ { "info-dir", required_argument, NULL, 'D' },
+ { "info-file", required_argument, NULL, 'i' },
+ { "item", required_argument, NULL, 'e' },
+ { "quiet", no_argument, NULL, 'q' },
+ { "remove", no_argument, NULL, 'r' },
+ { "section", required_argument, NULL, 's' },
+ { "version", no_argument, NULL, 'V' },
+ { 0 }
+};
+
+main (argc, argv)
+ int argc;
+ char **argv;
+{
+ char *infile = 0, *dirfile = 0;
+ char *infile_sans_info;
+ unsigned infilelen_sans_info;
+ FILE *output;
+
+ /* Record the text of the Info file, as a sequence of characters
+ and as a sequence of lines. */
+ char *input_data;
+ int input_size;
+ struct line_data *input_lines;
+ int input_nlines;
+
+ /* Record here the specified section names and directory entries. */
+ struct spec_section *input_sections = NULL;
+ struct spec_entry *entries_to_add = NULL;
+ int n_entries_to_add = 0;
+
+ /* Record the old text of the dir file, as plain characters,
+ as lines, and as nodes. */
+ char *dir_data;
+ int dir_size;
+ int dir_nlines;
+ struct line_data *dir_lines;
+ struct node *dir_nodes;
+
+ /* Nonzero means --delete was specified (just delete existing entries). */
+ int delete_flag = 0;
+ int something_deleted = 0;
+ /* Nonzero means -q was specified. */
+ int quiet_flag = 0;
+
+ int node_header_flag;
+ int prefix_length;
+ int i;
+
+ progname = argv[0];
+
+ while (1)
+ {
+ int opt = getopt_long (argc, argv, "i:d:e:s:hHr", longopts, 0);
+
+ if (opt == EOF)
+ break;
+
+ switch (opt)
+ {
+ case 0:
+ /* If getopt returns 0, then it has already processed a
+ long-named option. We should do nothing. */
+ break;
+
+ case 1:
+ abort ();
+
+ case 'd':
+ if (dirfile)
+ {
+ fprintf (stderr, "%s: Specify the Info directory only once.\n",
+ progname);
+ suggest_asking_for_help ();
+ }
+ dirfile = optarg;
+ break;
+
+ case 'D':
+ if (dirfile)
+ {
+ fprintf (stderr, "%s: Specify the Info directory only once.\n",
+ progname);
+ suggest_asking_for_help ();
+ }
+ dirfile = concat (optarg, "", "/dir");
+ break;
+
+ case 'e':
+ {
+ struct spec_entry *next
+ = (struct spec_entry *) xmalloc (sizeof (struct spec_entry));
+ if (! (*optarg != 0 && optarg[strlen (optarg) - 1] == '\n'))
+ optarg = concat (optarg, "\n", "");
+ next->text = optarg;
+ next->next = entries_to_add;
+ entries_to_add = next;
+ n_entries_to_add++;
+ }
+ break;
+
+ case 'h':
+ case 'H':
+ print_help ();
+ exit (0);
+
+ case 'i':
+ if (infile)
+ {
+ fprintf (stderr, "%s: Specify the Info file only once.\n",
+ progname);
+ suggest_asking_for_help ();
+ }
+ infile = optarg;
+ break;
+
+ case 'q':
+ quiet_flag = 1;
+ break;
+
+ case 'r':
+ delete_flag = 1;
+ break;
+
+ case 's':
+ {
+ struct spec_section *next
+ = (struct spec_section *) xmalloc (sizeof (struct spec_section));
+ next->name = optarg;
+ next->next = input_sections;
+ next->missing = 1;
+ input_sections = next;
+ }
+ break;
+
+ case 'V':
+ puts (INSTALL_INFO_VERSION_STRING);
+puts ("Copyright (C) 1996 Free Software Foundation, Inc.\n\
+There is NO warranty. You may redistribute this software\n\
+under the terms of the GNU General Public License.\n\
+For more information about these matters, see the files named COPYING.");
+ exit (0);
+
+ default:
+ suggest_asking_for_help ();
+ }
+ }
+
+ /* Interpret the non-option arguments as file names. */
+ for (; optind < argc; ++optind)
+ {
+ if (infile == 0)
+ infile = argv[optind];
+ else if (dirfile == 0)
+ dirfile = argv[optind];
+ else
+ error ("excess command line argument `%s'", argv[optind]);
+ }
+
+ if (!infile)
+ fatal ("No input file specified");
+ if (!dirfile)
+ fatal ("No dir file specified");
+
+ /* Read the Info file and parse it into lines. */
+
+ input_data = readfile (infile, &input_size);
+ input_lines = findlines (input_data, input_size, &input_nlines);
+
+ /* Parse the input file to find the section names it specifies. */
+
+ if (input_sections == 0)
+ {
+ prefix_length = strlen ("INFO-DIR-SECTION ");
+ for (i = 0; i < input_nlines; i++)
+ {
+ if (!strncmp ("INFO-DIR-SECTION ", input_lines[i].start,
+ prefix_length))
+ {
+ struct spec_section *next
+ = (struct spec_section *) xmalloc (sizeof (struct spec_section));
+ next->name = copy_string (input_lines[i].start + prefix_length,
+ input_lines[i].size - prefix_length);
+ next->next = input_sections;
+ next->missing = 1;
+ input_sections = next;
+ }
+ }
+ }
+
+ /* Default to section "Miscellaneous" if no sections specified. */
+ if (input_sections == 0)
+ {
+ input_sections
+ = (struct spec_section *) xmalloc (sizeof (struct spec_section));
+ input_sections->name = "Miscellaneous";
+ input_sections->next = 0;
+ input_sections->missing = 1;
+ }
+
+ /* Now find the directory entries specified in the file
+ and put them on entries_to_add. But not if entries
+ were specified explicitly with command options. */
+
+ if (entries_to_add == 0)
+ {
+ char *start_of_this_entry = 0;
+ for (i = 0; i < input_nlines; i++)
+ {
+ if (!strncmp ("START-INFO-DIR-ENTRY", input_lines[i].start,
+ input_lines[i].size)
+ && sizeof ("START-INFO-DIR-ENTRY") - 1 == input_lines[i].size)
+ {
+ if (start_of_this_entry != 0)
+ fatal ("START-INFO-DIR-ENTRY without matching END-INFO-DIR-ENTRY");
+ start_of_this_entry = input_lines[i + 1].start;
+ }
+ if (!strncmp ("END-INFO-DIR-ENTRY", input_lines[i].start,
+ input_lines[i].size)
+ && sizeof ("END-INFO-DIR-ENTRY") - 1 == input_lines[i].size)
+ {
+ if (start_of_this_entry != 0)
+ {
+ struct spec_entry *next
+ = (struct spec_entry *) xmalloc (sizeof (struct spec_entry));
+ next->text = copy_string (start_of_this_entry,
+ input_lines[i].start - start_of_this_entry);
+ next->next = entries_to_add;
+ entries_to_add = next;
+ n_entries_to_add++;
+ start_of_this_entry = 0;
+ }
+ else
+ fatal ("END-INFO-DIR-ENTRY without matching START-INFO-DIR-ENTRY");
+ }
+ }
+ if (start_of_this_entry != 0)
+ fatal ("START-INFO-DIR-ENTRY without matching END-INFO-DIR-ENTRY");
+ }
+
+ if (!delete_flag)
+ if (entries_to_add == 0)
+ fatal ("no info dir entry in `%s'", infile);
+
+ /* Now read in the Info dir file. */
+ dir_data = readfile (dirfile, &dir_size);
+ dir_lines = findlines (dir_data, dir_size, &dir_nlines);
+
+ /* We will be comparing the entries in the dir file against the
+ current filename, so need to strip off any directory prefix and any
+ .info suffix. */
+ {
+ unsigned basename_len;
+ extern char *strrchr ();
+ char *infile_basename = strrchr (infile, '/');
+ if (infile_basename)
+ infile_basename++;
+ else
+ infile_basename = infile;
+
+ basename_len = strlen (infile_basename);
+ infile_sans_info
+ = (strlen (infile_basename) > 5
+ && strcmp (infile_basename + basename_len - 5, ".info") == 0)
+ ? copy_string (infile_basename, basename_len - 5)
+ : infile_basename;
+
+ infilelen_sans_info = strlen (infile_sans_info);
+ }
+
+ /* Parse the dir file. Find all the nodes, and their menus,
+ and the sections of their menus. */
+
+ dir_nodes = 0;
+ node_header_flag = 0;
+ for (i = 0; i < dir_nlines; i++)
+ {
+ /* Parse node header lines. */
+ if (node_header_flag)
+ {
+ int j, end;
+ for (j = 0; j < dir_lines[i].size; j++)
+ /* Find the node name and store it in the `struct node'. */
+ if (!strncmp ("Node:", dir_lines[i].start + j, 5))
+ {
+ char *line = dir_lines[i].start;
+ /* Find the start of the node name. */
+ j += 5;
+ while (line[j] == ' ' || line[j] == '\t')
+ j++;
+ /* Find the end of the node name. */
+ end = j;
+ while (line[end] != 0 && line[end] != ',' && line[end] != '\n'
+ && line[end] != '\t')
+ end++;
+ dir_nodes->name = copy_string (line + j, end - j);
+ }
+ node_header_flag = 0;
+ }
+
+ /* Notice the start of a node. */
+ if (*dir_lines[i].start == 037)
+ {
+ struct node *next
+ = (struct node *) xmalloc (sizeof (struct node));
+ next->next = dir_nodes;
+ next->name = NULL;
+ next->start_line = i;
+ next->end_line = 0;
+ next->menu_start = NULL;
+ next->sections = NULL;
+ next->last_section = NULL;
+
+ if (dir_nodes != 0)
+ dir_nodes->end_line = i;
+ /* Fill in the end of the last menu section
+ of the previous node. */
+ if (dir_nodes != 0 && dir_nodes->last_section != 0)
+ dir_nodes->last_section->end_line = i;
+
+ dir_nodes = next;
+
+ /* The following line is the header of this node;
+ parse it. */
+ node_header_flag = 1;
+ }
+
+ /* Notice the lines that start menus. */
+ if (dir_nodes != 0
+ && !strncmp ("* Menu:", dir_lines[i].start, 7))
+ dir_nodes->menu_start = dir_lines[i + 1].start;
+
+ /* Notice sections in menus. */
+ if (dir_nodes != 0
+ && dir_nodes->menu_start != 0
+ && *dir_lines[i].start != '\n'
+ && *dir_lines[i].start != '*'
+ && *dir_lines[i].start != ' '
+ && *dir_lines[i].start != '\t')
+ {
+ /* Add this menu section to the node's list.
+ This list grows in forward order. */
+ struct menu_section *next
+ = (struct menu_section *) xmalloc (sizeof (struct menu_section));
+ next->start_line = i + 1;
+ next->next = 0;
+ next->end_line = 0;
+ next->name = copy_string (dir_lines[i].start, dir_lines[i].size);
+ if (dir_nodes->sections)
+ {
+ dir_nodes->last_section->next = next;
+ dir_nodes->last_section->end_line = i;
+ }
+ else
+ dir_nodes->sections = next;
+ dir_nodes->last_section = next;
+ }
+
+ /* Check for an existing entry that should be deleted.
+ Delete all entries which specify this file name. */
+ if (*dir_lines[i].start == '*')
+ {
+ char *p = dir_lines[i].start;
+
+ while (*p != 0 && *p != ':')
+ p++;
+ p++;
+ while (*p == ' ') p++;
+ if (*p == '(')
+ {
+ p++;
+ if ((dir_lines[i].size
+ > (p - dir_lines[i].start + infilelen_sans_info))
+ && !strncmp (p, infile_sans_info, infilelen_sans_info)
+ && p[infilelen_sans_info] == ')')
+ dir_lines[i].delete = 1;
+ }
+ }
+ /* Treat lines that start with whitespace
+ as continuations; if we are deleting an entry,
+ delete all its continuations as well. */
+ else if (i > 0
+ && (*dir_lines[i].start == ' '
+ || *dir_lines[i].start == '\t'))
+ {
+ dir_lines[i].delete = dir_lines[i - 1].delete;
+ something_deleted = 1;
+ }
+ }
+
+ /* Finish the info about the end of the last node. */
+ if (dir_nodes != 0)
+ {
+ dir_nodes->end_line = dir_nlines;
+ if (dir_nodes->last_section != 0)
+ dir_nodes->last_section->end_line = dir_nlines;
+ }
+
+ /* Decide where to add the new entries (unless --delete was used).
+ Find the menu sections to add them in.
+ In each section, find the proper alphabetical place to add
+ each of the entries. */
+
+ if (!delete_flag)
+ {
+ struct node *node;
+ struct menu_section *section;
+ struct spec_section *spec;
+
+ for (node = dir_nodes; node; node = node->next)
+ for (section = node->sections; section; section = section->next)
+ {
+ for (i = section->end_line; i > section->start_line; i--)
+ if (dir_lines[i - 1].size != 0)
+ break;
+ section->end_line = i;
+
+ for (spec = input_sections; spec; spec = spec->next)
+ if (!strcmp (spec->name, section->name))
+ break;
+ if (spec)
+ {
+ int add_at_line = section->end_line;
+ struct spec_entry *entry;
+ /* Say we have found at least one section with this name,
+ so we need not add such a section. */
+ spec->missing = 0;
+ /* For each entry, find the right place in this section
+ to add it. */
+ for (entry = entries_to_add; entry; entry = entry->next)
+ {
+ int textlen = strlen (entry->text);
+ /* Subtract one because dir_lines is zero-based,
+ but the `end_line' and `start_line' members are
+ one-based. */
+ for (i = section->end_line - 1;
+ i >= section->start_line - 1; i--)
+ {
+ /* If an entry exists with the same name,
+ and was not marked for deletion
+ (which means it is for some other file),
+ we are in trouble. */
+ if (dir_lines[i].start[0] == '*'
+ && menu_line_equal (entry->text, textlen,
+ dir_lines[i].start,
+ dir_lines[i].size)
+ && !dir_lines[i].delete)
+ fatal ("menu item `%s' already exists, for file `%s'",
+ extract_menu_item_name (entry->text),
+ extract_menu_file_name (dir_lines[i].start));
+ if (dir_lines[i].start[0] == '*'
+ && menu_line_lessp (entry->text, textlen,
+ dir_lines[i].start,
+ dir_lines[i].size))
+ add_at_line = i;
+ }
+ insert_entry_here (entry, add_at_line,
+ dir_lines, n_entries_to_add);
+ }
+ }
+ }
+
+ /* Mark the end of the Top node as the place to add any
+ new sections that are needed. */
+ for (node = dir_nodes; node; node = node->next)
+ if (node->name && strcmp (node->name, "Top") == 0)
+ dir_lines[node->end_line].add_sections_before = 1;
+ }
+
+ if (delete_flag && !something_deleted && !quiet_flag)
+ warning ("no entries found for `%s'; nothing deleted", infile);
+
+ /* Output the old dir file, interpolating the new sections
+ and/or new entries where appropriate. */
+
+ output = fopen (dirfile, "w");
+ if (!output)
+ {
+ perror (dirfile);
+ exit (1);
+ }
+
+ for (i = 0; i <= dir_nlines; i++)
+ {
+ int j;
+
+ /* If we decided to output some new entries before this line,
+ output them now. */
+ if (dir_lines[i].add_entries_before)
+ for (j = 0; j < n_entries_to_add; j++)
+ {
+ struct spec_entry *this = dir_lines[i].add_entries_before[j];
+ if (this == 0)
+ break;
+ fputs (this->text, output);
+ }
+ /* If we decided to add some sections here
+ because there are no such sections in the file,
+ output them now. */
+ if (dir_lines[i].add_sections_before)
+ {
+ struct spec_section *spec;
+ struct spec_section **sections;
+ int n_sections = 0;
+
+ /* Count the sections and allocate a vector for all of them. */
+ for (spec = input_sections; spec; spec = spec->next)
+ n_sections++;
+ sections = ((struct spec_section **)
+ xmalloc (n_sections * sizeof (struct spec_section *)));
+
+ /* Fill the vector SECTIONS with pointers to all the sections,
+ and sort them. */
+ j = 0;
+ for (spec = input_sections; spec; spec = spec->next)
+ sections[j++] = spec;
+ qsort (sections, n_sections, sizeof (struct spec_section *),
+ compare_section_names);
+
+ /* Generate the new sections in alphabetical order.
+ In each new section, output all of our entries. */
+ for (j = 0; j < n_sections; j++)
+ {
+ spec = sections[j];
+ if (spec->missing)
+ {
+ struct spec_entry *entry;
+
+ putc ('\n', output);
+ fputs (spec->name, output);
+ putc ('\n', output);
+ for (entry = entries_to_add; entry; entry = entry->next)
+ fputs (entry->text, output);
+ }
+ }
+
+ free (sections);
+ }
+
+ /* Output the original dir lines unless marked for deletion. */
+ if (i < dir_nlines && !dir_lines[i].delete)
+ {
+ fwrite (dir_lines[i].start, 1, dir_lines[i].size, output);
+ putc ('\n', output);
+ }
+ }
+
+ fclose (output);
+
+ exit (0);
+}
+
+/* Read all of file FILNAME into memory
+ and return the address of the data.
+ Store the size into SIZEP.
+ If there is trouble, do a fatal error. */
+
+char *
+readfile (filename, sizep)
+ char *filename;
+ int *sizep;
+{
+ int data_size = 1024;
+ char *data = (char *) xmalloc (data_size);
+ int filled = 0;
+ int nread = 0;
+
+ int desc = open (filename, O_RDONLY);
+
+ if (desc < 0)
+ pfatal_with_name (filename);
+
+ while (1)
+ {
+ nread = read (desc, data + filled, data_size - filled);
+ if (nread < 0)
+ pfatal_with_name (filename);
+ if (nread == 0)
+ break;
+
+ filled += nread;
+ if (filled == data_size)
+ {
+ data_size *= 2;
+ data = (char *) xrealloc (data, data_size);
+ }
+ }
+
+ *sizep = filled;
+ return data;
+}
+
+/* Divide the text at DATA (of SIZE bytes) into lines.
+ Return a vector of struct line_data describing the lines.
+ Store the length of that vector into *NLINESP. */
+
+struct line_data *
+findlines (data, size, nlinesp)
+ char *data;
+ int size;
+ int *nlinesp;
+{
+ struct line_data *lines;
+ int lines_allocated = 512;
+ int filled = 0;
+ int i = 0;
+ int lineflag;
+
+ lines = (struct line_data *) xmalloc (lines_allocated * sizeof (struct line_data));
+
+ lineflag = 1;
+ for (i = 0; i < size; i++)
+ {
+ if (lineflag)
+ {
+ if (filled == lines_allocated)
+ {
+ lines_allocated *= 2;
+ lines = (struct line_data *) xrealloc (lines, lines_allocated * sizeof (struct line_data));
+ }
+ lines[filled].start = &data[i];
+ lines[filled].add_entries_before = 0;
+ lines[filled].add_sections_before = 0;
+ lines[filled].delete = 0;
+ if (filled > 0)
+ lines[filled - 1].size
+ = lines[filled].start - lines[filled - 1].start - 1;
+ filled++;
+ }
+ lineflag = (data[i] == '\n');
+ }
+ if (filled > 0)
+ lines[filled - 1].size = &data[i] - lines[filled - 1].start - lineflag;
+
+ /* Do not leave garbage in the last element. */
+ lines[filled].start = NULL;
+ lines[filled].add_entries_before = NULL;
+ lines[filled].add_sections_before = 0;
+ lines[filled].delete = 0;
+ lines[filled].size = 0;
+
+ *nlinesp = filled;
+ return lines;
+}
+
+/* Compare the menu item names in LINE1 (line length LEN1)
+ and LINE2 (line length LEN2). Return 1 if the item name
+ in LINE1 is less, 0 otherwise. */
+
+int
+menu_line_lessp (line1, len1, line2, len2)
+ char *line1;
+ int len1;
+ char *line2;
+ int len2;
+{
+ int minlen = (len1 < len2 ? len1 : len2);
+ int i;
+
+ for (i = 0; i < minlen; i++)
+ {
+ /* If one item name is a prefix of the other,
+ the former one is less. */
+ if (line1[i] == ':' && line2[i] != ':')
+ return 1;
+ if (line2[i] == ':' && line1[i] != ':')
+ return 0;
+ /* If they both continue and differ, one is less. */
+ if (line1[i] < line2[i])
+ return 1;
+ if (line1[i] > line2[i])
+ return 0;
+ }
+ /* With a properly formatted dir file,
+ we can only get here if the item names are equal. */
+ return 0;
+}
+
+/* Compare the menu item names in LINE1 (line length LEN1)
+ and LINE2 (line length LEN2). Return 1 if the item names are equal,
+ 0 otherwise. */
+
+int
+menu_line_equal (line1, len1, line2, len2)
+ char *line1;
+ int len1;
+ char *line2;
+ int len2;
+{
+ int minlen = (len1 < len2 ? len1 : len2);
+ int i;
+
+ for (i = 0; i < minlen; i++)
+ {
+ /* If both item names end here, they are equal. */
+ if (line1[i] == ':' && line2[i] == ':')
+ return 1;
+ /* If they both continue and differ, one is less. */
+ if (line1[i] != line2[i])
+ return 0;
+ }
+ /* With a properly formatted dir file,
+ we can only get here if the item names are equal. */
+ return 1;
+}
+
+/* This is the comparison function for qsort
+ for a vector of pointers to struct spec_section.
+ Compare the section names. */
+
+int
+compare_section_names (sec1, sec2)
+ struct spec_section **sec1, **sec2;
+{
+ char *name1 = (*sec1)->name;
+ char *name2 = (*sec2)->name;
+ return strcmp (name1, name2);
+}
+
+/* Insert ENTRY into the add_entries_before vector
+ for line number LINE_NUMBER of the dir file.
+ DIR_LINES and N_ENTRIES carry information from like-named variables
+ in main. */
+
+void
+insert_entry_here (entry, line_number, dir_lines, n_entries)
+ struct spec_entry *entry;
+ int line_number;
+ struct line_data *dir_lines;
+ int n_entries;
+{
+ int i;
+
+ if (dir_lines[line_number].add_entries_before == 0)
+ {
+ dir_lines[line_number].add_entries_before
+ = (struct spec_entry **) xmalloc (n_entries * sizeof (struct spec_entry *));
+ for (i = 0; i < n_entries; i++)
+ dir_lines[line_number].add_entries_before[i] = 0;
+ }
+
+ for (i = 0; i < n_entries; i++)
+ if (dir_lines[line_number].add_entries_before[i] == 0)
+ break;
+
+ if (i == n_entries)
+ abort ();
+
+ dir_lines[line_number].add_entries_before[i] = entry;
+}
diff --git a/contrib/texinfo/util/mkinstalldirs b/contrib/texinfo/util/mkinstalldirs
new file mode 100755
index 0000000..a01481b
--- /dev/null
+++ b/contrib/texinfo/util/mkinstalldirs
@@ -0,0 +1,40 @@
+#! /bin/sh
+# mkinstalldirs --- make directory hierarchy
+# Author: Noah Friedman <friedman@prep.ai.mit.edu>
+# Created: 1993-05-16
+# Public domain
+
+# $Id: mkinstalldirs,v 1.10 1996/05/03 07:37:52 friedman Exp $
+
+errstatus=0
+
+for file
+do
+ set fnord `echo ":$file" | sed -ne 's/^:\//#/;s/^://;s/\// /g;s/^#/\//;p'`
+ shift
+
+ pathcomp=
+ for d
+ do
+ pathcomp="$pathcomp$d"
+ case "$pathcomp" in
+ -* ) pathcomp=./$pathcomp ;;
+ esac
+
+ if test ! -d "$pathcomp"; then
+ echo "mkdir $pathcomp" 1>&2
+
+ mkdir "$pathcomp" || lasterr=$?
+
+ if test ! -d "$pathcomp"; then
+ errstatus=$lasterr
+ fi
+ fi
+
+ pathcomp="$pathcomp/"
+ done
+done
+
+exit $errstatus
+
+# mkinstalldirs ends here
diff --git a/contrib/texinfo/util/tex3patch b/contrib/texinfo/util/tex3patch
new file mode 100755
index 0000000..1708c75
--- /dev/null
+++ b/contrib/texinfo/util/tex3patch
@@ -0,0 +1,71 @@
+#!/bin/sh
+# Auxiliary script to work around TeX 3.0 bug. ---- tex3patch ----
+# patches texinfo.tex in current directory, or in directory given as arg.
+
+ANYVERSION=no
+
+for arg in $1 $2
+do
+ case $arg in
+ --dammit | -d ) ANYVERSION=yes ;;
+
+ * ) dir=$arg
+ esac
+done
+
+if [ -z "$dir" ]; then
+ dir='.'
+fi
+
+if [ \( 2 -lt $# \) -o \
+ \( ! -f $dir/texinfo.tex \) ]; then
+ echo "To patch texinfo.tex for peaceful coexistence with Unix TeX 3.0,"
+ echo "run $0"
+ echo "with no arguments in the same directory as texinfo.tex; or run"
+ echo " $0 DIRECTORY"
+ echo "(where DIRECTORY is a path leading to texinfo.tex)."
+ exit
+fi
+
+if [ -z "$TMPDIR" ]; then
+ TMPDIR=/tmp
+fi
+
+echo "Checking for \`dummy.tfm'"
+
+( cd $TMPDIR; tex '\relax \batchmode \font\foo=dummy \bye' )
+
+grep -s '3.0' $TMPDIR/texput.log
+if [ 1 = "$?" -a "$ANYVERSION" != "yes" ]; then
+ echo "You probably do not need this patch,"
+ echo "since your TeX does not seem to be version 3.0."
+ echo "If you insist on applying the patch, run $0"
+ echo "again with the option \`--dammit'"
+ exit
+fi
+
+grep -s 'file not found' $TMPDIR/texput.log
+if [ 0 = $? ]; then
+ echo "This patch requires the dummy font metric file \`dummy.tfm',"
+ echo "which does not seem to be part of your TeX installation."
+ echo "Please get your TeX maintainer to install \`dummy.tfm',"
+ echo "then run this script again."
+ exit
+fi
+rm $TMPDIR/texput.log
+
+echo "Patching $dir/texinfo.tex"
+
+sed -e 's/%%*\\font\\nullfont/\\font\\nullfont/' \
+ $dir/texinfo.tex >$TMPDIR/texinfo.tex
+mv $dir/texinfo.tex $dir/texinfo.tex-distrib; mv $TMPDIR/texinfo.tex $dir
+
+if [ 0 = $? ]; then
+ echo "Patched $dir/texinfo.tex to avoid TeX 3.0 bug."
+ echo "The original version is saved as $dir/texinfo.tex-distrib."
+else
+ echo "Patch failed. Sorry."
+fi
+----------------------------------------tex3patch ends
+
+
diff --git a/contrib/texinfo/util/texi2dvi b/contrib/texinfo/util/texi2dvi
new file mode 100755
index 0000000..9b2e48e
--- /dev/null
+++ b/contrib/texinfo/util/texi2dvi
@@ -0,0 +1,364 @@
+#! /bin/sh
+# texi2dvi --- smartly produce DVI files from texinfo sources
+
+# Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc.
+
+# $Id: texi2dvi,v 1.10 1996/10/04 18:21:55 karl Exp $
+
+# 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, 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, you can either send email to this
+# program's maintainer or write to: The Free Software Foundation,
+# Inc.; 59 Temple Place, Suite 330; Boston, MA 02111-1307, USA.
+
+# Commentary:
+
+# Author: Noah Friedman <friedman@prep.ai.mit.edu>
+
+# Please send bug reports, etc. to bug-texinfo@prep.ai.mit.edu
+# If possible, please send a copy of the output of the script called with
+# the `--debug' option when making a bug report.
+
+# In the interest of general portability, some common bourne shell
+# constructs were avoided because they weren't guaranteed to be available
+# in some earlier implementations. I've tried to make this program as
+# portable as possible. Welcome to unix, where the lowest common
+# denominator is rapidly diminishing.
+#
+# Among the more interesting lossages I noticed with some bourne shells
+# are:
+# * No shell functions.
+# * No `unset' builtin.
+# * `shift' cannot take a numeric argument, and signals an error if
+# there are no arguments to shift.
+
+# Code:
+
+# Name by which this script was invoked.
+progname=`echo "$0" | sed -e 's/[^\/]*\///g'`
+
+# This string is expanded by rcs automatically when this file is checked out.
+rcs_revision='$Revision: 1.10 $'
+version=`set - $rcs_revision; echo $2`
+
+# To prevent hairy quoting and escaping later.
+bq='`'
+eq="'"
+
+usage="Usage: $0 [OPTION]... FILE...
+Run a Texinfo document through TeX.
+
+Options:
+-D, --debug Turn on shell debugging ($bq${bq}set -x$eq$eq).
+-t, --texinfo CMD Insert CMD after @setfilename before running TeX.
+--verbose Report on what is done.
+-h, --help Display this help and exit.
+-v, --version Display version information and exit.
+
+The values of the TEX, TEXINDEX, and MAKEINFO environment variables are
+used to run those commands, if they are set.
+
+Email bug reports to bug-texinfo@prep.ai.mit.edu.
+"
+
+# Initialize variables.
+# Don't use `unset' since old bourne shells don't have this command.
+# Instead, assign them an empty value.
+# Some of these, like TEX and TEXINDEX, may be inherited from the environment.
+backup_extension=.bak # these files get deleted if all goes well.
+debug=
+orig_pwd="`pwd`"
+textra=
+verbose=false
+makeinfo="${MAKEINFO-makeinfo}"
+texindex="${TEXINDEX-texindex}"
+tex="${TEX-tex}"
+
+# Save this so we can construct a new TEXINPUTS path for each file.
+TEXINPUTS_orig="$TEXINPUTS"
+export TEXINPUTS
+
+# Parse command line arguments.
+# Make sure that all wildcarded options are long enough to be unambiguous.
+# It's a good idea to document the full long option name in each case.
+# Long options which take arguments will need a `*' appended to the
+# canonical name to match the value appended after the `=' character.
+while : ; do
+ case $# in 0) break ;; esac
+ case "$1" in
+ -D | --debug | --d* ) debug=t; shift ;;
+ -h | --help | --h* ) echo "$usage"; exit 0 ;;
+ # OK, we should do real option parsing here, but be lazy for now.
+ -t | --texinfo | --t*) shift; textra="$textra $1"; shift ;;
+ -v | --vers* )
+ echo "$progname (Texinfo 3.9) $version"
+ echo "Copyright (C) 1996 Free Software Foundation, Inc.
+There is NO warranty. You may redistribute this software
+under the terms of the GNU General Public License.
+For more information about these matters, see the files named COPYING."
+ exit 0 ;;
+ --verb* ) verbose=echo; shift ;;
+ -- ) # Stop option processing
+ shift
+ break
+ ;;
+ -* )
+ case "$1" in
+ --*=* ) arg=`echo "$1" | sed -e 's/=.*//'` ;;
+ * ) arg="$1" ;;
+ esac
+ exec 1>&2
+ echo "$progname: Unknown or ambiguous option $bq$arg$eq."
+ echo "$progname: Try $bq--help$eq for more information."
+ exit 1
+ ;;
+ * )
+ break
+ ;;
+ esac
+done
+
+# See if there are any command line args left (which will be interpreted as
+# filename arguments).
+if test $# -eq 0; then
+ exec 1>&2
+ echo "$progname: At least one file name is required as an argument."
+ echo "$progname: Try $bq--help$eq for more information."
+ exit 2
+fi
+
+test "$debug" = t && set -x
+
+# Texify files
+for command_line_filename in ${1+"$@"} ; do
+ $verbose "Processing $command_line_filename ..."
+
+ # See if file exists. If it doesn't we're in trouble since, even
+ # though the user may be able to reenter a valid filename at the tex
+ # prompt (assuming they're attending the terminal), this script won't
+ # be able to find the right index files and so forth.
+ if test ! -r "${command_line_filename}" ; then
+ echo "$0: Could not read ${command_line_filename}." >&2
+ continue
+ fi
+
+ # Roughly equivalent to `dirname ...`, but more portable
+ directory="`echo ${command_line_filename} | sed 's/\/[^\/]*$//'`"
+ filename_texi="`basename ${command_line_filename}`"
+ # Strip off the last extension part (probably .texinfo or .texi)
+ filename_noext="`echo ${filename_texi} | sed 's/\.[^.]*$//'`"
+
+ # Use same basename since we want to generate aux files with the same
+ # basename as the manual. Use extension .texi for the temp file so
+ # that TeX will ignore it. Thus, we must use a subdirectory.
+ #
+ # Output the macro-expanded file to here.
+ tmp_dir=${TMPDIR-/tmp}/$$
+ filename_tmp=$tmp_dir/$filename_noext.texi
+ # Output the file with the user's extra commands to here.
+ filename_tmp2=$tmp_dir.2/$filename_noext.texi
+ mkdir $tmp_dir $tmp_dir.2
+
+ # If directory and file are the same, then it's probably because there's
+ # no pathname component. Set dirname to `.', the current directory.
+ if test "z${directory}" = "z${command_line_filename}" ; then
+ directory=.
+ fi
+
+ # Source file might @include additional texinfo sources. Put `.' and
+ # directory where source file(s) reside in TEXINPUTS before anything
+ # else. `.' goes first to ensure that any old .aux, .cps, etc. files in
+ # ${directory} don't get used in preference to fresher files in `.'.
+ TEXINPUTS=".:${directory}:${TEXINPUTS_orig}"
+
+ # Expand macro commands in the original source file using Makeinfo;
+ # the macro syntax bfox implemented is impossible to implement in TeX.
+ # Always use `end' footnote style, since the `separate' style
+ # generates different output (arguably this is a bug in -E).
+ # Discard main info output, the user asked to run TeX, not makeinfo.
+ # Redirect output to /dev/null to throw away `Making info file...' msg.
+ $verbose "Macro-expanding $command_line_filename to $filename_tmp ..."
+ $makeinfo --footnote-style=end -E $filename_tmp -o /dev/null \
+ $command_line_filename >/dev/null
+
+ # But if there were no macros, or makeinfo failed for some reason,
+ # just use the original file. (It shouldn't make any difference, but
+ # let's be safe.)
+ if test $? -ne 0 || cmp -s $filename_tmp $command_line_filename; then
+ $verbose "Reverting to $command_line_filename ..."
+ filename_input=$command_line_filename
+ else
+ filename_input=$filename_tmp
+ fi
+
+ # Used most commonly for @finalout, @smallbook, etc.
+ if test -n "$textra"; then
+ $verbose "Inserting extra commands: $textra."
+ sed '/^@setfilename/a\
+'"$textra" $filename_input >$filename_tmp2
+ filename_input=$filename_tmp2
+ fi
+
+ while true; do # will break out of loop below
+ # "Unset" variables that might have values from previous iterations and
+ # which won't be completely reset later.
+ definite_index_files=
+
+ # Find all files having root filename with a two-letter extension,
+ # determine whether they're really index files, and save them. Foo.aux
+ # is actually the cross-references file, but we need to keep track of
+ # that too.
+ possible_index_files="`eval echo ${filename_noext}.?? ${filename_noext}.aux`"
+ for this_file in ${possible_index_files} ; do
+ # If file is empty, forget it.
+ test -s "${this_file}" || continue
+
+ # Examine first character of file. If it's not suitable to be an
+ # index or xref file, don't process it.
+ first_character="`sed -n '1s/^\(.\).*$/\1/p;q' ${this_file}`"
+ if test "x${first_character}" = "x\\" \
+ || test "x${first_character}" = "x'"; then
+ definite_index_files="${definite_index_files} ${this_file}"
+ fi
+ done
+ orig_index_files="${definite_index_files}"
+ orig_index_files_sans_aux="`echo ${definite_index_files} \
+ | sed 's/'${filename_noext}'\.aux//;
+ s/^[ ]*//;s/[ ]*$//;'`"
+
+ # Now save copies of original index files so we have some means of
+ # comparison later.
+ $verbose "Backing up current index files: $orig_index_files ..."
+ for index_file_to_save in ${orig_index_files} ; do
+ cp "${index_file_to_save}" "${index_file_to_save}${backup_extension}"
+ done
+
+ # Run texindex on current index files. If they already exist, and
+ # after running TeX a first time the index files don't change, then
+ # there's no reason to run TeX again. But we won't know that if the
+ # index files are out of date or nonexistent.
+ if test -n "${orig_index_files_sans_aux}" ; then
+ $verbose "Running $texindex $orig_index_files_sans_aux ..."
+ ${texindex} ${orig_index_files_sans_aux}
+ fi
+
+ # Finally, run TeX.
+ $verbose "Running $tex $filename_input ..."
+ ${tex} "$filename_input"
+
+ # Check if index files changed.
+ #
+ definite_index_files=
+ # Get list of new index files.
+ possible_index_files="`eval echo ${filename_noext}.?? ${filename_noext}.aux`"
+ for this_file in ${possible_index_files} ; do
+ # If file is empty, forget it.
+ test -s "${this_file}" || continue
+
+ # Examine first character of file. If it's not a backslash or
+ # single quote, then it's definitely not an index or xref file.
+ # (Will have to check for @ when we switch to Texinfo syntax in
+ # all these files...)
+ first_character="`sed -n '1s/^\(.\).*$/\1/p;q' ${this_file}`"
+ if test "x${first_character}" = "x\\" \
+ || test "x${first_character}" = "x'"; then
+ definite_index_files="${definite_index_files} ${this_file}"
+ fi
+ done
+ new_index_files="${definite_index_files}"
+ new_index_files_sans_aux="`echo ${definite_index_files} \
+ | sed 's/'${filename_noext}'\.aux//;
+ s/^[ ]*//;s/[ ]*$//;'`"
+
+ # If old and new list don't at least have the same file list, then one
+ # file or another has definitely changed.
+ $verbose "Original index files =$orig_index_files"
+ $verbose "New index files =$new_index_files"
+ if test "z${orig_index_files}" != "z${new_index_files}" ; then
+ index_files_changed_p=t
+ else
+ # File list is the same. We must compare each file until we find a
+ # difference.
+ index_files_changed_p=
+ for this_file in ${new_index_files} ; do
+ $verbose "Comparing index file $this_file ..."
+ # cmp -s will return nonzero exit status if files differ.
+ cmp -s "${this_file}" "${this_file}${backup_extension}"
+ if test $? -ne 0 ; then
+ # We only need to keep comparing until we find *one* that
+ # differs, because we'll have to run texindex & tex no
+ # matter what.
+ index_files_changed_p=t
+ $verbose "Index file $this_file differed:"
+ test $verbose = echo \
+ && diff -c "${this_file}${backup_extension}" "${this_file}"
+ break
+ fi
+ done
+ fi
+
+ # If index files have changed since TeX has been run, or if the aux
+ # file wasn't present originally, run texindex and TeX again.
+ if test "${index_files_changed_p}" ; then :; else
+ # Nothing changed. We're done with TeX.
+ break
+ fi
+ done
+
+ # Generate list of files to delete, then call rm once with the entire
+ # list. This is significantly faster than multiple executions of rm.
+ file_list=
+ for file in ${orig_index_files} ; do
+ file_list="${file_list} ${file}${backup_extension}"
+ done
+ if test -n "${file_list}" ; then
+ $verbose "Removing $file_list $tmp_dir $tmp_dir.2 ..."
+ rm -f ${file_list}
+ rm -rf $tmp_dir $tmp_dir.2
+ fi
+done
+
+$verbose "$0 done."
+true # exit successfully.
+
+# texi2dvi ends here
+# $Log: texi2dvi,v $
+# Revision 1.10 1996/10/04 18:21:55 karl
+# Include only the current year in the copyright message.
+#
+# Revision 1.9 1996/10/04 11:49:48 karl
+# Exit successfully. From arnold.
+#
+# Revision 1.8 1996/10/03 23:14:26 karl
+# Only show diff if verbose.
+# Update version number.
+#
+# Revision 1.7 1996/09/29 22:56:08 karl
+# Use $progname instead of $0 for --version.
+#
+# Revision 1.6 1996/09/28 21:01:23 karl
+# Recompute original index files each time through loop.
+# Make indentation uniform.
+# Use same basename for the temp input files.
+# Standardize --version output.
+#
+# Revision 1.5 1996/09/26 14:46:34 karl
+# (texi2dvi): Run TeX until the aux/index files stabilize, instead of just
+# twice. From: David Shaw <daves@gsms01.alcatel.com.au>.
+#
+# Revision 1.4 1996/08/27 18:59:26 karl
+# Include bug reporting address.
+#
+# Revision 1.3 1996/07/26 18:20:56 karl
+# Do macro expansion with makeinfo before running TeX.
+# Various expansion safety measures added for test; avoid use of -o.
+#
diff --git a/contrib/texinfo/util/texindex.c b/contrib/texinfo/util/texindex.c
new file mode 100644
index 0000000..47a5679
--- /dev/null
+++ b/contrib/texinfo/util/texindex.c
@@ -0,0 +1,1793 @@
+/* Prepare TeX index dribble output into an actual index.
+ $Id: texindex.c,v 1.6 1996/10/04 18:21:30 karl Exp $
+
+ Copyright (C) 1987, 91, 92, 96 Free Software Foundation, Inc.
+
+ 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307. */
+
+#include <stdio.h>
+#include <ctype.h>
+#include <errno.h>
+#include "getopt.h"
+
+#define TEXINDEX_VERSION_STRING "GNU Texindex (Texinfo 3.9) 2.1"
+
+#if defined (emacs)
+# include "../src/config.h"
+/* Some s/os.h files redefine these. */
+# undef read
+# undef close
+# undef write
+# undef open
+#endif
+
+#if defined (HAVE_STRING_H)
+# include <string.h>
+#endif /* HAVE_STRING_H */
+
+#if !defined (HAVE_STRCHR)
+char *strrchr ();
+#endif /* !HAVE_STRCHR */
+
+#if defined (STDC_HEADERS)
+# include <stdlib.h>
+#else /* !STDC_HEADERS */
+char *getenv (), *malloc (), *realloc ();
+#endif /* !STDC_HEADERS */
+
+#if defined (HAVE_UNISTD_H)
+# include <unistd.h>
+#else /* !HAVE_UNISTD_H */
+off_t lseek ();
+#endif /* !HAVE_UNISTD_H */
+
+#if !defined (HAVE_MEMSET)
+#undef memset
+#define memset(ptr, ignore, count) bzero (ptr, count)
+#endif
+
+
+char *mktemp ();
+
+#if defined (VMS)
+# include <file.h>
+# define TI_NO_ERROR ((1 << 28) | 1)
+# define TI_FATAL_ERROR ((1 << 28) | 4)
+# define unlink delete
+#else /* !VMS */
+# if defined (HAVE_SYS_FCNTL_H)
+# include <sys/types.h>
+# include <sys/fcntl.h>
+# endif /* HAVE_SYS_FCNTL_H */
+
+# if defined (_AIX) || !defined (_POSIX_VERSION)
+# include <sys/file.h>
+# else /* !AIX && _POSIX_VERSION */
+# if !defined (HAVE_SYS_FCNTL_H)
+# include <fcntl.h>
+# endif /* !HAVE_FCNTL_H */
+# endif /* !_AIX && _POSIX_VERSION */
+# define TI_NO_ERROR 0
+# define TI_FATAL_ERROR 1
+#endif /* !VMS */
+
+#if !defined (SEEK_SET)
+# define SEEK_SET 0
+# define SEEK_CUR 1
+# define SEEK_END 2
+#endif /* !SEEK_SET */
+
+#ifndef errno
+extern int errno;
+#endif
+#ifndef strerror
+extern char *strerror ();
+#endif
+
+/* When sorting in core, this structure describes one line
+ and the position and length of its first keyfield. */
+struct lineinfo
+{
+ char *text; /* The actual text of the line. */
+ union {
+ char *text; /* The start of the key (for textual comparison). */
+ long number; /* The numeric value (for numeric comparison). */
+ } key;
+ long keylen; /* Length of KEY field. */
+};
+
+/* This structure describes a field to use as a sort key. */
+struct keyfield
+{
+ int startwords; /* Number of words to skip. */
+ int startchars; /* Number of additional chars to skip. */
+ int endwords; /* Number of words to ignore at end. */
+ int endchars; /* Ditto for characters of last word. */
+ char ignore_blanks; /* Non-zero means ignore spaces and tabs. */
+ char fold_case; /* Non-zero means case doesn't matter. */
+ char reverse; /* Non-zero means compare in reverse order. */
+ char numeric; /* Non-zeros means field is ASCII numeric. */
+ char positional; /* Sort according to file position. */
+ char braced; /* Count balanced-braced groupings as fields. */
+};
+
+/* Vector of keyfields to use. */
+struct keyfield keyfields[3];
+
+/* Number of keyfields stored in that vector. */
+int num_keyfields = 3;
+
+/* Vector of input file names, terminated with a null pointer. */
+char **infiles;
+
+/* Vector of corresponding output file names, or NULL, meaning default it
+ (add an `s' to the end). */
+char **outfiles;
+
+/* Length of `infiles'. */
+int num_infiles;
+
+/* Pointer to the array of pointers to lines being sorted. */
+char **linearray;
+
+/* The allocated length of `linearray'. */
+long nlines;
+
+/* Directory to use for temporary files. On Unix, it ends with a slash. */
+char *tempdir;
+
+/* Start of filename to use for temporary files. */
+char *tempbase;
+
+/* Number of last temporary file. */
+int tempcount;
+
+/* Number of last temporary file already deleted.
+ Temporary files are deleted by `flush_tempfiles' in order of creation. */
+int last_deleted_tempcount;
+
+/* During in-core sort, this points to the base of the data block
+ which contains all the lines of data. */
+char *text_base;
+
+/* Additional command switches .*/
+
+/* Nonzero means do not delete tempfiles -- for debugging. */
+int keep_tempfiles;
+
+/* The name this program was run with. */
+char *program_name;
+
+/* Forward declarations of functions in this file. */
+
+void decode_command ();
+void sort_in_core ();
+void sort_offline ();
+char **parsefile ();
+char *find_field ();
+char *find_pos ();
+long find_value ();
+char *find_braced_pos ();
+char *find_braced_end ();
+void writelines ();
+int compare_field ();
+int compare_full ();
+long readline ();
+int merge_files ();
+int merge_direct ();
+void pfatal_with_name ();
+void fatal ();
+void error ();
+void *xmalloc (), *xrealloc ();
+char *concat ();
+char *maketempname ();
+void flush_tempfiles ();
+char *tempcopy ();
+
+#define MAX_IN_CORE_SORT 500000
+
+void
+main (argc, argv)
+ int argc;
+ char **argv;
+{
+ int i;
+
+ tempcount = 0;
+ last_deleted_tempcount = 0;
+
+ program_name = strrchr (argv[0], '/');
+ if (program_name != (char *)NULL)
+ program_name++;
+ else
+ program_name = argv[0];
+
+ /* Describe the kind of sorting to do. */
+ /* The first keyfield uses the first braced field and folds case. */
+ keyfields[0].braced = 1;
+ keyfields[0].fold_case = 1;
+ keyfields[0].endwords = -1;
+ keyfields[0].endchars = -1;
+
+ /* The second keyfield uses the second braced field, numerically. */
+ keyfields[1].braced = 1;
+ keyfields[1].numeric = 1;
+ keyfields[1].startwords = 1;
+ keyfields[1].endwords = -1;
+ keyfields[1].endchars = -1;
+
+ /* The third keyfield (which is ignored while discarding duplicates)
+ compares the whole line. */
+ keyfields[2].endwords = -1;
+ keyfields[2].endchars = -1;
+
+ decode_command (argc, argv);
+
+ tempbase = mktemp (concat ("txiXXXXXX", "", ""));
+
+ /* Process input files completely, one by one. */
+
+ for (i = 0; i < num_infiles; i++)
+ {
+ int desc;
+ long ptr;
+ char *outfile;
+
+ desc = open (infiles[i], O_RDONLY, 0);
+ if (desc < 0)
+ pfatal_with_name (infiles[i]);
+ lseek (desc, (off_t) 0, SEEK_END);
+ ptr = (long) lseek (desc, (off_t) 0, SEEK_CUR);
+
+ close (desc);
+
+ outfile = outfiles[i];
+ if (!outfile)
+ {
+ outfile = concat (infiles[i], "s", "");
+ }
+
+ if (ptr < MAX_IN_CORE_SORT)
+ /* Sort a small amount of data. */
+ sort_in_core (infiles[i], ptr, outfile);
+ else
+ sort_offline (infiles[i], ptr, outfile);
+ }
+
+ flush_tempfiles (tempcount);
+ exit (TI_NO_ERROR);
+}
+
+typedef struct
+{
+ char *long_name;
+ char *short_name;
+ int *variable_ref;
+ int variable_value;
+ char *arg_name;
+ char *doc_string;
+} TEXINDEX_OPTION;
+
+TEXINDEX_OPTION texindex_options[] = {
+ { "--keep", "-k", &keep_tempfiles, 1, (char *)NULL,
+ "keep temporary files around after processing" },
+ { "--no-keep", 0, &keep_tempfiles, 0, (char *)NULL,
+ "do not keep temporary files around after processing (default)" },
+ { "--output", "-o", (int *)NULL, 0, "FILE",
+ "send output to FILE" },
+ { "--version", (char *)NULL, (int *)NULL, 0, (char *)NULL,
+ "display version information and exit" },
+ { "--help", "-h", (int *)NULL, 0, (char *)NULL,
+ "display this help and exit" },
+ { (char *)NULL, (char *)NULL, (int *)NULL, 0, (char *)NULL }
+};
+
+void
+usage (result_value)
+ int result_value;
+{
+ register int i;
+ FILE *f = result_value ? stderr : stdout;
+
+ fprintf (f, "Usage: %s [OPTION]... FILE...\n", program_name);
+ fprintf (f, "Generate a sorted index for each TeX output FILE.\n");
+ /* Avoid trigraph nonsense. */
+ fprintf (f, "Usually FILE... is `foo.??\' for a document `foo.texi'.\n");
+ fprintf (f, "\nOptions:\n");
+
+ for (i = 0; texindex_options[i].long_name; i++)
+ {
+ if (texindex_options[i].short_name)
+ fprintf (f, "%s, ", texindex_options[i].short_name);
+
+ fprintf (f, "%s %s",
+ texindex_options[i].long_name,
+ texindex_options[i].arg_name
+ ? texindex_options[i].arg_name : "");
+
+ fprintf (f, "\t%s\n", texindex_options[i].doc_string);
+ }
+ puts ("\nEmail bug reports to bug-texinfo@prep.ai.mit.edu.");
+
+ exit (result_value);
+}
+
+/* Decode the command line arguments to set the parameter variables
+ and set up the vector of keyfields and the vector of input files. */
+
+void
+decode_command (argc, argv)
+ int argc;
+ char **argv;
+{
+ int arg_index = 1;
+ int optc;
+ char **ip;
+ char **op;
+
+ /* Store default values into parameter variables. */
+
+ tempdir = getenv ("TMPDIR");
+#ifdef VMS
+ if (tempdir == NULL)
+ tempdir = "sys$scratch:";
+#else
+ if (tempdir == NULL)
+ tempdir = "/tmp/";
+ else
+ tempdir = concat (tempdir, "/", "");
+#endif
+
+ keep_tempfiles = 0;
+
+ /* Allocate ARGC input files, which must be enough. */
+
+ infiles = (char **) xmalloc (argc * sizeof (char *));
+ outfiles = (char **) xmalloc (argc * sizeof (char *));
+ ip = infiles;
+ op = outfiles;
+
+ while (arg_index < argc)
+ {
+ char *arg = argv[arg_index++];
+
+ if (*arg == '-')
+ {
+ if (strcmp (arg, "--version") == 0)
+ {
+ puts (TEXINDEX_VERSION_STRING);
+puts ("Copyright (C) 1996 Free Software Foundation, Inc.\n\
+There is NO warranty. You may redistribute this software\n\
+under the terms of the GNU General Public License.\n\
+For more information about these matters, see the files named COPYING.");
+ exit (0);
+ }
+ else if ((strcmp (arg, "--keep") == 0) ||
+ (strcmp (arg, "-k") == 0))
+ {
+ keep_tempfiles = 1;
+ }
+ else if ((strcmp (arg, "--help") == 0) ||
+ (strcmp (arg, "-h") == 0))
+ {
+ usage (0);
+ }
+ else if ((strcmp (arg, "--output") == 0) ||
+ (strcmp (arg, "-o") == 0))
+ {
+ if (argv[arg_index] != (char *)NULL)
+ {
+ arg_index++;
+ if (op > outfiles)
+ *(op - 1) = argv[arg_index];
+ }
+ else
+ usage (1);
+ }
+ else
+ usage (1);
+ }
+ else
+ {
+ *ip++ = arg;
+ *op++ = (char *)NULL;
+ }
+ }
+
+ /* Record number of keyfields and terminate list of filenames. */
+ num_infiles = ip - infiles;
+ *ip = (char *)NULL;
+ if (num_infiles == 0)
+ usage (1);
+}
+
+/* Return a name for a temporary file. */
+
+char *
+maketempname (count)
+ int count;
+{
+ char tempsuffix[10];
+ sprintf (tempsuffix, "%d", count);
+ return concat (tempdir, tempbase, tempsuffix);
+}
+
+/* Delete all temporary files up to TO_COUNT. */
+
+void
+flush_tempfiles (to_count)
+ int to_count;
+{
+ if (keep_tempfiles)
+ return;
+ while (last_deleted_tempcount < to_count)
+ unlink (maketempname (++last_deleted_tempcount));
+}
+
+/* Copy the input file open on IDESC into a temporary file
+ and return the temporary file name. */
+
+#define BUFSIZE 1024
+
+char *
+tempcopy (idesc)
+ int idesc;
+{
+ char *outfile = maketempname (++tempcount);
+ int odesc;
+ char buffer[BUFSIZE];
+
+ odesc = open (outfile, O_WRONLY | O_CREAT, 0666);
+
+ if (odesc < 0)
+ pfatal_with_name (outfile);
+
+ while (1)
+ {
+ int nread = read (idesc, buffer, BUFSIZE);
+ write (odesc, buffer, nread);
+ if (!nread)
+ break;
+ }
+
+ close (odesc);
+
+ return outfile;
+}
+
+/* Compare LINE1 and LINE2 according to the specified set of keyfields. */
+
+int
+compare_full (line1, line2)
+ char **line1, **line2;
+{
+ int i;
+
+ /* Compare using the first keyfield;
+ if that does not distinguish the lines, try the second keyfield;
+ and so on. */
+
+ for (i = 0; i < num_keyfields; i++)
+ {
+ long length1, length2;
+ char *start1 = find_field (&keyfields[i], *line1, &length1);
+ char *start2 = find_field (&keyfields[i], *line2, &length2);
+ int tem = compare_field (&keyfields[i], start1, length1, *line1 - text_base,
+ start2, length2, *line2 - text_base);
+ if (tem)
+ {
+ if (keyfields[i].reverse)
+ return -tem;
+ return tem;
+ }
+ }
+
+ return 0; /* Lines match exactly. */
+}
+
+/* Compare LINE1 and LINE2, described by structures
+ in which the first keyfield is identified in advance.
+ For positional sorting, assumes that the order of the lines in core
+ reflects their nominal order. */
+
+int
+compare_prepared (line1, line2)
+ struct lineinfo *line1, *line2;
+{
+ int i;
+ int tem;
+ char *text1, *text2;
+
+ /* Compare using the first keyfield, which has been found for us already. */
+ if (keyfields->positional)
+ {
+ if (line1->text - text_base > line2->text - text_base)
+ tem = 1;
+ else
+ tem = -1;
+ }
+ else if (keyfields->numeric)
+ tem = line1->key.number - line2->key.number;
+ else
+ tem = compare_field (keyfields, line1->key.text, line1->keylen, 0,
+ line2->key.text, line2->keylen, 0);
+ if (tem)
+ {
+ if (keyfields->reverse)
+ return -tem;
+ return tem;
+ }
+
+ text1 = line1->text;
+ text2 = line2->text;
+
+ /* Compare using the second keyfield;
+ if that does not distinguish the lines, try the third keyfield;
+ and so on. */
+
+ for (i = 1; i < num_keyfields; i++)
+ {
+ long length1, length2;
+ char *start1 = find_field (&keyfields[i], text1, &length1);
+ char *start2 = find_field (&keyfields[i], text2, &length2);
+ int tem = compare_field (&keyfields[i], start1, length1, text1 - text_base,
+ start2, length2, text2 - text_base);
+ if (tem)
+ {
+ if (keyfields[i].reverse)
+ return -tem;
+ return tem;
+ }
+ }
+
+ return 0; /* Lines match exactly. */
+}
+
+/* Like compare_full but more general.
+ You can pass any strings, and you can say how many keyfields to use.
+ POS1 and POS2 should indicate the nominal positional ordering of
+ the two lines in the input. */
+
+int
+compare_general (str1, str2, pos1, pos2, use_keyfields)
+ char *str1, *str2;
+ long pos1, pos2;
+ int use_keyfields;
+{
+ int i;
+
+ /* Compare using the first keyfield;
+ if that does not distinguish the lines, try the second keyfield;
+ and so on. */
+
+ for (i = 0; i < use_keyfields; i++)
+ {
+ long length1, length2;
+ char *start1 = find_field (&keyfields[i], str1, &length1);
+ char *start2 = find_field (&keyfields[i], str2, &length2);
+ int tem = compare_field (&keyfields[i], start1, length1, pos1,
+ start2, length2, pos2);
+ if (tem)
+ {
+ if (keyfields[i].reverse)
+ return -tem;
+ return tem;
+ }
+ }
+
+ return 0; /* Lines match exactly. */
+}
+
+/* Find the start and length of a field in STR according to KEYFIELD.
+ A pointer to the starting character is returned, and the length
+ is stored into the int that LENGTHPTR points to. */
+
+char *
+find_field (keyfield, str, lengthptr)
+ struct keyfield *keyfield;
+ char *str;
+ long *lengthptr;
+{
+ char *start;
+ char *end;
+ char *(*fun) ();
+
+ if (keyfield->braced)
+ fun = find_braced_pos;
+ else
+ fun = find_pos;
+
+ start = (*fun) (str, keyfield->startwords, keyfield->startchars,
+ keyfield->ignore_blanks);
+ if (keyfield->endwords < 0)
+ {
+ if (keyfield->braced)
+ end = find_braced_end (start);
+ else
+ {
+ end = start;
+ while (*end && *end != '\n')
+ end++;
+ }
+ }
+ else
+ {
+ end = (*fun) (str, keyfield->endwords, keyfield->endchars, 0);
+ if (end - str < start - str)
+ end = start;
+ }
+ *lengthptr = end - start;
+ return start;
+}
+
+/* Return a pointer to a specified place within STR,
+ skipping (from the beginning) WORDS words and then CHARS chars.
+ If IGNORE_BLANKS is nonzero, we skip all blanks
+ after finding the specified word. */
+
+char *
+find_pos (str, words, chars, ignore_blanks)
+ char *str;
+ int words, chars;
+ int ignore_blanks;
+{
+ int i;
+ char *p = str;
+
+ for (i = 0; i < words; i++)
+ {
+ char c;
+ /* Find next bunch of nonblanks and skip them. */
+ while ((c = *p) == ' ' || c == '\t')
+ p++;
+ while ((c = *p) && c != '\n' && !(c == ' ' || c == '\t'))
+ p++;
+ if (!*p || *p == '\n')
+ return p;
+ }
+
+ while (*p == ' ' || *p == '\t')
+ p++;
+
+ for (i = 0; i < chars; i++)
+ {
+ if (!*p || *p == '\n')
+ break;
+ p++;
+ }
+ return p;
+}
+
+/* Like find_pos but assumes that each field is surrounded by braces
+ and that braces within fields are balanced. */
+
+char *
+find_braced_pos (str, words, chars, ignore_blanks)
+ char *str;
+ int words, chars;
+ int ignore_blanks;
+{
+ int i;
+ int bracelevel;
+ char *p = str;
+ char c;
+
+ for (i = 0; i < words; i++)
+ {
+ bracelevel = 1;
+ while ((c = *p++) != '{' && c != '\n' && c)
+ /* Do nothing. */ ;
+ if (c != '{')
+ return p - 1;
+ while (bracelevel)
+ {
+ c = *p++;
+ if (c == '{')
+ bracelevel++;
+ if (c == '}')
+ bracelevel--;
+ if (c == 0 || c == '\n')
+ return p - 1;
+ }
+ }
+
+ while ((c = *p++) != '{' && c != '\n' && c)
+ /* Do nothing. */ ;
+
+ if (c != '{')
+ return p - 1;
+
+ if (ignore_blanks)
+ while ((c = *p) == ' ' || c == '\t')
+ p++;
+
+ for (i = 0; i < chars; i++)
+ {
+ if (!*p || *p == '\n')
+ break;
+ p++;
+ }
+ return p;
+}
+
+/* Find the end of the balanced-brace field which starts at STR.
+ The position returned is just before the closing brace. */
+
+char *
+find_braced_end (str)
+ char *str;
+{
+ int bracelevel;
+ char *p = str;
+ char c;
+
+ bracelevel = 1;
+ while (bracelevel)
+ {
+ c = *p++;
+ if (c == '{')
+ bracelevel++;
+ if (c == '}')
+ bracelevel--;
+ if (c == 0 || c == '\n')
+ return p - 1;
+ }
+ return p - 1;
+}
+
+long
+find_value (start, length)
+ char *start;
+ long length;
+{
+ while (length != 0L)
+ {
+ if (isdigit (*start))
+ return atol (start);
+ length--;
+ start++;
+ }
+ return 0l;
+}
+
+/* Vector used to translate characters for comparison.
+ This is how we make all alphanumerics follow all else,
+ and ignore case in the first sorting. */
+int char_order[256];
+
+void
+init_char_order ()
+{
+ int i;
+ for (i = 1; i < 256; i++)
+ char_order[i] = i;
+
+ for (i = '0'; i <= '9'; i++)
+ char_order[i] += 512;
+
+ for (i = 'a'; i <= 'z'; i++)
+ {
+ char_order[i] = 512 + i;
+ char_order[i + 'A' - 'a'] = 512 + i;
+ }
+}
+
+/* Compare two fields (each specified as a start pointer and a character count)
+ according to KEYFIELD.
+ The sign of the value reports the relation between the fields. */
+
+int
+compare_field (keyfield, start1, length1, pos1, start2, length2, pos2)
+ struct keyfield *keyfield;
+ char *start1;
+ long length1;
+ long pos1;
+ char *start2;
+ long length2;
+ long pos2;
+{
+ if (keyfields->positional)
+ {
+ if (pos1 > pos2)
+ return 1;
+ else
+ return -1;
+ }
+ if (keyfield->numeric)
+ {
+ long value = find_value (start1, length1) - find_value (start2, length2);
+ if (value > 0)
+ return 1;
+ if (value < 0)
+ return -1;
+ return 0;
+ }
+ else
+ {
+ char *p1 = start1;
+ char *p2 = start2;
+ char *e1 = start1 + length1;
+ char *e2 = start2 + length2;
+
+ while (1)
+ {
+ int c1, c2;
+
+ if (p1 == e1)
+ c1 = 0;
+ else
+ c1 = *p1++;
+ if (p2 == e2)
+ c2 = 0;
+ else
+ c2 = *p2++;
+
+ if (char_order[c1] != char_order[c2])
+ return char_order[c1] - char_order[c2];
+ if (!c1)
+ break;
+ }
+
+ /* Strings are equal except possibly for case. */
+ p1 = start1;
+ p2 = start2;
+ while (1)
+ {
+ int c1, c2;
+
+ if (p1 == e1)
+ c1 = 0;
+ else
+ c1 = *p1++;
+ if (p2 == e2)
+ c2 = 0;
+ else
+ c2 = *p2++;
+
+ if (c1 != c2)
+ /* Reverse sign here so upper case comes out last. */
+ return c2 - c1;
+ if (!c1)
+ break;
+ }
+
+ return 0;
+ }
+}
+
+/* A `struct linebuffer' is a structure which holds a line of text.
+ `readline' reads a line from a stream into a linebuffer
+ and works regardless of the length of the line. */
+
+struct linebuffer
+{
+ long size;
+ char *buffer;
+};
+
+/* Initialize LINEBUFFER for use. */
+
+void
+initbuffer (linebuffer)
+ struct linebuffer *linebuffer;
+{
+ linebuffer->size = 200;
+ linebuffer->buffer = (char *) xmalloc (200);
+}
+
+/* Read a line of text from STREAM into LINEBUFFER.
+ Return the length of the line. */
+
+long
+readline (linebuffer, stream)
+ struct linebuffer *linebuffer;
+ FILE *stream;
+{
+ char *buffer = linebuffer->buffer;
+ char *p = linebuffer->buffer;
+ char *end = p + linebuffer->size;
+
+ while (1)
+ {
+ int c = getc (stream);
+ if (p == end)
+ {
+ buffer = (char *) xrealloc (buffer, linebuffer->size *= 2);
+ p += buffer - linebuffer->buffer;
+ end += buffer - linebuffer->buffer;
+ linebuffer->buffer = buffer;
+ }
+ if (c < 0 || c == '\n')
+ {
+ *p = 0;
+ break;
+ }
+ *p++ = c;
+ }
+
+ return p - buffer;
+}
+
+/* Sort an input file too big to sort in core. */
+
+void
+sort_offline (infile, nfiles, total, outfile)
+ char *infile;
+ int nfiles;
+ long total;
+ char *outfile;
+{
+ /* More than enough. */
+ int ntemps = 2 * (total + MAX_IN_CORE_SORT - 1) / MAX_IN_CORE_SORT;
+ char **tempfiles = (char **) xmalloc (ntemps * sizeof (char *));
+ FILE *istream = fopen (infile, "r");
+ int i;
+ struct linebuffer lb;
+ long linelength;
+ int failure = 0;
+
+ initbuffer (&lb);
+
+ /* Read in one line of input data. */
+
+ linelength = readline (&lb, istream);
+
+ if (lb.buffer[0] != '\\' && lb.buffer[0] != '@')
+ {
+ error ("%s: not a texinfo index file", infile);
+ return;
+ }
+
+ /* Split up the input into `ntemps' temporary files, or maybe fewer,
+ and put the new files' names into `tempfiles' */
+
+ for (i = 0; i < ntemps; i++)
+ {
+ char *outname = maketempname (++tempcount);
+ FILE *ostream = fopen (outname, "w");
+ long tempsize = 0;
+
+ if (!ostream)
+ pfatal_with_name (outname);
+ tempfiles[i] = outname;
+
+ /* Copy lines into this temp file as long as it does not make file
+ "too big" or until there are no more lines. */
+
+ while (tempsize + linelength + 1 <= MAX_IN_CORE_SORT)
+ {
+ tempsize += linelength + 1;
+ fputs (lb.buffer, ostream);
+ putc ('\n', ostream);
+
+ /* Read another line of input data. */
+
+ linelength = readline (&lb, istream);
+ if (!linelength && feof (istream))
+ break;
+
+ if (lb.buffer[0] != '\\' && lb.buffer[0] != '@')
+ {
+ error ("%s: not a texinfo index file", infile);
+ failure = 1;
+ goto fail;
+ }
+ }
+ fclose (ostream);
+ if (feof (istream))
+ break;
+ }
+
+ free (lb.buffer);
+
+fail:
+ /* Record number of temp files we actually needed. */
+
+ ntemps = i;
+
+ /* Sort each tempfile into another tempfile.
+ Delete the first set of tempfiles and put the names of the second
+ into `tempfiles'. */
+
+ for (i = 0; i < ntemps; i++)
+ {
+ char *newtemp = maketempname (++tempcount);
+ sort_in_core (&tempfiles[i], MAX_IN_CORE_SORT, newtemp);
+ if (!keep_tempfiles)
+ unlink (tempfiles[i]);
+ tempfiles[i] = newtemp;
+ }
+
+ if (failure)
+ return;
+
+ /* Merge the tempfiles together and indexify. */
+
+ merge_files (tempfiles, ntemps, outfile);
+}
+
+/* Sort INFILE, whose size is TOTAL,
+ assuming that is small enough to be done in-core,
+ then indexify it and send the output to OUTFILE (or to stdout). */
+
+void
+sort_in_core (infile, total, outfile)
+ char *infile;
+ long total;
+ char *outfile;
+{
+ char **nextline;
+ char *data = (char *) xmalloc (total + 1);
+ char *file_data;
+ long file_size;
+ int i;
+ FILE *ostream = stdout;
+ struct lineinfo *lineinfo;
+
+ /* Read the contents of the file into the moby array `data'. */
+
+ int desc = open (infile, O_RDONLY, 0);
+
+ if (desc < 0)
+ fatal ("failure reopening %s", infile);
+ for (file_size = 0;;)
+ {
+ i = read (desc, data + file_size, total - file_size);
+ if (i <= 0)
+ break;
+ file_size += i;
+ }
+ file_data = data;
+ data[file_size] = 0;
+
+ close (desc);
+
+ if (file_size > 0 && data[0] != '\\' && data[0] != '@')
+ {
+ error ("%s: not a texinfo index file", infile);
+ return;
+ }
+
+ init_char_order ();
+
+ /* Sort routines want to know this address. */
+
+ text_base = data;
+
+ /* Create the array of pointers to lines, with a default size
+ frequently enough. */
+
+ nlines = total / 50;
+ if (!nlines)
+ nlines = 2;
+ linearray = (char **) xmalloc (nlines * sizeof (char *));
+
+ /* `nextline' points to the next free slot in this array.
+ `nlines' is the allocated size. */
+
+ nextline = linearray;
+
+ /* Parse the input file's data, and make entries for the lines. */
+
+ nextline = parsefile (infile, nextline, file_data, file_size);
+ if (nextline == 0)
+ {
+ error ("%s: not a texinfo index file", infile);
+ return;
+ }
+
+ /* Sort the lines. */
+
+ /* If we have enough space, find the first keyfield of each line in advance.
+ Make a `struct lineinfo' for each line, which records the keyfield
+ as well as the line, and sort them. */
+
+ lineinfo = (struct lineinfo *) malloc ((nextline - linearray) * sizeof (struct lineinfo));
+
+ if (lineinfo)
+ {
+ struct lineinfo *lp;
+ char **p;
+
+ for (lp = lineinfo, p = linearray; p != nextline; lp++, p++)
+ {
+ lp->text = *p;
+ lp->key.text = find_field (keyfields, *p, &lp->keylen);
+ if (keyfields->numeric)
+ lp->key.number = find_value (lp->key.text, lp->keylen);
+ }
+
+ qsort (lineinfo, nextline - linearray, sizeof (struct lineinfo),
+ compare_prepared);
+
+ for (lp = lineinfo, p = linearray; p != nextline; lp++, p++)
+ *p = lp->text;
+
+ free (lineinfo);
+ }
+ else
+ qsort (linearray, nextline - linearray, sizeof (char *), compare_full);
+
+ /* Open the output file. */
+
+ if (outfile)
+ {
+ ostream = fopen (outfile, "w");
+ if (!ostream)
+ pfatal_with_name (outfile);
+ }
+
+ writelines (linearray, nextline - linearray, ostream);
+ if (outfile)
+ fclose (ostream);
+
+ free (linearray);
+ free (data);
+}
+
+/* Parse an input string in core into lines.
+ DATA is the input string, and SIZE is its length.
+ Data goes in LINEARRAY starting at NEXTLINE.
+ The value returned is the first entry in LINEARRAY still unused.
+ Value 0 means input file contents are invalid. */
+
+char **
+parsefile (filename, nextline, data, size)
+ char *filename;
+ char **nextline;
+ char *data;
+ long size;
+{
+ char *p, *end;
+ char **line = nextline;
+
+ p = data;
+ end = p + size;
+ *end = 0;
+
+ while (p != end)
+ {
+ if (p[0] != '\\' && p[0] != '@')
+ return 0;
+
+ *line = p;
+ while (*p && *p != '\n')
+ p++;
+ if (p != end)
+ p++;
+
+ line++;
+ if (line == linearray + nlines)
+ {
+ char **old = linearray;
+ linearray = (char **) xrealloc (linearray, sizeof (char *) * (nlines *= 4));
+ line += linearray - old;
+ }
+ }
+
+ return line;
+}
+
+/* Indexification is a filter applied to the sorted lines
+ as they are being written to the output file.
+ Multiple entries for the same name, with different page numbers,
+ get combined into a single entry with multiple page numbers.
+ The first braced field, which is used for sorting, is discarded.
+ However, its first character is examined, folded to lower case,
+ and if it is different from that in the previous line fed to us
+ a \initial line is written with one argument, the new initial.
+
+ If an entry has four braced fields, then the second and third
+ constitute primary and secondary names.
+ In this case, each change of primary name
+ generates a \primary line which contains only the primary name,
+ and in between these are \secondary lines which contain
+ just a secondary name and page numbers. */
+
+/* The last primary name we wrote a \primary entry for.
+ If only one level of indexing is being done, this is the last name seen. */
+char *lastprimary;
+/* Length of storage allocated for lastprimary. */
+int lastprimarylength;
+
+/* Similar, for the secondary name. */
+char *lastsecondary;
+int lastsecondarylength;
+
+/* Zero if we are not in the middle of writing an entry.
+ One if we have written the beginning of an entry but have not
+ yet written any page numbers into it.
+ Greater than one if we have written the beginning of an entry
+ plus at least one page number. */
+int pending;
+
+/* The initial (for sorting purposes) of the last primary entry written.
+ When this changes, a \initial {c} line is written */
+
+char *lastinitial;
+
+int lastinitiallength;
+
+/* When we need a string of length 1 for the value of lastinitial,
+ store it here. */
+
+char lastinitial1[2];
+
+/* Initialize static storage for writing an index. */
+
+void
+init_index ()
+{
+ pending = 0;
+ lastinitial = lastinitial1;
+ lastinitial1[0] = 0;
+ lastinitial1[1] = 0;
+ lastinitiallength = 0;
+ lastprimarylength = 100;
+ lastprimary = (char *) xmalloc (lastprimarylength + 1);
+ memset (lastprimary, '\0', lastprimarylength + 1);
+ lastsecondarylength = 100;
+ lastsecondary = (char *) xmalloc (lastsecondarylength + 1);
+ memset (lastsecondary, '\0', lastsecondarylength + 1);
+}
+
+/* Indexify. Merge entries for the same name,
+ insert headers for each initial character, etc. */
+
+void
+indexify (line, ostream)
+ char *line;
+ FILE *ostream;
+{
+ char *primary, *secondary, *pagenumber;
+ int primarylength, secondarylength = 0, pagelength;
+ int nosecondary;
+ int initiallength;
+ char *initial;
+ char initial1[2];
+ register char *p;
+
+ /* First, analyze the parts of the entry fed to us this time. */
+
+ p = find_braced_pos (line, 0, 0, 0);
+ if (*p == '{')
+ {
+ initial = p;
+ /* Get length of inner pair of braces starting at `p',
+ including that inner pair of braces. */
+ initiallength = find_braced_end (p + 1) + 1 - p;
+ }
+ else
+ {
+ initial = initial1;
+ initial1[0] = *p;
+ initial1[1] = 0;
+ initiallength = 1;
+
+ if (initial1[0] >= 'a' && initial1[0] <= 'z')
+ initial1[0] -= 040;
+ }
+
+ pagenumber = find_braced_pos (line, 1, 0, 0);
+ pagelength = find_braced_end (pagenumber) - pagenumber;
+ if (pagelength == 0)
+ abort ();
+
+ primary = find_braced_pos (line, 2, 0, 0);
+ primarylength = find_braced_end (primary) - primary;
+
+ secondary = find_braced_pos (line, 3, 0, 0);
+ nosecondary = !*secondary;
+ if (!nosecondary)
+ secondarylength = find_braced_end (secondary) - secondary;
+
+ /* If the primary is different from before, make a new primary entry. */
+ if (strncmp (primary, lastprimary, primarylength))
+ {
+ /* Close off current secondary entry first, if one is open. */
+ if (pending)
+ {
+ fputs ("}\n", ostream);
+ pending = 0;
+ }
+
+ /* If this primary has a different initial, include an entry for
+ the initial. */
+ if (initiallength != lastinitiallength ||
+ strncmp (initial, lastinitial, initiallength))
+ {
+ fprintf (ostream, "\\initial {");
+ fwrite (initial, 1, initiallength, ostream);
+ fprintf (ostream, "}\n", initial);
+ if (initial == initial1)
+ {
+ lastinitial = lastinitial1;
+ *lastinitial1 = *initial1;
+ }
+ else
+ {
+ lastinitial = initial;
+ }
+ lastinitiallength = initiallength;
+ }
+
+ /* Make the entry for the primary. */
+ if (nosecondary)
+ fputs ("\\entry {", ostream);
+ else
+ fputs ("\\primary {", ostream);
+ fwrite (primary, primarylength, 1, ostream);
+ if (nosecondary)
+ {
+ fputs ("}{", ostream);
+ pending = 1;
+ }
+ else
+ fputs ("}\n", ostream);
+
+ /* Record name of most recent primary. */
+ if (lastprimarylength < primarylength)
+ {
+ lastprimarylength = primarylength + 100;
+ lastprimary = (char *) xrealloc (lastprimary,
+ 1 + lastprimarylength);
+ }
+ strncpy (lastprimary, primary, primarylength);
+ lastprimary[primarylength] = 0;
+
+ /* There is no current secondary within this primary, now. */
+ lastsecondary[0] = 0;
+ }
+
+ /* Should not have an entry with no subtopic following one with a subtopic. */
+
+ if (nosecondary && *lastsecondary)
+ error ("entry %s follows an entry with a secondary name", line);
+
+ /* Start a new secondary entry if necessary. */
+ if (!nosecondary && strncmp (secondary, lastsecondary, secondarylength))
+ {
+ if (pending)
+ {
+ fputs ("}\n", ostream);
+ pending = 0;
+ }
+
+ /* Write the entry for the secondary. */
+ fputs ("\\secondary {", ostream);
+ fwrite (secondary, secondarylength, 1, ostream);
+ fputs ("}{", ostream);
+ pending = 1;
+
+ /* Record name of most recent secondary. */
+ if (lastsecondarylength < secondarylength)
+ {
+ lastsecondarylength = secondarylength + 100;
+ lastsecondary = (char *) xrealloc (lastsecondary,
+ 1 + lastsecondarylength);
+ }
+ strncpy (lastsecondary, secondary, secondarylength);
+ lastsecondary[secondarylength] = 0;
+ }
+
+ /* Here to add one more page number to the current entry. */
+ if (pending++ != 1)
+ fputs (", ", ostream); /* Punctuate first, if this is not the first. */
+ fwrite (pagenumber, pagelength, 1, ostream);
+}
+
+/* Close out any unfinished output entry. */
+
+void
+finish_index (ostream)
+ FILE *ostream;
+{
+ if (pending)
+ fputs ("}\n", ostream);
+ free (lastprimary);
+ free (lastsecondary);
+}
+
+/* Copy the lines in the sorted order.
+ Each line is copied out of the input file it was found in. */
+
+void
+writelines (linearray, nlines, ostream)
+ char **linearray;
+ int nlines;
+ FILE *ostream;
+{
+ char **stop_line = linearray + nlines;
+ char **next_line;
+
+ init_index ();
+
+ /* Output the text of the lines, and free the buffer space. */
+
+ for (next_line = linearray; next_line != stop_line; next_line++)
+ {
+ /* If -u was specified, output the line only if distinct from previous one. */
+ if (next_line == linearray
+ /* Compare previous line with this one, using only the
+ explicitly specd keyfields. */
+ || compare_general (*(next_line - 1), *next_line, 0L, 0L, num_keyfields - 1))
+ {
+ char *p = *next_line;
+ char c;
+
+ while ((c = *p++) && c != '\n')
+ /* Do nothing. */ ;
+ *(p - 1) = 0;
+ indexify (*next_line, ostream);
+ }
+ }
+
+ finish_index (ostream);
+}
+
+/* Assume (and optionally verify) that each input file is sorted;
+ merge them and output the result.
+ Returns nonzero if any input file fails to be sorted.
+
+ This is the high-level interface that can handle an unlimited
+ number of files. */
+
+#define MAX_DIRECT_MERGE 10
+
+int
+merge_files (infiles, nfiles, outfile)
+ char **infiles;
+ int nfiles;
+ char *outfile;
+{
+ char **tempfiles;
+ int ntemps;
+ int i;
+ int value = 0;
+ int start_tempcount = tempcount;
+
+ if (nfiles <= MAX_DIRECT_MERGE)
+ return merge_direct (infiles, nfiles, outfile);
+
+ /* Merge groups of MAX_DIRECT_MERGE input files at a time,
+ making a temporary file to hold each group's result. */
+
+ ntemps = (nfiles + MAX_DIRECT_MERGE - 1) / MAX_DIRECT_MERGE;
+ tempfiles = (char **) xmalloc (ntemps * sizeof (char *));
+ for (i = 0; i < ntemps; i++)
+ {
+ int nf = MAX_DIRECT_MERGE;
+ if (i + 1 == ntemps)
+ nf = nfiles - i * MAX_DIRECT_MERGE;
+ tempfiles[i] = maketempname (++tempcount);
+ value |= merge_direct (&infiles[i * MAX_DIRECT_MERGE], nf, tempfiles[i]);
+ }
+
+ /* All temporary files that existed before are no longer needed
+ since their contents have been merged into our new tempfiles.
+ So delete them. */
+ flush_tempfiles (start_tempcount);
+
+ /* Now merge the temporary files we created. */
+
+ merge_files (tempfiles, ntemps, outfile);
+
+ free (tempfiles);
+
+ return value;
+}
+
+/* Assume (and optionally verify) that each input file is sorted;
+ merge them and output the result.
+ Returns nonzero if any input file fails to be sorted.
+
+ This version of merging will not work if the number of
+ input files gets too high. Higher level functions
+ use it only with a bounded number of input files. */
+
+int
+merge_direct (infiles, nfiles, outfile)
+ char **infiles;
+ int nfiles;
+ char *outfile;
+{
+ struct linebuffer *lb1, *lb2;
+ struct linebuffer **thisline, **prevline;
+ FILE **streams;
+ int i;
+ int nleft;
+ int lossage = 0;
+ int *file_lossage;
+ struct linebuffer *prev_out = 0;
+ FILE *ostream = stdout;
+
+ if (outfile)
+ {
+ ostream = fopen (outfile, "w");
+ }
+ if (!ostream)
+ pfatal_with_name (outfile);
+
+ init_index ();
+
+ if (nfiles == 0)
+ {
+ if (outfile)
+ fclose (ostream);
+ return 0;
+ }
+
+ /* For each file, make two line buffers.
+ Also, for each file, there is an element of `thisline'
+ which points at any time to one of the file's two buffers,
+ and an element of `prevline' which points to the other buffer.
+ `thisline' is supposed to point to the next available line from the file,
+ while `prevline' holds the last file line used,
+ which is remembered so that we can verify that the file is properly sorted. */
+
+ /* lb1 and lb2 contain one buffer each per file. */
+ lb1 = (struct linebuffer *) xmalloc (nfiles * sizeof (struct linebuffer));
+ lb2 = (struct linebuffer *) xmalloc (nfiles * sizeof (struct linebuffer));
+
+ /* thisline[i] points to the linebuffer holding the next available line in file i,
+ or is zero if there are no lines left in that file. */
+ thisline = (struct linebuffer **)
+ xmalloc (nfiles * sizeof (struct linebuffer *));
+ /* prevline[i] points to the linebuffer holding the last used line
+ from file i. This is just for verifying that file i is properly
+ sorted. */
+ prevline = (struct linebuffer **)
+ xmalloc (nfiles * sizeof (struct linebuffer *));
+ /* streams[i] holds the input stream for file i. */
+ streams = (FILE **) xmalloc (nfiles * sizeof (FILE *));
+ /* file_lossage[i] is nonzero if we already know file i is not
+ properly sorted. */
+ file_lossage = (int *) xmalloc (nfiles * sizeof (int));
+
+ /* Allocate and initialize all that storage. */
+
+ for (i = 0; i < nfiles; i++)
+ {
+ initbuffer (&lb1[i]);
+ initbuffer (&lb2[i]);
+ thisline[i] = &lb1[i];
+ prevline[i] = &lb2[i];
+ file_lossage[i] = 0;
+ streams[i] = fopen (infiles[i], "r");
+ if (!streams[i])
+ pfatal_with_name (infiles[i]);
+
+ readline (thisline[i], streams[i]);
+ }
+
+ /* Keep count of number of files not at eof. */
+ nleft = nfiles;
+
+ while (nleft)
+ {
+ struct linebuffer *best = 0;
+ struct linebuffer *exch;
+ int bestfile = -1;
+ int i;
+
+ /* Look at the next avail line of each file; choose the least one. */
+
+ for (i = 0; i < nfiles; i++)
+ {
+ if (thisline[i] &&
+ (!best ||
+ 0 < compare_general (best->buffer, thisline[i]->buffer,
+ (long) bestfile, (long) i, num_keyfields)))
+ {
+ best = thisline[i];
+ bestfile = i;
+ }
+ }
+
+ /* Output that line, unless it matches the previous one and we
+ don't want duplicates. */
+
+ if (!(prev_out &&
+ !compare_general (prev_out->buffer,
+ best->buffer, 0L, 1L, num_keyfields - 1)))
+ indexify (best->buffer, ostream);
+ prev_out = best;
+
+ /* Now make the line the previous of its file, and fetch a new
+ line from that file. */
+
+ exch = prevline[bestfile];
+ prevline[bestfile] = thisline[bestfile];
+ thisline[bestfile] = exch;
+
+ while (1)
+ {
+ /* If the file has no more, mark it empty. */
+
+ if (feof (streams[bestfile]))
+ {
+ thisline[bestfile] = 0;
+ /* Update the number of files still not empty. */
+ nleft--;
+ break;
+ }
+ readline (thisline[bestfile], streams[bestfile]);
+ if (thisline[bestfile]->buffer[0] || !feof (streams[bestfile]))
+ break;
+ }
+ }
+
+ finish_index (ostream);
+
+ /* Free all storage and close all input streams. */
+
+ for (i = 0; i < nfiles; i++)
+ {
+ fclose (streams[i]);
+ free (lb1[i].buffer);
+ free (lb2[i].buffer);
+ }
+ free (file_lossage);
+ free (lb1);
+ free (lb2);
+ free (thisline);
+ free (prevline);
+ free (streams);
+
+ if (outfile)
+ fclose (ostream);
+
+ return lossage;
+}
+
+/* Print error message and exit. */
+
+void
+fatal (format, arg)
+ char *format, *arg;
+{
+ error (format, arg);
+ exit (TI_FATAL_ERROR);
+}
+
+/* Print error message. FORMAT is printf control string, ARG is arg for it. */
+void
+error (format, arg)
+ char *format, *arg;
+{
+ printf ("%s: ", program_name);
+ printf (format, arg);
+ if (format[strlen (format) -1] != '\n')
+ printf ("\n");
+}
+
+void
+perror_with_name (name)
+ char *name;
+{
+ char *s;
+
+ s = strerror (errno);
+ printf ("%s: ", program_name);
+ printf ("%s; for file `%s'.\n", s, name);
+}
+
+void
+pfatal_with_name (name)
+ char *name;
+{
+ char *s;
+
+ s = strerror (errno);
+ printf ("%s: ", program_name);
+ printf ("%s; for file `%s'.\n", s, name);
+ exit (TI_FATAL_ERROR);
+}
+
+/* Return a newly-allocated string whose contents concatenate those of
+ S1, S2, S3. */
+
+char *
+concat (s1, s2, s3)
+ char *s1, *s2, *s3;
+{
+ int len1 = strlen (s1), len2 = strlen (s2), len3 = strlen (s3);
+ char *result = (char *) xmalloc (len1 + len2 + len3 + 1);
+
+ strcpy (result, s1);
+ strcpy (result + len1, s2);
+ strcpy (result + len1 + len2, s3);
+ *(result + len1 + len2 + len3) = 0;
+
+ return result;
+}
+
+#if !defined (HAVE_STRERROR)
+extern char *sys_errlist[];
+extern int sys_nerr;
+
+char *
+strerror (num)
+ int num;
+{
+ if (num >= sys_nerr)
+ return ("");
+ else
+ return (sys_errlist[num]);
+}
+#endif /* !HAVE_STRERROR */
+
+#if !defined (HAVE_STRCHR)
+char *
+strrchr (string, character)
+ char *string;
+ int character;
+{
+ register int i;
+
+ for (i = strlen (string) - 1; i > -1; i--)
+ if (string[i] == character)
+ return (string + i);
+
+ return ((char *)NULL);
+}
+#endif /* HAVE_STRCHR */
+
+/* Just like malloc, but kills the program in case of fatal error. */
+void *
+xmalloc (nbytes)
+ int nbytes;
+{
+ void *temp = (void *) malloc (nbytes);
+
+ if (nbytes && temp == (void *)NULL)
+ memory_error ("xmalloc", nbytes);
+
+ return (temp);
+}
+
+/* Like realloc (), but barfs if there isn't enough memory. */
+void *
+xrealloc (pointer, nbytes)
+ void *pointer;
+ int nbytes;
+{
+ void *temp;
+
+ if (!pointer)
+ temp = (void *)xmalloc (nbytes);
+ else
+ temp = (void *)realloc (pointer, nbytes);
+
+ if (nbytes && !temp)
+ memory_error ("xrealloc", nbytes);
+
+ return (temp);
+}
+
+memory_error (callers_name, bytes_wanted)
+ char *callers_name;
+ int bytes_wanted;
+{
+ char printable_string[80];
+
+ sprintf (printable_string,
+ "Virtual memory exhausted in %s ()! Needed %d bytes.",
+ callers_name, bytes_wanted);
+
+ error (printable_string);
+ abort ();
+}
+
OpenPOWER on IntegriCloud