mirror of
https://github.com/opnsense/src.git
synced 2026-05-28 04:12:45 -04:00
This commit was generated by cvs2svn to compensate for changes in r21495,
which included commits to RCS files with non-trunk default branches.
This commit is contained in:
commit
7df7ad2abd
107 changed files with 77698 additions and 0 deletions
339
contrib/texinfo/COPYING
Normal file
339
contrib/texinfo/COPYING
Normal file
|
|
@ -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.
|
||||
2346
contrib/texinfo/ChangeLog
Normal file
2346
contrib/texinfo/ChangeLog
Normal file
File diff suppressed because it is too large
Load diff
181
contrib/texinfo/INSTALL
Normal file
181
contrib/texinfo/INSTALL
Normal file
|
|
@ -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.
|
||||
|
||||
119
contrib/texinfo/INTRODUCTION
Normal file
119
contrib/texinfo/INTRODUCTION
Normal file
|
|
@ -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.
|
||||
211
contrib/texinfo/Makefile.in
Normal file
211
contrib/texinfo/Makefile.in
Normal file
|
|
@ -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:
|
||||
93
contrib/texinfo/NEWS
Normal file
93
contrib/texinfo/NEWS
Normal file
|
|
@ -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.
|
||||
163
contrib/texinfo/README
Normal file
163
contrib/texinfo/README
Normal file
|
|
@ -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.
|
||||
35
contrib/texinfo/TODO
Normal file
35
contrib/texinfo/TODO
Normal file
|
|
@ -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.
|
||||
1876
contrib/texinfo/configure
vendored
Executable file
1876
contrib/texinfo/configure
vendored
Executable file
File diff suppressed because it is too large
Load diff
42
contrib/texinfo/configure.in
Normal file
42
contrib/texinfo/configure.in
Normal file
|
|
@ -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)
|
||||
16
contrib/texinfo/dir
Normal file
16
contrib/texinfo/dir
Normal file
|
|
@ -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:
|
||||
309
contrib/texinfo/dir-example
Normal file
309
contrib/texinfo/dir-example
Normal file
|
|
@ -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.
|
||||
88
contrib/texinfo/emacs/Makefile.in
Normal file
88
contrib/texinfo/emacs/Makefile.in
Normal file
|
|
@ -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:
|
||||
|
||||
250
contrib/texinfo/emacs/detexinfo.el
Normal file
250
contrib/texinfo/emacs/detexinfo.el
Normal file
|
|
@ -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 ;;;;;;;;;;;;;;;;
|
||||
7
contrib/texinfo/emacs/elisp-comp
Executable file
7
contrib/texinfo/emacs/elisp-comp
Executable file
|
|
@ -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
|
||||
1846
contrib/texinfo/emacs/info.el
Normal file
1846
contrib/texinfo/emacs/info.el
Normal file
File diff suppressed because it is too large
Load diff
429
contrib/texinfo/emacs/informat.el
Normal file
429
contrib/texinfo/emacs/informat.el
Normal file
|
|
@ -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
|
||||
247
contrib/texinfo/emacs/makeinfo.el
Normal file
247
contrib/texinfo/emacs/makeinfo.el
Normal file
|
|
@ -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
|
||||
|
||||
180
contrib/texinfo/emacs/new-useful-setqs
Normal file
180
contrib/texinfo/emacs/new-useful-setqs
Normal file
|
|
@ -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)))
|
||||
3979
contrib/texinfo/emacs/texinfmt.el
Normal file
3979
contrib/texinfo/emacs/texinfmt.el
Normal file
File diff suppressed because it is too large
Load diff
932
contrib/texinfo/emacs/texinfo.el
Normal file
932
contrib/texinfo/emacs/texinfo.el
Normal file
|
|
@ -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
|
||||
346
contrib/texinfo/emacs/texnfo-tex.el
Normal file
346
contrib/texinfo/emacs/texnfo-tex.el
Normal file
|
|
@ -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 ;;;;;;;;;;;;;;;;
|
||||
2058
contrib/texinfo/emacs/texnfo-upd.el
Normal file
2058
contrib/texinfo/emacs/texnfo-upd.el
Normal file
File diff suppressed because it is too large
Load diff
227
contrib/texinfo/info/Makefile.in
Normal file
227
contrib/texinfo/info/Makefile.in
Normal file
|
|
@ -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
|
||||
200
contrib/texinfo/info/NEWS
Normal file
200
contrib/texinfo/info/NEWS
Normal file
|
|
@ -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.
|
||||
|
||||
37
contrib/texinfo/info/README
Normal file
37
contrib/texinfo/info/README
Normal file
|
|
@ -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>
|
||||
112
contrib/texinfo/info/clib.c
Normal file
112
contrib/texinfo/info/clib.c
Normal file
|
|
@ -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 */
|
||||
|
||||
42
contrib/texinfo/info/clib.h
Normal file
42
contrib/texinfo/info/clib.h
Normal file
|
|
@ -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_ */
|
||||
|
||||
|
||||
273
contrib/texinfo/info/dir.c
Normal file
273
contrib/texinfo/info/dir.c
Normal file
|
|
@ -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;
|
||||
}
|
||||
561
contrib/texinfo/info/display.c
Normal file
561
contrib/texinfo/info/display.c
Normal file
|
|
@ -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);
|
||||
}
|
||||
76
contrib/texinfo/info/display.h
Normal file
76
contrib/texinfo/info/display.h
Normal file
|
|
@ -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_ */
|
||||
58
contrib/texinfo/info/doc.h
Normal file
58
contrib/texinfo/info/doc.h
Normal file
|
|
@ -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_ */
|
||||
5
contrib/texinfo/info/dribble
Normal file
5
contrib/texinfo/info/dribble
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
mfoo
|
||||
em
|
||||
buffers
|
||||
|
||||
ââ
|
||||
71
contrib/texinfo/info/dribble.c
Normal file
71
contrib/texinfo/info/dribble.c
Normal file
|
|
@ -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);
|
||||
}
|
||||
41
contrib/texinfo/info/dribble.h
Normal file
41
contrib/texinfo/info/dribble.h
Normal file
|
|
@ -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_ */
|
||||
1508
contrib/texinfo/info/echo_area.c
Normal file
1508
contrib/texinfo/info/echo_area.c
Normal file
File diff suppressed because it is too large
Load diff
63
contrib/texinfo/info/echo_area.h
Normal file
63
contrib/texinfo/info/echo_area.h
Normal file
|
|
@ -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_ */
|
||||
617
contrib/texinfo/info/filesys.c
Normal file
617
contrib/texinfo/info/filesys.c
Normal file
|
|
@ -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);
|
||||
}
|
||||
|
||||
84
contrib/texinfo/info/filesys.h
Normal file
84
contrib/texinfo/info/filesys.h
Normal file
|
|
@ -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_ */
|
||||
265
contrib/texinfo/info/footnotes.c
Normal file
265
contrib/texinfo/info/footnotes.c
Normal file
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
46
contrib/texinfo/info/footnotes.h
Normal file
46
contrib/texinfo/info/footnotes.h
Normal file
|
|
@ -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_ */
|
||||
|
||||
95
contrib/texinfo/info/gc.c
Normal file
95
contrib/texinfo/info/gc.c
Normal file
|
|
@ -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;
|
||||
}
|
||||
36
contrib/texinfo/info/gc.h
Normal file
36
contrib/texinfo/info/gc.h
Normal file
|
|
@ -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_ */
|
||||
94
contrib/texinfo/info/general.h
Normal file
94
contrib/texinfo/info/general.h
Normal file
|
|
@ -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_ */
|
||||
667
contrib/texinfo/info/indices.c
Normal file
667
contrib/texinfo/info/indices.c
Normal file
|
|
@ -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 ();
|
||||
}
|
||||
|
||||
39
contrib/texinfo/info/indices.h
Normal file
39
contrib/texinfo/info/indices.h
Normal file
|
|
@ -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_ */
|
||||
1365
contrib/texinfo/info/info-stnd.texi
Normal file
1365
contrib/texinfo/info/info-stnd.texi
Normal file
File diff suppressed because it is too large
Load diff
672
contrib/texinfo/info/info-utils.c
Normal file
672
contrib/texinfo/info/info-utils.c
Normal file
|
|
@ -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);
|
||||
}
|
||||
140
contrib/texinfo/info/info-utils.h
Normal file
140
contrib/texinfo/info/info-utils.h
Normal file
|
|
@ -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_ */
|
||||
229
contrib/texinfo/info/info.1
Normal file
229
contrib/texinfo/info/info.1
Normal file
|
|
@ -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
|
||||
565
contrib/texinfo/info/info.c
Normal file
565
contrib/texinfo/info/info.c
Normal file
|
|
@ -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);
|
||||
}
|
||||
100
contrib/texinfo/info/info.h
Normal file
100
contrib/texinfo/info/info.h
Normal file
|
|
@ -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_ */
|
||||
|
||||
916
contrib/texinfo/info/info.texi
Normal file
916
contrib/texinfo/info/info.texi
Normal file
|
|
@ -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
|
||||
771
contrib/texinfo/info/infodoc.c
Normal file
771
contrib/texinfo/info/infodoc.c
Normal file
|
|
@ -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);
|
||||
}
|
||||
274
contrib/texinfo/info/infomap.c
Normal file
274
contrib/texinfo/info/infomap.c
Normal file
|
|
@ -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;
|
||||
|
||||
82
contrib/texinfo/info/infomap.h
Normal file
82
contrib/texinfo/info/infomap.h
Normal file
|
|
@ -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_ */
|
||||
195
contrib/texinfo/info/m-x.c
Normal file
195
contrib/texinfo/info/m-x.c
Normal file
|
|
@ -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);
|
||||
}
|
||||
481
contrib/texinfo/info/makedoc.c
Normal file
481
contrib/texinfo/info/makedoc.c
Normal file
|
|
@ -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);
|
||||
}
|
||||
|
||||
643
contrib/texinfo/info/man.c
Normal file
643
contrib/texinfo/info/man.c
Normal file
|
|
@ -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);
|
||||
}
|
||||
36
contrib/texinfo/info/man.h
Normal file
36
contrib/texinfo/info/man.h
Normal file
|
|
@ -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_ */
|
||||
329
contrib/texinfo/info/nodemenu.c
Normal file
329
contrib/texinfo/info/nodemenu.c
Normal file
|
|
@ -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 ();
|
||||
}
|
||||
1207
contrib/texinfo/info/nodes.c
Normal file
1207
contrib/texinfo/info/nodes.c
Normal file
File diff suppressed because it is too large
Load diff
168
contrib/texinfo/info/nodes.h
Normal file
168
contrib/texinfo/info/nodes.h
Normal file
|
|
@ -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_ */
|
||||
519
contrib/texinfo/info/search.c
Normal file
519
contrib/texinfo/info/search.c
Normal file
|
|
@ -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);
|
||||
}
|
||||
75
contrib/texinfo/info/search.h
Normal file
75
contrib/texinfo/info/search.h
Normal file
|
|
@ -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_ */
|
||||
|
||||
4263
contrib/texinfo/info/session.c
Normal file
4263
contrib/texinfo/info/session.c
Normal file
File diff suppressed because it is too large
Load diff
146
contrib/texinfo/info/session.h
Normal file
146
contrib/texinfo/info/session.h
Normal file
|
|
@ -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_ */
|
||||
173
contrib/texinfo/info/signals.c
Normal file
173
contrib/texinfo/info/signals.c
Normal file
|
|
@ -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 */
|
||||
}
|
||||
}
|
||||
89
contrib/texinfo/info/signals.h
Normal file
89
contrib/texinfo/info/signals.h
Normal file
|
|
@ -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_ */
|
||||
76
contrib/texinfo/info/termdep.h
Normal file
76
contrib/texinfo/info/termdep.h
Normal file
|
|
@ -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_ */
|
||||
769
contrib/texinfo/info/terminal.c
Normal file
769
contrib/texinfo/info/terminal.c
Normal file
|
|
@ -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 ();
|
||||
}
|
||||
|
||||
129
contrib/texinfo/info/terminal.h
Normal file
129
contrib/texinfo/info/terminal.h
Normal file
|
|
@ -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_ */
|
||||
376
contrib/texinfo/info/tilde.c
Normal file
376
contrib/texinfo/info/tilde.c
Normal file
|
|
@ -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 */
|
||||
|
||||
58
contrib/texinfo/info/tilde.h
Normal file
58
contrib/texinfo/info/tilde.h
Normal file
|
|
@ -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 ();
|
||||
|
||||
1270
contrib/texinfo/info/userdoc.texi
Normal file
1270
contrib/texinfo/info/userdoc.texi
Normal file
File diff suppressed because it is too large
Load diff
272
contrib/texinfo/info/variables.c
Normal file
272
contrib/texinfo/info/variables.c
Normal file
|
|
@ -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);
|
||||
}
|
||||
64
contrib/texinfo/info/variables.h
Normal file
64
contrib/texinfo/info/variables.h
Normal file
|
|
@ -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_ */
|
||||
1482
contrib/texinfo/info/window.c
Normal file
1482
contrib/texinfo/info/window.c
Normal file
File diff suppressed because it is too large
Load diff
229
contrib/texinfo/info/window.h
Normal file
229
contrib/texinfo/info/window.h
Normal file
|
|
@ -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_ */
|
||||
80
contrib/texinfo/info/xmalloc.c
Normal file
80
contrib/texinfo/info/xmalloc.c
Normal file
|
|
@ -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 */
|
||||
250
contrib/texinfo/install-sh
Executable file
250
contrib/texinfo/install-sh
Executable file
|
|
@ -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
|
||||
82
contrib/texinfo/libtxi/Makefile.in
Normal file
82
contrib/texinfo/libtxi/Makefile.in
Normal file
|
|
@ -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:
|
||||
504
contrib/texinfo/libtxi/alloca.c
Normal file
504
contrib/texinfo/libtxi/alloca.c
Normal file
|
|
@ -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 */
|
||||
44
contrib/texinfo/libtxi/bzero.c
Normal file
44
contrib/texinfo/libtxi/bzero.c
Normal file
|
|
@ -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 */
|
||||
762
contrib/texinfo/libtxi/getopt.c
Normal file
762
contrib/texinfo/libtxi/getopt.c
Normal file
|
|
@ -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 */
|
||||
129
contrib/texinfo/libtxi/getopt.h
Normal file
129
contrib/texinfo/libtxi/getopt.h
Normal file
|
|
@ -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 */
|
||||
180
contrib/texinfo/libtxi/getopt1.c
Normal file
180
contrib/texinfo/libtxi/getopt1.c
Normal file
|
|
@ -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 */
|
||||
20
contrib/texinfo/libtxi/memcpy.c
Normal file
20
contrib/texinfo/libtxi/memcpy.c
Normal file
|
|
@ -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;
|
||||
}
|
||||
24
contrib/texinfo/libtxi/memmove.c
Normal file
24
contrib/texinfo/libtxi/memmove.c
Normal file
|
|
@ -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++;
|
||||
}
|
||||
43
contrib/texinfo/libtxi/strdup.c
Normal file
43
contrib/texinfo/libtxi/strdup.c
Normal file
|
|
@ -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;
|
||||
}
|
||||
112
contrib/texinfo/makeinfo/Makefile.in
Normal file
112
contrib/texinfo/makeinfo/Makefile.in
Normal file
|
|
@ -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:
|
||||
177
contrib/texinfo/makeinfo/macro.texi
Normal file
177
contrib/texinfo/makeinfo/macro.texi
Normal file
|
|
@ -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
|
||||
|
||||
|
||||
9349
contrib/texinfo/makeinfo/makeinfo.c
Normal file
9349
contrib/texinfo/makeinfo/makeinfo.c
Normal file
File diff suppressed because it is too large
Load diff
193
contrib/texinfo/makeinfo/makeinfo.h
Normal file
193
contrib/texinfo/makeinfo/makeinfo.h
Normal file
|
|
@ -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 */
|
||||
303
contrib/texinfo/makeinfo/makeinfo.texi
Normal file
303
contrib/texinfo/makeinfo/makeinfo.texi
Normal file
|
|
@ -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
|
||||
418
contrib/texinfo/makeinfo/multi.c
Normal file
418
contrib/texinfo/makeinfo/multi.c
Normal file
|
|
@ -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
|
||||
}
|
||||
4692
contrib/texinfo/texinfo.tex
Normal file
4692
contrib/texinfo/texinfo.tex
Normal file
File diff suppressed because it is too large
Load diff
16886
contrib/texinfo/texinfo.texi
Normal file
16886
contrib/texinfo/texinfo.texi
Normal file
File diff suppressed because it is too large
Load diff
101
contrib/texinfo/util/Makefile.in
Normal file
101
contrib/texinfo/util/Makefile.in
Normal file
|
|
@ -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:
|
||||
238
contrib/texinfo/util/deref.c
Normal file
238
contrib/texinfo/util/deref.c
Normal file
|
|
@ -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;
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue