Virgin import of GNU texinfo 4.0

This commit is contained in:
Ruslan Ermilov 2000-01-17 10:39:58 +00:00
parent d8b5c7ed06
commit cab79d6646
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/vendor/texinfo/dist/; revision=56160
89 changed files with 24258 additions and 11856 deletions

View File

@ -1,3 +1,3 @@
Richard Stallman, Brian Fox, Bob Chassell, Noah Friedman, Paul Rubin,
Karl Berry, and no doubt many others.
Karl Berry, Eli Zaretskii, and many others.

File diff suppressed because it is too large Load Diff

View File

@ -48,18 +48,6 @@ 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
==========================
@ -90,13 +78,10 @@ program is not part of this distribution, but is available separately.
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)
$ (cd doc; make 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).
You can then print the resulting .dvi files with the `lpr' or `lp'
commands, or maybe `dvips'.
For example, the command to print the texinfo.dvi file might be:

View File

@ -1,11 +1,113 @@
This file records noteworthy changes.
4.0 (28 September 1999)
* Language:
. New command @anchor for cross references to arbitrary points.
. New commands @documentlanguage sets the main document language,
and @documentencoding sets the document input encoding (although not
much is done yet with either).
. New command @pagesizes allows limited control of text area for typesetting.
. New command @acronym for abbreviations in all caps, such as `NASA'.
. New command @alias for simple command aliases.
. New command @definfoenclose for better control of info output.
. New commands @deftypeivar for typed instance variables of a class
and @deftypeop for typed operations of a class.
. New command @novalidate suppresses cross-reference checking and (in
TeX) auxiliary file creation.
. New commands @setcontentsaftertitlepage and
@setshortcontentsaftertitlepage to force printing the table of
contents after @end titlepage. Also, @contents and @shortcontents
themselves can now appear at the beginning of the document as
well as the end.
. New markup commands: @env (for environment variables), @command (for
command names), @option (for command-line options).
. New commands @smallformat and @smalldisplay, a la @smallexample.
. New command @exampleindent to set indentation of example-like
environments a la @paragraphindent.
. @uref takes an optional third argument of text to show instead of
(rather than in addition to) the url for info and dvi output.
. @footnote works in an @item for a @table.
* texinfo.tex:
. latest version always at ftp://ftp.gnu.org/gnu/texinfo.tex (and mirrors).
. implements @macro.
. implements @paragraphindent (except asis).
. @emph and @i use true italic type (cmti) instead of slanted (cmsl).
. implements pdf output when run with pdftex.
. better support for internationalization via txi-??.tex files.
* makeinfo:
. supports HTML output with the --html option.
. implication of --html: @top nodes should be wrapped in @ifnottex
rather than @ifinfo. @ifinfo conditionals are not expanded with --html.
. new option --number-sections to output chapter/section numbers.
. dashes and quotes are not treated specially in node names.
. new option --commands-in-node-names to allow @-commands in node names.
(Not implemented in TeX, and most likely never will be.)
. @emph output uses _underscores_.
. @image looks for .png files before .jpg.
. only output `Making ... file' line when verbose.
. allow -v as synonym for --verbose.
. new command line options to specify which conditionals to process
(but --iftex is not fully implemented).
. warns if @var contains any of ,[]().
. @quote-arg implicitly done for all one-argument macros, so commas in
the argument text are allowed.
. \\ required in macro body to get single \, no other `escapes' defined.
* info:
. ISO Latin 1 characters are displayed and input as-is by default.
. new option --vi-keys to enable vi-like and less-like key bindings.
. new command S does case-sensitive searching.
. new commands C-x n and C-x N repeat last search, respectively, in the
same and in reverse direction, without prompting for the string. These
commands are bound to n and N under --vi-keys, like in Less.
. new command G menu1 menu2 ... searches for menu items from (dir),
as allowed on the command line.
. new command O (capital o, not zero) goes directly to the node that
describes command-line options.
. new command-line option --show-options causes the node which
describes command-line options to be the first node displayed.
. M-prior and M-DEL do new command info-scroll-other-window-backward.
. / searches like s does.
. If the search string includes upper-case letters, in both incremental
and non-incremental search, the search is case-sensitive.
. S searches case-sensitively even if the search string is all
lower-case.
. - makes the argument negative (so e.g. `- /' searches backward).
. l restores point in the window returned to.
. SPC/DEL do not move outside the current document.
. foo.info is found before foo.
. `info foo --index-search=bar' now searches for bar in foo's index.
. support for files compressed with bzip2.
* install-info:
. handles gzipped dir files.
. sort entries into alphabetical order.
. install direntries only in preceding dircategory, not in all.
. --delete does not require the info file to exist.
. --delete can handle XEmacs-style dir entries.
* texi2dvi:
. bug fixed: now uses only the @iftex and @tex parts of the source.
. process LaTeX source as well as Texinfo source.
. output PDF (using pdftex) with new option --pdf.
. handles --OPTION=ARG style of command line arguments.
. new option --batch for progress reports but no interaction.
. new option --clean to remove all auxiliary files.
. new option --quiet for silence (unless there are errors).
. new option -I for specifying directories for @include to search.
. handles LaTeX files (running BibTeX etc.).
* Fixes to util/gen-dir-node and util/fix-info-dir (formerly util/update-info).
* Distribution:
. Man pages included.
. Czech and Norwegian message translations.
. Various translations for texinfo.tex fixed words included.
. DJGPP support.
3.12 (3 March 1998)
* Elisp files removed, since they are only usefully distributed with Emacs.
* Restore inclusion of compile-time $(infodir) to INFOPATH.
* install-info creates a proper dir file.
* Various portability fixes.
3.11 (31 July 1997)
* New commands:
- @uref to make a reference to a url; @url now only indicates such.
@ -40,6 +142,7 @@ This file records noteworthy changes.
3.10 (nonexistent)
3.9 (4 October 1996)
* makeinfo:
- Give a suppressible (with --no-validate) error for references
@ -52,6 +155,7 @@ This file records noteworthy changes.
* 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
@ -93,46 +197,55 @@ This file records noteworthy changes.
@infoinclude
@iappendix @iappendixsection @iappendixsec @iappendixsubsec
@iappendixsubsubsec
@ichapter @isection @isubsection @isubsubsection
@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.
Just bug fixes, see ChangeLog for full details.
texinfo-3.0: first release of Texinfo version 2, with many new commands.
3.0: first release of Texinfo version 2, with many new commands.
Here is the separate NEWS for old releases of Info:
Version 2.11, Sat Apr 1 09:15:21 1995
@ -332,4 +445,3 @@ Changes since 2.0:
* Scrolling in redisplay is implemented.
* Recursive uses of the echo area made more robust.
* Garbage collection of unreferenced nodes.

View File

@ -1,48 +1,82 @@
This is the README file for the GNU Texinfo distribution.
The primary distribution point is ftp://ftp.gnu.org/pub/gnu.
The primary distribution point is ftp://ftp.gnu.org/gnu/texinfo/.
Please email bugs or suggestions to bug-texinfo@gnu.org. (If you wish,
you can join this list by sending a subscribe message to
bug-texinfo-request@gnu.org.) Patches are welcome; if possible, please
make them with diff -c and include ChangeLog entries.
Mailing lists:
- bug-texinfo@gnu.org for bug reports or enhancement suggestions,
archived at ftp://ftp-mailing-list-archives.gnu.org/.
- help-texinfo@gnu.org for authoring questions and general discussion.
archived at the same place.
- texinfo-pretest@tug.org for pretests of new releases,
archived at http://tug.org/archives/texinfo-pretest/.
There are as yet no corresponding newsgroups.
For bug reports, please include enough information for the maintainers
to reproduce the problem. Generally speaking, that means:
- the version number of Texinfo and the program(s) involved (use --version).
- hardware, operating system, and compiler versions (uname -a).
- any unusual options you gave to configure (see config.status).
- the contents of any input files necessary to reproduce the bug (crucial!).
- a description of the problem and any samples of the erroneous output.
- anything else that you think would be helpful.
Patches are most welcome; if possible, please make them with diff -c and
include ChangeLog entries.
When sending email, please do not encode or split the messages in any
way if at all possible; it's much easier to deal with one large message
than many small ones. GNU shar is a convenient way of packaging
multiple and/or binary files for email.
Programs within this distribution have their own version numbers. When
you refer to a file, please mention its own version, as well as the
version number of the Texinfo distribution.
For generic installation instructions on compiling and installing this
Automake-based distribution, please read the file `INSTALL'.
Installation notes specific to Texinfo:
* The Info tree uses a file `dir' as its root node; the `dir-example'
file in this distribution is included for informative purposes.
Use it, modify it, or ignore it just as you like.
* The Info tree uses a file `dir' as its root node; the `dir-example'
file in this distribution is included as a possible starting point.
Use it, modify it, or ignore it just as you like.
* You can create a file texinfo.cnf to be read by TeX when
processing Texinfo manuals. For example, it might contain the
command @afourpaper. See the `Preparing for TeX' node in
texinfo.texi for more details.
* You can create a file texinfo.cnf to be read by TeX when
processing Texinfo manuals. For example, you might like to use
@afourpaper by default. See the `Preparing for TeX' node in
texinfo.txi for more details. You don't have to create the file if
you have nothing to put in it.
* If your info files are not in $prefix/info, you may wish to add a line
#define DEFAULT_INFOPATH "/mydir1:/mydir2:/etc"
to config.h after running configure.
* If your info files are not in $prefix/info, you may wish to add a line
#define DEFAULT_INFOPATH "/mydir1:/mydir2:..."
to config.h after running configure.
* For instructions on compiling this distribution with DJGPP tools
for MS-DOS and MS-Windows, please see the file djgpp/README.
This distribution includes (but is not limited to) the following files:
If you would like to contribute to the GNU project by implementing
additional documentation output formats for Texinfo, that would be
great. But please do not write a separate translator texi2foo for your
favorite format foo! That is the hard way to do the job, and makes
extra work in subsequent maintenance, since the Texinfo language is
continually being enhanced and updated. Instead, the best approach is
modify Makeinfo to generate the new format, as it does now for Info and HTML.
This distribution includes the following files, among others:
README This file.
NEWS Summary of new features by release.
INTRODUCTION Brief introduction to the system, and
how to create readable files from the
Texinfo source files in this distribution.
Texinfo source files (in ./doc):
texinfo.texi This manual describes the Texinfo language
and many of the associated tools. It
tells how to use Texinfo to write
documentation, how to use Texinfo mode
in GNU Emacs, TeX, makeinfo, and the
Emacs Lisp Texinfo formatting commands.
texinfo.txi Describes the Texinfo language and many
of the associated tools. It tells how
to use Texinfo to write documentation,
how to use Texinfo mode in GNU Emacs,
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
@ -72,26 +106,20 @@ Printing related files:
util/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.
TeX and texindex.
Source files for standalone C programs (./lib, ./makeinfo, ./info):
makeinfo.c This file contains the source for
makeinfo/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
info/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
Installation files:
configure This file creates creates a Makefile
@ -110,11 +138,7 @@ Installation files:
to use to make a Makefile.in.
Other files (util):
NEWS This contains a summary of new
features since the first edition
of Texinfo.
Other files:
fixfonts This is a shell script to install the
`lcircle10' TeX fonts as an alias for

View File

@ -1,8 +1,8 @@
If you are interested in working on any of these, email bug-texinfo@gnu.org.
* Makeinfo:
- HTML output is being actively worked on, and with luck will be in
the next release.
- Support output of Docbook format and SGML-Tools format.
- Support output of true 8-bit characters from accent commands, etc.
- 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.
@ -13,23 +13,27 @@ If you are interested in working on any of these, email bug-texinfo@gnu.org.
chapter/section references. See:
ftp://ftp.simtel.net/pub/simtelnet/gnu/djgpp/v2/faq201s.zip
- Call Ghostscript to get ASCII output for the @image command.
- Better HTML output: allow settable background color, table colors
and spacing, <head> meta tags, back link from footnote marker, etc.
- Could warn if @sc{TEXT} for all-caps TEXT, since it's a no-op.
* TeX:
- Use @ as the escape character, and Texinfo syntax generally, in the
table of contents, aux, and index files. Eliminate all the crazy
multiple redefinitions of every Texinfo command in different contexts.
- Handle @hsep and @vsep in @multitables.
- Introduce new command to change \bindingoffset.
- How about using latex2html to produce HTML?
* General:
- Better i18n support, including support for 8-bit input characters,
and 8-bit output in info. Perhaps have to use the ec fonts.
- Support compressed image files, automatic generation of .txt
or .jpg from .eps by Ghostscript.
- Repeat TeX run until cross-references stabilize, not just twice.
(Document this in manual and fix texi2dvi.)
- Handle reference card creation, perhaps by only paying attention to
sectioning and @def... commands.
- Allow : in node names for info files, for names like `class::method'.
- Allow @end (and other?) commands to be indented in the source.
- Get Info declared as a MIME Content-Type.
* Language:
@ -41,15 +45,18 @@ If you are interested in working on any of these, email bug-texinfo@gnu.org.
@caption ... @end caption
<arbitrary Texinfo commands>
@end figure
- support bibliographies with BibTeX (see web2c/doc for kludge prototype).
- @flushboth to combine @flushleft and @flushright, for RFC's.
- @part sectioning command.
- Anchors a la HTML?
- Allow subitems and `see' and `see also' in indices.
- @verbatim ... @end verbatim.
- @exercise/@answer command for, e.g., gawk.
- Allow @hsep/@vsep at @item, instead of just in template.
- The dark corner symbol for the gawk manual.
- Support automatic line numbering of examples.
- Change bars. This is difficult or impossible in TeX,
unfortunately. To do it right requires device driver support.
wdiff or ediff may be better in some cases, anyway.
* Doc:
- Include a complete functional summary, as in a reference card, in
@ -59,20 +66,29 @@ If you are interested in working on any of these, email bug-texinfo@gnu.org.
for an example of doing it in both the tex and info versions.
* Info:
- Regular expression search.
- Allow key rebinding, perhaps through the readline library.
- Full-text search across all info files installed on the system.
- Support character sets other than ISO Latin 1.
- Perhaps comply with LANGUAGE setting on a per-node basis, to allow
incremental translation of Texinfo files.
- Search all nodes of dir file at startup, then can have
INFO-DIR-SEPARATE-GROUPS and other such.
- Better dir file merging.
- Steal interface ideas from Lynx: TAB for navigating to next link
within a page, number links, etc.
within a page, number links, use color, etc. Perhaps code from the pinfo
viewer can be reused: http://zeus.polsl.gliwice.pl/~pborys/.
- q within help should quit help like C-x 0.
- Full-text search on all available info files.
- Incorporate an X-based viewer, perhaps tkinfo:
http://www.math.ucsb.edu/~boldt/tkinfo/.
- Incorporate an X-based viewer, perhaps tkinfo
http://www.math.ucsb.edu/~boldt/tkinfo/
or saxinfo.
- Perhaps process Texinfo files directly instead of converting to Info:
ftp://ftp.cs.berkeley.edu/ucb/people/phelps/tcltk/tkman.tar.Z
+ ftp://ftp.cs.berkeley.edu/ucb/people/phelps/tcltk/rman.tar.Z
+ Tcl/Tk 8.0 from ftp.smli.com in the /pub/tcl directory.
From: phelps@ecstasy.CS.Berkeley.EDU (Tom Phelps)
(But this has the disadvantage of needing to be updated when the
Texinfo language changes, so don't.)
* Install-info:
- be able to copy the info file to compile-time $(infodir), to

View File

@ -1,6 +1,7 @@
/* config.h.in. Generated automatically from configure.in by autoheader. */
/* config.in. Generated automatically from configure.in by autoheader. */
/* acconfig.h
This file is in the public domain.
$Id: acconfig.h,v 1.3 1998/12/06 22:04:03 karl Exp $
Descriptive text for the C preprocessor macros that
the distributed Autoconf macros can define.
@ -38,6 +39,9 @@
/* Define if you have a working `mmap' system call. */
#undef HAVE_MMAP
/* Define if you have the strcoll function and it is properly defined. */
#undef HAVE_STRCOLL
/* Define if you have the vprintf function. */
#undef HAVE_VPRINTF
@ -77,6 +81,9 @@
*/
#undef STACK_DIRECTION
/* Define if the `S_IS*' macros in <sys/stat.h> do not work properly. */
#undef STAT_MACROS_BROKEN
/* Define if you have the ANSI C header files. */
#undef STDC_HEADERS
@ -98,12 +105,6 @@
/* Define as 1 if you have the stpcpy function. */
#undef HAVE_STPCPY
/* Define to the name of the distribution. */
#undef PACKAGE
/* Define to the version of the distribution. */
#undef VERSION
/* Define if you have the __argz_count function. */
#undef HAVE___ARGZ_COUNT
@ -170,6 +171,9 @@
/* Define if you have the strerror function. */
#undef HAVE_STRERROR
/* Define if you have the strncasecmp function. */
#undef HAVE_STRNCASECMP
/* Define if you have the <argz.h> header file. */
#undef HAVE_ARGZ_H
@ -185,6 +189,9 @@
/* Define if you have the <malloc.h> header file. */
#undef HAVE_MALLOC_H
/* Define if you have the <memory.h> header file. */
#undef HAVE_MEMORY_H
/* Define if you have the <ncurses/termcap.h> header file. */
#undef HAVE_NCURSES_TERMCAP_H
@ -194,6 +201,9 @@
/* Define if you have the <pwd.h> header file. */
#undef HAVE_PWD_H
/* Define if you have the <stdlib.h> header file. */
#undef HAVE_STDLIB_H
/* Define if you have the <string.h> header file. */
#undef HAVE_STRING_H
@ -233,22 +243,33 @@
/* Define if you have the <unistd.h> header file. */
#undef HAVE_UNISTD_H
/* Define if you have the <values.h> header file. */
#undef HAVE_VALUES_H
/* Define if you have the bsd library (-lbsd). */
#undef HAVE_LIBBSD
/* Define if you have the i library (-li). */
#undef HAVE_LIBI
/* Define if you have the z library (-lz). */
#undef HAVE_LIBZ
/* Name of package */
#undef PACKAGE
/* Version number of package */
#undef VERSION
/* Define if TIOCGWINSZ requires sys/ioctl.h */
#undef GWINSZ_IN_SYS_IOCTL
/* Define if this function is declared. */
#undef HAVE_DECL_STRERROR
/* Define if this function is declared. */
#undef HAVE_DECL_STRCASECMP
/* Define if this function is declared. */
#undef HAVE_DECL_STRNCASECMP
/* Define if this function is declared. */
#undef HAVE_DECL_STRCOLL
/* For gettext (NLS) */
#include <libintl.h>
#define _(String) gettext (String)
#define N_(String) (String)
/* Leave that blank line there!! Autoheader needs it.

View File

@ -1,22 +1,30 @@
This directory contains documentation on the Texinfo system and the TeX
sources needed to process Texinfo sources. (Use texi2dvi to run a
Texinfo manual through TeX to produce a DVI file.)
sources needed to process Texinfo sources. We recommend using the
texi2dvi included in the distribution to run a Texinfo manual through
TeX to produce a DVI file.
The .tex files are not installed automatically because TeX installations
vary so widely. Installing them in the wrong place would give a false
sense of security. So, you should simply cp *.tex to the appropriate
place. If your installation follows the TeX Directory Structure
standard (http://www.tug.org/tds/), this will be the directory
standard (http://tug.org/tds/), this will be the directory
<texmf>/tex/texinfo/ for texinfo.tex and <texmf>/tex/plain/dvips/ for
epsf.tex. If you use the default installation paths, <texmf> will be
/usr/local/share/texmf. If you have teTeX, you can find <texmf> by
running:
texconfig confall | grep \^TEXMF=
(The configure script tries to do this for you.)
/usr/local/share/texmf. On systems with TeX preinstalled, as most
GNU/Linux distributions offer, <texmf> will often be something like
/usr/share/texmf.
It is also possible to put these .tex files in a `local' place instead
of overwriting existing ones, but it is more complicated. See your TeX
documentation in general and the texmf.cnf file in particular for information.
If you add files to your TeX installations, not just replace existing
ones, you very likely have to update your ls-R file; do this with the
mktexlsr command. In older versions, this was named MakeTeXls-R.
You can get the latest texinfo.tex from
ftp://ftp.tug.org/tex/texinfo.tex
ftp://ftp.cs.umb.edu/pub/tex/texinfo.tex
ftp://ftp.gnu.org/gnu/texinfo.tex (and all GNU mirrors)
ftp://tug.org/tex/texinfo.tex (and all CTAN mirrors)
or on the FSF machines in /home/gd/gnu/doc/texinfo.tex.
If you have problems with the version in this distribution, please check
for a newer version.

401
contrib/texinfo/doc/help2man Executable file
View File

@ -0,0 +1,401 @@
#!/usr/local/bin/perl -w
# Generate a short man page from --help and --version output.
# Copyright © 1997, 98, 99 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 Brendan O'Dea <bod@compusol.com.au>
use 5.004;
use strict;
use Getopt::Long;
use Text::Tabs qw(expand);
use POSIX qw(strftime setlocale LC_TIME);
my $this_program = 'help2man';
my $this_version = '1.013';
my $version_info = <<EOT;
$this_program $this_version
Copyright (C) 1997, 98, 99 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Written by Brendan O'Dea <bod\@compusol.com.au>
EOT
my $help_info = <<EOT;
`$this_program' generates a man page out of `--help' and `--version' output.
Usage: $this_program [OPTION]... EXECUTABLE
-n, --name=STRING use `STRING' as the description for the NAME paragraph
-s, --section=SECTION use `SECTION' as the section for the man page
-i, --include=FILE include material from `FILE'
-I, --opt-include=FILE include material from `FILE' if it exists
-o, --output=FILE send output to `FILE'
-N, --no-info suppress pointer to Texinfo manual
--help print this help, then exit
--version print $this_program program version number, then exit
EXECUTABLE should accept `--help' and `--version' options.
EOT
my $section = 1;
my ($include, $opt_name, $opt_include, $opt_output, $opt_no_info);
# Parse options.
Getopt::Long::config('bundling');
GetOptions (
'n|name=s' => \$opt_name,
's|section=s' => \$section,
'i|include=s' => \$include,
'I|opt-include=s' => \$opt_include,
'o|output=s' => \$opt_output,
'N|no-info' => \$opt_no_info,
help => sub { print $help_info; exit },
version => sub { print $version_info; exit },
) or die $help_info;
die $help_info unless @ARGV == 1;
my %include = ();
my @include = (); # to retain order
# Process include file (if given). Format is:
#
# [section name]
# verbatim text
if ($include or $opt_include)
{
if (open INC, $include || $opt_include)
{
my $sect;
while (<INC>)
{
if (/^\[([^]]+)\]/)
{
$sect = uc $1;
$sect =~ s/^\s+//;
$sect =~ s/\s+$//;
next;
}
# Silently ignore anything before the first
# section--allows for comments and revision info.
next unless $sect;
push @include, $sect unless $include{$sect};
$include{$sect} ||= '';
$include{$sect} .= $_;
}
close INC;
die "$this_program: no valid information found in `$include'\n"
unless %include;
# Compress trailing blank lines.
for (keys %include)
{
$include{$_} =~ s/\n+$//;
$include{$_} .= "\n" unless /^NAME$/;
}
}
else
{
die "$this_program: can't open `$include' ($!)\n" if $include;
}
}
# Turn off localisation of executable's ouput.
@ENV{qw(LANGUAGE LANG LC_ALL)} = ('C') x 3;
# Turn off localisation of date (for strftime)
setlocale LC_TIME, 'C';
# Expand tabs, strip trailing spaces and break into paragraphs
sub paragraphs { split /\n\n+/, join '', expand @_ }
# Grab help and version paragraphs from executable
my @help = paragraphs `$ARGV[0] --help 2>/dev/null`
or die "$this_program: can't get `--help' info from $ARGV[0]\n";
my @version = paragraphs `$ARGV[0] --version 2>/dev/null`
or die "$this_program: can't get `--version' info from $ARGV[0]\n";
my $date = strftime "%B %Y", localtime;
(my $program = $ARGV[0]) =~ s!.*/!!;
my $package = $program;
my $version;
if ($opt_output)
{
unlink $opt_output
or die "$this_program: can't unlink $opt_output ($!)\n"
if -e $opt_output;
open STDOUT, ">$opt_output"
or die "$this_program: can't create $opt_output ($!)\n";
}
# The first line of the --version information is assumed to be in one
# of the following formats:
#
# <version>
# <program> <version>
# {GNU,Free} <program> <version>
# <program> ({GNU,Free} <package>) <version>
# <program> - {GNU,Free} <package> <version>
#
# and seperated from any copyright/author details by a blank line.
$_ = shift @version;
if (/^(\S+) +\(((?:GNU|Free) +[^)]+)\) +(.*)/ or
/^(\S+) +- *((?:GNU|Free) +\S+) +(.*)/)
{
$program = $1;
$package = $2;
$version = $3;
}
elsif (/^((?:GNU|Free) +)?(\S+) +(.*)/)
{
$program = $2;
$package = $1 ? "$1$2" : $2;
$version = $3;
}
else
{
$version = $_;
}
$program =~ s!.*/!!;
# no info for `info' itself
$opt_no_info = 1 if $program eq 'info';
# --name overrides --include contents
$include{NAME} = "$program \\- $opt_name" if $opt_name;
# Default (useless) NAME paragraph
$include{NAME} ||= "$program \\- manual page for $program $version";
# Man pages traditionally have the page title in caps.
my $PROGRAM = uc $program;
# Header.
print <<EOT;
.\\" DO NOT MODIFY THIS FILE! It was generated by $this_program $this_version.
.TH $PROGRAM "$section" "$date" "$package $version" FSF
.SH NAME
$include{NAME}
EOT
my $break;
my $accumulate = 1;
my @description = ();
sub convert_option;
# Output converted --help information.
for (@help)
{
chomp;
if (s/^Usage: +\S+ +(.*)\n?//)
{
# Turn the usage clause into a synopsis.
my $synopsis = '';
do {
my $syn = $1;
$syn =~ s/(([][]|\.\.+)+)/\\fR$1\\fI/g;
$syn =~ s/^/\\fI/ unless $syn =~ s/^\\fR//;
$syn .= '\fR';
$syn =~ s/\\fI( *)\\fR/$1/g;
$synopsis .= ".br\n" unless $accumulate;
$synopsis .= ".B $program\n";
$synopsis .= "$syn\n";
$accumulate = 0;
} while s/^(?:Usage| *or): +\S+ +(.*)\n?//;
# Include file overrides SYNOPSIS.
print ".SH SYNOPSIS\n", $include{SYNOPSIS} || $synopsis;
# Dump any accumulated description text.
print ".SH DESCRIPTION\n";
print @description;
# Add additional description text from include file.
if ($include{DESCRIPTION})
{
print ".PP\n" unless $include{DESCRIPTION} =~ /^\..P/;
print $include{DESCRIPTION};
}
$break = 1;
next unless $_;
}
# Accumulate text if the synopsis has not been produced yet.
if ($accumulate)
{
push @description, ".PP\n" if @description;
push @description, "$_\n";
next;
}
# Convert some standard paragraph names
if (s/^(Options|Examples): *\n//)
{
print qq(.SH \U$1\n);
$break = '';
next unless length;
}
# Catch bug report text.
if (/^Report bugs |^Email bug reports to /)
{
print qq(.SH "REPORTING BUGS"\n$_\n);
$break = '';
next;
}
# Option subsections have second line indented.
if (s/^(\S.*)\n / /)
{
print qq(.SS "$1"\n);
$break = '';
}
my $output = '';
while (length)
{
my $indent = 0;
# Tagged paragraph
if (s/^( +(\S.*?) +)(\S.*)\n?//)
{
$indent = length $1;
$output .= ".TP\n$2\n$3\n";
$break = 1;
}
# Indented paragraph
elsif (s/^( +)(\S.*)\n?//)
{
$indent = length $1;
$output .= ".IP\n$2\n";
$break = 1;
}
# Left justified paragraph
else
{
s/(.*)\n?//;
$output .= ".PP\n" if $break;
$output .= "$1\n";
$break = 1;
}
# Continuations
$output .= "$1\n" while s/^ {$indent}(\S.*)\n?//;
}
$_ = $output;
# Escape backslashes.
s/\\/\\e/g;
# Convert options.
s/(^| )(-[][\w=-]+)/$1 . convert_option $2/mge;
print;
}
# Print any include items other than the ones we have already dealt
# with.
for (@include)
{
print qq(.SH "$_"\n$include{$_})
unless /^(NAME|SYNOPSIS|DESCRIPTION|SEE ALSO)$/;
}
# Refer to the real documentation.
if ($include{'SEE ALSO'} or !$opt_no_info)
{
print qq(.SH "SEE ALSO"\n);
print $include{'SEE ALSO'}, ".PP\n" if $include{'SEE ALSO'};
print <<EOT unless $opt_no_info;
The full documentation for
.B $program
is maintained as a Texinfo manual. If the
.B info
and
.B $program
programs are properly installed at your site, the command
.IP
.B info $program
.PP
should give you access to the complete manual.
EOT
}
# Output converted --version information.
for (@version)
{
chomp;
# Join hyphenated lines.
s/([A-Za-z])-\n */$1/g;
# Convert copyright symbol or (c) to nroff character.
s/Copyright +(?:\xa9|\([Cc]\))/Copyright \\(co/g;
# Insert appropriate headings for copyright and author.
if (/^Copyright \\/) { print ".SH COPYRIGHT\n" }
elsif (/^Written +by/) { print ".SH AUTHOR\n" }
else { print ".PP\n"; }
# Insert line breaks before additional copyright messages and the
# disclaimer.
s/(.)\n(Copyright |This is free software)/$1\n.br\n$2/g;
print "$_\n";
}
exit;
# Convert option dashes to \- to stop nroff from hyphenating 'em, and
# embolden. Option arguments get italicised.
sub convert_option
{
my $option = '\fB' . shift;
$option =~ s/-/\\-/g;
unless ($option =~ s/\[=(.*)\]$/\\fR[=\\fI$1\\fR]/)
{
$option =~ s/=(.)/\\fR=\\fI$1/;
$option =~ s/ (.)/ \\fI$1/;
$option .= '\fR';
}
$option;
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,80 @@
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.013.
.TH INFO "1" "September 1999" "GNU texinfo 4.0" FSF
.SH NAME
info \- read Info documents
.SH SYNOPSIS
.B info
[\fIOPTION\fR]... [\fIMENU-ITEM\fR...]
.SH DESCRIPTION
.PP
Read documentation in Info format.
.SH OPTIONS
.TP
\fB\-\-apropos\fR=\fISUBJECT\fR
look up SUBJECT in all indices of all manuals.
.TP
\fB\-\-directory\fR=\fIDIR\fR
add DIR to INFOPATH.
.TP
\fB\-\-dribble\fR=\fIFILENAME\fR
remember user keystrokes in FILENAME.
.TP
\fB\-\-file\fR=\fIFILENAME\fR
specify Info file to visit.
.TP
\fB\-\-help\fR
display this help and exit.
.TP
\fB\-\-index\-search\fR=\fISTRING\fR
go to node pointed by index entry STRING.
.TP
\fB\-\-node\fR=\fINODENAME\fR
specify nodes in first visited Info file.
.TP
\fB\-\-output\fR=\fIFILENAME\fR
output selected nodes to FILENAME.
.TP
\fB\-\-restore\fR=\fIFILENAME\fR
read initial keystrokes from FILENAME.
.TP
\fB\-\-show\-options\fR, \fB\-\-usage\fR
go to command-line options node.
.TP
\fB\-\-subnodes\fR
recursively output menu items.
.TP
\fB\-\-vi\-keys\fR
use vi-like and less-like key bindings.
.TP
\fB\-\-version\fR
display version information and exit.
.PP
The first non-option argument, if present, is the menu entry to start from;
it is searched for in all `dir' files along INFOPATH.
If it is not present, info merges all `dir' files and shows the result.
Any remaining arguments are treated as the names of menu
items relative to the initial node visited.
.SH EXAMPLES
.TP
info
show top-level dir menu
.TP
info emacs
start at emacs node from top-level dir
.TP
info emacs buffers
start at buffers node within emacs manual
.TP
info \fB\-\-show\-options\fR emacs
start at node with emacs' command line options
.TP
info \fB\-f\fR ./foo.info
show file ./foo.info, not searching dir
.SH "REPORTING BUGS"
Email bug reports to bug-texinfo@gnu.org,
general questions and discussion to help-texinfo@gnu.org.
.SH COPYRIGHT
Copyright \(co 1999 Free Software Foundation, Inc.
There is NO warranty. You may redistribute this software
under the terms of the GNU General Public License.
For more information about these matters, see the files named COPYING.

View File

@ -0,0 +1,62 @@
.\" info(5)
.\" $Id: info.5,v 1.2 1998/07/31 17:39:31 karl Exp $
.\"
.\" Copyright (C) 1998 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 Foundation.
.\"
.TH INFO 5 "GNU Info" "FSF"
.SH NAME
info \- readable online documentation
.SH DESCRIPTION
The Info file format is an easily-parsable representation for online
documents. It can be read by
.I emacs(1)
and
.I info(1)
among other programs.
.PP
Info files are usually created from
.I texinfo(5)
sources by
.IR makeinfo(1) ,
but can be created from scratch if so desired.
.PP
For a full description of the Texinfo language and associated tools,
please see the Texinfo manual (written in Texinfo itself). Most likely,
running this command from your shell:
.RS
.I info texinfo
.RE
or this key sequence from inside Emacs:
.RS
.I M-x info RET m texinfo RET
.RE
will get you there.
.SH AVAILABILITY
ftp://ftp.gnu.org/pub/gnu/texinfo-<version>.tar.gz
.br
or any GNU mirror site.
.SH "REPORTING BUGS"
Please send bug reports to bug-texinfo@gnu.org,
general questions and discussion to help-texinfo@gnu.org.
.SH "SEE ALSO"
info(1), install-info(1), makeinfo(1), texi2dvi(1),
.br
texindex(1).
.br
emacs(1), tex(1).
.br
texinfo(5).

View File

@ -1,9 +1,9 @@
\input texinfo @c -*-texinfo-*-
@comment %**start of header
@comment %**start of header
@setfilename info.info
@settitle Info 1.0
@comment %**end of header
@comment $Id: info.texi,v 1.4 1997/07/10 21:58:11 karl Exp $
@settitle Info
@comment %**end of header
@comment $Id: info.texi,v 1.11 1999/04/19 21:37:23 karl Exp $
@dircategory Texinfo documentation system
@direntry
@ -11,10 +11,10 @@
@end direntry
@ifinfo
This file describes how to use Info,
the on-line, menu-driven GNU documentation system.
This file describes how to use Info, the on-line, menu-driven GNU
documentation system.
Copyright (C) 1989, 92, 96, 97 Free Software Foundation, Inc.
Copyright (C) 1989, 92, 96, 97, 98, 99 Free Software Foundation, Inc.
Permission is granted to make and distribute verbatim copies of
this manual provided the copyright notice and this permission notice
@ -44,10 +44,9 @@ by the Free Software Foundation.
@author Brian Fox
@page
@vskip 0pt plus 1filll
Copyright @copyright{} 1989, 1992, 1993, 1996, 1997 Free Software
Copyright @copyright{} 1989, 92, 93, 96, 97, 98, 99 Free Software
Foundation, Inc.
@sp 2
Published by the Free Software Foundation @*
59 Temple Place - Suite 330 @*
Boston, MA 02111-1307, USA.
@ -67,31 +66,20 @@ 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)
@ifnottex
@node Top
@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
@end ifnottex
@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).
* Creating an Info File:: How to make your own Info file.
@end menu
@node Getting Started, Advanced Info, Top, Top
@ -101,7 +89,7 @@ To learn advanced Info commands, type @kbd{n} twice. This brings you to
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
file. The third part is about how to generate Info files from
Texinfo files.
@iftex
@ -110,7 +98,7 @@ 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.
well.
There are two ways of looking at the online version of this manual:
@ -340,7 +328,7 @@ 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.
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
@ -427,16 +415,14 @@ what you have entered.
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!@*
Here is a menu to give you a chance to practice. This menu gives you
three ways of going to one place, Help-FOO:
@menu
* 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!
@end menu
>> Now type just an @kbd{m} and see what happens:
@ -559,17 +545,16 @@ to cancel the @samp{f}.
@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
@subsection 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.
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.
@ -590,15 +575,15 @@ manner.
@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
@node Advanced Info
@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}.)
Texinfo, texinfo, Texinfo}.)
@menu
* Expert:: Advanced Info commands: g, s, e, and 1 - 5.
@ -639,12 +624,12 @@ 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).
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}, ...
@ -652,9 +637,9 @@ might like to use the commands @kbd{1}, @kbd{2}, @kbd{3}, @kbd{4}, ...
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
If your 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
underlined, 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
@ -678,12 +663,12 @@ Create some nodes, in some file, to document that topic.
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.
Usually, the way to create the nodes is with Texinfo (@pxref{Top,,
Overview of Texinfo, texinfo, Texinfo}); this has the advantage that you
can also make a printed manual from them. However, if you want to edit
an Info file, here is how.
The new node can live in an existing documentation file, or in a new
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
@ -693,12 +678,12 @@ 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}.
@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
@ -728,10 +713,10 @@ 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.
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
@ -741,7 +726,7 @@ to help identify the node for the user.
@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.
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.
@ -766,11 +751,11 @@ 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 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
@ -816,7 +801,7 @@ They are just examples. The places they ``lead to'' do not really exist!
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
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
@ -847,24 +832,24 @@ 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
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.
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.
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
@ -894,18 +879,17 @@ 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.
@node Creating an Info File
@chapter Creating an Info File
@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}, to learn how to
write a Texinfo file.
@xref{Top,, Overview of Texinfo, texinfo, Texinfo: The GNU Documentation
Format}, to learn how to write a Texinfo file.
@xref{Creating an Info File,,, texinfo, Texinfo}, to learn how to create
an Info file from a Texinfo file.
@xref{Installing an Info File,,, texinfo, Texinfo}, to learn how to
install an Info file after you have created one.
@bye

View File

@ -0,0 +1,84 @@
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.013.
.TH INSTALL-INFO "1" "September 1999" "GNU texinfo 4.0" FSF
.SH NAME
install-info \- update info/dir entries
.SH SYNOPSIS
.B install-info
[\fIOPTION\fR]... [\fIINFO-FILE \fR[\fIDIR-FILE\fR]]
.SH DESCRIPTION
.PP
Install or delete dir entries from INFO-FILE in the Info directory file
DIR-FILE.
.SH OPTIONS
.TP
\fB\-\-delete\fR
delete existing entries for INFO-FILE from DIR-FILE;
.IP
don't insert any new entries.
.TP
\fB\-\-dir\-file\fR=\fINAME\fR
specify file name of Info directory file.
.IP
This is equivalent to using the DIR-FILE argument.
.TP
\fB\-\-entry\fR=\fITEXT\fR
insert TEXT as an Info directory entry.
.IP
TEXT should have the form of an Info menu item line
plus zero or more extra lines starting with whitespace.
If you specify more than one entry, they are all added.
If you don't specify any entries, they are determined
from information in the Info file itself.
.TP
\fB\-\-help\fR
display this help and exit.
.TP
\fB\-\-info\-file\fR=\fIFILE\fR
specify Info file to install in the directory.
.IP
This is equivalent to using the INFO-FILE argument.
.TP
\fB\-\-info\-dir\fR=\fIDIR\fR
same as \fB\-\-dir\-file\fR=\fIDIR\fR/dir.
.TP
\fB\-\-item\fR=\fITEXT\fR
same as \fB\-\-entry\fR TEXT.
.IP
An Info directory entry is actually a menu item.
.TP
\fB\-\-quiet\fR
suppress warnings.
.TP
\fB\-\-remove\fR
same as \fB\-\-delete\fR.
.TP
\fB\-\-section\fR=\fISEC\fR
put this file's entries in section SEC of the directory.
.IP
If you specify more than one section, all the entries
are added in each of the sections.
If you don't specify any sections, they are determined
from information in the Info file itself.
.TP
\fB\-\-version\fR
display version information and exit.
.SH "REPORTING BUGS"
Email bug reports to bug-texinfo@gnu.org,
general questions and discussion to help-texinfo@gnu.org.
.SH "SEE ALSO"
The full documentation for
.B install-info
is maintained as a Texinfo manual. If the
.B info
and
.B install-info
programs are properly installed at your site, the command
.IP
.B info install-info
.PP
should give you access to the complete manual.
.SH COPYRIGHT
Copyright \(co 1999 Free Software Foundation, Inc.
There is NO warranty. You may redistribute this software
under the terms of the GNU General Public License.
For more information about these matters, see the files named COPYING.

View File

@ -0,0 +1,152 @@
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.013.
.TH MAKEINFO "1" "September 1999" "GNU texinfo 4.0" FSF
.SH NAME
makeinfo \- translate Texinfo documents
.SH SYNOPSIS
.B makeinfo
[\fIOPTION\fR]...\fI TEXINFO-FILE\fR...
.SH DESCRIPTION
.PP
Translate Texinfo source documentation to various other formats:
Info files suitable for reading online with Emacs or standalone GNU Info
(by default); plain text (with \fB\-\-no\-headers\fR); or HTML (with \fB\-\-html\fR).
.SH OPTIONS
.TP
\fB\-\-commands\-in\-node\-names\fR
allow @ commands in node names.
.TP
\fB\-D\fR VAR
define a variable, as with @set.
.TP
\fB\-E\fR, \fB\-\-macro\-expand\fR FILE
output macro-expanded source to FILE.
.TP
\fB\-\-error\-limit\fR=\fINUM\fR
quit after NUM errors (default 100).
.TP
\fB\-\-fill\-column\fR=\fINUM\fR
break Info lines at NUM characters (default 72).
.TP
\fB\-\-footnote\-style\fR=\fISTYLE\fR
output footnotes according to STYLE:
.IP
`separate' to place footnotes in their own node,
`end' to place the footnotes at the end of the
.IP
node in which they are defined (the default).
.TP
\fB\-\-force\fR
preserve output even if errors.
.TP
\fB\-\-help\fR
display this help and exit.
.TP
\fB\-\-html\fR
output HTML rather than Info format;
.TP
\fB\-I\fR DIR
append DIR to the @include search path.
.TP
\fB\-\-ifhtml\fR
process @ifhtml and @html text even when not
.IP
generating HTML.
.TP
\fB\-\-ifinfo\fR
process @ifinfo text even when generating HTML.
.TP
\fB\-\-iftex\fR
process @iftex and @tex text.
.IP
implies \fB\-\-no\-split\fR.
.TP
\fB\-\-no\-headers\fR
suppress Info node separators and Node: lines and
.IP
write to standard output without \fB\-\-output\fR.
.TP
\fB\-\-no\-ifhtml\fR
do not process @ifhtml and @html text.
.TP
\fB\-\-no\-ifinfo\fR
do not process @ifinfo text.
.TP
\fB\-\-no\-iftex\fR
do not process @iftex and @tex text.
.TP
\fB\-\-no\-split\fR
suppress splitting of large Info output files or
generation of one HTML file per node.
.TP
\fB\-\-no\-validate\fR
suppress node cross-reference validation.
.TP
\fB\-\-no\-warn\fR
suppress warnings (but not errors).
.TP
\fB\-\-number\-sections\fR
include chapter, section, etc. numbers in output.
.TP
\fB\-o\fR, \fB\-\-output\fR=\fIFILE\fR
output to FILE, ignoring any @setfilename.
.TP
\fB\-P\fR DIR
prepend DIR to the @include search path.
.TP
\fB\-\-paragraph\-indent\fR=\fIVAL\fR
indent Info paragraphs by VAL spaces (default 3).
.IP
if VAL is `none', do not indent;
if VAL is `asis', preserve existing indentation.
.TP
\fB\-\-reference\-limit\fR=\fINUM\fR
warn about at most NUM references (default 1000).
.TP
\fB\-U\fR VAR
undefine a variable, as with @clear.
.TP
\fB\-v\fR, \fB\-\-verbose\fR
explain what is being done.
.TP
\fB\-\-version\fR
display version information and exit.
.PP
The defaults for the @if... conditionals depend on the output format:
if generating HTML, \fB\-\-ifhtml\fR is on and the others are off;
if generating Info or plain text, \fB\-\-ifinfo\fR is on and the others are off.
.SH EXAMPLES
.TP
makeinfo foo.texi
write Info to foo's @setfilename
.TP
makeinfo \fB\-\-html\fR foo.texi
write HTML to foo's @setfilename
.TP
makeinfo \fB\-\-no\-headers\fR \fB\-o\fR - foo.texi
write plain text to standard output
.TP
makeinfo \fB\-\-number\-sections\fR foo.texi
write Info with numbered sections
.TP
makeinfo \fB\-\-no\-split\fR foo.texi
write one Info file however big
.SH "REPORTING BUGS"
Email bug reports to bug-texinfo@gnu.org,
general questions and discussion to help-texinfo@gnu.org.
.SH "SEE ALSO"
The full documentation for
.B makeinfo
is maintained as a Texinfo manual. If the
.B info
and
.B makeinfo
programs are properly installed at your site, the command
.IP
.B info makeinfo
.PP
should give you access to the complete manual.
.SH COPYRIGHT
Copyright \(co 1999 Free Software Foundation, Inc.
There is NO warranty. You may redistribute this software
under the terms of the GNU General Public License.
For more information about these matters, see the files named COPYING.

View File

@ -0,0 +1,47 @@
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.013.
.TH TEXINDEX "1" "September 1999" "GNU texinfo 4.0" FSF
.SH NAME
texindex \- sort Texinfo index files
.SH SYNOPSIS
.B texindex
[\fIOPTION\fR]...\fI FILE\fR...
.SH DESCRIPTION
.PP
Generate a sorted index for each TeX output FILE.
Usually FILE... is specified as `foo.??' for a document `foo.texi'.
.SH OPTIONS
.TP
\fB\-h\fR, \fB\-\-help\fR
display this help and exit
.TP
\fB\-k\fR, \fB\-\-keep\fR
keep temporary files around after processing
.TP
\fB\-\-no\-keep\fR
do not keep temporary files around after processing (default)
.TP
\fB\-o\fR, \fB\-\-output\fR FILE
send output to FILE
.TP
\fB\-\-version\fR
display version information and exit
.SH "REPORTING BUGS"
Email bug reports to bug-texinfo@gnu.org,
general questions and discussion to help-texinfo@gnu.org.
.SH "SEE ALSO"
The full documentation for
.B texindex
is maintained as a Texinfo manual. If the
.B info
and
.B texindex
programs are properly installed at your site, the command
.IP
.B info texindex
.PP
should give you access to the complete manual.
.SH COPYRIGHT
Copyright \(co 1999 Free Software Foundation, Inc.
There is NO warranty. You may redistribute this software
under the terms of the GNU General Public License.
For more information about these matters, see the files named COPYING.

View File

@ -0,0 +1,51 @@
.\" texinfo(5)
.\" $Id: texinfo.5,v 1.3 1999/03/25 21:28:25 karl Exp $
.\"
.\" Copyright (C) 1998, 99 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 Foundation.
.\"
.TH TEXINFO 5 "GNU Texinfo" "FSF"
.SH NAME
Texinfo \- software documentation system
.SH DESCRIPTION
Texinfo is a documentation system that uses a single source file to
produce both online information and printed output. It is primarily
designed for writing software manuals.
.PP
For a full description of the Texinfo language and associated tools,
please see the Texinfo manual (written in Texinfo itself). Most likely,
running this command from your shell:
.RS
.I info texinfo
.RE
or this key sequence from inside Emacs:
.RS
.I M-x info RET m texinfo RET
.RE
will get you there.
.SH AVAILABILITY
ftp://ftp.gnu.org/gnu/texinfo/
.br
or any GNU mirror site.
.SH "REPORTING BUGS"
Please send bug reports to bug-texinfo@gnu.org,
general questions and discussion to help-texinfo@gnu.org.
.SH "SEE ALSO"
info(1), install-info(1), makeinfo(1), texi2dvi(1), texindex(1).
.br
emacs(1), tex(1).
.br
info(5).

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,3 @@
@set UPDATED 28 September 1999
@set EDITION 4.0
@set VERSION 4.0

View File

@ -14,11 +14,6 @@ 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.

View File

@ -1,7 +1,7 @@
/* dir.c -- How to build a special "dir" node from "localdir" files.
$Id: dir.c,v 1.6 1997/07/27 21:09:20 karl Exp $
/* dir.c -- how to build a special "dir" node from "localdir" files.
$Id: dir.c,v 1.7 1998/06/28 19:51:36 karl Exp $
Copyright (C) 1993, 97 Free Software Foundation, Inc.
Copyright (C) 1993, 97, 98 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
@ -125,7 +125,7 @@ maybe_build_dir_node (dirname)
char *fullpath = xmalloc (3 + strlen (this_dir) + namelen);
strcpy (fullpath, this_dir);
if (fullpath[strlen (fullpath) - 1] != '/')
if (!IS_SLASH (fullpath[strlen (fullpath) - 1]))
strcat (fullpath, "/");
strcat (fullpath, from_file);
@ -135,8 +135,9 @@ maybe_build_dir_node (dirname)
if (statable && S_ISREG (finfo.st_mode) && new_dir_file_p (&finfo))
{
long filesize;
int compressed;
char *contents = filesys_read_info_file (fullpath, &filesize,
&finfo);
&finfo, &compressed);
if (contents)
{
update_tags++;

View File

@ -35,21 +35,28 @@ FUNCTION_DOC function_doc_array[] = {
{ info_global_next_node, "global-next-node", "Move forwards or down through node structure" },
{ info_global_prev_node, "global-prev-node", "Move backwards or up through node structure" },
{ info_scroll_forward, "scroll-forward", "Scroll forward in this window" },
{ info_scroll_forward_set_window, "scroll-forward-set-window", "Scroll forward in this window and set default window size" },
{ info_scroll_backward, "scroll-backward", "Scroll backward in this window" },
{ info_scroll_backward_set_window, "scroll-backward-set-window", "Scroll backward in this window and set default window size" },
{ info_beginning_of_node, "beginning-of-node", "Move to the start of this node" },
{ info_end_of_node, "end-of-node", "Move to the end of this node" },
{ info_down_line, "down-line", "Scroll down by lines" },
{ info_up_line, "up-line", "Scroll up by lines" },
{ info_scroll_half_screen_down, "scroll-half-screen-down", "Scroll down by half screen size" },
{ info_scroll_half_screen_up, "scroll-half-screen-up", "Scroll up by half screen size" },
{ info_next_window, "next-window", "Select the next window" },
{ info_prev_window, "prev-window", "Select the previous window" },
{ info_split_window, "split-window", "Split the current window" },
{ info_delete_window, "delete-window", "Delete the current window" },
{ info_keep_one_window, "keep-one-window", "Delete all other windows" },
{ info_scroll_other_window, "scroll-other-window", "Scroll the other window" },
{ info_scroll_other_window_backward, "scroll-other-window-backward", "Scroll the other window backward" },
{ info_grow_window, "grow-window", "Grow (or shrink) this window" },
{ info_tile_windows, "tile-windows", "Divide the available screen space among the visible windows" },
{ info_toggle_wrap, "toggle-wrap", "Toggle the state of line wrapping in the current window" },
{ info_next_node, "next-node", "Select the `Next' node" },
{ info_prev_node, "prev-node", "Select the `Prev' node" },
{ info_up_node, "up-node", "Select the `Up' node" },
{ info_next_node, "next-node", "Select the Next node" },
{ info_prev_node, "prev-node", "Select the Prev node" },
{ info_up_node, "up-node", "Select the Up node" },
{ info_last_node, "last-node", "Select the last node in this file" },
{ info_first_node, "first-node", "Select the first node in this file" },
{ info_last_menu_item, "last-menu-item", "Select the last item in this node's menu" },
@ -59,6 +66,8 @@ FUNCTION_DOC function_doc_array[] = {
{ info_find_menu, "find-menu", "Move to the start of this node's menu" },
{ info_visit_menu, "visit-menu", "Visit as many menu items at once as possible" },
{ info_goto_node, "goto-node", "Read a node name and select it" },
{ info_menu_sequence, "menu-sequence", "Read a list of menus starting from dir and follow them" },
{ info_goto_invocation_node, "goto-invocation-node", "Find the node describing program invocation" },
{ info_man, "man", "Read a manpage reference and select it" },
{ info_top_node, "top-node", "Select the node `Top' in this file" },
{ info_dir_node, "dir-node", "Select the node `(dir)'" },
@ -66,14 +75,18 @@ FUNCTION_DOC function_doc_array[] = {
{ info_kill_node, "kill-node", "Kill this node" },
{ info_view_file, "view-file", "Read the name of a file and select it" },
{ info_print_node, "print-node", "Pipe the contents of this node through INFO_PRINT_COMMAND" },
{ info_search_case_sensitively, "search-case-sensitively", "Read a string and search for it case-sensitively" },
{ info_search, "search", "Read a string and search for it" },
{ info_search_backward, "search-backward", "Read a string and search backward for it" },
{ info_search_next, "search-next", "Repeat last search in the same direction" },
{ info_search_previous, "search-previous", "Repeat last search in the reverse direction" },
{ isearch_forward, "isearch-forward", "Search interactively for a string as you type it" },
{ isearch_backward, "isearch-backward", "Search interactively for a string as you type it" },
{ info_move_to_prev_xref, "move-to-prev-xref", "Move to the previous cross reference" },
{ info_move_to_next_xref, "move-to-next-xref", "Move to the next cross reference" },
{ info_select_reference_this_line, "select-reference-this-line", "Select reference or menu item appearing on this line" },
{ info_abort_key, "abort-key", "Cancel current operation" },
{ info_move_to_window_line, "move-to-window-line", "Move to the cursor to a specific line of the window" },
{ info_move_to_window_line, "move-to-window-line", "Move the cursor to a specific line of the window" },
{ info_redraw_display, "redraw-display", "Redraw the display" },
{ info_quit, "quit", "Quit using Info" },
{ info_do_lowercase_version, "do-lowercase-version", "" },

View File

@ -1,9 +1,6 @@
/* dribble.c -- Dribble files for Info. */
/* 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.
Copyright (C) 1993, 98 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
@ -37,7 +34,8 @@ open_dribble_file (name)
/* Perhaps close existing dribble file. */
close_dribble_file ();
info_dribble_file = fopen (name, "w");
/* Keystrokes can be non-printable characters, so we need binary I/O. */
info_dribble_file = fopen (name, FOPEN_WBIN);
#if defined (HAVE_SETVBUF)
if (info_dribble_file)

View File

@ -1,7 +1,7 @@
/* echo-area.c -- How to read a line in the echo area.
$Id: echo-area.c,v 1.10 1998/02/26 22:47:02 karl Exp $
/* echo-area.c -- how to read a line in the echo area.
$Id: echo-area.c,v 1.12 1999/03/03 22:22:14 karl Exp $
Copyright (C) 1993, 97, 98 Free Software Foundation, Inc.
Copyright (C) 1993, 97, 98, 99 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
@ -940,7 +940,8 @@ DECLARE_INFO_COMMAND (ea_possible_completions, _("List possible completions"))
initialize_message_buffer ();
printf_to_message_buffer (completions_found_index == 1
? _("One completion:\n")
: _("%d completions:\n"));
: _("%d completions:\n"),
completions_found_index);
/* Find the maximum length of a label. */
for (i = 0; i < completions_found_index; i++)
@ -1462,7 +1463,7 @@ echo_area_stack_contains_completions_p ()
static void
pause_or_input ()
{
#if defined (FD_SET)
#ifdef FD_SET
struct timeval timer;
fd_set readfds;
int ready;
@ -1470,14 +1471,14 @@ pause_or_input ()
FD_ZERO (&readfds);
FD_SET (fileno (stdin), &readfds);
timer.tv_sec = 2;
timer.tv_usec = 750;
timer.tv_usec = 0;
ready = select (fileno (stdin) + 1, &readfds, (fd_set *) NULL,
(fd_set *) NULL, &timer);
#endif /* FD_SET */
}
/* Print MESSAGE right after the end of the current line, and wait
for input or 2.75 seconds, whichever comes first. Then flush the
for input or a couple of seconds, whichever comes first. Then flush the
informational message that was printed. */
void
inform_in_echo_area (message)
@ -1487,8 +1488,9 @@ inform_in_echo_area (message)
char *text;
text = xstrdup (message);
for (i = 0; text[i] && text[i] != '\n'; i++);
text[i] = '\0';
for (i = 0; text[i] && text[i] != '\n'; i++)
;
text[i] = 0;
echo_area_initialize_node ();
sprintf (&input_line[input_line_end], "%s[%s]\n",

View File

@ -1,5 +1,5 @@
/* filesys.c -- File system specific functions for hacking this system.
$Id: filesys.c,v 1.6 1998/02/21 22:52:46 karl Exp $
/* filesys.c -- filesystem specific functions.
$Id: filesys.c,v 1.10 1998/12/06 21:58:30 karl Exp $
Copyright (C) 1993, 97, 98 Free Software Foundation, Inc.
@ -26,6 +26,7 @@
/* Local to this file. */
static char *info_file_in_path (), *lookup_info_filename ();
static char *info_absolute_file ();
static void remember_info_filename (), maybe_initialize_infopath ();
typedef struct
@ -35,18 +36,29 @@ typedef struct
} COMPRESSION_ALIST;
static char *info_suffixes[] = {
"",
".info",
"-info",
"/index",
(char *)NULL
".inf", /* 8+3 file on filesystem which supports long file names */
#ifdef __MSDOS__
/* 8+3 file names strike again... */
".in", /* for .inz, .igz etc. */
".i",
#endif
"",
NULL
};
static COMPRESSION_ALIST compress_suffixes[] = {
{ ".gz", "gunzip" },
{ ".bz2", "bunzip2" },
{ ".z", "gunzip" },
{ ".Z", "uncompress" },
{ ".Y", "unyabba" },
{ ".z", "gunzip" },
{ ".gz", "gunzip" },
#ifdef __MSDOS__
{ "gz", "gunzip" },
{ "z", "gunzip" },
#endif
{ (char *)NULL, (char *)NULL }
};
@ -86,21 +98,22 @@ info_find_fullpath (partial)
/* 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, "/");
if (IS_ABSOLUTE (partial))
temp = info_absolute_file (partial);
else if (initial_character == '~')
{
expansion = tilde_expand_word (partial);
if (*expansion == '/')
if (IS_ABSOLUTE (expansion))
{
temp = info_file_in_path (expansion + 1, "/");
temp = info_absolute_file (expansion);
free (expansion);
}
else
temp = expansion;
}
else if (initial_character == '.' &&
(partial[1] == '/' || (partial[1] == '.' && partial[2] == '/')))
(IS_SLASH (partial[1]) ||
(partial[1] == '.' && IS_SLASH (partial[2]))))
{
if (local_temp_filename_size < 1024)
local_temp_filename = (char *)xrealloc
@ -117,7 +130,9 @@ info_find_fullpath (partial)
strcat (local_temp_filename, "/");
strcat (local_temp_filename, partial);
return (local_temp_filename);
temp = info_absolute_file (local_temp_filename); /* try extensions */
if (!temp)
partial = local_temp_filename;
}
else
temp = info_file_in_path (partial, infopath);
@ -167,7 +182,7 @@ info_file_in_path (filename, path)
temp = (char *)xmalloc (30 + strlen (temp_dirname) + strlen (filename));
strcpy (temp, temp_dirname);
if (temp[(strlen (temp)) - 1] != '/')
if (!IS_SLASH (temp[(strlen (temp)) - 1]))
strcat (temp, "/");
strcat (temp, filename);
@ -229,8 +244,26 @@ info_file_in_path (filename, path)
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.
/* Assume FNAME is an absolute file name, and check whether it is
a regular file. If it is, return it as a new string; otherwise
return a NULL pointer. We do it by taking the file name apart
into its directory and basename parts, and calling info_file_in_path.*/
static char *
info_absolute_file (fname)
char *fname;
{
char *containing_dir = xstrdup (fname);
char *base = filename_non_directory (containing_dir);
if (base > containing_dir)
base[-1] = '\0';
return info_file_in_path (filename_non_directory (fname), containing_dir);
}
/* Given a string containing units of information separated by
the PATH_SEP character, 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)
@ -243,7 +276,7 @@ extract_colon_unit (string, idx)
if ((i >= strlen (string)) || !string)
return ((char *) NULL);
while (string[i] && string[i] != ':')
while (string[i] && string[i] != PATH_SEP[0])
i++;
if (i == start)
{
@ -285,7 +318,7 @@ lookup_info_filename (filename)
register int i;
for (i = 0; names_and_files[i]; i++)
{
if (strcmp (names_and_files[i]->filename, filename) == 0)
if (FILENAME_CMP (names_and_files[i]->filename, filename) == 0)
return (names_and_files[i]->expansion);
}
}
@ -354,14 +387,14 @@ info_add_path (path, where)
strcpy (infopath, path);
else if (where == INFOPATH_APPEND)
{
strcat (infopath, ":");
strcat (infopath, PATH_SEP);
strcat (infopath, path);
}
else if (where == INFOPATH_PREPEND)
{
char *temp = xstrdup (infopath);
strcpy (infopath, path);
strcat (infopath, ":");
strcat (infopath, PATH_SEP);
strcat (infopath, temp);
free (temp);
}
@ -378,28 +411,70 @@ zap_infopath ()
infopath_size = 0;
}
/* Given a chunk of text and its length, convert all CRLF pairs at every
end-of-line into a single Newline character. Return the length of
produced text.
This is required because the rest of code is too entrenched in having
a single newline at each EOL; in particular, searching for various
Info headers and cookies can become extremely tricky if that assumption
breaks.
FIXME: this could also support Mac-style text files with a single CR
at the EOL, but what about random CR characters in non-Mac files? Can
we afford converting them into newlines as well? Maybe implement some
heuristics here, like in Emacs 20.
FIXME: is it a good idea to show the EOL type on the modeline? */
long
convert_eols (text, textlen)
char *text;
long textlen;
{
register char *s = text;
register char *d = text;
while (textlen--)
{
if (*s == '\r' && textlen && s[1] == '\n')
{
s++;
textlen--;
}
*d++ = *s++;
}
return (long)(d - text);
}
/* 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 turns out to be compressed, set IS_COMPRESSED to non-zero.
If the file cannot be read, return a NULL pointer. */
char *
filesys_read_info_file (pathname, filesize, finfo)
filesys_read_info_file (pathname, filesize, finfo, is_compressed)
char *pathname;
long *filesize;
struct stat *finfo;
int *is_compressed;
{
long st_size;
*filesize = filesys_error_number = 0;
if (compressed_filename_p (pathname))
return (filesys_read_compressed (pathname, filesize, finfo));
{
*is_compressed = 1;
return (filesys_read_compressed (pathname, filesize, finfo));
}
else
{
int descriptor;
char *contents;
descriptor = open (pathname, O_RDONLY, 0666);
*is_compressed = 0;
descriptor = open (pathname, O_RDONLY | O_BINARY, 0666);
/* If the file couldn't be opened, give up. */
if (descriptor < 0)
@ -413,15 +488,24 @@ filesys_read_info_file (pathname, filesize, finfo)
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);
filesys_error_number = errno;
close (descriptor);
free (contents);
return ((char *)NULL);
}
close (descriptor);
*filesize = st_size;
/* Convert any DOS-style CRLF EOLs into Unix-style NL.
Seems like a good idea to have even on Unix, in case the Info
files are coming from some Windows system across a network. */
*filesize = convert_eols (contents, st_size);
/* EOL conversion can shrink the text quite a bit. We don't
want to waste storage. */
if (*filesize < st_size)
contents = (char *)xrealloc (contents, 1 + *filesize);
return (contents);
}
}
@ -449,8 +533,11 @@ filesys_read_compressed (pathname, filesize, finfo)
if (!decompressor)
return ((char *)NULL);
command = (char *)xmalloc (10 + strlen (pathname) + strlen (decompressor));
sprintf (command, "%s < %s", decompressor, pathname);
command = (char *)xmalloc (15 + strlen (pathname) + strlen (decompressor));
/* Explicit .exe suffix makes the diagnostics of `popen'
better on systems where COMMAND.COM is the stock shell. */
sprintf (command, "%s%s < %s",
decompressor, STRIP_DOT_EXE ? ".exe" : "", pathname);
#if !defined (BUILDING_LIBRARY)
if (info_windows_initialized_p)
@ -464,7 +551,7 @@ filesys_read_compressed (pathname, filesize, finfo)
}
#endif /* !BUILDING_LIBRARY */
stream = popen (command, "r");
stream = popen (command, FOPEN_RBIN);
free (command);
/* Read chunks from this file until there are none left to read. */
@ -493,9 +580,18 @@ filesys_read_compressed (pathname, filesize, finfo)
}
free (chunk);
pclose (stream);
contents = (char *)xrealloc (contents, offset + 1);
*filesize = offset;
if (pclose (stream) == -1)
{
if (contents)
free (contents);
contents = (char *)NULL;
filesys_error_number = errno;
}
else
{
*filesize = convert_eols (contents, offset);
contents = (char *)xrealloc (contents, 1 + *filesize);
}
}
else
{
@ -547,9 +643,19 @@ filesys_decompressor_for_file (filename)
return ((char *)NULL);
for (i = 0; compress_suffixes[i].suffix; i++)
if (strcmp (extension, compress_suffixes[i].suffix) == 0)
if (FILENAME_CMP (extension, compress_suffixes[i].suffix) == 0)
return (compress_suffixes[i].decompressor);
#if defined (__MSDOS__)
/* If no other suffix matched, allow any extension which ends
with `z' to be decompressed by gunzip. Due to limited 8+3 DOS
file namespace, we can expect many such cases, and supporting
every weird suffix thus produced would be a pain. */
if (extension[strlen (extension) - 1] == 'z' ||
extension[strlen (extension) - 1] == 'Z')
return "gunzip";
#endif
return ((char *)NULL);
}
@ -582,3 +688,26 @@ filesys_error_string (filename, error_num)
return (errmsg_buf);
}
/* Check for FILENAME eq "dir" first, then all the compression
suffixes. */
int
is_dir_name (filename)
char *filename;
{
unsigned i;
if (strcasecmp (filename, "dir") == 0)
return 1;
for (i = 0; compress_suffixes[i].suffix; i++)
{
char dir_compressed[50]; /* can be short */
strcpy (dir_compressed, "dir");
strcat (dir_compressed, compress_suffixes[i].suffix);
if (strcasecmp (filename, dir_compressed) == 0)
return 1;
}
return 0;
}

View File

@ -1,10 +1,7 @@
/* filesys.h -- External declarations of functions and vars in filesys.c.
$Id: filesys.h,v 1.3 1997/07/15 18:39:08 karl Exp $
/* filesys.h -- external declarations for filesys.c.
$Id: filesys.h,v 1.5 1998/07/21 22:25:44 karl Exp $
This file is part of GNU Info, a program for reading online documentation
stored in Info format.
Copyright (C) 1993, 97 Free Software Foundation, Inc.
Copyright (C) 1993, 97, 98 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
@ -46,6 +43,11 @@ extern void info_add_path ();
If it can't find the file, it returns NULL. */
extern char *info_find_fullpath ();
/* Given a chunk of text and its length, convert all CRLF pairs at the
EOLs into a single Newline character. Return the length of produced
text. */
long convert_eols ();
/* 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.
@ -69,6 +71,9 @@ extern int filesys_error_number;
Advance IDX to the character after the colon. */
extern char *extract_colon_unit ();
/* Return true if FILENAME is `dir', with a possible compression suffix. */
extern int is_dir_name ();
/* 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:."

View File

@ -1,7 +1,7 @@
/* footnotes.c -- Some functions for manipulating footnotes.
$Id: footnotes.c,v 1.4 1997/07/24 21:23:33 karl Exp $
$Id: footnotes.c,v 1.9 1999/09/25 16:10:04 karl Exp $
Copyright (C) 1993, 97 Free Software Foundation, Inc.
Copyright (C) 1993, 97, 98, 99 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
@ -60,7 +60,7 @@ make_footnotes_node (node)
/* See if this node contains the magic footnote label. */
fn_start =
info_search_in_node (FOOTNOTE_LABEL, node, 0, (WINDOW *)NULL, 1);
info_search_in_node (FOOTNOTE_LABEL, node, 0, (WINDOW *)NULL, 1, 0);
/* If it doesn't, check to see if it has an associated footnotes node. */
if (fn_start == -1)
@ -73,16 +73,21 @@ make_footnotes_node (node)
{
register int i;
char *refname;
int reflen = strlen ("-Footnotes") + strlen (node->nodename);
refname = (char *)xmalloc
(1 + strlen ("-Footnotes") + strlen (node->nodename));
refname = (char *)xmalloc (reflen + 1);
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))
/* Support both the older "foo-Footnotes" and the new
style "foo-Footnote-NN" references. */
(strcmp (refs[i]->nodename, refname) == 0 ||
(strncmp (refs[i]->nodename, refname, reflen - 1) == 0 &&
refs[i]->nodename[reflen - 1] == '-' &&
isdigit (refs[i]->nodename[reflen]))))
{
char *filename;
@ -110,6 +115,7 @@ make_footnotes_node (node)
/* Make the new node. */
result = (NODE *)xmalloc (sizeof (NODE));
result->flags = 0;
result->display_pos = 0;
/* Get the size of the footnotes appearing within this node. */
{
@ -250,11 +256,11 @@ DECLARE_INFO_COMMAND (info_show_footnotes,
switch (result)
{
case FN_UNFOUND:
info_error (NO_FOOT_NODE);
info_error (msg_no_foot_node);
break;
case FN_UNABLE:
info_error (WIN_TOO_SMALL);
info_error (msg_win_too_small);
break;
}
}

View File

@ -1,10 +1,7 @@
/* footnotes.h -- Some functions for manipulating footnotes.
$Id: footnotes.h,v 1.3 1997/07/15 18:40:27 karl Exp $
$Id: footnotes.h,v 1.4 1998/11/29 21:44:49 karl Exp $
This file is part of GNU Info, a program for reading online documentation
stored in Info format.
Copyright (C) 1993, 97 Free Software Foundation, Inc.
Copyright (C) 1993, 97, 98 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
@ -26,7 +23,7 @@
#define INFO_FOOTNOTES_H
/* Magic string which indicates following text is footnotes. */
#define FOOTNOTE_LABEL _("---------- Footnotes ----------")
#define FOOTNOTE_LABEL N_("---------- Footnotes ----------")
#define FN_FOUND 0
#define FN_UNFOUND 1

View File

@ -12,15 +12,22 @@ extern void info_backward_word ();
extern void info_global_next_node ();
extern void info_global_prev_node ();
extern void info_scroll_forward ();
extern void info_scroll_forward_set_window ();
extern void info_scroll_backward ();
extern void info_scroll_backward_set_window ();
extern void info_beginning_of_node ();
extern void info_end_of_node ();
extern void info_down_line ();
extern void info_up_line ();
extern void info_scroll_half_screen_down ();
extern void info_scroll_half_screen_up ();
extern void info_next_window ();
extern void info_prev_window ();
extern void info_split_window ();
extern void info_delete_window ();
extern void info_keep_one_window ();
extern void info_scroll_other_window ();
extern void info_scroll_other_window_backward ();
extern void info_grow_window ();
extern void info_tile_windows ();
extern void info_toggle_wrap ();
@ -36,6 +43,8 @@ extern void info_xref_item ();
extern void info_find_menu ();
extern void info_visit_menu ();
extern void info_goto_node ();
extern void info_menu_sequence ();
extern void info_goto_invocation_node ();
extern void info_man ();
extern void info_top_node ();
extern void info_dir_node ();
@ -43,7 +52,11 @@ extern void info_history_node ();
extern void info_kill_node ();
extern void info_view_file ();
extern void info_print_node ();
extern void info_search_case_sensitively ();
extern void info_search ();
extern void info_search_backward ();
extern void info_search_next ();
extern void info_search_previous ();
extern void isearch_forward ();
extern void isearch_backward ();
extern void info_move_to_prev_xref ();

View File

@ -1,7 +1,7 @@
/* indices.c -- Commands for dealing with an Info file Index.
$Id: indices.c,v 1.6 1997/07/24 21:25:53 karl Exp $
/* indices.c -- deal with an Info file index.
$Id: indices.c,v 1.14 1999/09/25 16:10:04 karl Exp $
Copyright (C) 1993, 97 Free Software Foundation, Inc.
Copyright (C) 1993, 97, 98, 99 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
@ -199,7 +199,7 @@ do_info_index_search (window, count, search_string)
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))
(FILENAME_CMP (initial_index_filename, fb->filename) != 0))
{
info_free_references (index_index);
window_message_in_echo_area (_("Finding index entries..."));
@ -296,7 +296,7 @@ index_entry_exists (window, string)
fb = file_buffer_of_window (window);
if (!initial_index_filename
|| (strcmp (initial_index_filename, fb->filename) != 0))
|| (FILENAME_CMP (initial_index_filename, fb->filename) != 0))
{
info_free_references (index_index);
index_index = info_indices_of_file_buffer (fb);
@ -439,15 +439,12 @@ DECLARE_INFO_COMMAND (info_next_index_match,
if (!node)
{
info_error (CANT_FILE_NODE,
info_error (msg_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);
info_set_node_of_window (1, window, node);
/* Try to find an occurence of LABEL in this node. */
{
@ -497,11 +494,13 @@ apropos_in_all_indices (search_string, inform)
REFERENCE **this_index, *this_item;
NODE *this_node;
FILE_BUFFER *this_fb;
int dir_node_duplicated = 0;
this_item = dir_menu[dir_index];
if (!this_item->filename)
{
dir_node_duplicated = 1;
if (dir_node->parent)
this_item->filename = xstrdup (dir_node->parent);
else
@ -517,7 +516,11 @@ apropos_in_all_indices (search_string, inform)
this_node = info_get_node (this_item->label, "Top");
if (!this_node)
continue;
{
if (dir_node_duplicated)
free (this_item->filename);
continue;
}
/* Get the file buffer associated with this node. */
{
@ -529,6 +532,19 @@ apropos_in_all_indices (search_string, inform)
this_fb = info_find_file (files_name);
/* If we already scanned this file, don't do that again.
In addition to being faster, this also avoids having
multiple identical entries in the *Apropos* menu. */
for (i = 0; i < dir_index; i++)
if (FILENAME_CMP (this_fb->filename, dir_menu[i]->filename) == 0)
break;
if (i < dir_index)
{
if (dir_node_duplicated)
free (this_item->filename);
continue;
}
if (this_fb && inform)
message_in_echo_area (_("Scanning indices of \"%s\"..."), files_name);
@ -584,7 +600,7 @@ apropos_in_all_indices (search_string, inform)
}
#define APROPOS_NONE \
_("No available info files reference \"%s\" in their indices.")
N_("No available info files have \"%s\" in their indices.")
void
info_apropos (string)
@ -596,7 +612,7 @@ info_apropos (string)
if (!apropos_list)
{
info_error (APROPOS_NONE, string);
info_error (_(APROPOS_NONE), string);
}
else
{
@ -604,7 +620,7 @@ info_apropos (string)
REFERENCE *entry;
for (i = 0; (entry = apropos_list[i]); i++)
fprintf (stderr, "\"(%s)%s\" -- %s\n",
fprintf (stdout, "\"(%s)%s\" -- %s\n",
entry->filename, entry->nodename, entry->label);
}
info_free_references (apropos_list);
@ -638,7 +654,7 @@ DECLARE_INFO_COMMAND (info_index_apropos,
if (!apropos_list)
{
info_error (APROPOS_NONE, line);
info_error (_(APROPOS_NONE), line);
}
else
{
@ -653,10 +669,14 @@ DECLARE_INFO_COMMAND (info_index_apropos,
for (i = 0; apropos_list[i]; i++)
{
int len;
sprintf (line_buffer, "* (%s)%s::",
/* The label might be identical to that of another index
entry in another Info file. Therefore, we make the file
name part of the menu entry, to make them all distinct. */
sprintf (line_buffer, "* %s [%s]: ",
apropos_list[i]->label, apropos_list[i]->filename);
len = pad_to (40, line_buffer);
sprintf (line_buffer + len, "(%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);

View File

@ -1,9 +1,7 @@
/* info-utils.c -- Useful functions for manipulating Info file quirks. */
/* info-utils.c -- miscellanous.
$Id: info-utils.c,v 1.7 1998/08/10 18:07:47 karl Exp $
/* This file is part of GNU Info, a program for reading online documentation
stored in Info format.
Copyright (C) 1993 Free Software Foundation, Inc.
Copyright (C) 1993, 98 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
@ -29,7 +27,7 @@
/* When non-zero, various display and input functions handle ISO Latin
character sets correctly. */
int ISO_Latin_p = 0;
int ISO_Latin_p = 1;
/* Variable which holds the most recent filename parsed as a result of
calling info_parse_xxx (). */
@ -300,8 +298,8 @@ info_references_internal (label, binding)
return (refs);
}
/* Get the entry associated with LABEL in MENU. Return a pointer to the
REFERENCE if found, or NULL. */
/* Get the entry associated with LABEL in REFERENCES. Return a pointer
to the ENTRY if found, or NULL. */
REFERENCE *
info_get_labeled_reference (label, references)
char *label;
@ -444,19 +442,10 @@ printed_representation (character, hpos)
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))
int printable_limit = ISO_Latin_p ? 255 : 127;
/* Show CTRL-x as ^X. */
if (iscntrl (character) && character < 127)
{
switch (character)
{
@ -480,17 +469,23 @@ printed_representation (character, hpos)
the_rep[i++] = (character | 0x40);
}
}
/* Show META-x as 0370. */
else if (character > printable_limit)
{
sprintf (the_rep + i, "\\%0o", character);
i = strlen (the_rep);
}
else if (character == DEL)
{
the_rep[i++] = '^';
the_rep[i++] = '?';
}
else
the_rep[i++] = character;
the_rep[i] = '\0';
the_rep[i] = 0;
return (the_rep);
return the_rep;
}
@ -604,14 +599,13 @@ char *
filename_non_directory (pathname)
char *pathname;
{
char *filename;
register char *filename = pathname + strlen (pathname);
filename = (char *) strrchr (pathname, '/');
if (HAVE_DRIVE (pathname))
pathname += 2;
if (filename)
filename++;
else
filename = pathname;
while (filename > pathname && !IS_SLASH (filename[-1]))
filename--;
return (filename);
}
@ -663,3 +657,17 @@ get_internal_info_window (name)
return (win);
}
/* Return a window displaying the node NODE. */
WINDOW *
get_window_of_node (node)
NODE *node;
{
WINDOW *win = (WINDOW *)NULL;
for (win = windows; win; win = win->next)
if (win->node == node)
break;
return (win);
}

View File

@ -1,10 +1,7 @@
/* info-utils.h -- Exported functions and variables from info-util.c.
$Id: info-utils.h,v 1.3 1997/07/15 18:42:20 karl Exp $
/* info-utils.h -- Exported functions and variables from info-utils.c.
$Id: info-utils.h,v 1.5 1998/08/10 18:07:28 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.
Copyright (C) 1993, 96, 98 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
@ -25,13 +22,6 @@
#ifndef 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"
@ -118,22 +108,22 @@ extern void name_internal_node ();
Info window. */
extern WINDOW *get_internal_info_window ();
/* Return a window displaying the node NODE. */
extern WINDOW *get_window_of_node ();
/* 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 globals `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) \
if (!info_parsed_nodename && !info_parsed_filename) \
info_parse_label (INFO_ALTPREV_LABEL, n); \
} while (0)

View File

@ -1,7 +1,7 @@
/* info.c -- Display nodes of Info files in multiple windows.
$Id: info.c,v 1.18 1998/02/27 21:37:27 karl Exp $
$Id: info.c,v 1.41 1999/09/25 16:10:04 karl Exp $
Copyright (C) 1993, 96, 97, 98 Free Software Foundation, Inc.
Copyright (C) 1993, 96, 97, 98, 99 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
@ -27,12 +27,7 @@
# include "man.h"
#endif /* HANDLE_MAN_PAGES */
/* The version numbers of this version of Info. */
int info_major_version = 2;
int info_minor_version = 18;
/* basename (argv[0]) */
static char *program_name = NULL;
static char *program_name = "info";
/* Non-zero means search all indices for APROPOS_SEARCH_STRING. */
static int apropos_p = 0;
@ -44,8 +39,13 @@ static char *apropos_search_string = (char *)NULL;
apropos, this puts the user at the node, running info. */
static int index_search_p = 0;
/* Non-zero means look for the node which describes the invocation
and command-line options of the program, and start the info
session at that node. */
static int goto_invocation_p = 0;
/* Variable containing the string to search for when index_search_p is
non-zero. */
non-zero. */
static char *index_search_string = (char *)NULL;
/* Non-zero means print version info only. */
@ -73,6 +73,18 @@ static char *user_output_filename = (char *)NULL;
dumped in the order encountered. This basically can print a book. */
int dump_subnodes = 0;
/* Non-zero means make default keybindings be loosely modeled on vi(1). */
int vi_keys_p = 0;
#ifdef __MSDOS__
/* Non-zero indicates that screen output should be made 'speech-friendly'.
Since on MSDOS the usual behavior is to write directly to the video
memory, speech synthesizer software cannot grab the output. Therefore,
we provide a user option which tells us to avoid direct screen output
and use stdout instead (which loses the color output). */
int speech_friendly = 0;
#endif
/* 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. */
@ -87,22 +99,33 @@ static struct option long_options[] = {
{ "file", 1, 0, 'f' },
{ "subnodes", 0, &dump_subnodes, 1 },
{ "output", 1, 0, 'o' },
{ "show-options", 0, 0, 'O' },
{ "usage", 0, 0, 'O' },
{ "vi-keys", 0, &vi_keys_p, 1 },
{ "help", 0, &print_help_p, 1 },
{ "version", 0, &print_version_p, 1 },
{ "dribble", 1, 0, DRIBBLE_OPTION },
{ "restore", 1, 0, RESTORE_OPTION },
#ifdef __MSDOS__
{ "speech-friendly", 0, &speech_friendly, 1 },
#endif
{ "index-search", 1, 0, IDXSRCH_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";
#ifdef __MSDOS__
static char *short_options = "d:n:f:o:Osb";
#else
static char *short_options = "d:n:f:o:Os";
#endif
/* When non-zero, the Info window system has been initialized. */
int info_windows_initialized_p = 0;
/* Some "forward" declarations. */
static void info_short_help (), remember_info_program_name ();
static void init_messages ();
/* **************************************************************** */
@ -119,8 +142,6 @@ main (argc, argv)
int getopt_long_index; /* Index returned by getopt_long (). */
NODE *initial_node; /* First node loaded by Info. */
remember_info_program_name (argv[0]);
#ifdef HAVE_SETLOCALE
/* Set locale via LC_ALL. */
setlocale (LC_ALL, "");
@ -130,6 +151,8 @@ main (argc, argv)
bindtextdomain (PACKAGE, LOCALEDIR);
textdomain (PACKAGE);
init_messages ();
while (1)
{
int option_character;
@ -177,12 +200,25 @@ main (argc, argv)
user_output_filename = xstrdup (optarg);
break;
/* User has specified that she wants to find the "Options"
or "Invocation" node for the program. */
case 'O':
goto_invocation_p = 1;
break;
/* User is specifying that she wishes to dump the subnodes of
the node that she is dumping. */
case 's':
dump_subnodes = 1;
break;
#ifdef __MSDOS__
/* User specifies that she wants speech-friendly output. */
case 'b':
speech_friendly = 1;
break;
#endif /* __MSDOS__ */
/* User has specified a string to search all indices for. */
case APROPOS_OPTION:
apropos_p = 1;
@ -209,8 +245,8 @@ main (argc, argv)
break;
default:
fprintf (stderr, _("Try --help for more information."));
exit (1);
fprintf (stderr, _("Try --help for more information.\n"));
xexit (1);
}
}
@ -226,23 +262,23 @@ main (argc, argv)
/* If the user specified --version, then show the version and exit. */
if (print_version_p)
{
printf ("%s (GNU %s %s) %s\n", program_name, PACKAGE, VERSION,
version_string ());
printf ("%s (GNU %s) %s\n", program_name, PACKAGE, VERSION);
puts ("");
printf (_("Copyright (C) %s 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.\n"),
"1998");
exit (0);
"1999");
xexit (0);
}
/* If the `--help' option was present, show the help and exit. */
if (print_help_p)
{
info_short_help ();
exit (0);
xexit (0);
}
/* If the user hasn't specified a path for Info files, default it.
Lowest priority is our messy hardwired list in filesys.h.
Then comes the user's INFODIR from the Makefile.
@ -255,7 +291,7 @@ For more information about these matters, see the files named COPYING.\n"),
{
unsigned len = strlen (path_from_env);
/* Trailing : on INFOPATH means insert the default path. */
if (len && path_from_env[len - 1] == ':')
if (len && path_from_env[len - 1] == PATH_SEP[0])
{
path_from_env[len - 1] = 0;
info_add_path (DEFAULT_INFOPATH, INFOPATH_PREPEND);
@ -283,7 +319,14 @@ For more information about these matters, see the files named COPYING.\n"),
if (temp != directory_name)
{
*temp = 0;
if (HAVE_DRIVE (directory_name) && temp == directory_name + 2)
{
/* The directory of "d:foo" is stored as "d:.", to avoid
mixing it with "d:/" when a slash is appended. */
*temp = '.';
temp += 2;
}
temp[-1] = 0;
info_add_path (directory_name, INFOPATH_PREPEND);
}
@ -295,13 +338,13 @@ For more information about these matters, see the files named COPYING.\n"),
if (apropos_p)
{
info_apropos (apropos_search_string);
exit (0);
xexit (0);
}
/* Get the initial Info node. It is either "(dir)Top", or what the user
specifed with values in user_filename and user_nodenames. */
initial_node = info_get_node (user_filename,
user_nodenames ? user_nodenames[0] : NULL);
user_nodenames ? user_nodenames[0] : 0);
/* If we couldn't get the initial node, this user is in trouble. */
if (!initial_node)
@ -309,9 +352,9 @@ For more information about these matters, see the files named COPYING.\n"),
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);
info_error (msg_cant_find_node,
user_nodenames ? user_nodenames[0] : "Top");
xexit (1);
}
/* Special cases for when the user specifies multiple nodes. If we
@ -328,228 +371,112 @@ For more information about these matters, see the files named COPYING.\n"),
else
begin_multiple_window_info_session (user_filename, user_nodenames);
exit (0);
}
/* If the user specified `--index-search=STRING', start the info
session in the node corresponding to the first match. */
if (index_search_p)
{
int status = 0;
initialize_info_session (initial_node, 0);
if (index_entry_exists (windows, index_search_string))
{
terminal_clear_screen ();
terminal_prep_terminal ();
display_update_display (windows);
info_last_executed_command = (VFunction *)NULL;
do_info_index_search (windows, 0, index_search_string);
info_read_and_dispatch ();
terminal_unprep_terminal ();
/* On program exit, leave the cursor at the bottom of the
window, and restore the terminal IO. */
terminal_goto_xy (0, screenheight - 1);
terminal_clear_to_eol ();
fflush (stdout);
}
else
{
fputs (_("no entries found\n"), stderr);
status = 2;
}
close_dribble_file ();
exit (status);
xexit (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;
{
char *errstr, *errarg1, *errarg2;
NODE *new_initial_node = info_follow_menus (initial_node, argv + optind,
&errstr, &errarg1, &errarg2);
if (new_initial_node && new_initial_node != initial_node)
initial_node = new_initial_node;
/* Remember the name of the menu entry we want. */
arg = argv[optind++];
/* If the user specified that this node should be output, then do that
now. Otherwise, start the Info session with this node. Or act
accordingly if the initial node was not found. */
if (user_output_filename)
{
if (!errstr)
dump_node_to_file (initial_node, user_output_filename,
dump_subnodes);
else
info_error (errstr, errarg1, errarg2);
}
else
{
if (!first_arg)
first_arg = arg;
if (errstr)
begin_info_session_with_error (initial_node, errstr,
errarg1, errarg2);
/* If the user specified `--index-search=STRING' or
--show-options, start the info session in the node
corresponding to what they want. */
else if (index_search_p || goto_invocation_p)
{
int status = 0;
/* Build and return a list of the menu items in this node. */
menu = info_menu_of_node (initial_node);
initialize_info_session (initial_node, 0);
/* 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);
}
if (goto_invocation_p
|| index_entry_exists (windows, index_search_string))
{
terminal_prep_terminal ();
terminal_clear_screen ();
info_last_executed_command = (VFunction *)NULL;
/* Find the specified menu item. */
entry = info_get_labeled_reference (arg, menu);
if (index_search_p)
do_info_index_search (windows, 0, index_search_string);
else
{
/* If they said "info --show-options foo bar baz",
the last of the arguments is the program whose
options they want to see. */
char **p = argv + optind;
char *program;
/* 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;
if (*p)
{
while (p[1])
p++;
program = xstrdup (*p);
}
else if (user_filename)
/* If there's no command-line arguments to
supply the program name, use the Info file
name (sans extension and leading directories)
instead. */
program = program_name_from_file_name (user_filename);
else
program = xstrdup ("");
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;
}
info_intuit_options_node (windows, initial_node, program);
free (program);
}
if (!entry && best_guess != -1)
entry = menu[best_guess];
}
info_read_and_dispatch ();
/* 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.");
/* On program exit, leave the cursor at the bottom of the
window, and restore the terminal IO. */
terminal_goto_xy (0, screenheight - 1);
terminal_clear_to_eol ();
fflush (stdout);
terminal_unprep_terminal ();
}
else
{
fprintf (stderr, _("no index entries found for `%s'\n"),
index_search_string);
status = 2;
}
#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 */
close_dribble_file ();
xexit (status);
}
else
begin_info_session (initial_node);
}
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 = xstrdup (initial_node->parent);
else
entry->filename = xstrdup (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 = xstrdup (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);
}
return (vstring);
xexit (0);
}
}
/* Error handling. */
static void
remember_info_program_name (fullpath)
char *fullpath;
{
char *filename;
filename = filename_non_directory (fullpath);
program_name = xstrdup (filename);
}
/* Non-zero if an error has been signalled. */
int info_error_was_printed = 0;
@ -595,33 +522,99 @@ info_error (format, arg1, arg2)
}
}
/* Produce a scaled down description of the available options to Info. */
static void
info_short_help ()
{
printf (_("\
Usage: %s [OPTION]... [INFO-FILE [MENU-ITEM...]]\n\
Usage: %s [OPTION]... [MENU-ITEM...]\n\
\n\
Read documentation in Info format.\n\
For more complete documentation on how to use Info, run `info info options'.\n\
\n\
Options:\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 display this help and exit.\n\
--version display version information and exit.\n\
--apropos=SUBJECT look up SUBJECT in all indices of all manuals.\n\
--directory=DIR add DIR to INFOPATH.\n\
--dribble=FILENAME remember user keystrokes in FILENAME.\n\
--file=FILENAME specify Info file to visit.\n\
--help display this help and exit.\n\
--index-search=STRING go to node pointed by index entry STRING.\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\
--show-options, --usage go to command-line options node.\n\
--subnodes recursively output menu items.\n%s\
--vi-keys use vi-like and less-like key bindings.\n\
--version display version information and exit.\n\
\n\
The first argument, if present, is the name of the Info file to read.\n\
The first non-option argument, if present, is the menu entry to start from;\n\
it is searched for in all `dir' files along INFOPATH.\n\
If it is not present, info merges all `dir' files and shows the result.\n\
Any remaining arguments are treated as the names of menu\n\
items in the initial node visited. For example, `info emacs buffers'\n\
moves to the node `buffers' in the info file `emacs'.\n\
items relative to the initial node visited.\n\
\n\
Email bug reports to bug-texinfo@gnu.org."), program_name);
Examples:\n\
info show top-level dir menu\n\
info emacs start at emacs node from top-level dir\n\
info emacs buffers start at buffers node within emacs manual\n\
info --show-options emacs start at node with emacs' command line options\n\
info -f ./foo.info show file ./foo.info, not searching dir\n\
\n\
Email bug reports to bug-texinfo@gnu.org,\n\
general questions and discussion to help-texinfo@gnu.org.\n\
"),
program_name,
#ifdef __MSDOS__
"\
--speech-friendly be friendly to speech synthesizers.\n"
#else
""
#endif
);
exit (0);
xexit (0);
}
/* Initialize strings for gettext. Because gettext doesn't handle N_ or
_ within macro definitions, we put shared messages into variables and
use them that way. This also has the advantage that there's only one
copy of the strings. */
char *msg_cant_find_node;
char *msg_cant_file_node;
char *msg_cant_find_window;
char *msg_cant_find_point;
char *msg_cant_kill_last;
char *msg_no_menu_node;
char *msg_no_foot_node;
char *msg_no_xref_node;
char *msg_no_pointer;
char *msg_unknown_command;
char *msg_term_too_dumb;
char *msg_at_node_bottom;
char *msg_at_node_top;
char *msg_one_window;
char *msg_win_too_small;
char *msg_cant_make_help;
static void
init_messages ()
{
msg_cant_find_node = _("Cannot find node `%s'.");
msg_cant_file_node = _("Cannot find node `(%s)%s'.");
msg_cant_find_window = _("Cannot find a window!");
msg_cant_find_point = _("Point doesn't appear within this window's node!");
msg_cant_kill_last = _("Cannot delete the last window.");
msg_no_menu_node = _("No menu in this node.");
msg_no_foot_node = _("No footnotes in this node.");
msg_no_xref_node = _("No cross references in this node.");
msg_no_pointer = _("No `%s' pointer for this node.");
msg_unknown_command = _("Unknown Info command `%c'; try `?' for help.");
msg_term_too_dumb = _("Terminal type `%s' is not smart enough to run Info.");
msg_at_node_bottom = _("You are already at the last page of this node.");
msg_at_node_top = _("You are already at the first page of this node.");
msg_one_window = _("Only one window.");
msg_win_too_small = _("Resulting window would be too small.");
msg_cant_make_help = _("Not enough room for a help window, please delete a window.");
}

View File

@ -1,10 +1,7 @@
/* info.h -- Header file which includes all of the other headers.
$Id: info.h,v 1.7 1998/02/27 21:36:04 karl Exp $
$Id: info.h,v 1.14 1999/09/25 16:10:04 karl Exp $
This file is part of GNU Info, a program for reading online documentation
stored in Info format.
Copyright (C) 1993, 97, 98 Free Software Foundation, Inc.
Copyright (C) 1993, 97, 98, 99 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
@ -22,7 +19,7 @@
Written by Brian Fox (bfox@ai.mit.edu). */
#if !defined (INFO_H)
#ifndef INFO_H
#define INFO_H
/* We always want these, so why clutter up the compile command? */
@ -119,6 +116,9 @@ extern int info_error_was_printed;
/* Non-zero means ring terminal bell on errors. */
extern int info_error_rings_bell_p;
/* Non-zero means default keybindings are loosely modeled on vi(1). */
extern int vi_keys_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. */
@ -127,28 +127,23 @@ extern void info_error ();
/* The version numbers of Info. */
extern int info_major_version, info_minor_version;
/* 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.")
extern char *msg_cant_find_node;
extern char *msg_cant_file_node;
extern char *msg_cant_find_window;
extern char *msg_cant_find_point;
extern char *msg_cant_kill_last;
extern char *msg_no_menu_node;
extern char *msg_no_foot_node;
extern char *msg_no_xref_node;
extern char *msg_no_pointer;
extern char *msg_unknown_command;
extern char *msg_term_too_dumb;
extern char *msg_at_node_bottom;
extern char *msg_at_node_top;
extern char *msg_one_window;
extern char *msg_win_too_small;
extern char *msg_cant_make_help;
/* Found in info-utils.c. */

View File

@ -1,7 +1,7 @@
/* infodoc.c -- Functions which build documentation nodes.
$Id: infodoc.c,v 1.4 1997/07/25 21:08:40 karl Exp $
$Id: infodoc.c,v 1.23 1999/09/25 16:10:04 karl Exp $
Copyright (C) 1993, 97 Free Software Foundation, Inc.
Copyright (C) 1993, 97, 98, 99 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
@ -21,14 +21,9 @@
#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 */
/* HELP_NODE_GETS_REGENERATED is always defined now that keys may get
rebound, or other changes in the help text may occur. */
#define HELP_NODE_GETS_REGENERATED 1
/* **************************************************************** */
/* */
@ -47,40 +42,94 @@ 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[] = {
N_ ("Basic Commands in Info Windows"),
"******************************",
"",
" h Invoke the Info tutorial.",
" CTRL-x 0 Quit this help.",
" q Quit Info altogether.",
"",
"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.",
"",
"Other commands:",
"--------------------",
" 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.",
N_("Basic Commands in Info Windows\n"),
N_("******************************\n"),
"\n",
N_(" %-10s Quit this help.\n"),
N_(" %-10s Quit Info altogether.\n"),
N_(" %-10s Invoke the Info tutorial.\n"),
"\n",
N_("Moving within a node:\n"),
N_("---------------------\n"),
N_(" %-10s Scroll forward a page.\n"),
N_(" %-10s Scroll backward a page.\n"),
N_(" %-10s Go to the beginning of this node.\n"),
N_(" %-10s Go to the end of this node.\n"),
N_(" %-10s Scroll forward 1 line.\n"),
N_(" %-10s Scroll backward 1 line.\n"),
"\n",
N_("Selecting other nodes:\n"),
N_("----------------------\n"),
N_(" %-10s Move to the `next' node of this node.\n"),
N_(" %-10s Move to the `previous' node of this node.\n"),
N_(" %-10s Move `up' from this node.\n"),
N_(" %-10s Pick menu item specified by name.\n"),
N_(" Picking a menu item causes another node to be selected.\n"),
N_(" %-10s Follow a cross reference. Reads name of reference.\n"),
N_(" %-10s Move to the last node seen in this window.\n"),
N_(" %-10s Skip to next hypertext link within this node.\n"),
N_(" %-10s Follow the hypertext link under cursor.\n"),
N_(" %-10s Move to the `directory' node. Equivalent to `g (DIR)'.\n"),
N_(" %-10s Move to the Top node. Equivalent to `g Top'.\n"),
"\n",
N_("Other commands:\n"),
N_("---------------\n"),
N_(" %-10s Pick first ... ninth item in node's menu.\n"),
N_(" %-10s Pick last item in node's menu.\n"),
N_(" %-10s Search for a specified string in the index entries of this Info\n"),
N_(" file, and select the node referenced by the first entry found.\n"),
N_(" %-10s Move to node specified by name.\n"),
N_(" You may include a filename as well, as in (FILENAME)NODENAME.\n"),
N_(" %-10s Search forward through this Info file for a specified string,\n"),
N_(" and select the node in which the next occurrence is found.\n"),
N_(" %-10s Search backward in this Info file for a specified string,\n"),
N_(" and select the node in which the next occurrence is found.\n"),
NULL
};
static char *info_help_keys_text[][2] = {
{ "", "" },
{ "", "" },
{ "", "" },
{ "CTRL-x 0", "CTRL-x 0" },
{ "q", "q" },
{ "h", "ESC h" },
{ "", "" },
{ "", "" },
{ "", "" },
{ "SPC", "SPC" },
{ "DEL", "b" },
{ "b", "ESC b" },
{ "e", "ESC e" },
{ "ESC 1 SPC", "RET" },
{ "ESC 1 DEL", "y" },
{ "", "" },
{ "", "" },
{ "", "" },
{ "n", "CTRL-x n" },
{ "p", "CTRL-x p" },
{ "u", "CTRL-x u" },
{ "m", "ESC m" },
{ "", "" },
{ "f", "ESC f" },
{ "l", "l" },
{ "TAB", "TAB" },
{ "RET", "CTRL-x RET" },
{ "d", "ESC d" },
{ "t", "ESC t" },
{ "", "" },
{ "", "" },
{ "", "" },
{ "1-9", "ESC 1-9" },
{ "0", "ESC 0" },
{ "i", "CTRL-x i" },
{ "", "" },
{ "g", "CTRL-x g" },
{ "", "" },
{ "s", "/" },
{ "", "" },
{ "ESC - s", "?" },
{ "", "" },
NULL
};
@ -163,15 +212,21 @@ dump_map_to_message_buffer (prefix, map)
}
}
/* How to create internal_info_help_node. */
/* How to create internal_info_help_node. HELP_IS_ONLY_WINDOW_P says
whether we're going to end up in a second (or more) window of our
own, or whether there's only one window and we're going to usurp it.
This determines how to quit the help window. Maybe we should just
make q do the right thing in both cases. */
static void
create_internal_info_help_node ()
create_internal_info_help_node (help_is_only_window_p)
int help_is_only_window_p;
{
register int i;
char *contents = (char *)NULL;
NODE *node;
char *contents = NULL;
#if !defined (HELP_NODE_GETS_REGENERATED)
#ifndef HELP_NODE_GETS_REGENERATED
if (internal_info_help_node_contents)
contents = internal_info_help_node_contents;
#endif /* !HELP_NODE_GETS_REGENERATED */
@ -183,16 +238,30 @@ create_internal_info_help_node ()
initialize_message_buffer ();
for (i = 0; info_internal_help_text[i]; i++)
printf_to_message_buffer ("%s\n", info_internal_help_text[i]);
{
/* Don't translate blank lines, gettext outputs the po file
header in that case. We want a blank line. */
char *msg = *(info_internal_help_text[i])
? _(info_internal_help_text[i])
: info_internal_help_text[i];
char *key = info_help_keys_text[i][vi_keys_p];
/* If we have only one window (because the window size was too
small to split it), CTRL-x 0 doesn't work to `quit' help. */
if (STREQ (key, "CTRL-x 0") && help_is_only_window_p)
key = "l";
printf_to_message_buffer (msg, key);
}
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 (_("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");
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");
printf_to_message_buffer (_("Commands available in the echo area:\n\n"));
dump_map_to_message_buffer ("", echo_area_keymap);
#if defined (NAMED_FUNCTIONS)
@ -215,7 +284,11 @@ create_internal_info_help_node ()
printf_to_message_buffer
("M-x %s\n %s\n",
function_doc_array[i].func_name,
replace_in_documentation (function_doc_array[i].doc));
replace_in_documentation (strlen (function_doc_array[i].doc)
== 0
? function_doc_array[i].doc
: _(function_doc_array[i].doc)));
}
}
@ -258,17 +331,22 @@ create_internal_info_help_node ()
}
/* Return a window which is the window showing help in this Info. */
/* If the eligible window's height is >= this, split it to make the help
window. Otherwise display the help window in the current window. */
#define HELP_SPLIT_SIZE 24
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);
int help_is_only_window_p;
WINDOW *eligible = NULL;
WINDOW *help_window = get_window_of_node (internal_info_help_node);
/* If we couldn't find the help window, then make it. */
if (!help_window)
{
WINDOW *window;
int max = 0;
for (window = windows; window; window = window->next)
@ -281,23 +359,29 @@ info_find_or_create_help_window ()
}
if (!eligible)
return ((WINDOW *)NULL);
return NULL;
}
#if !defined (HELP_NODE_GETS_REGENERATED)
#ifndef HELP_NODE_GETS_REGENERATED
else
return (help_window);
#endif /* !HELP_NODE_GETS_REGENERATED */
/* help window is static, just return it. */
return help_window;
#endif /* not HELP_NODE_GETS_REGENERATED */
/* Make sure that we have a node containing the help text. */
create_internal_info_help_node ();
/* Make sure that we have a node containing the help text. The
argument is false if help will be the only window (so l must be used
to quit help), true if help will be one of several visible windows
(so CTRL-x 0 must be used to quit help). */
help_is_only_window_p
= (help_window && !windows->next
|| !help_window && eligible->height < HELP_SPLIT_SIZE);
create_internal_info_help_node (help_is_only_window_p);
/* 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
{ /* Split the largest window into 2 windows, and show the help text
in that window. */
if (eligible->height > 30)
if (eligible->height >= HELP_SPLIT_SIZE)
{
active_window = eligible;
help_window = window_make_window (internal_info_help_node);
@ -310,8 +394,7 @@ info_find_or_create_help_window ()
}
}
else
{
/* Case where help node always gets regenerated, and we have an
{ /* Case where help node always gets regenerated, and we have an
existing window in which to place the node. */
if (active_window != help_window)
{
@ -321,7 +404,7 @@ info_find_or_create_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);
return help_window;
}
/* Create or move to the help window. */
@ -337,7 +420,7 @@ DECLARE_INFO_COMMAND (info_get_help_window, _("Display help message"))
}
else
{
info_error (CANT_MAKE_HELP);
info_error (msg_cant_make_help);
}
}
@ -381,7 +464,7 @@ DECLARE_INFO_COMMAND (info_get_info_help_node, _("Visit Info node `(info)Help'")
if (info_recent_file_error)
info_error (info_recent_file_error);
else
info_error (CANT_FILE_NODE, "Info", nodename);
info_error (msg_cant_file_node, "Info", nodename);
}
else
{
@ -418,7 +501,9 @@ function_documentation (function)
if (function == function_doc_array[i].func)
break;
return (replace_in_documentation (function_doc_array[i].doc));
return replace_in_documentation ((strlen (function_doc_array[i].doc) == 0)
? function_doc_array[i].doc
: _(function_doc_array[i].doc));
}
#if defined (NAMED_FUNCTIONS)
@ -475,21 +560,21 @@ DECLARE_INFO_COMMAND (describe_key, _("Print documentation for KEY"))
char *rep;
Keymap map;
keyname[0] = '\0';
keyname[0] = 0;
map = window->keymap;
while (1)
for (;;)
{
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 (Meta_p (keystroke))
{
if (map[ESC].type != ISKMAP)
{
window_message_in_echo_area
(_("ESC %s is undefined."), pretty_keyname (UnMeta (keystroke)));
(_("ESC %s is undefined."), pretty_keyname (UnMeta (keystroke)));
return;
}
@ -627,7 +712,7 @@ replace_in_documentation (string)
/* 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
/* 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)
@ -687,7 +772,7 @@ where_is_internal (map, function)
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++)
@ -718,13 +803,13 @@ where_is_internal (map, function)
}
}
return ((char *)NULL);
return NULL;
}
extern char *read_function_name ();
DECLARE_INFO_COMMAND (info_where_is,
"Show what to type to execute a given command")
_("Show what to type to execute a given command"))
{
char *command_name;

View File

@ -1,7 +1,7 @@
/* infomap.c -- Keymaps for Info.
$Id: infomap.c,v 1.7 1997/07/31 20:37:32 karl Exp $
$Id: infomap.c,v 1.20 1999/06/25 21:57:40 karl Exp $
Copyright (C) 1993, 97 Free Software Foundation, Inc.
Copyright (C) 1993, 97, 98, 99 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
@ -67,7 +67,7 @@ keymap_copy_keymap (map)
return (keymap);
}
/* Free the keymap and it's descendents. */
/* Free the keymap and its descendants. */
void
keymap_discard_keymap (map)
Keymap (map);
@ -141,49 +141,54 @@ keymap_bind_keyseq (map, keyseq, keyentry)
/* Initialize the standard info keymaps. */
Keymap info_keymap = (Keymap)NULL;
Keymap echo_area_keymap = (Keymap)NULL;
Keymap info_keymap = NULL;
Keymap echo_area_keymap = NULL;
void
initialize_info_keymaps ()
static void
initialize_emacs_like_keymaps ()
{
register int i;
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 ();
}
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 ();
/* Bind the echo area insert routines. Let's make all characters
insertable by default, regardless of which character set we might
be using. */
for (i = 0; i < 256; i++)
echo_area_keymap[i].function = ea_insert;
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)[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;
info_keymap['-'].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;
@ -203,7 +208,12 @@ initialize_info_keymaps ()
map[SPC].function = ea_complete;
map[TAB].function = ea_complete;
map['?'].function = ea_possible_completions;
#ifdef __MSDOS__
/* PC users will lynch me if I don't give them their usual DEL effect... */
map[DEL].function = ea_delete;
#else
map[DEL].function = ea_rubout;
#endif
/* Bind the echo area ESC keymap. */
map = (Keymap)echo_area_keymap[ESC].function;
@ -272,6 +282,7 @@ initialize_info_keymaps ()
map[Control ('u')].function = info_universal_argument;
map[Control ('v')].function = info_scroll_forward;
map[','].function = info_next_index_match;
map['/'].function = info_search;
for (i = '1'; i < '9' + 1; i++)
map[i].function = info_menu_digit;
@ -288,15 +299,19 @@ initialize_info_keymaps ()
map['e'].function = info_end_of_node;
map['f'].function = info_xref_item;
map['g'].function = info_goto_node;
map['G'].function = info_menu_sequence;
map['h'].function = info_get_info_help_node;
map['i'].function = info_index_search;
map['I'].function = info_goto_invocation_node;
map['l'].function = info_history_node;
map['m'].function = info_menu_item;
map['n'].function = info_next_node;
map['O'].function = info_goto_invocation_node;
map['p'].function = info_prev_node;
map['q'].function = info_quit;
map['r'].function = info_xref_item;
map['s'].function = info_search;
map['S'].function = info_search_case_sensitively;
map['t'].function = info_top_node;
map['u'].function = info_up_node;
map[DEL].function = info_scroll_backward;
@ -316,6 +331,7 @@ initialize_info_keymaps ()
#if defined (NAMED_FUNCTIONS)
map['x'].function = info_execute_command;
#endif /* NAMED_FUNCTIONS */
map[DEL].function = info_scroll_other_window_backward;
/* Bind members in the Control-X map for Info windows. */
map = (Keymap)info_keymap[Control ('x')].function;
@ -331,6 +347,8 @@ initialize_info_keymaps ()
map['^'].function = info_grow_window;
map['b'].function = select_visited_node;
map['k'].function = info_kill_node;
map['n'].function = info_search_next;
map['N'].function = info_search_previous;
map['o'].function = info_next_window;
map['t'].function = info_tile_windows;
map['w'].function = info_toggle_wrap;
@ -359,6 +377,7 @@ initialize_info_keymaps ()
keymap_bind_keyseq (map, "\033OB", &map['f']);
keymap_bind_keyseq (map, "\033[B", &map['f']);
keymap_bind_keyseq (map, term_kN, &map[Control ('v')]); /* pagedown */
keymap_bind_keyseq (map, term_kP, &map[DEL]); /* pageup */
/* The alternative to this definition of a `main map' key in the
`ESC map' section, is something like:
@ -366,3 +385,297 @@ initialize_info_keymaps ()
*/
keymap_bind_keyseq (info_keymap/*sic*/, term_kP, &map['v']); /* pageup */
}
static void
initialize_vi_like_keymaps ()
{
register int i;
Keymap map;
if (!info_keymap)
{
info_keymap = keymap_make_keymap ();
echo_area_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 ();
/* Bind the echo area insert routines. */
for (i = 0; i < 256; i++)
echo_area_keymap[i].function = ea_insert;
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++)
{
info_keymap[i].function =
((Keymap) echo_area_keymap[ESC].function)[i].function =
info_add_digit_to_numeric_arg;
}
info_keymap['-'].function =
((Keymap) echo_area_keymap[ESC].function)['-'].function =
info_add_digit_to_numeric_arg;
/* Bind the echo area routines. */
map = echo_area_keymap;
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 = ea_abort;
map[Control ('v')].function = ea_quoted_insert;
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;
#ifdef __MSDOS__
/* PC users will lynch me if I don't give them their usual DEL effect... */
map[DEL].function = ea_delete;
#else
map[DEL].function = ea_rubout;
#endif
/* Bind the echo area ESC keymap. */
map = (Keymap)echo_area_keymap[ESC].function;
map[Control ('g')].function = ea_abort;
map[Control ('h')].function = ea_backward_kill_word;
map[Control ('v')].function = ea_scroll_completions_window;
map['0'].function = ea_beg_of_line;
map['$'].function = ea_end_of_line;
map['b'].function = ea_backward_word;
map['d'].function = ea_kill_word;
map['f'].function = ea_forward_word;
map['h'].function = ea_forward;
map['l'].function = ea_backward;
map['w'].function = ea_forward_word;
map['x'].function = ea_delete;
map['X'].function = ea_kill_word;
map['y'].function = ea_yank_pop;
map['?'].function = ea_possible_completions;
map[TAB].function = ea_tab_insert;
map[DEL].function = ea_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;
/* Arrow key bindings for echo area keymaps. It seems that some
terminals do not match their termcap entries, so it's best to just
define everything with both of the usual prefixes. */
map = echo_area_keymap;
keymap_bind_keyseq (map, term_ku, &map[Control ('p')]); /* up */
keymap_bind_keyseq (map, "\033OA", &map[Control ('p')]);
keymap_bind_keyseq (map, "\033[A", &map[Control ('p')]);
keymap_bind_keyseq (map, term_kd, &map[Control ('n')]); /* down */
keymap_bind_keyseq (map, "\033OB", &map[Control ('n')]);
keymap_bind_keyseq (map, "\033[B", &map[Control ('n')]);
keymap_bind_keyseq (map, term_kr, &map[Control ('f')]); /* right */
keymap_bind_keyseq (map, "\033OC", &map[Control ('f')]);
keymap_bind_keyseq (map, "\033[C", &map[Control ('f')]);
keymap_bind_keyseq (map, term_kl, &map[Control ('b')]); /* left */
keymap_bind_keyseq (map, "\033OD", &map[Control ('b')]);
keymap_bind_keyseq (map, "\033[D", &map[Control ('b')]);
map = (Keymap)echo_area_keymap[ESC].function;
keymap_bind_keyseq (map, term_kl, &map['b']); /* left */
keymap_bind_keyseq (map, "\033OA", &map['b']);
keymap_bind_keyseq (map, "\033[A", &map['b']);
keymap_bind_keyseq (map, term_kr, &map['f']); /* right */
keymap_bind_keyseq (map, "\033OB", &map['f']);
keymap_bind_keyseq (map, "\033[B", &map['f']);
/* Bind commands for Info window keymaps. */
map = info_keymap;
map[TAB].function = info_move_to_next_xref;
map[LFD].function = info_down_line;
map[RET].function = info_down_line;
map[SPC].function = info_scroll_forward;
map[Control ('a')].function = info_beginning_of_line;
map[Control ('b')].function = info_scroll_backward;
map[Control ('d')].function = info_scroll_half_screen_down;
map[Control ('e')].function = info_down_line;
map[Control ('f')].function = info_scroll_forward;
map[Control ('g')].function = info_abort_key;
map[Control ('k')].function = info_up_line;
map[Control ('l')].function = info_redraw_display;
map[Control ('n')].function = info_down_line;
map[Control ('p')].function = info_up_line;
map[Control ('r')].function = info_redraw_display;
map[Control ('s')].function = isearch_forward;
map[Control ('u')].function = info_scroll_half_screen_up;
map[Control ('v')].function = info_scroll_forward;
map[Control ('y')].function = info_up_line;
map[','].function = info_next_index_match;
map['/'].function = info_search;
for (i = '1'; i < '9' + 1; i++)
((Keymap) info_keymap[ESC].function)[i].function = info_menu_digit;
((Keymap) info_keymap[ESC].function)['0'].function = info_last_menu_item;
map['<'].function = info_first_node;
map['>'].function = info_last_node;
map['?'].function = info_search_backward;
map['['].function = info_global_prev_node;
map[']'].function = info_global_next_node;
map['\''].function = info_history_node;
map['b'].function = info_scroll_backward;
map['d'].function = info_scroll_half_screen_down;
map['e'].function = info_down_line;
map['E'].function = info_view_file;
map['f'].function = info_scroll_forward;
map['F'].function = info_scroll_forward;
map['g'].function = info_first_node;
map['G'].function = info_last_node;
map['h'].function = info_get_help_window;
map['H'].function = info_get_help_window;
map['i'].function = info_index_search;
map['I'].function = info_goto_invocation_node;
map['j'].function = info_down_line;
map['k'].function = info_up_line;
map['l'].function = info_history_node;
map['m'].function = info_menu_item;
map['n'].function = info_search_next;
map['N'].function = info_search_previous;
map['O'].function = info_goto_invocation_node;
map['p'].function = info_prev_node;
map['q'].function = info_quit;
map['Q'].function = info_quit;
map['r'].function = info_redraw_display;
map['R'].function = info_redraw_display;
map['s'].function = info_search;
map['S'].function = info_search_case_sensitively;
map['t'].function = info_top_node;
map['u'].function = info_scroll_half_screen_up;
map['w'].function = info_scroll_backward_set_window;
map['y'].function = info_up_line;
map['z'].function = info_scroll_forward_set_window;
map['Z'].function = NULL; /* unbind, so it works to bind "ZZ" below */
map[DEL].function = info_scroll_backward;
keymap_bind_keyseq (map, ":q", &map['q']);
keymap_bind_keyseq (map, ":Q", &map['q']);
keymap_bind_keyseq (map, "ZZ", &map['q']);
/* 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[SPC].function = info_scroll_forward;
map[Control ('v')].function = info_scroll_other_window;
map['<'].function = info_beginning_of_node;
map['>'].function = info_end_of_node;
map['/'].function = info_search;
map['?'].function = info_search_backward;
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_select_reference_this_line;
map['h'].function = info_get_info_help_node;
map['m'].function = info_menu_item;
map['n'].function = info_search;
map['N'].function = info_search_backward;
map['r'].function = isearch_backward;
map['s'].function = isearch_forward;
map['t'].function = info_top_node;
map['v'].function = info_scroll_backward;
#if defined (NAMED_FUNCTIONS)
map['x'].function = info_execute_command;
#endif /* NAMED_FUNCTIONS */
map[DEL].function = info_scroll_other_window_backward;
/* 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[LFD].function = info_select_reference_this_line;
map[RET].function = info_select_reference_this_line;
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['g'].function = info_goto_node;
map['i'].function = info_index_search;
map['I'].function = info_goto_invocation_node;
map['k'].function = info_kill_node;
map['n'].function = info_next_node;
map['o'].function = info_next_window;
map['O'].function = info_goto_invocation_node;
map['p'].function = info_prev_node;
map['r'].function = info_xref_item;
map['t'].function = info_tile_windows;
map['u'].function = info_up_node;
map['w'].function = info_toggle_wrap;
map[','].function = info_next_index_match;
keymap_bind_keyseq (info_keymap, ":e", &map[Control ('v')]);
/* Arrow key bindings for Info windows keymap. */
map = info_keymap;
keymap_bind_keyseq (map, term_kN, &map[Control ('v')]); /* pagedown */
keymap_bind_keyseq (map, term_ku, &map[Control ('p')]); /* up */
keymap_bind_keyseq (map, "\033OA", &map[Control ('p')]);
keymap_bind_keyseq (map, "\033[A", &map[Control ('p')]);
keymap_bind_keyseq (map, term_kd, &map[Control ('n')]); /* down */
keymap_bind_keyseq (map, "\033OB", &map[Control ('n')]);
keymap_bind_keyseq (map, "\033[B", &map[Control ('n')]);
keymap_bind_keyseq (map, term_kr, &map[Control ('f')]); /* right */
keymap_bind_keyseq (map, "\033OC", &map[Control ('f')]);
keymap_bind_keyseq (map, "\033[C", &map[Control ('f')]);
keymap_bind_keyseq (map, term_kl, &map[Control ('b')]); /* left */
keymap_bind_keyseq (map, "\033OD", &map[Control ('b')]);
keymap_bind_keyseq (map, "\033[D", &map[Control ('b')]);
map = (Keymap)info_keymap[ESC].function;
keymap_bind_keyseq (map, term_kl, &map['b']); /* left */
keymap_bind_keyseq (map, "\033OA", &map['b']);
keymap_bind_keyseq (map, "\033[A", &map['b']);
keymap_bind_keyseq (map, term_kr, &map['f']); /* right */
keymap_bind_keyseq (map, "\033OB", &map['f']);
keymap_bind_keyseq (map, "\033[B", &map['f']);
keymap_bind_keyseq (map, term_kN, &map[Control ('v')]); /* pagedown */
keymap_bind_keyseq (map, term_kP, &map[DEL]); /* pageup */
/* The alternative to this definition of a `main map' key in the
`ESC map' section, is something like:
keymap_bind_keyseq (map, term_kP, &((KeyMap)map[ESC].function).map['v']);
*/
keymap_bind_keyseq (info_keymap/*sic*/, term_kP, &map['v']); /* pageup */
}
void
initialize_info_keymaps ()
{
if (vi_keys_p)
initialize_vi_like_keymaps ();
else
initialize_emacs_like_keymaps ();
}

View File

@ -1,7 +1,7 @@
/* m-x.c -- Meta-X minibuffer reader.
$Id: m-x.c,v 1.5 1997/07/24 21:28:00 karl Exp $
/* m-x.c -- Meta-x minibuffer reader.
$Id: m-x.c,v 1.8 1999/06/25 21:57:40 karl Exp $
Copyright (C) 1993, 97 Free Software Foundation, Inc.
Copyright (C) 1993, 97, 98 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
@ -149,7 +149,7 @@ DECLARE_INFO_COMMAND (info_execute_command,
DECLARE_INFO_COMMAND (set_screen_height,
_("Set the height of the displayed window"))
{
int new_height;
int new_height, old_height = screenheight;
if (info_explicit_arg || count != 1)
new_height = count;
@ -185,6 +185,20 @@ DECLARE_INFO_COMMAND (set_screen_height,
terminal_clear_screen ();
display_clear_display (the_display);
screenheight = new_height;
display_initialize_display (screenwidth, screenheight);
window_new_screen_size (screenwidth, screenheight);
#ifdef SET_SCREEN_SIZE_HELPER
SET_SCREEN_SIZE_HELPER;
#endif
if (screenheight == old_height)
{
/* Display dimensions didn't actually change, so
window_new_screen_size won't do anything, but we've
already cleared the display above. Undo the damage. */
window_mark_chain (windows, W_UpdateWindow);
display_update_display (windows);
}
else
{
display_initialize_display (screenwidth, screenheight);
window_new_screen_size (screenwidth, screenheight);
}
}

View File

@ -1,7 +1,7 @@
/* man.c: How to read and format man files.
$Id: man.c,v 1.6 1997/07/31 23:49:59 karl Exp $
$Id: man.c,v 1.13 1999/07/05 20:43:23 karl Exp $
Copyright (C) 1995, 97 Free Software Foundation, Inc.
Copyright (C) 1995, 97, 98, 99 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
@ -44,6 +44,14 @@
# endif /* !hpux */
#endif /* FD_SET */
#if STRIP_DOT_EXE
static char const * const exec_extensions[] = {
".exe", ".com", ".bat", ".btm", ".sh", ".ksh", ".pl", ".sed", "", NULL
};
#else
static char const * const exec_extensions[] = { "", NULL };
#endif
static char *read_from_fd ();
static void clean_manpage ();
static NODE *manpage_node_of_file_buffer ();
@ -76,6 +84,7 @@ get_manpage_node (file_buffer, pagename)
char header[1024];
long oldsize, newsize;
int hlen, plen;
char *old_contents = file_buffer->contents;
sprintf (header, "\n\n%c\n%s %s, %s %s, %s (dir)\n\n",
INFO_COOKIE,
@ -89,13 +98,49 @@ get_manpage_node (file_buffer, pagename)
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);
memcpy (file_buffer->contents + oldsize + hlen, 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);
/* We have just relocated file_buffer->contents from under
the feet of info_windows[] array. Therefore, all the
nodes on that list which are showing man pages have their
contents member pointing into the blue. Undo that harm. */
if (old_contents && oldsize && old_contents != file_buffer->contents)
{
int iw;
INFO_WINDOW *info_win;
char *old_contents_end = old_contents + oldsize;
for (iw = 0; (info_win = info_windows[iw]); iw++)
{
int in;
for (in = 0; in < info_win->nodes_index; in++)
{
NODE *node = info_win->nodes[in];
/* It really only suffices to see that node->filename
is "*manpages*". But after several hours of
debugging this, would you blame me for being a bit
paranoid? */
if (node && node->filename && node->contents &&
strcmp (node->filename,
MANPAGE_FILE_BUFFER_NAME) == 0 &&
node->contents >= old_contents &&
node->contents + node->nodelen <= old_contents_end)
{
info_win->nodes[in] =
manpage_node_of_file_buffer (file_buffer,
node->nodename);
free (node->nodename);
free (node);
}
}
}
}
}
node = manpage_node_of_file_buffer (file_buffer, pagename);
@ -134,6 +179,8 @@ executable_file_in_path (filename, path)
while ((temp_dirname = extract_colon_unit (path, &dirname_index)))
{
char *temp;
char *temp_end;
int i;
/* Expand a leading tilde if one is present. */
if (*temp_dirname == '~')
@ -145,22 +192,30 @@ executable_file_in_path (filename, path)
temp_dirname = expanded_dirname;
}
temp = (char *)xmalloc (30 + strlen (temp_dirname) + strlen (filename));
temp = (char *)xmalloc (34 + strlen (temp_dirname) + strlen (filename));
strcpy (temp, temp_dirname);
if (temp[(strlen (temp)) - 1] != '/')
if (!IS_SLASH (temp[(strlen (temp)) - 1]))
strcat (temp, "/");
strcat (temp, filename);
temp_end = temp + strlen (temp);
free (temp_dirname);
statable = (stat (temp, &finfo) == 0);
/* Look for FILENAME, possibly with any of the extensions
in EXEC_EXTENSIONS[]. */
for (i = 0; exec_extensions[i]; i++)
{
if (exec_extensions[i][0])
strcpy (temp_end, exec_extensions[i]);
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);
/* 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);
}
free (temp);
}
return ((char *)NULL);
}
@ -210,13 +265,14 @@ get_page_and_section (pagename)
}
}
#if PIPE_USE_FORK
static void
reap_children (sig)
int sig;
{
int status;
wait (&status);
wait (NULL);
}
#endif
static char *
get_manpage_contents (pagename)
@ -225,7 +281,8 @@ get_manpage_contents (pagename)
static char *formatter_args[4] = { (char *)NULL };
int pipes[2];
pid_t child;
char *formatted_page = (char *)NULL;
RETSIGTYPE (*sigsave) ();
char *formatted_page = NULL;
int arg_index = 1;
if (formatter_args[0] == (char *)NULL)
@ -245,12 +302,12 @@ get_manpage_contents (pagename)
/* 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]. */
#if PIPE_USE_FORK
pipe (pipes);
signal (SIGCHLD, reap_children);
sigsave = signal (SIGCHLD, reap_children);
child = fork ();
if (child == -1)
return ((char *)NULL);
@ -261,14 +318,14 @@ get_manpage_contents (pagename)
close (pipes[1]);
formatted_page = read_from_fd (pipes[0]);
close (pipes[0]);
signal (SIGCHLD, sigsave);
}
else
{
/* In the child, close the read end of the pipe, make the write end
{ /* 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. */
freopen (NULL_DEVICE, "w", stderr);
freopen (NULL_DEVICE, "r", stdin);
dup2 (pipes[1], fileno (stdout));
execv (formatter_args[0], formatter_args);
@ -276,8 +333,39 @@ get_manpage_contents (pagename)
/* If we get here, we couldn't exec, so close out the pipe and
exit. */
close (pipes[1]);
exit (0);
xexit (0);
}
#else /* !PIPE_USE_FORK */
/* Cannot fork/exec, but can popen/pclose. */
{
FILE *fpipe;
char *cmdline = xmalloc (strlen (formatter_args[0])
+ strlen (manpage_pagename)
+ (arg_index > 2 ? strlen (manpage_section) : 0)
+ 3);
int save_stderr = dup (fileno (stderr));
int fd_err = open (NULL_DEVICE, O_WRONLY, 0666);
if (fd_err > 2)
dup2 (fd_err, fileno (stderr)); /* Don't print errors. */
sprintf (cmdline, "%s %s %s", formatter_args[0], manpage_pagename,
arg_index > 2 ? manpage_section : "");
fpipe = popen (cmdline, "r");
free (cmdline);
if (fd_err > 2)
close (fd_err);
dup2 (save_stderr, fileno (stderr));
if (fpipe == 0)
return ((char *)NULL);
formatted_page = read_from_fd (fileno (fpipe));
if (pclose (fpipe) == -1)
{
if (formatted_page)
free (formatted_page);
return ((char *)NULL);
}
}
#endif /* !PIPE_USE_FORK */
/* If we have the page, then clean it up. */
if (formatted_page)
@ -342,10 +430,11 @@ manpage_node_of_file_buffer (file_buffer, pagename)
{
node = (NODE *)xmalloc (sizeof (NODE));
node->filename = file_buffer->filename;
node->nodename = tag->nodename;
node->nodename = xstrdup (tag->nodename);
node->contents = file_buffer->contents + tag->nodestart;
node->nodelen = tag->nodelen;
node->flags = 0;
node->display_pos = 0;
node->parent = (char *)NULL;
node->flags = (N_HasTagsTable | N_IsManPage);
node->contents += skip_node_separator (node->contents);

View File

@ -1,7 +1,7 @@
/* nodemenu.c -- Produce a menu of all visited nodes.
$Id: nodemenu.c,v 1.7 1997/07/24 21:30:30 karl Exp $
/* nodemenu.c -- produce a menu of all visited nodes.
$Id: nodemenu.c,v 1.8 1998/06/28 19:54:27 karl Exp $
Copyright (C) 1993, 97 Free Software Foundation, Inc.
Copyright (C) 1993, 97, 98 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
@ -168,7 +168,9 @@ get_visited_nodes (filter_func)
/* Delete duplicates. */
for (i = 0, newlen = 1; i < lines_index - 1; i++)
{
if (strcmp (lines[i], lines[i + 1]) == 0)
/* Use FILENAME_CMP here, since the most important piece
of info in each line is the file name of the node. */
if (FILENAME_CMP (lines[i], lines[i + 1]) == 0)
{
free (lines[i]);
lines[i] = (char *)NULL;

View File

@ -1,9 +1,7 @@
/* nodes.c -- How to get an Info file and node. */
/* nodes.c -- how to get an Info file and node.
$Id: nodes.c,v 1.14 1999/08/15 10:18:09 karl Exp $
/* This file is part of GNU Info, a program for reading online documentation
stored in Info format.
Copyright (C) 1993 Free Software Foundation, Inc.
Copyright (C) 1993, 98, 99 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
@ -32,12 +30,6 @@
# include "man.h"
#endif /* HANDLE_MAN_PAGES */
/* **************************************************************** */
/* */
/* Functions Static to this File */
/* */
/* **************************************************************** */
static void forget_info_file (), remember_info_file ();
static void free_file_buffer_tags (), free_info_tag ();
static void get_nodes_of_tags_table (), get_nodes_of_info_file ();
@ -50,8 +42,7 @@ static NODE *info_node_of_file_buffer_tags ();
static long get_node_length ();
/* Magic number that RMS used to decide how much a tags table pointer could
be off by. I feel that it should be much smaller, like on the order of
4. */
be off by. I feel that it should be much smaller, like 4. */
#define DEFAULT_INFO_FUDGE 1000
/* Passed to *_internal functions. INFO_GET_TAGS says to do what is
@ -59,46 +50,36 @@ static long get_node_length ();
#define INFO_NO_TAGS 0
#define INFO_GET_TAGS 1
/* **************************************************************** */
/* */
/* Global Variables */
/* */
/* **************************************************************** */
/* Global variables. */
/* When non-zero, this is a string describing the recent file error. */
char *info_recent_file_error = (char *)NULL;
char *info_recent_file_error = NULL;
/* The list of already loaded nodes. */
FILE_BUFFER **info_loaded_files = (FILE_BUFFER **)NULL;
FILE_BUFFER **info_loaded_files = NULL;
/* The number of slots currently allocated to LOADED_FILES. */
int info_loaded_files_slots = 0;
/* **************************************************************** */
/* */
/* Public Functions for Node Manipulation */
/* */
/* **************************************************************** */
/* Public functions for node manipulation. */
/* Used to build "dir" menu from "localdir" files found in INFOPATH. */
/* Used to build `dir' menu from `localdir' files found in INFOPATH. */
extern void maybe_build_dir_node ();
/* Return a pointer to a NODE structure for the Info node (FILENAME)NODENAME.
FILENAME can be passed as NULL, in which case the filename of "dir" is used.
NODENAME can be passed as NULL, in which case the nodename of "Top" is used.
If the node cannot be found, return a NULL pointer. */
If FILENAME is NULL, `dir' is used.
IF NODENAME is NULL, `Top' is used.
If the node cannot be found, return NULL. */
NODE *
info_get_node (filename, nodename)
char *filename, *nodename;
{
FILE_BUFFER *file_buffer;
NODE *node;
FILE_BUFFER *file_buffer = NULL;
file_buffer = (FILE_BUFFER *)NULL;
info_recent_file_error = (char *)NULL;
info_recent_file_error = NULL;
info_parse_node (nodename, DONT_SKIP_NEWLINES);
nodename = (char *)NULL;
nodename = NULL;
if (info_parsed_filename)
filename = info_parsed_filename;
@ -112,23 +93,23 @@ info_get_node (filename, nodename)
/* If the file to be looked up is "dir", build the contents from all of
the "dir"s and "localdir"s found in INFOPATH. */
if (strcasecmp (filename, "dir") == 0)
if (is_dir_name (filename))
maybe_build_dir_node (filename);
/* Find the correct info file. */
/* Find the correct info file, or give up. */
file_buffer = info_find_file (filename);
if (!file_buffer)
{
if (filesys_error_number)
info_recent_file_error =
filesys_error_string (filename, filesys_error_number);
return ((NODE *)NULL);
return NULL;
}
/* Look for the node. */
node = info_get_node_of_file_buffer (nodename, file_buffer);
/* If the node looked for was "Top", try again looking for the node under
a slightly different name. */
/* If the node not found was "Top", try again with different case. */
if (!node && (nodename == NULL || strcasecmp (nodename, "Top") == 0))
{
node = info_get_node_of_file_buffer ("Top", file_buffer);
@ -137,7 +118,8 @@ info_get_node (filename, nodename)
if (!node)
node = info_get_node_of_file_buffer ("TOP", file_buffer);
}
return (node);
return node;
}
/* Return a pointer to a NODE structure for the Info node NODENAME in
@ -149,12 +131,12 @@ info_get_node_of_file_buffer (nodename, file_buffer)
char *nodename;
FILE_BUFFER *file_buffer;
{
NODE *node = (NODE *)NULL;
NODE *node = NULL;
/* If we are unable to find the file, we have to give up. There isn't
anything else we can do. */
if (!file_buffer)
return ((NODE *)NULL);
return NULL;
/* If the file buffer was gc'ed, reload the contents now. */
if (!file_buffer->contents)
@ -171,11 +153,12 @@ info_get_node_of_file_buffer (nodename, file_buffer)
{
node = (NODE *)xmalloc (sizeof (NODE));
node->filename = file_buffer->fullpath;
node->parent = (char *)NULL;
node->parent = NULL;
node->nodename = xstrdup ("*");
node->contents = file_buffer->contents;
node->nodelen = file_buffer->filesize;
node->flags = 0;
node->display_pos = 0;
}
#if defined (HANDLE_MAN_PAGES)
/* If the file buffer is the magic one associated with manpages, call
@ -195,7 +178,7 @@ info_get_node_of_file_buffer (nodename, file_buffer)
}
/* Return the results of our node search. */
return (node);
return node;
}
/* Locate the file named by FILENAME, and return the information structure
@ -207,7 +190,7 @@ FILE_BUFFER *
info_find_file (filename)
char *filename;
{
return (info_find_file_internal (filename, INFO_GET_TAGS));
return info_find_file_internal (filename, INFO_GET_TAGS);
}
/* Load the info file FILENAME, remembering information about it in a
@ -216,15 +199,11 @@ FILE_BUFFER *
info_load_file (filename)
char *filename;
{
return (info_load_file_internal (filename, INFO_GET_TAGS));
return info_load_file_internal (filename, INFO_GET_TAGS);
}
/* **************************************************************** */
/* */
/* Private Functions Implementation */
/* */
/* **************************************************************** */
/* Private functions implementation. */
/* The workhorse for info_find_file (). Non-zero 2nd argument says to
try to build a tags table (or otherwise glean the nodes) for this
@ -236,30 +215,30 @@ info_find_file_internal (filename, get_tags)
char *filename;
int get_tags;
{
register int i;
register FILE_BUFFER *file_buffer;
int i;
FILE_BUFFER *file_buffer;
/* First try to find the file in our list of already loaded files. */
if (info_loaded_files)
{
for (i = 0; (file_buffer = info_loaded_files[i]); i++)
if ((strcmp (filename, file_buffer->filename) == 0) ||
(strcmp (filename, file_buffer->fullpath) == 0) ||
((*filename != '/') &&
strcmp (filename,
filename_non_directory (file_buffer->fullpath)) == 0))
if ((FILENAME_CMP (filename, file_buffer->filename) == 0) ||
(FILENAME_CMP (filename, file_buffer->fullpath) == 0) ||
(!IS_ABSOLUTE (filename) &&
FILENAME_CMP (filename,
filename_non_directory (file_buffer->fullpath)) == 0))
{
struct stat new_info, *old_info;
/* This file is loaded. If the filename that we want is
specifically "dir", then simply return the file buffer. */
if (strcasecmp (filename_non_directory (filename), "dir") == 0)
return (file_buffer);
if (is_dir_name (filename_non_directory (filename)))
return file_buffer;
#if defined (HANDLE_MAN_PAGES)
/* Do the same for the magic MANPAGE file. */
if (file_buffer->flags & N_IsManPage)
return (file_buffer);
return file_buffer;
#endif /* HANDLE_MAN_PAGES */
/* The file appears to be already loaded, and it is not "dir".
@ -268,7 +247,7 @@ info_find_file_internal (filename, get_tags)
if (stat (file_buffer->fullpath, &new_info) == -1)
{
filesys_error_number = errno;
return ((FILE_BUFFER *)NULL);
return NULL;
}
old_info = &file_buffer->finfo;
@ -288,10 +267,18 @@ info_find_file_internal (filename, get_tags)
for this file, and there isn't one here, build the nodes
for this file_buffer. In any case, return the file_buffer
object. */
if (!file_buffer->contents)
{
/* The file's contents have been gc'ed. Reload it. */
info_reload_file_buffer_contents (file_buffer);
if (!file_buffer->contents)
return NULL;
}
if (get_tags && !file_buffer->tags)
build_tags_and_nodes (file_buffer);
return (file_buffer);
return file_buffer;
}
}
}
@ -310,7 +297,7 @@ info_find_file_internal (filename, get_tags)
if (file_buffer)
remember_info_file (file_buffer);
return (file_buffer);
return file_buffer;
}
/* The workhorse function for info_load_file (). Non-zero second argument
@ -325,8 +312,8 @@ info_load_file_internal (filename, get_tags)
char *fullpath, *contents;
long filesize;
struct stat finfo;
int retcode;
FILE_BUFFER *file_buffer = (FILE_BUFFER *)NULL;
int retcode, compressed;
FILE_BUFFER *file_buffer = NULL;
/* Get the full pathname of this file, as known by the info system.
That is to say, search along INFOPATH and expand tildes, etc. */
@ -338,18 +325,16 @@ info_load_file_internal (filename, get_tags)
/* If the file referenced by the name returned from info_find_fullpath ()
doesn't exist, then try again with the last part of the filename
appearing in lowercase. */
/* This is probably not needed at all on those systems which define
FILENAME_CMP to be strcasecmp. But let's do it anyway, lest some
network redirector supports case sensitivity. */
if (retcode < 0)
{
char *lowered_name;
char *basename;
lowered_name = xstrdup (filename);
basename = (char *) strrchr (lowered_name, '/');
if (basename)
basename++;
else
basename = lowered_name;
basename = filename_non_directory (lowered_name);
while (*basename)
{
@ -369,14 +354,14 @@ info_load_file_internal (filename, get_tags)
if (retcode < 0)
{
filesys_error_number = errno;
return ((FILE_BUFFER *)NULL);
return NULL;
}
/* Otherwise, try to load the file. */
contents = filesys_read_info_file (fullpath, &filesize, &finfo);
contents = filesys_read_info_file (fullpath, &filesize, &finfo, &compressed);
if (!contents)
return ((FILE_BUFFER *)NULL);
return NULL;
/* The file was found, and can be read. Allocate FILE_BUFFER and fill
in the various members. */
@ -386,16 +371,16 @@ info_load_file_internal (filename, get_tags)
file_buffer->finfo = finfo;
file_buffer->filesize = filesize;
file_buffer->contents = contents;
if (file_buffer->filesize != file_buffer->finfo.st_size)
if (compressed)
file_buffer->flags |= N_IsCompressed;
/* If requested, build the tags and nodes for this file buffer. */
if (get_tags)
build_tags_and_nodes (file_buffer);
return (file_buffer);
return file_buffer;
}
/* Grovel FILE_BUFFER->contents finding tags and nodes, and filling in the
various slots. This can also be used to rebuild a tag or node table. */
void
@ -527,6 +512,7 @@ get_nodes_of_info_file (file_buffer)
int start, end;
char *nodeline;
TAG *entry;
int anchor = 0;
/* Skip past the characters just found. */
binding.start = nodestart;
@ -537,6 +523,13 @@ get_nodes_of_info_file (file_buffer)
/* Find "Node:" */
start = string_in_line (INFO_NODE_LABEL, nodeline);
/* No Node:. Maybe it's a Ref:. */
if (start == -1)
{
start = string_in_line (INFO_REF_LABEL, nodeline);
if (start != -1)
anchor = 1;
}
/* If not there, this is not the start of a node. */
if (start == -1)
@ -550,21 +543,24 @@ get_nodes_of_info_file (file_buffer)
skip_node_characters (nodeline + start, DONT_SKIP_NEWLINES);
/* Okay, we have isolated the node name, and we know where the
node starts. Remember this information in a NODE structure. */
entry = (TAG *)xmalloc (sizeof (TAG));
entry->nodename = (char *)xmalloc (1 + (end - start));
node starts. Remember this information. */
entry = xmalloc (sizeof (TAG));
entry->nodename = xmalloc (1 + (end - start));
strncpy (entry->nodename, nodeline + start, end - start);
entry->nodename[end - start] = '\0';
entry->nodename[end - start] = 0;
entry->nodestart = nodestart;
{
SEARCH_BINDING node_body;
if (anchor)
entry->nodelen = 0;
else
{
SEARCH_BINDING node_body;
node_body.buffer = binding.buffer + binding.start;
node_body.start = 0;
node_body.end = binding.end - binding.start;
node_body.flags = S_FoldCase;
entry->nodelen = get_node_length (&node_body);
}
node_body.buffer = binding.buffer + binding.start;
node_body.start = 0;
node_body.end = binding.end - binding.start;
node_body.flags = S_FoldCase;
entry->nodelen = get_node_length (&node_body);
}
entry->filename = file_buffer->fullpath;
@ -579,17 +575,16 @@ static long
get_node_length (binding)
SEARCH_BINDING *binding;
{
register int i;
int i;
char *body;
/* From the Info-RFC file:
[A node] ends with either a ^_, a ^L, or the end of file. */
/* [A node] ends with either a ^_, a ^L, or end of file. */
for (i = binding->start, body = binding->buffer; i < binding->end; i++)
{
if (body[i] == INFO_FF || body[i] == INFO_COOKIE)
break;
}
return ((long) i - binding->start);
return i - binding->start;
}
/* Build and save the array of nodes in FILE_BUFFER by searching through the
@ -599,9 +594,10 @@ get_nodes_of_tags_table (file_buffer, buffer_binding)
FILE_BUFFER *file_buffer;
SEARCH_BINDING *buffer_binding;
{
int offset, tags_index = 0;
int name_offset;
SEARCH_BINDING *search;
long position;
int tags_index = 0;
search = copy_binding (buffer_binding);
@ -624,6 +620,8 @@ get_nodes_of_tags_table (file_buffer, buffer_binding)
{
TAG *entry;
char *nodedef;
unsigned p;
int anchor = 0;
/* Prepare to skip this line. */
search->start = position;
@ -634,36 +632,45 @@ get_nodes_of_tags_table (file_buffer, buffer_binding)
continue;
/* Find the label preceding the node name. */
offset =
name_offset =
string_in_line (INFO_NODE_LABEL, search->buffer + search->start);
/* If no node label, maybe it's an anchor. */
if (name_offset == -1)
{
name_offset = string_in_line (INFO_REF_LABEL,
search->buffer + search->start);
if (name_offset != -1)
anchor = 1;
}
/* If not there, not a defining line, so we must be out of the
tags table. */
if (offset == -1)
tags table. */
if (name_offset == -1)
break;
/* Point to the beginning of the node definition. */
search->start += offset;
entry = xmalloc (sizeof (TAG));
/* Find the beginning of the node definition. */
search->start += name_offset;
nodedef = search->buffer + search->start;
nodedef += skip_whitespace (nodedef);
/* Move past the node's name. */
for (offset = 0;
(nodedef[offset]) && (nodedef[offset] != INFO_TAGSEP);
offset++);
if (nodedef[offset] != INFO_TAGSEP)
/* Move past the node's name in this tag to the TAGSEP character. */
for (p = 0; nodedef[p] && nodedef[p] != INFO_TAGSEP; p++)
;
if (nodedef[p] != INFO_TAGSEP)
continue;
entry = (TAG *)xmalloc (sizeof (TAG));
entry->nodename = (char *)xmalloc (1 + offset);
strncpy (entry->nodename, nodedef, offset);
entry->nodename[offset] = '\0';
offset++;
entry->nodestart = (long) atol (nodedef + offset);
entry->nodename = xmalloc (p + 1);
strncpy (entry->nodename, nodedef, p);
entry->nodename[p] = 0;
p++;
entry->nodestart = atol (nodedef + p);
/* We don't know the length of this node yet. */
entry->nodelen = -1;
/* If a node, we don't know the length yet, but if it's an
anchor, the length is 0. */
entry->nodelen = anchor ? 0 : -1;
/* The filename of this node is currently known as the same as the
name of this file. */
@ -677,7 +684,7 @@ get_nodes_of_tags_table (file_buffer, buffer_binding)
free (search);
}
/* A structure used only in get_tags_of_indirect_tags_table () to hold onto
/* A structure used only in `get_tags_of_indirect_tags_table' to hold onto
an intermediate value. */
typedef struct {
char *filename;
@ -692,8 +699,8 @@ get_tags_of_indirect_tags_table (file_buffer, indirect_binding, tags_binding)
FILE_BUFFER *file_buffer;
SEARCH_BINDING *indirect_binding, *tags_binding;
{
register int i;
SUBFILE **subfiles = (SUBFILE **)NULL;
int i;
SUBFILE **subfiles = NULL;
int subfiles_index = 0, subfiles_slots = 0;
TAG *entry;
@ -723,7 +730,7 @@ get_tags_of_indirect_tags_table (file_buffer, indirect_binding, tags_binding)
subfile = (SUBFILE *)xmalloc (sizeof (SUBFILE));
subfile->filename = (char *)xmalloc (colon);
strncpy (subfile->filename, line, colon - 1);
subfile->filename[colon - 1] = '\0';
subfile->filename[colon - 1] = 0;
subfile->first_byte = (long) atol (line + colon);
add_pointer_to_array
@ -742,7 +749,7 @@ get_tags_of_indirect_tags_table (file_buffer, indirect_binding, tags_binding)
}
else
{
register int tags_index;
int tags_index;
long header_length;
SEARCH_BINDING binding;
@ -762,14 +769,21 @@ get_tags_of_indirect_tags_table (file_buffer, indirect_binding, tags_binding)
/* Build the file buffer's list of subfiles. */
{
char *containing_dir, *temp;
char *containing_dir = xstrdup (file_buffer->fullpath);
char *temp = filename_non_directory (containing_dir);
int len_containing_dir;
containing_dir = xstrdup (file_buffer->fullpath);
temp = (char *) strrchr (containing_dir, '/');
if (temp)
*temp = '\0';
if (temp > containing_dir)
{
if (HAVE_DRIVE (file_buffer->fullpath) &&
temp == containing_dir + 2)
{
/* Avoid converting "d:foo" into "d:/foo" below. */
*temp = '.';
temp += 2;
}
temp[-1] = 0;
}
len_containing_dir = strlen (containing_dir);
@ -789,7 +803,7 @@ get_tags_of_indirect_tags_table (file_buffer, indirect_binding, tags_binding)
file_buffer->subfiles[i] = fullpath;
}
file_buffer->subfiles[i] = (char *)NULL;
file_buffer->subfiles[i] = NULL;
free (containing_dir);
}
@ -814,7 +828,7 @@ get_tags_of_indirect_tags_table (file_buffer, indirect_binding, tags_binding)
free (subfiles[i]);
free (file_buffer->subfiles[i]);
}
file_buffer->subfiles = (char **)NULL;
file_buffer->subfiles = NULL;
free_file_buffer_tags (file_buffer);
return;
}
@ -825,9 +839,8 @@ get_tags_of_indirect_tags_table (file_buffer, indirect_binding, tags_binding)
preceding this one is the one containing the node. */
entry->filename = file_buffer->subfiles[i - 1];
entry->nodestart -= subfiles[i -1]->first_byte;
entry->nodestart -= subfiles[i - 1]->first_byte;
entry->nodestart += header_length;
entry->nodelen = -1;
}
/* We have successfully built the tags table. Remember that it
@ -845,18 +858,89 @@ get_tags_of_indirect_tags_table (file_buffer, indirect_binding, tags_binding)
free (subfiles);
}
/* Return the node that contains TAG in FILE_BUFFER, else
(pathologically) NULL. Called from info_node_of_file_buffer_tags. */
static NODE *
find_node_of_anchor (file_buffer, tag)
FILE_BUFFER *file_buffer;
TAG *tag;
{
int anchor_pos, node_pos;
TAG *node_tag;
NODE *node;
/* Look through the tag list for the anchor. */
for (anchor_pos = 0; file_buffer->tags[anchor_pos]; anchor_pos++)
{
TAG *t = file_buffer->tags[anchor_pos];
if (t->nodestart == tag->nodestart)
break;
}
/* Should not happen, because we should always find the anchor. */
if (!file_buffer->tags[anchor_pos])
return NULL;
/* We've found the anchor. Look backwards in the tag table for the
preceding node (we're assuming the tags are given in order),
skipping over any preceding anchors. */
for (node_pos = anchor_pos - 1;
node_pos >= 0 && file_buffer->tags[node_pos]->nodelen == 0;
node_pos--)
;
/* An info file with an anchor before any nodes is pathological, but
it's possible, so don't crash. */
if (node_pos < 0)
return NULL;
/* We have the tag for the node that contained the anchor tag. */
node_tag = file_buffer->tags[node_pos];
/* Look up the node name in the tag table to get the actual node.
This is a recursive call, but it can't recurse again, because we
call it with a real node. */
node = info_node_of_file_buffer_tags (file_buffer, node_tag->nodename);
/* Start displaying the node at the anchor position. */
if (node)
{ /* The nodestart for real nodes is three characters before the `F'
in the `File:' line (a newline, the CTRL-_, and another
newline). The nodestart for anchors is the actual position.
But we offset by only 2, rather than 3, because if an anchor is
at the beginning of a paragraph, it's nicer for it to end up on
the beginning of the first line of the paragraph rather than
the blank line before it. (makeinfo has no way of knowing that
a paragraph is going to start, so we can't fix it there.) */
node->display_pos = file_buffer->tags[anchor_pos]->nodestart
- (node_tag->nodestart + 2);
/* Otherwise an anchor at the end of a node ends up displaying at
the end of the last line of the node (way over on the right of
the screen), which looks wrong. */
if (node->display_pos >= node->nodelen)
node->display_pos = node->nodelen - 1;
/* Don't search in the node for the xref text, it's not there. */
node->flags |= N_FromAnchor;
}
return node;
}
/* Return the node from FILE_BUFFER which matches NODENAME by searching
the tags table in FILE_BUFFER. If the node could not be found, return
a NULL pointer. */
the tags table in FILE_BUFFER, or NULL. */
static NODE *
info_node_of_file_buffer_tags (file_buffer, nodename)
FILE_BUFFER *file_buffer;
char *nodename;
{
register int i;
TAG *tag;
int i;
for (i = 0; (tag = file_buffer->tags[i]); i++)
for (i = 0; (tag = file_buffer->tags[i]); i++)
if (strcmp (nodename, tag->nodename) == 0)
{
FILE_BUFFER *subfile;
@ -864,27 +948,26 @@ info_node_of_file_buffer_tags (file_buffer, nodename)
subfile = info_find_file_internal (tag->filename, INFO_NO_TAGS);
if (!subfile)
return ((NODE *)NULL);
return NULL;
if (!subfile->contents)
{
info_reload_file_buffer_contents (subfile);
if (!subfile->contents)
return ((NODE *)NULL);
return NULL;
}
/* If we were able to find this file and load it, then return
the node within it. */
{
NODE *node;
node = (NODE *)xmalloc (sizeof (NODE));
node->filename = (subfile->fullpath);
node->nodename = tag->nodename;
node->contents = subfile->contents + tag->nodestart;
node->flags = 0;
node->parent = (char *)NULL;
NODE *node = xmalloc (sizeof (NODE));
node->filename = subfile->fullpath;
node->parent = NULL;
node->nodename = tag->nodename;
node->contents = subfile->contents + tag->nodestart;
node->display_pos = 0;
node->flags = 0;
if (file_buffer->flags & N_HasTagsTable)
{
@ -923,14 +1006,14 @@ info_node_of_file_buffer_tags (file_buffer, nodename)
max = subfile->filesize - tag->nodestart;
/* NODE_SEP gets the address of the separator which defines
this node, or (char *)NULL if the node wasn't found.
this node, or NULL if the node wasn't found.
NODE->contents is side-effected to point to right after
the separator. */
node_sep = adjust_nodestart (node, min, max);
if (node_sep == (char *)NULL)
if (node_sep == NULL)
{
free (node);
return ((NODE *)NULL);
return NULL;
}
/* Readjust tag->nodestart. */
tag->nodestart = node_sep - subfile->contents;
@ -943,46 +1026,49 @@ info_node_of_file_buffer_tags (file_buffer, nodename)
node_body.end = buff_end - node_body.buffer;
node_body.flags = 0;
tag->nodelen = get_node_length (&node_body);
node->nodelen = tag->nodelen;
}
else if (tag->nodelen == 0) /* anchor, return containing node */
{
free (node);
node = find_node_of_anchor (file_buffer, tag);
}
else
{
/* Since we know the length of this node, we have already
adjusted tag->nodestart to point to the exact start of
it. Simply skip the node separator. */
node->contents += skip_node_separator (node->contents);
node->nodelen = tag->nodelen;
}
node->nodelen = tag->nodelen;
return (node);
return node;
}
}
/* There was a tag table for this file, and the node wasn't found.
Return NULL, since this file doesn't contain the desired node. */
return ((NODE *)NULL);
return NULL;
}
/* **************************************************************** */
/* */
/* Managing file_buffers, nodes, and tags. */
/* */
/* **************************************************************** */
/* Managing file_buffers, nodes, and tags. */
/* Create a new, empty file buffer. */
FILE_BUFFER *
make_file_buffer ()
{
FILE_BUFFER *file_buffer;
FILE_BUFFER *file_buffer = xmalloc (sizeof (FILE_BUFFER));
file_buffer = (FILE_BUFFER *)xmalloc (sizeof (FILE_BUFFER));
file_buffer->filename = file_buffer->fullpath = (char *)NULL;
file_buffer->contents = (char *)NULL;
file_buffer->tags = (TAG **)NULL;
file_buffer->subfiles = (char **)NULL;
file_buffer->filename = file_buffer->fullpath = NULL;
file_buffer->contents = NULL;
file_buffer->tags = NULL;
file_buffer->subfiles = NULL;
file_buffer->tags_slots = 0;
file_buffer->flags = 0;
return (file_buffer);
return file_buffer;
}
/* Add FILE_BUFFER to our list of already loaded info files. */
@ -1004,15 +1090,15 @@ static void
forget_info_file (filename)
char *filename;
{
register int i;
int i;
FILE_BUFFER *file_buffer;
if (!info_loaded_files)
return;
for (i = 0; (file_buffer = info_loaded_files[i]); i++)
if ((strcmp (filename, file_buffer->filename) == 0) ||
(strcmp (filename, file_buffer->fullpath) == 0))
for (i = 0; file_buffer = info_loaded_files[i]; i++)
if (FILENAME_CMP (filename, file_buffer->filename) == 0
|| FILENAME_CMP (filename, file_buffer->fullpath) == 0)
{
free (file_buffer->filename);
free (file_buffer->fullpath);
@ -1020,13 +1106,17 @@ forget_info_file (filename)
if (file_buffer->contents)
free (file_buffer->contents);
/* Note that free_file_buffer_tags () also kills the subfiles
list, since the subfiles list is only of use in conjunction
with tags. */
/* free_file_buffer_tags () also kills the subfiles list, since
the subfiles list is only of use in conjunction with tags. */
free_file_buffer_tags (file_buffer);
while ((info_loaded_files[i] = info_loaded_files[++i]))
;
/* Move rest of list down. */
while (info_loaded_files[i + 1])
{
info_loaded_files[i] = info_loaded_files[i + 1];
i++;
}
info_loaded_files[i] = 0;
break;
}
@ -1037,17 +1127,17 @@ static void
free_file_buffer_tags (file_buffer)
FILE_BUFFER *file_buffer;
{
register int i;
int i;
if (file_buffer->tags)
{
register TAG *tag;
TAG *tag;
for (i = 0; (tag = file_buffer->tags[i]); i++)
free_info_tag (tag);
free (file_buffer->tags);
file_buffer->tags = (TAG **)NULL;
file_buffer->tags = NULL;
file_buffer->tags_slots = 0;
}
@ -1057,7 +1147,7 @@ free_file_buffer_tags (file_buffer)
free (file_buffer->subfiles[i]);
free (file_buffer->subfiles);
file_buffer->subfiles = (char **)NULL;
file_buffer->subfiles = NULL;
}
}
@ -1084,6 +1174,7 @@ static void
info_reload_file_buffer_contents (fb)
FILE_BUFFER *fb;
{
int is_compressed;
#if defined (HANDLE_MAN_PAGES)
/* If this is the magic manpage node, don't try to reload, just give up. */
@ -1095,8 +1186,9 @@ info_reload_file_buffer_contents (fb)
/* Let the filesystem do all the work for us. */
fb->contents =
filesys_read_info_file (fb->fullpath, &(fb->filesize), &(fb->finfo));
if (fb->filesize != (long) (fb->finfo.st_size))
filesys_read_info_file (fb->fullpath, &(fb->filesize), &(fb->finfo),
&is_compressed);
if (is_compressed)
fb->flags |= N_IsCompressed;
}
@ -1157,7 +1249,7 @@ adjust_nodestart (node, min, max)
(strncmp (node->nodename, nodedef, offset) == 0))
{
node->contents = nodestart;
return (node_body.buffer + position);
return node_body.buffer + position;
}
}
}
@ -1173,7 +1265,7 @@ adjust_nodestart (node, min, max)
/* If the node couldn't be found, we lose big. */
if (position == -1)
return ((char *)NULL);
return NULL;
/* Otherwise, the node was found, but the tags table could need updating
(if we used a tag to get here, that is). Set the flag in NODE->flags. */
@ -1181,5 +1273,5 @@ adjust_nodestart (node, min, max)
node->contents += skip_node_separator (node->contents);
if (node->flags & N_HasTagsTable)
node->flags |= N_UpdateTags;
return (node_body.buffer + position);
return node_body.buffer + position;
}

View File

@ -1,10 +1,7 @@
/* nodes.h -- How we represent nodes internally.
$Id: nodes.h,v 1.5 1997/07/18 14:33:44 karl Exp $
$Id: nodes.h,v 1.8 1998/07/10 20:28:43 karl Exp $
This file is part of GNU Info, a program for reading online documentation
stored in Info format.
Copyright (C) 1993, 97 Free Software Foundation, Inc.
Copyright (C) 1993, 97, 98 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
@ -22,16 +19,12 @@
Written by Brian Fox (bfox@ai.mit.edu). */
#if !defined (NODES_H)
#ifndef NODES_H
#define NODES_H
#include "info.h"
/* **************************************************************** */
/* */
/* User Code Interface */
/* */
/* **************************************************************** */
/* 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
@ -47,6 +40,7 @@ typedef struct {
char *nodename; /* The name of this node. */
char *contents; /* Characters appearing in this node. */
long nodelen; /* The length of the CONTENTS member. */
unsigned long display_pos; /* Where to display at, if nonzero. */
int flags; /* See immediately below. */
} NODE;
@ -57,18 +51,14 @@ typedef struct {
#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. */
#define N_IsManPage 0x40 /* This node is a manpage. */
#define N_FromAnchor 0x80 /* Synthesized for an anchor reference. */
/* **************************************************************** */
/* */
/* Internal Data Structures */
/* */
/* **************************************************************** */
/* Internal data structures. */
/* Some defines describing details about Info file contents. */
/* String Constants. */
/* String constants. */
#define INFO_FILE_LABEL "File:"
#define INFO_REF_LABEL "Ref:"
#define INFO_NODE_LABEL "Node:"
#define INFO_PREV_LABEL "Prev:"
#define INFO_ALTPREV_LABEL "Previous:"
@ -82,7 +72,7 @@ typedef struct {
#define INDIRECT_TAGS_TABLE_LABEL "Indirect:\n"
#define TAGS_TABLE_IS_INDIRECT_LABEL "(Indirect)"
/* Character Constants. */
/* Character constants. */
#define INFO_COOKIE '\037'
#define INFO_FF '\014'
#define INFO_TAGSEP '\177'
@ -119,12 +109,8 @@ typedef struct {
int tags_slots; /* Number of slots allocated for TAGS. */
int flags; /* Various flags. Mimics of N_* flags. */
} FILE_BUFFER;
/* **************************************************************** */
/* */
/* Externally Visible Functions */
/* */
/* **************************************************************** */
/* Externally visible functions. */
/* Array of FILE_BUFFER * which represents the currently loaded info files. */
extern FILE_BUFFER **info_loaded_files;
@ -166,4 +152,4 @@ extern char *info_recent_file_error;
/* Create a new, empty file buffer. */
extern FILE_BUFFER *make_file_buffer ();
#endif /* !NODES_H */
#endif /* not NODES_H */

View File

@ -1,9 +1,7 @@
/* search.c -- How to search large bodies of text. */
/* search.c -- searching large bodies of text.
$Id: search.c,v 1.5 1999/03/05 19:56:59 karl Exp $
/* This file is part of GNU Info, a program for reading online documentation
stored in Info format.
Copyright (C) 1993, 97 Free Software Foundation, Inc.
Copyright (C) 1993, 97, 98 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
@ -198,7 +196,7 @@ search_backward (input_string, binding)
{
c = *(buff - i);
if (c != string[i] && (alternate && c != alternate[i]))
if (c != string[i] && (!alternate || c != alternate[i]))
break;
}
@ -292,7 +290,7 @@ skip_whitespace_and_newlines (string)
{
register int i;
for (i = 0; string && (whitespace (string[i]) || string[i] == '\n'); i++);
for (i = 0; string && whitespace_or_newline (string[i]); i++);
return (i);
}

View File

@ -1,10 +1,7 @@
/* search.h -- Structure used to search large bodies of text, with bounds.
$Id: search.h,v 1.3 1997/07/15 18:43:49 karl Exp $
$Id: search.h,v 1.4 1998/04/19 20:50:23 karl Exp $
This file is part of GNU Info, a program for reading online documentation
stored in Info format.
Copyright (C) 1993, 97 Free Software Foundation, Inc.
Copyright (C) 1993, 97, 98 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
@ -53,11 +50,6 @@ extern int looking_at ();
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

File diff suppressed because it is too large Load Diff

View File

@ -1,9 +1,7 @@
/* session.h -- Functions found in session.c. */
/* session.h -- Functions found in session.c.
$Id: session.h,v 1.9 1999/06/25 21:57:40 karl Exp $
/* This file is part of GNU Info, a program for reading online documentation
stored in Info format.
Copyright (C) 1993 Free Software Foundation, Inc.
Copyright (C) 1993, 98, 99 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
@ -21,7 +19,7 @@
Written by Brian Fox (bfox@ai.mit.edu). */
#if !defined (SESSION_H)
#ifndef SESSION_H
#define SESSION_H
#include "info.h"
@ -76,6 +74,7 @@ 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 ();
extern char *program_name_from_file_name ();
/* Do the physical deletion of WINDOW, and forget this window and
associated nodes. */
@ -110,6 +109,8 @@ extern void info_move_to_prev_xref (), info_move_to_next_xref ();
extern void info_scroll_forward (), info_scroll_backward ();
extern void info_redraw_display (), info_toggle_wrap ();
extern void info_move_to_window_line ();
extern void info_up_line (), info_down_line ();
extern void info_scroll_half_screen_down (), info_scroll_half_screen_up ();
/* Manipulating multiple windows. */
extern void info_split_window (), info_delete_window ();
@ -123,6 +124,8 @@ 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 ();
extern void info_menu_sequence ();
extern NODE *info_follow_menus (/* initial_node, menus, errstr, errarg */);
/* Selecting cross references. */
extern void info_menu_digit (), info_menu_item (), info_xref_item ();
@ -136,6 +139,8 @@ extern void info_initialize_numeric_arg (), info_numeric_arg_digit_loop ();
/* Searching commands. */
extern void info_search (), isearch_forward (), isearch_backward ();
extern void info_search_case_sensitively (), info_search_backward ();
extern void info_search_next (), info_search_previous ();
/* Dumping and printing nodes. */
extern void info_print_node ();
@ -143,4 +148,4 @@ extern void info_print_node ();
/* Miscellaneous commands. */
extern void info_abort_key (), info_quit (), info_do_lowercase_version ();
#endif /* SESSION_H */
#endif /* not SESSION_H */

View File

@ -1,9 +1,7 @@
/* signals.c -- Install and maintain Info signal handlers. */
/* signals.c -- install and maintain Info signal handlers.
$Id: signals.c,v 1.6 1998/12/06 22:00:04 karl Exp $
/* 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.
Copyright (C) 1993, 94, 95, 98 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
@ -30,6 +28,9 @@
/* */
/* **************************************************************** */
/* Non-zero when our signal handler has been called to handle SIGWINCH. */
static int in_sigwinch = 0;
#if !defined (HAVE_SIGPROCMASK) && defined (HAVE_SIGSETMASK)
/* Perform OPERATION on NEWSET, perhaps leaving information in OLDSET. */
static void
@ -66,7 +67,7 @@ typedef RETSIGTYPE signal_handler ();
static RETSIGTYPE info_signal_handler ();
static signal_handler *old_TSTP, *old_TTOU, *old_TTIN;
static signal_handler *old_WINCH, *old_INT;
static signal_handler *old_WINCH, *old_INT, *old_USR1;
void
initialize_info_signal_handler ()
@ -84,6 +85,11 @@ initialize_info_signal_handler ()
#if defined (SIGINT)
old_INT = (signal_handler *) signal (SIGINT, info_signal_handler);
#endif
#if defined (SIGUSR1)
/* Used by DJGPP to simulate SIGTSTP on Ctrl-Z. */
old_USR1 = (signal_handler *) signal (SIGUSR1, info_signal_handler);
#endif
}
static void
@ -97,6 +103,19 @@ redisplay_after_signal ()
fflush (stdout);
}
static void
reset_info_window_sizes ()
{
terminal_goto_xy (0, 0);
fflush (stdout);
terminal_unprep_terminal ();
terminal_get_screen_size ();
terminal_prep_terminal ();
display_initialize_display (screenwidth, screenheight);
window_new_screen_size (screenwidth, screenheight, NULL);
redisplay_after_signal ();
}
static RETSIGTYPE
info_signal_handler (sig)
int sig;
@ -145,28 +164,43 @@ info_signal_handler (sig)
}
break;
#if defined (SIGWINCH)
#if defined (SIGWINCH) || defined (SIGUSR1)
#ifdef SIGWINCH
case SIGWINCH:
#endif
#ifdef SIGUSR1
case SIGUSR1:
#endif
{
/* 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);
if (!in_sigwinch) {
in_sigwinch++;
/* Turn off terminal IO, tell our parent that the window has changed,
then reinitialize the terminal and rebuild our windows. */
#ifdef SIGWINCH
if (sig == SIGWINCH)
old_signal_handler = &old_WINCH;
#endif
#ifdef SIGUSR1
if (sig == SIGUSR1)
old_signal_handler = &old_USR1;
#endif
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 = (signal_handler *) signal (sig, info_signal_handler);
redisplay_after_signal ();
/* After our old signal handler returns... */
*old_signal_handler
= (signal_handler *) signal (sig, info_signal_handler);
terminal_prep_terminal ();
reset_info_window_sizes ();
in_sigwinch--;
}
}
break;
#endif /* SIGWINCH */
#endif /* SIGWINCH || SIGUSR1 */
}
}

View File

@ -1,10 +1,7 @@
/* termdep.h -- System things that terminal.c depends on.
$Id: termdep.h,v 1.3 1997/07/05 21:17:14 karl Exp $
$Id: termdep.h,v 1.4 1998/04/13 22:02:57 karl Exp $
This file is part of GNU Info, a program for reading online documentation
stored in Info format.
Copyright (C) 1993, 96, 97 Free Software Foundation, Inc.
Copyright (C) 1993, 96, 97, 98 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
@ -33,6 +30,9 @@
#ifdef HAVE_TERMIOS_H
# include <termios.h>
# ifdef GWINSZ_IN_SYS_IOCTL
# include <sys/ioctl.h>
# endif
#else
# if defined (HAVE_TERMIO_H)
# include <termio.h>

View File

@ -1,7 +1,7 @@
/* terminal.c -- How to handle the physical terminal for Info.
$Id: terminal.c,v 1.9 1998/02/22 00:05:15 karl Exp $
$Id: terminal.c,v 1.19 1999/09/20 12:28:54 karl Exp $
Copyright (C) 1988, 89, 90, 91, 92, 93, 96, 97, 98
Copyright (C) 1988, 89, 90, 91, 92, 93, 96, 97, 98, 99
Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
@ -26,6 +26,7 @@
#include <sys/types.h>
#include <signal.h>
#include <sys/ioctl.h> /* TIOCGWINSZ on LynxOS, at least */
/* The Unix termcap interface code. */
#ifdef HAVE_NCURSES_TERMCAP_H
@ -76,9 +77,10 @@ VFunction *terminal_scroll_terminal_hook = (VFunction *)NULL;
/* **************************************************************** */
/* 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;
used to float within it. And the name of the terminal. */
static char *term_buffer = NULL;
static char *term_string_buffer = NULL;
static char *term_name;
/* Some strings to control terminal actions. These are output by tputs (). */
static char *term_goto, *term_clreol, *term_cr, *term_clrpag;
@ -146,12 +148,13 @@ terminal_begin_using_terminal ()
#endif
send_to_terminal (term_begin_use);
/* Without this fflush and sleep, running info in a shelltool or
cmdtool (TERM=sun-cmd) with scrollbars loses -- the scrollbars are
not restored properly.
From: strube@physik3.gwdg.de (Hans Werner Strube). */
fflush (stdout);
sleep (1);
if (STREQ (term_name, "sun-cmd"))
/* Without this fflush and sleep, running info in a shelltool or
cmdtool (TERM=sun-cmd) with scrollbars loses -- the scrollbars are
not restored properly.
From: strube@physik3.gwdg.de (Hans Werner Strube). */
sleep (1);
#ifdef SIGWINCH
signal (SIGWINCH, sigsave);
@ -177,7 +180,9 @@ terminal_end_using_terminal ()
send_to_terminal (term_end_use);
fflush (stdout);
sleep (1);
if (STREQ (term_name, "sun-cmd"))
/* See comments at other sleep. */
sleep (1);
#ifdef SIGWINCH
signal (SIGWINCH, sigsave);
@ -516,7 +521,7 @@ void
terminal_initialize_terminal (terminal_name)
char *terminal_name;
{
char *term, *buffer;
char *buffer;
terminal_is_dumb_p = 0;
@ -526,37 +531,46 @@ terminal_initialize_terminal (terminal_name)
return;
}
term = terminal_name ? terminal_name : getenv ("TERM");
term_name = terminal_name ? terminal_name : getenv ("TERM");
if (!term_name)
term_name = "dumb";
if (!term_string_buffer)
term_string_buffer = (char *)xmalloc (2048);
term_string_buffer = xmalloc (2048);
if (!term_buffer)
term_buffer = (char *)xmalloc (2048);
term_buffer = xmalloc (2048);
buffer = term_string_buffer;
term_clrpag = term_cr = term_clreol = (char *)NULL;
term_clrpag = term_cr = term_clreol = NULL;
if (!term)
term = "dumb";
if (tgetent (term_buffer, term) <= 0)
/* HP-UX 11.x returns 0 for OK --jeff.hull@state.co.us. */
if (tgetent (term_buffer, term_name) < 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;
term_kP = term_kN = (char *)NULL;
term_up = term_dn = audible_bell = visible_bell = NULL;
term_ku = term_kd = term_kl = term_kr = NULL;
term_kP = term_kN = NULL;
return;
}
BC = tgetstr ("pc", &buffer);
PC = BC ? *BC : 0;
#if defined (TIOCGETP)
#if defined (HAVE_TERMIOS_H)
{
struct termios ti;
if (tcgetattr (fileno(stdout), &ti) != -1)
ospeed = cfgetospeed (&ti);
else
ospeed = B9600;
}
#else
# if defined (TIOCGETP)
{
struct sgttyb sg;
@ -565,16 +579,17 @@ terminal_initialize_terminal (terminal_name)
else
ospeed = B9600;
}
#else
# else
ospeed = B9600;
#endif /* !TIOCGETP */
# endif /* !TIOCGETP */
#endif
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. */
/* Find out about this terminal's scrolling capability. */
term_AL = tgetstr ("AL", &buffer);
term_DL = tgetstr ("DL", &buffer);
term_al = tgetstr ("al", &buffer);
@ -633,23 +648,7 @@ terminal_initialize_terminal (terminal_name)
terminal_is_dumb_p = 1;
}
/* **************************************************************** */
/* */
/* 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
/* How to read characters from the terminal. */
#if defined (HAVE_TERMIOS_H)
struct termios original_termios, ttybuff;
@ -662,6 +661,25 @@ struct termio original_termio, ttybuff;
int original_tty_flags = 0;
int original_lmode;
struct sgttyb ttybuff;
# if defined(TIOCGETC) && defined(M_XENIX)
/* SCO 3.2v5.0.2 defines but does not support TIOCGETC. Gak. Maybe
better fix would be to use Posix termios in preference. --gildea,
1jul99. */
# undef TIOCGETC
# endif
# 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
# endif /* !HAVE_TERMIO_H */
#endif /* !HAVE_TERMIOS_H */
@ -835,3 +853,6 @@ terminal_unprep_terminal ()
terminal_end_using_terminal ();
}
#ifdef __MSDOS__
# include "pcterm.c"
#endif

View File

@ -1,10 +1,7 @@
/* tilde.c -- Tilde expansion code (~/foo := $HOME/foo).
$Id: tilde.c,v 1.9 1998/02/22 23:03:21 karl Exp $
/* tilde.c -- tilde expansion code (~/foo := $HOME/foo).
$Id: tilde.c,v 1.13 1999/03/03 22:42:21 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, 98
Copyright (C) 1988, 89, 90, 91, 92, 93, 96, 98, 99
Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
@ -23,27 +20,9 @@
Written by Brian Fox (bfox@ai.mit.edu). */
/* Indent #pragma so that older Cpp's don't try to parse it. */
#ifdef _AIX
#pragma alloca
#endif /* _AIX */
/* Include config.h before doing alloca. */
#include "info.h"
#ifdef __GNUC__
# undef alloca
# define alloca __builtin_alloca
#else
# ifdef HAVE_ALLOCA_H
# include <alloca.h>
# else
# ifndef _AIX
char *alloca ();
# endif
# endif
#endif
#if defined (TEST) || defined (STATIC_MALLOC)
static void *xmalloc (), *xrealloc ();
#endif /* TEST || STATIC_MALLOC */
@ -123,7 +102,7 @@ tilde_find_suffix (string)
for (i = 0; i < string_len; i++)
{
if (string[i] == '/' || !string[i])
if (IS_SLASH (string[i]) || !string[i])
break;
for (j = 0; suffixes && suffixes[j]; j++)
@ -203,14 +182,12 @@ char *
tilde_expand_word (filename)
char *filename;
{
char *dirname;
dirname = filename ? xstrdup (filename) : (char *)NULL;
char *dirname = filename ? xstrdup (filename) : NULL;
if (dirname && *dirname == '~')
{
char *temp_name;
if (!dirname[1] || dirname[1] == '/')
if (!dirname[1] || IS_SLASH (dirname[1]))
{
/* Prepend $HOME to the rest of the string. */
char *temp_home = getenv ("HOME");
@ -226,30 +203,31 @@ tilde_expand_word (filename)
temp_home = entry->pw_dir;
}
temp_name = (char *)
alloca (1 + strlen (&dirname[1])
+ (temp_home ? strlen (temp_home) : 0));
temp_name[0] = '\0';
temp_name = xmalloc (1 + strlen (&dirname[1])
+ (temp_home ? strlen (temp_home) : 0));
if (temp_home)
strcpy (temp_name, temp_home);
else
temp_name[0] = 0;
strcat (temp_name, &dirname[1]);
free (dirname);
dirname = xstrdup (temp_name);
free (temp_name);
}
else
{
struct passwd *user_entry;
char *username = (char *)alloca (257);
char *username = xmalloc (257);
int i, c;
for (i = 1; (c = dirname[i]); i++)
{
if (c == '/')
if (IS_SLASH (c))
break;
else
username[i - 1] = c;
}
username[i - 1] = '\0';
username[i - 1] = 0;
if (!(user_entry = (struct passwd *) getpwnam (username)))
{
@ -264,8 +242,8 @@ tilde_expand_word (filename)
if (expansion)
{
temp_name = (char *)alloca
(1 + strlen (expansion) + strlen (&dirname[i]));
temp_name = xmalloc (1 + strlen (expansion)
+ strlen (&dirname[i]));
strcpy (temp_name, expansion);
strcat (temp_name, &dirname[i]);
free (expansion);
@ -276,18 +254,22 @@ tilde_expand_word (filename)
}
else
{
temp_name = (char *)alloca
(1 + strlen (user_entry->pw_dir) + strlen (&dirname[i]));
temp_name = xmalloc (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 = xstrdup (temp_name);
free (temp_name);
}
endpwent ();
endpwent ();
free (username);
}
}
return (dirname);
return dirname;
}
@ -322,7 +304,7 @@ main (argc, argv)
printf (" --> %s\n", result);
free (result);
}
exit (0);
xexit (0);
}
static void memory_error_and_abort ();

View File

@ -1,5 +1,5 @@
/* variables.c -- How to manipulate user visible variables in Info.
$Id: variables.c,v 1.5 1997/07/18 14:34:23 karl Exp $
$Id: variables.c,v 1.7 1999/06/25 21:57:40 karl Exp $
This file is part of GNU Info, a program for reading online documentation
stored in Info format.

View File

@ -1,10 +1,7 @@
/* window.c -- Windows in Info.
$Id: window.c,v 1.5 1998/02/23 22:43:38 karl Exp $
/* window.c -- windows in Info.
$Id: window.c,v 1.11 1999/06/25 21:57:40 karl Exp $
This file is part of GNU Info, a program for reading online documentation
stored in Info format.
Copyright (C) 1993, 97 Free Software Foundation, Inc.
Copyright (C) 1993, 97, 98 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
@ -30,16 +27,16 @@
#include "infomap.h"
/* The window which describes the screen. */
WINDOW *the_screen = (WINDOW *)NULL;
WINDOW *the_screen = NULL;
/* The window which describes the echo area. */
WINDOW *the_echo_area = (WINDOW *)NULL;
WINDOW *the_echo_area = NULL;
/* The list of windows in Info. */
WINDOW *windows = (WINDOW *)NULL;
WINDOW *windows = NULL;
/* Pointer to the active window in WINDOW_LIST. */
WINDOW *active_window = (WINDOW *)NULL;
WINDOW *active_window = NULL;
/* The size of the echo area in Info. It never changes, irregardless of the
size of the screen. */
@ -56,9 +53,9 @@ void
window_initialize_windows (width, height)
int width, height;
{
the_screen = (WINDOW *)xmalloc (sizeof (WINDOW));
the_echo_area = (WINDOW *)xmalloc (sizeof (WINDOW));
windows = (WINDOW *)xmalloc (sizeof (WINDOW));
the_screen = xmalloc (sizeof (WINDOW));
the_echo_area = xmalloc (sizeof (WINDOW));
windows = xmalloc (sizeof (WINDOW));
active_window = windows;
zero_mem (the_screen, sizeof (WINDOW));
@ -85,7 +82,7 @@ window_initialize_windows (width, height)
area. */
the_echo_area->height = ECHO_AREA_HEIGHT;
active_window->height = the_screen->height - 1 - the_echo_area->height;
window_new_screen_size (width, height, (VFunction *)NULL);
window_new_screen_size (width, height, NULL);
/* The echo area uses a different keymap than normal info windows. */
the_echo_area->keymap = echo_area_keymap;
@ -102,7 +99,7 @@ window_initialize_windows (width, height)
/* If non-null, a function to call with WINDOW as argument when the function
window_new_screen_size () has deleted WINDOW. */
VFunction *window_deletion_notifier = (VFunction *)NULL;
VFunction *window_deletion_notifier = NULL;
void
window_new_screen_size (width, height)
@ -139,7 +136,7 @@ window_new_screen_size (width, height)
{
windows->height = 0;
maybe_free (windows->line_starts);
windows->line_starts = (char **)NULL;
windows->line_starts = NULL;
windows->line_count = 0;
break;
}
@ -187,7 +184,7 @@ window_new_screen_size (width, height)
{
win->width = width;
maybe_free (win->modeline);
win->modeline = (char *)xmalloc (1 + width);
win->modeline = xmalloc (1 + width);
}
win->height += delta_each;
@ -274,14 +271,14 @@ window_make_window (node)
/* If there isn't enough room to make another window, return now. */
if ((active_window->height / 2) < WINDOW_MIN_SIZE)
return ((WINDOW *)NULL);
return (NULL);
/* Make and initialize the new window.
The fudging about with -1 and +1 is because the following window in the
chain cannot start at window->height, since that is where the modeline
for the previous window is displayed. The inverse adjustment is made
in window_delete_window (). */
window = (WINDOW *)xmalloc (sizeof (WINDOW));
window = xmalloc (sizeof (WINDOW));
window->width = the_screen->width;
window->height = (active_window->height / 2) - 1;
#if defined (SPLIT_BEFORE_ACTIVE)
@ -292,8 +289,8 @@ window_make_window (node)
#endif
window->keymap = info_keymap;
window->goal_column = -1;
window->modeline = (char *)xmalloc (1 + window->width);
window->line_starts = (char **)NULL;
window->modeline = xmalloc (1 + window->width);
window->line_starts = NULL;
window->flags = W_UpdateWindow | W_WindowVisible;
window_set_node_of_window (window, node);
@ -538,7 +535,7 @@ window_tile_windows (style)
per_win_height = avail / numwins;
leftover = avail - (per_win_height * numwins);
last_adjusted = (WINDOW *)NULL;
last_adjusted = NULL;
for (win = windows; win; win = win->next)
{
if (do_internals || !win->node ||
@ -610,10 +607,12 @@ window_set_node_of_window (window, node)
window->point = 0;
recalculate_line_starts (window);
window->flags |= W_UpdateWindow;
/* The display_pos member is nonzero if we're displaying an anchor. */
window->point = node ? node->display_pos : 0;
window_adjust_pagetop (window);
window_make_modeline (window);
}
/* Delete WINDOW from the list of known windows. If this window was the
active window, make the next window in the chain be the active window.
If the active window is the next or previous window, choose that window
@ -766,7 +765,7 @@ string_width (string, hpos)
return (width);
}
/* Quickly guess the approximate number of lines to that NODE would
/* Quickly guess the approximate number of lines that NODE would
take to display. This really only counts carriage returns. */
int
window_physical_lines (node)
@ -793,12 +792,12 @@ calculate_line_starts (window)
WINDOW *window;
{
register int i, hpos;
char **line_starts = (char **)NULL;
char **line_starts = NULL;
int line_starts_index = 0, line_starts_slots = 0;
int bump_index;
NODE *node;
window->line_starts = (char **)NULL;
window->line_starts = NULL;
window->line_count = 0;
node = window->node;
@ -1079,9 +1078,9 @@ window_make_modeline (window)
/* Calculate the maximum size of the information to stick in MODELINE. */
{
int modeline_len = 0;
char *parent = (char *)NULL, *filename = "*no file*";
char *parent = NULL, *filename = "*no file*";
char *nodename = "*no node*";
char *update_message = (char *)NULL;
char *update_message = NULL;
NODE *node = window->node;
if (node)
@ -1113,7 +1112,7 @@ window_make_modeline (window)
modeline_len += 10 + strlen (_("-----Info: (), lines ----, "));
modeline_len += window->width;
modeline = (char *)xmalloc (1 + modeline_len);
modeline = xmalloc (1 + modeline_len);
/* Special internal windows have no filename. */
if (!parent && !*filename)
@ -1194,14 +1193,10 @@ window_set_state (window, state)
}
/* **************************************************************** */
/* */
/* Manipulating Home-Made Nodes */
/* */
/* **************************************************************** */
/* Manipulating home-made nodes. */
/* A place to buffer echo area messages. */
static NODE *echo_area_node = (NODE *)NULL;
static NODE *echo_area_node = NULL;
/* Make the node of the_echo_area be an empty one. */
static void
@ -1213,7 +1208,7 @@ free_echo_area ()
free (echo_area_node);
}
echo_area_node = (NODE *)NULL;
echo_area_node = NULL;
window_set_node_of_window (the_echo_area, echo_area_node);
}
@ -1245,7 +1240,7 @@ window_message_in_echo_area (format, arg1, arg2)
and ARG2. The message appears immediately, but does not destroy
any existing message. A future call to unmessage_in_echo_area ()
restores the old contents. */
static NODE **old_echo_area_nodes = (NODE **)NULL;
static NODE **old_echo_area_nodes = NULL;
static int old_echo_area_nodes_index = 0;
static int old_echo_area_nodes_slots = 0;
@ -1260,7 +1255,7 @@ message_in_echo_area (format, arg1, arg2)
old_echo_area_nodes, old_echo_area_nodes_slots,
4, NODE *);
}
echo_area_node = (NODE *)NULL;
echo_area_node = NULL;
window_message_in_echo_area (format, arg1, arg2);
}
@ -1277,7 +1272,7 @@ unmessage_in_echo_area ()
}
/* A place to build a message. */
static char *message_buffer = (char *)NULL;
static char *message_buffer = NULL;
static int message_buffer_index = 0;
static int message_buffer_size = 0;
@ -1290,7 +1285,7 @@ message_buffer_resize (length)
if (!message_buffer)
{
message_buffer_size = length + 1;
message_buffer = (char *)xmalloc (message_buffer_size);
message_buffer = xmalloc (message_buffer_size);
message_buffer_index = 0;
}
@ -1328,14 +1323,44 @@ build_message_buffer (format, arg1, arg2)
else
{
char c;
char *fmt_start = format + i;
char *fmt;
int fmt_len, formatted_len;
c = format[++i];
i++;
while (format[i] && strchr ("-. +0123456789", format[i]))
i++;
c = format[i];
if (c == '\0')
abort ();
fmt_len = format + i - fmt_start + 1;
fmt = (char *) xmalloc (fmt_len + 1);
strncpy (fmt, fmt_start, fmt_len);
fmt[fmt_len] = '\0';
/* If we have "%-98s", maybe 98 calls for a longer string. */
if (fmt_len > 2)
{
int j;
for (j = 0; j < fmt_len; j++)
if (isdigit (fmt[j]))
break;
formatted_len = atoi (fmt + j);
}
else
formatted_len = c == 's' ? 0 : 1; /* %s can produce empty string */
switch (c)
{
case '%': /* Insert a percent sign. */
message_buffer_resize (len + 1);
message_buffer[message_buffer_index++] = '%';
message_buffer_resize (len + formatted_len);
sprintf
(message_buffer + message_buffer_index, fmt, "%");
message_buffer_index += formatted_len;
break;
case 's': /* Insert the current arg as a string. */
@ -1346,9 +1371,11 @@ build_message_buffer (format, arg1, arg2)
string = (char *)args[arg_index++];
string_len = strlen (string);
if (formatted_len > string_len)
string_len = formatted_len;
message_buffer_resize (len + string_len);
sprintf
(message_buffer + message_buffer_index, "%s", string);
(message_buffer + message_buffer_index, fmt, string);
message_buffer_index += string_len;
}
break;
@ -1361,9 +1388,10 @@ build_message_buffer (format, arg1, arg2)
long_val = (long)args[arg_index++];
integer = (int)long_val;
message_buffer_resize (len + 32);
message_buffer_resize (len + formatted_len > 32
? formatted_len : 32);
sprintf
(message_buffer + message_buffer_index, "%d", integer);
(message_buffer + message_buffer_index, fmt, integer);
message_buffer_index = strlen (message_buffer);
}
break;
@ -1376,14 +1404,17 @@ build_message_buffer (format, arg1, arg2)
long_val = (long)args[arg_index++];
character = (int)long_val;
message_buffer_resize (len + 1);
message_buffer[message_buffer_index++] = character;
message_buffer_resize (len + formatted_len);
sprintf
(message_buffer + message_buffer_index, fmt, character);
message_buffer_index += formatted_len;
}
break;
default:
abort ();
}
free (fmt);
}
}
message_buffer[message_buffer_index] = '\0';
@ -1411,15 +1442,16 @@ message_buffer_to_node ()
{
NODE *node;
node = (NODE *)xmalloc (sizeof (NODE));
node->filename = (char *)NULL;
node->parent = (char *)NULL;
node->nodename = (char *)NULL;
node = xmalloc (sizeof (NODE));
node->filename = NULL;
node->parent = NULL;
node->nodename = NULL;
node->flags = 0;
node->display_pos =0;
/* Make sure that this buffer ends with a newline. */
node->nodelen = 1 + strlen (message_buffer);
node->contents = (char *)xmalloc (1 + node->nodelen);
node->contents = xmalloc (1 + node->nodelen);
strcpy (node->contents, message_buffer);
node->contents[node->nodelen - 1] = '\n';
node->contents[node->nodelen] = '\0';

View File

@ -1,13 +1,13 @@
/* 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
"Keep this file name-space clean" means, talk to drepper@gnu.org
before changing it!
Copyright (C) 1987, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97
Copyright (C) 1987, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98
Free Software Foundation, Inc.
NOTE: The canonical source of this file is maintained with the GNU C Library.
Bugs can be reported to bug-glibc@prep.ai.mit.edu.
Bugs can be reported to bug-glibc@gnu.org.
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
@ -27,19 +27,19 @@
/* 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
# define _NO_PROTO
#endif
#ifdef HAVE_CONFIG_H
#include <config.h>
# include <config.h>
#endif
#if !defined (__STDC__) || !__STDC__
#if !defined __STDC__ || !__STDC__
/* This is a separate conditional since some stdc systems
reject `defined (const)'. */
#ifndef const
#define const
#endif
# ifndef const
# define const
# endif
#endif
#include <stdio.h>
@ -53,11 +53,11 @@
it is simpler to just do this in the source for each such file. */
#define GETOPT_INTERFACE_VERSION 2
#if !defined (_LIBC) && defined (__GLIBC__) && __GLIBC__ >= 2
#include <gnu-versions.h>
#if _GNU_GETOPT_INTERFACE_VERSION == GETOPT_INTERFACE_VERSION
#define ELIDE_CODE
#endif
#if !defined _LIBC && defined __GLIBC__ && __GLIBC__ >= 2
# include <gnu-versions.h>
# if _GNU_GETOPT_INTERFACE_VERSION == GETOPT_INTERFACE_VERSION
# define ELIDE_CODE
# endif
#endif
#ifndef ELIDE_CODE
@ -68,26 +68,26 @@
#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>
#include <unistd.h>
# include <stdlib.h>
# include <unistd.h>
#endif /* GNU C library. */
#ifdef VMS
#include <unixlib.h>
#if HAVE_STRING_H - 0
#include <string.h>
#endif
# include <unixlib.h>
# if HAVE_STRING_H - 0
# include <string.h>
# endif
#endif
#ifndef _
/* This is for other GNU distributions with internationalized messages.
When compiling libc, the _ macro is predefined. */
#ifdef HAVE_LIBINTL_H
# include <libintl.h>
# define _(msgid) gettext (msgid)
#else
# define _(msgid) (msgid)
#endif
# ifdef HAVE_LIBINTL_H
# include <libintl.h>
# define _(msgid) gettext (msgid)
# else
# define _(msgid) (msgid)
# endif
#endif
/* This version of `getopt' appears to the caller like standard Unix `getopt'
@ -197,14 +197,22 @@ static char *posixly_correct;
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
# include <string.h>
# define my_index strchr
#else
# if HAVE_STRING_H
# include <string.h>
# else
# include <strings.h>
# endif
/* Avoid depending on library functions or files
whose names are inconsistent. */
char *getenv ();
#ifndef getenv
extern char *getenv ();
#endif
static char *
my_index (str, chr)
@ -225,11 +233,11 @@ my_index (str, chr)
#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__
# if (!defined __STDC__ || !__STDC__) && !defined strlen
/* 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 /* not __STDC__ */
#endif /* __GNUC__ */
#endif /* not __GNU_LIBRARY__ */
@ -292,7 +300,7 @@ text_set_element (__libc_subinit, store_args_and_env);
`first_nonopt' and `last_nonopt' are relocated so that they describe
the new indices of the non-options in ARGV after they are moved. */
#if defined (__STDC__) && __STDC__
#if defined __STDC__ && __STDC__
static void exchange (char **);
#endif
@ -378,7 +386,7 @@ exchange (argv)
/* Initialize the internal data when the first call is made. */
#if defined (__STDC__) && __STDC__
#if defined __STDC__ && __STDC__
static const char *_getopt_initialize (int, char *const *, const char *);
#endif
static const char *
@ -527,11 +535,11 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only)
from the shell indicating it is not an option. The later information
is only used when the used in the GNU libc. */
#ifdef _LIBC
#define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\0' \
|| (optind < nonoption_flags_len \
&& __getopt_nonoption_flags[optind] == '1'))
# define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\0' \
|| (optind < nonoption_flags_len \
&& __getopt_nonoption_flags[optind] == '1'))
#else
#define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\0')
# define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\0')
#endif
if (nextchar == NULL || *nextchar == '\0')

View File

@ -2,7 +2,7 @@
Copyright (C) 1989,90,91,92,93,94,96,97 Free Software Foundation, Inc.
NOTE: The canonical source of this file is maintained with the GNU C Library.
Bugs can be reported to bug-glibc@prep.ai.mit.edu.
Bugs can be reported to bug-glibc@gnu.org.
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

View File

@ -1,8 +1,9 @@
/* getopt_long and getopt_long_only entry points for GNU getopt.
Copyright (C) 1987,88,89,90,91,92,93,94,96,97 Free Software Foundation, Inc.
Copyright (C) 1987,88,89,90,91,92,93,94,96,97,98
Free Software Foundation, Inc.
NOTE: The canonical source of this file is maintained with the GNU C Library.
Bugs can be reported to bug-glibc@prep.ai.mit.edu.
Bugs can be reported to bug-glibc@gnu.org.
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
@ -25,7 +26,7 @@
#include "getopt.h"
#if !defined (__STDC__) || !__STDC__
#if !defined __STDC__ || !__STDC__
/* This is a separate conditional since some stdc systems
reject `defined (const)'. */
#ifndef const
@ -44,7 +45,7 @@
it is simpler to just do this in the source for each such file. */
#define GETOPT_INTERFACE_VERSION 2
#if !defined (_LIBC) && defined (__GLIBC__) && __GLIBC__ >= 2
#if !defined _LIBC && defined __GLIBC__ && __GLIBC__ >= 2
#include <gnu-versions.h>
#if _GNU_GETOPT_INTERFACE_VERSION == GETOPT_INTERFACE_VERSION
#define ELIDE_CODE

View File

@ -0,0 +1,182 @@
/* Message catalogs for internationalization.
Copyright (C) 1995, 1996, 1997, 1998 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. */
/* Because on some systems (e.g. Solaris) we sometimes have to include
the systems libintl.h as well as this file we have more complex
include protection above. But the systems header might perhaps also
define _LIBINTL_H and therefore we have to protect the definition here. */
#if !defined _LIBINTL_H || !defined _LIBGETTEXT_H
#ifndef _LIBINTL_H
# define _LIBINTL_H 1
#endif
#define _LIBGETTEXT_H 1
/* We define an additional symbol to signal that we use the GNU
implementation of gettext. */
#define __USE_GNU_GETTEXT 1
#include <sys/types.h>
#if HAVE_LOCALE_H
# include <locale.h>
#endif
#ifdef __cplusplus
extern "C" {
#endif
/* @@ end of prolog @@ */
#ifndef PARAMS
# if __STDC__ || defined __cplusplus
# define PARAMS(args) args
# else
# define PARAMS(args) ()
# endif
#endif
#ifndef NULL
# if !defined __cplusplus || defined __GNUC__
# define NULL ((void *) 0)
# else
# define NULL (0)
# endif
#endif
#if !HAVE_LC_MESSAGES
/* This value determines the behaviour of the gettext() and dgettext()
function. But some system does not have this defined. Define it
to a default value. */
# define LC_MESSAGES (-1)
#endif
/* Declarations for gettext-using-catgets interface. Derived from
Jim Meyering's libintl.h. */
struct _msg_ent
{
const char *_msg;
int _msg_number;
};
#if HAVE_CATGETS
/* These two variables are defined in the automatically by po-to-tbl.sed
generated file `cat-id-tbl.c'. */
extern const struct _msg_ent _msg_tbl[];
extern int _msg_tbl_length;
#endif
/* For automatical extraction of messages sometimes no real
translation is needed. Instead the string itself is the result. */
#define gettext_noop(Str) (Str)
/* Look up MSGID in the current default message catalog for the current
LC_MESSAGES locale. If not found, returns MSGID itself (the default
text). */
extern char *gettext PARAMS ((const char *__msgid));
extern char *gettext__ PARAMS ((const char *__msgid));
/* Look up MSGID in the DOMAINNAME message catalog for the current
LC_MESSAGES locale. */
extern char *dgettext PARAMS ((const char *__domainname, const char *__msgid));
extern char *dgettext__ PARAMS ((const char *__domainname,
const char *__msgid));
/* Look up MSGID in the DOMAINNAME message catalog for the current CATEGORY
locale. */
extern char *dcgettext PARAMS ((const char *__domainname, const char *__msgid,
int __category));
extern char *dcgettext__ PARAMS ((const char *__domainname,
const char *__msgid, int __category));
/* Set the current default message catalog to DOMAINNAME.
If DOMAINNAME is null, return the current default.
If DOMAINNAME is "", reset to the default of "messages". */
extern char *textdomain PARAMS ((const char *__domainname));
extern char *textdomain__ PARAMS ((const char *__domainname));
/* Specify that the DOMAINNAME message catalog will be found
in DIRNAME rather than in the system locale data base. */
extern char *bindtextdomain PARAMS ((const char *__domainname,
const char *__dirname));
extern char *bindtextdomain__ PARAMS ((const char *__domainname,
const char *__dirname));
#if ENABLE_NLS
/* Solaris 2.3 has the gettext function but dcgettext is missing.
So we omit this optimization for Solaris 2.3. BTW, Solaris 2.4
has dcgettext. */
# if !HAVE_CATGETS && (!HAVE_GETTEXT || HAVE_DCGETTEXT)
# define gettext(Msgid) \
dgettext (NULL, Msgid)
# define dgettext(Domainname, Msgid) \
dcgettext (Domainname, Msgid, LC_MESSAGES)
# if defined __GNUC__ && __GNUC__ == 2 && __GNUC_MINOR__ >= 7
/* This global variable is defined in loadmsgcat.c. We need a sign,
whether a new catalog was loaded, which can be associated with all
translations. */
extern int _nl_msg_cat_cntr;
# define dcgettext(Domainname, Msgid, Category) \
(__extension__ \
({ \
char *__result; \
if (__builtin_constant_p (Msgid)) \
{ \
static char *__translation__; \
static int __catalog_counter__; \
if (! __translation__ || __catalog_counter__ != _nl_msg_cat_cntr) \
{ \
__translation__ = \
dcgettext__ (Domainname, Msgid, Category); \
__catalog_counter__ = _nl_msg_cat_cntr; \
} \
__result = __translation__; \
} \
else \
__result = dcgettext__ (Domainname, Msgid, Category); \
__result; \
}))
# endif
# endif
#else
# define gettext(Msgid) (Msgid)
# define dgettext(Domainname, Msgid) (Msgid)
# define dcgettext(Domainname, Msgid, Category) (Msgid)
# define textdomain(Domainname) ((char *) Domainname)
# define bindtextdomain(Domainname, Dirname) ((char *) Dirname)
#endif
/* @@ begin of epilog @@ */
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,37 @@
/* substring.c -- extract substring.
$Id: substring.c,v 1.1 1999/02/17 22:30:10 karl Exp $
Copyright (C) 1999 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 "system.h"
char *
substring (start, end)
char *start;
char *end;
{
char *result = xmalloc (end - start + 1);
char *scan_result = result;
char *scan = start;
while (scan < end)
*scan_result++ = *scan++;
*scan_result = 0;
return result;
}

View File

@ -1,7 +1,7 @@
/* system.h: System-dependent declarations. Include this first.
$Id: system.h,v 1.5 1997/07/31 20:34:36 karl Exp $
/* system.h: system-dependent declarations; include this first.
$Id: system.h,v 1.14 1999/07/17 21:11:34 karl Exp $
Copyright (C) 1997 Free Software Foundation, Inc.
Copyright (C) 1997, 98, 99 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
@ -37,7 +37,22 @@
#ifdef HAVE_LOCALE_H
#include <locale.h>
#endif
#ifndef HAVE_SETLOCALE
#define setlocale(category,locale) /* empty */
#endif
/* For gettext (NLS). */
#include <libintl.h>
#define _(String) gettext (String)
#define N_(String) (String)
#ifdef STDC_HEADERS
#define getopt system_getopt
#include <stdlib.h>
#undef getopt
#else
extern char *getenv ();
#endif
/* Don't use bcopy! Use memmove if source and destination may overlap,
memcpy otherwise. */
@ -51,18 +66,6 @@
char *memchr ();
#endif
#ifdef STDC_HEADERS
#define getopt system_getopt
#include <stdlib.h>
#undef getopt
#else
extern char *getenv ();
#endif
#ifndef HAVE_STRERROR
extern char *strerror ();
#endif
#include <errno.h>
#ifndef errno
extern int errno;
@ -71,7 +74,29 @@ extern int errno;
#include <perror.h>
#endif
#ifndef HAVE_DECL_STRERROR
extern char *strerror ();
#endif
#ifndef HAVE_DECL_STRCASECMP
extern int strcasecmp ();
#endif
#ifndef HAVE_DECL_STRNCASECMP
extern int strncasecmp ();
#endif
#ifndef HAVE_DECL_STRCOLL
extern int strcoll ();
#endif
#include <sys/stat.h>
#if STAT_MACROS_BROKEN
# undef S_ISDIR
#endif
#if !defined(S_ISDIR) && defined(S_IFDIR)
# define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR)
#endif
#ifdef HAVE_SYS_FILE_H
#include <sys/file.h>
@ -89,6 +114,77 @@ extern int errno;
#endif /* not HAVE_FCNTL_H */
#endif /* not O_RDONLY */
/* MS-DOS and similar non-Posix systems have some peculiarities:
- they distinguish between binary and text files;
- they use both `/' and `\\' as directory separator in file names;
- they can have a drive letter X: prepended to a file name;
- they have a separate root directory on each drive;
- their filesystems are case-insensitive;
- directories in environment variables (like INFOPATH) are separated
by `;' rather than `:';
- text files can have their lines ended either with \n or with \r\n pairs;
These are all parameterized here except the last, which is
handled by the source code as appropriate (mostly, in info/). */
#ifndef O_BINARY
# ifdef _O_BINARY
# define O_BINARY _O_BINARY
# else
# define O_BINARY 0
# endif
#endif /* O_BINARY */
#if O_BINARY
# include <io.h>
# ifdef __MSDOS__
# include <limits.h>
# ifdef __DJGPP__
# define HAVE_LONG_FILENAMES(dir) (pathconf (dir, _PC_NAME_MAX) > 12)
# define NULL_DEVICE "/dev/null"
# else /* !__DJGPP__ */
# define HAVE_LONG_FILENAMES(dir) (0)
# define NULL_DEVICE "NUL"
# endif /* !__DJGPP__ */
# define SET_SCREEN_SIZE_HELPER terminal_prep_terminal()
# define DEFAULT_INFO_PRINT_COMMAND ">PRN"
# else /* !__MSDOS__ */
# define setmode(f,m) _setmode(f,m)
# define HAVE_LONG_FILENAMES(dir) (1)
# define NULL_DEVICE "NUL"
# endif /* !__MSDOS__ */
# define SET_BINARY(f) do {if (!isatty(f)) setmode(f,O_BINARY);} while(0)
# define FOPEN_RBIN "rb"
# define FOPEN_WBIN "wb"
# define IS_SLASH(c) ((c) == '/' || (c) == '\\')
# define HAVE_DRIVE(n) ((n)[0] && (n)[1] == ':')
# define IS_ABSOLUTE(n) (IS_SLASH((n)[0]) || ((n)[0] && (n)[1] == ':'))
# define FILENAME_CMP strcasecmp
# define FILENAME_CMPN strncasecmp
# define PATH_SEP ";"
# define STRIP_DOT_EXE 1
# define DEFAULT_TMPDIR "c:/"
# define PIPE_USE_FORK 0
#else /* not O_BINARY */
# define SET_BINARY(f) (void)0
# define FOPEN_RBIN "r"
# define FOPEN_WBIN "w"
# define IS_SLASH(c) ((c) == '/')
# define HAVE_DRIVE(n) (0)
# define IS_ABSOLUTE(n) ((n)[0] == '/')
# define FILENAME_CMP strcmp
# define FILENAME_CMPN strncmp
# define HAVE_LONG_FILENAMES(dir) (1)
# define PATH_SEP ":"
# define STRIP_DOT_EXE 0
# ifdef VMS
# define DEFAULT_TMPDIR "sys$scratch:"
# else
# define DEFAULT_TMPDIR "/tmp/"
# endif
# define NULL_DEVICE "/dev/null"
# define PIPE_USE_FORK 1
#endif /* not O_BINARY */
#ifdef HAVE_PWD_H
#include <pwd.h>
#endif
@ -98,5 +194,10 @@ struct passwd *getpwnam ();
/* Our library routines not included in any system library. */
extern void *xmalloc (), *xrealloc ();
extern char *xstrdup ();
extern void xexit ();
extern char *substring ();
/* For convenience. */
#define STREQ(s1,s2) (strcmp (s1, s2) == 0)
#endif /* TEXINFO_SYSTEM_H */

View File

@ -0,0 +1,86 @@
/* xexit.c -- exit with attention to return values and closing stdout.
$Id: xexit.c,v 1.5 1999/02/19 14:13:51 karl Exp $
Copyright (C) 1999 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 "system.h"
/* SunOS 4.1.1 gets STDC_HEADERS defined, but it doesn't provide
EXIT_FAILURE. So far no system has defined one of EXIT_FAILURE and
EXIT_SUCCESS without the other. */
#ifdef EXIT_SUCCESS
/* The following test is to work around the gross typo in
systems like Sony NEWS-OS Release 4.0C, whereby EXIT_FAILURE
is defined to 0, not 1. */
# if !EXIT_FAILURE
# undef EXIT_FAILURE
# define EXIT_FAILURE 1
# endif
#else /* not EXIT_SUCCESS */
# ifdef VMS /* these values suppress some messages; from gnuplot */
# define EXIT_SUCCESS 1
# define EXIT_FAILURE 0x10000002
# else /* not VMS */
# define EXIT_SUCCESS 0
# define EXIT_FAILURE 1
# endif /* not VMS */
#endif /* not EXIT_SUCCESS */
/* Flush stdout first, exit if failure. Otherwise, if EXIT_STATUS is
zero, exit successfully, else unsuccessfully. */
void
xexit (exit_status)
int exit_status;
{
if (ferror (stdout))
{
fprintf (stderr, "ferror on stdout");
exit_status = 1;
}
else if (fflush (stdout) != 0)
{
fprintf (stderr, "fflush error on stdout");
exit_status = 1;
}
exit_status = exit_status == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
exit (exit_status);
}
/* Why do we care about stdout you may ask? Here's why, from Jim
Meyering in the lib/closeout.c file. */
/* If a program writes *anything* to stdout, that program should close
stdout and make sure that the close succeeds. Otherwise, suppose that
you go to the extreme of checking the return status of every function
that does an explicit write to stdout. The last printf can succeed in
writing to the internal stream buffer, and yet the fclose(stdout) could
still fail (due e.g., to a disk full error) when it tries to write
out that buffered data. Thus, you would be left with an incomplete
output file and the offending program would exit successfully.
Besides, it's wasteful to check the return value from every call
that writes to stdout -- just let the internal stream state record
the failure. That's what the ferror test is checking below.
It's important to detect such failures and exit nonzero because many
tools (most notably `make' and other build-management systems) depend
on being able to detect failure in other tools via their exit status. */

View File

@ -1,8 +1,8 @@
makeinfo is a standalone program to convert Texinfo source into Info
files readable with standalone info or M-x info in Emacs.
makeinfo can also output plain ASCII. Work to support HTML and Troff
output is almost complete.
makeinfo can also output plain ASCII (with --no-headers)
or HTML (with --html).
The Emacs function M-x texinfo-format-buffer does more or less the same
job, but makeinfo is faster and gives better error messages.

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,50 @@
/* cmds.h -- declarations for cmds.c.
$Id: cmds.h,v 1.4 1999/04/25 20:43:51 karl Exp $
Copyright (C) 1998, 99 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. */
#ifndef CMDS_H
#define CMDS_H
/* The three arguments a command can get are a flag saying whether it is
before argument parsing (START) or after (END), the starting position
of the arguments, and the ending position. */
typedef void COMMAND_FUNCTION (); /* So we can say COMMAND_FUNCTION *foo; */
/* Each command has an associated function. When the command is
encountered in the text, the associated function is called with START
as the argument. If the function expects arguments in braces, it
remembers itself on the stack. When the corresponding close brace is
encountered, the function is called with END as the argument. */
#define START 0
#define END 1
/* Does the command expect braces? */
#define NO_BRACE_ARGS 0
#define BRACE_ARGS 1
#define MAYBE_BRACE_ARGS 2
typedef struct
{
char *name;
COMMAND_FUNCTION *proc;
int argument_in_braces;
} COMMAND;
extern COMMAND command_table[];
#endif /* !CMDS_H */

View File

@ -0,0 +1,663 @@
/* defun.c -- @defun and friends.
$Id: defun.c,v 1.11 1999/07/11 16:50:19 karl Exp $
Copyright (C) 1998, 99 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 "system.h"
#include "defun.h"
#include "insertion.h"
#include "makeinfo.h"
#define DEFUN_SELF_DELIMITING(c) \
((c) == '(' || (c) == ')' || (c) == '[' || (c) == ']')
struct token_accumulator
{
unsigned int length;
unsigned int index;
char **tokens;
};
static void
initialize_token_accumulator (accumulator)
struct token_accumulator *accumulator;
{
accumulator->length = 0;
accumulator->index = 0;
accumulator->tokens = NULL;
}
static void
accumulate_token (accumulator, token)
struct token_accumulator *accumulator;
char *token;
{
if (accumulator->index >= accumulator->length)
{
accumulator->length += 10;
accumulator->tokens = xrealloc (accumulator->tokens,
(accumulator->length * sizeof (char *)));
}
accumulator->tokens[accumulator->index] = token;
accumulator->index += 1;
}
/* Given STRING_POINTER pointing at an open brace, skip forward and return a
pointer to just past the matching close brace. */
static int
scan_group_in_string (string_pointer)
char **string_pointer;
{
char *scan_string = (*string_pointer) + 1;
unsigned int level = 1;
for (;;)
{
int c;
if (level == 0)
{
*string_pointer = scan_string;
return 1;
}
c = *scan_string++;
if (c == 0)
{
/* Tweak line_number to compensate for fact that
we gobbled the whole line before coming here. */
line_number -= 1;
line_error (_("Missing `}' in @def arg"));
line_number += 1;
*string_pointer = scan_string - 1;
return 0;
}
if (c == '{')
level += 1;
if (c == '}')
level -= 1;
}
}
/* Return a list of tokens from the contents of STRING.
Commands and brace-delimited groups count as single tokens.
Contiguous whitespace characters are converted to a token
consisting of a single space. */
static char **
args_from_string (string)
char *string;
{
struct token_accumulator accumulator;
char *token_start, *token_end;
char *scan_string = string;
initialize_token_accumulator (&accumulator);
while (*scan_string)
{ /* Replace arbitrary whitespace by a single space. */
if (whitespace (*scan_string))
{
scan_string += 1;
while (whitespace (*scan_string))
scan_string += 1;
accumulate_token ((&accumulator), (xstrdup (" ")));
continue;
}
/* Commands count as single tokens. */
if (*scan_string == COMMAND_PREFIX)
{
token_start = scan_string;
scan_string += 1;
if (self_delimiting (*scan_string))
scan_string += 1;
else
{
int c;
while (1)
{
c = *scan_string++;
if ((c == 0) || (c == '{') || (whitespace (c)))
{
scan_string -= 1;
break;
}
}
if (*scan_string == '{')
{
char *s = scan_string;
(void) scan_group_in_string (&s);
scan_string = s;
}
}
token_end = scan_string;
}
/* Parentheses and brackets are self-delimiting. */
else if (DEFUN_SELF_DELIMITING (*scan_string))
{
token_start = scan_string;
scan_string += 1;
token_end = scan_string;
}
/* Open brace introduces a group that is a single token. */
else if (*scan_string == '{')
{
char *s = scan_string;
int balanced = scan_group_in_string (&s);
token_start = scan_string + 1;
scan_string = s;
token_end = balanced ? (scan_string - 1) : scan_string;
}
/* Otherwise a token is delimited by whitespace, parentheses,
brackets, or braces. A token is also ended by a command. */
else
{
token_start = scan_string;
for (;;)
{
int c;
c = *scan_string++;
/* Do not back up if we're looking at a }; since the only
valid }'s are those matched with {'s, we want to give
an error. If we back up, we go into an infinite loop. */
if (!c || whitespace (c) || DEFUN_SELF_DELIMITING (c)
|| c == '{')
{
scan_string--;
break;
}
/* If we encounter a command embedded within a token,
then end the token. */
if (c == COMMAND_PREFIX)
{
scan_string--;
break;
}
}
token_end = scan_string;
}
accumulate_token (&accumulator, substring (token_start, token_end));
}
accumulate_token (&accumulator, NULL);
return accumulator.tokens;
}
static void
process_defun_args (defun_args, auto_var_p)
char **defun_args;
int auto_var_p;
{
int pending_space = 0;
for (;;)
{
char *defun_arg = *defun_args++;
if (defun_arg == NULL)
break;
if (defun_arg[0] == ' ')
{
pending_space = 1;
continue;
}
if (pending_space)
{
add_char (' ');
pending_space = 0;
}
if (DEFUN_SELF_DELIMITING (defun_arg[0]))
add_char (defun_arg[0]);
else if (defun_arg[0] == '&')
if (html)
{
defun_arg = escape_string (xstrdup (defun_arg));
add_word (defun_arg);
free (defun_arg);
}
else
add_word (defun_arg);
else if (defun_arg[0] == COMMAND_PREFIX)
execute_string ("%s", defun_arg);
else if (auto_var_p)
if (html)
{
defun_arg = escape_string (xstrdup (defun_arg));
add_word (defun_arg);
free (defun_arg);
}
else
add_word (defun_arg);
else
add_word (defun_arg);
}
}
static char *
next_nonwhite_defun_arg (arg_pointer)
char ***arg_pointer;
{
char **scan = (*arg_pointer);
char *arg = (*scan++);
if ((arg != 0) && (*arg == ' '))
arg = *scan++;
if (arg == 0)
scan -= 1;
*arg_pointer = scan;
return (arg == 0) ? "" : arg;
}
/* This is needed also in insertion.c. */
enum insertion_type
get_base_type (type)
enum insertion_type type;
{
enum insertion_type base_type;
switch (type)
{
case defivar: base_type = defcv; break;
case defmac: base_type = deffn; break;
case defmethod: base_type = defop; break;
case defopt: base_type = defvr; break;
case defspec: base_type = deffn; break;
case deftypefun: base_type = deftypefn; break;
case deftypeivar: base_type = deftypeivar; break;
case deftypemethod: base_type = deftypemethod; break;
case deftypeop: base_type = deftypeop; break;
case deftypevar: base_type = deftypevr; break;
case defun: base_type = deffn; break;
case defvar: base_type = defvr; break;
default:
base_type = type;
break;
}
return base_type;
}
/* Make the defun type insertion.
TYPE says which insertion this is.
X_P, if nonzero, says not to start a new insertion. */
static void
defun_internal (type, x_p)
enum insertion_type type;
int x_p;
{
enum insertion_type base_type;
char **defun_args, **scan_args;
char *category, *defined_name, *type_name, *type_name2;
{
char *line;
/* The @def.. line is the only place in Texinfo where you are
allowed to use unquoted braces that don't delimit arguments of
a command or a macro; in any other place it will trigger an
error message from the reader loop. The special handling of
this case inside `args_from_string' is an extra special hack
which allows this. The side effect is that if we try to expand
the rest of the line below, the recursive reader loop will
signal an error if there are brace-delimited arguments on that line.
The best solution to this would be to change the syntax of
@def.. commands so that it doesn't violate Texinfo's own rules.
But it's probably too late for this now, as it will break a lot
of existing manuals.
Unfortunately, this means that you can't call macros, use @value, etc.
inside @def.. commands, sigh. */
get_rest_of_line (0, &line);
defun_args = (args_from_string (line));
free (line);
}
scan_args = defun_args;
/* Get base type and category string. */
base_type = get_base_type (type);
/* xx all these const strings should be determined upon
documentlanguage argument and NOT via gettext (kama). */
switch (type)
{
case defun:
case deftypefun:
category = _("Function");
break;
case defmac:
category = _("Macro");
break;
case defspec:
category = _("Special Form");
break;
case defvar:
case deftypevar:
category = _("Variable");
break;
case defopt:
category = _("User Option");
break;
case defivar:
case deftypeivar:
category = _("Instance Variable");
break;
case defmethod:
case deftypemethod:
category = _("Method");
break;
default:
category = next_nonwhite_defun_arg (&scan_args);
break;
}
/* The class name. */
if ((base_type == deftypefn)
|| (base_type == deftypevr)
|| (base_type == defcv)
|| (base_type == defop)
|| (base_type == deftypeivar)
|| (base_type == deftypemethod)
|| (base_type == deftypeop)
)
type_name = next_nonwhite_defun_arg (&scan_args);
/* The type name for typed languages. */
if (base_type == deftypemethod
|| base_type == deftypeivar
|| base_type == deftypeop
)
type_name2 = next_nonwhite_defun_arg (&scan_args);
/* The function or whatever that's actually being defined. */
defined_name = next_nonwhite_defun_arg (&scan_args);
/* This hack exists solely for the purposes of formatting the Texinfo
manual. I couldn't think of a better way. The token might be a
simple @@ followed immediately by more text. If this is the case,
then the next defun arg is part of this one, and we should
concatenate them. */
if (*scan_args && **scan_args && !whitespace (**scan_args)
&& STREQ (defined_name, "@@"))
{
char *tem = xmalloc (3 + strlen (scan_args[0]));
sprintf (tem, "@@%s", scan_args[0]);
free (scan_args[0]);
scan_args[0] = tem;
scan_args++;
defined_name = tem;
}
if (!x_p)
begin_insertion (type);
/* Write the definition header line.
This should start at the normal indentation. */
current_indent -= default_indentation_increment;
start_paragraph ();
if (html && !x_p)
/* Start the definition on new paragraph. */
add_word ("<p>\n");
if (!html)
switch (base_type)
{
case deffn:
case defvr:
case deftp:
execute_string (" -- %s: %s", category, defined_name);
break;
case deftypefn:
case deftypevr:
execute_string (" -- %s: %s %s", category, type_name, defined_name);
break;
case defcv:
execute_string (" -- %s %s %s: %s", category, _("of"), type_name,
defined_name);
break;
case deftypeivar:
execute_string (" -- %s %s %s: %s %s", category, _("of"), type_name,
type_name2, defined_name);
break;
case defop:
execute_string (" -- %s %s %s: %s", category, _("on"), type_name,
defined_name);
break;
case deftypeop:
execute_string (" -- %s %s %s: %s %s", category, _("on"), type_name,
type_name2, defined_name);
break;
case deftypemethod:
execute_string (" -- %s %s %s: %s %s", category, _("on"), type_name,
type_name2, defined_name);
break;
}
if (html)
{
/* If this is not a @def...x version, it could only
be a normal version @def.... So start the table here. */
if (!x_p)
add_word ("<table width=\"100%\">\n");
/* If this is an @def...x there has to be an other @def... before
it, so this is only a new row within an existing table. With
two complete standalone tables the gap between them is too big. */
add_word ("<tr>\n");
add_word ("<td align=\"left\">");
switch (base_type)
{
case deffn:
case defvr:
case deftp:
/* <i> is for the following function arguments. */
add_word_args ("<b>%s</b><i>", defined_name);
break;
case deftypefn:
case deftypevr:
add_word_args ("%s <b>%s</b><i>", type_name, defined_name);
break;
case defcv:
case defop:
add_word_args ("<b>%s</b><i>", defined_name);
break;
case deftypemethod:
case deftypeop:
case deftypeivar:
add_word_args ("%s <b>%s</b><i>", type_name2, defined_name);
break;
}
} /* if (html)... */
current_indent += default_indentation_increment;
/* Now process the function arguments, if any. If these carry onto
the next line, they should be indented by two increments to
distinguish them from the body of the definition, which is indented
by one increment. */
current_indent += default_indentation_increment;
switch (base_type)
{
case deffn:
case defop:
process_defun_args (scan_args, 1);
break;
/* Through Makeinfo 1.67 we processed remaining args only for deftp,
deftypefn, and deftypemethod. But the libc manual, for example,
needs to say:
@deftypevar {char *} tzname[2]
And simply allowing the extra text seems far simpler than trying
to invent yet more defn commands. In any case, we should either
output it or give an error, not silently ignore it. */
default:
process_defun_args (scan_args, 0);
break;
}
current_indent -= default_indentation_increment;
close_single_paragraph ();
if (html)
{
/* xx The single words (on, off) used here, should depend on
documentlanguage and NOT on gettext --kama. */
switch (base_type)
{
case deffn:
case defvr:
case deftp:
case deftypefn:
case deftypevr:
add_word ("</i>"); /* close italic area for arguments */
/* put the rest into the second column */
add_word_args ("</td>\n<td align=\"right\">%s", category);
break;
case defcv:
add_word ("</td>\n<td align=\"right\">");
add_word_args ("%s %s %s", category, _("of"), type_name);
break;
case defop:
case deftypemethod:
case deftypeop:
add_word ("</i>");
add_word ("</td>\n<td align=\"right\">");
add_word_args ("%s %s %s", category, _("on"), type_name);
break;
case deftypeivar:
add_word ("</i>");
add_word ("</td>\n<td align=\"right\">");
add_word_args ("%s %s %s", category, _("of"), type_name);
break;
} /* switch (base_type)... */
add_word ("</td>\n"); /* close second column */
add_word ("</tr>\n"); /* close row */
/* This is needed because I have to know if the next line is
normal text or another @def..x. If text follows, create a new
table to get the indentation for the following text.
This construction would fail if someone uses:
@deffn
@sp 2
@deffnx
.
@end deffn
But we don't care. */
if (!looking_at ("@def"))
{
add_word ("</table>\n");
add_word ("<table width=\"95%\" align=\"center\">\n");
add_word ("<tr><td>\n");
}
} /* if (html)... */
/* Make an entry in the appropriate index. */
switch (base_type)
{
case deffn:
case deftypefn:
execute_string ("@findex %s\n", defined_name);
break;
case defvr:
case deftypevr:
case defcv:
execute_string ("@vindex %s\n", defined_name);
break;
case deftypeivar:
execute_string ("@vindex %s %s %s\n", defined_name, _("of"), type_name);
break;
case defop:
case deftypeop:
case deftypemethod:
execute_string ("@findex %s %s %s\n", defined_name, _("on"), type_name);
break;
case deftp:
execute_string ("@tindex %s\n", defined_name);
break;
}
/* Deallocate the token list. */
scan_args = defun_args;
while (1)
{
char * arg = (*scan_args++);
if (arg == NULL)
break;
free (arg);
}
free (defun_args);
}
/* Add an entry for a function, macro, special form, variable, or option.
If the name of the calling command ends in `x', then this is an extra
entry included in the body of an insertion of the same type. */
void
cm_defun ()
{
int x_p;
enum insertion_type type;
char *temp = xstrdup (command);
x_p = (command[strlen (command) - 1] == 'x');
if (x_p)
temp[strlen (temp) - 1] = 0;
type = find_type_from_name (temp);
free (temp);
/* If we are adding to an already existing insertion, then make sure
that we are already in an insertion of type TYPE. */
if (x_p && (!insertion_level || insertion_stack->insertion != type))
{
line_error (_("Must be in `%s' insertion to use `%sx'"),
command, command);
discard_until ("\n");
return;
}
defun_internal (type, x_p);
}

View File

@ -0,0 +1,31 @@
/* defun.h -- declaration for defuns.
$Id: defun.h,v 1.2 1999/03/25 22:49:10 karl Exp $
Copyright (C) 1999 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 Karl Heinz Marbaise <kama@hippo.fido.de>. */
#ifndef DEFUN_H
#define DEFUN_H
#include "insertion.h"
extern enum insertion_type get_base_type ();
extern void cm_defun ();
#endif /* !DEFUN_H */

View File

@ -0,0 +1,529 @@
/* files.c -- file-related functions for Texinfo.
$Id: files.c,v 1.5 1999/03/23 21:42:44 karl Exp $
Copyright (C) 1998, 99 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 "system.h"
#include "files.h"
#include "macro.h"
#include "makeinfo.h"
FSTACK *filestack = NULL;
static int node_filename_stack_index = 0;
static int node_filename_stack_size = 0;
static char **node_filename_stack = NULL;
/* Looking for include files. */
/* Given a string containing units of information separated by colons,
return the next one pointed to by INDEX, or NULL if there are no more.
Advance INDEX to the character after the colon. */
static char *
extract_colon_unit (string, index)
char *string;
int *index;
{
int start;
int path_sep_char = PATH_SEP[0];
int i = *index;
if (!string || (i >= strlen (string)))
return NULL;
/* Each call to this routine leaves the index pointing at a colon if
there is more to the path. If i > 0, then increment past the
`:'. If i == 0, then the path has a leading colon. Trailing colons
are handled OK by the `else' part of the if statement; an empty
string is returned in that case. */
if (i && string[i] == path_sep_char)
i++;
start = i;
while (string[i] && string[i] != path_sep_char) i++;
*index = i;
if (i == start)
{
if (string[i])
(*index)++;
/* Return "" in the case of a trailing `:'. */
return xstrdup ("");
}
else
{
char *value;
value = xmalloc (1 + (i - start));
memcpy (value, &string[start], (i - start));
value [i - start] = 0;
return value;
}
}
/* Return the full pathname for FILENAME by searching along PATH.
When found, return the stat () info for FILENAME in FINFO.
If PATH is NULL, only the current directory is searched.
If the file could not be found, return a NULL pointer. */
static char *
get_file_info_in_path (filename, path, finfo)
char *filename, *path;
struct stat *finfo;
{
char *dir;
int result, index = 0;
if (path == NULL)
path = ".";
/* Handle absolute pathnames. */
if (IS_ABSOLUTE (filename)
|| (*filename == '.'
&& (IS_SLASH (filename[1])
|| (filename[1] == '.' && IS_SLASH (filename[2])))))
{
if (stat (filename, finfo) == 0)
return xstrdup (filename);
else
return NULL;
}
while ((dir = extract_colon_unit (path, &index)))
{
char *fullpath;
if (!*dir)
{
free (dir);
dir = xstrdup (".");
}
fullpath = xmalloc (2 + strlen (dir) + strlen (filename));
sprintf (fullpath, "%s/%s", dir, filename);
free (dir);
result = stat (fullpath, finfo);
if (result == 0)
return fullpath;
else
free (fullpath);
}
return NULL;
}
/* Find and load the file named FILENAME. Return a pointer to
the loaded file, or NULL if it can't be loaded. */
char *
find_and_load (filename)
char *filename;
{
struct stat fileinfo;
long file_size;
int file = -1, count = 0;
char *fullpath, *result;
#if O_BINARY || defined (VMS)
int n;
#endif
result = fullpath = NULL;
fullpath = get_file_info_in_path (filename, include_files_path, &fileinfo);
if (!fullpath)
goto error_exit;
filename = fullpath;
file_size = (long) fileinfo.st_size;
file = open (filename, O_RDONLY);
if (file < 0)
goto error_exit;
/* Load the file, with enough room for a newline and a null. */
result = xmalloc (file_size + 2);
/* VMS stat lies about the st_size value. The actual number of
readable bytes is always less than this value. The arcane
mysteries of VMS/RMS are too much to probe, so this hack
suffices to make things work. */
#if O_BINARY || defined (VMS)
#ifdef VMS
while ((n = read (file, result + count, file_size)) > 0)
#else /* !VMS */
#ifndef WIN32
while ((n = read (file, result + count, file_size)) > 0)
#else /* WIN32 */
/* Does WIN32 really need reading 1 character at a time?? */
while ((n = read (file, result + count, 1)) > 0)
#endif /* WIN32 */
#endif /* !VMS */
count += n;
if (0 < count && count < file_size)
result = xrealloc (result, count + 2); /* why waste the slack? */
else if (n == -1)
#else /* !VMS && !O_BINARY */
count = file_size;
if (read (file, result, file_size) != file_size)
#endif /* !VMS && !WIN32 */
error_exit:
{
if (result)
free (result);
if (fullpath)
free (fullpath);
if (file != -1)
close (file);
return NULL;
}
close (file);
/* Set the globals to the new file. */
input_text = result;
input_text_length = count;
input_filename = fullpath;
node_filename = xstrdup (fullpath);
input_text_offset = 0;
line_number = 1;
/* Not strictly necessary. This magic prevents read_token () from doing
extra unnecessary work each time it is called (that is a lot of times).
INPUT_TEXT_LENGTH is one past the actual end of the text. */
input_text[input_text_length] = '\n';
/* This, on the other hand, is always necessary. */
input_text[input_text_length+1] = 0;
return result;
}
/* Pushing and popping files. */
void
push_node_filename ()
{
if (node_filename_stack_index + 1 > node_filename_stack_size)
node_filename_stack = xrealloc
(node_filename_stack, (node_filename_stack_size += 10) * sizeof (char *));
node_filename_stack[node_filename_stack_index] = node_filename;
node_filename_stack_index++;
}
void
pop_node_filename ()
{
node_filename = node_filename_stack[--node_filename_stack_index];
}
/* Save the state of the current input file. */
void
pushfile ()
{
FSTACK *newstack = xmalloc (sizeof (FSTACK));
newstack->filename = input_filename;
newstack->text = input_text;
newstack->size = input_text_length;
newstack->offset = input_text_offset;
newstack->line_number = line_number;
newstack->next = filestack;
filestack = newstack;
push_node_filename ();
}
/* Make the current file globals be what is on top of the file stack. */
void
popfile ()
{
FSTACK *tos = filestack;
if (!tos)
abort (); /* My fault. I wonder what I did? */
if (macro_expansion_output_stream)
{
maybe_write_itext (input_text, input_text_offset);
forget_itext (input_text);
}
/* Pop the stack. */
filestack = filestack->next;
/* Make sure that commands with braces have been satisfied. */
if (!executing_string && !me_executing_string)
discard_braces ();
/* Get the top of the stack into the globals. */
input_filename = tos->filename;
input_text = tos->text;
input_text_length = tos->size;
input_text_offset = tos->offset;
line_number = tos->line_number;
free (tos);
/* Go back to the (now) current node. */
pop_node_filename ();
}
/* Flush all open files on the file stack. */
void
flush_file_stack ()
{
while (filestack)
{
char *fname = input_filename;
char *text = input_text;
popfile ();
free (fname);
free (text);
}
}
/* Return the index of the first character in the filename
which is past all the leading directory characters. */
static int
skip_directory_part (filename)
char *filename;
{
int i = strlen (filename) - 1;
while (i && !IS_SLASH (filename[i]))
i--;
if (IS_SLASH (filename[i]))
i++;
else if (filename[i] && HAVE_DRIVE (filename))
i = 2;
return i;
}
char *
filename_non_directory (name)
char *name;
{
return xstrdup (name + skip_directory_part (name));
}
/* Return just the simple part of the filename; i.e. the
filename without the path information, or extensions.
This conses up a new string. */
char *
filename_part (filename)
char *filename;
{
char *basename = filename_non_directory (filename);
#ifdef REMOVE_OUTPUT_EXTENSIONS
/* See if there is an extension to remove. If so, remove it. */
{
char *temp;
temp = strrchr (basename, '.');
if (temp)
*temp = 0;
}
#endif /* REMOVE_OUTPUT_EXTENSIONS */
return basename;
}
/* Return the pathname part of filename. This can be NULL. */
char *
pathname_part (filename)
char *filename;
{
char *expand_filename ();
char *result = NULL;
int i;
filename = expand_filename (filename, "");
i = skip_directory_part (filename);
if (i)
{
result = xmalloc (1 + i);
strncpy (result, filename, i);
result[i] = 0;
}
free (filename);
return result;
}
/* Return the expansion of FILENAME. */
char *
expand_filename (filename, input_name)
char *filename, *input_name;
{
int i;
char *full_pathname ();
if (filename)
{
filename = full_pathname (filename);
if (IS_ABSOLUTE (filename)
|| (*filename == '.' &&
(IS_SLASH (filename[1]) ||
(filename[1] == '.' && IS_SLASH (filename[2])))))
return filename;
}
else
{
filename = filename_non_directory (input_name);
if (!*filename)
{
free (filename);
filename = xstrdup ("noname.texi");
}
for (i = strlen (filename) - 1; i; i--)
if (filename[i] == '.')
break;
if (!i)
i = strlen (filename);
if (i + 6 > (strlen (filename)))
filename = xrealloc (filename, i + 6);
strcpy (filename + i, html ? ".html" : ".info");
return filename;
}
if (IS_ABSOLUTE (input_name))
{
/* Make it so that relative names work. */
char *result;
i = strlen (input_name) - 1;
result = xmalloc (1 + strlen (input_name) + strlen (filename));
strcpy (result, input_name);
while (!IS_SLASH (result[i]) && i)
i--;
if (IS_SLASH (result[i]))
i++;
strcpy (&result[i], filename);
free (filename);
return result;
}
return filename;
}
/* Return the full path to FILENAME. */
char *
full_pathname (filename)
char *filename;
{
int initial_character;
char *result;
/* No filename given? */
if (!filename || !*filename)
return xstrdup ("");
/* Already absolute? */
if (IS_ABSOLUTE (filename) ||
(*filename == '.' &&
(IS_SLASH (filename[1]) ||
(filename[1] == '.' && IS_SLASH (filename[2])))))
return xstrdup (filename);
initial_character = *filename;
if (initial_character != '~')
{
char *localdir = xmalloc (1025);
#ifdef HAVE_GETCWD
if (!getcwd (localdir, 1024))
#else
if (!getwd (localdir))
#endif
{
fprintf (stderr, _("%s: getwd: %s, %s\n"),
progname, filename, localdir);
xexit (1);
}
strcat (localdir, "/");
strcat (localdir, filename);
result = xstrdup (localdir);
free (localdir);
}
else
{ /* Does anybody know why WIN32 doesn't want to support $HOME?
If the reason is they don't have getpwnam, they should
only disable the else clause below. */
#ifndef WIN32
if (IS_SLASH (filename[1]))
{
/* Return the concatenation of the environment variable HOME
and the rest of the string. */
char *temp_home;
temp_home = (char *) getenv ("HOME");
result = xmalloc (strlen (&filename[1])
+ 1
+ temp_home ? strlen (temp_home)
: 0);
*result = 0;
if (temp_home)
strcpy (result, temp_home);
strcat (result, &filename[1]);
}
else
{
struct passwd *user_entry;
int i, c;
char *username = xmalloc (257);
for (i = 1; (c = filename[i]); i++)
{
if (IS_SLASH (c))
break;
else
username[i - 1] = c;
}
if (c)
username[i - 1] = 0;
user_entry = getpwnam (username);
if (!user_entry)
return xstrdup (filename);
result = xmalloc (1 + strlen (user_entry->pw_dir)
+ strlen (&filename[i]));
strcpy (result, user_entry->pw_dir);
strcat (result, &filename[i]);
}
#endif /* not WIN32 */
}
return result;
}
char *
output_name_from_input_name (name)
char *name;
{
return expand_filename (NULL, name);
}

View File

@ -0,0 +1,45 @@
/* files.h -- declarations for files.c.
$Id: files.h,v 1.1 1998/10/24 21:37:25 karl Exp $
Copyright (C) 1998 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.
*/
#ifndef FILES_H
#define FILES_H
/* A stack of file information records. If a new file is read in with
"@input", we remember the old input file state on this stack. */
typedef struct fstack
{
struct fstack *next;
char *filename;
char *text;
int size;
int offset;
int line_number;
} FSTACK;
extern FSTACK *filestack;
extern void pushfile (), popfile ();
extern void flush_file_stack ();
extern char *find_and_load ();
extern char *output_name_from_input_name ();
extern char *expand_filename ();
extern char *filename_part ();
extern char *pathname_part ();
#endif /* !FILES_H */

View File

@ -0,0 +1,359 @@
/* footnote.c -- footnotes for Texinfo.
$Id: footnote.c,v 1.10 1999/09/20 12:20:52 karl Exp $
Copyright (C) 1998, 99 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 "system.h"
#include "footnote.h"
#include "macro.h"
#include "makeinfo.h"
/* Nonzero means that the footnote style for this document was set on
the command line, which overrides any other settings. */
int footnote_style_preset = 0;
/* The current footnote number in this node. Each time a new node is
started this is reset to 1. */
int current_footnote_number = 1;
/* Nonzero means we automatically number footnotes with no specified marker. */
int number_footnotes = 1;
/* Nonzero means we are currently outputting footnotes. */
int already_outputting_pending_notes = 0;
/* Footnotes can be handled in one of two ways:
separate_node:
Make them look like followed references, with the reference
destinations in a makeinfo manufactured node or,
end_node:
Make them appear at the bottom of the node that they originally
appeared in. */
#define separate_node 0
#define end_node 1
int footnote_style = end_node;
int first_footnote_this_node = 1;
int footnote_count = 0;
/* Set the footnote style based on the style identifier in STRING. */
int
set_footnote_style (string)
char *string;
{
if (strcasecmp (string, "separate") == 0)
footnote_style = separate_node;
else if (strcasecmp (string, "end") == 0)
footnote_style = end_node;
else
return -1;
return 0;
}
void
cm_footnotestyle ()
{
char *arg;
get_rest_of_line (1, &arg);
/* If set on command line, do not change the footnote style. */
if (!footnote_style_preset && set_footnote_style (arg) != 0)
line_error (_("Bad argument to %c%s"), COMMAND_PREFIX, command);
free (arg);
}
typedef struct fn
{
struct fn *next;
char *marker;
char *note;
int number;
} FN;
FN *pending_notes = NULL;
/* A method for remembering footnotes. Note that this list gets output
at the end of the current node. */
void
remember_note (marker, note)
char *marker, *note;
{
FN *temp = xmalloc (sizeof (FN));
temp->marker = xstrdup (marker);
temp->note = xstrdup (note);
temp->next = pending_notes;
temp->number = current_footnote_number;
pending_notes = temp;
footnote_count++;
}
/* How to get rid of existing footnotes. */
static void
free_pending_notes ()
{
FN *temp;
while ((temp = pending_notes))
{
free (temp->marker);
free (temp->note);
pending_notes = pending_notes->next;
free (temp);
}
first_footnote_this_node = 1;
footnote_count = 0;
current_footnote_number = 1; /* for html */
}
/* What to do when you see a @footnote construct. */
/* Handle a "footnote".
footnote *{this is a footnote}
where "*" is the (optional) marker character for this note. */
void
cm_footnote ()
{
char *marker;
char *note;
get_until ("{", &marker);
canon_white (marker);
if (macro_expansion_output_stream && !executing_string)
append_to_expansion_output (input_text_offset + 1); /* include the { */
/* Read the argument in braces. */
if (curchar () != '{')
{
line_error (_("`%c%s' needs an argument `{...}', not just `%s'"),
COMMAND_PREFIX, command, marker);
free (marker);
return;
}
else
{
int len;
int braces = 1;
int loc = ++input_text_offset;
while (braces)
{
if (loc == input_text_length)
{
line_error (_("No closing brace for footnote `%s'"), marker);
return;
}
if (input_text[loc] == '{')
braces++;
else if (input_text[loc] == '}')
braces--;
else if (input_text[loc] == '\n')
line_number++;
loc++;
}
len = (loc - input_text_offset) - 1;
note = xmalloc (len + 1);
memcpy (note, &input_text[input_text_offset], len);
note[len] = 0;
input_text_offset = loc;
}
/* Must write the macro-expanded argument to the macro expansion
output stream. This is like the case in index_add_arg. */
if (macro_expansion_output_stream && !executing_string)
{
/* Calling me_execute_string on a lone } provokes an error, since
as far as the reader knows there is no matching {. We wrote
the { above in the call to append_to_expansion_output. */
me_execute_string_keep_state (note, "}");
}
if (!current_node || !*current_node)
{
line_error (_("Footnote defined without parent node"));
free (marker);
free (note);
return;
}
if (!*marker)
{
free (marker);
if (number_footnotes)
{
marker = xmalloc (10);
sprintf (marker, "%d", current_footnote_number);
}
else
marker = xstrdup ("*");
}
remember_note (marker, note);
/* fixme: html: footnote processing needs work; we currently ignore
the style requested; we could clash with a node name of the form
`fn-<n>', though that's unlikely. */
if (html)
add_word_args ("<a rel=footnote href=\"#fn-%d\"><sup>%s</sup></a>",
current_footnote_number, marker);
else
/* Your method should at least insert MARKER. */
switch (footnote_style)
{
case separate_node:
add_word_args ("(%s)", marker);
execute_string (" (*note %s-Footnote-%d::)",
current_node, current_footnote_number);
if (first_footnote_this_node)
{
char *temp_string, *expanded_ref;
temp_string = xmalloc (strlen (current_node)
+ strlen ("-Footnotes") + 1);
strcpy (temp_string, current_node);
strcat (temp_string, "-Footnotes");
expanded_ref = expansion (temp_string, 0);
remember_node_reference (expanded_ref, line_number,
followed_reference);
free (temp_string);
free (expanded_ref);
first_footnote_this_node = 0;
}
break;
case end_node:
add_word_args ("(%s)", marker);
break;
default:
break;
}
current_footnote_number++;
free (marker);
free (note);
}
/* Output the footnotes. We are at the end of the current node. */
void
output_pending_notes ()
{
FN *footnote = pending_notes;
if (!pending_notes)
return;
if (html)
{ /* The type= attribute is used just in case some weirdo browser
out there doesn't use numbers by default. Since we rely on the
browser to produce the footnote numbers, we need to make sure
they ARE indeed numbers. Pre-HTML4 browsers seem to not care. */
add_word ("<hr><h4>");
add_word (_("Footnotes"));
add_word ("</h4>\n<ol type=\"1\">\n");
}
else
switch (footnote_style)
{
case separate_node:
{
char *old_current_node = current_node;
char *old_command = xstrdup (command);
already_outputting_pending_notes++;
execute_string ("%cnode %s-Footnotes,,,%s\n",
COMMAND_PREFIX, current_node, current_node);
already_outputting_pending_notes--;
current_node = old_current_node;
free (command);
command = old_command;
}
break;
case end_node:
close_paragraph ();
in_fixed_width_font++;
/* This string should be translated according to the
@documentlanguage, not the current LANG. We can't do that
yet, so leave it in English. */
execute_string ("---------- Footnotes ----------\n\n");
in_fixed_width_font--;
break;
}
/* Handle the footnotes in reverse order. */
{
FN **array = xmalloc ((footnote_count + 1) * sizeof (FN *));
array[footnote_count] = NULL;
while (--footnote_count > -1)
{
array[footnote_count] = footnote;
footnote = footnote->next;
}
filling_enabled = 1;
indented_fill = 1;
while ((footnote = array[++footnote_count]))
{
if (html)
{
/* Make the text of every footnote begin a separate paragraph. */
add_word_args ("<li><a name=\"fn-%d\"></a>\n<p>",
footnote->number);
execute_string ("%s", footnote->note);
add_word ("</p>\n");
}
else
{
char *old_current_node = current_node;
char *old_command = xstrdup (command);
already_outputting_pending_notes++;
execute_string ("%canchor{%s-Footnote-%d}(%s) %s",
COMMAND_PREFIX, current_node, footnote->number,
footnote->marker, footnote->note);
already_outputting_pending_notes--;
current_node = old_current_node;
free (command);
command = old_command;
}
close_paragraph ();
}
if (html)
add_word ("</ol><hr>");
close_paragraph ();
free (array);
}
free_pending_notes ();
}

View File

@ -0,0 +1,37 @@
/* footnote.h -- declarations for footnote.c.
$Id: footnote.h,v 1.2 1998/10/26 22:16:15 karl Exp $
Copyright (C) 1998 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.
*/
#ifndef FOOTNOTE_H
#define FOOTNOTE_H
extern int footnote_style_preset;
extern int current_footnote_number;
extern int number_footnotes;
extern int already_outputting_pending_notes;
/* The Texinfo @commands. */
extern void cm_footnote ();
extern void cm_footnotestyle ();
extern int set_footnote_style (); /* called for -s option */
extern void output_pending_notes (); /* called for output */
#endif /* !FOOTNOTE_H */

View File

@ -0,0 +1,182 @@
/* html.c -- html-related utilities.
$Id: html.c,v 1.5 1999/09/18 19:27:41 karl Exp $
Copyright (C) 1999 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 "system.h"
#include "cmds.h"
#include "html.h"
#include "lang.h"
#include "makeinfo.h"
#include "sectioning.h"
/* See html.h. */
int html_output_head_p = 0;
void
html_output_head ()
{
char *html_title;
if (html_output_head_p)
return;
html_output_head_p = 1;
/* The <title> should not have markup. */
html_title = title ? text_expansion (title) : _("Untitled");
add_word_args ("<html lang=\"%s\"><head>\n<title>%s</title>\n",
language_table[language_code].abbrev, html_title);
add_word ("<meta http-equiv=\"Content-Type\" content=\"text/html");
if (document_encoding)
add_word_args ("; charset=%s", document_encoding);
add_word ("\">\n");
add_word_args ("<meta name=description content=\"%s\">\n", html_title);
add_word_args ("<meta name=generator content=\"makeinfo %s\">\n", VERSION);
add_word ("<link href=\"http://texinfo.org/\" rel=generator-home>\n");
add_word ("</head><body>\n\n");
}
/* Escape HTML special characters in the string if necessary,
returning a pointer to a possibly newly-allocated one. */
char *
escape_string (string)
char * string;
{
int i=0, newlen=0;
char * newstring;
do
{
/* Find how much to allocate. */
switch (string[i])
{
case '&':
newlen += 5; /* `&amp;' */
break;
case '<':
case '>':
newlen += 4; /* `&lt;', `&gt;' */
break;
default:
newlen++;
}
i++;
}
while (string[i]);
if (newlen == i) return string; /* Already OK. */
newstring = xmalloc (newlen + 2);
i = 0;
do
{
switch (string[i])
{
case '&':
strcpy (newstring, "&amp;");
newstring += 5;
break;
case '<':
strcpy (newstring, "&lt;");
newstring += 4;
break;
case '>':
strcpy (newstring, "&gt;");
newstring += 4;
break;
default:
newstring[0] = string[i];
newstring++;
}
}
while (string[i++]);
free (string);
return newstring - newlen -1;
}
/* Open or close TAG according to START_OR_END. */
void
insert_html_tag (start_or_end, tag)
int start_or_end;
char *tag;
{
if (!paragraph_is_open && (start_or_end == START))
{
/* Need to compensate for the <p> we are about to insert, or
else cm_xxx functions that call us will get wrong text
between START and END. */
adjust_braces_following (output_paragraph_offset, 3);
add_word ("<p>");
}
add_char ('<');
if (start_or_end != START)
add_char ('/');
add_word (tag);
add_char ('>');
}
/* Output an HTML <link> to the filename for NODE, including the
other string as extra attributes. */
void
add_link (node, attributes)
char *node, *attributes;
{
if (node)
{
add_word_args ("<link %s href=\"", attributes);
add_anchor_name (node, 1);
add_word ("\">\n");
}
}
/* Output NAME with characters escaped as appropriate for an anchor
name, i.e., escape URL special characters as %<n>. */
void
add_escaped_anchor_name (name)
char *name;
{
for (; *name; name++)
{
if (*name == '&')
add_word ("&amp;");
else if (! URL_SAFE_CHAR (*name))
/* Cast so characters with the high bit set are treated as >128,
for example o-umlaut should be 246, not -10. */
add_word_args ("%%%x", (unsigned char) *name);
else
add_char (*name);
}
}
/* Insert the text for the name of a reference in an HTML anchor
appropriate for NODENAME. If HREF is nonzero, it will be
appropriate for a href= attribute, rather than name= i.e., including
the `#' if it's an internal reference. */
void
add_anchor_name (nodename, href)
char *nodename;
int href;
{
if (href)
add_char ('#');
add_escaped_anchor_name (nodename);
}

View File

@ -0,0 +1,44 @@
/* html.h -- declarations for html-related utilities.
$Id: html.h,v 1.1 1999/04/25 20:53:33 karl Exp $
Copyright (C) 1999 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. */
#ifndef HTML_H
#define HTML_H
/* Nonzero if we have output the <head>. */
extern int html_output_head_p;
/* Perform the <head> output. */
extern void html_output_head ();
/* Escape &<>. */
extern char *escape_string (/* char * */);
/* Open or close TAG according to START_OR_END. */
extern void insert_html_tag (/* int start_or_end, char *tag */);
/* Output HTML <link> to NODE, plus extra ATTRIBUTES. */
extern void add_link (/* char *node, char *attributes */);
/* Escape URL-special characters as %xy. */
extern void add_escaped_anchor_name (/* char *name */);
/* See html.c. */
extern void add_anchor_name (/* nodename, href */);
#endif /* !HTML_H */

View File

@ -0,0 +1,823 @@
/* index.c -- indexing for Texinfo.
$Id: index.c,v 1.21 1999/07/18 18:50:02 karl Exp $
Copyright (C) 1998, 99 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 "system.h"
#include "index.h"
#include "lang.h"
#include "macro.h"
#include "toc.h"
/* An index element... */
typedef struct index_elt
{
struct index_elt *next;
char *entry; /* The index entry itself, after expansion. */
char *entry_text; /* The original, non-expanded entry text. */
char *node; /* The node from whence it came. */
int code; /* Nonzero means add `@code{...}' when
printing this element. */
int defining_line; /* Line number where this entry was written. */
char *defining_file; /* Source file for defining_line. */
} INDEX_ELT;
/* A list of short-names for each index.
There are two indices into the the_indices array.
* read_index is the index that points to the list of index
entries that we will find if we ask for the list of entries for
this name.
* write_index is the index that points to the list of index entries
that we will add new entries to.
Initially, read_index and write_index are the same, but the
@syncodeindex and @synindex commands can change the list we add
entries to.
For example, after the commands
@cindex foo
@defindex ii
@synindex cp ii
@cindex bar
the cp index will contain the entry `foo', and the new ii
index will contain the entry `bar'. This is consistent with the
way texinfo.tex handles the same situation.
In addition, for each index, it is remembered whether that index is
a code index or not. Code indices have @code{} inserted around the
first word when they are printed with printindex. */
typedef struct
{
char *name;
int read_index; /* index entries for `name' */
int write_index; /* store index entries here, @synindex can change it */
int code;
} INDEX_ALIST;
INDEX_ALIST **name_index_alist = NULL;
/* An array of pointers. Each one is for a different index. The
"synindex" command changes which array slot is pointed to by a
given "index". */
INDEX_ELT **the_indices = NULL;
/* The number of defined indices. */
int defined_indices = 0;
/* Stuff for defining commands on the fly. */
COMMAND **user_command_array = NULL;
int user_command_array_len = 0;
/* How to compare index entries for sorting. May be set to strcoll. */
int (*index_compare_fn) () = strcasecmp;
/* Find which element in the known list of indices has this name.
Returns -1 if NAME isn't found. */
static int
find_index_offset (name)
char *name;
{
int i;
for (i = 0; i < defined_indices; i++)
if (name_index_alist[i] && STREQ (name, name_index_alist[i]->name))
return i;
return -1;
}
/* Return a pointer to the entry of (name . index) for this name.
Return NULL if the index doesn't exist. */
INDEX_ALIST *
find_index (name)
char *name;
{
int offset = find_index_offset (name);
if (offset > -1)
return name_index_alist[offset];
else
return NULL;
}
/* User-defined commands, which happens only from user-defined indexes.
Used to initialize the builtin indices, too. */
void
define_user_command (name, proc, needs_braces_p)
char *name;
COMMAND_FUNCTION *proc;
int needs_braces_p;
{
int slot = user_command_array_len;
user_command_array_len++;
if (!user_command_array)
user_command_array = xmalloc (1 * sizeof (COMMAND *));
user_command_array = xrealloc (user_command_array,
(1 + user_command_array_len) * sizeof (COMMAND *));
user_command_array[slot] = xmalloc (sizeof (COMMAND));
user_command_array[slot]->name = xstrdup (name);
user_command_array[slot]->proc = proc;
user_command_array[slot]->argument_in_braces = needs_braces_p;
}
/* Please release me, let me go... */
static void
free_index (index)
INDEX_ELT *index;
{
INDEX_ELT *temp;
while ((temp = index))
{
free (temp->entry);
free (temp->entry_text);
/* Do not free the node, because we already freed the tag table,
which freed all the node names. */
/* free (temp->node); */
index = index->next;
free (temp);
}
}
/* Flush an index by name. This will delete the list of entries that
would be written by a @printindex command for this index. */
static void
undefindex (name)
char *name;
{
int i;
int which = find_index_offset (name);
/* The index might have already been freed if this was the target of
an @synindex. */
if (which < 0 || !name_index_alist[which])
return;
i = name_index_alist[which]->read_index;
free_index (the_indices[i]);
the_indices[i] = NULL;
free (name_index_alist[which]->name);
free (name_index_alist[which]);
name_index_alist[which] = NULL;
}
/* Add the arguments to the current index command to the index NAME.
html fixxme generate specific html anchor */
static void
index_add_arg (name)
char *name;
{
int which;
char *index_entry;
INDEX_ALIST *tem;
tem = find_index (name);
which = tem ? tem->write_index : -1;
if (macro_expansion_output_stream && !executing_string)
append_to_expansion_output (input_text_offset + 1);
get_rest_of_line (0, &index_entry);
ignore_blank_line ();
if (macro_expansion_output_stream && !executing_string)
{
char *index_line = xmalloc (strlen (index_entry) + 2);
sprintf (index_line, "%s\n", index_entry);
me_execute_string_keep_state (index_line, NULL);
free (index_line);
}
if (which < 0)
{
line_error (_("Unknown index `%s'"), name);
free (index_entry);
}
else
{
INDEX_ELT *new = xmalloc (sizeof (INDEX_ELT));
new->next = the_indices[which];
new->entry_text = index_entry;
new->entry = NULL;
new->node = current_node ? current_node : xstrdup ("");
new->code = tem->code;
new->defining_line = line_number - 1;
/* We need to make a copy since input_filename may point to
something that goes away, for example, inside a macro.
(see the findexerr test). */
new->defining_file = xstrdup (input_filename);
the_indices[which] = new;
}
}
/* The function which user defined index commands call. */
static void
gen_index ()
{
char *name = xstrdup (command);
if (strlen (name) >= strlen ("index"))
name[strlen (name) - strlen ("index")] = 0;
index_add_arg (name);
free (name);
}
/* Define an index known as NAME. We assign the slot number.
If CODE is nonzero, make this a code index. */
static void
defindex (name, code)
char *name;
int code;
{
int i, slot;
/* If it already exists, flush it. */
undefindex (name);
/* Try to find an empty slot. */
slot = -1;
for (i = 0; i < defined_indices; i++)
if (!name_index_alist[i])
{
slot = i;
break;
}
if (slot < 0)
{ /* No such luck. Make space for another index. */
slot = defined_indices;
defined_indices++;
name_index_alist = (INDEX_ALIST **)
xrealloc (name_index_alist, (1 + defined_indices)
* sizeof (INDEX_ALIST *));
the_indices = (INDEX_ELT **)
xrealloc (the_indices, (1 + defined_indices) * sizeof (INDEX_ELT *));
}
/* We have a slot. Start assigning. */
name_index_alist[slot] = xmalloc (sizeof (INDEX_ALIST));
name_index_alist[slot]->name = xstrdup (name);
name_index_alist[slot]->read_index = slot;
name_index_alist[slot]->write_index = slot;
name_index_alist[slot]->code = code;
the_indices[slot] = NULL;
}
/* Define an index NAME, implicitly @code if CODE is nonzero. */
static void
top_defindex (name, code)
char *name;
int code;
{
char *temp;
temp = xmalloc (1 + strlen (name) + strlen ("index"));
sprintf (temp, "%sindex", name);
define_user_command (temp, gen_index, 0);
defindex (name, code);
free (temp);
}
/* Set up predefined indices. */
void
init_indices ()
{
int i;
/* Create the default data structures. */
/* Initialize data space. */
if (!the_indices)
{
the_indices = xmalloc ((1 + defined_indices) * sizeof (INDEX_ELT *));
the_indices[defined_indices] = NULL;
name_index_alist = xmalloc ((1 + defined_indices)
* sizeof (INDEX_ALIST *));
name_index_alist[defined_indices] = NULL;
}
/* If there were existing indices, get rid of them now. */
for (i = 0; i < defined_indices; i++)
{
undefindex (name_index_alist[i]->name);
if (name_index_alist[i])
{ /* Suppose we're called with two input files, and the first
does a @synindex pg cp. Then, when we get here to start
the second file, the "pg" element won't get freed by
undefindex (because it's pointing to "cp"). So free it
here; otherwise, when we try to define the pg index again
just below, it will still point to cp. */
free (name_index_alist[i]->name);
free (name_index_alist[i]);
name_index_alist[i] = NULL;
}
}
/* Add the default indices. */
top_defindex ("cp", 0); /* cp is the only non-code index. */
top_defindex ("fn", 1);
top_defindex ("ky", 1);
top_defindex ("pg", 1);
top_defindex ("tp", 1);
top_defindex ("vr", 1);
}
/* Given an index name, return the offset in the_indices of this index,
or -1 if there is no such index. */
int
translate_index (name)
char *name;
{
INDEX_ALIST *which = find_index (name);
if (which)
return which->read_index;
else
return -1;
}
/* Return the index list which belongs to NAME. */
INDEX_ELT *
index_list (name)
char *name;
{
int which = translate_index (name);
if (which < 0)
return (INDEX_ELT *) -1;
else
return the_indices[which];
}
/* Define a new index command. Arg is name of index. */
static void
gen_defindex (code)
int code;
{
char *name;
get_rest_of_line (0, &name);
if (find_index (name))
{
line_error (_("Index `%s' already exists"), name);
}
else
{
char *temp = xmalloc (strlen (name) + sizeof ("index"));
sprintf (temp, "%sindex", name);
define_user_command (temp, gen_index, 0);
defindex (name, code);
free (temp);
}
free (name);
}
void
cm_defindex ()
{
gen_defindex (0);
}
void
cm_defcodeindex ()
{
gen_defindex (1);
}
/* Expects 2 args, on the same line. Both are index abbreviations.
Make the first one be a synonym for the second one, i.e. make the
first one have the same index as the second one. */
void
cm_synindex ()
{
int source, target;
char *abbrev1, *abbrev2;
skip_whitespace ();
get_until_in_line (0, " ", &abbrev1);
target = find_index_offset (abbrev1);
skip_whitespace ();
get_until_in_line (0, " ", &abbrev2);
source = find_index_offset (abbrev2);
if (source < 0 || target < 0)
{
line_error (_("Unknown index `%s' and/or `%s' in @synindex"),
abbrev1, abbrev2);
}
else
{
name_index_alist[target]->write_index
= name_index_alist[source]->write_index;
}
free (abbrev1);
free (abbrev2);
}
void
cm_pindex () /* Pinhead index. */
{
index_add_arg ("pg");
}
void
cm_vindex () /* Variable index. */
{
index_add_arg ("vr");
}
void
cm_kindex () /* Key index. */
{
index_add_arg ("ky");
}
void
cm_cindex () /* Concept index. */
{
index_add_arg ("cp");
}
void
cm_findex () /* Function index. */
{
index_add_arg ("fn");
}
void
cm_tindex () /* Data Type index. */
{
index_add_arg ("tp");
}
int
index_element_compare (element1, element2)
INDEX_ELT **element1, **element2;
{
return index_compare_fn ((*element1)->entry, (*element2)->entry);
}
/* Force all index entries to be unique. */
void
make_index_entries_unique (array, count)
INDEX_ELT **array;
int count;
{
int i, j;
INDEX_ELT **copy;
int counter = 1;
copy = xmalloc ((1 + count) * sizeof (INDEX_ELT *));
for (i = 0, j = 0; i < count; i++)
{
if (i == (count - 1)
|| array[i]->node != array[i + 1]->node
|| !STREQ (array[i]->entry, array[i + 1]->entry))
copy[j++] = array[i];
else
{
free (array[i]->entry);
free (array[i]->entry_text);
free (array[i]);
}
}
copy[j] = NULL;
/* Now COPY contains only unique entries. Duplicated entries in the
original array have been freed. Replace the current array with
the copy, fixing the NEXT pointers. */
for (i = 0; copy[i]; i++)
{
copy[i]->next = copy[i + 1];
/* Fix entry names which are the same. They point to different nodes,
so we make the entry name unique. */
if (copy[i+1]
&& STREQ (copy[i]->entry, copy[i + 1]->entry)
&& !html)
{
char *new_entry_name;
new_entry_name = xmalloc (10 + strlen (copy[i]->entry));
sprintf (new_entry_name, "%s <%d>", copy[i]->entry, counter);
free (copy[i]->entry);
copy[i]->entry = new_entry_name;
counter++;
}
else
counter = 1;
array[i] = copy[i];
}
array[i] = NULL;
/* Free the storage used only by COPY. */
free (copy);
}
/* Sort the index passed in INDEX, returning an array of
pointers to elements. The array is terminated with a NULL
pointer. We call qsort because it's supposed to be fast.
I think this looks bad. */
INDEX_ELT **
sort_index (index)
INDEX_ELT *index;
{
INDEX_ELT **array;
INDEX_ELT *temp = index;
int count = 0;
int save_line_number = line_number;
char *save_input_filename = input_filename;
int save_html = html;
/* Pretend we are in non-HTML mode, for the purpose of getting the
expanded index entry that lacks any markup and other HTML escape
characters which could produce a wrong sort order. */
/* fixme: html: this still causes some markup, such as non-ASCII
characters @AE{} etc., to sort incorrectly. */
html = 0;
while (temp)
{
count++;
temp = temp->next;
}
/* We have the length. Make an array. */
array = xmalloc ((count + 1) * sizeof (INDEX_ELT *));
count = 0;
temp = index;
while (temp)
{
array[count++] = temp;
/* Set line number and input filename to the source line for this
index entry, as this expansion finds any errors. */
line_number = array[count - 1]->defining_line;
input_filename = array[count - 1]->defining_file;
/* If this particular entry should be printed as a "code" index,
then expand it as @code{entry}, i.e. as in fixed-width font. */
array[count-1]->entry = expansion (temp->entry_text,
array[count-1]->code);
temp = temp->next;
}
array[count] = NULL; /* terminate the array. */
line_number = save_line_number;
input_filename = save_input_filename;
html = save_html;
#ifdef HAVE_STRCOLL
/* This is not perfect. We should set (then restore) the locale to the
documentlanguage, so strcoll operates according to the document's
locale, not the user's. For now, I'm just going to assume that
those few new documents which use @documentlanguage will be
processed in the appropriate locale. In any case, don't use
strcoll in the C (aka POSIX) locale, that is the ASCII ordering. */
if (language_code != en)
{
char *lang_env = getenv ("LANG");
if (lang_env && !STREQ (lang_env, "C") && !STREQ (lang_env, "POSIX"))
index_compare_fn = strcoll;
}
#endif /* HAVE_STRCOLL */
/* Sort the array. */
qsort (array, count, sizeof (INDEX_ELT *), index_element_compare);
make_index_entries_unique (array, count);
return array;
}
/* Nonzero means that we are in the middle of printing an index. */
int printing_index = 0;
/* Takes one arg, a short name of an index to print.
Outputs a menu of the sorted elements of the index. */
void
cm_printindex ()
{
int item;
INDEX_ELT *index;
INDEX_ELT *last_index = 0;
INDEX_ELT **array;
char *index_name;
unsigned line_length;
char *line;
int saved_inhibit_paragraph_indentation = inhibit_paragraph_indentation;
int saved_filling_enabled = filling_enabled;
int saved_line_number = line_number;
char *saved_input_filename = input_filename;
close_paragraph ();
get_rest_of_line (0, &index_name);
index = index_list (index_name);
if (index == (INDEX_ELT *)-1)
{
line_error (_("Unknown index `%s' in @printindex"), index_name);
free (index_name);
return;
}
/* Do this before sorting, so execute_string in index_element_compare
will give the same results as when we actually print. */
printing_index = 1;
filling_enabled = 0;
inhibit_paragraph_indentation = 1;
array = sort_index (index);
close_paragraph ();
if (html)
add_word ("<ul compact>");
else if (!no_headers)
add_word ("* Menu:\n\n");
me_inhibit_expansion++;
/* This will probably be enough. */
line_length = 100;
line = xmalloc (line_length);
for (item = 0; (index = array[item]); item++)
{
/* A pathological document might have an index entry outside of any
node. Don't crash; try using the section name instead. */
char *index_node = index->node;
line_number = index->defining_line;
input_filename = index->defining_file;
if ((!index_node || !*index_node) && html)
index_node = toc_find_section_of_node (index_node);
if (!index_node || !*index_node)
{
line_error (_("Entry for index `%s' outside of any node"),
index_name);
if (html || !no_headers)
index_node = _("(outside of any node)");
}
if (html)
/* fixme: html: we should use specific index anchors pointing
to the actual location of the indexed position (but then we
have to find something to wrap the anchor around). */
{
if (last_index
&& STREQ (last_index->entry_text, index->entry_text))
add_word (", "); /* Don't repeat the previous entry. */
else
{
/* In the HTML case, the expanded index entry is not
good for us, since it was expanded for non-HTML mode
inside sort_index. So we need to HTML-escape and
expand the original entry text here. */
char *escaped_entry = xstrdup (index->entry_text);
char *expanded_entry;
/* expansion() doesn't HTML-escape the argument, so need
to do it separately. */
escaped_entry = escape_string (escaped_entry);
expanded_entry = expansion (escaped_entry, index->code);
add_word_args ("\n<li>%s: ", expanded_entry);
free (escaped_entry);
free (expanded_entry);
}
add_word ("<a href=\"");
if (index->node && *index->node)
{
/* Make sure any non-macros in the node name are expanded. */
in_fixed_width_font++;
index_node = expansion (index_node, 0);
in_fixed_width_font--;
add_anchor_name (index_node, 1);
add_word_args ("\">%s</a>", index_node);
free (index_node);
}
else if (STREQ (index_node, _("(outside of any node)")))
{
add_anchor_name (index_node, 1);
add_word_args ("\">%s</a>", index_node);
}
else
/* If we use the section instead of the (missing) node, then
index_node already includes all we need except the #. */
add_word_args ("#%s</a>", index_node);
}
else
{
unsigned new_length = strlen (index->entry);
if (new_length < 50) /* minimum length used below */
new_length = 50;
new_length += strlen (index_node) + 7; /* * : .\n\0 */
if (new_length > line_length)
{
line_length = new_length;
line = xrealloc (line, line_length);
}
/* Print the entry, nicely formatted. We've already
expanded any commands in index->entry, including any
implicit @code. Thus, can't call execute_string, since
@@ has turned into @. */
if (!no_headers)
{
sprintf (line, "* %-37s ", index->entry);
line[2 + strlen (index->entry)] = ':';
insert_string (line);
/* Make sure any non-macros in the node name are expanded. */
in_fixed_width_font++;
execute_string ("%s.\n", index_node);
in_fixed_width_font--;
}
else
{
/* With --no-headers, the @node lines are gone, so
there's little sense in referring to them in the
index. Instead, output the number or name of the
section that corresponds to that node. */
char *section_name = toc_find_section_of_node (index_node);
sprintf (line, "%-*s ", number_sections ? 50 : 1, index->entry);
line[strlen (index->entry)] = ':';
insert_string (line);
if (section_name)
{
int idx = 0;
unsigned ref_len = strlen (section_name) + 30;
if (ref_len > line_length)
{
line_length = ref_len;
line = xrealloc (line, line_length);
}
if (number_sections)
{
while (section_name[idx]
&& (isdigit (section_name[idx])
|| (idx && section_name[idx] == '.')))
idx++;
}
if (idx)
sprintf (line, " See %.*s.\n", idx, section_name);
else
sprintf (line, "\n See ``%s''.\n", section_name);
insert_string (line);
}
else
{
insert_string (" "); /* force a blank */
execute_string ("See node %s.\n", index_node);
}
}
}
/* Prevent `output_paragraph' from growing to the size of the
whole index. */
flush_output ();
last_index = index;
}
free (line);
free (index_name);
me_inhibit_expansion--;
printing_index = 0;
free (array);
close_single_paragraph ();
filling_enabled = saved_filling_enabled;
inhibit_paragraph_indentation = saved_inhibit_paragraph_indentation;
input_filename = saved_input_filename;
line_number = saved_line_number;
if (html)
add_word ("</ul>");
}

View File

@ -0,0 +1,36 @@
/* index.h -- declarations for index.c.
$Id: index.h,v 1.4 1999/04/19 18:12:17 karl Exp $
Copyright (C) 1998, 99 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. */
#ifndef INDEX_H
#define INDEX_H
#include "makeinfo.h"
#include "cmds.h"
/* User commands are only new indices. (Macros are handled separately.) */
extern COMMAND **user_command_array;
extern int user_command_array_len;
/* Initialize all indices. */
extern void init_indices ();
/* Function to compare index entries for sorting. */
extern int (*index_compare_fn) ();
#endif /* !INDEX_H */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,61 @@
/* insertion.h -- declarations for insertion.c.
$Id: insertion.h,v 1.6 1999/07/06 23:12:58 karl Exp $
Copyright (C) 1998, 99 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. */
#ifndef INSERTION_H
#define INSERTION_H
/* Must match list in insertion.c. */
enum insertion_type
{
cartouche, defcv, deffn, defivar, defmac, defmethod, defop, defopt,
defspec, deftp, deftypefn, deftypefun, deftypeivar, deftypemethod,
deftypeop, deftypevar, deftypevr, defun, defvar, defvr, detailmenu,
direntry, display, enumerate, example, flushleft, flushright, format,
ftable, group, ifclear, ifhtml, ifinfo, ifnothtml, ifnotinfo,
ifnottex, ifset, iftex, itemize, lisp, menu, multitable, quotation,
rawhtml, rawtex, smalldisplay, smallexample, smallformat, smalllisp,
table, tex, vtable, bad_type
};
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;
extern int insertion_level;
extern INSERTION_ELT *insertion_stack;
extern int in_menu;
extern int in_detailmenu;
extern int had_menu_commentary;
extern int in_paragraph;
extern void command_name_condition ();
extern void cm_ifnothtml (), cm_ifhtml(), cm_html ();
extern void cm_ifinfo (), cm_ifnotinfo ();
extern void cm_ifnottex (), cm_iftex (), cm_tex ();
#endif /* !INSERTION_H */

View File

@ -0,0 +1,415 @@
/* lang.c -- language depend behaviour (startpoint)
$Id: lang.c,v 1.11 1999/07/13 21:16:29 karl Exp $
Copyright (C) 1999 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 Karl Heinz Marbaise <kama@hippo.fido.de>. */
#include "system.h"
#include "cmds.h"
#include "lang.h"
#include "makeinfo.h"
/* Current document encoding. */
char *document_encoding = NULL;
/* Current language code; default is English. */
language_code_type language_code = en;
language_struct language_table[] = {
{ aa, "aa", "Afar" },
{ ab, "ab", "Abkhazian" },
{ af, "af", "Afrikaans" },
{ am, "am", "Amharic" },
{ ar, "ar", "Arabic" },
{ as, "as", "Assamese" },
{ ay, "ay", "Aymara" },
{ az, "az", "Azerbaijani" },
{ ba, "ba", "Bashkir" },
{ be, "be", "Byelorussian" },
{ bg, "bg", "Bulgarian" },
{ bh, "bh", "Bihari" },
{ bi, "bi", "Bislama" },
{ bn, "bn", "Bengali; Bangla" },
{ bo, "bo", "Tibetan" },
{ br, "br", "Breton" },
{ ca, "ca", "Catalan" },
{ co, "co", "Corsican" },
{ cs, "cs", "Czech" },
{ cy, "cy", "Welsh" },
{ da, "da", "Danish" },
{ de, "de", "German" },
{ dz, "dz", "Bhutani" },
{ el, "el", "Greek" },
{ en, "en", "English" },
{ eo, "eo", "Esperanto" },
{ es, "es", "Spanish" },
{ et, "et", "Estonian" },
{ eu, "eu", "Basque" },
{ fa, "fa", "Persian" },
{ fi, "fi", "Finnish" },
{ fj, "fj", "Fiji" },
{ fo, "fo", "Faroese" },
{ fr, "fr", "French" },
{ fy, "fy", "Frisian" },
{ ga, "ga", "Irish" },
{ gd, "gd", "Scots Gaelic" },
{ gl, "gl", "Galician" },
{ gn, "gn", "Guarani" },
{ gu, "gu", "Gujarati" },
{ ha, "ha", "Hausa" },
{ he, "he", "Hebrew" } /* (formerly iw) */,
{ hi, "hi", "Hindi" },
{ hr, "hr", "Croatian" },
{ hu, "hu", "Hungarian" },
{ hy, "hy", "Armenian" },
{ ia, "ia", "Interlingua" },
{ id, "id", "Indonesian" } /* (formerly in) */,
{ ie, "ie", "Interlingue" },
{ ik, "ik", "Inupiak" },
{ is, "is", "Icelandic" },
{ it, "it", "Italian" },
{ iu, "iu", "Inuktitut" },
{ ja, "ja", "Japanese" },
{ jw, "jw", "Javanese" },
{ ka, "ka", "Georgian" },
{ kk, "kk", "Kazakh" },
{ kl, "kl", "Greenlandic" },
{ km, "km", "Cambodian" },
{ kn, "kn", "Kannada" },
{ ko, "ko", "Korean" },
{ ks, "ks", "Kashmiri" },
{ ku, "ku", "Kurdish" },
{ ky, "ky", "Kirghiz" },
{ la, "la", "Latin" },
{ ln, "ln", "Lingala" },
{ lo, "lo", "Laothian" },
{ lt, "lt", "Lithuanian" },
{ lv, "lv", "Latvian, Lettish" },
{ mg, "mg", "Malagasy" },
{ mi, "mi", "Maori" },
{ mk, "mk", "Macedonian" },
{ ml, "ml", "Malayalam" },
{ mn, "mn", "Mongolian" },
{ mo, "mo", "Moldavian" },
{ mr, "mr", "Marathi" },
{ ms, "ms", "Malay" },
{ mt, "mt", "Maltese" },
{ my, "my", "Burmese" },
{ na, "na", "Nauru" },
{ ne, "ne", "Nepali" },
{ nl, "nl", "Dutch" },
{ no, "no", "Norwegian" },
{ oc, "oc", "Occitan" },
{ om, "om", "(Afan) Oromo" },
{ or, "or", "Oriya" },
{ pa, "pa", "Punjabi" },
{ pl, "pl", "Polish" },
{ ps, "ps", "Pashto, Pushto" },
{ pt, "pt", "Portuguese" },
{ qu, "qu", "Quechua" },
{ rm, "rm", "Rhaeto-Romance" },
{ rn, "rn", "Kirundi" },
{ ro, "ro", "Romanian" },
{ ru, "ru", "Russian" },
{ rw, "rw", "Kinyarwanda" },
{ sa, "sa", "Sanskrit" },
{ sd, "sd", "Sindhi" },
{ sg, "sg", "Sangro" },
{ sh, "sh", "Serbo-Croatian" },
{ si, "si", "Sinhalese" },
{ sk, "sk", "Slovak" },
{ sl, "sl", "Slovenian" },
{ sm, "sm", "Samoan" },
{ sn, "sn", "Shona" },
{ so, "so", "Somali" },
{ sq, "sq", "Albanian" },
{ sr, "sr", "Serbian" },
{ ss, "ss", "Siswati" },
{ st, "st", "Sesotho" },
{ su, "su", "Sundanese" },
{ sv, "sv", "Swedish" },
{ sw, "sw", "Swahili" },
{ ta, "ta", "Tamil" },
{ te, "te", "Telugu" },
{ tg, "tg", "Tajik" },
{ th, "th", "Thai" },
{ ti, "ti", "Tigrinya" },
{ tk, "tk", "Turkmen" },
{ tl, "tl", "Tagalog" },
{ tn, "tn", "Setswana" },
{ to, "to", "Tonga" },
{ tr, "tr", "Turkish" },
{ ts, "ts", "Tsonga" },
{ tt, "tt", "Tatar" },
{ tw, "tw", "Twi" },
{ ug, "ug", "Uighur" },
{ uk, "uk", "Ukrainian" },
{ ur, "ur", "Urdu" },
{ uz, "uz", "Uzbek" },
{ vi, "vi", "Vietnamese" },
{ vo, "vo", "Volapuk" },
{ wo, "wo", "Wolof" },
{ xh, "xh", "Xhosa" },
{ yi, "yi", "Yiddish" } /* (formerly ji) */,
{ yo, "yo", "Yoruba" },
{ za, "za", "Zhuang" },
{ zh, "zh", "Chinese" },
{ zu, "zu", "Zulu" },
{ last_language_code, NULL, NULL }
};
/* @documentlanguage. Maybe we'll do something useful with this in the
future. For now, we just recognize it. */
void
cm_documentlanguage ()
{
language_code_type c;
char *lang_arg;
/* Read the line with the language code on it. */
get_rest_of_line (1, &lang_arg);
/* Linear search is fine these days. */
for (c = aa; c != last_language_code; c++)
{
if (strcmp (lang_arg, language_table[c].abbrev) == 0)
{ /* Set current language code. */
language_code = c;
break;
}
}
/* If we didn't find this code, complain. */
if (c == last_language_code)
warning (_("%s is not a valid ISO 639 language code"), lang_arg);
free (lang_arg);
}
/* @documentencoding. Set global. */
void
cm_documentencoding ()
{
get_rest_of_line (1, &document_encoding);
}
/* Accent commands that take explicit arguments and don't have any
special HTML support. */
void
cm_accent (arg)
int arg;
{
if (arg == START)
{
/* Must come first to avoid ambiguity with overdot. */
if (strcmp (command, "udotaccent") == 0) /* underdot */
add_char ('.');
}
else if (arg == END)
{
if (strcmp (command, "=") == 0) /* macron */
add_word (html ? "&macr;" : "=");
else if (strcmp (command, "H") == 0) /* Hungarian umlaut */
add_word ("''");
else if (strcmp (command, "dotaccent") == 0) /* overdot */
add_meta_char ('.');
else if (strcmp (command, "ringaccent") == 0) /* ring */
add_char ('*');
else if (strcmp (command, "tieaccent") == 0) /* long tie */
add_char ('[');
else if (strcmp (command, "u") == 0) /* breve */
add_char ('(');
else if (strcmp (command, "ubaraccent") == 0) /* underbar */
add_char ('_');
else if (strcmp (command, "v") == 0) /* hacek/check */
add_word (html ? "&lt;" : "<");
}
}
/* Common routine for the accent characters that have support in HTML.
If the character being accented is in the HTML_SUPPORTED set, then
produce &CHTML_SOLO;, for example, &Auml; for an A-umlaut. If not in
HTML_SUPPORTED, just produce &HTML_SOLO;X for the best we can do with
at an X-umlaut. Finally, if not producing HTML, just use SINGLE, a
character such as " which is the best plain text representation we
can manage. If HTML_SOLO_STANDALONE is zero the given HTML_SOLO
does not exist as valid standalone character in HTML. */
static void
cm_accent_generic (arg, start, end, html_supported, single,
html_solo_standalone, html_solo)
int arg, start, end;
char *html_supported;
int single;
int html_solo_standalone;
char *html_solo;
{
if (html)
{
static int valid_html_accent;
if (arg == START)
{ /* If HTML has good support for this character, use it. */
if (strchr (html_supported, curchar ()))
{ /* Yes; start with an ampersand. The character itself
will be added later in read_command (makeinfo.c). */
add_char ('&');
valid_html_accent = 1;
}
else
{ /* No special HTML support, so produce standalone char. */
valid_html_accent = 0;
if (html_solo_standalone)
{
add_char ('&');
add_word (html_solo);
add_char (';');
}
else
/* If the html_solo does not exist as standalone character
(namely &circ; &grave; &tilde;), then we use
the single character version instead. */
add_char (single);
}
}
else if (arg == END)
{ /* Only if we saw a valid_html_accent can we use the full
HTML accent (umlaut, grave ...). */
if (valid_html_accent)
{
add_word (html_solo);
add_char (';');
}
}
}
else if (arg == END)
{ /* Not producing HTML, so just use the normal character. */
add_char (single);
}
}
void
cm_accent_umlaut (arg, start, end)
int arg, start, end;
{
cm_accent_generic (arg, start, end, "aouAOUEeIiy", '"', 1, "uml");
}
void
cm_accent_acute (arg, start, end)
int arg, start, end;
{
cm_accent_generic (arg, start, end, "AEIOUYaeiouy", '\'', 1, "acute");
}
void
cm_accent_cedilla (arg, start, end)
int arg, start, end;
{
cm_accent_generic (arg, start, end, "Cc", ',', 1, "cedil");
}
void
cm_accent_hat (arg, start, end)
int arg, start, end;
{
cm_accent_generic (arg, start, end, "AEIOUaeiou", '^', 0, "circ");
}
void
cm_accent_grave (arg, start, end)
int arg, start, end;
{
cm_accent_generic (arg, start, end, "AEIOUaeiou", '`', 0, "grave");
}
void
cm_accent_tilde (arg, start, end)
int arg, start, end;
{
cm_accent_generic (arg, start, end, "AOano", '~', 0, "tilde");
}
/* Non-English letters/characters that don't insert themselves. */
void
cm_special_char (arg)
{
if (arg == START)
{
if ((*command == 'L' || *command == 'l'
|| *command == 'O' || *command == 'o')
&& command[1] == 0)
{ /* Lslash lslash Oslash oslash.
Lslash and lslash aren't supported in HTML. */
if (html && (command[0] == 'O' || command[0] == 'o'))
add_word_args ("&%cslash;", command[0]);
else
add_word_args ("/%c", command[0]);
}
else if (strcmp (command, "exclamdown") == 0)
add_word (html ? "&iexcl;" : "!");
else if (strcmp (command, "pounds") == 0)
add_word (html ? "&pound;" : "#");
else if (strcmp (command, "questiondown") == 0)
add_word (html ? "&iquest;" : "?");
else if (strcmp (command, "AE") == 0)
add_word (html ? "&AElig;" : command);
else if (strcmp (command, "ae") == 0)
add_word (html ? "&aelig;" : command);
else if (strcmp (command, "OE") == 0)
add_word (html ? "&#140;" : command);
else if (strcmp (command, "oe") == 0)
add_word (html ? "&#156;" : command);
else if (strcmp (command, "AA") == 0)
add_word (html ? "&Aring;" : command);
else if (strcmp (command, "aa") == 0)
add_word (html ? "&aring;" : command);
else if (strcmp (command, "ss") == 0)
add_word (html ? "&szlig;" : command);
else
line_error ("cm_special_char internal error: command=@%s", command);
}
}
/* Dotless i or j. */
void
cm_dotless (arg, start, end)
int arg, start, end;
{
if (arg == END)
{
if (output_paragraph[start] != 'i' && output_paragraph[start] != 'j')
/* This error message isn't perfect if the argument is multiple
characters, but it doesn't seem worth getting right. */
line_error (_("%c%s expects `i' or `j' as argument, not `%c'"),
COMMAND_PREFIX, command, output_paragraph[start]);
else if (end - start != 1)
line_error (_("%c%s expects a single character `i' or `j' as argument"),
COMMAND_PREFIX, command);
/* We've already inserted the `i' or `j', so nothing to do. */
}
}

View File

@ -0,0 +1,86 @@
/* lang.h -- declarations for language codes etc.
$Id: lang.h,v 1.6 1999/03/22 20:07:34 karl Exp $
Copyright (C) 1999 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 Karl Heinz Marbaise <kama@hippo.fido.de>. */
#ifndef LANG_H
#define LANG_H
/* The langauge code which can be changed through @documentlanguage
* Actualy Info does not support this (may be in the future) ;-)
* Default for language code is en (english!) kama
* These code should ISO 639 two letter codes.
*/
typedef enum
{
aa, ab, af, am, ar, as, ay, az,
ba, be, bg, bh, bi, bn, bo, br,
ca, co, cs, cy,
da, de, dz,
el, en, eo, es, et, eu,
fa, fi, fj, fo, fr, fy,
ga, gd, gl, gn, gu,
ha, he, hi, hr, hu, hy,
ia, id, ie, ik, is, it, iu,
ja, jw,
ka, kk, kl, km, kn, ko, ks, ku, ky,
la, ln, lo, lt, lv,
mg, mi, mk, ml, mn, mo, mr, ms, mt, my,
na, ne, nl, no,
oc, om, or,
pa, pl, ps, pt,
qu,
rm, rn, ro, ru, rw,
sa, sd, sg, sh, si, sk, sl, sm, sn, so, sq, sr, ss, st, su, sv, sw,
ta, te, tg, th, ti, tk, tl, tn, to, tr, ts, tt, tw,
ug, uk, ur, uz,
vi, vo,
wo,
xh,
yi, yo,
za, zh, zu,
last_language_code
} language_code_type;
/* The current language code. */
extern language_code_type language_code;
/* Information about all valid languages. */
typedef struct
{
language_code_type lc; /* language code as enum type */
char *abbrev; /* two letter language code */
char *desc; /* full name for language code */
} language_struct;
extern language_struct language_table[];
/* The encoding, or null if not set. */
extern char *document_encoding;
/* The commands. */
extern void cm_documentlanguage (), cm_documentencoding ();
/* Accents, other non-English characters. */
void cm_accent (), cm_special_char (), cm_dotless ();
extern void cm_accent_umlaut (), cm_accent_acute (), cm_accent_cedilla (),
cm_accent_hat (), cm_accent_grave (), cm_accent_tilde ();
#endif /* not LANG_H */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,71 @@
/* macro.h -- declarations for macro.c.
$Id: macro.h,v 1.5 1999/07/15 00:00:46 karl Exp $
Copyright (C) 1998, 99 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.
*/
#ifndef MACRO_H
#define MACRO_H
extern FILE *macro_expansion_output_stream;
extern char *macro_expansion_filename;
extern int me_executing_string;
extern int only_macro_expansion;
/* Here is a structure used to remember input text strings and offsets
within them. */
typedef struct {
char *pointer; /* Pointer to the input text. */
int offset; /* Offset of the last character output. */
} ITEXT;
/* Macro definitions for user-defined commands. */
typedef struct {
char *name; /* Name of the macro. */
char **arglist; /* Args to replace when executing. */
char *body; /* Macro body. */
char *source_file; /* File where this macro is defined. */
int source_lineno; /* Line number within FILENAME. */
int inhibited; /* Nonzero means make find_macro () fail. */
int flags; /* ME_RECURSE, ME_QUOTE_ARG, etc. */
} MACRO_DEF;
/* flags for MACRO_DEF */
#define ME_RECURSE 0x01
#define ME_QUOTE_ARG 0x02
extern void execute_macro ();
extern MACRO_DEF *find_macro ();
extern char *expand_macro ();
extern ITEXT *remember_itext ();
extern void forget_itext ();
extern void maybe_write_itext ();
extern void write_region_to_macro_output ();
extern void append_to_expansion_output ();
extern void me_append_before_this_command ();
extern void me_execute_string ();
extern char *alias_expand ();
extern int enclosure_command ();
extern void enclosure_expand ();
/* The @commands. */
extern void cm_macro (), cm_rmacro (), cm_unmacro ();
extern void cm_alias (), cm_definfoenclose ();
#endif /* not MACRO_H */

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,7 @@
/* makeinfo.h -- Declarations for Makeinfo.
$Id: makeinfo.h,v 1.3 1997/07/15 18:28:38 karl Exp $
/* makeinfo.h -- declarations for Makeinfo.
$Id: makeinfo.h,v 1.25 1999/09/18 18:09:22 karl Exp $
Copyright (C) 1996, 97 Free Software Foundation, Inc.
Copyright (C) 1996, 97, 98, 99 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
@ -19,68 +19,44 @@
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)
#ifndef MAKEINFO_H
#define MAKEINFO_H
#if defined (COMPILING_MAKEINFO)
# define DECLARE(type, var, init) type var = init
#ifdef COMPILING_MAKEINFO
# define DECLARE(type,var,init) type var = init
#else
# define DECLARE(type, var, init) extern type var
# define DECLARE(type,var,init) extern type var
#endif
enum insertion_type
/* Hardcoded per GNU standards, not dependent on argv[0]. */
DECLARE (char *, progname, "makeinfo");
enum reftype
{
cartouche, defcv, deffn, defivar, defmac, defmethod,
defop, defopt, defspec, deftp, deftypefn, deftypefun,
deftypemethod, deftypevar, deftypevr, defun, defvar,
defvr, detailmenu, direntry, display, enumerate, example,
flushleft, flushright, format, ftable, group, ifclear,
ifinfo, ifnothtml, ifnottex, ifset, itemize, lisp, menu,
multitable, quotation, smallexample, smalllisp, table, vtable,
bad_type
menu_reference, followed_reference
};
DECLARE (int, insertion_level, 0);
extern char *get_xref_token ();
/* Nonzero means a string is in execution, as opposed to a file. */
DECLARE (int, executing_string, 0);
#if defined (COMPILING_MAKEINFO)
char *insertion_type_names[] =
{
"cartouche", "defcv", "deffn", "defivar", "defmac", "defmethod",
"defop", "defopt", "defspec", "deftp", "deftypefn", "deftypefun",
"deftypemethod", "deftypevar", "deftypevr", "defun", "defvar",
"defvr", "detailmenu", "direntry", "display", "enumerate", "example",
"flushleft", "flushright", "format", "ftable", "group", "ifclear",
"ifinfo", "ifnothtml", "ifnottex", "ifset", "itemize", "lisp", "menu",
"multitable", "quotation", "smallexample", "smalllisp", "table", "vtable",
"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);
/* Nonzero means to inhibit writing macro expansions to the output
stream, because it has already been written. */
DECLARE (int, me_inhibit_expansion, 0);
extern char *expansion (), *text_expansion ();
/* Current output stream. */
DECLARE (FILE *, output_stream, (FILE *)NULL);
DECLARE (FILE *, output_stream, NULL);
DECLARE (char *, pretty_output_filename, NULL);
/* Current output file name. */
DECLARE (char *, current_output_filename, NULL);
/* Output paragraph buffer. */
DECLARE (unsigned char *, output_paragraph, (unsigned char *)NULL);
DECLARE (unsigned char *, output_paragraph, NULL);
/* Offset into OUTPUT_PARAGRAPH. */
DECLARE (int, output_paragraph_offset, 0);
@ -88,46 +64,132 @@ DECLARE (int, output_paragraph_offset, 0);
/* The output paragraph "cursor" horizontal position. */
DECLARE (int, output_column, 0);
/* Non-zero means output_paragraph contains text. */
/* Position in the output file. */
DECLARE (int, output_position, 0);
/* The offset into OUTPUT_PARAGRAPH where we have a meta character
produced by a markup such as @code or @dfn. */
DECLARE (int, meta_char_pos, -1);
/* Nonzero means output_paragraph contains text. */
DECLARE (int, paragraph_is_open, 0);
/* Nonzero means that `start_paragraph' MUST be called before we pay
any attention to `close_paragraph' calls. */
DECLARE (int, must_start_paragraph, 0);
/* Nonzero means that we have seen "@top" once already. */
DECLARE (int, top_node_seen, 0);
/* Nonzero means that we have seen a non-"@top" node already. */
DECLARE (int, non_top_node_seen, 0);
/* Nonzero indicates that indentation is temporarily turned off. */
DECLARE (int, no_indent, 1);
/* Nonzero indicates that filling a line also indents the new line. */
DECLARE (int, indented_fill, 0);
/* Nonzero means forcing output text to be flushright. */
DECLARE (int, force_flush_right, 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);
/* Nonzero means that words are not to be split, even in long lines. This
gets changed for cm_w (). */
DECLARE (int, non_splitting_words, 0);
/* Amount by which @example indentation increases/decreases. */
DECLARE (int, default_indentation_increment, 5);
/* Nonzero means that we are currently hacking the insides of an
insertion which would use a fixed width font. */
DECLARE (int, in_fixed_width_font, 0);
/* Nonzero if we are currently processing a multitable command */
DECLARE (int, multitable_active, 0);
/* Nonzero means that we're generating HTML. */
DECLARE (int, html, 0);
/* Nonzero means escape characters in HTML output. */
DECLARE (int, escape_html, 1);
extern char *escape_string (); /* do HTML escapes */
/* Nonzero means that the use of paragraph_start_indent is inhibited.
@example uses this to line up the left columns of the example text.
A negative value for this variable is incremented each time it is used.
@noindent uses this to inhibit indentation for a single paragraph. */
DECLARE (int, inhibit_paragraph_indentation, 0);
/* Nonzero indicates that filling will take place on long lines. */
DECLARE (int, filling_enabled, 1);
/* The current node's node name. */
DECLARE (char *, current_node, NULL);
/* Command name in the process of being hacked. */
DECLARE (char *, command, NULL);
/* Nonzero if the last character inserted has the syntax class of NEWLINE. */
DECLARE (int, last_char_was_newline, 1);
/* 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_length, 0);
DECLARE (int, input_text_offset, 0);
DECLARE (int, line_number, 0);
#define curchar() input_text[input_text_offset]
/* **************************************************************** */
/* */
/* Global Defines */
/* */
/* **************************************************************** */
/* A colon separated list of directories to search for files included
with @include. This can be controlled with the `-I' option to makeinfo. */
DECLARE (char *, include_files_path, NULL);
/* Error levels */
#define NO_ERROR 0
#define SYNTAX 2
#define FATAL 4
/* The filename of the current input file. This is never freed. */
DECLARE (char *, node_filename, NULL);
/* Nonzero means do not output "Node: Foo" for node separations, that
is, generate plain text. (--no-headers) */
DECLARE (int, no_headers, 0);
/* Nonzero means that we process @html and @rawhtml even when not
generating HTML. (--ifhtml) */
DECLARE (int, process_html, 0);
/* Nonzero means that we process @ifinfo even when generating HTML.
(--ifinfo) */
DECLARE (int, process_info, 1);
/* Nonzero means that we process @tex and @iftex. (--iftex) */
DECLARE (int, process_tex, 0);
/* Maximum number of references to a single node before complaining.
(--reference-limit) */
DECLARE (int, reference_warning_limit, 1000);
/* Default is to check node references. (--no-validate) */
DECLARE (int, validating, 1);
/* Nonzero means print information about what is going on. (--verbose) */
DECLARE (int, verbose_mode, 0);
/* Nonzero means prefix each @chapter, ... with a number like 1. (--number-sections) */
DECLARE (int, number_sections, 0);
/* Nonzero means expand node names and references while validating.
This will avoid errors when the Texinfo document uses features
like @@ and @value inconsistently in node names, but will slow
the program by about 80%. You HAVE been warned. */
DECLARE (int, expensive_validation, 0);
/* 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)))
@ -138,9 +200,9 @@ DECLARE (int, line_number, 0);
#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'))
#define whitespace(c) ((c) == '\t' || (c) == ' ')
#define sentence_ender(c) ((c) == '.' || (c) == '?' || (c) == '!')
#define cr_or_whitespace(c) (whitespace(c) || (c) == '\r' || (c) == '\n')
#ifndef isletter
#define isletter(c) (((c) >= 'A' && (c) <= 'Z') || ((c) >= 'a' && (c) <= 'z'))
@ -158,33 +220,30 @@ DECLARE (int, line_number, 0);
#define digit_value(c) ((c) - '0')
#endif
#define member(c, s) (strchr (s, c) != NULL)
#define HTML_SAFE "$-_.+!*'()"
#define URL_SAFE_CHAR(ch) (isalnum (ch) || strchr (HTML_SAFE, ch))
#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 command_char(c) (!cr_or_whitespace(c) \
&& (c) != '{' \
&& (c) != '}' \
&& (c) != '=')
#define skip_whitespace() \
while ((input_text_offset != size_of_input_text) && \
while ((input_text_offset != input_text_length) && \
whitespace (curchar())) \
input_text_offset++
#define skip_whitespace_and_newlines() \
do { \
while ((input_text_offset != size_of_input_text) && \
(whitespace (curchar ()) || (curchar () == '\n'))) \
while (input_text_offset != input_text_length \
&& cr_or_whitespace (curchar ())) \
{ \
if (curchar () == '\n') \
line_number++; \
@ -192,4 +251,10 @@ typedef void COMMAND_FUNCTION (); /* So I can say COMMAND_FUNCTION *foo; */
} \
} while (0)
#endif /* !MAKEINFO_H */
/* Return nonzero if STRING is the text at input_text + input_text_offset,
else zero. */
#define looking_at(string) \
(strncmp (input_text + input_text_offset, string, strlen (string)) == 0)
#endif /* not MAKEINFO_H */

View File

@ -1,7 +1,7 @@
/* multi.c -- multitable stuff for makeinfo.
$Id: multi.c,v 1.9 1997/07/24 22:01:00 karl Exp $
$Id: multi.c,v 1.18 1999/08/17 21:06:56 karl Exp $
Copyright (C) 1996, 97 Free Software Foundation, Inc.
Copyright (C) 1996, 97, 98, 99 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
@ -18,6 +18,7 @@
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include "system.h"
#include "insertion.h"
#include "makeinfo.h"
#define MAXCOLS 100 /* remove this limit later @@ */
@ -51,6 +52,7 @@ struct env
{
unsigned char *output_paragraph;
int output_paragraph_offset;
int meta_char_pos;
int output_column;
int paragraph_is_open;
int current_indent;
@ -66,20 +68,33 @@ 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;
/* whether this is the first row. */
static int first_row;
static void output_multitable_row ();
/* 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. */
/* Output a row. Calls insert, but also flushes the buffered output
when we see a newline, since in multitable every line is a separate
paragraph. */
static void
out_char (ch)
int ch;
{
extern int output_position;
putc (ch, output_stream);
output_position++;
if (html)
add_char (ch);
else
{
int env = select_output_environment (0);
insert (ch);
if (ch == '\n')
{
uninhibit_output_flushing ();
flush_output ();
inhibit_output_flushing ();
}
select_output_environment (env);
}
}
@ -88,6 +103,12 @@ draw_horizontal_separator ()
{
int i, j, s;
if (html)
{
add_word ("<hr>");
return;
}
for (s = 0; s < envs[0].current_indent; s++)
out_char (' ');
if (vsep)
@ -101,34 +122,48 @@ draw_horizontal_separator ()
out_char ('\n');
}
/* 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
}
For HTML we construct a simple HTML 3.2 table with <br>s inserted
to help non-tables browsers. `@item' inserts a <tr> and `@tab'
inserts <td>; we also try to close <tr>. The only real
alternative is to rely on the info formatting engine and present
preformatted text. */
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;
}
close_single_paragraph ();
/* 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 ();
first_row = 1;
/* <p> for non-tables browsers. @multitable implicitly ends the
current paragraph, so this is ok. */
if (html)
add_word ("<p><table>");
if (hsep)
draw_horizontal_separator ();
@ -141,6 +176,53 @@ do_multitable ()
++multitable_active;
}
/* Called to handle a {...} template on the @multitable line.
We're at the { and our first job is to find the matching }; as a side
effect, we change *PARAMS to point to after it. Our other job is to
expand the template text and return the width of that string. */
static unsigned
find_template_width (params)
char **params;
{
char *template, *xtemplate;
unsigned len;
char *start = *params;
int brace_level = 0;
/* The first character should be a {. */
if (!params || !*params || **params != '{')
{
line_error ("find_template width internal error: passed %s",
params ? *params : "null");
return 0;
}
do
{
if (**params == '{' && (*params)[-1] != '@')
brace_level++;
else if (**params == '}' && (*params)[-1] != '@')
brace_level--;
else if (**params == 0)
{
line_error (_("Missing } in @multitable template"));
return 0;
}
(*params)++;
}
while (brace_level > 0);
template = substring (start + 1, *params - 1); /* omit braces */
xtemplate = expansion (template, 0);
len = strlen (xtemplate);
free (template);
free (xtemplate);
return len;
}
/* Read the parameters for a multitable from the current command
line, save the parameters away, and return the
number of columns. */
@ -150,7 +232,7 @@ setup_multitable_parameters ()
char *params = insertion_stack->item_function;
int nchars;
float columnfrac;
char command[200]; /* naughty, should be no fixed limits */
char command[200]; /* xx no fixed limits */
int i = 1;
/* We implement @hsep and @vsep even though TeX doesn't.
@ -176,12 +258,12 @@ setup_multitable_parameters ()
for ( ; i <= MAXCOLS; i++) {
if (sscanf (params, "%f", &columnfrac) < 1)
goto done;
/* Unfortunately, can't use %n since some m68k-hp-bsd libc
/* Unfortunately, can't use %n since m68k-hp-bsd libc (at least)
doesn't support it. So skip whitespace (preceding the
number) and then non-whitespace (the number). */
while (*params && (*params == ' ' || *params == '\t'))
params++;
/* Hmm, but what what @columnfractions 3foo. Well, I suppose
/* Hmm, but what about @columnfractions 3foo. Well, I suppose
it's invalid input anyway. */
while (*params && *params != ' ' && *params != '\t'
&& *params != '\n' && *params != '@')
@ -192,15 +274,11 @@ setup_multitable_parameters ()
}
} else if (*params == '{') {
char *start = params;
while ((*params != '}' || params[-1] == '@') && *params) {
params++;
}
unsigned template_width = find_template_width (&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 five, not ten. Also have to match
braces, then. How to take into account current_indent here? */
setup_output_environment (i++, params++ - start);
How to take into account current_indent here? */
setup_output_environment (i++, template_width + 2);
} else {
warning (_("ignoring stray text `%s' after @multitable"), params);
@ -252,6 +330,7 @@ select_output_environment (n)
/* stash current env info from global vars into the old environment */
e->output_paragraph = output_paragraph;
e->output_paragraph_offset = output_paragraph_offset;
e->meta_char_pos = meta_char_pos;
e->output_column = output_column;
e->paragraph_is_open = paragraph_is_open;
e->current_indent = current_indent;
@ -262,6 +341,7 @@ select_output_environment (n)
e = &envs[current_env_no];
output_paragraph = e->output_paragraph;
output_paragraph_offset = e->output_paragraph_offset;
meta_char_pos = e->meta_char_pos;
output_column = e->output_column;
paragraph_is_open = e->paragraph_is_open;
current_indent = e->current_indent;
@ -281,8 +361,6 @@ nselect_next_environment ()
}
static void output_multitable_row ();
/* do anything needed at the beginning of processing a
multitable column. */
void
@ -300,10 +378,20 @@ int
multitable_item ()
{
if (!multitable_active) {
/* impossible, I think. */
error (_("multitable item not in active multitable"));
exit (1);
line_error ("multitable_item internal error: no active multitable");
xexit (1);
}
if (html)
{
if (!first_row)
add_word ("<br></tr>"); /* <br> for non-tables browsers. */
add_word ("<tr align=\"left\"><td>");
first_row = 0;
return;
}
first_row = 0;
if (current_env_no > 0) {
output_multitable_row ();
}
@ -311,7 +399,7 @@ multitable_item ()
select_output_environment (1);
if (!output_paragraph) {
line_error (_("Cannot select column #%d in multitable"), current_env_no);
exit (FATAL);
exit (1);
}
init_column ();
@ -322,11 +410,11 @@ multitable_item ()
static void
output_multitable_row ()
{
int i, j, s, remaining;
/* offset in the output paragraph of the next char needing
to be output for that column. */
int offset[MAXCOLS];
int i, j, s, remaining;
int had_newline = 0;
for (i = 0; i <= last_column; i++)
offset[i] = 0;
@ -340,9 +428,12 @@ output_multitable_row ()
/* 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--;
}
if (envs[i].output_paragraph_offset)
while (cr_or_whitespace (CHAR_AT (envs[i].output_paragraph_offset - 1)))
envs[i].output_paragraph_offset--;
if (i == current_env_no)
output_paragraph_offset = envs[i].output_paragraph_offset;
}
/* read the current line from each column, outputting them all
@ -367,7 +458,7 @@ output_multitable_row ()
out_char ('|');
for (i = 1; i <= last_column; i++) {
for (s = 0; i < envs[i].current_indent; s++)
for (s = 0; s < envs[i].current_indent; s++)
out_char (' ');
for (j = 0; CHAR_ADDR (j) < envs[i].output_paragraph_offset; j++) {
if (CHAR_AT (j) == '\n')
@ -375,13 +466,22 @@ output_multitable_row ()
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 (' ');
/* Do not output trailing blanks if we're in the last column and
there will be no trailing |. */
if (i < last_column && !vsep)
for (; j <= envs[i].fill_column; j++)
out_char (' ');
if (vsep)
out_char ('|'); /* draw column separator */
}
out_char ('\n'); /* end of line */
had_newline = 1;
}
/* If completely blank item, get blank line despite no other output. */
if (!had_newline)
out_char ('\n'); /* end of line */
if (hsep)
draw_horizontal_separator ();
@ -403,7 +503,11 @@ cm_tab ()
if (!multitable_active)
error (_("ignoring @tab outside of multitable"));
nselect_next_environment ();
if (html)
add_word ("<td>");
else
nselect_next_environment ();
init_column ();
}
@ -412,17 +516,19 @@ cm_tab ()
void
end_multitable ()
{
output_multitable_row ();
if (!html)
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 ();
close_insertion_paragraph ();
if (html)
add_word ("<br></tr></table>\n");
#if 0
printf (_("** Multicolumn output from last row:\n"));

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,111 @@
/* node.h -- declarations for Node.
$Id: node.h,v 1.5 1999/07/11 16:50:19 karl Exp $
Copyright (C) 1996, 97, 98, 99 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). */
#ifndef NODE_H
#define NODE_H
/* The various references that we know about. */
/* What we remember for each node. */
typedef struct tentry
{
struct tentry *next_ent;
char *node; /* Name of this node. */
char *prev; /* Name of "Prev:" for this node. */
char *next; /* Name of "Next:" for this node. */
char *up; /* Name of "Up:" for this node. */
int position; /* Output file position of this node. */
int line_no; /* Defining line in source file. */
char *filename; /* The file that this node was found in. */
int touched; /* Nonzero means this node has been referenced. */
int flags;
int number; /* Number for this node, relevant for HTML
splitting -- from use+define order, not just
define. */
} TAG_ENTRY;
/* If node-a has a "Next" for node-b, but node-b has no "Prev" for node-a,
we turn on this flag bit in node-b's tag entry. This means that when
it is time to validate node-b, we don't report an additional error
if there was no "Prev" field. */
#define TAG_FLAG_PREV_ERROR 1
#define TAG_FLAG_NEXT_ERROR 2
#define TAG_FLAG_UP_ERROR 4
#define TAG_FLAG_NO_WARN 8
#define TAG_FLAG_IS_TOP 16
#define TAG_FLAG_ANCHOR 32
/* Menu reference, *note reference, and validation hacking. */
/* A structure to remember references with. A reference to a node is
either an entry in a menu, or a cross-reference made with [px]ref. */
typedef struct node_ref
{
struct node_ref *next;
char *node; /* Name of node referred to. */
char *containing_node; /* Name of node containing this reference. */
int line_no; /* Line number where the reference occurs. */
int section; /* Section level where the reference occurs. */
char *filename; /* Name of file where the reference occurs. */
enum reftype type; /* Type of reference, either menu or note. */
int number; /* Number for this node, relevant for
HTML splitting -- from use+define
order, not just define. */
} NODE_REF;
/* The linked list of such structures. */
extern NODE_REF *node_references;
/* A similar list for references occuring in @node next
and similar references, needed for HTML. */
extern NODE_REF *node_node_references;
/* List of all nodes. */
extern TAG_ENTRY *tag_table;
/* Counter for setting node_ref.number; zero is Top. */
extern int node_number;
/* The current node's section level. */
extern int current_section;
/* Nonzero when the next sectioning command should generate an anchor
corresponding to the current node in HTML mode. */
extern int outstanding_node;
extern TAG_ENTRY *find_node ();
/* A search string which is used to find a line defining a node. */
DECLARE (char *, node_search_string, "\n@node ");
/* Extract node name from a menu item. */
extern char *glean_node_from_menu ();
/* Remember a node for later validation. */
extern void remember_node_reference ();
/* Remember the name of the current output file. */
extern void set_current_output_filename ();
/* Expand macros and commands in the node name and canonicalize
whitespace in the resulting expansion. */
extern char *expand_node_name ();
#endif /* NODE_H */

View File

@ -0,0 +1,691 @@
/* sectioning.c -- all related stuff @chapter, @section... @contents
$Id: sectioning.c,v 1.12 1999/08/17 21:06:50 karl Exp $
Copyright (C) 1999 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 Karl Heinz Marbaise <kama@hippo.fido.de>. */
#include "system.h"
#include "cmds.h"
#include "macro.h"
#include "makeinfo.h"
#include "node.h"
#include "toc.h"
#include "sectioning.h"
/* See comment in sectioning.h. */
section_alist_type section_alist[] = {
{ "unnumberedsubsubsec", 5, ENUM_SECT_NO, TOC_YES },
{ "unnumberedsubsec", 4, ENUM_SECT_NO, TOC_YES },
{ "unnumberedsec", 3, ENUM_SECT_NO, TOC_YES },
{ "unnumbered", 2, ENUM_SECT_NO, TOC_YES },
{ "appendixsubsubsec", 5, ENUM_SECT_APP, TOC_YES }, /* numbered like A.X.X.X */
{ "appendixsubsec", 4, ENUM_SECT_APP, TOC_YES },
{ "appendixsec", 3, ENUM_SECT_APP, TOC_YES },
{ "appendixsection", 3, ENUM_SECT_APP, TOC_YES },
{ "appendix", 2, ENUM_SECT_APP, TOC_YES },
{ "subsubsec", 5, ENUM_SECT_YES, TOC_YES },
{ "subsubsection", 5, ENUM_SECT_YES, TOC_YES },
{ "subsection", 4, ENUM_SECT_YES, TOC_YES },
{ "section", 3, ENUM_SECT_YES, TOC_YES },
{ "chapter", 2, ENUM_SECT_YES, TOC_YES },
{ "subsubheading", 5, ENUM_SECT_NO, TOC_NO },
{ "subheading", 4, ENUM_SECT_NO, TOC_NO },
{ "heading", 3, ENUM_SECT_NO, TOC_NO },
{ "chapheading", 2, ENUM_SECT_NO, TOC_NO },
{ "majorheading", 2, ENUM_SECT_NO, TOC_NO },
{ "top", 1, ENUM_SECT_NO, TOC_YES },
{ NULL, 0, 0, 0 }
};
/* The argument of @settitle, used for HTML. */
char *title = NULL;
#define APPENDIX_MAGIC 1024
#define UNNUMBERED_MAGIC 2048
/* Number memory for every level @chapter, @section,
@subsection, @subsubsection. */
static int numbers [] = { 0, 0, 0, 0 };
/* enum_marker == APPENDIX_MAGIC then we are counting appendencies
enum_marker == UNNUMBERED_MAGIC then we are within unnumbered area.
Handling situations like this:
@unnumbered ..
@section ... */
static int enum_marker = 0;
/* Organized by level commands. That is, "*" == chapter, "=" == section. */
static char *scoring_characters = "*=-.";
/* Amount to offset the name of sectioning commands to levels by. */
static int section_alist_offset = 0;
/* num == ENUM_SECT_NO means unnumbered (should never call this)
num == ENUM_SECT_YES means numbered
num == ENUM_SECT_APP means numbered like A.1 and so on */
char *
get_sectioning_number (level, num)
int level;
int num;
{
static char s[100]; /* should ever be enough for 99.99.99.99
Appendix A.1 */
char *p;
int i;
s[0] = 0;
/* create enumeration in front of chapter, section, subsection and so on. */
for (i = 0; i < level; i++)
{
p = s + strlen (s);
if ((i == 0) && (enum_marker == APPENDIX_MAGIC))
sprintf (p, "%c.", numbers[i] + 64); /* Should be changed to
be more portable */
else
sprintf (p, "%d.", numbers[i]);
}
/* the last number is never followed by a dot */
p = s + strlen (s);
if ((num == ENUM_SECT_APP)
&& (i == 0)
&& (enum_marker == APPENDIX_MAGIC))
sprintf (p, _("Appendix %c "), numbers[i] + 64);
else
sprintf (p, "%d ", numbers[i]);
return s;
}
/* Set the level of @top to LEVEL. Return the old level of @top. */
int
set_top_section_level (level)
int level;
{
int i, result = -1;
for (i = 0; section_alist[i].name; i++)
if (strcmp (section_alist[i].name, "top") == 0)
{
result = section_alist[i].level;
section_alist[i].level = level;
break;
}
return result;
}
/* return the index of the given sectioning command in section_alist */
int
search_sectioning (text)
char *text;
{
int i;
char *t;
/* ignore the optional command prefix */
if (text[0] == COMMAND_PREFIX)
text++;
for (i = 0; (t = section_alist[i].name); i++)
{
if (strcmp (t, text) == 0)
{
return i;
}
}
return -1;
}
/* Return an integer which identifies the type section present in TEXT. */
int
what_section (text)
char *text;
{
int index, j;
char *temp;
int return_val;
find_section_command:
for (j = 0; text[j] && cr_or_whitespace (text[j]); j++);
if (text[j] != COMMAND_PREFIX)
return -1;
text = text + j + 1;
/* We skip @c, @comment, and @?index commands. */
if ((strncmp (text, "comment", strlen ("comment")) == 0) ||
(text[0] == 'c' && cr_or_whitespace (text[1])) ||
(strcmp (text + 1, "index") == 0))
{
while (*text++ != '\n');
goto find_section_command;
}
/* Handle italicized sectioning commands. */
if (*text == 'i')
text++;
for (j = 0; text[j] && !cr_or_whitespace (text[j]); j++);
temp = xmalloc (1 + j);
strncpy (temp, text, j);
temp[j] = 0;
index = search_sectioning (temp);
free (temp);
if (index >= 0)
{
return_val = section_alist[index].level + section_alist_offset;
if (return_val < 0)
return_val = 0;
else if (return_val > 5)
return_val = 5;
return return_val;
}
return -1;
}
void
sectioning_underscore (cmd)
char *cmd;
{
char character;
char *temp;
int level;
temp = xmalloc (2 + strlen (cmd));
temp[0] = COMMAND_PREFIX;
strcpy (&temp[1], cmd);
level = what_section (temp);
free (temp);
level -= 2;
if (level < 0)
level = 0;
if (html)
sectioning_html (level, cmd);
else
{
character = scoring_characters[level];
insert_and_underscore (level, character, cmd);
}
}
/* insert_and_underscore and sectioning_html are the
only functions which call this.
I have created this, because it was exactly the same
code in both functions. */
static char *
handle_enum_increment (level, index)
int level;
int index;
{
/* special for unnumbered */
if (number_sections && section_alist[index].num == ENUM_SECT_NO)
{
if (level == 0
&& enum_marker != UNNUMBERED_MAGIC)
enum_marker = UNNUMBERED_MAGIC;
}
/* enumerate only things which are allowed */
if (number_sections && section_alist[index].num)
{
/* reset the marker if we get into enumerated areas */
if (section_alist[index].num == ENUM_SECT_YES
&& level == 0
&& enum_marker == UNNUMBERED_MAGIC)
enum_marker = 0;
/* This is special for appendix; if we got the first
time an appendix command then we are entering appendix.
Thats the point we have to start countint with A, B and so on. */
if (section_alist[index].num == ENUM_SECT_APP
&& level == 0
&& enum_marker != APPENDIX_MAGIC)
{
enum_marker = APPENDIX_MAGIC;
numbers [0] = 0; /* this means we start with Appendix A */
}
/* only increment counters if we are not in unnumbered
area. This handles situations like this:
@unnumbered .... This sets enum_marker to UNNUMBERED_MAGIC
@section .... */
if (enum_marker != UNNUMBERED_MAGIC)
{
int i;
/* reset all counters which are one level deeper */
for (i = level; i < 3; i++)
numbers [i + 1] = 0;
numbers[level]++;
return xstrdup
(get_sectioning_number (level, section_alist[index].num));
}
} /* if (number_sections)... */
return xstrdup ("");
}
/* Insert the text following input_text_offset up to the end of the line
in a new, separate paragraph. Directly underneath it, insert a
line of WITH_CHAR, the same length of the inserted text. */
void
insert_and_underscore (level, with_char, cmd)
int level;
int with_char;
char *cmd;
{
int i, len;
int index;
int old_no_indent;
unsigned char *starting_pos, *ending_pos;
char *temp;
close_paragraph ();
filling_enabled = indented_fill = 0;
old_no_indent = no_indent;
no_indent = 1;
if (macro_expansion_output_stream && !executing_string)
append_to_expansion_output (input_text_offset + 1);
get_rest_of_line (0, &temp);
starting_pos = output_paragraph + output_paragraph_offset;
index = search_sectioning (cmd);
if (index < 0)
{
/* should never happen, but a poor guy, named Murphy ... */
warning (_("Internal error (search_sectioning) \"%s\"!"), cmd);
return;
}
/* This is a bit tricky: we must produce "X.Y SECTION-NAME" in the
Info output and in TOC, but only SECTION-NAME in the macro-expanded
output. */
/* Step 1: produce "X.Y" and add it to Info output. */
add_word (handle_enum_increment (level, index));
/* Step 2: add "SECTION-NAME" to both Info and macro-expanded output. */
if (macro_expansion_output_stream && !executing_string)
{
char *temp1 = xmalloc (2 + strlen (temp));
sprintf (temp1, "%s\n", temp);
remember_itext (input_text, input_text_offset);
me_execute_string (temp1);
free (temp1);
}
else
execute_string ("%s\n", temp);
/* Step 3: pluck "X.Y SECTION-NAME" from the output buffer and
insert it into the TOC. */
ending_pos = output_paragraph + output_paragraph_offset;
if (section_alist[index].toc == TOC_YES)
toc_add_entry (substring (starting_pos, ending_pos - 1),
level, current_node, NULL);
free (temp);
len = (ending_pos - starting_pos) - 1;
for (i = 0; i < len; i++)
add_char (with_char);
insert ('\n');
close_paragraph ();
filling_enabled = 1;
no_indent = old_no_indent;
}
/* Insert the text following input_text_offset up to the end of the
line as an HTML heading element of the appropriate `level' and
tagged as an anchor for the current node.. */
void
sectioning_html (level, cmd)
int level;
char *cmd;
{
static int toc_ref_count = 0;
int index;
int old_no_indent;
unsigned char *starting_pos, *ending_pos;
char *temp, *toc_anchor = NULL;
close_paragraph ();
filling_enabled = indented_fill = 0;
old_no_indent = no_indent;
no_indent = 1;
add_word_args ("<h%d>", level + 1); /* level 0 is <h1> */
/* If we are outside of any node, produce an anchor that
the TOC could refer to. */
if (!current_node || !*current_node)
{
starting_pos = output_paragraph + output_paragraph_offset;
add_word_args ("<a name=\"TOC%d\">", toc_ref_count++);
toc_anchor = substring (starting_pos + 9,
output_paragraph + output_paragraph_offset);
}
starting_pos = output_paragraph + output_paragraph_offset;
if (macro_expansion_output_stream && !executing_string)
append_to_expansion_output (input_text_offset + 1);
get_rest_of_line (0, &temp);
index = search_sectioning (cmd);
if (index < 0)
{
/* should never happen, but a poor guy, named Murphy ... */
warning (_("Internal error (search_sectioning) \"%s\"!"), cmd);
return;
}
/* Produce "X.Y" and add it to HTML output. */
add_word (handle_enum_increment (level, index));
/* add the section name to both HTML and macro-expanded output. */
if (macro_expansion_output_stream && !executing_string)
{
remember_itext (input_text, input_text_offset);
me_execute_string (temp);
write_region_to_macro_output ("\n", 0, 1);
}
else
execute_string ("%s", temp);
ending_pos = output_paragraph + output_paragraph_offset;
/* Pluck ``X.Y SECTION-NAME'' from the output buffer and insert it
into the TOC. */
if (section_alist[index].toc == TOC_YES)
toc_add_entry (substring (starting_pos, ending_pos),
level, current_node, toc_anchor);
free (temp);
if (outstanding_node)
outstanding_node = 0;
add_word_args ("</h%d>", level+1);
close_paragraph();
filling_enabled = 1;
no_indent = old_no_indent;
}
/* Shift the meaning of @section to @chapter. */
void
cm_raisesections ()
{
discard_until ("\n");
section_alist_offset--;
}
/* Shift the meaning of @chapter to @section. */
void
cm_lowersections ()
{
discard_until ("\n");
section_alist_offset++;
}
/* The command still works, but prints a warning message in addition. */
void
cm_ideprecated (arg, start, end)
int arg, start, end;
{
warning (_("%c%s is obsolete; use %c%s instead"),
COMMAND_PREFIX, command, COMMAND_PREFIX, command + 1);
sectioning_underscore (command + 1);
}
/* Treat this just like @unnumbered. The only difference is
in node defaulting. */
void
cm_top ()
{
/* It is an error to have more than one @top. */
if (top_node_seen && strcmp (current_node, "Top") != 0)
{
TAG_ENTRY *tag = tag_table;
line_error (_("Node with %ctop as a section already exists"),
COMMAND_PREFIX);
while (tag)
{
if (tag->flags & TAG_FLAG_IS_TOP)
{
int old_line_number = line_number;
char *old_input_filename = input_filename;
line_number = tag->line_no;
input_filename = tag->filename;
line_error (_("Here is the %ctop node"), COMMAND_PREFIX);
input_filename = old_input_filename;
line_number = old_line_number;
return;
}
tag = tag->next_ent;
}
}
else
{
TAG_ENTRY *top_node = find_node ("Top");
top_node_seen = 1;
/* It is an error to use @top before you have used @node. */
if (!tag_table)
{
char *top_name;
get_rest_of_line (0, &top_name);
line_error (_("%ctop used before %cnode, defaulting to %s"),
COMMAND_PREFIX, COMMAND_PREFIX, top_name);
execute_string ("@node Top, , (dir), (dir)\n@top %s\n", top_name);
free (top_name);
return;
}
else if (html && splitting)
{
char *next = top_node ? top_node->next : NULL;
add_word ("<p>");
if (next)
{
add_word (_("Next:"));
add_word ("<a rel=next href=\"");
add_anchor_name (next, 1);
add_word ("\">");
execute_string (next);
add_word ("</a>\n");
}
}
cm_unnumbered ();
/* The most recently defined node is the top node. */
tag_table->flags |= TAG_FLAG_IS_TOP;
/* Now set the logical hierarchical level of the Top node. */
{
int orig_offset = input_text_offset;
input_text_offset = search_forward (node_search_string, orig_offset);
if (input_text_offset > 0)
{
int this_section;
/* We have encountered a non-top node, so mark that one exists. */
non_top_node_seen = 1;
/* Move to the end of this line, and find out what the
sectioning command is here. */
while (input_text[input_text_offset] != '\n')
input_text_offset++;
if (input_text_offset < input_text_length)
input_text_offset++;
this_section = what_section (input_text + input_text_offset);
/* If we found a sectioning command, then give the top section
a level of this section - 1. */
if (this_section != -1)
set_top_section_level (this_section - 1);
}
input_text_offset = orig_offset;
}
}
}
/* The remainder of the text on this line is a chapter heading. */
void
cm_chapter ()
{
sectioning_underscore ("chapter");
}
/* The remainder of the text on this line is a section heading. */
void
cm_section ()
{
sectioning_underscore ("section");
}
/* The remainder of the text on this line is a subsection heading. */
void
cm_subsection ()
{
sectioning_underscore ("subsection");
}
/* The remainder of the text on this line is a subsubsection heading. */
void
cm_subsubsection ()
{
sectioning_underscore ("subsubsection");
}
/* The remainder of the text on this line is an unnumbered heading. */
void
cm_unnumbered ()
{
sectioning_underscore ("unnumbered");
}
/* The remainder of the text on this line is an unnumbered section heading. */
void
cm_unnumberedsec ()
{
sectioning_underscore ("unnumberedsec");
}
/* The remainder of the text on this line is an unnumbered
subsection heading. */
void
cm_unnumberedsubsec ()
{
sectioning_underscore ("unnumberedsubsec");
}
/* The remainder of the text on this line is an unnumbered
subsubsection heading. */
void
cm_unnumberedsubsubsec ()
{
sectioning_underscore ("unnumberedsubsubsec");
}
/* The remainder of the text on this line is an appendix heading. */
void
cm_appendix ()
{
sectioning_underscore ("appendix");
}
/* The remainder of the text on this line is an appendix section heading. */
void
cm_appendixsec ()
{
sectioning_underscore ("appendixsec");
}
/* The remainder of the text on this line is an appendix subsection heading. */
void
cm_appendixsubsec ()
{
sectioning_underscore ("appendixsubsec");
}
/* The remainder of the text on this line is an appendix
subsubsection heading. */
void
cm_appendixsubsubsec ()
{
sectioning_underscore ("appendixsubsubsec");
}
/* Compatibility functions substitute for chapter, section, etc. */
void
cm_majorheading ()
{
sectioning_underscore ("majorheading");
}
void
cm_chapheading ()
{
sectioning_underscore ("chapheading");
}
void
cm_heading ()
{
sectioning_underscore ("heading");
}
void
cm_subheading ()
{
sectioning_underscore ("subheading");
}
void
cm_subsubheading ()
{
sectioning_underscore ("subsubheading");
}

View File

@ -0,0 +1,80 @@
/* sectioning.h -- all related stuff @chapter, @section... @contents
$Id: sectioning.h,v 1.2 1999/03/09 22:48:15 karl Exp $
Copyright (C) 1999 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 Karl Heinz Marbaise <kama@hippo.fido.de>. */
#ifndef SECTIONING_H
#define SECTIONING_H
/* Sectioning. */
extern void
cm_chapter (), cm_unnumbered (), cm_appendix (), cm_top (),
cm_section (), cm_unnumberedsec (), cm_appendixsec (),
cm_subsection (), cm_unnumberedsubsec (), cm_appendixsubsec (),
cm_subsubsection (), cm_unnumberedsubsubsec (), cm_appendixsubsubsec (),
cm_heading (), cm_chapheading (), cm_subheading (), cm_subsubheading (),
cm_majorheading (), cm_raisesections (), cm_lowersections (),
cm_ideprecated ();
extern void
sectioning_underscore (), insert_and_underscore ();
extern int what_section ();
/* is needed in node.c */
extern int set_top_section_level ();
extern void sectioning_html ();
extern int what_section ();
/* The argument of @settitle, used for HTML. */
extern char *title;
/* Here is a structure which associates sectioning commands with
an integer that reflects the depth of the current section. */
typedef struct
{
char *name;
int level; /* I can't replace the levels with defines
because it is changed during run */
int num; /* ENUM_SECT_NO means no enumeration...
ENUM_SECT_YES means enumerated version
ENUM_SECT_APP appendix (Character enumerated
at first position */
int toc; /* TOC_NO means do not enter in toc;
TOC_YES means enter it in toc */
} section_alist_type;
extern section_alist_type section_alist[];
/* enumerate sections */
#define ENUM_SECT_NO 0
#define ENUM_SECT_YES 1
#define ENUM_SECT_APP 2
/* make entries into toc no/yes */
#define TOC_NO 0
#define TOC_YES 1
#endif /* not SECTIONING_H */

View File

@ -0,0 +1,476 @@
/* toc.c -- table of contents handling.
$Id: toc.c,v 1.14 1999/08/09 20:28:18 karl Exp $
Copyright (C) 1999 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 Karl Heinz Marbaise <kama@hippo.fido.de>. */
#include "system.h"
#include "makeinfo.h"
#include "cmds.h"
#include "files.h"
#include "macro.h"
#include "node.h"
#include "lang.h"
#include "makeinfo.h"
#include "sectioning.h"
#include "toc.h"
/* array of toc entries */
static TOC_ENTRY_ELT **toc_entry_alist = NULL;
/* toc_counter start from 0 ... n for every @chapter, @section ... */
static int toc_counter = 0;
/* the file where we found the @contents directive */
char *contents_filename;
/* the file where we found the @shortcontents directive */
char *shortcontents_filename;
static const char contents_placebo[] = "\n...Table of Contents...\n";
static const char shortcontents_placebo[] = "\n...Short Contents...\n";
static const char lots_of_stars[] =
"***************************************************************************";
/* Routine to add an entry to the table of contents */
int
toc_add_entry (tocname, level, node_name, anchor)
char *tocname;
int level;
char *node_name;
char *anchor;
{
char *tocname_and_node, *expanded_node, *s, *d;
if (!node_name)
node_name = "";
/* I assume that xrealloc behaves like xmalloc if toc_entry_alist is
NULL */
toc_entry_alist = xrealloc (toc_entry_alist,
(toc_counter + 1) * sizeof (TOC_ENTRY_ELT *));
toc_entry_alist[toc_counter] = xmalloc (sizeof (TOC_ENTRY_ELT));
if (html)
{
/* We need to insert the expanded node name into the TOC, so
that when we eventually output the TOC, its <A REF= link will
point to the <A NAME= tag created by cm_node in the navigation
bar. We cannot expand the containing_node member, for the
reasons explained in the WARNING below. We also cannot wait
with the node name expansion until the TOC is actually output,
since by that time the macro definitions may have been changed.
So instead we store in the tocname member the expanded node
name and the TOC name concatenated together (with the necessary
HTML markup), since that's how they are output. */
if (!anchor)
s = expanded_node = expand_node_name (node_name);
else
expanded_node = anchor;
/* Sigh... Need to HTML-escape the expanded node name like
add_anchor_name does, except that we are not writing this to
the output, so can't use add_anchor_name... */
/* The factor 5 in the next allocation is because the maximum
expansion of HTML-escaping is for the & character, which is
output as "&amp;". 2 is for "> that separates node from tocname. */
d = tocname_and_node = (char *)xmalloc (2 + 5 * strlen (expanded_node)
+ strlen (tocname) + 1);
if (!anchor)
{
for (; *s; s++)
{
if (*s == '&')
{
strcpy (d, "&amp;");
d += 5;
}
else if (! URL_SAFE_CHAR (*s))
{
sprintf (d, "%%%x", (unsigned char) *s);
/* do this manually since sprintf returns char * on
SunOS 4 and other old systems. */
while (*d)
d++;
}
else
*d++ = *s;
}
strcpy (d, "\">");
}
else
/* Section outside any node, they provided explicit anchor. */
strcpy (d, anchor);
strcat (d, tocname);
free (tocname); /* it was malloc'ed by substring() */
free (expanded_node);
toc_entry_alist[toc_counter]->name = tocname_and_node;
}
else
toc_entry_alist[toc_counter]->name = tocname;
/* WARNING! The node name saved in containing_node member must
be the node name with _only_ macros expanded (the macros in
the node name are expanded by cm_node when it grabs the name
from the @node directive). Non-macros, like @value, @@ and
other @-commands must NOT be expanded in containing_node,
because toc_find_section_of_node looks up the node name where
they are also unexpanded. You *have* been warned! */
toc_entry_alist[toc_counter]->containing_node = xstrdup (node_name);
toc_entry_alist[toc_counter]->level = level;
toc_entry_alist[toc_counter]->number = toc_counter;
/* have to be done at least */
return toc_counter++;
}
/* Return the name of a chapter/section/subsection etc. that
corresponds to the node NODE. If the node isn't found,
return NULL.
WARNING! This function relies on NODE being unexpanded
except for macros (i.e., @value, @@, and other non-macros
should NOT be expanded), because the containing_node member
stores unexpanded node names.
Note that this function returns the first section whose
containing node is NODE. Thus, they will lose if they use
more than a single chapter structioning command in a node,
or if they have a node without any structuring commands. */
char *
toc_find_section_of_node (node)
char *node;
{
int i;
if (!node)
node = "";
for (i = 0; i < toc_counter; i++)
if (STREQ (node, toc_entry_alist[i]->containing_node))
return toc_entry_alist[i]->name;
return NULL;
}
/* free up memory used by toc entries */
void
toc_free ()
{
int i;
if (toc_counter)
{
for (i = 0; i < toc_counter; i++)
{
free (toc_entry_alist[i]->name);
free (toc_entry_alist[i]->containing_node);
free (toc_entry_alist[i]);
}
free (toc_entry_alist);
toc_entry_alist = NULL; /* to be sure ;-) */
toc_counter = 0; /* to be absolutley sure ;-) */
}
}
/* print table of contents in HTML, may be we can produce a standalone
HTML file? */
static void
contents_update_html (fp)
FILE *fp;
{
int i;
int k;
int last_level;
/* does exist any toc? */
if (!toc_counter)
/* no, so return to sender ;-) */
return;
flush_output (); /* in case we are writing stdout */
fprintf (fp, "\n<h1>%s</h1>\n<ul>\n", _("Table of Contents"));
last_level = toc_entry_alist[0]->level;
for (i = 0; i < toc_counter; i++)
{
if (toc_entry_alist[i]->level > last_level)
{
/* unusual, but it is possible
@chapter ...
@subsubsection ... ? */
for (k = 0; k < (toc_entry_alist[i]->level-last_level); k++)
fputs ("<ul>\n", fp);
}
else if (toc_entry_alist[i]->level < last_level)
{
/* @subsubsection ...
@chapter ... this IS usual.*/
for (k = 0; k < (last_level-toc_entry_alist[i]->level); k++)
fputs ("</ul>\n", fp);
}
fprintf (fp, "<li><a href=\"#%s</a>\n", toc_entry_alist[i]->name);
last_level = toc_entry_alist[i]->level;
}
/* Go back to start level. */
if (toc_entry_alist[0]->level < last_level)
for (k = 0; k < (last_level-toc_entry_alist[0]->level); k++)
fputs ("</ul>\n", fp);
fputs ("</ul>\n\n", fp);
}
/* print table of contents in ASCII (--no-headers)
May be we should create a new command line switch --ascii ? */
static void
contents_update_info (fp)
FILE *fp;
{
int i;
int k;
if (!toc_counter)
return;
flush_output (); /* in case we are writing stdout */
fprintf (fp, "%s\n%.*s\n\n", _("Table of Contents"),
(int) strlen (_("Table of Contents")), lots_of_stars);
for (i = 0; i < toc_counter; i++)
{
if (toc_entry_alist[i]->level == 0)
fputs ("\n", fp);
/* indention with two spaces per level, should this
changed? */
for (k = 0; k < toc_entry_alist[i]->level; k++)
fputs (" ", fp);
fprintf (fp, "%s\n", toc_entry_alist[i]->name);
}
fputs ("\n\n", fp);
}
/* shortcontents in HTML; Should this produce a standalone file? */
static void
shortcontents_update_html (fp)
FILE *fp;
{
int i;
/* does exist any toc? */
if (!toc_counter)
return;
flush_output (); /* in case we are writing stdout */
fprintf (fp, "\n<h1>%s</h1>\n<ul>\n", _("Short Contents"));
for (i = 0; i < toc_counter; i++)
{
if ((toc_entry_alist[i])->level == 0)
{
fputs ("<li>", fp);
fprintf (fp, "<a href=\"#%s\n", toc_entry_alist[i]->name);
}
}
fputs ("</ul>\n\n", fp);
}
/* short contents in ASCII (--no-headers).
May be we should create a new command line switch --ascii ? */
static void
shortcontents_update_info (fp)
FILE *fp;
{
int i;
if (!toc_counter)
return;
flush_output (); /* in case we are writing stdout */
fprintf (fp, "%s\n%.*s\n\n", _("Short Contents"),
(int) strlen (_("Short Contents")), lots_of_stars);
for (i = 0; i < toc_counter; i++)
{
if ((toc_entry_alist[i])->level == 0)
fprintf (fp, "%s\n", toc_entry_alist[i]->name);
}
fputs ("\n\n", fp);
}
static FILE *toc_fp;
static char *toc_buf;
static int
rewrite_top (fname, placebo)
const char *fname, *placebo;
{
int idx;
toc_buf = find_and_load (fname);
if (!toc_buf)
{
/* Can't rewrite standard output. No point in complaining. */
if (!STREQ (fname, "-"))
fs_error (fname);
return -1;
}
idx = search_forward (placebo, 0);
if (idx < 0)
{
error (_("%s: TOC should be here, but it was not found"), fname);
return -1;
}
toc_fp = fopen (fname, "w");
if (!toc_fp)
{
fs_error (fname);
return -1;
}
if (fwrite (toc_buf, 1, idx, toc_fp) != idx)
{
fs_error (fname);
return -1;
}
return idx + strlen (placebo);
}
static void
contents_update ()
{
int cont_idx = rewrite_top (contents_filename, contents_placebo);
if (cont_idx < 0)
return;
if (html)
contents_update_html (toc_fp);
else
contents_update_info (toc_fp);
if (fwrite (toc_buf + cont_idx, 1, input_text_length - cont_idx, toc_fp)
!= input_text_length - cont_idx
|| fclose (toc_fp) != 0)
fs_error (contents_filename);
}
static void
shortcontents_update ()
{
int cont_idx = rewrite_top (shortcontents_filename, shortcontents_placebo);
if (cont_idx < 0)
return;
if (html)
shortcontents_update_html (toc_fp);
else
shortcontents_update_info (toc_fp);
if (fwrite (toc_buf + cont_idx, 1, input_text_length - cont_idx - 1, toc_fp)
!= input_text_length - cont_idx - 1
|| fclose (toc_fp) != 0)
fs_error (shortcontents_filename);
}
void
toc_update ()
{
if (!html && !no_headers)
return;
if (contents_filename)
contents_update ();
if (shortcontents_filename)
shortcontents_update ();
}
void
cm_contents (arg)
int arg;
{
if ((html || no_headers) && arg == START)
{
if (contents_filename)
{
free (contents_filename);
contents_filename = NULL;
}
if (contents_filename && STREQ (contents_filename, "-"))
{
if (html)
contents_update_html (stdout);
else
contents_update_info (stdout);
}
else
{
contents_filename = xstrdup (current_output_filename);
insert_string (contents_placebo); /* just mark it, for now */
}
}
}
void
cm_shortcontents (arg)
int arg;
{
if ((html || no_headers) && arg == START)
{
if (shortcontents_filename)
{
free (shortcontents_filename);
shortcontents_filename = NULL;
}
if (shortcontents_filename && STREQ (shortcontents_filename, "-"))
{
if (html)
shortcontents_update_html (stdout);
else
shortcontents_update_info (stdout);
}
else
{
shortcontents_filename = xstrdup (current_output_filename);
insert_string (shortcontents_placebo); /* just mark it, for now */
}
}
}

View File

@ -0,0 +1,49 @@
/* toc.h -- table of contents handling.
$Id: toc.h,v 1.4 1999/04/25 19:49:22 karl Exp $
Copyright (C) 1999 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 Karl Heinz Marbaise <kama@hippo.fido.de>. */
#ifndef TOC_H
#define TOC_H
/* the file where we found the @contents directive */
extern char *contents_filename;
/* the file where we found the @shortcontents directive */
extern char *shortcontents_filename;
/* Structure to hold one entry for the toc. */
typedef struct toc_entry_elt {
char *name;
char *containing_node; /* Name of node containing this section. */
int number; /* counting number from 0...n independent from
chapter/section can be used for anchors or
references to it. */
int level; /* level: chapter, section, subsection... */
} TOC_ENTRY_ELT;
/* all routines which have relationship with TOC should start with
toc_ (this is a kind of name-space) */
extern int toc_add_entry (); /* return the number for the toc-entry */
extern void toc_free ();
extern char *toc_find_section_of_node ();
extern void cm_contents (), cm_shortcontents ();
#endif /* not TOC_H */

View File

@ -2,3 +2,9 @@ Assorted Texinfo-related programs and scripts.
texindex, texi2dvi, and install-info get installed.
The other items here are for your amusement and/or hacking pleasure.
You may also be interested in a2ps, an ASCII->PostScript program which
has a Texinfo style option. Available from
http://www.inf.enst.fr/~demaille/a2ps/ and
ftp://ftp.enst.fr/pub/unix/a2ps/.

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,7 @@
/* Prepare TeX index dribble output into an actual index.
$Id: texindex.c,v 1.22 1998/02/22 23:00:09 karl Exp $
/* Process TeX index dribble output into an actual index.
$Id: texindex.c,v 1.34 1999/08/06 17:03:14 karl Exp $
Copyright (C) 1987, 91, 92, 96, 97, 98 Free Software Foundation, Inc.
Copyright (C) 1987, 91, 92, 96, 97, 98, 99 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
@ -20,6 +20,8 @@
#include "system.h"
#include <getopt.h>
static char *program_name = "texindex";
#if defined (emacs)
# include "../src/config.h"
/* Some s/os.h files redefine these. */
@ -34,19 +36,8 @@
#define memset(ptr, ignore, count) bzero (ptr, count)
#endif
char *mktemp ();
#if defined (VMS)
# include <file.h>
# define TI_NO_ERROR ((1 << 28) | 1)
# define TI_FATAL_ERROR ((1 << 28) | 4)
# define unlink delete
#else /* !VMS */
# define TI_NO_ERROR 0
# define TI_FATAL_ERROR 1
#endif /* !VMS */
#if !defined (SEEK_SET)
# define SEEK_SET 0
# define SEEK_CUR 1
@ -124,11 +115,7 @@ char *text_base;
/* Nonzero means do not delete tempfiles -- for debugging. */
int keep_tempfiles;
/* The name this program was run with. */
char *program_name;
/* Forward declarations of functions in this file. */
void decode_command ();
void sort_in_core ();
void sort_offline ();
@ -149,9 +136,7 @@ void fatal ();
void error ();
void *xmalloc (), *xrealloc ();
char *concat ();
char *maketempname ();
void flush_tempfiles ();
char *tempcopy ();
#define MAX_IN_CORE_SORT 500000
@ -165,12 +150,6 @@ main (argc, argv)
tempcount = 0;
last_deleted_tempcount = 0;
program_name = strrchr (argv[0], '/');
if (program_name != (char *)NULL)
program_name++;
else
program_name = argv[0];
#ifdef HAVE_SETLOCALE
/* Set locale via LC_ALL. */
setlocale (LC_ALL, "");
@ -208,14 +187,26 @@ main (argc, argv)
for (i = 0; i < num_infiles; i++)
{
int desc;
long ptr;
off_t ptr;
char *outfile;
struct stat instat;
desc = open (infiles[i], O_RDONLY, 0);
if (desc < 0)
pfatal_with_name (infiles[i]);
if (stat (infiles[i], &instat))
pfatal_with_name (infiles[i]);
if (S_ISDIR (instat.st_mode))
{
#ifdef EISDIR
errno = EISDIR;
#endif
pfatal_with_name (infiles[i]);
}
lseek (desc, (off_t) 0, SEEK_END);
ptr = (long) lseek (desc, (off_t) 0, SEEK_CUR);
ptr = (off_t) lseek (desc, (off_t) 0, SEEK_CUR);
close (desc);
@ -233,8 +224,8 @@ main (argc, argv)
}
flush_tempfiles (tempcount);
exit (TI_NO_ERROR);
xexit (0);
return 0; /* Avoid bogus warnings. */
}
@ -249,6 +240,8 @@ typedef struct
} TEXINDEX_OPTION;
TEXINDEX_OPTION texindex_options[] = {
{ "--help", "-h", (int *)NULL, 0, (char *)NULL,
N_("display this help and exit") },
{ "--keep", "-k", &keep_tempfiles, 1, (char *)NULL,
N_("keep temporary files around after processing") },
{ "--no-keep", 0, &keep_tempfiles, 0, (char *)NULL,
@ -257,8 +250,6 @@ TEXINDEX_OPTION texindex_options[] = {
N_("send output to FILE") },
{ "--version", (char *)NULL, (int *)NULL, 0, (char *)NULL,
N_("display version information and exit") },
{ "--help", "-h", (int *)NULL, 0, (char *)NULL,
N_("display this help and exit") },
{ (char *)NULL, (char *)NULL, (int *)NULL, 0, (char *)NULL }
};
@ -272,11 +263,15 @@ usage (result_value)
fprintf (f, _("Usage: %s [OPTION]... FILE...\n"), program_name);
fprintf (f, _("Generate a sorted index for each TeX output FILE.\n"));
/* Avoid trigraph nonsense. */
fprintf (f, _("Usually FILE... is `foo.??\' for a document `foo.texi'.\n"));
fprintf (f,
_("Usually FILE... is specified as `foo.%c%c\' for a document `foo.texi'.\n"),
'?', '?'); /* avoid trigraph in cat-id-tbl.c */
fprintf (f, _("\nOptions:\n"));
for (i = 0; texindex_options[i].long_name; i++)
{
putc (' ', f);
if (texindex_options[i].short_name)
fprintf (f, "%s, ", texindex_options[i].short_name);
@ -287,9 +282,12 @@ usage (result_value)
fprintf (f, "\t%s\n", _(texindex_options[i].doc_string));
}
puts (_("\nEmail bug reports to bug-texinfo@gnu.org."));
fputs (_("\n\
Email bug reports to bug-texinfo@gnu.org,\n\
general questions and discussion to help-texinfo@gnu.org.\n\
"), f);
exit (result_value);
xexit (result_value);
}
/* Decode the command line arguments to set the parameter variables
@ -307,15 +305,14 @@ decode_command (argc, argv)
/* Store default values into parameter variables. */
tempdir = getenv ("TMPDIR");
#ifdef VMS
if (tempdir == NULL)
tempdir = "sys$scratch:";
#else
tempdir = getenv ("TEMP");
if (tempdir == NULL)
tempdir = "/tmp/";
tempdir = getenv ("TMP");
if (tempdir == NULL)
tempdir = DEFAULT_TMPDIR;
else
tempdir = concat (tempdir, "/", "");
#endif
keep_tempfiles = 0;
@ -335,12 +332,13 @@ decode_command (argc, argv)
if (strcmp (arg, "--version") == 0)
{
printf ("texindex (GNU %s) %s\n", PACKAGE, VERSION);
printf (_("Copyright (C) %s Free Software Foundation, Inc.\n\
puts ("");
printf (_("Copyright (C) %s 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.\n"),
"1998");
exit (0);
"1999");
xexit (0);
}
else if ((strcmp (arg, "--keep") == 0) ||
(strcmp (arg, "-k") == 0))
@ -383,12 +381,12 @@ For more information about these matters, see the files named COPYING.\n"),
/* Return a name for a temporary file. */
char *
static char *
maketempname (count)
int count;
{
char tempsuffix[10];
sprintf (tempsuffix, "%d", count);
sprintf (tempsuffix, ".%d", count);
return concat (tempdir, tempbase, tempsuffix);
}
@ -404,36 +402,6 @@ flush_tempfiles (to_count)
unlink (maketempname (++last_deleted_tempcount));
}
/* Copy the input file open on IDESC into a temporary file
and return the temporary file name. */
#define BUFSIZE 1024
char *
tempcopy (idesc)
int idesc;
{
char *outfile = maketempname (++tempcount);
int odesc;
char buffer[BUFSIZE];
odesc = open (outfile, O_WRONLY | O_CREAT, 0666);
if (odesc < 0)
pfatal_with_name (outfile);
while (1)
{
int nread = read (idesc, buffer, BUFSIZE);
write (odesc, buffer, nread);
if (!nread)
break;
}
close (odesc);
return outfile;
}
/* Compare LINE1 and LINE2 according to the specified set of keyfields. */
@ -894,7 +862,7 @@ void
sort_offline (infile, nfiles, total, outfile)
char *infile;
int nfiles;
long total;
off_t total;
char *outfile;
{
/* More than enough. */
@ -993,7 +961,7 @@ sort_offline (infile, nfiles, total, outfile)
void
sort_in_core (infile, total, outfile)
char *infile;
long total;
off_t total;
char *outfile;
{
char **nextline;
@ -1251,7 +1219,7 @@ indexify (line, ostream)
pagenumber = find_braced_pos (line, 1, 0, 0);
pagelength = find_braced_end (pagenumber) - pagenumber;
if (pagelength == 0)
abort ();
fatal (_("No page number in %s"), line);
primary = find_braced_pos (line, 2, 0, 0);
primarylength = find_braced_end (primary) - primary;
@ -1627,7 +1595,7 @@ fatal (format, arg)
char *format, *arg;
{
error (format, arg);
exit (TI_FATAL_ERROR);
xexit (1);
}
/* Print error message. FORMAT is printf control string, ARG is arg for it. */
@ -1661,7 +1629,7 @@ pfatal_with_name (name)
s = strerror (errno);
printf ("%s: ", program_name);
printf (_("%s; for file `%s'.\n"), s, name);
exit (TI_FATAL_ERROR);
xexit (1);
}
/* Return a newly-allocated string whose contents concatenate those of
@ -1682,21 +1650,6 @@ concat (s1, s2, s3)
return result;
}
#if !defined (HAVE_STRERROR)
extern char *sys_errlist[];
extern int sys_nerr;
char *
strerror (num)
int num;
{
if (num >= sys_nerr)
return ("");
else
return (sys_errlist[num]);
}
#endif /* !HAVE_STRERROR */
#if !defined (HAVE_STRCHR)
char *
strrchr (string, character)
@ -1712,50 +1665,3 @@ strrchr (string, character)
return ((char *)NULL);
}
#endif /* HAVE_STRCHR */
void
memory_error (callers_name, bytes_wanted)
char *callers_name;
int bytes_wanted;
{
char printable_string[80];
sprintf (printable_string,
_("Virtual memory exhausted in %s ()! Needed %d bytes."),
callers_name, bytes_wanted);
error (printable_string);
abort ();
}
/* Just like malloc, but kills the program in case of fatal error. */
void *
xmalloc (nbytes)
int nbytes;
{
void *temp = (void *) malloc (nbytes);
if (nbytes && temp == (void *)NULL)
memory_error ("xmalloc", nbytes);
return (temp);
}
/* Like realloc (), but barfs if there isn't enough memory. */
void *
xrealloc (pointer, nbytes)
void *pointer;
int nbytes;
{
void *temp;
if (!pointer)
temp = (void *)xmalloc (nbytes);
else
temp = (void *)realloc (pointer, nbytes);
if (nbytes && !temp)
memory_error ("xrealloc", nbytes);
return (temp);
}