[llvm-commits] CVS: llvm/test/Programs/MultiSource/Applications/treecc/doc/Makefile.am Makefile.in binary_readme.txt essay.html extending.txt mkdoc mkhtml mkpdf texinfo.tex treecc.1 treecc.texi
John Criswell
criswell at cs.uiuc.edu
Tue Apr 6 12:56:06 PDT 2004
Changes in directory llvm/test/Programs/MultiSource/Applications/treecc/doc:
Makefile.am added (r1.1)
Makefile.in added (r1.1)
binary_readme.txt added (r1.1)
essay.html added (r1.1)
extending.txt added (r1.1)
mkdoc added (r1.1)
mkhtml added (r1.1)
mkpdf added (r1.1)
texinfo.tex added (r1.1)
treecc.1 added (r1.1)
treecc.texi added (r1.1)
---
Log message:
Adding in documentation for good measure.
---
Diffs of the changes: (+9697 -0)
Index: llvm/test/Programs/MultiSource/Applications/treecc/doc/Makefile.am
diff -c /dev/null llvm/test/Programs/MultiSource/Applications/treecc/doc/Makefile.am:1.1
*** /dev/null Tue Apr 6 12:54:55 2004
--- llvm/test/Programs/MultiSource/Applications/treecc/doc/Makefile.am Tue Apr 6 12:54:44 2004
***************
*** 0 ****
--- 1,3 ----
+ man_MANS = treecc.1
+ info_TEXINFOS = treecc.texi
+ CLEANFILES = treecc.info treecc.info-1 treecc.info-2 treecc.info-3
Index: llvm/test/Programs/MultiSource/Applications/treecc/doc/Makefile.in
diff -c /dev/null llvm/test/Programs/MultiSource/Applications/treecc/doc/Makefile.in:1.1
*** /dev/null Tue Apr 6 12:54:55 2004
--- llvm/test/Programs/MultiSource/Applications/treecc/doc/Makefile.in Tue Apr 6 12:54:44 2004
***************
*** 0 ****
--- 1,360 ----
+ # Makefile.in generated automatically by automake 1.4 from Makefile.am
+
+ # Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc.
+ # This Makefile.in is free software; the Free Software Foundation
+ # gives unlimited permission to copy and/or distribute it,
+ # with or without modifications, as long as this notice is preserved.
+
+ # This program is distributed in the hope that it will be useful,
+ # but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+ # even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ # PARTICULAR PURPOSE.
+
+
+ SHELL = @SHELL@
+
+ srcdir = @srcdir@
+ top_srcdir = @top_srcdir@
+ VPATH = @srcdir@
+ prefix = @prefix@
+ exec_prefix = @exec_prefix@
+
+ bindir = @bindir@
+ sbindir = @sbindir@
+ libexecdir = @libexecdir@
+ datadir = @datadir@
+ sysconfdir = @sysconfdir@
+ sharedstatedir = @sharedstatedir@
+ localstatedir = @localstatedir@
+ libdir = @libdir@
+ infodir = @infodir@
+ mandir = @mandir@
+ includedir = @includedir@
+ oldincludedir = /usr/include
+
+ DESTDIR =
+
+ pkgdatadir = $(datadir)/@PACKAGE@
+ pkglibdir = $(libdir)/@PACKAGE@
+ pkgincludedir = $(includedir)/@PACKAGE@
+
+ top_builddir = ..
+
+ ACLOCAL = @ACLOCAL@
+ AUTOCONF = @AUTOCONF@
+ AUTOMAKE = @AUTOMAKE@
+ AUTOHEADER = @AUTOHEADER@
+
+ INSTALL = @INSTALL@
+ INSTALL_PROGRAM = @INSTALL_PROGRAM@ $(AM_INSTALL_PROGRAM_FLAGS)
+ INSTALL_DATA = @INSTALL_DATA@
+ INSTALL_SCRIPT = @INSTALL_SCRIPT@
+ transform = @program_transform_name@
+
+ NORMAL_INSTALL = :
+ PRE_INSTALL = :
+ POST_INSTALL = :
+ NORMAL_UNINSTALL = :
+ PRE_UNINSTALL = :
+ POST_UNINSTALL = :
+ build_alias = @build_alias@
+ build_triplet = @build@
+ host_alias = @host_alias@
+ host_triplet = @host@
+ target_alias = @target_alias@
+ target_triplet = @target@
+ AWK = @AWK@
+ CC = @CC@
+ EXEEXT = @EXEEXT@
+ EXPR_CPP = @EXPR_CPP@
+ LEX = @LEX@
+ LN_S = @LN_S@
+ MAINT = @MAINT@
+ MAKEINFO = @MAKEINFO@
+ OBJEXT = @OBJEXT@
+ PACKAGE = @PACKAGE@
+ RANLIB = @RANLIB@
+ VERSION = @VERSION@
+ YACC = @YACC@
+
+ man_MANS = treecc.1
+ info_TEXINFOS = treecc.texi
+ CLEANFILES = treecc.info treecc.info-1 treecc.info-2 treecc.info-3
+ mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+ CONFIG_HEADER = ../config.h
+ CONFIG_CLEAN_FILES =
+ TEXI2DVI = texi2dvi
+ INFO_DEPS = treecc.info
+ DVIS = treecc.dvi
+ TEXINFOS = treecc.texi
+ man1dir = $(mandir)/man1
+ MANS = $(man_MANS)
+
+ NROFF = nroff
+ DIST_COMMON = Makefile.am Makefile.in texinfo.tex
+
+
+ DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
+
+ TAR = gtar
+ GZIP_ENV = --best
+ all: all-redirect
+ .SUFFIXES:
+ .SUFFIXES: .dvi .info .ps .texi .texinfo .txi
+ $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
+ cd $(top_srcdir) && $(AUTOMAKE) --gnu doc/Makefile
+
+ Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status $(BUILT_SOURCES)
+ cd $(top_builddir) \
+ && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
+
+
+ treecc.info: treecc.texi
+ treecc.dvi: treecc.texi
+
+
+ DVIPS = dvips
+
+ .texi.info:
+ @cd $(srcdir) && rm -f $@ $@-[0-9] $@-[0-9][0-9]
+ cd $(srcdir) \
+ && $(MAKEINFO) `echo $< | sed 's,.*/,,'`
+
+ .texi.dvi:
+ TEXINPUTS=.:$$TEXINPUTS \
+ MAKEINFO='$(MAKEINFO) -I $(srcdir)' $(TEXI2DVI) $<
+
+ .texi:
+ @cd $(srcdir) && rm -f $@ $@-[0-9] $@-[0-9][0-9]
+ cd $(srcdir) \
+ && $(MAKEINFO) `echo $< | sed 's,.*/,,'`
+
+ .texinfo.info:
+ @cd $(srcdir) && rm -f $@ $@-[0-9] $@-[0-9][0-9]
+ cd $(srcdir) \
+ && $(MAKEINFO) `echo $< | sed 's,.*/,,'`
+
+ .texinfo:
+ @cd $(srcdir) && rm -f $@ $@-[0-9] $@-[0-9][0-9]
+ cd $(srcdir) \
+ && $(MAKEINFO) `echo $< | sed 's,.*/,,'`
+
+ .texinfo.dvi:
+ TEXINPUTS=.:$$TEXINPUTS \
+ MAKEINFO='$(MAKEINFO) -I $(srcdir)' $(TEXI2DVI) $<
+
+ .txi.info:
+ @cd $(srcdir) && rm -f $@ $@-[0-9] $@-[0-9][0-9]
+ cd $(srcdir) \
+ && $(MAKEINFO) `echo $< | sed 's,.*/,,'`
+
+ .txi.dvi:
+ TEXINPUTS=.:$$TEXINPUTS \
+ MAKEINFO='$(MAKEINFO) -I $(srcdir)' $(TEXI2DVI) $<
+
+ .txi:
+ @cd $(srcdir) && rm -f $@ $@-[0-9] $@-[0-9][0-9]
+ cd $(srcdir) \
+ && $(MAKEINFO) `echo $< | sed 's,.*/,,'`
+ .dvi.ps:
+ $(DVIPS) $< -o $@
+
+ install-info-am: $(INFO_DEPS)
+ @$(NORMAL_INSTALL)
+ $(mkinstalldirs) $(DESTDIR)$(infodir)
+ @list='$(INFO_DEPS)'; \
+ for file in $$list; do \
+ d=$(srcdir); \
+ for ifile in `cd $$d && echo $$file $$file-[0-9] $$file-[0-9][0-9]`; do \
+ if test -f $$d/$$ifile; then \
+ echo " $(INSTALL_DATA) $$d/$$ifile $(DESTDIR)$(infodir)/$$ifile"; \
+ $(INSTALL_DATA) $$d/$$ifile $(DESTDIR)$(infodir)/$$ifile; \
+ else : ; fi; \
+ done; \
+ done
+ @$(POST_INSTALL)
+ @if $(SHELL) -c 'install-info --version | sed 1q | fgrep -s -v -i debian' >/dev/null 2>&1; then \
+ list='$(INFO_DEPS)'; \
+ for file in $$list; do \
+ echo " install-info --info-dir=$(DESTDIR)$(infodir) $(DESTDIR)$(infodir)/$$file";\
+ install-info --info-dir=$(DESTDIR)$(infodir) $(DESTDIR)$(infodir)/$$file || :;\
+ done; \
+ else : ; fi
+
+ uninstall-info:
+ $(PRE_UNINSTALL)
+ @if $(SHELL) -c 'install-info --version | sed 1q | fgrep -s -v -i debian' >/dev/null 2>&1; then \
+ ii=yes; \
+ else ii=; fi; \
+ list='$(INFO_DEPS)'; \
+ for file in $$list; do \
+ test -z "$ii" \
+ || install-info --info-dir=$(DESTDIR)$(infodir) --remove $$file; \
+ done
+ @$(NORMAL_UNINSTALL)
+ list='$(INFO_DEPS)'; \
+ for file in $$list; do \
+ (cd $(DESTDIR)$(infodir) && rm -f $$file $$file-[0-9] $$file-[0-9][0-9]); \
+ done
+
+ dist-info: $(INFO_DEPS)
+ list='$(INFO_DEPS)'; \
+ for base in $$list; do \
+ d=$(srcdir); \
+ for file in `cd $$d && eval echo $$base*`; do \
+ test -f $(distdir)/$$file \
+ || ln $$d/$$file $(distdir)/$$file 2> /dev/null \
+ || cp -p $$d/$$file $(distdir)/$$file; \
+ done; \
+ done
+
+ mostlyclean-aminfo:
+ -rm -f treecc.aux treecc.cp treecc.cps treecc.dvi treecc.fn treecc.fns \
+ treecc.ky treecc.kys treecc.ps treecc.log treecc.pg \
+ treecc.toc treecc.tp treecc.tps treecc.vr treecc.vrs \
+ treecc.op treecc.tr treecc.cv treecc.cn
+
+ clean-aminfo:
+
+ distclean-aminfo:
+
+ maintainer-clean-aminfo:
+ cd $(srcdir) && for i in $(INFO_DEPS); do \
+ rm -f $$i; \
+ if test "`echo $$i-[0-9]*`" != "$$i-[0-9]*"; then \
+ rm -f $$i-[0-9]*; \
+ fi; \
+ done
+
+ install-man1:
+ $(mkinstalldirs) $(DESTDIR)$(man1dir)
+ @list='$(man1_MANS)'; \
+ l2='$(man_MANS)'; for i in $$l2; do \
+ case "$$i" in \
+ *.1*) list="$$list $$i" ;; \
+ esac; \
+ done; \
+ for i in $$list; do \
+ if test -f $(srcdir)/$$i; then file=$(srcdir)/$$i; \
+ else file=$$i; fi; \
+ ext=`echo $$i | sed -e 's/^.*\\.//'`; \
+ inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \
+ inst=`echo $$inst | sed '$(transform)'`.$$ext; \
+ echo " $(INSTALL_DATA) $$file $(DESTDIR)$(man1dir)/$$inst"; \
+ $(INSTALL_DATA) $$file $(DESTDIR)$(man1dir)/$$inst; \
+ done
+
+ uninstall-man1:
+ @list='$(man1_MANS)'; \
+ l2='$(man_MANS)'; for i in $$l2; do \
+ case "$$i" in \
+ *.1*) list="$$list $$i" ;; \
+ esac; \
+ done; \
+ for i in $$list; do \
+ ext=`echo $$i | sed -e 's/^.*\\.//'`; \
+ inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \
+ inst=`echo $$inst | sed '$(transform)'`.$$ext; \
+ echo " rm -f $(DESTDIR)$(man1dir)/$$inst"; \
+ rm -f $(DESTDIR)$(man1dir)/$$inst; \
+ done
+ install-man: $(MANS)
+ @$(NORMAL_INSTALL)
+ $(MAKE) $(AM_MAKEFLAGS) install-man1
+ uninstall-man:
+ @$(NORMAL_UNINSTALL)
+ $(MAKE) $(AM_MAKEFLAGS) uninstall-man1
+ tags: TAGS
+ TAGS:
+
+
+ distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir)
+
+ subdir = doc
+
+ distdir: $(DISTFILES)
+ here=`cd $(top_builddir) && pwd`; \
+ top_distdir=`cd $(top_distdir) && pwd`; \
+ distdir=`cd $(distdir) && pwd`; \
+ cd $(top_srcdir) \
+ && $(AUTOMAKE) --include-deps --build-dir=$$here --srcdir-name=$(top_srcdir) --output-dir=$$top_distdir --gnu doc/Makefile
+ @for file in $(DISTFILES); do \
+ d=$(srcdir); \
+ if test -d $$d/$$file; then \
+ cp -pr $$d/$$file $(distdir)/$$file; \
+ else \
+ test -f $(distdir)/$$file \
+ || ln $$d/$$file $(distdir)/$$file 2> /dev/null \
+ || cp -p $$d/$$file $(distdir)/$$file || :; \
+ fi; \
+ done
+ $(MAKE) $(AM_MAKEFLAGS) top_distdir="$(top_distdir)" distdir="$(distdir)" dist-info
+ info-am: $(INFO_DEPS)
+ info: info-am
+ dvi-am: $(DVIS)
+ dvi: dvi-am
+ check-am: all-am
+ check: check-am
+ installcheck-am:
+ installcheck: installcheck-am
+ install-exec-am:
+ install-exec: install-exec-am
+
+ install-data-am: install-info-am install-man
+ install-data: install-data-am
+
+ install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+ install: install-am
+ uninstall-am: uninstall-info uninstall-man
+ uninstall: uninstall-am
+ all-am: Makefile $(INFO_DEPS) $(MANS)
+ all-redirect: all-am
+ install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install
+ installdirs:
+ $(mkinstalldirs) $(DESTDIR)$(infodir) $(DESTDIR)$(mandir)/man1
+
+
+ mostlyclean-generic:
+
+ clean-generic:
+ -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
+
+ distclean-generic:
+ -rm -f Makefile $(CONFIG_CLEAN_FILES)
+ -rm -f config.cache config.log stamp-h stamp-h[0-9]*
+
+ maintainer-clean-generic:
+ mostlyclean-am: mostlyclean-aminfo mostlyclean-generic
+
+ mostlyclean: mostlyclean-am
+
+ clean-am: clean-aminfo clean-generic mostlyclean-am
+
+ clean: clean-am
+
+ distclean-am: distclean-aminfo distclean-generic clean-am
+
+ distclean: distclean-am
+
+ maintainer-clean-am: maintainer-clean-aminfo maintainer-clean-generic \
+ distclean-am
+ @echo "This command is intended for maintainers to use;"
+ @echo "it deletes files that may require special tools to rebuild."
+
+ maintainer-clean: maintainer-clean-am
+
+ .PHONY: install-info-am uninstall-info mostlyclean-aminfo \
+ distclean-aminfo clean-aminfo maintainer-clean-aminfo install-man1 \
+ uninstall-man1 install-man uninstall-man tags distdir info-am info \
+ dvi-am dvi check check-am installcheck-am installcheck install-exec-am \
+ install-exec install-data-am install-data install-am install \
+ uninstall-am uninstall all-redirect all-am all installdirs \
+ mostlyclean-generic distclean-generic clean-generic \
+ maintainer-clean-generic clean mostlyclean distclean maintainer-clean
+
+
+ # Tell versions [3.59,3.63) of GNU make to not export all variables.
+ # Otherwise a system limit (for SysV at least) may be exceeded.
+ .NOEXPORT:
Index: llvm/test/Programs/MultiSource/Applications/treecc/doc/binary_readme.txt
diff -c /dev/null llvm/test/Programs/MultiSource/Applications/treecc/doc/binary_readme.txt:1.1
*** /dev/null Tue Apr 6 12:54:55 2004
--- llvm/test/Programs/MultiSource/Applications/treecc/doc/binary_readme.txt Tue Apr 6 12:54:44 2004
***************
*** 0 ****
--- 1,58 ----
+
+ Tree Compiler-Compiler
+ ======================
+
+ The treecc program is designed to assist in the development of compilers
+ and other language-based tools. It manages the generation of code to handle
+ abstract syntax trees and operations upon the trees.
+
+ A fuller account of why treecc exists and what it can be used for can
+ be found in the HTML documentation within the "doc\html" subdirectory,
+ and in the introductory article "doc\intro.html".
+
+ Installing Treecc
+ -----------------
+
+ The zip file should be unpacked in a new directory on your hard drive.
+ For example, "C:\Treecc". Then add "C:\Treecc\bin" to your PATH to
+ be able to run the tool.
+
+ To uninstall treecc, simply delete the entire contents of the install
+ directory.
+
+ Obtaining the source and more recent versions
+ ---------------------------------------------
+
+ The latest version of treecc can be obtained from the following Web site:
+
+ http://www.southern-storm.com.au/treecc/
+
+ The source code is also available from this site, under the terms of the
+ GNU General Public License.
+
+ The authors can be contacted via e-mail at the following address:
+
+ treecc at southern-storm.com.au
+
+ Copyright Considerations
+ ------------------------
+
+ Treecc is distributed under the terms of the GNU General Public License.
+ A copy of this can be found in the "COPYING" file.
+
+ However, it is not our intention to restrict the use of treecc to only
+ free software providers. Use by commercial software vendors is welcome.
+
+ When you use treecc on your own input files to generate source code as
+ output, the resulting source code files are also owned by you. You may
+ re-distribute unmodified copies of these output source files, and any
+ binaries derived from them, in any way you see fit. Executing treecc on
+ your input files does not automatically incur obligations under the GPL.
+
+ If you modify treecc itself, and generate new output files as a result,
+ then you must release all source modifications to treecc with your program
+ so that other users can benefit from your changes under the terms of the GPL.
+
+ Contact the authors if you have any questions regarding the above.
+ It is our intention to allow the same amount of access to treecc output
+ files as is currently available using the GNU Bison and Flex programs.
Index: llvm/test/Programs/MultiSource/Applications/treecc/doc/essay.html
diff -c /dev/null llvm/test/Programs/MultiSource/Applications/treecc/doc/essay.html:1.1
*** /dev/null Tue Apr 6 12:54:55 2004
--- llvm/test/Programs/MultiSource/Applications/treecc/doc/essay.html Tue Apr 6 12:54:44 2004
***************
*** 0 ****
--- 1,596 ----
+ <html>
+ <head>
+ <title>Treecc: An Aspect-Oriented Approach to Writing Compilers</title>
+ </head>
+ <body bgcolor="#ffffff">
+ <h1>Treecc: An Aspect-Oriented Approach to Writing Compilers</h1>
+
+ Rhys Weatherley, <a href="mailto:rweather at southern-storm.com.au">rweather at southern-storm.com.au</a>.<p>
+
+ Copyright © 2001, 2002 Rhys Weatherley<br>
+ Verbatim copying and distribution of this entire article is permitted
+ in any medium, provided this copyright notice is preserved.<p>
+
+ This is a copy of an article that was published in
+ <a href="http://www.rons.net.cn/english/FSM/issue02">Issue 2</a>
+ of Free Software Magazine.<p>
+
+ <h2>1. Introduction</h2>
+
+ The C# compiler in Portable.NET <a href="#pnetref">[1]</a> is built on top
+ of the "Tree Compiler Compiler" (treecc) utility program.
+ Treecc <a href="#treeccref">[2]</a> is distributed as Free Software
+ under the terms of the GNU General Public License.<p>
+
+ This article provides some background of why treecc came about. It discusses
+ two common compiler implementation techniques, and the reasons why they
+ often fail to manage the complexity of large programming languages like C#.<p>
+
+ We then discuss a new programming technique called "Aspect-Oriented
+ Programming". Treecc is an example of applying this technique to managing
+ the complexity of compiler construction.<p>
+
+ <h2>2. Patterns and Compiler Design</h2>
+
+ Compiler writing is generally seen as a black art, but in reality it isn't
+ all that hard. The basic compilation steps are:<p>
+
+ <ol>
+ <li>Convert the program into an abstract syntax tree.</li>
+ <li>Perform type-checking and semantic analysis on the tree.</li>
+ <li>Rearrange the tree to perform optimisations.</li>
+ <li>Convert the tree into the target code.</li>
+ </ol>
+
+ The difficulty in writing compilers is not the steps involved, but rather
+ the sheer number of tiny little details to keep straight. Modern languages
+ contain large numbers of operators, which are all very similar, but slightly
+ different:<p>
+
+ <blockquote>
+ Add, substract, multiply, divide, remainder, shift left, shift right,
+ shift right unsigned, bitwise and, bitwise or, exclusive-or, negate,
+ bitwise not, logical not, logical and, logical or, ...
+ </blockquote>
+
+ And that's just the operators. Introduce statements, arrays, type coercion,
+ method invocation, and class definition, and it becomes very easy to
+ forget something amongst the forest of code.<p>
+
+ In an attempt to control this complexity, two common pattern-based
+ approaches have arisen over the years: Inheritance and Visitor.<p>
+
+ The inheritance pattern can be characterised as follows:<p>
+
+ <ol>
+ <li>Declare a node type for every syntactic element in the language.
+ All types ultimately inherit from "<code>Node</code>".</li>
+ <li>Declare virtual methods in "<code>Node</code>" for
+ operations on node types: semantic analysis, optimization,
+ code generation, etc.</li>
+ <li>Override the virtuals in sub-classes to provide the
+ compiler implementation.</li>
+ </ol><p>
+
+ The visitor pattern can be characterised as follows:<p>
+
+ <ol>
+ <li>Declare a node type for every syntactic element in the language.
+ All types ultimately inherit from "<code>Node</code>".</li>
+ <li>Declare a "<code>Visitor</code>" class with abstract virtual
+ methods such as "<code>VisitAdd</code>", "<code>VisitSub</code>",
+ "<code>VisitIf</code>", "<code>VisitFunction</code>",
+ etc for all of the node types.</li>
+ <li>Define a "walking procedure" over "<code>Node</code>" objects for
+ walking around a syntax tree, making callbacks on a supplied
+ visitor object.</li>
+ <li>Create multiple classes that inherit from "<code>Visitor</code>",
+ one for each operation. Implement the "<code>Visit*</code>"
+ functions for that type of operation.</li>
+ </ol>
+
+ In the following sections, we will explore why these two patterns often
+ fail to manage compiler complexity, even when the programmer applies them
+ rigorously.<p>
+
+ <h2>3. The implementation language is your worst enemy</h2>
+
+ We will start with the inheritance pattern. Consider that we've written
+ the following C# code during the "declare all the node types" phase of
+ the project:<p>
+
+ <blockquote>
+ <pre>public class UnaryExpression : Expression
+ {
+ protected Expression expr;
+
+ public UnaryExpression(Expression _expr) { expr = _expr; }
+ }
+
+ public class NegateExpression : UnaryExpression
+ {
+ public NegateExpression(Expression _expr) : base(_expr) {}
+ }
+
+ public class UnaryPlusExpression : UnaryExpression
+ {
+ public UnaryPlusExpression(Expression _expr) : base(_expr) {}
+ }
+
+ public class BitwiseNotExpression : UnaryExpression
+ {
+ public BitwiseNotExpression(Expression _expr) : base(_expr) {}
+ }</pre>
+ </blockquote>
+
+ We continue this process for several hundred other node types, gradually
+ building up the entire syntax tree. This will probably take several weeks
+ to complete for a substantial language like C#, assuming that we are writing
+ the parser alongside the node types.<p>
+
+ We now want to go in and implement type-checking, so we modify the
+ "<code>UnaryExpression</code>" class as follows:<p>
+
+ <blockquote>
+ <pre>public class UnaryExpression : Expression
+ {
+ protected Expression expr;
+
+ public UnaryExpression(Expression _expr) { expr = _expr; }
+
+ public override LanguageType TypeCheck()
+ {
+ LanguageType type = expr.TypeCheck();
+ if(type.IsInteger() || type.IsFloat())
+ {
+ return type;
+ }
+ throw new TypeCheckException();
+ }
+ }</pre>
+ </blockquote>
+
+ We've put the common unary expression type-checking code in a common base
+ class. This makes it easier to maintain because there is only one copy.
+ We continue the process over the next few weeks and months for all the
+ other operators, statements, and declarations in the language. So far,
+ so good.<p>
+
+ Unfortunately, we've made a mistake. The "<code>BitwiseNot</code>"
+ operator is only legal on integer values; not floating-point.<p>
+
+ But will we find this bug? It was several weeks ago when we first wrote
+ the "<code>BitwiseNotExpression</code>" class, and we have since forgotten
+ all about it. It may even have been written by another programmer on the
+ team, who has also forgotten all about it. When we build our compiler,
+ we don't get any errors because the implemention language is perfectly
+ happy with the above code.<p>
+
+ Surely testing will find it? We are building a test suite alongside
+ the code, right? Unfortunately, that doesn't help either. The test
+ suite for a major language will be at least as complex as the compiler
+ itself, and so there is always the temptation to abstract common tests
+ into common test classes. We've just shifted the bug into the test suite
+ and given ourselves a false sense of security.<p>
+
+ So we keep coding for several more months, adding lots more code. And then
+ a really nasty bug pops up. The "<code>BitwiseNot</code>" operator is acting
+ strangely, and we have no idea why. The system is now so complex, with
+ so many common base classes implementing fallback defaults, that tracking
+ this down becomes very hard.<p>
+
+ The inheritance pattern has a fatal flaw. Adding a new operation entails
+ a very large maintainence burden, because hundreds of classes must be
+ modified. This is very error-prone, so we try to abstract details into
+ common base classes. But this introduces other errors.<p>
+
+ The problem basically boils down to semantic analysis: the implementation
+ language does not have enough knowledge about the application domain to
+ spot the problem and warn us about it. So it happily compiles the code
+ and leaves us to hang ourselves on the system's complexity later.
+ Programming languages are supposed to help us manage complexity, not
+ make the problem worse!<p>
+
+ I wrote a number of compilers using the inheritance approach, and every
+ single time the complexity killed me. I needed fallback defaults for
+ code maintainence reasons, but using fallbacks introduced massive numbers
+ of bugs. I was stuck.<p>
+
+ <h2>4. Design patterns aren't always what they are cracked up to be</h2>
+
+ After much hair-pulling, I searched <em>Design Patterns</em>
+ by Gamma, et al <a href="#gammaref">[3]</a>. "<em>Is there a better
+ way of doing this?</em>". Visitor patterns are the answer:
+ the book even gives a compiler example.<p>
+
+ Visitors solve the "<em>I forgot to implement the <code>BitwiseNot</code></em>"
+ problem. Because every node type has its own "<code>Visit*</code>" method,
+ we will get an error when we try to build the compiler without implementing
+ the operation for a node type. Of course, this assumes that we haven't
+ been dumb and implemented fallback defaults in the "<code>Visitor</code>"
+ base class.<p>
+
+ Instead of using virtual methods, we can implement visitors using
+ switch statements over node types. e.g.<p>
+
+ <blockquote>
+ <pre>switch(node.type)
+ {
+ case Negate: ...
+ case UnaryPlus: ...
+ case BinaryNot: ...
+ ...
+ }</pre>
+ </blockquote>
+
+ However, switch statements have a similar flaw to inheritance: the
+ implementation language will not warn us if we forget to put in
+ a case for every node type. It will happily fall out through the
+ "<code>default</code>" case with no warning. Tracking down these bugs
+ can be just as hard as tracking down inheritance fallback bugs.
+ Using virtual methods is "safer", if not quite as efficient.<p>
+
+ Unfortunately, there is a catch with visitors, as explained in
+ <em>Design Patterns</em>:<p>
+
+ <blockquote>
+ <em>Use the Visitor pattern when ... the classes defining the object
+ structure rarely change, but you often want to define new operations
+ over the structure. Changing the object structure classes requires
+ redefining the interface to all visitors, which is potentially
+ costly. If the object structure classes change often, then it's
+ probably better to define the operations in those classes.</em>
+ </blockquote>
+
+ During the early stages of writing a compiler, the node types change very
+ frequently. This activates the Achilles heel of the Visitor pattern,
+ and creates a maintainence nightmare. The book suggests that we should
+ use the inheritance approach to solve this problem.<p>
+
+ <h2>5. So which one do we use? Inheritance or Visitor?</h2>
+
+ The inheritance pattern becomes a problem when new operations are needed.
+ The solution is visitors. Visitors become a problem when new node types
+ are needed. The solution is inheritance.<p>
+
+ What we have is a situation that the design patterns gurus didn't
+ consider: if the set of nodes and operations are both changing rapidly,
+ then we will have problems no matter what we do.<p>
+
+ We need a solution that combines the strengths of both patterns without
+ the drawbacks of either. We want the implementation language to catch
+ us when we forget something, but we also want it to handle large numbers
+ of nodes and operations smoothly. We want to split different operations
+ into different modules, but also keep them closely associated with the
+ node type.<p>
+
+ None of the standard patterns provide this combination of functionality,
+ because none of the existing implementation languages support both styles
+ of program design at the same time.<p>
+
+ <h2>6. Aspect-Oriented Programming</h2>
+
+ A new field in language design has emerged in recent years called
+ "Aspect-Oriented Programming" (AOP). A good review of the field
+ can be found in the October 2001 issue of the "<em>Communications of
+ the ACM</em>" <a href="#aopref">[4]</a>, and on the AspectJ Web site
+ <a href="#aspectjref">[5]</a>.<p>
+
+ The following excerpt from the introduction to the AOP section in the
+ CACM issue describes the essential aspects of AOP, and the difference
+ between OOP and AOP:<p>
+
+ <blockquote>
+ <em>AOP is based on the idea that computer systems are better programmed
+ by separately specifying the various concerns (properties or areas
+ of interest) of a system and some description of their relationships,
+ and then relying on mechanisms in the underlying AOP environment to
+ weave or compose them together into a coherent program. ...
+ While the tendancy in OOP's is to find commonality among classes
+ and push it up the inheritance tree, AOP attempts to realize
+ scattered concerns as first-class elements, and eject them
+ horizontally from the object structure.</em>
+ </blockquote>
+
+ Aspect-orientation gives us some hope of solving our compiler
+ complexity problems. When we moved from the inheritance pattern
+ to the visitor pattern, we were attempting to eject the operations
+ horizontally. But it didn't quite work as well as we had hoped: the
+ intrinsic complexity of the set of nodes kept interfering. AOP
+ allows us to take the idea further, without re-introducing the problems
+ that visitors have.<p>
+
+ We can view each operation on node types (semantic analysis,
+ optimization, code generation, etc) as an "aspect" of the compiler's
+ construction. The AOP language weaves these aspects with the node
+ types to create the final compiler.<p>
+
+ However, we don't really want to invent a completely new programming
+ language for compiler construction. We would have to implement this
+ new language using all of the flawed techniques that makes writing
+ compilers hard. It's a classic chicken and egg problem: we don't
+ want to replace a buggy compiler with a buggy compiler implementation
+ language.<p>
+
+ We can strike a compromise, similar to that used by lex and yacc.
+ Those tools use a custom syntax for the difficult parts, and a
+ pre-existing underlying language (usually C) to implement everything
+ else. The code is expanded by the tool and then compiled with the
+ underlying language's compiler.<p>
+
+ Treecc uses a domain-specific aspect-oriented programming language for
+ declaring and managing nodes and operations, and uses an underlying language
+ to implement the body of the operations. C, C++, C#, or Java can be used
+ as the underlying language, depending upon your personal preference.<p>
+
+ Treecc is about 13,000 lines of code in size, which is relatively
+ easy to debug by hand.<p>
+
+ <em>Aside:</em> treecc does not support all of the AOP features that are
+ described in the literature. Treecc weaves together classes from multiple
+ method definitions. Other AOP languages can also weave together methods
+ from fragments in multiple aspects. We concentrated on those AOP features
+ that were useful for compiler construction. Other features could be
+ incorporated at a later date.<p>
+
+ <h2>7. Using Treecc to Beat Inheritance Bugs</h2>
+
+ Now that we've identified the problems of inheritance and visitor patterns
+ for compiler implementation, we will show how treecc helps the programmer
+ avoid these traps.<p>
+
+ The following is the treecc definition of our example node types:
+
+ <blockquote>
+ <pre>%option lang = "C#"
+
+ %node Expression %abstract %typedef
+
+ %node UnaryExpression Expression %abstract =
+ {
+ Expression expr;
+ }
+
+ %node NegateExpression UnaryExpression
+ %node UnaryPlusExpression UnaryExpression
+ %node BitwiseNotExpression UnaryExpression</pre>
+ </blockquote>
+
+ Treecc converts this into a number of C# classes, one for each
+ node type. It also inserts helper methods for testing the type
+ of a node and for tracking source line numbers. If the output language
+ is C or C++, treecc will also insert code for allocating large numbers
+ of nodes efficiently.<p>
+
+ The type-checking operation (or "aspect") is declared as follows:<p>
+
+ <blockquote>
+ <pre>%operation %virtual LanguageType TypeCheck(Expression e)
+
+ TypeCheck(NegateExpression),
+ TypeCheck(UnaryPlusExpression)
+ {
+ LanguageType type = e.expr.TypeCheck();
+ if(type.IsInteger() || type.IsFloat())
+ {
+ return type;
+ }
+ throw new TypeCheckException();
+ }
+
+ TypeCheck(BitwiseNotExpression)
+ {
+ LanguageType type = e.expr.TypeCheck();
+ if(type.IsInteger())
+ {
+ return type;
+ }
+ throw new TypeCheckException();
+ }</pre>
+ </blockquote>
+
+ We have not declared the operation to cover "<code>Expression</code>" or
+ "<code>UnaryExpression</code>". Instead, we list all of the applicable
+ subtypes explicitly. When treecc is run on the above file, it will check
+ that every non-abstract node type is handled by an operation case. If it finds
+ a missing type, it will report an error. Let's demonstrate that by adding a
+ new unary expression type:<p>
+
+ <blockquote><code>
+ %node LogicalNotExpression UnaryExpression<br>
+ <br>
+ eg.tc:17: node type `LogicalNotExpression' is not handled in operation `TypeCheck'<br>
+ </code></blockquote>
+
+ This is at the heart of treecc's power: it performs a large amount of
+ semantic analysis over the node types to determine if the programmer has
+ forgotten something. The programmer is notified of this early in
+ development process, when it is easier to fix the problem.<p>
+
+ As we discussed earlier, we want to implement common code in common
+ base classes to improve code sharing. However, this introduces
+ hard to find bugs. Treecc avoids the need to do this by allowing
+ the programmer to attach multiple cases to the same code block,
+ as in the case of "<code>NegateExpression</code>" and
+ "<code>UnaryPlusExpression</code>" above.<p>
+
+ An important feature of aspect-oriented languages is aspect modularity:
+ it should be possible to implement separate aspects in different parts
+ of the code. Treecc supports this by separating node and operation
+ definitions. Operations do not need to be implemented in the same
+ file as the nodes to which they apply, and multiple operations on
+ the same node types can be scattered through-out the code.<p>
+
+ Portable.NET takes this even further by separating individual operations
+ across multiple files for expressions, statements, declarations, etc.
+ This introduces a clearer structure to the code that makes it easier
+ to navigate the source during compiler construction. The semantic analysis
+ routines in treecc ensure that nothing is missed when all of the
+ separate modules are recombined.<p>
+
+ <h2>8. Painless Visitors</h2>
+
+ The previous example used a "<code>%virtual</code>" operation, which
+ is defined over all node types. Treecc inserts the virtual method
+ body wherever it is required.<p>
+
+ Sometimes we don't want to define an operation as a virtual method.
+ We would prefer to use the visitor approach. The following is what
+ a visitor version of "<code>TypeCheck</code>" would look like:
+
+ <blockquote>
+ <pre>%operation LanguageType TypeChecker::TypeCheck(Expression e) = {null}
+
+ TypeCheck(NegateExpression),
+ TypeCheck(UnaryPlusExpression)
+ {
+ LanguageType type = TypeCheck(e.expr);
+ if(type.IsInteger() || type.IsFloat())
+ {
+ return type;
+ }
+ throw new TypeCheckException();
+ }
+
+ TypeCheck(BitwiseNotExpression)
+ {
+ LanguageType type = TypeCheck(e.expr);
+ if(type.IsInteger())
+ {
+ return type;
+ }
+ throw new TypeCheckException();
+ }</pre>
+ </blockquote>
+
+ This is almost identical to the previous version, except for the
+ definition of the operation, and the calling conventions for
+ "<code>TypeCheck</code>". Behind the scenes, treecc creates
+ a class called "<code>TypeChecker</code>" that contains a static
+ method called "<code>TypeCheck</code>". This is the visitor.<p>
+
+ Interestingly, if we had used C as the underlying language, then no
+ changes are necessary to the bodies of the operation cases. Only
+ the "<code>%virtual</code>" keyword changes. The C macro pre-processor
+ is used to smooth out the differences.<p>
+
+ This illustrates another useful property of treecc: it is very simple
+ to flip operations between inhertance-based virtuals and visitor-based
+ non-virtuals. This allows the programmer to start developing the compiler
+ one way, change their mind, and quickly flip to the other way.<p>
+
+ Normally, changing inheritance-based code into visitor-based code
+ would entail a complete system rewrite. Changing patterns with
+ treecc is trivial.<p>
+
+ This is a common property of aspect-oriented programming languages:
+ because the language takes care of the inserting the aspects into
+ the main classes, it is easier to change the style of insertion
+ without a major system overhaul.<p>
+
+ Non-virtual operations can be applied to multiple arguments, which
+ can be very useful when implementing coercions:
+
+ <blockquote>
+ <pre>%enum SimpleType =
+ {
+ Integer,
+ Long,
+ Float,
+ Error
+ }
+
+ %operation %inline SimpleType Binary::Coerce
+ ([SimpleType type1], [SimpleType type2]) = {Error}
+
+ Coerce(Integer, Integer)
+ {
+ return Integer;
+ }
+
+ Coerce(Integer, Long),
+ Coerce(Long, Integer),
+ Coerce(Long, Long)
+ {
+ return Long;
+ }
+
+ Coerce(Integer, Float),
+ Coerce(Float, Integer),
+ Coerce(Long, Float),
+ Coerce(Float, Float)
+ {
+ return Float;
+ }
+
+ Coerce(Integer, Error),
+ Coerce(Error, Integer),
+ Coerce(Long, Error),
+ Coerce(Error, Long),
+ Coerce(Float, Error),
+ Coerce(Error, Float),
+ Coerce(Error, Error)
+ {
+ return Error;
+ }</pre>
+ </blockquote>
+
+ Treecc turns this into a highly efficient nested switch statement,
+ which would be extremely difficult to debug by hand. We actually
+ left out one of the cases above, so we get an error:
+
+ <blockquote><code>eg.tc:48: case `Float, Long' is missing from operation `Coerce'</code></blockquote>
+
+ Casts and coercions on primitive types can now be implemented as
+ simple table lookups, with treecc checking the completeness of the
+ table for us.<p>
+
+ <h2>9. Conclusion and Future Directions</h2>
+
+ Treecc provides a new way to attack the complexity of compiler implementation
+ by automating error-prone tasks. It performs a large amount of semantic
+ analysis on the program to ensure that common problems are caught early
+ in the development cycle.<p>
+
+ Because treecc is based on an aspect-oriented foundation, it allows the
+ programmer to separate out concerns and deal with them individually.
+ Treecc puts the whole system back together in the most efficient manner
+ possible.<p>
+
+ The system is not necessarily complete. We'd like to experiment with
+ rule-based code generation techniques. At present, optimizers and
+ code generators must be written by hand, as operations on node types.<p>
+
+ A rule-based system would make it easier to build clever optimizers
+ as a set of pattern matching directives. Operations are already a
+ special class of pattern matcher, but they don't have any back-tracking
+ and retry capabilities.<p>
+
+ Another area that treecc can be applied to is the construction of
+ "Just In Time" compilers. The first phase of the JIT process is the
+ reconstruction of the intermediate code form of the program. This
+ intermediate code typically takes the form of abstract syntax trees or
+ three-address statements.<p>
+
+ Treecc is well-suited to the management of JIT intermediate forms.
+ Register allocation, dynamic flow analysis, and machine-dependent
+ code generation can be added as JIT aspects. We are currently
+ exploring the use of treecc to assist in the construction of a
+ JIT for Portable.NET<p>
+
+ <h2>References</h2>
+
+ <a name="pnetref">[1] Portable.NET Web Site, <a href="http://www.southern-storm.com.au/portable_net.html">http://www.southern-storm.com.au/portable_net.html</a>.<p>
+
+ <a name="treeccref">[2] Treecc Web Site, <a href="http://www.southern-storm.com.au/treecc.html">http://www.southern-storm.com.au/treecc.html</a>.<p>
+
+ <a name="gammaref">[3] Gamma, et al., <em>Design Patterns: Elements of
+ Reusable Object-Oriented Software</em>, Addison-Wesley, 1995.<p>
+
+ <a name="aopref">[4] Aspect-Oriented Programming, <em>Communications of
+ the ACM</em>, October 2001.<p>
+
+ <a name="aspectjref">[5] AspectJ Web Site, <a href="http://www.aspectj.org/">http://www.aspectj.org/</a>.<p>
+
+ </body>
+ </html>
Index: llvm/test/Programs/MultiSource/Applications/treecc/doc/extending.txt
diff -c /dev/null llvm/test/Programs/MultiSource/Applications/treecc/doc/extending.txt:1.1
*** /dev/null Tue Apr 6 12:54:55 2004
--- llvm/test/Programs/MultiSource/Applications/treecc/doc/extending.txt Tue Apr 6 12:54:44 2004
***************
*** 0 ****
--- 1,99 ----
+ Quick and Dirty Guide to Extending and Testing Treecc
+
+ 1. Adding a new output language - Scaffolding
+
+ The following is the bare scaffolding to link a new language into treecc:
+
+ - Add a new identifier to the TREECC_LANG_* list in "info.h".
+ - Recognise the language name for the "lang" option in "options.c",
+ function "LangOption".
+ - Add a new case to the switch statement in "TreeCCGenerate" function
+ in the file "gen.c" for the language identifier, which calls a
+ function called "TreeCCGenerateLang", which you should prototype
+ in "gen.h".
+ - Add a new "gen_lang.c" file to the project (don't forget to
+ update Makefile.am), which implements the output routines.
+
+ 2. Adding a new output language - Details
+
+ The "gen_lang.c" file needs to export a single function called
+ "TreeCCGenerateLang", which iterates over all the nodes and operations
+ to output the final code.
+
+ The "TreeCCGenerateLang" function must perform the following tasks,
+ roughly in this order:
+
+ - Output any source header information that is required.
+ - Output node kinds, which are used to uniquely identify each
+ node type (e.g. "#define expression_kind 1" in C). In an OO
+ language, you can output these kind values
+ - Perform forward declaration of the node classes and operations,
+ if required by the output language (C# and Java don't need this,
+ but C does).
+ - Output the node allocation skeleton (normally not needed if
+ your language is garbage-collected).
+ - Define the node classes, and any factory create methods that
+ are required. You may also need to define a "state type" which
+ holds common allocation information.
+ - Output non-virtual operations, by calling "TreeCCGenerateNonVirtuals",
+ and passing it a function block ("TreeCCNonVirtual" type) to
+ assist with the output process.
+ - Output any source footer information that is required, including
+ helper functions for node allocation, kind testing, etc.
+
+ It is usually easiest to start with one of the existing output languages
+ and then cut-and-paste yourself a new one. If you are using a non garbage
+ collected language such as C or C++, then start with either "gen_c.c" or
+ "gen_cpp.c" as a base. If you are using a garbage collected language
+ like C# or Java, then start with either "gen_cs.c" or "gen_java.c".
+
+ The function "TreeCCNodeVisitAll" can be very useful for iterating over
+ all node types in the system: pass it a callback that provides your
+ language-specific node handling code. See "info.h" and "gen.h" for
+ other helper functions.
+
+ Nodes and operations can be written to multiple output files, and you
+ must handle this properly. The functions in "stream.h" can assist with
+ this. The "header" and "source" fields in "TreeCCNode" and "TreeCCOperation"
+ describe where to output node and operation implementations.
+
+ The actual API to nodes and operations is language-specific, but try
+ to follow the existing styles where possible. See "doc/treecc.texi"
+ for documentation on the existing API styles.
+
+ 2. Testing all possible variants.
+
+ There are lots of different output modes (re-entrant vs non re-entrant,
+ line tracking vs no line tracking, abstract factories, virtual vs non-virtual
+ operations, inline vs non-inline, etc).
+
+ Your test cases in the "tests" directory should attempt to cover the
+ major areas. See the "output*.tst" files for the existing tests. You
+ shouldn't need to create "input" or "parse" tests, as they are generic.
+
+ Once you have written a new "outputN.tst" file, generate test output
+ using "./test_output outputN.tst >outputN.out". Then hand-inspect the
+ "outputN.out" file for problems. Once you are satisfied that your
+ "gen_lang.c" code is generating the right output, add the following
+ line to "tests/test_list":
+
+ test_output outputN
+
+ After you have done this, you can run "make check" to verify that you
+ haven't broken anything as you made changes to the system.
+
+ 3. Add an example.
+
+ Go into the "examples" directory and add a new version of the expression
+ example for your language, to demonstrate how to use treecc with the
+ language. The examples doesn't necessarily need to compile - just give
+ a guide as to how to use the tool.
+
+ 4. Write documentation.
+
+ Add a new section to "doc/treecc.texi" describing the API for your
+ language, using the existing sections as to a guide to the text.
+
+ 5. It's not as hard as your think!
+
+ The above may look daunting, but it's mostly a cut-and-paste exercise.
Index: llvm/test/Programs/MultiSource/Applications/treecc/doc/mkdoc
diff -c /dev/null llvm/test/Programs/MultiSource/Applications/treecc/doc/mkdoc:1.1
*** /dev/null Tue Apr 6 12:54:55 2004
--- llvm/test/Programs/MultiSource/Applications/treecc/doc/mkdoc Tue Apr 6 12:54:44 2004
***************
*** 0 ****
--- 1,34 ----
+ #!/bin/sh
+ #
+ # mkdoc - Make all forms of documentation for treecc from Texinfo input.
+ #
+ # Usage: mkdir outdir
+
+ # Check the command-line.
+ if [ -z "$1" ]; then
+ echo "Usage: $0 outdir"
+ exit 1
+ fi
+
+ # Check that we are executed in the correct directory.
+ if [ ! -f treecc.texi ]; then
+ echo "Cannot find treecc.texi"
+ exit 1
+ fi
+
+ # Create the output directory.
+ if [ ! -d "$1" ]; then
+ mkdir "$1"
+ fi
+
+ # Create the online HTML documentation.
+ ./mkhtml "$1"
+
+ # Create the PDF documentation.
+ ./mkpdf
+ cp treecc.pdf "$1"
+
+ # Pack up the HTML documentation into a tar.gz file.
+ cd "$1"
+ tar cfz treecc-doc.tar.gz *.html
+ exit 0
Index: llvm/test/Programs/MultiSource/Applications/treecc/doc/mkhtml
diff -c /dev/null llvm/test/Programs/MultiSource/Applications/treecc/doc/mkhtml:1.1
*** /dev/null Tue Apr 6 12:54:55 2004
--- llvm/test/Programs/MultiSource/Applications/treecc/doc/mkhtml Tue Apr 6 12:54:45 2004
***************
*** 0 ****
--- 1,29 ----
+ #!/bin/sh
+ #
+ # mkhtml - Make html documentation for treecc from Texinfo input.
+ #
+ # Usage: mkhtml outdir
+
+ # Check the command-line.
+ if [ -z "$1" ]; then
+ echo "Usage: $0 outdir"
+ exit 1
+ fi
+
+ # Check that we are executed in the correct directory.
+ if [ ! -f treecc.texi ]; then
+ echo "Cannot find treecc.texi"
+ exit 1
+ fi
+
+ # Create the output directory.
+ if [ ! -d "$1" ]; then
+ mkdir "$1"
+ fi
+
+ # Get the full pathname of the input file.
+ PATHNAME=`pwd`/treecc.texi
+
+ # Change to the output directory and execute "texi2html".
+ cd "$1"
+ exec texi2html -split_chapter "$PATHNAME"
Index: llvm/test/Programs/MultiSource/Applications/treecc/doc/mkpdf
diff -c /dev/null llvm/test/Programs/MultiSource/Applications/treecc/doc/mkpdf:1.1
*** /dev/null Tue Apr 6 12:54:55 2004
--- llvm/test/Programs/MultiSource/Applications/treecc/doc/mkpdf Tue Apr 6 12:54:45 2004
***************
*** 0 ****
--- 1,5 ----
+ #!/bin/sh
+ #
+ # mkpdf - Make the PDF version of the treecc documentation
+
+ exec texi2dvi --pdf treecc.texi
Index: llvm/test/Programs/MultiSource/Applications/treecc/doc/texinfo.tex
diff -c /dev/null llvm/test/Programs/MultiSource/Applications/treecc/doc/texinfo.tex:1.1
*** /dev/null Tue Apr 6 12:54:55 2004
--- llvm/test/Programs/MultiSource/Applications/treecc/doc/texinfo.tex Tue Apr 6 12:54:45 2004
***************
*** 0 ****
--- 1,5484 ----
+ % texinfo.tex -- TeX macros to handle Texinfo files.
+ %
+ % Load plain if necessary, i.e., if running under initex.
+ \expandafter\ifx\csname fmtname\endcsname\relax\input plain\fi
+ %
+ \def\texinfoversion{1999-01-05}%
+ %
+ % Copyright (C) 1985, 86, 88, 90, 91, 92, 93, 94, 95, 96, 97, 98
+ % Free Software Foundation, Inc.
+ %
+ % This texinfo.tex file is free software; you can redistribute it and/or
+ % modify it under the terms of the GNU General Public License as
+ % published by the Free Software Foundation; either version 2, or (at
+ % your option) any later version.
+ %
+ % This texinfo.tex file is distributed in the hope that it will be
+ % useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ % of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ % General Public License for more details.
+ %
+ % You should have received a copy of the GNU General Public License
+ % along with this texinfo.tex file; see the file COPYING. If not, write
+ % to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ % Boston, MA 02111-1307, USA.
+ %
+ % In other words, you are welcome to use, share and improve this program.
+ % You are forbidden to forbid anyone else to use, share and improve
+ % what you give them. Help stamp out software-hoarding!
+ %
+ % Please try the latest version of texinfo.tex before submitting bug
+ % reports; you can get the latest version from:
+ % ftp://ftp.gnu.org/pub/gnu/texinfo.tex
+ % /home/gd/gnu/doc/texinfo.tex on the GNU machines.
+ % (and all GNU mirrors, see http://www.gnu.org/order/ftp.html)
+ % ftp://tug.org/tex/texinfo.tex
+ % ftp://ctan.org/macros/texinfo/texinfo.tex
+ % (and all CTAN mirrors, finger ctan at ctan.org for a list).
+ % The texinfo.tex in the texinfo distribution itself could well be out
+ % of date, so if that's what you're using, please check.
+ %
+ % Send bug reports to bug-texinfo at gnu.org.
+ % Please include a precise test case in each bug report,
+ % including a complete document with which we can reproduce the problem.
+ %
+ % To process a Texinfo manual with TeX, it's most reliable to use the
+ % texi2dvi shell script that comes with the distribution. For simple
+ % manuals, however, you can get away with:
+ % tex foo.texi
+ % texindex foo.??
+ % tex foo.texi
+ % tex foo.texi
+ % dvips foo.dvi -o # or whatever, to process the dvi file.
+ % The extra runs of TeX get the cross-reference information correct.
+ % Sometimes one run after texindex suffices, and sometimes you need more
+ % than two; texi2dvi does it as many times as necessary.
+
+ \message{Loading texinfo [version \texinfoversion]:}
+
+ % If in a .fmt file, print the version number
+ % and turn on active characters that we couldn't do earlier because
+ % they might have appeared in the input file name.
+ \everyjob{\message{[Texinfo version \texinfoversion]}%
+ \catcode`+=\active \catcode`\_=\active}
+
+ % Save some parts of plain tex whose names we will redefine.
+
+ \let\ptexb=\b
+ \let\ptexbullet=\bullet
+ \let\ptexc=\c
+ \let\ptexcomma=\,
+ \let\ptexdot=\.
+ \let\ptexdots=\dots
+ \let\ptexend=\end
+ \let\ptexequiv=\equiv
+ \let\ptexexclam=\!
+ \let\ptexi=\i
+ \let\ptexlbrace=\{
+ \let\ptexrbrace=\}
+ \let\ptexstar=\*
+ \let\ptext=\t
+
+ % We never want plain's outer \+ definition in Texinfo.
+ % For @tex, we can use \tabalign.
+ \let\+ = \relax
+
+
+ \message{Basics,}
+ \chardef\other=12
+
+ % If this character appears in an error message or help string, it
+ % starts a new line in the output.
+ \newlinechar = `^^J
+
+ % Set up fixed words for English if not already set.
+ \ifx\putwordAppendix\undefined \gdef\putwordAppendix{Appendix}\fi
+ \ifx\putwordChapter\undefined \gdef\putwordChapter{Chapter}\fi
+ \ifx\putwordfile\undefined \gdef\putwordfile{file}\fi
+ \ifx\putwordInfo\undefined \gdef\putwordInfo{Info}\fi
+ \ifx\putwordMethodon\undefined \gdef\putwordMethodon{Method on}\fi
+ \ifx\putwordon\undefined \gdef\putwordon{on}\fi
+ \ifx\putwordpage\undefined \gdef\putwordpage{page}\fi
+ \ifx\putwordsection\undefined \gdef\putwordsection{section}\fi
+ \ifx\putwordSection\undefined \gdef\putwordSection{Section}\fi
+ \ifx\putwordsee\undefined \gdef\putwordsee{see}\fi
+ \ifx\putwordSee\undefined \gdef\putwordSee{See}\fi
+ \ifx\putwordShortContents\undefined \gdef\putwordShortContents{Short Contents}\fi
+ \ifx\putwordTableofContents\undefined\gdef\putwordTableofContents{Table of Contents}\fi
+
+ % Ignore a token.
+ %
+ \def\gobble#1{}
+
+ \hyphenation{ap-pen-dix}
+ \hyphenation{mini-buf-fer mini-buf-fers}
+ \hyphenation{eshell}
+ \hyphenation{white-space}
+
+ % Margin to add to right of even pages, to left of odd pages.
+ \newdimen \bindingoffset
+ \newdimen \normaloffset
+ \newdimen\pagewidth \newdimen\pageheight
+
+ % Sometimes it is convenient to have everything in the transcript file
+ % and nothing on the terminal. We don't just call \tracingall here,
+ % since that produces some useless output on the terminal.
+ %
+ \def\gloggingall{\begingroup \globaldefs = 1 \loggingall \endgroup}%
+ \ifx\eTeXversion\undefined
+ \def\loggingall{\tracingcommands2 \tracingstats2
+ \tracingpages1 \tracingoutput1 \tracinglostchars1
+ \tracingmacros2 \tracingparagraphs1 \tracingrestores1
+ \showboxbreadth\maxdimen\showboxdepth\maxdimen
+ }%
+ \else
+ \def\loggingall{\tracingcommands3 \tracingstats2
+ \tracingpages1 \tracingoutput1 \tracinglostchars1
+ \tracingmacros2 \tracingparagraphs1 \tracingrestores1
+ \tracingscantokens1 \tracingassigns1 \tracingifs1
+ \tracinggroups1 \tracingnesting2
+ \showboxbreadth\maxdimen\showboxdepth\maxdimen
+ }%
+ \fi
+
+ % For @cropmarks command.
+ % Do @cropmarks to get crop marks.
+ %
+ \newif\ifcropmarks
+ \let\cropmarks = \cropmarkstrue
+ %
+ % Dimensions to add cropmarks at corners.
+ % Added by P. A. MacKay, 12 Nov. 1986
+ %
+ \newdimen\outerhsize \newdimen\outervsize % set by the paper size routines
+ \newdimen\cornerlong \cornerlong=1pc
+ \newdimen\cornerthick \cornerthick=.3pt
+ \newdimen\topandbottommargin \topandbottommargin=.75in
+
+ % Main output routine.
+ \chardef\PAGE = 255
+ \output = {\onepageout{\pagecontents\PAGE}}
+
+ \newbox\headlinebox
+ \newbox\footlinebox
+
+ % \onepageout takes a vbox as an argument. Note that \pagecontents
+ % does insertions, but you have to call it yourself.
+ \def\onepageout#1{%
+ \ifcropmarks \hoffset=0pt \else \hoffset=\normaloffset \fi
+ %
+ \ifodd\pageno \advance\hoffset by \bindingoffset
+ \else \advance\hoffset by -\bindingoffset\fi
+ %
+ % Do this outside of the \shipout so @code etc. will be expanded in
+ % the headline as they should be, not taken literally (outputting ''code).
+ \setbox\headlinebox = \vbox{\let\hsize=\pagewidth \makeheadline}%
+ \setbox\footlinebox = \vbox{\let\hsize=\pagewidth \makefootline}%
+ %
+ {%
+ % Have to do this stuff outside the \shipout because we want it to
+ % take effect in \write's, yet the group defined by the \vbox ends
+ % before the \shipout runs.
+ %
+ \escapechar = `\\ % use backslash in output files.
+ \indexdummies % don't expand commands in the output.
+ \normalturnoffactive % \ in index entries must not stay \, e.g., if
+ % the page break happens to be in the middle of an example.
+ \shipout\vbox{%
+ \ifcropmarks \vbox to \outervsize\bgroup
+ \hsize = \outerhsize
+ \vskip-\topandbottommargin
+ \vtop to0pt{%
+ \line{\ewtop\hfil\ewtop}%
+ \nointerlineskip
+ \line{%
+ \vbox{\moveleft\cornerthick\nstop}%
+ \hfill
+ \vbox{\moveright\cornerthick\nstop}%
+ }%
+ \vss}%
+ \vskip\topandbottommargin
+ \line\bgroup
+ \hfil % center the page within the outer (page) hsize.
+ \ifodd\pageno\hskip\bindingoffset\fi
+ \vbox\bgroup
+ \fi
+ %
+ \unvbox\headlinebox
+ \pagebody{#1}%
+ \ifdim\ht\footlinebox > 0pt
+ % Only leave this space if the footline is nonempty.
+ % (We lessened \vsize for it in \oddfootingxxx.)
+ % The \baselineskip=24pt in plain's \makefootline has no effect.
+ \vskip 2\baselineskip
+ \unvbox\footlinebox
+ \fi
+ %
+ \ifcropmarks
+ \egroup % end of \vbox\bgroup
+ \hfil\egroup % end of (centering) \line\bgroup
+ \vskip\topandbottommargin plus1fill minus1fill
+ \boxmaxdepth = \cornerthick
+ \vbox to0pt{\vss
+ \line{%
+ \vbox{\moveleft\cornerthick\nsbot}%
+ \hfill
+ \vbox{\moveright\cornerthick\nsbot}%
+ }%
+ \nointerlineskip
+ \line{\ewbot\hfil\ewbot}%
+ }%
+ \egroup % \vbox from first cropmarks clause
+ \fi
+ }% end of \shipout\vbox
+ }% end of group with \turnoffactive
+ \advancepageno
+ \ifnum\outputpenalty>-20000 \else\dosupereject\fi
+ }
+
+ \newinsert\margin \dimen\margin=\maxdimen
+
+ \def\pagebody#1{\vbox to\pageheight{\boxmaxdepth=\maxdepth #1}}
+ {\catcode`\@ =11
+ \gdef\pagecontents#1{\ifvoid\topins\else\unvbox\topins\fi
+ % marginal hacks, juha at viisa.uucp (Juha Takala)
+ \ifvoid\margin\else % marginal info is present
+ \rlap{\kern\hsize\vbox to\z@{\kern1pt\box\margin \vss}}\fi
+ \dimen@=\dp#1 \unvbox#1
+ \ifvoid\footins\else\vskip\skip\footins\footnoterule \unvbox\footins\fi
+ \ifr at ggedbottom \kern-\dimen@ \vfil \fi}
+ }
+
+ % Here are the rules for the cropmarks. Note that they are
+ % offset so that the space between them is truly \outerhsize or \outervsize
+ % (P. A. MacKay, 12 November, 1986)
+ %
+ \def\ewtop{\vrule height\cornerthick depth0pt width\cornerlong}
+ \def\nstop{\vbox
+ {\hrule height\cornerthick depth\cornerlong width\cornerthick}}
+ \def\ewbot{\vrule height0pt depth\cornerthick width\cornerlong}
+ \def\nsbot{\vbox
+ {\hrule height\cornerlong depth\cornerthick width\cornerthick}}
+
+ % Parse an argument, then pass it to #1. The argument is the rest of
+ % the input line (except we remove a trailing comment). #1 should be a
+ % macro which expects an ordinary undelimited TeX argument.
+ %
+ \def\parsearg#1{%
+ \let\next = #1%
+ \begingroup
+ \obeylines
+ \futurelet\temp\parseargx
+ }
+
+ % If the next token is an obeyed space (from an @example environment or
+ % the like), remove it and recurse. Otherwise, we're done.
+ \def\parseargx{%
+ % \obeyedspace is defined far below, after the definition of \sepspaces.
+ \ifx\obeyedspace\temp
+ \expandafter\parseargdiscardspace
+ \else
+ \expandafter\parseargline
+ \fi
+ }
+
+ % Remove a single space (as the delimiter token to the macro call).
+ {\obeyspaces %
+ \gdef\parseargdiscardspace {\futurelet\temp\parseargx}}
+
+ {\obeylines %
+ \gdef\parseargline#1^^M{%
+ \endgroup % End of the group started in \parsearg.
+ %
+ % First remove any @c comment, then any @comment.
+ % Result of each macro is put in \toks0.
+ \argremovec #1\c\relax %
+ \expandafter\argremovecomment \the\toks0 \comment\relax %
+ %
+ % Call the caller's macro, saved as \next in \parsearg.
+ \expandafter\next\expandafter{\the\toks0}%
+ }%
+ }
+
+ % Since all \c{,omment} does is throw away the argument, we can let TeX
+ % do that for us. The \relax here is matched by the \relax in the call
+ % in \parseargline; it could be more or less anything, its purpose is
+ % just to delimit the argument to the \c.
+ \def\argremovec#1\c#2\relax{\toks0 = {#1}}
+ \def\argremovecomment#1\comment#2\relax{\toks0 = {#1}}
+
+ % \argremovec{,omment} might leave us with trailing spaces, though; e.g.,
+ % @end itemize @c foo
+ % will have two active spaces as part of the argument with the
+ % `itemize'. Here we remove all active spaces from #1, and assign the
+ % result to \toks0.
+ %
+ % This loses if there are any *other* active characters besides spaces
+ % in the argument -- _ ^ +, for example -- since they get expanded.
+ % Fortunately, Texinfo does not define any such commands. (If it ever
+ % does, the catcode of the characters in questionwill have to be changed
+ % here.) But this means we cannot call \removeactivespaces as part of
+ % \argremovec{,omment}, since @c uses \parsearg, and thus the argument
+ % that \parsearg gets might well have any character at all in it.
+ %
+ \def\removeactivespaces#1{%
+ \begingroup
+ \ignoreactivespaces
+ \edef\temp{#1}%
+ \global\toks0 = \expandafter{\temp}%
+ \endgroup
+ }
+
+ % Change the active space to expand to nothing.
+ %
+ \begingroup
+ \obeyspaces
+ \gdef\ignoreactivespaces{\obeyspaces\let =\empty}
+ \endgroup
+
+
+ \def\flushcr{\ifx\par\lisppar \def\next##1{}\else \let\next=\relax \fi \next}
+
+ %% These are used to keep @begin/@end levels from running away
+ %% Call \inENV within environments (after a \begingroup)
+ \newif\ifENV \ENVfalse \def\inENV{\ifENV\relax\else\ENVtrue\fi}
+ \def\ENVcheck{%
+ \ifENV\errmessage{Still within an environment; press RETURN to continue}
+ \endgroup\fi} % This is not perfect, but it should reduce lossage
+
+ % @begin foo is the same as @foo, for now.
+ \newhelp\EMsimple{Press RETURN to continue.}
+
+ \outer\def\begin{\parsearg\beginxxx}
+
+ \def\beginxxx #1{%
+ \expandafter\ifx\csname #1\endcsname\relax
+ {\errhelp=\EMsimple \errmessage{Undefined command @begin #1}}\else
+ \csname #1\endcsname\fi}
+
+ % @end foo executes the definition of \Efoo.
+ %
+ \def\end{\parsearg\endxxx}
+ \def\endxxx #1{%
+ \removeactivespaces{#1}%
+ \edef\endthing{\the\toks0}%
+ %
+ \expandafter\ifx\csname E\endthing\endcsname\relax
+ \expandafter\ifx\csname \endthing\endcsname\relax
+ % There's no \foo, i.e., no ``environment'' foo.
+ \errhelp = \EMsimple
+ \errmessage{Undefined command `@end \endthing'}%
+ \else
+ \unmatchedenderror\endthing
+ \fi
+ \else
+ % Everything's ok; the right environment has been started.
+ \csname E\endthing\endcsname
+ \fi
+ }
+
+ % There is an environment #1, but it hasn't been started. Give an error.
+ %
+ \def\unmatchedenderror#1{%
+ \errhelp = \EMsimple
+ \errmessage{This `@end #1' doesn't have a matching `@#1'}%
+ }
+
+ % Define the control sequence \E#1 to give an unmatched @end error.
+ %
+ \def\defineunmatchedend#1{%
+ \expandafter\def\csname E#1\endcsname{\unmatchedenderror{#1}}%
+ }
+
+
+ % Single-spacing is done by various environments (specifically, in
+ % \nonfillstart and \quotations).
+ \newskip\singlespaceskip \singlespaceskip = 12.5pt
+ \def\singlespace{%
+ % Why was this kern here? It messes up equalizing space above and below
+ % environments. --karl, 6may93
+ %{\advance \baselineskip by -\singlespaceskip
+ %\kern \baselineskip}%
+ \setleading \singlespaceskip
+ }
+
+ %% Simple single-character @ commands
+
+ % @@ prints an @
+ % Kludge this until the fonts are right (grr).
+ \def\@{{\tt\char64}}
+
+ % This is turned off because it was never documented
+ % and you can use @w{...} around a quote to suppress ligatures.
+ %% Define @` and @' to be the same as ` and '
+ %% but suppressing ligatures.
+ %\def\`{{`}}
+ %\def\'{{'}}
+
+ % Used to generate quoted braces.
+ \def\mylbrace {{\tt\char123}}
+ \def\myrbrace {{\tt\char125}}
+ \let\{=\mylbrace
+ \let\}=\myrbrace
+ \begingroup
+ % Definitions to produce actual \{ & \} command in an index.
+ \catcode`\{ = 12 \catcode`\} = 12
+ \catcode`\[ = 1 \catcode`\] = 2
+ \catcode`\@ = 0 \catcode`\\ = 12
+ @gdef at lbracecmd[\{]%
+ @gdef at rbracecmd[\}]%
+ @endgroup
+
+ % Accents: @, @dotaccent @ringaccent @ubaraccent @udotaccent
+ % Others are defined by plain TeX: @` @' @" @^ @~ @= @v @H.
+ \let\, = \c
+ \let\dotaccent = \.
+ \def\ringaccent#1{{\accent23 #1}}
+ \let\tieaccent = \t
+ \let\ubaraccent = \b
+ \let\udotaccent = \d
+
+ % Other special characters: @questiondown @exclamdown
+ % Plain TeX defines: @AA @AE @O @OE @L (and lowercase versions) @ss.
+ \def\questiondown{?`}
+ \def\exclamdown{!`}
+
+ % Dotless i and dotless j, used for accents.
+ \def\imacro{i}
+ \def\jmacro{j}
+ \def\dotless#1{%
+ \def\temp{#1}%
+ \ifx\temp\imacro \ptexi
+ \else\ifx\temp\jmacro \j
+ \else \errmessage{@dotless can be used only with i or j}%
+ \fi\fi
+ }
+
+ % Be sure we're in horizontal mode when doing a tie, since we make space
+ % equivalent to this in @example-like environments. Otherwise, a space
+ % at the beginning of a line will start with \penalty -- and
+ % since \penalty is valid in vertical mode, we'd end up putting the
+ % penalty on the vertical list instead of in the new paragraph.
+ {\catcode`@ = 11
+ % Avoid using \@M directly, because that causes trouble
+ % if the definition is written into an index file.
+ \global\let\tiepenalty = \@M
+ \gdef\tie{\leavevmode\penalty\tiepenalty\ }
+ }
+
+ % @: forces normal size whitespace following.
+ \def\:{\spacefactor=1000 }
+
+ % @* forces a line break.
+ \def\*{\hfil\break\hbox{}\ignorespaces}
+
+ % @. is an end-of-sentence period.
+ \def\.{.\spacefactor=3000 }
+
+ % @! is an end-of-sentence bang.
+ \def\!{!\spacefactor=3000 }
+
+ % @? is an end-of-sentence query.
+ \def\?{?\spacefactor=3000 }
+
+ % @w prevents a word break. Without the \leavevmode, @w at the
+ % beginning of a paragraph, when TeX is still in vertical mode, would
+ % produce a whole line of output instead of starting the paragraph.
+ \def\w#1{\leavevmode\hbox{#1}}
+
+ % @group ... @end group forces ... to be all on one page, by enclosing
+ % it in a TeX vbox. We use \vtop instead of \vbox to construct the box
+ % to keep its height that of a normal line. According to the rules for
+ % \topskip (p.114 of the TeXbook), the glue inserted is
+ % max (\topskip - \ht (first item), 0). If that height is large,
+ % therefore, no glue is inserted, and the space between the headline and
+ % the text is small, which looks bad.
+ %
+ \def\group{\begingroup
+ \ifnum\catcode13=\active \else
+ \errhelp = \groupinvalidhelp
+ \errmessage{@group invalid in context where filling is enabled}%
+ \fi
+ %
+ % The \vtop we start below produces a box with normal height and large
+ % depth; thus, TeX puts \baselineskip glue before it, and (when the
+ % next line of text is done) \lineskip glue after it. (See p.82 of
+ % the TeXbook.) Thus, space below is not quite equal to space
+ % above. But it's pretty close.
+ \def\Egroup{%
+ \egroup % End the \vtop.
+ \endgroup % End the \group.
+ }%
+ %
+ \vtop\bgroup
+ % We have to put a strut on the last line in case the @group is in
+ % the midst of an example, rather than completely enclosing it.
+ % Otherwise, the interline space between the last line of the group
+ % and the first line afterwards is too small. But we can't put the
+ % strut in \Egroup, since there it would be on a line by itself.
+ % Hence this just inserts a strut at the beginning of each line.
+ \everypar = {\strut}%
+ %
+ % Since we have a strut on every line, we don't need any of TeX's
+ % normal interline spacing.
+ \offinterlineskip
+ %
+ % OK, but now we have to do something about blank
+ % lines in the input in @example-like environments, which normally
+ % just turn into \lisppar, which will insert no space now that we've
+ % turned off the interline space. Simplest is to make them be an
+ % empty paragraph.
+ \ifx\par\lisppar
+ \edef\par{\leavevmode \par}%
+ %
+ % Reset ^^M's definition to new definition of \par.
+ \obeylines
+ \fi
+ %
+ % Do @comment since we are called inside an environment such as
+ % @example, where each end-of-line in the input causes an
+ % end-of-line in the output. We don't want the end-of-line after
+ % the `@group' to put extra space in the output. Since @group
+ % should appear on a line by itself (according to the Texinfo
+ % manual), we don't worry about eating any user text.
+ \comment
+ }
+ %
+ % TeX puts in an \escapechar (i.e., `@') at the beginning of the help
+ % message, so this ends up printing `@group can only ...'.
+ %
+ \newhelp\groupinvalidhelp{%
+ group can only be used in environments such as @example,^^J%
+ where each line of input produces a line of output.}
+
+ % @need space-in-mils
+ % forces a page break if there is not space-in-mils remaining.
+
+ \newdimen\mil \mil=0.001in
+
+ \def\need{\parsearg\needx}
+
+ % Old definition--didn't work.
+ %\def\needx #1{\par %
+ %% This method tries to make TeX break the page naturally
+ %% if the depth of the box does not fit.
+ %{\baselineskip=0pt%
+ %\vtop to #1\mil{\vfil}\kern -#1\mil\nobreak
+ %\prevdepth=-1000pt
+ %}}
+
+ \def\needx#1{%
+ % Go into vertical mode, so we don't make a big box in the middle of a
+ % paragraph.
+ \par
+ %
+ % Don't add any leading before our big empty box, but allow a page
+ % break, since the best break might be right here.
+ \allowbreak
+ \nointerlineskip
+ \vtop to #1\mil{\vfil}%
+ %
+ % TeX does not even consider page breaks if a penalty added to the
+ % main vertical list is 10000 or more. But in order to see if the
+ % empty box we just added fits on the page, we must make it consider
+ % page breaks. On the other hand, we don't want to actually break the
+ % page after the empty box. So we use a penalty of 9999.
+ %
+ % There is an extremely small chance that TeX will actually break the
+ % page at this \penalty, if there are no other feasible breakpoints in
+ % sight. (If the user is using lots of big @group commands, which
+ % almost-but-not-quite fill up a page, TeX will have a hard time doing
+ % good page breaking, for example.) However, I could not construct an
+ % example where a page broke at this \penalty; if it happens in a real
+ % document, then we can reconsider our strategy.
+ \penalty9999
+ %
+ % Back up by the size of the box, whether we did a page break or not.
+ \kern -#1\mil
+ %
+ % Do not allow a page break right after this kern.
+ \nobreak
+ }
+
+ % @br forces paragraph break
+
+ \let\br = \par
+
+ % @dots{} output an ellipsis using the current font.
+ % We do .5em per period so that it has the same spacing in a typewriter
+ % font as three actual period characters.
+ %
+ \def\dots{%
+ \leavevmode
+ \hbox to 1.5em{%
+ \hskip 0pt plus 0.25fil minus 0.25fil
+ .\hss.\hss.%
+ \hskip 0pt plus 0.5fil minus 0.5fil
+ }%
+ }
+
+ % @enddots{} is an end-of-sentence ellipsis.
+ %
+ \def\enddots{%
+ \leavevmode
+ \hbox to 2em{%
+ \hskip 0pt plus 0.25fil minus 0.25fil
+ .\hss.\hss.\hss.%
+ \hskip 0pt plus 0.5fil minus 0.5fil
+ }%
+ \spacefactor=3000
+ }
+
+
+ % @page forces the start of a new page
+ %
+ \def\page{\par\vfill\supereject}
+
+ % @exdent text....
+ % outputs text on separate line in roman font, starting at standard page margin
+
+ % This records the amount of indent in the innermost environment.
+ % That's how much \exdent should take out.
+ \newskip\exdentamount
+
+ % This defn is used inside fill environments such as @defun.
+ \def\exdent{\parsearg\exdentyyy}
+ \def\exdentyyy #1{{\hfil\break\hbox{\kern -\exdentamount{\rm#1}}\hfil\break}}
+
+ % This defn is used inside nofill environments such as @example.
+ \def\nofillexdent{\parsearg\nofillexdentyyy}
+ \def\nofillexdentyyy #1{{\advance \leftskip by -\exdentamount
+ \leftline{\hskip\leftskip{\rm#1}}}}
+
+ % @inmargin{TEXT} puts TEXT in the margin next to the current paragraph.
+
+ \def\inmargin#1{%
+ \strut\vadjust{\nobreak\kern-\strutdepth
+ \vtop to \strutdepth{\baselineskip\strutdepth\vss
+ \llap{\rightskip=\inmarginspacing \vbox{\noindent #1}}\null}}}
+ \newskip\inmarginspacing \inmarginspacing=1cm
+ \def\strutdepth{\dp\strutbox}
+
+ %\hbox{{\rm#1}}\hfil\break}}
+
+ % @include file insert text of that file as input.
+ % Allow normal characters that we make active in the argument (a file name).
+ \def\include{\begingroup
+ \catcode`\\=12
+ \catcode`~=12
+ \catcode`^=12
+ \catcode`_=12
+ \catcode`|=12
+ \catcode`<=12
+ \catcode`>=12
+ \catcode`+=12
+ \parsearg\includezzz}
+ % Restore active chars for included file.
+ \def\includezzz#1{\endgroup\begingroup
+ % Read the included file in a group so nested @include's work.
+ \def\thisfile{#1}%
+ \input\thisfile
+ \endgroup}
+
+ \def\thisfile{}
+
+ % @center line outputs that line, centered
+
+ \def\center{\parsearg\centerzzz}
+ \def\centerzzz #1{{\advance\hsize by -\leftskip
+ \advance\hsize by -\rightskip
+ \centerline{#1}}}
+
+ % @sp n outputs n lines of vertical space
+
+ \def\sp{\parsearg\spxxx}
+ \def\spxxx #1{\vskip #1\baselineskip}
+
+ % @comment ...line which is ignored...
+ % @c is the same as @comment
+ % @ignore ... @end ignore is another way to write a comment
+
+ \def\comment{\begingroup \catcode`\^^M=\other%
+ \catcode`\@=\other \catcode`\{=\other \catcode`\}=\other%
+ \commentxxx}
+ {\catcode`\^^M=\other \gdef\commentxxx#1^^M{\endgroup}}
+
+ \let\c=\comment
+
+ % @paragraphindent is defined for the Info formatting commands only.
+ \let\paragraphindent=\comment
+
+ % Prevent errors for section commands.
+ % Used in @ignore and in failing conditionals.
+ \def\ignoresections{%
+ \let\chapter=\relax
+ \let\unnumbered=\relax
+ \let\top=\relax
+ \let\unnumberedsec=\relax
+ \let\unnumberedsection=\relax
+ \let\unnumberedsubsec=\relax
+ \let\unnumberedsubsection=\relax
+ \let\unnumberedsubsubsec=\relax
+ \let\unnumberedsubsubsection=\relax
+ \let\section=\relax
+ \let\subsec=\relax
+ \let\subsubsec=\relax
+ \let\subsection=\relax
+ \let\subsubsection=\relax
+ \let\appendix=\relax
+ \let\appendixsec=\relax
+ \let\appendixsection=\relax
+ \let\appendixsubsec=\relax
+ \let\appendixsubsection=\relax
+ \let\appendixsubsubsec=\relax
+ \let\appendixsubsubsection=\relax
+ \let\contents=\relax
+ \let\smallbook=\relax
+ \let\titlepage=\relax
+ }
+
+ % Used in nested conditionals, where we have to parse the Texinfo source
+ % and so want to turn off most commands, in case they are used
+ % incorrectly.
+ %
+ \def\ignoremorecommands{%
+ \let\defcodeindex = \relax
+ \let\defcv = \relax
+ \let\deffn = \relax
+ \let\deffnx = \relax
+ \let\defindex = \relax
+ \let\defivar = \relax
+ \let\defmac = \relax
+ \let\defmethod = \relax
+ \let\defop = \relax
+ \let\defopt = \relax
+ \let\defspec = \relax
+ \let\deftp = \relax
+ \let\deftypefn = \relax
+ \let\deftypefun = \relax
+ \let\deftypevar = \relax
+ \let\deftypevr = \relax
+ \let\defun = \relax
+ \let\defvar = \relax
+ \let\defvr = \relax
+ \let\ref = \relax
+ \let\xref = \relax
+ \let\printindex = \relax
+ \let\pxref = \relax
+ \let\settitle = \relax
+ \let\setchapternewpage = \relax
+ \let\setchapterstyle = \relax
+ \let\everyheading = \relax
+ \let\evenheading = \relax
+ \let\oddheading = \relax
+ \let\everyfooting = \relax
+ \let\evenfooting = \relax
+ \let\oddfooting = \relax
+ \let\headings = \relax
+ \let\include = \relax
+ \let\lowersections = \relax
+ \let\down = \relax
+ \let\raisesections = \relax
+ \let\up = \relax
+ \let\set = \relax
+ \let\clear = \relax
+ \let\item = \relax
+ }
+
+ % Ignore @ignore ... @end ignore.
+ %
+ \def\ignore{\doignore{ignore}}
+
+ % Ignore @ifinfo, @ifhtml, @ifnottex, @html, @menu, and @direntry text.
+ %
+ \def\ifinfo{\doignore{ifinfo}}
+ \def\ifhtml{\doignore{ifhtml}}
+ \def\ifnottex{\doignore{ifnottex}}
+ \def\html{\doignore{html}}
+ \def\menu{\doignore{menu}}
+ \def\direntry{\doignore{direntry}}
+
+ % @dircategory CATEGORY -- specify a category of the dir file
+ % which this file should belong to. Ignore this in TeX.
+ \let\dircategory = \comment
+
+ % Ignore text until a line `@end #1'.
+ %
+ \def\doignore#1{\begingroup
+ % Don't complain about control sequences we have declared \outer.
+ \ignoresections
+ %
+ % Define a command to swallow text until we reach `@end #1'.
+ % This @ is a catcode 12 token (that is the normal catcode of @ in
+ % this texinfo.tex file). We change the catcode of @ below to match.
+ \long\def\doignoretext##1 at end #1{\enddoignore}%
+ %
+ % Make sure that spaces turn into tokens that match what \doignoretext wants.
+ \catcode32 = 10
+ %
+ % Ignore braces, too, so mismatched braces don't cause trouble.
+ \catcode`\{ = 9
+ \catcode`\} = 9
+ %
+ % We must not have @c interpreted as a control sequence.
+ \catcode`\@ = 12
+ %
+ % Make the letter c a comment character so that the rest of the line
+ % will be ignored. This way, the document can have (for example)
+ % @c @end ifinfo
+ % and the @end ifinfo will be properly ignored.
+ % (We've just changed @ to catcode 12.)
+ \catcode`\c = 14
+ %
+ % And now expand that command.
+ \doignoretext
+ }
+
+ % What we do to finish off ignored text.
+ %
+ \def\enddoignore{\endgroup\ignorespaces}%
+
+ \newif\ifwarnedobs\warnedobsfalse
+ \def\obstexwarn{%
+ \ifwarnedobs\relax\else
+ % We need to warn folks that they may have trouble with TeX 3.0.
+ % This uses \immediate\write16 rather than \message to get newlines.
+ \immediate\write16{}
+ \immediate\write16{***WARNING*** for users of Unix TeX 3.0!}
+ \immediate\write16{This manual trips a bug in TeX version 3.0 (tex hangs).}
+ \immediate\write16{If you are running another version of TeX, relax.}
+ \immediate\write16{If you are running Unix TeX 3.0, kill this TeX process.}
+ \immediate\write16{ Then upgrade your TeX installation if you can.}
+ \immediate\write16{ (See ftp://ftp.gnu.org/pub/gnu/TeX.README.)}
+ \immediate\write16{If you are stuck with version 3.0, run the}
+ \immediate\write16{ script ``tex3patch'' from the Texinfo distribution}
+ \immediate\write16{ to use a workaround.}
+ \immediate\write16{}
+ \global\warnedobstrue
+ \fi
+ }
+
+ % **In TeX 3.0, setting text in \nullfont hangs tex. For a
+ % workaround (which requires the file ``dummy.tfm'' to be installed),
+ % uncomment the following line:
+ %%%%%\font\nullfont=dummy\let\obstexwarn=\relax
+
+ % Ignore text, except that we keep track of conditional commands for
+ % purposes of nesting, up to an `@end #1' command.
+ %
+ \def\nestedignore#1{%
+ \obstexwarn
+ % We must actually expand the ignored text to look for the @end
+ % command, so that nested ignore constructs work. Thus, we put the
+ % text into a \vbox and then do nothing with the result. To minimize
+ % the change of memory overflow, we follow the approach outlined on
+ % page 401 of the TeXbook: make the current font be a dummy font.
+ %
+ \setbox0 = \vbox\bgroup
+ % Don't complain about control sequences we have declared \outer.
+ \ignoresections
+ %
+ % Define `@end #1' to end the box, which will in turn undefine the
+ % @end command again.
+ \expandafter\def\csname E#1\endcsname{\egroup\ignorespaces}%
+ %
+ % We are going to be parsing Texinfo commands. Most cause no
+ % trouble when they are used incorrectly, but some commands do
+ % complicated argument parsing or otherwise get confused, so we
+ % undefine them.
+ %
+ % We can't do anything about stray @-signs, unfortunately;
+ % they'll produce `undefined control sequence' errors.
+ \ignoremorecommands
+ %
+ % Set the current font to be \nullfont, a TeX primitive, and define
+ % all the font commands to also use \nullfont. We don't use
+ % dummy.tfm, as suggested in the TeXbook, because not all sites
+ % might have that installed. Therefore, math mode will still
+ % produce output, but that should be an extremely small amount of
+ % stuff compared to the main input.
+ %
+ \nullfont
+ \let\tenrm = \nullfont \let\tenit = \nullfont \let\tensl = \nullfont
+ \let\tenbf = \nullfont \let\tentt = \nullfont \let\smallcaps = \nullfont
+ \let\tensf = \nullfont
+ % Similarly for index fonts (mostly for their use in
+ % smallexample)
+ \let\indrm = \nullfont \let\indit = \nullfont \let\indsl = \nullfont
+ \let\indbf = \nullfont \let\indtt = \nullfont \let\indsc = \nullfont
+ \let\indsf = \nullfont
+ %
+ % Don't complain when characters are missing from the fonts.
+ \tracinglostchars = 0
+ %
+ % Don't bother to do space factor calculations.
+ \frenchspacing
+ %
+ % Don't report underfull hboxes.
+ \hbadness = 10000
+ %
+ % Do minimal line-breaking.
+ \pretolerance = 10000
+ %
+ % Do not execute instructions in @tex
+ \def\tex{\doignore{tex}}%
+ % Do not execute macro definitions.
+ % `c' is a comment character, so the word `macro' will get cut off.
+ \def\macro{\doignore{ma}}%
+ }
+
+ % @set VAR sets the variable VAR to an empty value.
+ % @set VAR REST-OF-LINE sets VAR to the value REST-OF-LINE.
+ %
+ % Since we want to separate VAR from REST-OF-LINE (which might be
+ % empty), we can't just use \parsearg; we have to insert a space of our
+ % own to delimit the rest of the line, and then take it out again if we
+ % didn't need it. Make sure the catcode of space is correct to avoid
+ % losing inside @example, for instance.
+ %
+ \def\set{\begingroup\catcode` =10
+ \catcode`\-=12 \catcode`\_=12 % Allow - and _ in VAR.
+ \parsearg\setxxx}
+ \def\setxxx#1{\setyyy#1 \endsetyyy}
+ \def\setyyy#1 #2\endsetyyy{%
+ \def\temp{#2}%
+ \ifx\temp\empty \global\expandafter\let\csname SET#1\endcsname = \empty
+ \else \setzzz{#1}#2\endsetzzz % Remove the trailing space \setxxx inserted.
+ \fi
+ \endgroup
+ }
+ % Can't use \xdef to pre-expand #2 and save some time, since \temp or
+ % \next or other control sequences that we've defined might get us into
+ % an infinite loop. Consider `@set foo @cite{bar}'.
+ \def\setzzz#1#2 \endsetzzz{\expandafter\gdef\csname SET#1\endcsname{#2}}
+
+ % @clear VAR clears (i.e., unsets) the variable VAR.
+ %
+ \def\clear{\parsearg\clearxxx}
+ \def\clearxxx#1{\global\expandafter\let\csname SET#1\endcsname=\relax}
+
+ % @value{foo} gets the text saved in variable foo.
+ %
+ {
+ \catcode`\_ = \active
+ %
+ % We might end up with active _ or - characters in the argument if
+ % we're called from @code, as @code{@value{foo-bar_}}. So \let any
+ % such active characters to their normal equivalents.
+ \gdef\value{\begingroup
+ \catcode`\-=12 \catcode`\_=12
+ \indexbreaks \let_\normalunderscore
+ \valuexxx}
+ }
+ \def\valuexxx#1{\expandablevalue{#1}\endgroup}
+
+ % We have this subroutine so that we can handle at least some @value's
+ % properly in indexes (we \let\value to this in \indexdummies). Ones
+ % whose names contain - or _ still won't work, but we can't do anything
+ % about that. The command has to be fully expandable, since the result
+ % winds up in the index file. This means that if the variable's value
+ % contains other Texinfo commands, it's almost certain it will fail
+ % (although perhaps we could fix that with sufficient work to do a
+ % one-level expansion on the result, instead of complete).
+ %
+ \def\expandablevalue#1{%
+ \expandafter\ifx\csname SET#1\endcsname\relax
+ {[No value for ``#1'']}%
+ \else
+ \csname SET#1\endcsname
+ \fi
+ }
+
+ % @ifset VAR ... @end ifset reads the `...' iff VAR has been defined
+ % with @set.
+ %
+ \def\ifset{\parsearg\ifsetxxx}
+ \def\ifsetxxx #1{%
+ \expandafter\ifx\csname SET#1\endcsname\relax
+ \expandafter\ifsetfail
+ \else
+ \expandafter\ifsetsucceed
+ \fi
+ }
+ \def\ifsetsucceed{\conditionalsucceed{ifset}}
+ \def\ifsetfail{\nestedignore{ifset}}
+ \defineunmatchedend{ifset}
+
+ % @ifclear VAR ... @end ifclear reads the `...' iff VAR has never been
+ % defined with @set, or has been undefined with @clear.
+ %
+ \def\ifclear{\parsearg\ifclearxxx}
+ \def\ifclearxxx #1{%
+ \expandafter\ifx\csname SET#1\endcsname\relax
+ \expandafter\ifclearsucceed
+ \else
+ \expandafter\ifclearfail
+ \fi
+ }
+ \def\ifclearsucceed{\conditionalsucceed{ifclear}}
+ \def\ifclearfail{\nestedignore{ifclear}}
+ \defineunmatchedend{ifclear}
+
+ % @iftex, @ifnothtml, @ifnotinfo always succeed; we read the text
+ % following, through the first @end iftex (etc.). Make `@end iftex'
+ % (etc.) valid only after an @iftex.
+ %
+ \def\iftex{\conditionalsucceed{iftex}}
+ \def\ifnothtml{\conditionalsucceed{ifnothtml}}
+ \def\ifnotinfo{\conditionalsucceed{ifnotinfo}}
+ \defineunmatchedend{iftex}
+ \defineunmatchedend{ifnothtml}
+ \defineunmatchedend{ifnotinfo}
+
+ % We can't just want to start a group at @iftex (for example) and end it
+ % at @end iftex, since then @set commands inside the conditional have no
+ % effect (they'd get reverted at the end of the group). So we must
+ % define \Eiftex to redefine itself to be its previous value. (We can't
+ % just define it to fail again with an ``unmatched end'' error, since
+ % the @ifset might be nested.)
+ %
+ \def\conditionalsucceed#1{%
+ \edef\temp{%
+ % Remember the current value of \E#1.
+ \let\nece{prevE#1} = \nece{E#1}%
+ %
+ % At the `@end #1', redefine \E#1 to be its previous value.
+ \def\nece{E#1}{\let\nece{E#1} = \nece{prevE#1}}%
+ }%
+ \temp
+ }
+
+ % We need to expand lots of \csname's, but we don't want to expand the
+ % control sequences after we've constructed them.
+ %
+ \def\nece#1{\expandafter\noexpand\csname#1\endcsname}
+
+ % @asis just yields its argument. Used with @table, for example.
+ %
+ \def\asis#1{#1}
+
+ % @math means output in math mode.
+ % We don't use $'s directly in the definition of \math because control
+ % sequences like \math are expanded when the toc file is written. Then,
+ % we read the toc file back, the $'s will be normal characters (as they
+ % should be, according to the definition of Texinfo). So we must use a
+ % control sequence to switch into and out of math mode.
+ %
+ % This isn't quite enough for @math to work properly in indices, but it
+ % seems unlikely it will ever be needed there.
+ %
+ \let\implicitmath = $
+ \def\math#1{\implicitmath #1\implicitmath}
+
+ % @bullet and @minus need the same treatment as @math, just above.
+ \def\bullet{\implicitmath\ptexbullet\implicitmath}
+ \def\minus{\implicitmath-\implicitmath}
+
+ % @refill is a no-op.
+ \let\refill=\relax
+
+ % If working on a large document in chapters, it is convenient to
+ % be able to disable indexing, cross-referencing, and contents, for test runs.
+ % This is done with @novalidate (before @setfilename).
+ %
+ \newif\iflinks \linkstrue % by default we want the aux files.
+ \let\novalidate = \linksfalse
+
+ % @setfilename is done at the beginning of every texinfo file.
+ % So open here the files we need to have open while reading the input.
+ % This makes it possible to make a .fmt file for texinfo.
+ \def\setfilename{%
+ \iflinks
+ \readauxfile
+ \fi % \openindices needs to do some work in any case.
+ \openindices
+ \fixbackslash % Turn off hack to swallow `\input texinfo'.
+ \global\let\setfilename=\comment % Ignore extra @setfilename cmds.
+ %
+ % If texinfo.cnf is present on the system, read it.
+ % Useful for site-wide @afourpaper, etc.
+ % Just to be on the safe side, close the input stream before the \input.
+ \openin 1 texinfo.cnf
+ \ifeof1 \let\temp=\relax \else \def\temp{\input texinfo.cnf }\fi
+ \closein1
+ \temp
+ %
+ \comment % Ignore the actual filename.
+ }
+
+ % Called from \setfilename.
+ %
+ \def\openindices{%
+ \newindex{cp}%
+ \newcodeindex{fn}%
+ \newcodeindex{vr}%
+ \newcodeindex{tp}%
+ \newcodeindex{ky}%
+ \newcodeindex{pg}%
+ }
+
+ % @bye.
+ \outer\def\bye{\pagealignmacro\tracingstats=1\ptexend}
+
+
+ \message{fonts,}
+ % Font-change commands.
+
+ % Texinfo sort of supports the sans serif font style, which plain TeX does not.
+ % So we set up a \sf analogous to plain's \rm, etc.
+ \newfam\sffam
+ \def\sf{\fam=\sffam \tensf}
+ \let\li = \sf % Sometimes we call it \li, not \sf.
+
+ % We don't need math for this one.
+ \def\ttsl{\tenttsl}
+
+ % Use Computer Modern fonts at \magstephalf (11pt).
+ \newcount\mainmagstep
+ \mainmagstep=\magstephalf
+
+ % Set the font macro #1 to the font named #2, adding on the
+ % specified font prefix (normally `cm').
+ % #3 is the font's design size, #4 is a scale factor
+ \def\setfont#1#2#3#4{\font#1=\fontprefix#2#3 scaled #4}
+
+ % Use cm as the default font prefix.
+ % To specify the font prefix, you must define \fontprefix
+ % before you read in texinfo.tex.
+ \ifx\fontprefix\undefined
+ \def\fontprefix{cm}
+ \fi
+ % Support font families that don't use the same naming scheme as CM.
+ \def\rmshape{r}
+ \def\rmbshape{bx} %where the normal face is bold
+ \def\bfshape{b}
+ \def\bxshape{bx}
+ \def\ttshape{tt}
+ \def\ttbshape{tt}
+ \def\ttslshape{sltt}
+ \def\itshape{ti}
+ \def\itbshape{bxti}
+ \def\slshape{sl}
+ \def\slbshape{bxsl}
+ \def\sfshape{ss}
+ \def\sfbshape{ss}
+ \def\scshape{csc}
+ \def\scbshape{csc}
+
+ \ifx\bigger\relax
+ \let\mainmagstep=\magstep1
+ \setfont\textrm\rmshape{12}{1000}
+ \setfont\texttt\ttshape{12}{1000}
+ \else
+ \setfont\textrm\rmshape{10}{\mainmagstep}
+ \setfont\texttt\ttshape{10}{\mainmagstep}
+ \fi
+ % Instead of cmb10, you many want to use cmbx10.
+ % cmbx10 is a prettier font on its own, but cmb10
+ % looks better when embedded in a line with cmr10.
+ \setfont\textbf\bfshape{10}{\mainmagstep}
+ \setfont\textit\itshape{10}{\mainmagstep}
+ \setfont\textsl\slshape{10}{\mainmagstep}
+ \setfont\textsf\sfshape{10}{\mainmagstep}
+ \setfont\textsc\scshape{10}{\mainmagstep}
+ \setfont\textttsl\ttslshape{10}{\mainmagstep}
+ \font\texti=cmmi10 scaled \mainmagstep
+ \font\textsy=cmsy10 scaled \mainmagstep
+
+ % A few fonts for @defun, etc.
+ \setfont\defbf\bxshape{10}{\magstep1} %was 1314
+ \setfont\deftt\ttshape{10}{\magstep1}
+ \def\df{\let\tentt=\deftt \let\tenbf = \defbf \bf}
+
+ % Fonts for indices and small examples (9pt).
+ % We actually use the slanted font rather than the italic,
+ % because texinfo normally uses the slanted fonts for that.
+ % Do not make many font distinctions in general in the index, since they
+ % aren't very useful.
+ \setfont\ninett\ttshape{9}{1000}
+ \setfont\ninettsl\ttslshape{10}{900}
+ \setfont\indrm\rmshape{9}{1000}
+ \setfont\indit\itshape{9}{1000}
+ \setfont\indsl\slshape{9}{1000}
+ \let\indtt=\ninett
+ \let\indttsl=\ninettsl
+ \let\indsf=\indrm
+ \let\indbf=\indrm
+ \setfont\indsc\scshape{10}{900}
+ \font\indi=cmmi9
+ \font\indsy=cmsy9
+
+ % Fonts for title page:
+ \setfont\titlerm\rmbshape{12}{\magstep3}
+ \setfont\titleit\itbshape{10}{\magstep4}
+ \setfont\titlesl\slbshape{10}{\magstep4}
+ \setfont\titlett\ttbshape{12}{\magstep3}
+ \setfont\titlettsl\ttslshape{10}{\magstep4}
+ \setfont\titlesf\sfbshape{17}{\magstep1}
+ \let\titlebf=\titlerm
+ \setfont\titlesc\scbshape{10}{\magstep4}
+ \font\titlei=cmmi12 scaled \magstep3
+ \font\titlesy=cmsy10 scaled \magstep4
+ \def\authorrm{\secrm}
+
+ % Chapter (and unnumbered) fonts (17.28pt).
+ \setfont\chaprm\rmbshape{12}{\magstep2}
+ \setfont\chapit\itbshape{10}{\magstep3}
+ \setfont\chapsl\slbshape{10}{\magstep3}
+ \setfont\chaptt\ttbshape{12}{\magstep2}
+ \setfont\chapttsl\ttslshape{10}{\magstep3}
+ \setfont\chapsf\sfbshape{17}{1000}
+ \let\chapbf=\chaprm
+ \setfont\chapsc\scbshape{10}{\magstep3}
+ \font\chapi=cmmi12 scaled \magstep2
+ \font\chapsy=cmsy10 scaled \magstep3
+
+ % Section fonts (14.4pt).
+ \setfont\secrm\rmbshape{12}{\magstep1}
+ \setfont\secit\itbshape{10}{\magstep2}
+ \setfont\secsl\slbshape{10}{\magstep2}
+ \setfont\sectt\ttbshape{12}{\magstep1}
+ \setfont\secttsl\ttslshape{10}{\magstep2}
+ \setfont\secsf\sfbshape{12}{\magstep1}
+ \let\secbf\secrm
+ \setfont\secsc\scbshape{10}{\magstep2}
+ \font\seci=cmmi12 scaled \magstep1
+ \font\secsy=cmsy10 scaled \magstep2
+
+ % \setfont\ssecrm\bxshape{10}{\magstep1} % This size an font looked bad.
+ % \setfont\ssecit\itshape{10}{\magstep1} % The letters were too crowded.
+ % \setfont\ssecsl\slshape{10}{\magstep1}
+ % \setfont\ssectt\ttshape{10}{\magstep1}
+ % \setfont\ssecsf\sfshape{10}{\magstep1}
+
+ %\setfont\ssecrm\bfshape{10}{1315} % Note the use of cmb rather than cmbx.
+ %\setfont\ssecit\itshape{10}{1315} % Also, the size is a little larger than
+ %\setfont\ssecsl\slshape{10}{1315} % being scaled magstep1.
+ %\setfont\ssectt\ttshape{10}{1315}
+ %\setfont\ssecsf\sfshape{10}{1315}
+
+ %\let\ssecbf=\ssecrm
+
+ % Subsection fonts (13.15pt).
+ \setfont\ssecrm\rmbshape{12}{\magstephalf}
+ \setfont\ssecit\itbshape{10}{1315}
+ \setfont\ssecsl\slbshape{10}{1315}
+ \setfont\ssectt\ttbshape{12}{\magstephalf}
+ \setfont\ssecttsl\ttslshape{10}{1315}
+ \setfont\ssecsf\sfbshape{12}{\magstephalf}
+ \let\ssecbf\ssecrm
+ \setfont\ssecsc\scbshape{10}{\magstep1}
+ \font\sseci=cmmi12 scaled \magstephalf
+ \font\ssecsy=cmsy10 scaled 1315
+ % The smallcaps and symbol fonts should actually be scaled \magstep1.5,
+ % but that is not a standard magnification.
+
+ % In order for the font changes to affect most math symbols and letters,
+ % we have to define the \textfont of the standard families. Since
+ % texinfo doesn't allow for producing subscripts and superscripts, we
+ % don't bother to reset \scriptfont and \scriptscriptfont (which would
+ % also require loading a lot more fonts).
+ %
+ \def\resetmathfonts{%
+ \textfont0 = \tenrm \textfont1 = \teni \textfont2 = \tensy
+ \textfont\itfam = \tenit \textfont\slfam = \tensl \textfont\bffam = \tenbf
+ \textfont\ttfam = \tentt \textfont\sffam = \tensf
+ }
+
+
+ % The font-changing commands redefine the meanings of \tenSTYLE, instead
+ % of just \STYLE. We do this so that font changes will continue to work
+ % in math mode, where it is the current \fam that is relevant in most
+ % cases, not the current font. Plain TeX does \def\bf{\fam=\bffam
+ % \tenbf}, for example. By redefining \tenbf, we obviate the need to
+ % redefine \bf itself.
+ \def\textfonts{%
+ \let\tenrm=\textrm \let\tenit=\textit \let\tensl=\textsl
+ \let\tenbf=\textbf \let\tentt=\texttt \let\smallcaps=\textsc
+ \let\tensf=\textsf \let\teni=\texti \let\tensy=\textsy \let\tenttsl=\textttsl
+ \resetmathfonts}
+ \def\titlefonts{%
+ \let\tenrm=\titlerm \let\tenit=\titleit \let\tensl=\titlesl
+ \let\tenbf=\titlebf \let\tentt=\titlett \let\smallcaps=\titlesc
+ \let\tensf=\titlesf \let\teni=\titlei \let\tensy=\titlesy
+ \let\tenttsl=\titlettsl
+ \resetmathfonts \setleading{25pt}}
+ \def\titlefont#1{{\titlefonts\rm #1}}
+ \def\chapfonts{%
+ \let\tenrm=\chaprm \let\tenit=\chapit \let\tensl=\chapsl
+ \let\tenbf=\chapbf \let\tentt=\chaptt \let\smallcaps=\chapsc
+ \let\tensf=\chapsf \let\teni=\chapi \let\tensy=\chapsy \let\tenttsl=\chapttsl
+ \resetmathfonts \setleading{19pt}}
+ \def\secfonts{%
+ \let\tenrm=\secrm \let\tenit=\secit \let\tensl=\secsl
+ \let\tenbf=\secbf \let\tentt=\sectt \let\smallcaps=\secsc
+ \let\tensf=\secsf \let\teni=\seci \let\tensy=\secsy \let\tenttsl=\secttsl
+ \resetmathfonts \setleading{16pt}}
+ \def\subsecfonts{%
+ \let\tenrm=\ssecrm \let\tenit=\ssecit \let\tensl=\ssecsl
+ \let\tenbf=\ssecbf \let\tentt=\ssectt \let\smallcaps=\ssecsc
+ \let\tensf=\ssecsf \let\teni=\sseci \let\tensy=\ssecsy \let\tenttsl=\ssecttsl
+ \resetmathfonts \setleading{15pt}}
+ \let\subsubsecfonts = \subsecfonts % Maybe make sssec fonts scaled magstephalf?
+ \def\indexfonts{%
+ \let\tenrm=\indrm \let\tenit=\indit \let\tensl=\indsl
+ \let\tenbf=\indbf \let\tentt=\indtt \let\smallcaps=\indsc
+ \let\tensf=\indsf \let\teni=\indi \let\tensy=\indsy \let\tenttsl=\indttsl
+ \resetmathfonts \setleading{12pt}}
+
+ % Set up the default fonts, so we can use them for creating boxes.
+ %
+ \textfonts
+
+ % Define these so they can be easily changed for other fonts.
+ \def\angleleft{$\langle$}
+ \def\angleright{$\rangle$}
+
+ % Count depth in font-changes, for error checks
+ \newcount\fontdepth \fontdepth=0
+
+ % Fonts for short table of contents.
+ \setfont\shortcontrm\rmshape{12}{1000}
+ \setfont\shortcontbf\bxshape{12}{1000}
+ \setfont\shortcontsl\slshape{12}{1000}
+
+ %% Add scribe-like font environments, plus @l for inline lisp (usually sans
+ %% serif) and @ii for TeX italic
+
+ % \smartitalic{ARG} outputs arg in italics, followed by an italic correction
+ % unless the following character is such as not to need one.
+ \def\smartitalicx{\ifx\next,\else\ifx\next-\else\ifx\next.\else\/\fi\fi\fi}
+ \def\smartslanted#1{{\sl #1}\futurelet\next\smartitalicx}
+ \def\smartitalic#1{{\it #1}\futurelet\next\smartitalicx}
+
+ \let\i=\smartitalic
+ \let\var=\smartslanted
+ \let\dfn=\smartslanted
+ \let\emph=\smartitalic
+ \let\cite=\smartslanted
+
+ \def\b#1{{\bf #1}}
+ \let\strong=\b
+
+ % We can't just use \exhyphenpenalty, because that only has effect at
+ % the end of a paragraph. Restore normal hyphenation at the end of the
+ % group within which \nohyphenation is presumably called.
+ %
+ \def\nohyphenation{\hyphenchar\font = -1 \aftergroup\restorehyphenation}
+ \def\restorehyphenation{\hyphenchar\font = `- }
+
+ \def\t#1{%
+ {\tt \rawbackslash \frenchspacing #1}%
+ \null
+ }
+ \let\ttfont=\t
+ \def\samp#1{`\tclose{#1}'\null}
+ \setfont\smallrm\rmshape{8}{1000}
+ \font\smallsy=cmsy9
+ \def\key#1{{\smallrm\textfont2=\smallsy \leavevmode\hbox{%
+ \raise0.4pt\hbox{\angleleft}\kern-.08em\vtop{%
+ \vbox{\hrule\kern-0.4pt
+ \hbox{\raise0.4pt\hbox{\vphantom{\angleleft}}#1}}%
+ \kern-0.4pt\hrule}%
+ \kern-.06em\raise0.4pt\hbox{\angleright}}}}
+ % The old definition, with no lozenge:
+ %\def\key #1{{\ttsl \nohyphenation \uppercase{#1}}\null}
+ \def\ctrl #1{{\tt \rawbackslash \hat}#1}
+
+ % @file, @option are the same as @samp.
+ \let\file=\samp
+ \let\option=\samp
+
+ % @code is a modification of @t,
+ % which makes spaces the same size as normal in the surrounding text.
+ \def\tclose#1{%
+ {%
+ % Change normal interword space to be same as for the current font.
+ \spaceskip = \fontdimen2\font
+ %
+ % Switch to typewriter.
+ \tt
+ %
+ % But `\ ' produces the large typewriter interword space.
+ \def\ {{\spaceskip = 0pt{} }}%
+ %
+ % Turn off hyphenation.
+ \nohyphenation
+ %
+ \rawbackslash
+ \frenchspacing
+ #1%
+ }%
+ \null
+ }
+
+ % We *must* turn on hyphenation at `-' and `_' in \code.
+ % Otherwise, it is too hard to avoid overfull hboxes
+ % in the Emacs manual, the Library manual, etc.
+
+ % Unfortunately, TeX uses one parameter (\hyphenchar) to control
+ % both hyphenation at - and hyphenation within words.
+ % We must therefore turn them both off (\tclose does that)
+ % and arrange explicitly to hyphenate at a dash.
+ % -- rms.
+ {
+ \catcode`\-=\active
+ \catcode`\_=\active
+ %
+ \global\def\code{\begingroup
+ \catcode`\-=\active \let-\codedash
+ \catcode`\_=\active \let_\codeunder
+ \codex
+ }
+ %
+ % If we end up with any active - characters when handling the index,
+ % just treat them as a normal -.
+ \global\def\indexbreaks{\catcode`\-=\active \let-\realdash}
+ }
+
+ \def\realdash{-}
+ \def\codedash{-\discretionary{}{}{}}
+ \def\codeunder{\ifusingtt{\normalunderscore\discretionary{}{}{}}{\_}}
+ \def\codex #1{\tclose{#1}\endgroup}
+
+ %\let\exp=\tclose %Was temporary
+
+ % @kbd is like @code, except that if the argument is just one @key command,
+ % then @kbd has no effect.
+
+ % @kbdinputstyle -- arg is `distinct' (@kbd uses slanted tty font always),
+ % `example' (@kbd uses ttsl only inside of @example and friends),
+ % or `code' (@kbd uses normal tty font always).
+ \def\kbdinputstyle{\parsearg\kbdinputstylexxx}
+ \def\kbdinputstylexxx#1{%
+ \def\arg{#1}%
+ \ifx\arg\worddistinct
+ \gdef\kbdexamplefont{\ttsl}\gdef\kbdfont{\ttsl}%
+ \else\ifx\arg\wordexample
+ \gdef\kbdexamplefont{\ttsl}\gdef\kbdfont{\tt}%
+ \else\ifx\arg\wordcode
+ \gdef\kbdexamplefont{\tt}\gdef\kbdfont{\tt}%
+ \fi\fi\fi
+ }
+ \def\worddistinct{distinct}
+ \def\wordexample{example}
+ \def\wordcode{code}
+
+ % Default is kbdinputdistinct. (Too much of a hassle to call the macro,
+ % the catcodes are wrong for parsearg to work.)
+ \gdef\kbdexamplefont{\ttsl}\gdef\kbdfont{\ttsl}
+
+ \def\xkey{\key}
+ \def\kbdfoo#1#2#3\par{\def\one{#1}\def\three{#3}\def\threex{??}%
+ \ifx\one\xkey\ifx\threex\three \key{#2}%
+ \else{\tclose{\kbdfont\look}}\fi
+ \else{\tclose{\kbdfont\look}}\fi}
+
+ % For @url, @env, @command quotes seem unnecessary, so use \code.
+ \let\url=\code
+ \let\env=\code
+ \let\command=\code
+
+ % @uref (abbreviation for `urlref') takes an optional second argument
+ % specifying the text to display. First (mandatory) arg is the url.
+ % Perhaps eventually put in a hypertex \special here.
+ %
+ \def\uref#1{\urefxxx #1,,\finish}
+ \def\urefxxx#1,#2,#3\finish{%
+ \setbox0 = \hbox{\ignorespaces #2}%
+ \ifdim\wd0 > 0pt
+ \unhbox0\ (\code{#1})%
+ \else
+ \code{#1}%
+ \fi
+ }
+
+ % rms does not like the angle brackets --karl, 17may97.
+ % So now @email is just like @uref.
+ %\def\email#1{\angleleft{\tt #1}\angleright}
+ \let\email=\uref
+
+ % Check if we are currently using a typewriter font. Since all the
+ % Computer Modern typewriter fonts have zero interword stretch (and
+ % shrink), and it is reasonable to expect all typewriter fonts to have
+ % this property, we can check that font parameter.
+ %
+ \def\ifmonospace{\ifdim\fontdimen3\font=0pt }
+
+ % Typeset a dimension, e.g., `in' or `pt'. The only reason for the
+ % argument is to make the input look right: @dmn{pt} instead of @dmn{}pt.
+ %
+ \def\dmn#1{\thinspace #1}
+
+ \def\kbd#1{\def\look{#1}\expandafter\kbdfoo\look??\par}
+
+ % @l was never documented to mean ``switch to the Lisp font'',
+ % and it is not used as such in any manual I can find. We need it for
+ % Polish suppressed-l. --karl, 22sep96.
+ %\def\l#1{{\li #1}\null}
+
+ % Explicit font changes: @r, @sc, undocumented @ii.
+ \def\r#1{{\rm #1}} % roman font
+ \def\sc#1{{\smallcaps#1}} % smallcaps font
+ \def\ii#1{{\it #1}} % italic font
+
+ % @acronym downcases the argument and prints in smallcaps.
+ \def\acronym#1{{\smallcaps \lowercase{#1}}}
+
+ % @pounds{} is a sterling sign.
+ \def\pounds{{\it\$}}
+
+
+ \message{page headings,}
+
+ \newskip\titlepagetopglue \titlepagetopglue = 1.5in
+ \newskip\titlepagebottomglue \titlepagebottomglue = 2pc
+
+ % First the title page. Must do @settitle before @titlepage.
+ \newif\ifseenauthor
+ \newif\iffinishedtitlepage
+
+ % Do an implicit @contents or @shortcontents after @end titlepage if the
+ % user says @setcontentsaftertitlepage or @setshortcontentsaftertitlepage.
+ %
+ \newif\ifsetcontentsaftertitlepage
+ \let\setcontentsaftertitlepage = \setcontentsaftertitlepagetrue
+ \newif\ifsetshortcontentsaftertitlepage
+ \let\setshortcontentsaftertitlepage = \setshortcontentsaftertitlepagetrue
+
+ \def\shorttitlepage{\parsearg\shorttitlepagezzz}
+ \def\shorttitlepagezzz #1{\begingroup\hbox{}\vskip 1.5in \chaprm \centerline{#1}%
+ \endgroup\page\hbox{}\page}
+
+ \def\titlepage{\begingroup \parindent=0pt \textfonts
+ \let\subtitlerm=\tenrm
+ \def\subtitlefont{\subtitlerm \normalbaselineskip = 13pt \normalbaselines}%
+ %
+ \def\authorfont{\authorrm \normalbaselineskip = 16pt \normalbaselines}%
+ %
+ % Leave some space at the very top of the page.
+ \vglue\titlepagetopglue
+ %
+ % Now you can print the title using @title.
+ \def\title{\parsearg\titlezzz}%
+ \def\titlezzz##1{\leftline{\titlefonts\rm ##1}
+ % print a rule at the page bottom also.
+ \finishedtitlepagefalse
+ \vskip4pt \hrule height 4pt width \hsize \vskip4pt}%
+ % No rule at page bottom unless we print one at the top with @title.
+ \finishedtitlepagetrue
+ %
+ % Now you can put text using @subtitle.
+ \def\subtitle{\parsearg\subtitlezzz}%
+ \def\subtitlezzz##1{{\subtitlefont \rightline{##1}}}%
+ %
+ % @author should come last, but may come many times.
+ \def\author{\parsearg\authorzzz}%
+ \def\authorzzz##1{\ifseenauthor\else\vskip 0pt plus 1filll\seenauthortrue\fi
+ {\authorfont \leftline{##1}}}%
+ %
+ % Most title ``pages'' are actually two pages long, with space
+ % at the top of the second. We don't want the ragged left on the second.
+ \let\oldpage = \page
+ \def\page{%
+ \iffinishedtitlepage\else
+ \finishtitlepage
+ \fi
+ \oldpage
+ \let\page = \oldpage
+ \hbox{}}%
+ % \def\page{\oldpage \hbox{}}
+ }
+
+ \def\Etitlepage{%
+ \iffinishedtitlepage\else
+ \finishtitlepage
+ \fi
+ % It is important to do the page break before ending the group,
+ % because the headline and footline are only empty inside the group.
+ % If we use the new definition of \page, we always get a blank page
+ % after the title page, which we certainly don't want.
+ \oldpage
+ \endgroup
+ %
+ % If they want short, they certainly want long too.
+ \ifsetshortcontentsaftertitlepage
+ \shortcontents
+ \contents
+ \global\let\shortcontents = \relax
+ \global\let\contents = \relax
+ \fi
+ %
+ \ifsetcontentsaftertitlepage
+ \contents
+ \global\let\contents = \relax
+ \global\let\shortcontents = \relax
+ \fi
+ %
+ \HEADINGSon
+ }
+
+ \def\finishtitlepage{%
+ \vskip4pt \hrule height 2pt width \hsize
+ \vskip\titlepagebottomglue
+ \finishedtitlepagetrue
+ }
+
+ %%% Set up page headings and footings.
+
+ \let\thispage=\folio
+
+ \newtoks\evenheadline % headline on even pages
+ \newtoks\oddheadline % headline on odd pages
+ \newtoks\evenfootline % footline on even pages
+ \newtoks\oddfootline % footline on odd pages
+
+ % Now make Tex use those variables
+ \headline={{\textfonts\rm \ifodd\pageno \the\oddheadline
+ \else \the\evenheadline \fi}}
+ \footline={{\textfonts\rm \ifodd\pageno \the\oddfootline
+ \else \the\evenfootline \fi}\HEADINGShook}
+ \let\HEADINGShook=\relax
+
+ % Commands to set those variables.
+ % For example, this is what @headings on does
+ % @evenheading @thistitle|@thispage|@thischapter
+ % @oddheading @thischapter|@thispage|@thistitle
+ % @evenfooting @thisfile||
+ % @oddfooting ||@thisfile
+
+ \def\evenheading{\parsearg\evenheadingxxx}
+ \def\oddheading{\parsearg\oddheadingxxx}
+ \def\everyheading{\parsearg\everyheadingxxx}
+
+ \def\evenfooting{\parsearg\evenfootingxxx}
+ \def\oddfooting{\parsearg\oddfootingxxx}
+ \def\everyfooting{\parsearg\everyfootingxxx}
+
+ {\catcode`\@=0 %
+
+ \gdef\evenheadingxxx #1{\evenheadingyyy #1@|@|@|@|\finish}
+ \gdef\evenheadingyyy #1@|#2@|#3@|#4\finish{%
+ \global\evenheadline={\rlap{\centerline{#2}}\line{#1\hfil#3}}}
+
+ \gdef\oddheadingxxx #1{\oddheadingyyy #1@|@|@|@|\finish}
+ \gdef\oddheadingyyy #1@|#2@|#3@|#4\finish{%
+ \global\oddheadline={\rlap{\centerline{#2}}\line{#1\hfil#3}}}
+
+ \gdef\everyheadingxxx#1{\oddheadingxxx{#1}\evenheadingxxx{#1}}%
+
+ \gdef\evenfootingxxx #1{\evenfootingyyy #1@|@|@|@|\finish}
+ \gdef\evenfootingyyy #1@|#2@|#3@|#4\finish{%
+ \global\evenfootline={\rlap{\centerline{#2}}\line{#1\hfil#3}}}
+
+ \gdef\oddfootingxxx #1{\oddfootingyyy #1@|@|@|@|\finish}
+ \gdef\oddfootingyyy #1@|#2@|#3@|#4\finish{%
+ \global\oddfootline = {\rlap{\centerline{#2}}\line{#1\hfil#3}}%
+ %
+ % Leave some space for the footline. Hopefully ok to assume
+ % @evenfooting will not be used by itself.
+ \global\advance\pageheight by -\baselineskip
+ \global\advance\vsize by -\baselineskip
+ }
+
+ \gdef\everyfootingxxx#1{\oddfootingxxx{#1}\evenfootingxxx{#1}}
+ %
+ }% unbind the catcode of @.
+
+ % @headings double turns headings on for double-sided printing.
+ % @headings single turns headings on for single-sided printing.
+ % @headings off turns them off.
+ % @headings on same as @headings double, retained for compatibility.
+ % @headings after turns on double-sided headings after this page.
+ % @headings doubleafter turns on double-sided headings after this page.
+ % @headings singleafter turns on single-sided headings after this page.
+ % By default, they are off at the start of a document,
+ % and turned `on' after @end titlepage.
+
+ \def\headings #1 {\csname HEADINGS#1\endcsname}
+
+ \def\HEADINGSoff{
+ \global\evenheadline={\hfil} \global\evenfootline={\hfil}
+ \global\oddheadline={\hfil} \global\oddfootline={\hfil}}
+ \HEADINGSoff
+ % When we turn headings on, set the page number to 1.
+ % For double-sided printing, put current file name in lower left corner,
+ % chapter name on inside top of right hand pages, document
+ % title on inside top of left hand pages, and page numbers on outside top
+ % edge of all pages.
+ \def\HEADINGSdouble{
+ \global\pageno=1
+ \global\evenfootline={\hfil}
+ \global\oddfootline={\hfil}
+ \global\evenheadline={\line{\folio\hfil\thistitle}}
+ \global\oddheadline={\line{\thischapter\hfil\folio}}
+ \global\let\contentsalignmacro = \chapoddpage
+ }
+ \let\contentsalignmacro = \chappager
+
+ % For single-sided printing, chapter title goes across top left of page,
+ % page number on top right.
+ \def\HEADINGSsingle{
+ \global\pageno=1
+ \global\evenfootline={\hfil}
+ \global\oddfootline={\hfil}
+ \global\evenheadline={\line{\thischapter\hfil\folio}}
+ \global\oddheadline={\line{\thischapter\hfil\folio}}
+ \global\let\contentsalignmacro = \chappager
+ }
+ \def\HEADINGSon{\HEADINGSdouble}
+
+ \def\HEADINGSafter{\let\HEADINGShook=\HEADINGSdoublex}
+ \let\HEADINGSdoubleafter=\HEADINGSafter
+ \def\HEADINGSdoublex{%
+ \global\evenfootline={\hfil}
+ \global\oddfootline={\hfil}
+ \global\evenheadline={\line{\folio\hfil\thistitle}}
+ \global\oddheadline={\line{\thischapter\hfil\folio}}
+ \global\let\contentsalignmacro = \chapoddpage
+ }
+
+ \def\HEADINGSsingleafter{\let\HEADINGShook=\HEADINGSsinglex}
+ \def\HEADINGSsinglex{%
+ \global\evenfootline={\hfil}
+ \global\oddfootline={\hfil}
+ \global\evenheadline={\line{\thischapter\hfil\folio}}
+ \global\oddheadline={\line{\thischapter\hfil\folio}}
+ \global\let\contentsalignmacro = \chappager
+ }
+
+ % Subroutines used in generating headings
+ % Produces Day Month Year style of output.
+ \def\today{\number\day\space
+ \ifcase\month\or
+ January\or February\or March\or April\or May\or June\or
+ July\or August\or September\or October\or November\or December\fi
+ \space\number\year}
+
+ % Use this if you want the Month Day, Year style of output.
+ %\def\today{\ifcase\month\or
+ %January\or February\or March\or April\or May\or June\or
+ %July\or August\or September\or October\or November\or December\fi
+ %\space\number\day, \number\year}
+
+ % @settitle line... specifies the title of the document, for headings
+ % It generates no output of its own
+
+ \def\thistitle{No Title}
+ \def\settitle{\parsearg\settitlezzz}
+ \def\settitlezzz #1{\gdef\thistitle{#1}}
+
+
+ \message{tables,}
+ % Tables -- @table, @ftable, @vtable, @item(x), @kitem(x), @xitem(x).
+
+ % default indentation of table text
+ \newdimen\tableindent \tableindent=.8in
+ % default indentation of @itemize and @enumerate text
+ \newdimen\itemindent \itemindent=.3in
+ % margin between end of table item and start of table text.
+ \newdimen\itemmargin \itemmargin=.1in
+
+ % used internally for \itemindent minus \itemmargin
+ \newdimen\itemmax
+
+ % Note @table, @vtable, and @vtable define @item, @itemx, etc., with
+ % these defs.
+ % They also define \itemindex
+ % to index the item name in whatever manner is desired (perhaps none).
+
+ \newif\ifitemxneedsnegativevskip
+
+ \def\itemxpar{\par\ifitemxneedsnegativevskip\nobreak\vskip-\parskip\nobreak\fi}
+
+ \def\internalBitem{\smallbreak \parsearg\itemzzz}
+ \def\internalBitemx{\itemxpar \parsearg\itemzzz}
+
+ \def\internalBxitem "#1"{\def\xitemsubtopix{#1} \smallbreak \parsearg\xitemzzz}
+ \def\internalBxitemx "#1"{\def\xitemsubtopix{#1} \itemxpar \parsearg\xitemzzz}
+
+ \def\internalBkitem{\smallbreak \parsearg\kitemzzz}
+ \def\internalBkitemx{\itemxpar \parsearg\kitemzzz}
+
+ \def\kitemzzz #1{\dosubind {kw}{\code{#1}}{for {\bf \lastfunction}}%
+ \itemzzz {#1}}
+
+ \def\xitemzzz #1{\dosubind {kw}{\code{#1}}{for {\bf \xitemsubtopic}}%
+ \itemzzz {#1}}
+
+ \def\itemzzz #1{\begingroup %
+ \advance\hsize by -\rightskip
+ \advance\hsize by -\tableindent
+ \setbox0=\hbox{\itemfont{#1}}%
+ \itemindex{#1}%
+ \nobreak % This prevents a break before @itemx.
+ %
+ % If the item text does not fit in the space we have, put it on a line
+ % by itself, and do not allow a page break either before or after that
+ % line. We do not start a paragraph here because then if the next
+ % command is, e.g., @kindex, the whatsit would get put into the
+ % horizontal list on a line by itself, resulting in extra blank space.
+ \ifdim \wd0>\itemmax
+ %
+ % Make this a paragraph so we get the \parskip glue and wrapping,
+ % but leave it ragged-right.
+ \begingroup
+ \advance\leftskip by-\tableindent
+ \advance\hsize by\tableindent
+ \advance\rightskip by0pt plus1fil
+ \leavevmode\unhbox0\par
+ \endgroup
+ %
+ % We're going to be starting a paragraph, but we don't want the
+ % \parskip glue -- logically it's part of the @item we just started.
+ \nobreak \vskip-\parskip
+ %
+ % Stop a page break at the \parskip glue coming up. Unfortunately
+ % we can't prevent a possible page break at the following
+ % \baselineskip glue.
+ \nobreak
+ \endgroup
+ \itemxneedsnegativevskipfalse
+ \else
+ % The item text fits into the space. Start a paragraph, so that the
+ % following text (if any) will end up on the same line.
+ \noindent
+ % Do this with kerns and \unhbox so that if there is a footnote in
+ % the item text, it can migrate to the main vertical list and
+ % eventually be printed.
+ \nobreak\kern-\tableindent
+ \dimen0 = \itemmax \advance\dimen0 by \itemmargin \advance\dimen0 by -\wd0
+ \unhbox0
+ \nobreak\kern\dimen0
+ \endgroup
+ \itemxneedsnegativevskiptrue
+ \fi
+ }
+
+ \def\item{\errmessage{@item while not in a table}}
+ \def\itemx{\errmessage{@itemx while not in a table}}
+ \def\kitem{\errmessage{@kitem while not in a table}}
+ \def\kitemx{\errmessage{@kitemx while not in a table}}
+ \def\xitem{\errmessage{@xitem while not in a table}}
+ \def\xitemx{\errmessage{@xitemx while not in a table}}
+
+ % Contains a kludge to get @end[description] to work.
+ \def\description{\tablez{\dontindex}{1}{}{}{}{}}
+
+ % @table, @ftable, @vtable.
+ \def\table{\begingroup\inENV\obeylines\obeyspaces\tablex}
+ {\obeylines\obeyspaces%
+ \gdef\tablex #1^^M{%
+ \tabley\dontindex#1 \endtabley}}
+
+ \def\ftable{\begingroup\inENV\obeylines\obeyspaces\ftablex}
+ {\obeylines\obeyspaces%
+ \gdef\ftablex #1^^M{%
+ \tabley\fnitemindex#1 \endtabley
+ \def\Eftable{\endgraf\afterenvbreak\endgroup}%
+ \let\Etable=\relax}}
+
+ \def\vtable{\begingroup\inENV\obeylines\obeyspaces\vtablex}
+ {\obeylines\obeyspaces%
+ \gdef\vtablex #1^^M{%
+ \tabley\vritemindex#1 \endtabley
+ \def\Evtable{\endgraf\afterenvbreak\endgroup}%
+ \let\Etable=\relax}}
+
+ \def\dontindex #1{}
+ \def\fnitemindex #1{\doind {fn}{\code{#1}}}%
+ \def\vritemindex #1{\doind {vr}{\code{#1}}}%
+
+ {\obeyspaces %
+ \gdef\tabley#1#2 #3 #4 #5 #6 #7\endtabley{\endgroup%
+ \tablez{#1}{#2}{#3}{#4}{#5}{#6}}}
+
+ \def\tablez #1#2#3#4#5#6{%
+ \aboveenvbreak %
+ \begingroup %
+ \def\Edescription{\Etable}% Necessary kludge.
+ \let\itemindex=#1%
+ \ifnum 0#3>0 \advance \leftskip by #3\mil \fi %
+ \ifnum 0#4>0 \tableindent=#4\mil \fi %
+ \ifnum 0#5>0 \advance \rightskip by #5\mil \fi %
+ \def\itemfont{#2}%
+ \itemmax=\tableindent %
+ \advance \itemmax by -\itemmargin %
+ \advance \leftskip by \tableindent %
+ \exdentamount=\tableindent
+ \parindent = 0pt
+ \parskip = \smallskipamount
+ \ifdim \parskip=0pt \parskip=2pt \fi%
+ \def\Etable{\endgraf\afterenvbreak\endgroup}%
+ \let\item = \internalBitem %
+ \let\itemx = \internalBitemx %
+ \let\kitem = \internalBkitem %
+ \let\kitemx = \internalBkitemx %
+ \let\xitem = \internalBxitem %
+ \let\xitemx = \internalBxitemx %
+ }
+
+ % This is the counter used by @enumerate, which is really @itemize
+
+ \newcount \itemno
+
+ \def\itemize{\parsearg\itemizezzz}
+
+ \def\itemizezzz #1{%
+ \begingroup % ended by the @end itemize
+ \itemizey {#1}{\Eitemize}
+ }
+
+ \def\itemizey #1#2{%
+ \aboveenvbreak %
+ \itemmax=\itemindent %
+ \advance \itemmax by -\itemmargin %
+ \advance \leftskip by \itemindent %
+ \exdentamount=\itemindent
+ \parindent = 0pt %
+ \parskip = \smallskipamount %
+ \ifdim \parskip=0pt \parskip=2pt \fi%
+ \def#2{\endgraf\afterenvbreak\endgroup}%
+ \def\itemcontents{#1}%
+ \let\item=\itemizeitem}
+
+ % Set sfcode to normal for the chars that usually have another value.
+ % These are `.?!:;,'
+ \def\frenchspacing{\sfcode46=1000 \sfcode63=1000 \sfcode33=1000
+ \sfcode58=1000 \sfcode59=1000 \sfcode44=1000 }
+
+ % \splitoff TOKENS\endmark defines \first to be the first token in
+ % TOKENS, and \rest to be the remainder.
+ %
+ \def\splitoff#1#2\endmark{\def\first{#1}\def\rest{#2}}%
+
+ % Allow an optional argument of an uppercase letter, lowercase letter,
+ % or number, to specify the first label in the enumerated list. No
+ % argument is the same as `1'.
+ %
+ \def\enumerate{\parsearg\enumeratezzz}
+ \def\enumeratezzz #1{\enumeratey #1 \endenumeratey}
+ \def\enumeratey #1 #2\endenumeratey{%
+ \begingroup % ended by the @end enumerate
+ %
+ % If we were given no argument, pretend we were given `1'.
+ \def\thearg{#1}%
+ \ifx\thearg\empty \def\thearg{1}\fi
+ %
+ % Detect if the argument is a single token. If so, it might be a
+ % letter. Otherwise, the only valid thing it can be is a number.
+ % (We will always have one token, because of the test we just made.
+ % This is a good thing, since \splitoff doesn't work given nothing at
+ % all -- the first parameter is undelimited.)
+ \expandafter\splitoff\thearg\endmark
+ \ifx\rest\empty
+ % Only one token in the argument. It could still be anything.
+ % A ``lowercase letter'' is one whose \lccode is nonzero.
+ % An ``uppercase letter'' is one whose \lccode is both nonzero, and
+ % not equal to itself.
+ % Otherwise, we assume it's a number.
+ %
+ % We need the \relax at the end of the \ifnum lines to stop TeX from
+ % continuing to look for a <number>.
+ %
+ \ifnum\lccode\expandafter`\thearg=0\relax
+ \numericenumerate % a number (we hope)
+ \else
+ % It's a letter.
+ \ifnum\lccode\expandafter`\thearg=\expandafter`\thearg\relax
+ \lowercaseenumerate % lowercase letter
+ \else
+ \uppercaseenumerate % uppercase letter
+ \fi
+ \fi
+ \else
+ % Multiple tokens in the argument. We hope it's a number.
+ \numericenumerate
+ \fi
+ }
+
+ % An @enumerate whose labels are integers. The starting integer is
+ % given in \thearg.
+ %
+ \def\numericenumerate{%
+ \itemno = \thearg
+ \startenumeration{\the\itemno}%
+ }
+
+ % The starting (lowercase) letter is in \thearg.
+ \def\lowercaseenumerate{%
+ \itemno = \expandafter`\thearg
+ \startenumeration{%
+ % Be sure we're not beyond the end of the alphabet.
+ \ifnum\itemno=0
+ \errmessage{No more lowercase letters in @enumerate; get a bigger
+ alphabet}%
+ \fi
+ \char\lccode\itemno
+ }%
+ }
+
+ % The starting (uppercase) letter is in \thearg.
+ \def\uppercaseenumerate{%
+ \itemno = \expandafter`\thearg
+ \startenumeration{%
+ % Be sure we're not beyond the end of the alphabet.
+ \ifnum\itemno=0
+ \errmessage{No more uppercase letters in @enumerate; get a bigger
+ alphabet}
+ \fi
+ \char\uccode\itemno
+ }%
+ }
+
+ % Call itemizey, adding a period to the first argument and supplying the
+ % common last two arguments. Also subtract one from the initial value in
+ % \itemno, since @item increments \itemno.
+ %
+ \def\startenumeration#1{%
+ \advance\itemno by -1
+ \itemizey{#1.}\Eenumerate\flushcr
+ }
+
+ % @alphaenumerate and @capsenumerate are abbreviations for giving an arg
+ % to @enumerate.
+ %
+ \def\alphaenumerate{\enumerate{a}}
+ \def\capsenumerate{\enumerate{A}}
+ \def\Ealphaenumerate{\Eenumerate}
+ \def\Ecapsenumerate{\Eenumerate}
+
+ % Definition of @item while inside @itemize.
+
+ \def\itemizeitem{%
+ \advance\itemno by 1
+ {\let\par=\endgraf \smallbreak}%
+ \ifhmode \errmessage{In hmode at itemizeitem}\fi
+ {\parskip=0in \hskip 0pt
+ \hbox to 0pt{\hss \itemcontents\hskip \itemmargin}%
+ \vadjust{\penalty 1200}}%
+ \flushcr}
+
+ % @multitable macros
+ % Amy Hendrickson, 8/18/94, 3/6/96
+ %
+ % @multitable ... @end multitable will make as many columns as desired.
+ % Contents of each column will wrap at width given in preamble. Width
+ % can be specified either with sample text given in a template line,
+ % or in percent of \hsize, the current width of text on page.
+
+ % Table can continue over pages but will only break between lines.
+
+ % To make preamble:
+ %
+ % Either define widths of columns in terms of percent of \hsize:
+ % @multitable @columnfractions .25 .3 .45
+ % @item ...
+ %
+ % Numbers following @columnfractions are the percent of the total
+ % current hsize to be used for each column. You may use as many
+ % columns as desired.
+
+
+ % Or use a template:
+ % @multitable {Column 1 template} {Column 2 template} {Column 3 template}
+ % @item ...
+ % using the widest term desired in each column.
+ %
+ % For those who want to use more than one line's worth of words in
+ % the preamble, break the line within one argument and it
+ % will parse correctly, i.e.,
+ %
+ % @multitable {Column 1 template} {Column 2 template} {Column 3
+ % template}
+ % Not:
+ % @multitable {Column 1 template} {Column 2 template}
+ % {Column 3 template}
+
+ % Each new table line starts with @item, each subsequent new column
+ % starts with @tab. Empty columns may be produced by supplying @tab's
+ % with nothing between them for as many times as empty columns are needed,
+ % ie, @tab at tab@tab will produce two empty columns.
+
+ % @item, @tab, @multitable or @end multitable do not need to be on their
+ % own lines, but it will not hurt if they are.
+
+ % Sample multitable:
+
+ % @multitable {Column 1 template} {Column 2 template} {Column 3 template}
+ % @item first col stuff @tab second col stuff @tab third col
+ % @item
+ % first col stuff
+ % @tab
+ % second col stuff
+ % @tab
+ % third col
+ % @item first col stuff @tab second col stuff
+ % @tab Many paragraphs of text may be used in any column.
+ %
+ % They will wrap at the width determined by the template.
+ % @item at tab@tab This will be in third column.
+ % @end multitable
+
+ % Default dimensions may be reset by user.
+ % @multitableparskip is vertical space between paragraphs in table.
+ % @multitableparindent is paragraph indent in table.
+ % @multitablecolmargin is horizontal space to be left between columns.
+ % @multitablelinespace is space to leave between table items, baseline
+ % to baseline.
+ % 0pt means it depends on current normal line spacing.
+ %
+ \newskip\multitableparskip
+ \newskip\multitableparindent
+ \newdimen\multitablecolspace
+ \newskip\multitablelinespace
+ \multitableparskip=0pt
+ \multitableparindent=6pt
+ \multitablecolspace=12pt
+ \multitablelinespace=0pt
+
+ % Macros used to set up halign preamble:
+ %
+ \let\endsetuptable\relax
+ \def\xendsetuptable{\endsetuptable}
+ \let\columnfractions\relax
+ \def\xcolumnfractions{\columnfractions}
+ \newif\ifsetpercent
+
+ % #1 is the part of the @columnfraction before the decimal point, which
+ % is presumably either 0 or the empty string (but we don't check, we
+ % just throw it away). #2 is the decimal part, which we use as the
+ % percent of \hsize for this column.
+ \def\pickupwholefraction#1.#2 {%
+ \global\advance\colcount by 1
+ \expandafter\xdef\csname col\the\colcount\endcsname{.#2\hsize}%
+ \setuptable
+ }
+
+ \newcount\colcount
+ \def\setuptable#1{%
+ \def\firstarg{#1}%
+ \ifx\firstarg\xendsetuptable
+ \let\go = \relax
+ \else
+ \ifx\firstarg\xcolumnfractions
+ \global\setpercenttrue
+ \else
+ \ifsetpercent
+ \let\go\pickupwholefraction
+ \else
+ \global\advance\colcount by 1
+ \setbox0=\hbox{#1\unskip }% Add a normal word space as a separator;
+ % typically that is always in the input, anyway.
+ \expandafter\xdef\csname col\the\colcount\endcsname{\the\wd0}%
+ \fi
+ \fi
+ \ifx\go\pickupwholefraction
+ % Put the argument back for the \pickupwholefraction call, so
+ % we'll always have a period there to be parsed.
+ \def\go{\pickupwholefraction#1}%
+ \else
+ \let\go = \setuptable
+ \fi%
+ \fi
+ \go
+ }
+
+ % multitable syntax
+ \def\tab{&\hskip1sp\relax} % 2/2/96
+ % tiny skip here makes sure this column space is
+ % maintained, even if it is never used.
+
+ % @multitable ... @end multitable definitions:
+ %
+ \def\multitable{\parsearg\dotable}
+ \def\dotable#1{\bgroup
+ \vskip\parskip
+ \let\item\crcr
+ \tolerance=9500
+ \hbadness=9500
+ \setmultitablespacing
+ \parskip=\multitableparskip
+ \parindent=\multitableparindent
+ \overfullrule=0pt
+ \global\colcount=0
+ \def\Emultitable{\global\setpercentfalse\cr\egroup\egroup}%
+ %
+ % To parse everything between @multitable and @item:
+ \setuptable#1 \endsetuptable
+ %
+ % \everycr will reset column counter, \colcount, at the end of
+ % each line. Every column entry will cause \colcount to advance by one.
+ % The table preamble
+ % looks at the current \colcount to find the correct column width.
+ \everycr{\noalign{%
+ %
+ % \filbreak%% keeps underfull box messages off when table breaks over pages.
+ % Maybe so, but it also creates really weird page breaks when the table
+ % breaks over pages. Wouldn't \vfil be better? Wait until the problem
+ % manifests itself, so it can be fixed for real --karl.
+ \global\colcount=0\relax}}%
+ %
+ % This preamble sets up a generic column definition, which will
+ % be used as many times as user calls for columns.
+ % \vtop will set a single line and will also let text wrap and
+ % continue for many paragraphs if desired.
+ \halign\bgroup&\global\advance\colcount by 1\relax
+ \multistrut\vtop{\hsize=\expandafter\csname col\the\colcount\endcsname
+ %
+ % In order to keep entries from bumping into each other
+ % we will add a \leftskip of \multitablecolspace to all columns after
+ % the first one.
+ %
+ % If a template has been used, we will add \multitablecolspace
+ % to the width of each template entry.
+ %
+ % If the user has set preamble in terms of percent of \hsize we will
+ % use that dimension as the width of the column, and the \leftskip
+ % will keep entries from bumping into each other. Table will start at
+ % left margin and final column will justify at right margin.
+ %
+ % Make sure we don't inherit \rightskip from the outer environment.
+ \rightskip=0pt
+ \ifnum\colcount=1
+ % The first column will be indented with the surrounding text.
+ \advance\hsize by\leftskip
+ \else
+ \ifsetpercent \else
+ % If user has not set preamble in terms of percent of \hsize
+ % we will advance \hsize by \multitablecolspace.
+ \advance\hsize by \multitablecolspace
+ \fi
+ % In either case we will make \leftskip=\multitablecolspace:
+ \leftskip=\multitablecolspace
+ \fi
+ % Ignoring space at the beginning and end avoids an occasional spurious
+ % blank line, when TeX decides to break the line at the space before the
+ % box from the multistrut, so the strut ends up on a line by itself.
+ % For example:
+ % @multitable @columnfractions .11 .89
+ % @item @code{#}
+ % @tab Legal holiday which is valid in major parts of the whole country.
+ % Is automatically provided with highlighting sequences respectively marking
+ % characters.
+ \noindent\ignorespaces##\unskip\multistrut}\cr
+ }
+
+ \def\setmultitablespacing{% test to see if user has set \multitablelinespace.
+ % If so, do nothing. If not, give it an appropriate dimension based on
+ % current baselineskip.
+ \ifdim\multitablelinespace=0pt
+ %% strut to put in table in case some entry doesn't have descenders,
+ %% to keep lines equally spaced
+ \let\multistrut = \strut
+ %% Test to see if parskip is larger than space between lines of
+ %% table. If not, do nothing.
+ %% If so, set to same dimension as multitablelinespace.
+ \else
+ \gdef\multistrut{\vrule height\multitablelinespace depth\dp0
+ width0pt\relax} \fi
+ \ifdim\multitableparskip>\multitablelinespace
+ \global\multitableparskip=\multitablelinespace
+ \global\advance\multitableparskip-7pt %% to keep parskip somewhat smaller
+ %% than skip between lines in the table.
+ \fi%
+ \ifdim\multitableparskip=0pt
+ \global\multitableparskip=\multitablelinespace
+ \global\advance\multitableparskip-7pt %% to keep parskip somewhat smaller
+ %% than skip between lines in the table.
+ \fi}
+
+
+ \message{indexing,}
+ % Index generation facilities
+
+ % Define \newwrite to be identical to plain tex's \newwrite
+ % except not \outer, so it can be used within \newindex.
+ {\catcode`\@=11
+ \gdef\newwrite{\alloc at 7\write\chardef\sixt@@n}}
+
+ % \newindex {foo} defines an index named foo.
+ % It automatically defines \fooindex such that
+ % \fooindex ...rest of line... puts an entry in the index foo.
+ % It also defines \fooindfile to be the number of the output channel for
+ % the file that accumulates this index. The file's extension is foo.
+ % The name of an index should be no more than 2 characters long
+ % for the sake of vms.
+ %
+ \def\newindex#1{%
+ \iflinks
+ \expandafter\newwrite \csname#1indfile\endcsname
+ \openout \csname#1indfile\endcsname \jobname.#1 % Open the file
+ \fi
+ \expandafter\xdef\csname#1index\endcsname{% % Define @#1index
+ \noexpand\doindex{#1}}
+ }
+
+ % @defindex foo == \newindex{foo}
+
+ \def\defindex{\parsearg\newindex}
+
+ % Define @defcodeindex, like @defindex except put all entries in @code.
+
+ \def\newcodeindex#1{%
+ \iflinks
+ \expandafter\newwrite \csname#1indfile\endcsname
+ \openout \csname#1indfile\endcsname \jobname.#1
+ \fi
+ \expandafter\xdef\csname#1index\endcsname{%
+ \noexpand\docodeindex{#1}}
+ }
+
+ \def\defcodeindex{\parsearg\newcodeindex}
+
+ % @synindex foo bar makes index foo feed into index bar.
+ % Do this instead of @defindex foo if you don't want it as a separate index.
+ % The \closeout helps reduce unnecessary open files; the limit on the
+ % Acorn RISC OS is a mere 16 files.
+ \def\synindex#1 #2 {%
+ \expandafter\let\expandafter\synindexfoo\expandafter=\csname#2indfile\endcsname
+ \expandafter\closeout\csname#1indfile\endcsname
+ \expandafter\let\csname#1indfile\endcsname=\synindexfoo
+ \expandafter\xdef\csname#1index\endcsname{% define \xxxindex
+ \noexpand\doindex{#2}}%
+ }
+
+ % @syncodeindex foo bar similar, but put all entries made for index foo
+ % inside @code.
+ \def\syncodeindex#1 #2 {%
+ \expandafter\let\expandafter\synindexfoo\expandafter=\csname#2indfile\endcsname
+ \expandafter\closeout\csname#1indfile\endcsname
+ \expandafter\let\csname#1indfile\endcsname=\synindexfoo
+ \expandafter\xdef\csname#1index\endcsname{% define \xxxindex
+ \noexpand\docodeindex{#2}}%
+ }
+
+ % Define \doindex, the driver for all \fooindex macros.
+ % Argument #1 is generated by the calling \fooindex macro,
+ % and it is "foo", the name of the index.
+
+ % \doindex just uses \parsearg; it calls \doind for the actual work.
+ % This is because \doind is more useful to call from other macros.
+
+ % There is also \dosubind {index}{topic}{subtopic}
+ % which makes an entry in a two-level index such as the operation index.
+
+ \def\doindex#1{\edef\indexname{#1}\parsearg\singleindexer}
+ \def\singleindexer #1{\doind{\indexname}{#1}}
+
+ % like the previous two, but they put @code around the argument.
+ \def\docodeindex#1{\edef\indexname{#1}\parsearg\singlecodeindexer}
+ \def\singlecodeindexer #1{\doind{\indexname}{\code{#1}}}
+
+ \def\indexdummies{%
+ \def\ { }%
+ % Take care of the plain tex accent commands.
+ \def\"{\realbackslash "}%
+ \def\`{\realbackslash `}%
+ \def\'{\realbackslash '}%
+ \def\^{\realbackslash ^}%
+ \def\~{\realbackslash ~}%
+ \def\={\realbackslash =}%
+ \def\b{\realbackslash b}%
+ \def\c{\realbackslash c}%
+ \def\d{\realbackslash d}%
+ \def\u{\realbackslash u}%
+ \def\v{\realbackslash v}%
+ \def\H{\realbackslash H}%
+ % Take care of the plain tex special European modified letters.
+ \def\oe{\realbackslash oe}%
+ \def\ae{\realbackslash ae}%
+ \def\aa{\realbackslash aa}%
+ \def\OE{\realbackslash OE}%
+ \def\AE{\realbackslash AE}%
+ \def\AA{\realbackslash AA}%
+ \def\o{\realbackslash o}%
+ \def\O{\realbackslash O}%
+ \def\l{\realbackslash l}%
+ \def\L{\realbackslash L}%
+ \def\ss{\realbackslash ss}%
+ % Take care of texinfo commands likely to appear in an index entry.
+ % (Must be a way to avoid doing expansion at all, and thus not have to
+ % laboriously list every single command here.)
+ \def\@{@}% will be @@ when we switch to @ as escape char.
+ % Need these in case \tex is in effect and \{ is a \delimiter again.
+ % But can't use \lbracecmd and \rbracecmd because texindex assumes
+ % braces and backslashes are used only as delimiters.
+ \let\{ = \mylbrace
+ \let\} = \myrbrace
+ \def\_{{\realbackslash _}}%
+ \def\w{\realbackslash w }%
+ \def\bf{\realbackslash bf }%
+ %\def\rm{\realbackslash rm }%
+ \def\sl{\realbackslash sl }%
+ \def\sf{\realbackslash sf}%
+ \def\tt{\realbackslash tt}%
+ \def\gtr{\realbackslash gtr}%
+ \def\less{\realbackslash less}%
+ \def\hat{\realbackslash hat}%
+ \def\TeX{\realbackslash TeX}%
+ \def\dots{\realbackslash dots }%
+ \def\result{\realbackslash result}%
+ \def\equiv{\realbackslash equiv}%
+ \def\expansion{\realbackslash expansion}%
+ \def\print{\realbackslash print}%
+ \def\error{\realbackslash error}%
+ \def\point{\realbackslash point}%
+ \def\copyright{\realbackslash copyright}%
+ \def\tclose##1{\realbackslash tclose {##1}}%
+ \def\code##1{\realbackslash code {##1}}%
+ \def\uref##1{\realbackslash uref {##1}}%
+ \def\url##1{\realbackslash url {##1}}%
+ \def\env##1{\realbackslash env {##1}}%
+ \def\command##1{\realbackslash command {##1}}%
+ \def\option##1{\realbackslash option {##1}}%
+ \def\dotless##1{\realbackslash dotless {##1}}%
+ \def\samp##1{\realbackslash samp {##1}}%
+ \def\,##1{\realbackslash ,{##1}}%
+ \def\t##1{\realbackslash t {##1}}%
+ \def\r##1{\realbackslash r {##1}}%
+ \def\i##1{\realbackslash i {##1}}%
+ \def\b##1{\realbackslash b {##1}}%
+ \def\sc##1{\realbackslash sc {##1}}%
+ \def\cite##1{\realbackslash cite {##1}}%
+ \def\key##1{\realbackslash key {##1}}%
+ \def\file##1{\realbackslash file {##1}}%
+ \def\var##1{\realbackslash var {##1}}%
+ \def\kbd##1{\realbackslash kbd {##1}}%
+ \def\dfn##1{\realbackslash dfn {##1}}%
+ \def\emph##1{\realbackslash emph {##1}}%
+ \def\acronym##1{\realbackslash acronym {##1}}%
+ %
+ % Handle some cases of @value -- where the variable name does not
+ % contain - or _, and the value does not contain any
+ % (non-fully-expandable) commands.
+ \let\value = \expandablevalue
+ %
+ \unsepspaces
+ }
+
+ % If an index command is used in an @example environment, any spaces
+ % therein should become regular spaces in the raw index file, not the
+ % expansion of \tie (\\leavevmode \penalty \@M \ ).
+ {\obeyspaces
+ \gdef\unsepspaces{\obeyspaces\let =\space}}
+
+ % \indexnofonts no-ops all font-change commands.
+ % This is used when outputting the strings to sort the index by.
+ \def\indexdummyfont#1{#1}
+ \def\indexdummytex{TeX}
+ \def\indexdummydots{...}
+
+ \def\indexnofonts{%
+ % Just ignore accents.
+ \let\,=\indexdummyfont
+ \let\"=\indexdummyfont
+ \let\`=\indexdummyfont
+ \let\'=\indexdummyfont
+ \let\^=\indexdummyfont
+ \let\~=\indexdummyfont
+ \let\==\indexdummyfont
+ \let\b=\indexdummyfont
+ \let\c=\indexdummyfont
+ \let\d=\indexdummyfont
+ \let\u=\indexdummyfont
+ \let\v=\indexdummyfont
+ \let\H=\indexdummyfont
+ \let\dotless=\indexdummyfont
+ % Take care of the plain tex special European modified letters.
+ \def\oe{oe}%
+ \def\ae{ae}%
+ \def\aa{aa}%
+ \def\OE{OE}%
+ \def\AE{AE}%
+ \def\AA{AA}%
+ \def\o{o}%
+ \def\O{O}%
+ \def\l{l}%
+ \def\L{L}%
+ \def\ss{ss}%
+ \let\w=\indexdummyfont
+ \let\t=\indexdummyfont
+ \let\r=\indexdummyfont
+ \let\i=\indexdummyfont
+ \let\b=\indexdummyfont
+ \let\emph=\indexdummyfont
+ \let\strong=\indexdummyfont
+ \let\cite=\indexdummyfont
+ \let\sc=\indexdummyfont
+ %Don't no-op \tt, since it isn't a user-level command
+ % and is used in the definitions of the active chars like <, >, |...
+ %\let\tt=\indexdummyfont
+ \let\tclose=\indexdummyfont
+ \let\code=\indexdummyfont
+ \let\url=\indexdummyfont
+ \let\uref=\indexdummyfont
+ \let\env=\indexdummyfont
+ \let\command=\indexdummyfont
+ \let\option=\indexdummyfont
+ \let\file=\indexdummyfont
+ \let\samp=\indexdummyfont
+ \let\kbd=\indexdummyfont
+ \let\key=\indexdummyfont
+ \let\var=\indexdummyfont
+ \let\TeX=\indexdummytex
+ \let\dots=\indexdummydots
+ \def\@{@}%
+ }
+
+ % To define \realbackslash, we must make \ not be an escape.
+ % We must first make another character (@) an escape
+ % so we do not become unable to do a definition.
+
+ {\catcode`\@=0 \catcode`\\=\other
+ @gdef at realbackslash{\}}
+
+ \let\indexbackslash=0 %overridden during \printindex.
+ \let\SETmarginindex=\relax % put index entries in margin (undocumented)?
+
+ % For \ifx comparisons.
+ \def\emptymacro{\empty}
+
+ % Most index entries go through here, but \dosubind is the general case.
+ %
+ \def\doind#1#2{\dosubind{#1}{#2}\empty}
+
+ % Workhorse for all \fooindexes.
+ % #1 is name of index, #2 is stuff to put there, #3 is subentry --
+ % \empty if called from \doind, as we usually are. The main exception
+ % is with defuns, which call us directly.
+ %
+ \def\dosubind#1#2#3{%
+ % Put the index entry in the margin if desired.
+ \ifx\SETmarginindex\relax\else
+ \insert\margin{\hbox{\vrule height8pt depth3pt width0pt #2}}%
+ \fi
+ {%
+ \count255=\lastpenalty
+ {%
+ \indexdummies % Must do this here, since \bf, etc expand at this stage
+ \escapechar=`\\
+ {%
+ \let\folio = 0% We will expand all macros now EXCEPT \folio.
+ \def\rawbackslashxx{\indexbackslash}% \indexbackslash isn't defined now
+ % so it will be output as is; and it will print as backslash.
+ %
+ \def\thirdarg{#3}%
+ %
+ % If third arg is present, precede it with space in sort key.
+ \ifx\thirdarg\emptymacro
+ \let\subentry = \empty
+ \else
+ \def\subentry{ #3}%
+ \fi
+ %
+ % First process the index-string with all font commands turned off
+ % to get the string to sort by.
+ {\indexnofonts \xdef\indexsorttmp{#2\subentry}}%
+ %
+ % Now produce the complete index entry, with both the sort key and the
+ % original text, including any font commands.
+ \toks0 = {#2}%
+ \edef\temp{%
+ \write\csname#1indfile\endcsname{%
+ \realbackslash entry{\indexsorttmp}{\folio}{\the\toks0}}%
+ }%
+ %
+ % If third (subentry) arg is present, add it to the index string.
+ \ifx\thirdarg\emptymacro \else
+ \toks0 = {#3}%
+ \edef\temp{\temp{\the\toks0}}%
+ \fi
+ %
+ % If a skip is the last thing on the list now, preserve it
+ % by backing up by \lastskip, doing the \write, then inserting
+ % the skip again. Otherwise, the whatsit generated by the
+ % \write will make \lastskip zero. The result is that sequences
+ % like this:
+ % @end defun
+ % @tindex whatever
+ % @defun ...
+ % will have extra space inserted, because the \medbreak in the
+ % start of the @defun won't see the skip inserted by the @end of
+ % the previous defun.
+ %
+ % But don't do any of this if we're not in vertical mode. We
+ % don't want to do a \vskip and prematurely end a paragraph.
+ %
+ % Avoid page breaks due to these extra skips, too.
+ %
+ \iflinks
+ \ifvmode
+ \skip0 = \lastskip
+ \ifdim\lastskip = 0pt \else \nobreak\vskip-\lastskip \fi
+ \fi
+ %
+ \temp % do the write
+ %
+ %
+ \ifvmode \ifdim\skip0 = 0pt \else \nobreak\vskip\skip0 \fi \fi
+ \fi
+ }%
+ }%
+ \penalty\count255
+ }%
+ }
+
+ % The index entry written in the file actually looks like
+ % \entry {sortstring}{page}{topic}
+ % or
+ % \entry {sortstring}{page}{topic}{subtopic}
+ % The texindex program reads in these files and writes files
+ % containing these kinds of lines:
+ % \initial {c}
+ % before the first topic whose initial is c
+ % \entry {topic}{pagelist}
+ % for a topic that is used without subtopics
+ % \primary {topic}
+ % for the beginning of a topic that is used with subtopics
+ % \secondary {subtopic}{pagelist}
+ % for each subtopic.
+
+ % Define the user-accessible indexing commands
+ % @findex, @vindex, @kindex, @cindex.
+
+ \def\findex {\fnindex}
+ \def\kindex {\kyindex}
+ \def\cindex {\cpindex}
+ \def\vindex {\vrindex}
+ \def\tindex {\tpindex}
+ \def\pindex {\pgindex}
+
+ \def\cindexsub {\begingroup\obeylines\cindexsub}
+ {\obeylines %
+ \gdef\cindexsub "#1" #2^^M{\endgroup %
+ \dosubind{cp}{#2}{#1}}}
+
+ % Define the macros used in formatting output of the sorted index material.
+
+ % @printindex causes a particular index (the ??s file) to get printed.
+ % It does not print any chapter heading (usually an @unnumbered).
+ %
+ \def\printindex{\parsearg\doprintindex}
+ \def\doprintindex#1{\begingroup
+ \dobreak \chapheadingskip{10000}%
+ %
+ \indexfonts \rm
+ \tolerance = 9500
+ \indexbreaks
+ %
+ % See if the index file exists and is nonempty.
+ % Change catcode of @ here so that if the index file contains
+ % \initial {@}
+ % as its first line, TeX doesn't complain about mismatched braces
+ % (because it thinks @} is a control sequence).
+ \catcode`\@ = 11
+ \openin 1 \jobname.#1s
+ \ifeof 1
+ % \enddoublecolumns gets confused if there is no text in the index,
+ % and it loses the chapter title and the aux file entries for the
+ % index. The easiest way to prevent this problem is to make sure
+ % there is some text.
+ (Index is nonexistent)
+ \else
+ %
+ % If the index file exists but is empty, then \openin leaves \ifeof
+ % false. We have to make TeX try to read something from the file, so
+ % it can discover if there is anything in it.
+ \read 1 to \temp
+ \ifeof 1
+ (Index is empty)
+ \else
+ % Index files are almost Texinfo source, but we use \ as the escape
+ % character. It would be better to use @, but that's too big a change
+ % to make right now.
+ \def\indexbackslash{\rawbackslashxx}%
+ \catcode`\\ = 0
+ \escapechar = `\\
+ \begindoublecolumns
+ \input \jobname.#1s
+ \enddoublecolumns
+ \fi
+ \fi
+ \closein 1
+ \endgroup}
+
+ % These macros are used by the sorted index file itself.
+ % Change them to control the appearance of the index.
+
+ \def\initial#1{{%
+ % Some minor font changes for the special characters.
+ \let\tentt=\sectt \let\tt=\sectt \let\sf=\sectt
+ %
+ % Remove any glue we may have, we'll be inserting our own.
+ \removelastskip
+ %
+ % We like breaks before the index initials, so insert a bonus.
+ \penalty -300
+ %
+ % Typeset the initial. Making this add up to a whole number of
+ % baselineskips increases the chance of the dots lining up from column
+ % to column. It still won't often be perfect, because of the stretch
+ % we need before each entry, but it's better.
+ %
+ % No shrink because it confuses \balancecolumns.
+ \vskip 1.67\baselineskip plus .5\baselineskip
+ \leftline{\secbf #1}%
+ \vskip .33\baselineskip plus .1\baselineskip
+ %
+ % Do our best not to break after the initial.
+ \nobreak
+ }}
+
+ % This typesets a paragraph consisting of #1, dot leaders, and then #2
+ % flush to the right margin. It is used for index and table of contents
+ % entries. The paragraph is indented by \leftskip.
+ %
+ \def\entry#1#2{\begingroup
+ %
+ % Start a new paragraph if necessary, so our assignments below can't
+ % affect previous text.
+ \par
+ %
+ % Do not fill out the last line with white space.
+ \parfillskip = 0in
+ %
+ % No extra space above this paragraph.
+ \parskip = 0in
+ %
+ % Do not prefer a separate line ending with a hyphen to fewer lines.
+ \finalhyphendemerits = 0
+ %
+ % \hangindent is only relevant when the entry text and page number
+ % don't both fit on one line. In that case, bob suggests starting the
+ % dots pretty far over on the line. Unfortunately, a large
+ % indentation looks wrong when the entry text itself is broken across
+ % lines. So we use a small indentation and put up with long leaders.
+ %
+ % \hangafter is reset to 1 (which is the value we want) at the start
+ % of each paragraph, so we need not do anything with that.
+ \hangindent = 2em
+ %
+ % When the entry text needs to be broken, just fill out the first line
+ % with blank space.
+ \rightskip = 0pt plus1fil
+ %
+ % A bit of stretch before each entry for the benefit of balancing columns.
+ \vskip 0pt plus1pt
+ %
+ % Start a ``paragraph'' for the index entry so the line breaking
+ % parameters we've set above will have an effect.
+ \noindent
+ %
+ % Insert the text of the index entry. TeX will do line-breaking on it.
+ #1%
+ % The following is kludged to not output a line of dots in the index if
+ % there are no page numbers. The next person who breaks this will be
+ % cursed by a Unix daemon.
+ \def\tempa{{\rm }}%
+ \def\tempb{#2}%
+ \edef\tempc{\tempa}%
+ \edef\tempd{\tempb}%
+ \ifx\tempc\tempd\ \else%
+ %
+ % If we must, put the page number on a line of its own, and fill out
+ % this line with blank space. (The \hfil is overwhelmed with the
+ % fill leaders glue in \indexdotfill if the page number does fit.)
+ \hfil\penalty50
+ \null\nobreak\indexdotfill % Have leaders before the page number.
+ %
+ % The `\ ' here is removed by the implicit \unskip that TeX does as
+ % part of (the primitive) \par. Without it, a spurious underfull
+ % \hbox ensues.
+ \ #2% The page number ends the paragraph.
+ \fi%
+ \par
+ \endgroup}
+
+ % Like \dotfill except takes at least 1 em.
+ \def\indexdotfill{\cleaders
+ \hbox{$\mathsurround=0pt \mkern1.5mu ${\it .}$ \mkern1.5mu$}\hskip 1em plus 1fill}
+
+ \def\primary #1{\line{#1\hfil}}
+
+ \newskip\secondaryindent \secondaryindent=0.5cm
+
+ \def\secondary #1#2{
+ {\parfillskip=0in \parskip=0in
+ \hangindent =1in \hangafter=1
+ \noindent\hskip\secondaryindent\hbox{#1}\indexdotfill #2\par
+ }}
+
+ % Define two-column mode, which we use to typeset indexes.
+ % Adapted from the TeXbook, page 416, which is to say,
+ % the manmac.tex format used to print the TeXbook itself.
+ \catcode`\@=11
+
+ \newbox\partialpage
+ \newdimen\doublecolumnhsize
+
+ \def\begindoublecolumns{\begingroup % ended by \enddoublecolumns
+ % Grab any single-column material above us.
+ \output = {\global\setbox\partialpage = \vbox{%
+ %
+ % Here is a possibility not foreseen in manmac: if we accumulate a
+ % whole lot of material, we might end up calling this \output
+ % routine twice in a row (see the doublecol-lose test, which is
+ % essentially a couple of indexes with @setchapternewpage off). In
+ % that case, we must prevent the second \partialpage from
+ % simply overwriting the first, causing us to lose the page.
+ % This will preserve it until a real output routine can ship it
+ % out. Generally, \partialpage will be empty when this runs and
+ % this will be a no-op.
+ \unvbox\partialpage
+ %
+ % Unvbox the main output page.
+ \unvbox255
+ \kern-\topskip \kern\baselineskip
+ }}%
+ \eject % run that output routine to set \partialpage
+ %
+ % Use the double-column output routine for subsequent pages.
+ \output = {\doublecolumnout}%
+ %
+ % Change the page size parameters. We could do this once outside this
+ % routine, in each of @smallbook, @afourpaper, and the default 8.5x11
+ % format, but then we repeat the same computation. Repeating a couple
+ % of assignments once per index is clearly meaningless for the
+ % execution time, so we may as well do it in one place.
+ %
+ % First we halve the line length, less a little for the gutter between
+ % the columns. We compute the gutter based on the line length, so it
+ % changes automatically with the paper format. The magic constant
+ % below is chosen so that the gutter has the same value (well, +-<1pt)
+ % as it did when we hard-coded it.
+ %
+ % We put the result in a separate register, \doublecolumhsize, so we
+ % can restore it in \pagesofar, after \hsize itself has (potentially)
+ % been clobbered.
+ %
+ \doublecolumnhsize = \hsize
+ \advance\doublecolumnhsize by -.04154\hsize
+ \divide\doublecolumnhsize by 2
+ \hsize = \doublecolumnhsize
+ %
+ % Double the \vsize as well. (We don't need a separate register here,
+ % since nobody clobbers \vsize.)
+ \advance\vsize by -\ht\partialpage
+ \vsize = 2\vsize
+ }
+
+ % The double-column output routine for all double-column pages except
+ % the last.
+ %
+ \def\doublecolumnout{%
+ \splittopskip=\topskip \splitmaxdepth=\maxdepth
+ % Get the available space for the double columns -- the normal
+ % (undoubled) page height minus any material left over from the
+ % previous page.
+ \dimen@ = \vsize
+ \divide\dimen@ by 2
+ %
+ % box0 will be the left-hand column, box2 the right.
+ \setbox0=\vsplit255 to\dimen@ \setbox2=\vsplit255 to\dimen@
+ \onepageout\pagesofar
+ \unvbox255
+ \penalty\outputpenalty
+ }
+ \def\pagesofar{%
+ % Re-output the contents of the output page -- any previous material,
+ % followed by the two boxes we just split, in box0 and box2.
+ \advance\vsize by \ht\partialpage
+ \unvbox\partialpage
+ %
+ \hsize = \doublecolumnhsize
+ \wd0=\hsize \wd2=\hsize
+ \hbox to\pagewidth{\box0\hfil\box2}%
+ }
+ \def\enddoublecolumns{%
+ \output = {%
+ % Split the last of the double-column material. Leave it on the
+ % current page, no automatic page break.
+ \balancecolumns
+ %
+ % If we end up splitting too much material for the current page,
+ % though, there will be another page break right after this \output
+ % invocation ends. Having called \balancecolumns once, we do not
+ % want to call it again. Therefore, reset \output to its normal
+ % definition right away. (We hope \balancecolumns will never be
+ % called on to balance too much material, but if it is, this makes
+ % the output somewhat more palatable.)
+ \global\output = {\onepageout{\pagecontents\PAGE}}%
+ }%
+ \eject
+ \endgroup % started in \begindoublecolumns
+ %
+ % \pagegoal was set to the doubled \vsize above, since we restarted
+ % the current page. We're now back to normal single-column
+ % typesetting, so reset \pagegoal to the normal \vsize (after the
+ % \endgroup where \vsize got restored).
+ \pagegoal = \vsize
+ }
+ \def\balancecolumns{%
+ % Called at the end of the double column material.
+ \setbox0 = \vbox{\unvbox255}% like \box255 but more efficient, see p.120.
+ \dimen@ = \ht0
+ \advance\dimen@ by \topskip
+ \advance\dimen@ by-\baselineskip
+ \divide\dimen@ by 2 % target to split to
+ %debug\message{final 2-column material height=\the\ht0, target=\the\dimen at .}%
+ \splittopskip = \topskip
+ % Loop until we get a decent breakpoint.
+ {%
+ \vbadness = 10000
+ \loop
+ \global\setbox3 = \copy0
+ \global\setbox1 = \vsplit3 to \dimen@
+ \ifdim\ht3>\dimen@
+ \global\advance\dimen@ by 1pt
+ \repeat
+ }%
+ %debug\message{split to \the\dimen@, column heights: \the\ht1, \the\ht3.}%
+ \setbox0=\vbox to\dimen@{\unvbox1}%
+ \setbox2=\vbox to\dimen@{\unvbox3}%
+ %
+ \pagesofar
+ }
+ \catcode`\@ = \other
+
+
+ \message{sectioning,}
+ % Define chapters, sections, etc.
+
+ \newcount\chapno
+ \newcount\secno \secno=0
+ \newcount\subsecno \subsecno=0
+ \newcount\subsubsecno \subsubsecno=0
+
+ % This counter is funny since it counts through charcodes of letters A, B, ...
+ \newcount\appendixno \appendixno = `\@
+ \def\appendixletter{\char\the\appendixno}
+
+ % Each @chapter defines this as the name of the chapter.
+ % page headings and footings can use it. @section does likewise.
+ \def\thischapter{}
+ \def\thissection{}
+
+ \newcount\absseclevel % used to calculate proper heading level
+ \newcount\secbase\secbase=0 % @raise/lowersections modify this count
+
+ % @raisesections: treat @section as chapter, @subsection as section, etc.
+ \def\raisesections{\global\advance\secbase by -1}
+ \let\up=\raisesections % original BFox name
+
+ % @lowersections: treat @chapter as section, @section as subsection, etc.
+ \def\lowersections{\global\advance\secbase by 1}
+ \let\down=\lowersections % original BFox name
+
+ % Choose a numbered-heading macro
+ % #1 is heading level if unmodified by @raisesections or @lowersections
+ % #2 is text for heading
+ \def\numhead#1#2{\absseclevel=\secbase\advance\absseclevel by #1
+ \ifcase\absseclevel
+ \chapterzzz{#2}
+ \or
+ \seczzz{#2}
+ \or
+ \numberedsubseczzz{#2}
+ \or
+ \numberedsubsubseczzz{#2}
+ \else
+ \ifnum \absseclevel<0
+ \chapterzzz{#2}
+ \else
+ \numberedsubsubseczzz{#2}
+ \fi
+ \fi
+ }
+
+ % like \numhead, but chooses appendix heading levels
+ \def\apphead#1#2{\absseclevel=\secbase\advance\absseclevel by #1
+ \ifcase\absseclevel
+ \appendixzzz{#2}
+ \or
+ \appendixsectionzzz{#2}
+ \or
+ \appendixsubseczzz{#2}
+ \or
+ \appendixsubsubseczzz{#2}
+ \else
+ \ifnum \absseclevel<0
+ \appendixzzz{#2}
+ \else
+ \appendixsubsubseczzz{#2}
+ \fi
+ \fi
+ }
+
+ % like \numhead, but chooses numberless heading levels
+ \def\unnmhead#1#2{\absseclevel=\secbase\advance\absseclevel by #1
+ \ifcase\absseclevel
+ \unnumberedzzz{#2}
+ \or
+ \unnumberedseczzz{#2}
+ \or
+ \unnumberedsubseczzz{#2}
+ \or
+ \unnumberedsubsubseczzz{#2}
+ \else
+ \ifnum \absseclevel<0
+ \unnumberedzzz{#2}
+ \else
+ \unnumberedsubsubseczzz{#2}
+ \fi
+ \fi
+ }
+
+ % @chapter, @appendix, @unnumbered.
+ \def\thischaptername{No Chapter Title}
+ \outer\def\chapter{\parsearg\chapteryyy}
+ \def\chapteryyy #1{\numhead0{#1}} % normally numhead0 calls chapterzzz
+ \def\chapterzzz #1{%
+ \secno=0 \subsecno=0 \subsubsecno=0
+ \global\advance \chapno by 1 \message{\putwordChapter\space \the\chapno}%
+ \chapmacro {#1}{\the\chapno}%
+ \gdef\thissection{#1}%
+ \gdef\thischaptername{#1}%
+ % We don't substitute the actual chapter name into \thischapter
+ % because we don't want its macros evaluated now.
+ \xdef\thischapter{\putwordChapter{} \the\chapno: \noexpand\thischaptername}%
+ \toks0 = {#1}%
+ \edef\temp{\noexpand\writetocentry{\realbackslash chapentry{\the\toks0}%
+ {\the\chapno}}}%
+ \temp
+ \donoderef
+ \global\let\section = \numberedsec
+ \global\let\subsection = \numberedsubsec
+ \global\let\subsubsection = \numberedsubsubsec
+ }
+
+ \outer\def\appendix{\parsearg\appendixyyy}
+ \def\appendixyyy #1{\apphead0{#1}} % normally apphead0 calls appendixzzz
+ \def\appendixzzz #1{%
+ \secno=0 \subsecno=0 \subsubsecno=0
+ \global\advance \appendixno by 1
+ \message{\putwordAppendix\space \appendixletter}%
+ \chapmacro {#1}{\putwordAppendix{} \appendixletter}%
+ \gdef\thissection{#1}%
+ \gdef\thischaptername{#1}%
+ \xdef\thischapter{\putwordAppendix{} \appendixletter: \noexpand\thischaptername}%
+ \toks0 = {#1}%
+ \edef\temp{\noexpand\writetocentry{\realbackslash chapentry{\the\toks0}%
+ {\putwordAppendix{} \appendixletter}}}%
+ \temp
+ \appendixnoderef
+ \global\let\section = \appendixsec
+ \global\let\subsection = \appendixsubsec
+ \global\let\subsubsection = \appendixsubsubsec
+ }
+
+ % @centerchap is like @unnumbered, but the heading is centered.
+ \outer\def\centerchap{\parsearg\centerchapyyy}
+ \def\centerchapyyy #1{{\let\unnumbchapmacro=\centerchapmacro \unnumberedyyy{#1}}}
+
+ % @top is like @unnumbered.
+ \outer\def\top{\parsearg\unnumberedyyy}
+
+ \outer\def\unnumbered{\parsearg\unnumberedyyy}
+ \def\unnumberedyyy #1{\unnmhead0{#1}} % normally unnmhead0 calls unnumberedzzz
+ \def\unnumberedzzz #1{%
+ \secno=0 \subsecno=0 \subsubsecno=0
+ %
+ % This used to be simply \message{#1}, but TeX fully expands the
+ % argument to \message. Therefore, if #1 contained @-commands, TeX
+ % expanded them. For example, in `@unnumbered The @cite{Book}', TeX
+ % expanded @cite (which turns out to cause errors because \cite is meant
+ % to be executed, not expanded).
+ %
+ % Anyway, we don't want the fully-expanded definition of @cite to appear
+ % as a result of the \message, we just want `@cite' itself. We use
+ % \the<toks register> to achieve this: TeX expands \the<toks> only once,
+ % simply yielding the contents of <toks register>. (We also do this for
+ % the toc entries.)
+ \toks0 = {#1}\message{(\the\toks0)}%
+ %
+ \unnumbchapmacro {#1}%
+ \gdef\thischapter{#1}\gdef\thissection{#1}%
+ \toks0 = {#1}%
+ \edef\temp{\noexpand\writetocentry{\realbackslash unnumbchapentry{\the\toks0}}}%
+ \temp
+ \unnumbnoderef
+ \global\let\section = \unnumberedsec
+ \global\let\subsection = \unnumberedsubsec
+ \global\let\subsubsection = \unnumberedsubsubsec
+ }
+
+ % Sections.
+ \outer\def\numberedsec{\parsearg\secyyy}
+ \def\secyyy #1{\numhead1{#1}} % normally calls seczzz
+ \def\seczzz #1{%
+ \subsecno=0 \subsubsecno=0 \global\advance \secno by 1 %
+ \gdef\thissection{#1}\secheading {#1}{\the\chapno}{\the\secno}%
+ \toks0 = {#1}%
+ \edef\temp{\noexpand\writetocentry{\realbackslash secentry{\the\toks0}%
+ {\the\chapno}{\the\secno}}}%
+ \temp
+ \donoderef
+ \nobreak
+ }
+
+ \outer\def\appendixsection{\parsearg\appendixsecyyy}
+ \outer\def\appendixsec{\parsearg\appendixsecyyy}
+ \def\appendixsecyyy #1{\apphead1{#1}} % normally calls appendixsectionzzz
+ \def\appendixsectionzzz #1{%
+ \subsecno=0 \subsubsecno=0 \global\advance \secno by 1 %
+ \gdef\thissection{#1}\secheading {#1}{\appendixletter}{\the\secno}%
+ \toks0 = {#1}%
+ \edef\temp{\noexpand\writetocentry{\realbackslash secentry{\the\toks0}%
+ {\appendixletter}{\the\secno}}}%
+ \temp
+ \appendixnoderef
+ \nobreak
+ }
+
+ \outer\def\unnumberedsec{\parsearg\unnumberedsecyyy}
+ \def\unnumberedsecyyy #1{\unnmhead1{#1}} % normally calls unnumberedseczzz
+ \def\unnumberedseczzz #1{%
+ \plainsecheading {#1}\gdef\thissection{#1}%
+ \toks0 = {#1}%
+ \edef\temp{\noexpand\writetocentry{\realbackslash unnumbsecentry{\the\toks0}}}%
+ \temp
+ \unnumbnoderef
+ \nobreak
+ }
+
+ % Subsections.
+ \outer\def\numberedsubsec{\parsearg\numberedsubsecyyy}
+ \def\numberedsubsecyyy #1{\numhead2{#1}} % normally calls numberedsubseczzz
+ \def\numberedsubseczzz #1{%
+ \gdef\thissection{#1}\subsubsecno=0 \global\advance \subsecno by 1 %
+ \subsecheading {#1}{\the\chapno}{\the\secno}{\the\subsecno}%
+ \toks0 = {#1}%
+ \edef\temp{\noexpand\writetocentry{\realbackslash subsecentry{\the\toks0}%
+ {\the\chapno}{\the\secno}{\the\subsecno}}}%
+ \temp
+ \donoderef
+ \nobreak
+ }
+
+ \outer\def\appendixsubsec{\parsearg\appendixsubsecyyy}
+ \def\appendixsubsecyyy #1{\apphead2{#1}} % normally calls appendixsubseczzz
+ \def\appendixsubseczzz #1{%
+ \gdef\thissection{#1}\subsubsecno=0 \global\advance \subsecno by 1 %
+ \subsecheading {#1}{\appendixletter}{\the\secno}{\the\subsecno}%
+ \toks0 = {#1}%
+ \edef\temp{\noexpand\writetocentry{\realbackslash subsecentry{\the\toks0}%
+ {\appendixletter}{\the\secno}{\the\subsecno}}}%
+ \temp
+ \appendixnoderef
+ \nobreak
+ }
+
+ \outer\def\unnumberedsubsec{\parsearg\unnumberedsubsecyyy}
+ \def\unnumberedsubsecyyy #1{\unnmhead2{#1}} %normally calls unnumberedsubseczzz
+ \def\unnumberedsubseczzz #1{%
+ \plainsubsecheading {#1}\gdef\thissection{#1}%
+ \toks0 = {#1}%
+ \edef\temp{\noexpand\writetocentry{\realbackslash unnumbsubsecentry%
+ {\the\toks0}}}%
+ \temp
+ \unnumbnoderef
+ \nobreak
+ }
+
+ % Subsubsections.
+ \outer\def\numberedsubsubsec{\parsearg\numberedsubsubsecyyy}
+ \def\numberedsubsubsecyyy #1{\numhead3{#1}} % normally numberedsubsubseczzz
+ \def\numberedsubsubseczzz #1{%
+ \gdef\thissection{#1}\global\advance \subsubsecno by 1 %
+ \subsubsecheading {#1}
+ {\the\chapno}{\the\secno}{\the\subsecno}{\the\subsubsecno}%
+ \toks0 = {#1}%
+ \edef\temp{\noexpand\writetocentry{\realbackslash subsubsecentry{\the\toks0}%
+ {\the\chapno}{\the\secno}{\the\subsecno}{\the\subsubsecno}}}%
+ \temp
+ \donoderef
+ \nobreak
+ }
+
+ \outer\def\appendixsubsubsec{\parsearg\appendixsubsubsecyyy}
+ \def\appendixsubsubsecyyy #1{\apphead3{#1}} % normally appendixsubsubseczzz
+ \def\appendixsubsubseczzz #1{%
+ \gdef\thissection{#1}\global\advance \subsubsecno by 1 %
+ \subsubsecheading {#1}
+ {\appendixletter}{\the\secno}{\the\subsecno}{\the\subsubsecno}%
+ \toks0 = {#1}%
+ \edef\temp{\noexpand\writetocentry{\realbackslash subsubsecentry{\the\toks0}%
+ {\appendixletter}{\the\secno}{\the\subsecno}{\the\subsubsecno}}}%
+ \temp
+ \appendixnoderef
+ \nobreak
+ }
+
+ \outer\def\unnumberedsubsubsec{\parsearg\unnumberedsubsubsecyyy}
+ \def\unnumberedsubsubsecyyy #1{\unnmhead3{#1}} %normally unnumberedsubsubseczzz
+ \def\unnumberedsubsubseczzz #1{%
+ \plainsubsubsecheading {#1}\gdef\thissection{#1}%
+ \toks0 = {#1}%
+ \edef\temp{\noexpand\writetocentry{\realbackslash unnumbsubsubsecentry%
+ {\the\toks0}}}%
+ \temp
+ \unnumbnoderef
+ \nobreak
+ }
+
+ % These are variants which are not "outer", so they can appear in @ifinfo.
+ % Actually, they should now be obsolete; ordinary section commands should work.
+ \def\infotop{\parsearg\unnumberedzzz}
+ \def\infounnumbered{\parsearg\unnumberedzzz}
+ \def\infounnumberedsec{\parsearg\unnumberedseczzz}
+ \def\infounnumberedsubsec{\parsearg\unnumberedsubseczzz}
+ \def\infounnumberedsubsubsec{\parsearg\unnumberedsubsubseczzz}
+
+ \def\infoappendix{\parsearg\appendixzzz}
+ \def\infoappendixsec{\parsearg\appendixseczzz}
+ \def\infoappendixsubsec{\parsearg\appendixsubseczzz}
+ \def\infoappendixsubsubsec{\parsearg\appendixsubsubseczzz}
+
+ \def\infochapter{\parsearg\chapterzzz}
+ \def\infosection{\parsearg\sectionzzz}
+ \def\infosubsection{\parsearg\subsectionzzz}
+ \def\infosubsubsection{\parsearg\subsubsectionzzz}
+
+ % These macros control what the section commands do, according
+ % to what kind of chapter we are in (ordinary, appendix, or unnumbered).
+ % Define them by default for a numbered chapter.
+ \global\let\section = \numberedsec
+ \global\let\subsection = \numberedsubsec
+ \global\let\subsubsection = \numberedsubsubsec
+
+ % Define @majorheading, @heading and @subheading
+
+ % NOTE on use of \vbox for chapter headings, section headings, and such:
+ % 1) We use \vbox rather than the earlier \line to permit
+ % overlong headings to fold.
+ % 2) \hyphenpenalty is set to 10000 because hyphenation in a
+ % heading is obnoxious; this forbids it.
+ % 3) Likewise, headings look best if no \parindent is used, and
+ % if justification is not attempted. Hence \raggedright.
+
+
+ \def\majorheading{\parsearg\majorheadingzzz}
+ \def\majorheadingzzz #1{%
+ {\advance\chapheadingskip by 10pt \chapbreak }%
+ {\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000
+ \parindent=0pt\raggedright
+ \rm #1\hfill}}\bigskip \par\penalty 200}
+
+ \def\chapheading{\parsearg\chapheadingzzz}
+ \def\chapheadingzzz #1{\chapbreak %
+ {\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000
+ \parindent=0pt\raggedright
+ \rm #1\hfill}}\bigskip \par\penalty 200}
+
+ % @heading, @subheading, @subsubheading.
+ \def\heading{\parsearg\plainsecheading}
+ \def\subheading{\parsearg\plainsubsecheading}
+ \def\subsubheading{\parsearg\plainsubsubsecheading}
+
+ % These macros generate a chapter, section, etc. heading only
+ % (including whitespace, linebreaking, etc. around it),
+ % given all the information in convenient, parsed form.
+
+ %%% Args are the skip and penalty (usually negative)
+ \def\dobreak#1#2{\par\ifdim\lastskip<#1\removelastskip\penalty#2\vskip#1\fi}
+
+ \def\setchapterstyle #1 {\csname CHAPF#1\endcsname}
+
+ %%% Define plain chapter starts, and page on/off switching for it
+ % Parameter controlling skip before chapter headings (if needed)
+
+ \newskip\chapheadingskip
+
+ \def\chapbreak{\dobreak \chapheadingskip {-4000}}
+ \def\chappager{\par\vfill\supereject}
+ \def\chapoddpage{\chappager \ifodd\pageno \else \hbox to 0pt{} \chappager\fi}
+
+ \def\setchapternewpage #1 {\csname CHAPPAG#1\endcsname}
+
+ \def\CHAPPAGoff{%
+ \global\let\contentsalignmacro = \chappager
+ \global\let\pchapsepmacro=\chapbreak
+ \global\let\pagealignmacro=\chappager}
+
+ \def\CHAPPAGon{%
+ \global\let\contentsalignmacro = \chappager
+ \global\let\pchapsepmacro=\chappager
+ \global\let\pagealignmacro=\chappager
+ \global\def\HEADINGSon{\HEADINGSsingle}}
+
+ \def\CHAPPAGodd{
+ \global\let\contentsalignmacro = \chapoddpage
+ \global\let\pchapsepmacro=\chapoddpage
+ \global\let\pagealignmacro=\chapoddpage
+ \global\def\HEADINGSon{\HEADINGSdouble}}
+
+ \CHAPPAGon
+
+ \def\CHAPFplain{
+ \global\let\chapmacro=\chfplain
+ \global\let\unnumbchapmacro=\unnchfplain
+ \global\let\centerchapmacro=\centerchfplain}
+
+ % Plain chapter opening.
+ % #1 is the text, #2 the chapter number or empty if unnumbered.
+ \def\chfplain#1#2{%
+ \pchapsepmacro
+ {%
+ \chapfonts \rm
+ \def\chapnum{#2}%
+ \setbox0 = \hbox{#2\ifx\chapnum\empty\else\enspace\fi}%
+ \vbox{\hyphenpenalty=10000 \tolerance=5000 \parindent=0pt \raggedright
+ \hangindent = \wd0 \centerparametersmaybe
+ \unhbox0 #1\par}%
+ }%
+ \nobreak\bigskip % no page break after a chapter title
+ \nobreak
+ }
+
+ % Plain opening for unnumbered.
+ \def\unnchfplain#1{\chfplain{#1}{}}
+
+ % @centerchap -- centered and unnumbered.
+ \let\centerparametersmaybe = \relax
+ \def\centerchfplain#1{{%
+ \def\centerparametersmaybe{%
+ \advance\rightskip by 3\rightskip
+ \leftskip = \rightskip
+ \parfillskip = 0pt
+ }%
+ \chfplain{#1}{}%
+ }}
+
+ \CHAPFplain % The default
+
+ \def\unnchfopen #1{%
+ \chapoddpage {\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000
+ \parindent=0pt\raggedright
+ \rm #1\hfill}}\bigskip \par\nobreak
+ }
+
+ \def\chfopen #1#2{\chapoddpage {\chapfonts
+ \vbox to 3in{\vfil \hbox to\hsize{\hfil #2} \hbox to\hsize{\hfil #1} \vfil}}%
+ \par\penalty 5000 %
+ }
+
+ \def\centerchfopen #1{%
+ \chapoddpage {\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000
+ \parindent=0pt
+ \hfill {\rm #1}\hfill}}\bigskip \par\nobreak
+ }
+
+ \def\CHAPFopen{
+ \global\let\chapmacro=\chfopen
+ \global\let\unnumbchapmacro=\unnchfopen
+ \global\let\centerchapmacro=\centerchfopen}
+
+
+ % Section titles.
+ \newskip\secheadingskip
+ \def\secheadingbreak{\dobreak \secheadingskip {-1000}}
+ \def\secheading#1#2#3{\sectionheading{sec}{#2.#3}{#1}}
+ \def\plainsecheading#1{\sectionheading{sec}{}{#1}}
+
+ % Subsection titles.
+ \newskip \subsecheadingskip
+ \def\subsecheadingbreak{\dobreak \subsecheadingskip {-500}}
+ \def\subsecheading#1#2#3#4{\sectionheading{subsec}{#2.#3.#4}{#1}}
+ \def\plainsubsecheading#1{\sectionheading{subsec}{}{#1}}
+
+ % Subsubsection titles.
+ \let\subsubsecheadingskip = \subsecheadingskip
+ \let\subsubsecheadingbreak = \subsecheadingbreak
+ \def\subsubsecheading#1#2#3#4#5{\sectionheading{subsubsec}{#2.#3.#4.#5}{#1}}
+ \def\plainsubsubsecheading#1{\sectionheading{subsubsec}{}{#1}}
+
+
+ % Print any size section title.
+ %
+ % #1 is the section type (sec/subsec/subsubsec), #2 is the section
+ % number (maybe empty), #3 the text.
+ \def\sectionheading#1#2#3{%
+ {%
+ \expandafter\advance\csname #1headingskip\endcsname by \parskip
+ \csname #1headingbreak\endcsname
+ }%
+ {%
+ % Switch to the right set of fonts.
+ \csname #1fonts\endcsname \rm
+ %
+ % Only insert the separating space if we have a section number.
+ \def\secnum{#2}%
+ \setbox0 = \hbox{#2\ifx\secnum\empty\else\enspace\fi}%
+ %
+ \vbox{\hyphenpenalty=10000 \tolerance=5000 \parindent=0pt \raggedright
+ \hangindent = \wd0 % zero if no section number
+ \unhbox0 #3}%
+ }%
+ \ifdim\parskip<10pt \nobreak\kern10pt\nobreak\kern-\parskip\fi \nobreak
+ }
+
+
+ \message{toc,}
+ \newwrite\tocfile
+
+ % Write an entry to the toc file, opening it if necessary.
+ % Called from @chapter, etc. We supply {\folio} at the end of the
+ % argument, which will end up as the last argument to the \...entry macro.
+ %
+ % We open the .toc file here instead of at @setfilename or any other
+ % given time so that @contents can be put in the document anywhere.
+ %
+ \newif\iftocfileopened
+ \def\writetocentry#1{%
+ \iftocfileopened\else
+ \immediate\openout\tocfile = \jobname.toc
+ \global\tocfileopenedtrue
+ \fi
+ \iflinks \write\tocfile{#1{\folio}}\fi
+ }
+
+ \newskip\contentsrightmargin \contentsrightmargin=1in
+ \newcount\savepageno
+ \newcount\lastnegativepageno \lastnegativepageno = -1
+
+ % Finish up the main text and prepare to read what we've written
+ % to \tocfile.
+ %
+ \def\startcontents#1{%
+ % If @setchapternewpage on, and @headings double, the contents should
+ % start on an odd page, unlike chapters. Thus, we maintain
+ % \contentsalignmacro in parallel with \pagealignmacro.
+ % From: Torbjorn Granlund <tege at matematik.su.se>
+ \contentsalignmacro
+ \immediate\closeout\tocfile
+ %
+ % Don't need to put `Contents' or `Short Contents' in the headline.
+ % It is abundantly clear what they are.
+ \unnumbchapmacro{#1}\def\thischapter{}%
+ \savepageno = \pageno
+ \begingroup % Set up to handle contents files properly.
+ \catcode`\\=0 \catcode`\{=1 \catcode`\}=2 \catcode`\@=11
+ % We can't do this, because then an actual ^ in a section
+ % title fails, e.g., @chapter ^ -- exponentiation. --karl, 9jul97.
+ %\catcode`\^=7 % to see ^^e4 as \"a etc. juha at piuha.ydi.vtt.fi
+ \raggedbottom % Worry more about breakpoints than the bottom.
+ \advance\hsize by -\contentsrightmargin % Don't use the full line length.
+ %
+ % Roman numerals for page numbers.
+ \ifnum \pageno>0 \pageno = \lastnegativepageno \fi
+ }
+
+
+ % Normal (long) toc.
+ \def\contents{%
+ \startcontents{\putwordTableofContents}%
+ \openin 1 \jobname.toc
+ \ifeof 1 \else
+ \closein 1
+ \input \jobname.toc
+ \fi
+ \vfill \eject
+ \endgroup
+ \lastnegativepageno = \pageno
+ \pageno = \savepageno
+ }
+
+ % And just the chapters.
+ \def\summarycontents{%
+ \startcontents{\putwordShortContents}%
+ %
+ \let\chapentry = \shortchapentry
+ \let\unnumbchapentry = \shortunnumberedentry
+ % We want a true roman here for the page numbers.
+ \secfonts
+ \let\rm=\shortcontrm \let\bf=\shortcontbf \let\sl=\shortcontsl
+ \rm
+ \hyphenpenalty = 10000
+ \advance\baselineskip by 1pt % Open it up a little.
+ \def\secentry ##1##2##3##4{}
+ \def\unnumbsecentry ##1##2{}
+ \def\subsecentry ##1##2##3##4##5{}
+ \def\unnumbsubsecentry ##1##2{}
+ \def\subsubsecentry ##1##2##3##4##5##6{}
+ \def\unnumbsubsubsecentry ##1##2{}
+ \openin 1 \jobname.toc
+ \ifeof 1 \else
+ \closein 1
+ \input \jobname.toc
+ \fi
+ \vfill \eject
+ \endgroup
+ \lastnegativepageno = \pageno
+ \pageno = \savepageno
+ }
+ \let\shortcontents = \summarycontents
+
+ % These macros generate individual entries in the table of contents.
+ % The first argument is the chapter or section name.
+ % The last argument is the page number.
+ % The arguments in between are the chapter number, section number, ...
+
+ % Chapter-level things, for both the long and short contents.
+ \def\chapentry#1#2#3{\dochapentry{#2\labelspace#1}{#3}}
+
+ % See comments in \dochapentry re vbox and related settings
+ \def\shortchapentry#1#2#3{%
+ \tocentry{\shortchaplabel{#2}\labelspace #1}{\doshortpageno{#3}}%
+ }
+
+ % Typeset the label for a chapter or appendix for the short contents.
+ % The arg is, e.g. `Appendix A' for an appendix, or `3' for a chapter.
+ % We could simplify the code here by writing out an \appendixentry
+ % command in the toc file for appendices, instead of using \chapentry
+ % for both, but it doesn't seem worth it.
+ \setbox0 = \hbox{\shortcontrm \putwordAppendix }
+ \newdimen\shortappendixwidth \shortappendixwidth = \wd0
+
+ \def\shortchaplabel#1{%
+ % We typeset #1 in a box of constant width, regardless of the text of
+ % #1, so the chapter titles will come out aligned.
+ \setbox0 = \hbox{#1}%
+ \dimen0 = \ifdim\wd0 > \shortappendixwidth \shortappendixwidth \else 0pt \fi
+ %
+ % This space should be plenty, since a single number is .5em, and the
+ % widest letter (M) is 1em, at least in the Computer Modern fonts.
+ % (This space doesn't include the extra space that gets added after
+ % the label; that gets put in by \shortchapentry above.)
+ \advance\dimen0 by 1.1em
+ \hbox to \dimen0{#1\hfil}%
+ }
+
+ \def\unnumbchapentry#1#2{\dochapentry{#1}{#2}}
+ \def\shortunnumberedentry#1#2{\tocentry{#1}{\doshortpageno{#2}}}
+
+ % Sections.
+ \def\secentry#1#2#3#4{\dosecentry{#2.#3\labelspace#1}{#4}}
+ \def\unnumbsecentry#1#2{\dosecentry{#1}{#2}}
+
+ % Subsections.
+ \def\subsecentry#1#2#3#4#5{\dosubsecentry{#2.#3.#4\labelspace#1}{#5}}
+ \def\unnumbsubsecentry#1#2{\dosubsecentry{#1}{#2}}
+
+ % And subsubsections.
+ \def\subsubsecentry#1#2#3#4#5#6{%
+ \dosubsubsecentry{#2.#3.#4.#5\labelspace#1}{#6}}
+ \def\unnumbsubsubsecentry#1#2{\dosubsubsecentry{#1}{#2}}
+
+ % This parameter controls the indentation of the various levels.
+ \newdimen\tocindent \tocindent = 3pc
+
+ % Now for the actual typesetting. In all these, #1 is the text and #2 is the
+ % page number.
+ %
+ % If the toc has to be broken over pages, we want it to be at chapters
+ % if at all possible; hence the \penalty.
+ \def\dochapentry#1#2{%
+ \penalty-300 \vskip1\baselineskip plus.33\baselineskip minus.25\baselineskip
+ \begingroup
+ \chapentryfonts
+ \tocentry{#1}{\dopageno{#2}}%
+ \endgroup
+ \nobreak\vskip .25\baselineskip plus.1\baselineskip
+ }
+
+ \def\dosecentry#1#2{\begingroup
+ \secentryfonts \leftskip=\tocindent
+ \tocentry{#1}{\dopageno{#2}}%
+ \endgroup}
+
+ \def\dosubsecentry#1#2{\begingroup
+ \subsecentryfonts \leftskip=2\tocindent
+ \tocentry{#1}{\dopageno{#2}}%
+ \endgroup}
+
+ \def\dosubsubsecentry#1#2{\begingroup
+ \subsubsecentryfonts \leftskip=3\tocindent
+ \tocentry{#1}{\dopageno{#2}}%
+ \endgroup}
+
+ % Final typesetting of a toc entry; we use the same \entry macro as for
+ % the index entries, but we want to suppress hyphenation here. (We
+ % can't do that in the \entry macro, since index entries might consist
+ % of hyphenated-identifiers-that-do-not-fit-on-a-line-and-nothing-else.)
+ \def\tocentry#1#2{\begingroup
+ \vskip 0pt plus1pt % allow a little stretch for the sake of nice page breaks
+ % Do not use \turnoffactive in these arguments. Since the toc is
+ % typeset in cmr, so characters such as _ would come out wrong; we
+ % have to do the usual translation tricks.
+ \entry{#1}{#2}%
+ \endgroup}
+
+ % Space between chapter (or whatever) number and the title.
+ \def\labelspace{\hskip1em \relax}
+
+ \def\dopageno#1{{\rm #1}}
+ \def\doshortpageno#1{{\rm #1}}
+
+ \def\chapentryfonts{\secfonts \rm}
+ \def\secentryfonts{\textfonts}
+ \let\subsecentryfonts = \textfonts
+ \let\subsubsecentryfonts = \textfonts
+
+
+ \message{environments,}
+
+ % Since these characters are used in examples, it should be an even number of
+ % \tt widths. Each \tt character is 1en, so two makes it 1em.
+ % Furthermore, these definitions must come after we define our fonts.
+ \newbox\dblarrowbox \newbox\longdblarrowbox
+ \newbox\pushcharbox \newbox\bullbox
+ \newbox\equivbox \newbox\errorbox
+
+ %{\tentt
+ %\global\setbox\dblarrowbox = \hbox to 1em{\hfil$\Rightarrow$\hfil}
+ %\global\setbox\longdblarrowbox = \hbox to 1em{\hfil$\mapsto$\hfil}
+ %\global\setbox\pushcharbox = \hbox to 1em{\hfil$\dashv$\hfil}
+ %\global\setbox\equivbox = \hbox to 1em{\hfil$\ptexequiv$\hfil}
+ % Adapted from the manmac format (p.420 of TeXbook)
+ %\global\setbox\bullbox = \hbox to 1em{\kern.15em\vrule height .75ex width .85ex
+ % depth .1ex\hfil}
+ %}
+
+ % @point{}, @result{}, @expansion{}, @print{}, @equiv{}.
+ \def\point{$\star$}
+ \def\result{\leavevmode\raise.15ex\hbox to 1em{\hfil$\Rightarrow$\hfil}}
+ \def\expansion{\leavevmode\raise.1ex\hbox to 1em{\hfil$\mapsto$\hfil}}
+ \def\print{\leavevmode\lower.1ex\hbox to 1em{\hfil$\dashv$\hfil}}
+ \def\equiv{\leavevmode\lower.1ex\hbox to 1em{\hfil$\ptexequiv$\hfil}}
+
+ % Adapted from the TeXbook's \boxit.
+ {\tentt \global\dimen0 = 3em}% Width of the box.
+ \dimen2 = .55pt % Thickness of rules
+ % The text. (`r' is open on the right, `e' somewhat less so on the left.)
+ \setbox0 = \hbox{\kern-.75pt \tensf error\kern-1.5pt}
+
+ \global\setbox\errorbox=\hbox to \dimen0{\hfil
+ \hsize = \dimen0 \advance\hsize by -5.8pt % Space to left+right.
+ \advance\hsize by -2\dimen2 % Rules.
+ \vbox{
+ \hrule height\dimen2
+ \hbox{\vrule width\dimen2 \kern3pt % Space to left of text.
+ \vtop{\kern2.4pt \box0 \kern2.4pt}% Space above/below.
+ \kern3pt\vrule width\dimen2}% Space to right.
+ \hrule height\dimen2}
+ \hfil}
+
+ % The @error{} command.
+ \def\error{\leavevmode\lower.7ex\copy\errorbox}
+
+ % @tex ... @end tex escapes into raw Tex temporarily.
+ % One exception: @ is still an escape character, so that @end tex works.
+ % But \@ or @@ will get a plain tex @ character.
+
+ \def\tex{\begingroup
+ \catcode `\\=0 \catcode `\{=1 \catcode `\}=2
+ \catcode `\$=3 \catcode `\&=4 \catcode `\#=6
+ \catcode `\^=7 \catcode `\_=8 \catcode `\~=13 \let~=\tie
+ \catcode `\%=14
+ \catcode 43=12 % plus
+ \catcode`\"=12
+ \catcode`\==12
+ \catcode`\|=12
+ \catcode`\<=12
+ \catcode`\>=12
+ \escapechar=`\\
+ %
+ \let\b=\ptexb
+ \let\bullet=\ptexbullet
+ \let\c=\ptexc
+ \let\,=\ptexcomma
+ \let\.=\ptexdot
+ \let\dots=\ptexdots
+ \let\equiv=\ptexequiv
+ \let\!=\ptexexclam
+ \let\i=\ptexi
+ \let\{=\ptexlbrace
+ \let\+=\tabalign
+ \let\}=\ptexrbrace
+ \let\*=\ptexstar
+ \let\t=\ptext
+ %
+ \def\endldots{\mathinner{\ldots\ldots\ldots\ldots}}%
+ \def\enddots{\relax\ifmmode\endldots\else$\mathsurround=0pt \endldots\,$\fi}%
+ \def\@{@}%
+ \let\Etex=\endgroup}
+
+ % Define @lisp ... @endlisp.
+ % @lisp does a \begingroup so it can rebind things,
+ % including the definition of @endlisp (which normally is erroneous).
+
+ % Amount to narrow the margins by for @lisp.
+ \newskip\lispnarrowing \lispnarrowing=0.4in
+
+ % This is the definition that ^^M gets inside @lisp, @example, and other
+ % such environments. \null is better than a space, since it doesn't
+ % have any width.
+ \def\lisppar{\null\endgraf}
+
+ % Make each space character in the input produce a normal interword
+ % space in the output. Don't allow a line break at this space, as this
+ % is used only in environments like @example, where each line of input
+ % should produce a line of output anyway.
+ %
+ {\obeyspaces %
+ \gdef\sepspaces{\obeyspaces\let =\tie}}
+
+ % Define \obeyedspace to be our active space, whatever it is. This is
+ % for use in \parsearg.
+ {\sepspaces%
+ \global\let\obeyedspace= }
+
+ % This space is always present above and below environments.
+ \newskip\envskipamount \envskipamount = 0pt
+
+ % Make spacing and below environment symmetrical. We use \parskip here
+ % to help in doing that, since in @example-like environments \parskip
+ % is reset to zero; thus the \afterenvbreak inserts no space -- but the
+ % start of the next paragraph will insert \parskip
+ %
+ \def\aboveenvbreak{{\advance\envskipamount by \parskip
+ \endgraf \ifdim\lastskip<\envskipamount
+ \removelastskip \penalty-50 \vskip\envskipamount \fi}}
+
+ \let\afterenvbreak = \aboveenvbreak
+
+ % \nonarrowing is a flag. If "set", @lisp etc don't narrow margins.
+ \let\nonarrowing=\relax
+
+ % @cartouche ... @end cartouche: draw rectangle w/rounded corners around
+ % environment contents.
+ \font\circle=lcircle10
+ \newdimen\circthick
+ \newdimen\cartouter\newdimen\cartinner
+ \newskip\normbskip\newskip\normpskip\newskip\normlskip
+ \circthick=\fontdimen8\circle
+ %
+ \def\ctl{{\circle\char'013\hskip -6pt}}% 6pt from pl file: 1/2charwidth
+ \def\ctr{{\hskip 6pt\circle\char'010}}
+ \def\cbl{{\circle\char'012\hskip -6pt}}
+ \def\cbr{{\hskip 6pt\circle\char'011}}
+ \def\carttop{\hbox to \cartouter{\hskip\lskip
+ \ctl\leaders\hrule height\circthick\hfil\ctr
+ \hskip\rskip}}
+ \def\cartbot{\hbox to \cartouter{\hskip\lskip
+ \cbl\leaders\hrule height\circthick\hfil\cbr
+ \hskip\rskip}}
+ %
+ \newskip\lskip\newskip\rskip
+
+ \long\def\cartouche{%
+ \begingroup
+ \lskip=\leftskip \rskip=\rightskip
+ \leftskip=0pt\rightskip=0pt %we want these *outside*.
+ \cartinner=\hsize \advance\cartinner by-\lskip
+ \advance\cartinner by-\rskip
+ \cartouter=\hsize
+ \advance\cartouter by 18.4pt % allow for 3pt kerns on either
+ % side, and for 6pt waste from
+ % each corner char, and rule thickness
+ \normbskip=\baselineskip \normpskip=\parskip \normlskip=\lineskip
+ % Flag to tell @lisp, etc., not to narrow margin.
+ \let\nonarrowing=\comment
+ \vbox\bgroup
+ \baselineskip=0pt\parskip=0pt\lineskip=0pt
+ \carttop
+ \hbox\bgroup
+ \hskip\lskip
+ \vrule\kern3pt
+ \vbox\bgroup
+ \hsize=\cartinner
+ \kern3pt
+ \begingroup
+ \baselineskip=\normbskip
+ \lineskip=\normlskip
+ \parskip=\normpskip
+ \vskip -\parskip
+ \def\Ecartouche{%
+ \endgroup
+ \kern3pt
+ \egroup
+ \kern3pt\vrule
+ \hskip\rskip
+ \egroup
+ \cartbot
+ \egroup
+ \endgroup
+ }}
+
+
+ % This macro is called at the beginning of all the @example variants,
+ % inside a group.
+ \def\nonfillstart{%
+ \aboveenvbreak
+ \inENV % This group ends at the end of the body
+ \hfuzz = 12pt % Don't be fussy
+ \sepspaces % Make spaces be word-separators rather than space tokens.
+ \singlespace
+ \let\par = \lisppar % don't ignore blank lines
+ \obeylines % each line of input is a line of output
+ \parskip = 0pt
+ \parindent = 0pt
+ \emergencystretch = 0pt % don't try to avoid overfull boxes
+ % @cartouche defines \nonarrowing to inhibit narrowing
+ % at next level down.
+ \ifx\nonarrowing\relax
+ \advance \leftskip by \lispnarrowing
+ \exdentamount=\lispnarrowing
+ \let\exdent=\nofillexdent
+ \let\nonarrowing=\relax
+ \fi
+ }
+
+ % Define the \E... control sequence only if we are inside the particular
+ % environment, so the error checking in \end will work.
+ %
+ % To end an @example-like environment, we first end the paragraph (via
+ % \afterenvbreak's vertical glue), and then the group. That way we keep
+ % the zero \parskip that the environments set -- \parskip glue will be
+ % inserted at the beginning of the next paragraph in the document, after
+ % the environment.
+ %
+ \def\nonfillfinish{\afterenvbreak\endgroup}
+
+ % @lisp: indented, narrowed, typewriter font.
+ \def\lisp{\begingroup
+ \nonfillstart
+ \let\Elisp = \nonfillfinish
+ \tt
+ \let\kbdfont = \kbdexamplefont % Allow @kbd to do something special.
+ \gobble % eat return
+ }
+
+ % @example: Same as @lisp.
+ \def\example{\begingroup \def\Eexample{\nonfillfinish\endgroup}\lisp}
+
+ % @small... is usually equivalent to the non-small (@smallbook
+ % redefines). We must call \example (or whatever) last in the
+ % definition, since it reads the return following the @example (or
+ % whatever) command.
+ %
+ % This actually allows (for example) @end display inside an
+ % @smalldisplay. Too bad, but makeinfo will catch the error anyway.
+ %
+ \def\smalldisplay{\begingroup\def\Esmalldisplay{\nonfillfinish\endgroup}\display}
+ \def\smallexample{\begingroup\def\Esmallexample{\nonfillfinish\endgroup}\lisp}
+ \def\smallformat{\begingroup\def\Esmallformat{\nonfillfinish\endgroup}\format}
+ \def\smalllisp{\begingroup\def\Esmalllisp{\nonfillfinish\endgroup}\lisp}
+
+ % Real @smallexample and @smalllisp (when @smallbook): use smaller fonts.
+ % Originally contributed by Pavel at xerox.
+ \def\smalllispx{\begingroup
+ \def\Esmalllisp{\nonfillfinish\endgroup}%
+ \def\Esmallexample{\nonfillfinish\endgroup}%
+ \indexfonts
+ \lisp
+ }
+
+ % @display: same as @lisp except keep current font.
+ %
+ \def\display{\begingroup
+ \nonfillstart
+ \let\Edisplay = \nonfillfinish
+ \gobble
+ }
+
+ % @smalldisplay (when @smallbook): @display plus smaller fonts.
+ %
+ \def\smalldisplayx{\begingroup
+ \def\Esmalldisplay{\nonfillfinish\endgroup}%
+ \indexfonts \rm
+ \display
+ }
+
+ % @format: same as @display except don't narrow margins.
+ %
+ \def\format{\begingroup
+ \let\nonarrowing = t
+ \nonfillstart
+ \let\Eformat = \nonfillfinish
+ \gobble
+ }
+
+ % @smallformat (when @smallbook): @format plus smaller fonts.
+ %
+ \def\smallformatx{\begingroup
+ \def\Esmallformat{\nonfillfinish\endgroup}%
+ \indexfonts \rm
+ \format
+ }
+
+ % @flushleft (same as @format).
+ %
+ \def\flushleft{\begingroup \def\Eflushleft{\nonfillfinish\endgroup}\format}
+
+ % @flushright.
+ %
+ \def\flushright{\begingroup
+ \let\nonarrowing = t
+ \nonfillstart
+ \let\Eflushright = \nonfillfinish
+ \advance\leftskip by 0pt plus 1fill
+ \gobble
+ }
+
+ % @quotation does normal linebreaking (hence we can't use \nonfillstart)
+ % and narrows the margins.
+ %
+ \def\quotation{%
+ \begingroup\inENV %This group ends at the end of the @quotation body
+ {\parskip=0pt \aboveenvbreak}% because \aboveenvbreak inserts \parskip
+ \singlespace
+ \parindent=0pt
+ % We have retained a nonzero parskip for the environment, since we're
+ % doing normal filling. So to avoid extra space below the environment...
+ \def\Equotation{\parskip = 0pt \nonfillfinish}%
+ %
+ % @cartouche defines \nonarrowing to inhibit narrowing at next level down.
+ \ifx\nonarrowing\relax
+ \advance\leftskip by \lispnarrowing
+ \advance\rightskip by \lispnarrowing
+ \exdentamount = \lispnarrowing
+ \let\nonarrowing = \relax
+ \fi
+ }
+
+
+ \message{defuns,}
+ % Define formatter for defuns
+ % First, allow user to change definition object font (\df) internally
+ \def\setdeffont #1 {\csname DEF#1\endcsname}
+
+ \newskip\defbodyindent \defbodyindent=.4in
+ \newskip\defargsindent \defargsindent=50pt
+ \newskip\deftypemargin \deftypemargin=12pt
+ \newskip\deflastargmargin \deflastargmargin=18pt
+
+ \newcount\parencount
+ % define \functionparens, which makes ( and ) and & do special things.
+ % \functionparens affects the group it is contained in.
+ \def\activeparens{%
+ \catcode`\(=\active \catcode`\)=\active \catcode`\&=\active
+ \catcode`\[=\active \catcode`\]=\active}
+
+ % Make control sequences which act like normal parenthesis chars.
+ \let\lparen = ( \let\rparen = )
+
+ {\activeparens % Now, smart parens don't turn on until &foo (see \amprm)
+
+ % Be sure that we always have a definition for `(', etc. For example,
+ % if the fn name has parens in it, \boldbrax will not be in effect yet,
+ % so TeX would otherwise complain about undefined control sequence.
+ \global\let(=\lparen \global\let)=\rparen
+ \global\let[=\lbrack \global\let]=\rbrack
+
+ \gdef\functionparens{\boldbrax\let&=\amprm\parencount=0 }
+ \gdef\boldbrax{\let(=\opnr\let)=\clnr\let[=\lbrb\let]=\rbrb}
+ % This is used to turn on special parens
+ % but make & act ordinary (given that it's active).
+ \gdef\boldbraxnoamp{\let(=\opnr\let)=\clnr\let[=\lbrb\let]=\rbrb\let&=\ampnr}
+
+ % Definitions of (, ) and & used in args for functions.
+ % This is the definition of ( outside of all parentheses.
+ \gdef\oprm#1 {{\rm\char`\(}#1 \bf \let(=\opnested
+ \global\advance\parencount by 1
+ }
+ %
+ % This is the definition of ( when already inside a level of parens.
+ \gdef\opnested{\char`\(\global\advance\parencount by 1 }
+ %
+ \gdef\clrm{% Print a paren in roman if it is taking us back to depth of 0.
+ % also in that case restore the outer-level definition of (.
+ \ifnum \parencount=1 {\rm \char `\)}\sl \let(=\oprm \else \char `\) \fi
+ \global\advance \parencount by -1 }
+ % If we encounter &foo, then turn on ()-hacking afterwards
+ \gdef\amprm#1 {{\rm\}\let(=\oprm \let)=\clrm\ }
+ %
+ \gdef\normalparens{\boldbrax\let&=\ampnr}
+ } % End of definition inside \activeparens
+ %% These parens (in \boldbrax) actually are a little bolder than the
+ %% contained text. This is especially needed for [ and ]
+ \def\opnr{{\sf\char`\(}\global\advance\parencount by 1 }
+ \def\clnr{{\sf\char`\)}\global\advance\parencount by -1 }
+ \def\ampnr{\&}
+ \def\lbrb{{\bf\char`\[}}
+ \def\rbrb{{\bf\char`\]}}
+
+ % First, defname, which formats the header line itself.
+ % #1 should be the function name.
+ % #2 should be the type of definition, such as "Function".
+
+ \def\defname #1#2{%
+ % Get the values of \leftskip and \rightskip as they were
+ % outside the @def...
+ \dimen2=\leftskip
+ \advance\dimen2 by -\defbodyindent
+ \noindent
+ \setbox0=\hbox{\hskip \deflastargmargin{\rm #2}\hskip \deftypemargin}%
+ \dimen0=\hsize \advance \dimen0 by -\wd0 % compute size for first line
+ \dimen1=\hsize \advance \dimen1 by -\defargsindent %size for continuations
+ \parshape 2 0in \dimen0 \defargsindent \dimen1
+ % Now output arg 2 ("Function" or some such)
+ % ending at \deftypemargin from the right margin,
+ % but stuck inside a box of width 0 so it does not interfere with linebreaking
+ {% Adjust \hsize to exclude the ambient margins,
+ % so that \rightline will obey them.
+ \advance \hsize by -\dimen2
+ \rlap{\rightline{{\rm #2}\hskip -1.25pc }}}%
+ % Make all lines underfull and no complaints:
+ \tolerance=10000 \hbadness=10000
+ \advance\leftskip by -\defbodyindent
+ \exdentamount=\defbodyindent
+ {\df #1}\enskip % Generate function name
+ }
+
+ % Actually process the body of a definition
+ % #1 should be the terminating control sequence, such as \Edefun.
+ % #2 should be the "another name" control sequence, such as \defunx.
+ % #3 should be the control sequence that actually processes the header,
+ % such as \defunheader.
+
+ \def\defparsebody #1#2#3{\begingroup\inENV% Environment for definitionbody
+ \medbreak %
+ % Define the end token that this defining construct specifies
+ % so that it will exit this group.
+ \def#1{\endgraf\endgroup\medbreak}%
+ \def#2{\begingroup\obeylines\activeparens\spacesplit#3}%
+ \parindent=0in
+ \advance\leftskip by \defbodyindent
+ \exdentamount=\defbodyindent
+ \begingroup %
+ \catcode 61=\active % 61 is `='
+ \obeylines\activeparens\spacesplit#3}
+
+ % #1 is the \E... control sequence to end the definition (which we define).
+ % #2 is the \...x control sequence for consecutive fns (which we define).
+ % #3 is the control sequence to call to resume processing.
+ % #4, delimited by the space, is the class name.
+ %
+ \def\defmethparsebody#1#2#3#4 {\begingroup\inENV %
+ \medbreak %
+ % Define the end token that this defining construct specifies
+ % so that it will exit this group.
+ \def#1{\endgraf\endgroup\medbreak}%
+ \def#2##1 {\begingroup\obeylines\activeparens\spacesplit{#3{##1}}}%
+ \parindent=0in
+ \advance\leftskip by \defbodyindent
+ \exdentamount=\defbodyindent
+ \begingroup\obeylines\activeparens\spacesplit{#3{#4}}}
+
+ % @deftypemethod has an extra argument that nothing else does. Sigh.
+ % #1 is the \E... control sequence to end the definition (which we define).
+ % #2 is the \...x control sequence for consecutive fns (which we define).
+ % #3 is the control sequence to call to resume processing.
+ % #4, delimited by the space, is the class name.
+ % #5 is the method's return type.
+ %
+ \def\deftypemethparsebody#1#2#3#4 #5 {\begingroup\inENV %
+ \medbreak %
+ % Define the end token that this defining construct specifies
+ % so that it will exit this group.
+ \def#1{\endgraf\endgroup\medbreak}%
+ \def#2##1 ##2 {\begingroup\obeylines\activeparens\spacesplit{#3{##1}{##2}}}%
+ \parindent=0in
+ \advance\leftskip by \defbodyindent
+ \exdentamount=\defbodyindent
+ \begingroup\obeylines\activeparens\spacesplit{#3{#4}{#5}}}
+
+ \def\defopparsebody #1#2#3#4#5 {\begingroup\inENV %
+ \medbreak %
+ % Define the end token that this defining construct specifies
+ % so that it will exit this group.
+ \def#1{\endgraf\endgroup\medbreak}%
+ \def#2##1 ##2 {\def#4{##1}%
+ \begingroup\obeylines\activeparens\spacesplit{#3{##2}}}%
+ \parindent=0in
+ \advance\leftskip by \defbodyindent
+ \exdentamount=\defbodyindent
+ \begingroup\obeylines\activeparens\spacesplit{#3{#5}}}
+
+ % These parsing functions are similar to the preceding ones
+ % except that they do not make parens into active characters.
+ % These are used for "variables" since they have no arguments.
+
+ \def\defvarparsebody #1#2#3{\begingroup\inENV% Environment for definitionbody
+ \medbreak %
+ % Define the end token that this defining construct specifies
+ % so that it will exit this group.
+ \def#1{\endgraf\endgroup\medbreak}%
+ \def#2{\begingroup\obeylines\spacesplit#3}%
+ \parindent=0in
+ \advance\leftskip by \defbodyindent
+ \exdentamount=\defbodyindent
+ \begingroup %
+ \catcode 61=\active %
+ \obeylines\spacesplit#3}
+
+ % This is used for \def{tp,vr}parsebody. It could probably be used for
+ % some of the others, too, with some judicious conditionals.
+ %
+ \def\parsebodycommon#1#2#3{%
+ \begingroup\inENV %
+ \medbreak %
+ % Define the end token that this defining construct specifies
+ % so that it will exit this group.
+ \def#1{\endgraf\endgroup\medbreak}%
+ \def#2##1 {\begingroup\obeylines\spacesplit{#3{##1}}}%
+ \parindent=0in
+ \advance\leftskip by \defbodyindent
+ \exdentamount=\defbodyindent
+ \begingroup\obeylines
+ }
+
+ \def\defvrparsebody#1#2#3#4 {%
+ \parsebodycommon{#1}{#2}{#3}%
+ \spacesplit{#3{#4}}%
+ }
+
+ % This loses on `@deftp {Data Type} {struct termios}' -- it thinks the
+ % type is just `struct', because we lose the braces in `{struct
+ % termios}' when \spacesplit reads its undelimited argument. Sigh.
+ % \let\deftpparsebody=\defvrparsebody
+ %
+ % So, to get around this, we put \empty in with the type name. That
+ % way, TeX won't find exactly `{...}' as an undelimited argument, and
+ % won't strip off the braces.
+ %
+ \def\deftpparsebody #1#2#3#4 {%
+ \parsebodycommon{#1}{#2}{#3}%
+ \spacesplit{\parsetpheaderline{#3{#4}}}\empty
+ }
+
+ % Fine, but then we have to eventually remove the \empty *and* the
+ % braces (if any). That's what this does.
+ %
+ \def\removeemptybraces\empty#1\relax{#1}
+
+ % After \spacesplit has done its work, this is called -- #1 is the final
+ % thing to call, #2 the type name (which starts with \empty), and #3
+ % (which might be empty) the arguments.
+ %
+ \def\parsetpheaderline#1#2#3{%
+ #1{\removeemptybraces#2\relax}{#3}%
+ }%
+
+ \def\defopvarparsebody #1#2#3#4#5 {\begingroup\inENV %
+ \medbreak %
+ % Define the end token that this defining construct specifies
+ % so that it will exit this group.
+ \def#1{\endgraf\endgroup\medbreak}%
+ \def#2##1 ##2 {\def#4{##1}%
+ \begingroup\obeylines\spacesplit{#3{##2}}}%
+ \parindent=0in
+ \advance\leftskip by \defbodyindent
+ \exdentamount=\defbodyindent
+ \begingroup\obeylines\spacesplit{#3{#5}}}
+
+ % Split up #2 at the first space token.
+ % call #1 with two arguments:
+ % the first is all of #2 before the space token,
+ % the second is all of #2 after that space token.
+ % If #2 contains no space token, all of it is passed as the first arg
+ % and the second is passed as empty.
+
+ {\obeylines
+ \gdef\spacesplit#1#2^^M{\endgroup\spacesplitfoo{#1}#2 \relax\spacesplitfoo}%
+ \long\gdef\spacesplitfoo#1#2 #3#4\spacesplitfoo{%
+ \ifx\relax #3%
+ #1{#2}{}\else #1{#2}{#3#4}\fi}}
+
+ % So much for the things common to all kinds of definitions.
+
+ % Define @defun.
+
+ % First, define the processing that is wanted for arguments of \defun
+ % Use this to expand the args and terminate the paragraph they make up
+
+ \def\defunargs #1{\functionparens \sl
+ % Expand, preventing hyphenation at `-' chars.
+ % Note that groups don't affect changes in \hyphenchar.
+ \hyphenchar\tensl=0
+ #1%
+ \hyphenchar\tensl=45
+ \ifnum\parencount=0 \else \errmessage{Unbalanced parentheses in @def}\fi%
+ \interlinepenalty=10000
+ \advance\rightskip by 0pt plus 1fil
+ \endgraf\nobreak\vskip -\parskip\nobreak
+ }
+
+ \def\deftypefunargs #1{%
+ % Expand, preventing hyphenation at `-' chars.
+ % Note that groups don't affect changes in \hyphenchar.
+ % Use \boldbraxnoamp, not \functionparens, so that & is not special.
+ \boldbraxnoamp
+ \tclose{#1}% avoid \code because of side effects on active chars
+ \interlinepenalty=10000
+ \advance\rightskip by 0pt plus 1fil
+ \endgraf\nobreak\vskip -\parskip\nobreak
+ }
+
+ % Do complete processing of one @defun or @defunx line already parsed.
+
+ % @deffn Command forward-char nchars
+
+ \def\deffn{\defmethparsebody\Edeffn\deffnx\deffnheader}
+
+ \def\deffnheader #1#2#3{\doind {fn}{\code{#2}}%
+ \begingroup\defname {#2}{#1}\defunargs{#3}\endgroup %
+ \catcode 61=\other % Turn off change made in \defparsebody
+ }
+
+ % @defun == @deffn Function
+
+ \def\defun{\defparsebody\Edefun\defunx\defunheader}
+
+ \def\defunheader #1#2{\doind {fn}{\code{#1}}% Make entry in function index
+ \begingroup\defname {#1}{Function}%
+ \defunargs {#2}\endgroup %
+ \catcode 61=\other % Turn off change made in \defparsebody
+ }
+
+ % @deftypefun int foobar (int @var{foo}, float @var{bar})
+
+ \def\deftypefun{\defparsebody\Edeftypefun\deftypefunx\deftypefunheader}
+
+ % #1 is the data type. #2 is the name and args.
+ \def\deftypefunheader #1#2{\deftypefunheaderx{#1}#2 \relax}
+ % #1 is the data type, #2 the name, #3 the args.
+ \def\deftypefunheaderx #1#2 #3\relax{%
+ \doind {fn}{\code{#2}}% Make entry in function index
+ \begingroup\defname {\defheaderxcond#1\relax$$$#2}{Function}%
+ \deftypefunargs {#3}\endgroup %
+ \catcode 61=\other % Turn off change made in \defparsebody
+ }
+
+ % @deftypefn {Library Function} int foobar (int @var{foo}, float @var{bar})
+
+ \def\deftypefn{\defmethparsebody\Edeftypefn\deftypefnx\deftypefnheader}
+
+ % \defheaderxcond#1\relax$$$
+ % puts #1 in @code, followed by a space, but does nothing if #1 is null.
+ \def\defheaderxcond#1#2$$${\ifx#1\relax\else\code{#1#2} \fi}
+
+ % #1 is the classification. #2 is the data type. #3 is the name and args.
+ \def\deftypefnheader #1#2#3{\deftypefnheaderx{#1}{#2}#3 \relax}
+ % #1 is the classification, #2 the data type, #3 the name, #4 the args.
+ \def\deftypefnheaderx #1#2#3 #4\relax{%
+ \doind {fn}{\code{#3}}% Make entry in function index
+ \begingroup
+ \normalparens % notably, turn off `&' magic, which prevents
+ % at least some C++ text from working
+ \defname {\defheaderxcond#2\relax$$$#3}{#1}%
+ \deftypefunargs {#4}\endgroup %
+ \catcode 61=\other % Turn off change made in \defparsebody
+ }
+
+ % @defmac == @deffn Macro
+
+ \def\defmac{\defparsebody\Edefmac\defmacx\defmacheader}
+
+ \def\defmacheader #1#2{\doind {fn}{\code{#1}}% Make entry in function index
+ \begingroup\defname {#1}{Macro}%
+ \defunargs {#2}\endgroup %
+ \catcode 61=\other % Turn off change made in \defparsebody
+ }
+
+ % @defspec == @deffn Special Form
+
+ \def\defspec{\defparsebody\Edefspec\defspecx\defspecheader}
+
+ \def\defspecheader #1#2{\doind {fn}{\code{#1}}% Make entry in function index
+ \begingroup\defname {#1}{Special Form}%
+ \defunargs {#2}\endgroup %
+ \catcode 61=\other % Turn off change made in \defparsebody
+ }
+
+ % This definition is run if you use @defunx
+ % anywhere other than immediately after a @defun or @defunx.
+
+ \def\deffnx #1 {\errmessage{@deffnx in invalid context}}
+ \def\defunx #1 {\errmessage{@defunx in invalid context}}
+ \def\defmacx #1 {\errmessage{@defmacx in invalid context}}
+ \def\defspecx #1 {\errmessage{@defspecx in invalid context}}
+ \def\deftypefnx #1 {\errmessage{@deftypefnx in invalid context}}
+ \def\deftypemethodx #1 {\errmessage{@deftypemethodx in invalid context}}
+ \def\deftypefunx #1 {\errmessage{@deftypefunx in invalid context}}
+
+ % @defmethod, and so on
+
+ % @defop CATEGORY CLASS OPERATION ARG...
+
+ \def\defop #1 {\def\defoptype{#1}%
+ \defopparsebody\Edefop\defopx\defopheader\defoptype}
+
+ \def\defopheader #1#2#3{%
+ \dosubind {fn}{\code{#2}}{\putwordon\ #1}% Make entry in function index
+ \begingroup\defname {#2}{\defoptype{} on #1}%
+ \defunargs {#3}\endgroup %
+ }
+
+ % @deftypemethod CLASS RETURN-TYPE METHOD ARG...
+ %
+ \def\deftypemethod{%
+ \deftypemethparsebody\Edeftypemethod\deftypemethodx\deftypemethodheader}
+ %
+ % #1 is the class name, #2 the data type, #3 the method name, #4 the args.
+ \def\deftypemethodheader#1#2#3#4{%
+ \dosubind{fn}{\code{#3}}{\putwordon\ \code{#1}}% entry in function index
+ \begingroup
+ \defname{\defheaderxcond#2\relax$$$#3}{\putwordMethodon\ \code{#1}}%
+ \deftypefunargs{#4}%
+ \endgroup
+ }
+
+ % @defmethod == @defop Method
+ %
+ \def\defmethod{\defmethparsebody\Edefmethod\defmethodx\defmethodheader}
+ %
+ % #1 is the class name, #2 the method name, #3 the args.
+ \def\defmethodheader#1#2#3{%
+ \dosubind{fn}{\code{#2}}{\putwordon\ \code{#1}}% entry in function index
+ \begingroup
+ \defname{#2}{\putwordMethodon\ \code{#1}}%
+ \defunargs{#3}%
+ \endgroup
+ }
+
+ % @defcv {Class Option} foo-class foo-flag
+
+ \def\defcv #1 {\def\defcvtype{#1}%
+ \defopvarparsebody\Edefcv\defcvx\defcvarheader\defcvtype}
+
+ \def\defcvarheader #1#2#3{%
+ \dosubind {vr}{\code{#2}}{of #1}% Make entry in var index
+ \begingroup\defname {#2}{\defcvtype{} of #1}%
+ \defvarargs {#3}\endgroup %
+ }
+
+ % @defivar == @defcv {Instance Variable}
+
+ \def\defivar{\defvrparsebody\Edefivar\defivarx\defivarheader}
+
+ \def\defivarheader #1#2#3{%
+ \dosubind {vr}{\code{#2}}{of #1}% Make entry in var index
+ \begingroup\defname {#2}{Instance Variable of #1}%
+ \defvarargs {#3}\endgroup %
+ }
+
+ % These definitions are run if you use @defmethodx, etc.,
+ % anywhere other than immediately after a @defmethod, etc.
+
+ \def\defopx #1 {\errmessage{@defopx in invalid context}}
+ \def\defmethodx #1 {\errmessage{@defmethodx in invalid context}}
+ \def\defcvx #1 {\errmessage{@defcvx in invalid context}}
+ \def\defivarx #1 {\errmessage{@defivarx in invalid context}}
+
+ % Now @defvar
+
+ % First, define the processing that is wanted for arguments of @defvar.
+ % This is actually simple: just print them in roman.
+ % This must expand the args and terminate the paragraph they make up
+ \def\defvarargs #1{\normalparens #1%
+ \interlinepenalty=10000
+ \endgraf\nobreak\vskip -\parskip\nobreak}
+
+ % @defvr Counter foo-count
+
+ \def\defvr{\defvrparsebody\Edefvr\defvrx\defvrheader}
+
+ \def\defvrheader #1#2#3{\doind {vr}{\code{#2}}%
+ \begingroup\defname {#2}{#1}\defvarargs{#3}\endgroup}
+
+ % @defvar == @defvr Variable
+
+ \def\defvar{\defvarparsebody\Edefvar\defvarx\defvarheader}
+
+ \def\defvarheader #1#2{\doind {vr}{\code{#1}}% Make entry in var index
+ \begingroup\defname {#1}{Variable}%
+ \defvarargs {#2}\endgroup %
+ }
+
+ % @defopt == @defvr {User Option}
+
+ \def\defopt{\defvarparsebody\Edefopt\defoptx\defoptheader}
+
+ \def\defoptheader #1#2{\doind {vr}{\code{#1}}% Make entry in var index
+ \begingroup\defname {#1}{User Option}%
+ \defvarargs {#2}\endgroup %
+ }
+
+ % @deftypevar int foobar
+
+ \def\deftypevar{\defvarparsebody\Edeftypevar\deftypevarx\deftypevarheader}
+
+ % #1 is the data type. #2 is the name, perhaps followed by text that
+ % is actually part of the data type, which should not be put into the index.
+ \def\deftypevarheader #1#2{%
+ \dovarind#2 \relax% Make entry in variables index
+ \begingroup\defname {\defheaderxcond#1\relax$$$#2}{Variable}%
+ \interlinepenalty=10000
+ \endgraf\nobreak\vskip -\parskip\nobreak
+ \endgroup}
+ \def\dovarind#1 #2\relax{\doind{vr}{\code{#1}}}
+
+ % @deftypevr {Global Flag} int enable
+
+ \def\deftypevr{\defvrparsebody\Edeftypevr\deftypevrx\deftypevrheader}
+
+ \def\deftypevrheader #1#2#3{\dovarind#3 \relax%
+ \begingroup\defname {\defheaderxcond#2\relax$$$#3}{#1}
+ \interlinepenalty=10000
+ \endgraf\nobreak\vskip -\parskip\nobreak
+ \endgroup}
+
+ % This definition is run if you use @defvarx
+ % anywhere other than immediately after a @defvar or @defvarx.
+
+ \def\defvrx #1 {\errmessage{@defvrx in invalid context}}
+ \def\defvarx #1 {\errmessage{@defvarx in invalid context}}
+ \def\defoptx #1 {\errmessage{@defoptx in invalid context}}
+ \def\deftypevarx #1 {\errmessage{@deftypevarx in invalid context}}
+ \def\deftypevrx #1 {\errmessage{@deftypevrx in invalid context}}
+
+ % Now define @deftp
+ % Args are printed in bold, a slight difference from @defvar.
+
+ \def\deftpargs #1{\bf \defvarargs{#1}}
+
+ % @deftp Class window height width ...
+
+ \def\deftp{\deftpparsebody\Edeftp\deftpx\deftpheader}
+
+ \def\deftpheader #1#2#3{\doind {tp}{\code{#2}}%
+ \begingroup\defname {#2}{#1}\deftpargs{#3}\endgroup}
+
+ % This definition is run if you use @deftpx, etc
+ % anywhere other than immediately after a @deftp, etc.
+
+ \def\deftpx #1 {\errmessage{@deftpx in invalid context}}
+
+
+ \message{macros,}
+ % @macro.
+
+ % To do this right we need a feature of e-TeX, \scantokens,
+ % which we arrange to emulate with a temporary file in ordinary TeX.
+ \ifx\eTeXversion\undefined
+ \newwrite\macscribble
+ \def\scanmacro#1{%
+ \begingroup \newlinechar`\^^M
+ \immediate\openout\macscribble=\jobname.tmp
+ \immediate\write\macscribble{#1}%
+ \immediate\closeout\macscribble
+ \let\xeatspaces\eatspaces
+ \input \jobname.tmp
+ \endgroup
+ }
+ \else
+ \def\scanmacro#1{%
+ \begingroup \newlinechar`\^^M
+ \let\xeatspaces\eatspaces\scantokens{#1}\endgroup}
+ \fi
+
+ \newcount\paramno % Count of parameters
+ \newtoks\macname % Macro name
+ \newif\ifrecursive % Is it recursive?
+
+ % Utility routines.
+ % Thisdoes \let #1 = #2, except with \csnames.
+ \def\cslet#1#2{%
+ \expandafter\expandafter
+ \expandafter\let
+ \expandafter\expandafter
+ \csname#1\endcsname
+ \csname#2\endcsname}
+
+ % Trim leading and trailing spaces off a string.
+ % Concepts from aro-bend problem 15 (see CTAN).
+ {\catcode`\@=11
+ \gdef\eatspaces #1{\expandafter\trim@\expandafter{#1 }}
+ \gdef\trim@ #1{\trim@@ @#1 @ #1 @ @@}
+ \gdef\trim@@ #1@ #2@ #3@@{\trim@@@\empty #2 @}
+ \def\unbrace#1{#1}
+ \unbrace{\gdef\trim@@@ #1 } #2@{#1}
+ }
+
+ % Trim a single trailing ^^M off a string.
+ {\catcode`\^^M=12\catcode`\Q=3%
+ \gdef\eatcr #1{\eatcra #1Q^^MQ}%
+ \gdef\eatcra#1^^MQ{\eatcrb#1Q}%
+ \gdef\eatcrb#1Q#2Q{#1}%
+ }
+
+ % Macro bodies are absorbed as an argument in a context where
+ % all characters are catcode 10, 11 or 12, except \ which is active
+ % (as in normal texinfo). It is necessary to change the definition of \.
+
+ % It's necessary to have hard CRs when the macro is executed. This is
+ % done by making ^^M (\endlinechar) catcode 12 when reading the macro
+ % body, and then making it the \newlinechar in \scanmacro.
+
+ \def\macrobodyctxt{%
+ \catcode`\~=12
+ \catcode`\^=12
+ \catcode`\_=12
+ \catcode`\|=12
+ \catcode`\<=12
+ \catcode`\>=12
+ \catcode`\+=12
+ \catcode`\{=12
+ \catcode`\}=12
+ \catcode`\@=12
+ \catcode`\^^M=12
+ \usembodybackslash}
+
+ \def\macroargctxt{%
+ \catcode`\~=12
+ \catcode`\^=12
+ \catcode`\_=12
+ \catcode`\|=12
+ \catcode`\<=12
+ \catcode`\>=12
+ \catcode`\+=12
+ \catcode`\@=12
+ \catcode`\\=12}
+
+ % \mbodybackslash is the definition of \ in @macro bodies.
+ % It maps \foo\ => \csname macarg.foo\endcsname => #N
+ % where N is the macro parameter number.
+ % We define \csname macarg.\endcsname to be \realbackslash, so
+ % \\ in macro replacement text gets you a backslash.
+
+ {\catcode`@=0 @catcode`@\=@active
+ @gdef at usembodybackslash{@let\=@mbodybackslash}
+ @gdef at mbodybackslash#1\{@csname macarg.#1 at endcsname}
+ }
+ \expandafter\def\csname macarg.\endcsname{\realbackslash}
+
+ \def\macro{\recursivefalse\parsearg\macroxxx}
+ \def\rmacro{\recursivetrue\parsearg\macroxxx}
+
+ \def\macroxxx#1{%
+ \getargs{#1}% now \macname is the macname and \argl the arglist
+ \ifx\argl\empty % no arguments
+ \paramno=0%
+ \else
+ \expandafter\parsemargdef \argl;%
+ \fi
+ \expandafter\ifx \csname macsave.\the\macname\endcsname \relax
+ \cslet{macsave.\the\macname}{\the\macname}%
+ \else
+ \message{Warning: redefining \the\macname}%
+ \fi
+ \begingroup \macrobodyctxt
+ \ifrecursive \expandafter\parsermacbody
+ \else \expandafter\parsemacbody
+ \fi}
+
+ \def\unmacro{\parsearg\unmacroxxx}
+ \def\unmacroxxx#1{%
+ \expandafter\ifx \csname macsave.\the\macname\endcsname \relax
+ \errmessage{Macro \the\macname\ not defined.}%
+ \else
+ \cslet{#1}{macsave.#1}%
+ \expandafter\let \csname macsave.\the\macname\endcsname \undefined
+ \fi
+ }
+
+ % This makes use of the obscure feature that if the last token of a
+ % <parameter list> is #, then the preceding argument is delimited by
+ % an opening brace, and that opening brace is not consumed.
+ \def\getargs#1{\getargsxxx#1{}}
+ \def\getargsxxx#1#{\getmacname #1 \relax\getmacargs}
+ \def\getmacname #1 #2\relax{\macname={#1}}
+ \def\getmacargs#1{\def\argl{#1}}
+
+ % Parse the optional {params} list. Set up \paramno and \paramlist
+ % so \defmacro knows what to do. Define \macarg.blah for each blah
+ % in the params list, to be ##N where N is the position in that list.
+ % That gets used by \mbodybackslash (above).
+
+ % We need to get `macro parameter char #' into several definitions.
+ % The technique used is stolen from LaTeX: let \hash be something
+ % unexpandable, insert that wherever you need a #, and then redefine
+ % it to # just before using the token list produced.
+ %
+ % The same technique is used to protect \eatspaces till just before
+ % the macro is used.
+
+ \def\parsemargdef#1;{\paramno=0\def\paramlist{}%
+ \let\hash\relax\let\xeatspaces\relax\parsemargdefxxx#1,;,}
+ \def\parsemargdefxxx#1,{%
+ \if#1;\let\next=\relax
+ \else \let\next=\parsemargdefxxx
+ \advance\paramno by 1%
+ \expandafter\edef\csname macarg.\eatspaces{#1}\endcsname
+ {\xeatspaces{\hash\the\paramno}}%
+ \edef\paramlist{\paramlist\hash\the\paramno,}%
+ \fi\next}
+
+ % These two commands read recursive and nonrecursive macro bodies.
+ % (They're different since rec and nonrec macros end differently.)
+
+ \long\def\parsemacbody#1 at end macro%
+ {\xdef\temp{\eatcr{#1}}\endgroup\defmacro}%
+ \long\def\parsermacbody#1 at end rmacro%
+ {\xdef\temp{\eatcr{#1}}\endgroup\defmacro}%
+
+ % This defines the macro itself. There are six cases: recursive and
+ % nonrecursive macros of zero, one, and many arguments.
+ % Much magic with \expandafter here.
+ % \xdef is used so that macro definitions will survive the file
+ % they're defined in; @include reads the file inside a group.
+ \def\defmacro{%
+ \let\hash=##% convert placeholders to macro parameter chars
+ \ifrecursive
+ \ifcase\paramno
+ % 0
+ \expandafter\xdef\csname\the\macname\endcsname{%
+ \noexpand\scanmacro{\temp}}%
+ \or % 1
+ \expandafter\xdef\csname\the\macname\endcsname{%
+ \bgroup\noexpand\macroargctxt
+ \noexpand\braceorline\csname\the\macname xxx\endcsname}%
+ \expandafter\xdef\csname\the\macname xxx\endcsname##1{%
+ \egroup\noexpand\scanmacro{\temp}}%
+ \else % many
+ \expandafter\xdef\csname\the\macname\endcsname{%
+ \bgroup\noexpand\macroargctxt
+ \noexpand\csname\the\macname xx\endcsname}
+ \expandafter\xdef\csname\the\macname xx\endcsname##1{%
+ \csname\the\macname xxx\endcsname ##1,}%
+ \expandafter\expandafter
+ \expandafter\xdef
+ \expandafter\expandafter
+ \csname\the\macname xxx\endcsname
+ \paramlist{\egroup\noexpand\scanmacro{\temp}}%
+ \fi
+ \else
+ \ifcase\paramno
+ % 0
+ \expandafter\xdef\csname\the\macname\endcsname{%
+ \noexpand\norecurse{\the\macname}%
+ \noexpand\scanmacro{\temp}\egroup}%
+ \or % 1
+ \expandafter\xdef\csname\the\macname\endcsname{%
+ \bgroup\noexpand\macroargctxt
+ \noexpand\braceorline\csname\the\macname xxx\endcsname}%
+ \expandafter\xdef\csname\the\macname xxx\endcsname##1{%
+ \egroup
+ \noexpand\norecurse{\the\macname}%
+ \noexpand\scanmacro{\temp}\egroup}%
+ \else % many
+ \expandafter\xdef\csname\the\macname\endcsname{%
+ \bgroup\noexpand\macroargctxt
+ \noexpand\csname\the\macname xx\endcsname}
+ \expandafter\xdef\csname\the\macname xx\endcsname##1{%
+ \csname\the\macname xxx\endcsname ##1,}%
+ \expandafter\expandafter
+ \expandafter\xdef
+ \expandafter\expandafter
+ \csname\the\macname xxx\endcsname
+ \paramlist{%
+ \egroup
+ \noexpand\norecurse{\the\macname}%
+ \noexpand\scanmacro{\temp}\egroup}%
+ \fi
+ \fi}
+
+ \def\norecurse#1{\bgroup\cslet{#1}{macsave.#1}}
+
+ % \braceorline decides whether the next nonwhitespace character is a
+ % {. If so it reads up to the closing }, if not, it reads the whole
+ % line. Whatever was read is then fed to the next control sequence
+ % as an argument (by \parsebrace or \parsearg)
+ \def\braceorline#1{\let\next=#1\futurelet\nchar\braceorlinexxx}
+ \def\braceorlinexxx{%
+ \ifx\nchar\bgroup\else
+ \expandafter\parsearg
+ \fi \next}
+
+
+ \message{cross references,}
+ \newwrite\auxfile
+
+ \newif\ifhavexrefs % True if xref values are known.
+ \newif\ifwarnedxrefs % True if we warned once that they aren't known.
+
+ % @inforef is relatively simple.
+ \def\inforef #1{\inforefzzz #1,,,,**}
+ \def\inforefzzz #1,#2,#3,#4**{\putwordSee{} \putwordInfo{} \putwordfile{} \file{\ignorespaces #3{}},
+ node \samp{\ignorespaces#1{}}}
+
+ % @node's job is to define \lastnode.
+ \def\node{\ENVcheck\parsearg\nodezzz}
+ \def\nodezzz#1{\nodexxx [#1,]}
+ \def\nodexxx[#1,#2]{\gdef\lastnode{#1}}
+ \let\nwnode=\node
+ \let\lastnode=\relax
+
+ % The sectioning commands (@chapter, etc.) call these.
+ \def\donoderef{%
+ \ifx\lastnode\relax\else
+ \expandafter\expandafter\expandafter\setref{\lastnode}%
+ {Ysectionnumberandtype}%
+ \global\let\lastnode=\relax
+ \fi
+ }
+ \def\unnumbnoderef{%
+ \ifx\lastnode\relax\else
+ \expandafter\expandafter\expandafter\setref{\lastnode}{Ynothing}%
+ \global\let\lastnode=\relax
+ \fi
+ }
+ \def\appendixnoderef{%
+ \ifx\lastnode\relax\else
+ \expandafter\expandafter\expandafter\setref{\lastnode}%
+ {Yappendixletterandtype}%
+ \global\let\lastnode=\relax
+ \fi
+ }
+
+
+ % @anchor{NAME} -- define xref target at arbitrary point.
+ %
+ \def\anchor#1{\setref{#1}{Ynothing}}
+
+
+ % \setref{NAME}{SNT} defines a cross-reference point NAME, namely
+ % NAME-title, NAME-pg, and NAME-SNT. Called from \foonoderef. We have
+ % to set \indexdummies so commands such as @code in a section title
+ % aren't expanded. It would be nicer not to expand the titles in the
+ % first place, but there's so many layers that that is hard to do.
+ %
+ \def\setref#1#2{{%
+ \indexdummies
+ \dosetq{#1-title}{Ytitle}%
+ \dosetq{#1-pg}{Ypagenumber}%
+ \dosetq{#1-snt}{#2}
+ }}
+
+ % @xref, @pxref, and @ref generate cross-references. For \xrefX, #1 is
+ % the node name, #2 the name of the Info cross-reference, #3 the printed
+ % node name, #4 the name of the Info file, #5 the name of the printed
+ % manual. All but the node name can be omitted.
+ %
+ \def\pxref#1{\putwordsee{} \xrefX[#1,,,,,,,]}
+ \def\xref#1{\putwordSee{} \xrefX[#1,,,,,,,]}
+ \def\ref#1{\xrefX[#1,,,,,,,]}
+ \def\xrefX[#1,#2,#3,#4,#5,#6]{\begingroup
+ \def\printedmanual{\ignorespaces #5}%
+ \def\printednodename{\ignorespaces #3}%
+ \setbox1=\hbox{\printedmanual}%
+ \setbox0=\hbox{\printednodename}%
+ \ifdim \wd0 = 0pt
+ % No printed node name was explicitly given.
+ \expandafter\ifx\csname SETxref-automatic-section-title\endcsname\relax
+ % Use the node name inside the square brackets.
+ \def\printednodename{\ignorespaces #1}%
+ \else
+ % Use the actual chapter/section title appear inside
+ % the square brackets. Use the real section title if we have it.
+ \ifdim \wd1 > 0pt
+ % It is in another manual, so we don't have it.
+ \def\printednodename{\ignorespaces #1}%
+ \else
+ \ifhavexrefs
+ % We know the real title if we have the xref values.
+ \def\printednodename{\refx{#1-title}{}}%
+ \else
+ % Otherwise just copy the Info node name.
+ \def\printednodename{\ignorespaces #1}%
+ \fi%
+ \fi
+ \fi
+ \fi
+ %
+ % If we use \unhbox0 and \unhbox1 to print the node names, TeX does not
+ % insert empty discretionaries after hyphens, which means that it will
+ % not find a line break at a hyphen in a node names. Since some manuals
+ % are best written with fairly long node names, containing hyphens, this
+ % is a loss. Therefore, we give the text of the node name again, so it
+ % is as if TeX is seeing it for the first time.
+ \ifdim \wd1 > 0pt
+ \putwordsection{} ``\printednodename'' in \cite{\printedmanual}%
+ \else
+ % _ (for example) has to be the character _ for the purposes of the
+ % control sequence corresponding to the node, but it has to expand
+ % into the usual \leavevmode...\vrule stuff for purposes of
+ % printing. So we \turnoffactive for the \refx-snt, back on for the
+ % printing, back off for the \refx-pg.
+ {\normalturnoffactive
+ % Only output a following space if the -snt ref is nonempty; for
+ % @unnumbered and @anchor, it won't be.
+ \setbox2 = \hbox{\ignorespaces \refx{#1-snt}{}}%
+ \ifdim \wd2 > 0pt \refx{#1-snt}\space\fi
+ }%
+ % [mynode],
+ [\printednodename],\space
+ % page 3
+ \turnoffactive \putwordpage\tie\refx{#1-pg}{}%
+ \fi
+ \endgroup}
+
+ % \dosetq is the interface for calls from other macros
+
+ % Use \normalturnoffactive so that punctuation chars such as underscore
+ % and backslash work in node names. (\turnoffactive doesn't do \.)
+ \def\dosetq#1#2{%
+ {\let\folio=0
+ \normalturnoffactive
+ \edef\next{\write\auxfile{\internalsetq{#1}{#2}}}%
+ \iflinks
+ \next
+ \fi
+ }%
+ }
+
+ % \internalsetq {foo}{page} expands into
+ % CHARACTERS 'xrdef {foo}{...expansion of \Ypage...}
+ % When the aux file is read, ' is the escape character
+
+ \def\internalsetq #1#2{'xrdef {#1}{\csname #2\endcsname}}
+
+ % Things to be expanded by \internalsetq
+
+ \def\Ypagenumber{\folio}
+
+ \def\Ytitle{\thissection}
+
+ \def\Ynothing{}
+
+ \def\Ysectionnumberandtype{%
+ \ifnum\secno=0 \putwordChapter\xreftie\the\chapno %
+ \else \ifnum \subsecno=0 \putwordSection\xreftie\the\chapno.\the\secno %
+ \else \ifnum \subsubsecno=0 %
+ \putwordSection\xreftie\the\chapno.\the\secno.\the\subsecno %
+ \else %
+ \putwordSection\xreftie\the\chapno.\the\secno.\the\subsecno.\the\subsubsecno %
+ \fi \fi \fi }
+
+ \def\Yappendixletterandtype{%
+ \ifnum\secno=0 \putwordAppendix\xreftie'char\the\appendixno{}%
+ \else \ifnum \subsecno=0 \putwordSection\xreftie'char\the\appendixno.\the\secno %
+ \else \ifnum \subsubsecno=0 %
+ \putwordSection\xreftie'char\the\appendixno.\the\secno.\the\subsecno %
+ \else %
+ \putwordSection\xreftie'char\the\appendixno.\the\secno.\the\subsecno.\the\subsubsecno %
+ \fi \fi \fi }
+
+ \gdef\xreftie{'tie}
+
+ % Use TeX 3.0's \inputlineno to get the line number, for better error
+ % messages, but if we're using an old version of TeX, don't do anything.
+ %
+ \ifx\inputlineno\thisisundefined
+ \let\linenumber = \empty % Non-3.0.
+ \else
+ \def\linenumber{\the\inputlineno:\space}
+ \fi
+
+ % Define \refx{NAME}{SUFFIX} to reference a cross-reference string named NAME.
+ % If its value is nonempty, SUFFIX is output afterward.
+
+ \def\refx#1#2{%
+ \expandafter\ifx\csname X#1\endcsname\relax
+ % If not defined, say something at least.
+ \angleleft un\-de\-fined\angleright
+ \iflinks
+ \ifhavexrefs
+ \message{\linenumber Undefined cross reference `#1'.}%
+ \else
+ \ifwarnedxrefs\else
+ \global\warnedxrefstrue
+ \message{Cross reference values unknown; you must run TeX again.}%
+ \fi
+ \fi
+ \fi
+ \else
+ % It's defined, so just use it.
+ \csname X#1\endcsname
+ \fi
+ #2% Output the suffix in any case.
+ }
+
+ % This is the macro invoked by entries in the aux file.
+ %
+ \def\xrdef#1{\begingroup
+ % Reenable \ as an escape while reading the second argument.
+ \catcode`\\ = 0
+ \afterassignment\endgroup
+ \expandafter\gdef\csname X#1\endcsname
+ }
+
+ % Read the last existing aux file, if any. No error if none exists.
+ \def\readauxfile{\begingroup
+ \catcode`\^^@=\other
+ \catcode`\^^A=\other
+ \catcode`\^^B=\other
+ \catcode`\^^C=\other
+ \catcode`\^^D=\other
+ \catcode`\^^E=\other
+ \catcode`\^^F=\other
+ \catcode`\^^G=\other
+ \catcode`\^^H=\other
+ \catcode`\^^K=\other
+ \catcode`\^^L=\other
+ \catcode`\^^N=\other
+ \catcode`\^^P=\other
+ \catcode`\^^Q=\other
+ \catcode`\^^R=\other
+ \catcode`\^^S=\other
+ \catcode`\^^T=\other
+ \catcode`\^^U=\other
+ \catcode`\^^V=\other
+ \catcode`\^^W=\other
+ \catcode`\^^X=\other
+ \catcode`\^^Z=\other
+ \catcode`\^^[=\other
+ \catcode`\^^\=\other
+ \catcode`\^^]=\other
+ \catcode`\^^^=\other
+ \catcode`\^^_=\other
+ \catcode`\@=\other
+ \catcode`\^=\other
+ % It was suggested to define this as 7, which would allow ^^e4 etc.
+ % in xref tags, i.e., node names. But since ^^e4 notation isn't
+ % supported in the main text, it doesn't seem desirable. Furthermore,
+ % that is not enough: for node names that actually contain a ^
+ % character, we would end up writing a line like this: 'xrdef {'hat
+ % b-title}{'hat b} and \xrdef does a \csname...\endcsname on the first
+ % argument, and \hat is not an expandable control sequence. It could
+ % all be worked out, but why? Either we support ^^ or we don't.
+ %
+ % The other change necessary for this was to define \auxhat:
+ % \def\auxhat{\def^{'hat }}% extra space so ok if followed by letter
+ % and then to call \auxhat in \setq.
+ %
+ \catcode`\~=\other
+ \catcode`\[=\other
+ \catcode`\]=\other
+ \catcode`\"=\other
+ \catcode`\_=\other
+ \catcode`\|=\other
+ \catcode`\<=\other
+ \catcode`\>=\other
+ \catcode`\$=\other
+ \catcode`\#=\other
+ \catcode`\&=\other
+ \catcode`+=\other % avoid \+ for paranoia even though we've turned it off
+ % Make the characters 128-255 be printing characters
+ {%
+ \count 1=128
+ \def\loop{%
+ \catcode\count 1=\other
+ \advance\count 1 by 1
+ \ifnum \count 1<256 \loop \fi
+ }%
+ }%
+ % The aux file uses ' as the escape (for now).
+ % Turn off \ as an escape so we do not lose on
+ % entries which were dumped with control sequences in their names.
+ % For example, 'xrdef {$\leq $-fun}{page ...} made by @defun ^^
+ % Reference to such entries still does not work the way one would wish,
+ % but at least they do not bomb out when the aux file is read in.
+ \catcode`\{=1
+ \catcode`\}=2
+ \catcode`\%=\other
+ \catcode`\'=0
+ \catcode`\\=\other
+ %
+ \openin 1 \jobname.aux
+ \ifeof 1 \else
+ \closein 1
+ \input \jobname.aux
+ \global\havexrefstrue
+ \global\warnedobstrue
+ \fi
+ % Open the new aux file. TeX will close it automatically at exit.
+ \openout\auxfile=\jobname.aux
+ \endgroup}
+
+
+ % Footnotes.
+
+ \newcount \footnoteno
+
+ % The trailing space in the following definition for supereject is
+ % vital for proper filling; pages come out unaligned when you do a
+ % pagealignmacro call if that space before the closing brace is
+ % removed. (Generally, numeric constants should always be followed by a
+ % space to prevent strange expansion errors.)
+ \def\supereject{\par\penalty -20000\footnoteno =0 }
+
+ % @footnotestyle is meaningful for info output only.
+ \let\footnotestyle=\comment
+
+ \let\ptexfootnote=\footnote
+
+ {\catcode `\@=11
+ %
+ % Auto-number footnotes. Otherwise like plain.
+ \gdef\footnote{%
+ \global\advance\footnoteno by \@ne
+ \edef\thisfootno{$^{\the\footnoteno}$}%
+ %
+ % In case the footnote comes at the end of a sentence, preserve the
+ % extra spacing after we do the footnote number.
+ \let\@sf\empty
+ \ifhmode\edef\@sf{\spacefactor\the\spacefactor}\/\fi
+ %
+ % Remove inadvertent blank space before typesetting the footnote number.
+ \unskip
+ \thisfootno\@sf
+ \footnotezzz
+ }%
+
+ % Don't bother with the trickery in plain.tex to not require the
+ % footnote text as a parameter. Our footnotes don't need to be so general.
+ %
+ % Oh yes, they do; otherwise, @ifset and anything else that uses
+ % \parseargline fail inside footnotes because the tokens are fixed when
+ % the footnote is read. --karl, 16nov96.
+ %
+ \long\gdef\footnotezzz{\insert\footins\bgroup
+ % We want to typeset this text as a normal paragraph, even if the
+ % footnote reference occurs in (for example) a display environment.
+ % So reset some parameters.
+ \interlinepenalty\interfootnotelinepenalty
+ \splittopskip\ht\strutbox % top baseline for broken footnotes
+ \splitmaxdepth\dp\strutbox
+ \floatingpenalty\@MM
+ \leftskip\z at skip
+ \rightskip\z at skip
+ \spaceskip\z at skip
+ \xspaceskip\z at skip
+ \parindent\defaultparindent
+ %
+ % Hang the footnote text off the number.
+ \hang
+ \textindent{\thisfootno}%
+ %
+ % Don't crash into the line above the footnote text. Since this
+ % expands into a box, it must come within the paragraph, lest it
+ % provide a place where TeX can split the footnote.
+ \footstrut
+ \futurelet\next\fo at t
+ }
+ \def\fo at t{\ifcat\bgroup\noexpand\next \let\next\f@@t
+ \else\let\next\f at t\fi \next}
+ \def\f@@t{\bgroup\aftergroup\@foot\let\next}
+ \def\f at t#1{#1\@foot}
+ \def\@foot{\strut\egroup}
+
+ }%end \catcode `\@=11
+
+ % Set the baselineskip to #1, and the lineskip and strut size
+ % correspondingly. There is no deep meaning behind these magic numbers
+ % used as factors; they just match (closely enough) what Knuth defined.
+ %
+ \def\lineskipfactor{.08333}
+ \def\strutheightpercent{.70833}
+ \def\strutdepthpercent {.29167}
+ %
+ \def\setleading#1{%
+ \normalbaselineskip = #1\relax
+ \normallineskip = \lineskipfactor\normalbaselineskip
+ \normalbaselines
+ \setbox\strutbox =\hbox{%
+ \vrule width0pt height\strutheightpercent\baselineskip
+ depth \strutdepthpercent \baselineskip
+ }%
+ }
+
+ % @| inserts a changebar to the left of the current line. It should
+ % surround any changed text. This approach does *not* work if the
+ % change spans more than two lines of output. To handle that, we would
+ % have adopt a much more difficult approach (putting marks into the main
+ % vertical list for the beginning and end of each change).
+ %
+ \def\|{%
+ % \vadjust can only be used in horizontal mode.
+ \leavevmode
+ %
+ % Append this vertical mode material after the current line in the output.
+ \vadjust{%
+ % We want to insert a rule with the height and depth of the current
+ % leading; that is exactly what \strutbox is supposed to record.
+ \vskip-\baselineskip
+ %
+ % \vadjust-items are inserted at the left edge of the type. So
+ % the \llap here moves out into the left-hand margin.
+ \llap{%
+ %
+ % For a thicker or thinner bar, change the `1pt'.
+ \vrule height\baselineskip width1pt
+ %
+ % This is the space between the bar and the text.
+ \hskip 12pt
+ }%
+ }%
+ }
+
+ % For a final copy, take out the rectangles
+ % that mark overfull boxes (in case you have decided
+ % that the text looks ok even though it passes the margin).
+ %
+ \def\finalout{\overfullrule=0pt}
+
+ % @image. We use the macros from epsf.tex to support this.
+ % If epsf.tex is not installed and @image is used, we complain.
+ %
+ % Check for and read epsf.tex up front. If we read it only at @image
+ % time, we might be inside a group, and then its definitions would get
+ % undone and the next image would fail.
+ \openin 1 = epsf.tex
+ \ifeof 1 \else
+ \closein 1
+ % Do not bother showing banner with post-v2.7 epsf.tex (available in
+ % doc/epsf.tex until it shows up on ctan).
+ \def\epsfannounce{\toks0 = }%
+ \input epsf.tex
+ \fi
+ %
+ \newif\ifwarnednoepsf
+ \newhelp\noepsfhelp{epsf.tex must be installed for images to
+ work. It is also included in the Texinfo distribution, or you can get
+ it from ftp://ftp.tug.org/tex/epsf.tex.}
+ %
+ % Only complain once about lack of epsf.tex.
+ \def\image#1{%
+ \ifx\epsfbox\undefined
+ \ifwarnednoepsf \else
+ \errhelp = \noepsfhelp
+ \errmessage{epsf.tex not found, images will be ignored}%
+ \global\warnednoepsftrue
+ \fi
+ \else
+ \imagexxx #1,,,\finish
+ \fi
+ }
+ %
+ % Arguments to @image:
+ % #1 is (mandatory) image filename; we tack on .eps extension.
+ % #2 is (optional) width, #3 is (optional) height.
+ % #4 is just the usual extra ignored arg for parsing this stuff.
+ \def\imagexxx#1,#2,#3,#4\finish{%
+ % \epsfbox itself resets \epsf?size at each figure.
+ \setbox0 = \hbox{\ignorespaces #2}\ifdim\wd0 > 0pt \epsfxsize=#2\relax \fi
+ \setbox0 = \hbox{\ignorespaces #3}\ifdim\wd0 > 0pt \epsfysize=#3\relax \fi
+ % If the image is by itself, center it.
+ \ifvmode
+ \nobreak\medskip
+ \nobreak
+ \centerline{\epsfbox{#1.eps}}%
+ \bigbreak
+ \else
+ \epsfbox{#1.eps}%
+ \fi
+ }
+
+
+ \message{paper sizes,}
+ % And other related parameters.
+
+ \newdimen\defaultparindent \defaultparindent = 15pt
+
+ \chapheadingskip = 15pt plus 4pt minus 2pt
+ \secheadingskip = 12pt plus 3pt minus 2pt
+ \subsecheadingskip = 9pt plus 2pt minus 2pt
+
+ % Prevent underfull vbox error messages.
+ \vbadness = 10000
+
+ % Don't be so finicky about underfull hboxes, either.
+ \hbadness = 2000
+
+ % Following George Bush, just get rid of widows and orphans.
+ \widowpenalty=10000
+ \clubpenalty=10000
+
+ % Use TeX 3.0's \emergencystretch to help line breaking, but if we're
+ % using an old version of TeX, don't do anything. We want the amount of
+ % stretch added to depend on the line length, hence the dependence on
+ % \hsize. This makes it come to about 9pt for the 8.5x11 format. We
+ % call this whenever the paper size is set.
+ %
+ \def\setemergencystretch{%
+ \ifx\emergencystretch\thisisundefined
+ % Allow us to assign to \emergencystretch anyway.
+ \def\emergencystretch{\dimen0}%
+ \else
+ \emergencystretch = \hsize
+ \divide\emergencystretch by 45
+ \fi
+ }
+
+ % Parameters in order: 1) textheight; 2) textwidth; 3) voffset;
+ % 4) hoffset; 5) binding offset; 6) topskip. Then whoever calls us can
+ % set \parskip and call \setleading for \baselineskip.
+ %
+ \def\internalpagesizes#1#2#3#4#5#6{%
+ \voffset = #3\relax
+ \topskip = #6\relax
+ \splittopskip = \topskip
+ %
+ \vsize = #1\relax
+ \advance\vsize by \topskip
+ \outervsize = \vsize
+ \advance\outervsize by 2\topandbottommargin
+ \pageheight = \vsize
+ %
+ \hsize = #2\relax
+ \outerhsize = \hsize
+ \advance\outerhsize by 0.5in
+ \pagewidth = \hsize
+ %
+ \normaloffset = #4\relax
+ \bindingoffset = #5\relax
+ %
+ \parindent = \defaultparindent
+ \setemergencystretch
+ }
+
+ % @letterpaper (the default).
+ \def\letterpaper{{\globaldefs = 1
+ \parskip = 3pt plus 2pt minus 1pt
+ \setleading{13.2pt}%
+ %
+ % If page is nothing but text, make it come out even.
+ \internalpagesizes{46\baselineskip}{6in}{\voffset}{.25in}{\bindingoffset}{36pt}%
+ }}
+
+ % Use @smallbook to reset parameters for 7x9.5 (or so) format.
+ \def\smallbook{{\globaldefs = 1
+ \parskip = 2pt plus 1pt
+ \setleading{12pt}%
+ %
+ \internalpagesizes{7.5in}{5.in}{\voffset}{.25in}{\bindingoffset}{16pt}%
+ %
+ \lispnarrowing = 0.3in
+ \tolerance = 700
+ \hfuzz = 1pt
+ \contentsrightmargin = 0pt
+ \deftypemargin = 0pt
+ \defbodyindent = .5cm
+ %
+ \let\smalldisplay = \smalldisplayx
+ \let\smallexample = \smalllispx
+ \let\smallformat = \smallformatx
+ \let\smalllisp = \smalllispx
+ }}
+
+ % Use @afourpaper to print on European A4 paper.
+ \def\afourpaper{{\globaldefs = 1
+ \setleading{12pt}%
+ \parskip = 3pt plus 2pt minus 1pt
+ %
+ \internalpagesizes{53\baselineskip}{160mm}{\voffset}{4mm}{\bindingoffset}{44pt}%
+ %
+ \tolerance = 700
+ \hfuzz = 1pt
+ }}
+
+ % A specific text layout, 24x15cm overall, intended for A4 paper. Top margin
+ % 29mm, hence bottom margin 28mm, nominal side margin 3cm.
+ \def\afourlatex{{\globaldefs = 1
+ \setleading{13.6pt}%
+ %
+ \afourpaper
+ \internalpagesizes{237mm}{150mm}{3.6mm}{3.6mm}{3mm}{7mm}%
+ %
+ \globaldefs = 0
+ }}
+
+ % Use @afourwide to print on European A4 paper in wide format.
+ \def\afourwide{%
+ \afourpaper
+ \internalpagesizes{9.5in}{6.5in}{\hoffset}{\normaloffset}{\bindingoffset}{7mm}%
+ %
+ \globaldefs = 0
+ }
+
+ % @pagesizes TEXTHEIGHT[,TEXTWIDTH]
+ % Perhaps we should allow setting the margins, \topskip, \parskip,
+ % and/or leading, also. Or perhaps we should compute them somehow.
+ %
+ \def\pagesizes{\parsearg\pagesizesxxx}
+ \def\pagesizesxxx#1{\pagesizesyyy #1,,\finish}
+ \def\pagesizesyyy#1,#2,#3\finish{{%
+ \setbox0 = \hbox{\ignorespaces #2}\ifdim\wd0 > 0pt \hsize=#2\relax \fi
+ \globaldefs = 1
+ %
+ \parskip = 3pt plus 2pt minus 1pt
+ \setleading{13.2pt}%
+ %
+ \internalpagesizes{#1}{\hsize}{\voffset}{\normaloffset}{\bindingoffset}{44pt}%
+ }}
+
+ % Set default to letter.
+ %
+ \letterpaper
+
+ \message{and turning on texinfo input format.}
+
+ % Define macros to output various characters with catcode for normal text.
+ \catcode`\"=\other
+ \catcode`\~=\other
+ \catcode`\^=\other
+ \catcode`\_=\other
+ \catcode`\|=\other
+ \catcode`\<=\other
+ \catcode`\>=\other
+ \catcode`\+=\other
+ \def\normaldoublequote{"}
+ \def\normaltilde{~}
+ \def\normalcaret{^}
+ \def\normalunderscore{_}
+ \def\normalverticalbar{|}
+ \def\normalless{<}
+ \def\normalgreater{>}
+ \def\normalplus{+}
+
+ % This macro is used to make a character print one way in ttfont
+ % where it can probably just be output, and another way in other fonts,
+ % where something hairier probably needs to be done.
+ %
+ % #1 is what to print if we are indeed using \tt; #2 is what to print
+ % otherwise. Since all the Computer Modern typewriter fonts have zero
+ % interword stretch (and shrink), and it is reasonable to expect all
+ % typewriter fonts to have this, we can check that font parameter.
+ %
+ \def\ifusingtt#1#2{\ifdim \fontdimen3\the\font=0pt #1\else #2\fi}
+
+ % Turn off all special characters except @
+ % (and those which the user can use as if they were ordinary).
+ % Most of these we simply print from the \tt font, but for some, we can
+ % use math or other variants that look better in normal text.
+
+ \catcode`\"=\active
+ \def\activedoublequote{{\tt\char34}}
+ \let"=\activedoublequote
+ \catcode`\~=\active
+ \def~{{\tt\char126}}
+ \chardef\hat=`\^
+ \catcode`\^=\active
+ \def^{{\tt \hat}}
+
+ \catcode`\_=\active
+ \def_{\ifusingtt\normalunderscore\_}
+ % Subroutine for the previous macro.
+ \def\_{\leavevmode \kern.06em \vbox{\hrule width.3em height.1ex}}
+
+ \catcode`\|=\active
+ \def|{{\tt\char124}}
+ \chardef \less=`\<
+ \catcode`\<=\active
+ \def<{{\tt \less}}
+ \chardef \gtr=`\>
+ \catcode`\>=\active
+ \def>{{\tt \gtr}}
+ \catcode`\+=\active
+ \def+{{\tt \char 43}}
+ %\catcode 27=\active
+ %\def^^[{$\diamondsuit$}
+
+ % Set up an active definition for =, but don't enable it most of the time.
+ {\catcode`\==\active
+ \global\def={{\tt \char 61}}}
+
+ \catcode`+=\active
+ \catcode`\_=\active
+
+ % If a .fmt file is being used, characters that might appear in a file
+ % name cannot be active until we have parsed the command line.
+ % So turn them off again, and have \everyjob (or @setfilename) turn them on.
+ % \otherifyactive is called near the end of this file.
+ \def\otherifyactive{\catcode`+=\other \catcode`\_=\other}
+
+ \catcode`\@=0
+
+ % \rawbackslashxx output one backslash character in current font
+ \global\chardef\rawbackslashxx=`\\
+ %{\catcode`\\=\other
+ %@gdef at rawbackslashxx{\}}
+
+ % \rawbackslash redefines \ as input to do \rawbackslashxx.
+ {\catcode`\\=\active
+ @gdef at rawbackslash{@let\=@rawbackslashxx }}
+
+ % \normalbackslash outputs one backslash in fixed width font.
+ \def\normalbackslash{{\tt\rawbackslashxx}}
+
+ % Say @foo, not \foo, in error messages.
+ \escapechar=`\@
+
+ % \catcode 17=0 % Define control-q
+ \catcode`\\=\active
+
+ % Used sometimes to turn off (effectively) the active characters
+ % even after parsing them.
+ @def at turnoffactive{@let"=@normaldoublequote
+ @let\=@realbackslash
+ @let~=@normaltilde
+ @let^=@normalcaret
+ @let_=@normalunderscore
+ @let|=@normalverticalbar
+ @let<=@normalless
+ @let>=@normalgreater
+ @let+=@normalplus}
+
+ @def at normalturnoffactive{@let"=@normaldoublequote
+ @let\=@normalbackslash
+ @let~=@normaltilde
+ @let^=@normalcaret
+ @let_=@normalunderscore
+ @let|=@normalverticalbar
+ @let<=@normalless
+ @let>=@normalgreater
+ @let+=@normalplus}
+
+ % Make _ and + \other characters, temporarily.
+ % This is canceled by @fixbackslash.
+ @otherifyactive
+
+ % If a .fmt file is being used, we don't want the `\input texinfo' to show up.
+ % That is what \eatinput is for; after that, the `\' should revert to printing
+ % a backslash.
+ %
+ @gdef at eatinput input texinfo{@fixbackslash}
+ @global at let\ = @eatinput
+
+ % On the other hand, perhaps the file did not have a `\input texinfo'. Then
+ % the first `\{ in the file would cause an error. This macro tries to fix
+ % that, assuming it is called before the first `\' could plausibly occur.
+ % Also back turn on active characters that might appear in the input
+ % file name, in case not using a pre-dumped format.
+ %
+ @gdef at fixbackslash{@ifx\@eatinput @let\ = @normalbackslash @fi
+ @catcode`+=@active @catcode`@_=@active}
+
+ % These look ok in all fonts, so just make them not special. The @rm below
+ % makes sure that the current font starts out as the newly loaded cmr10
+ @catcode`@$=@other @catcode`@%=@other @catcode`@&=@other @catcode`@#=@other
+
+ @textfonts
+ @rm
+
+ @c Local variables:
+ @c eval: (add-hook 'write-file-hooks 'time-stamp)
+ @c page-delimiter: "^\\\\message"
+ @c time-stamp-start: "def\\\\texinfoversion{"
+ @c time-stamp-format: "%:y-%02m-%02d"
+ @c time-stamp-end: "}"
+ @c End:
Index: llvm/test/Programs/MultiSource/Applications/treecc/doc/treecc.1
diff -c /dev/null llvm/test/Programs/MultiSource/Applications/treecc/doc/treecc.1:1.1
*** /dev/null Tue Apr 6 12:54:55 2004
--- llvm/test/Programs/MultiSource/Applications/treecc/doc/treecc.1 Tue Apr 6 12:54:45 2004
***************
*** 0 ****
--- 1,113 ----
+ .\" Copyright (c) 2001 Southern Storm Software, Pty Ltd.
+ .\"
+ .\" This program is free software; you can redistribute it and/or modify
+ .\" it under the terms of the GNU General Public License as published by
+ .\" the Free Software Foundation; either version 2 of the License, or
+ .\" (at your option) any later version.
+ .\"
+ .\" This program is distributed in the hope that it will be useful,
+ .\" but WITHOUT ANY WARRANTY; without even the implied warranty of
+ .\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ .\" GNU General Public License for more details.
+ .\"
+ .\" You should have received a copy of the GNU General Public License
+ .\" along with this program; if not, write to the Free Software
+ .\" Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ .TH treecc 1 "19 June 2001" "Southern Storm Software" ""
+ .SH NAME
+ treecc \- tree compiler-compiler
+ .SH SYNOPSIS
+ .ll +8
+ .B treecc
+ [ options ]
+ .I input
+ \&...
+ .SH DESCRIPTION
+ .B Treecc
+ converts input files in the treecc syntax into source
+ code that permits creating and walking abstract syntax trees.
+ It is intended for use in developing compilers, in concert with
+ existing tools such as \fBlex\fR(1) and \fByacc\fR(1).
+ The treecc syntax is described in the \fBtreecc\fR texinfo
+ topic.
+ .SH OPTIONS
+ .TP
+ .B \-o \fIfile\fB, \-\-output \fIfile\fR
+ Set the name of the output file. If this option is not supplied,
+ then the name of the first input file will be used, with its
+ extension changed to ".c". If the input is stdin, the default
+ output file is "yy_tree.c".
+
+ This option may be overridden using the "%output" keyword in
+ the input files.
+ .TP
+ .B \-h \fIfile\fB, \-\-header \fIfile\fR
+ Set the name of the header output file. This is only used for
+ the C and C++ languages. If this option is not supplied,
+ then the name of the output file will be used, with its extension
+ changed to ".h". If the input is stdin, the default header output
+ file is "yy_tree.h".
+
+ This option may be overriden using the "%header" keyword in the
+ input files.
+
+ If this option is used with a language that does not require
+ headers, it will be ignored.
+ .TP
+ .B \-d \fIdir\fB, \-\-output\-dir \fIdir\fR
+ Set the name of the Java output directory. This is only used for
+ the Java language. If this option is not supplied, then the directory
+ corresponding to the first input file is used. If the input is stdin,
+ the default is the current directory.
+
+ This option may be overriden using the "%outdir" keyword in the
+ input files.
+
+ If this option is used with a language other than Java, it will be ignored.
+ .TP
+ .B \-e \fIext\fB, \-\-extension \fIext\fR
+ Change the default output file extension to \fIext\fR, instead of
+ ".c". The value \fIext\fR can have a leading dot, but this is
+ not required.
+ .TP
+ .B \-f, \-\-force\-create
+ \fBTreecc\fR attempts to optimise the creation of output files
+ so that they are only modified if a non-trivial change has
+ occurred in the input. This can reduce the number of source
+ code recompiles when \fBtreecc\fR is used in combination
+ with \fBmake\fR(1).
+
+ This option forces the output files to be created, even if they
+ are the same as existing files with the same name.
+
+ The directive "%option force" can be used in the input files
+ to achieve the same effect as this option.
+ .TP
+ .B \-O \fIopt\fB, \-\-option \fIopt\fR
+ Set a treecc option value. This is a command-line version of
+ the "%option" keyword in the input files.
+ .TP
+ .B \-n, \-\-no\-output
+ Suppress the generation of output files. \fBTreecc\fR parses the
+ input files, checks for errors, and then stops.
+ .TP
+ .B \-\-help
+ Print a usage message for the \fBtreecc\fR program.
+ .TP
+ .B \-v, \-\-version
+ Print the version of the \fBtreecc\fR program.
+ .TP
+ .B \-\-
+ Marks the end of the command-line options, and the beginning of
+ the input filenames. You may need to use this if your filename
+ begins with '-'. e.g. "treecc -- -input.tc". This is not needed
+ if the input is stdin: "treecc -" is perfectly valid.
+ .SH "AUTHOR"
+ Written by Southern Storm Software, Pty Ltd.
+
+ http://www.southern-storm.com.au/
+ .SH "SEE ALSO"
+ lex(1), yacc(1), make(1)
+ .SH "DIAGNOSTICS"
+ Exit status is 1 if an error occurred while processing the input.
+ Otherwise the exit status is 0.
Index: llvm/test/Programs/MultiSource/Applications/treecc/doc/treecc.texi
diff -c /dev/null llvm/test/Programs/MultiSource/Applications/treecc/doc/treecc.texi:1.1
*** /dev/null Tue Apr 6 12:54:55 2004
--- llvm/test/Programs/MultiSource/Applications/treecc/doc/treecc.texi Tue Apr 6 12:54:45 2004
***************
*** 0 ****
--- 1,2916 ----
+ \input texinfo @c -*-texinfo-*-
+ @c %** start of header
+ @setfilename treecc.info
+ @settitle Tree Compiler-Compiler
+ @setchapternewpage off
+ @c %** end of header
+
+ @dircategory DotGNU
+ @direntry
+ * TreeCC: (treecc). Generate code for compilers to build
+ abstract syntax trees.
+ @end direntry
+
+ @ifinfo
+ The treecc program converts descriptions of abstract syntax
+ trees into source code that can be used to support compiler
+ development.
+
+ @noindent
+ Copyright @copyright{} 2001 Southern Storm Software, Pty Ltd
+ @*Copyright @copyright{} 2003 Free Software Foundation, Inc.
+ @end ifinfo
+
+ @titlepage
+ @sp 10
+ @center @titlefont{Tree Compiler-Compiler}
+
+ @vskip 50pt
+
+ @center{Rhys Weatherley}
+
+ @vskip 50pt
+ @center{Copyright @copyright{} 2001, 2002 Southern Storm Software, Pty Ltd}
+ @center{Copyright @copyright{} 2003 Free Software Foundation, Inc.}
+ @end titlepage
+
+ @c -----------------------------------------------------------------------
+
+ @node Top, Overview, , (dir)
+ @menu
+ * Overview:: Treecc in brief
+ * Expression Example:: A simple example of using treecc
+ * Invoking Treecc:: Invoking treecc from the command-line
+ * Syntax:: Syntax of input files
+ * Line Tracking:: Tracking line numbers in source files
+ * Output APIs:: API's that are available in the generated output
+ * Full Expression Example:: Full code for the expression example
+ * EBNF Syntax:: Full EBNF syntax for treecc input files
+ * Index:: Index of concepts and facilities
+ @end menu
+
+ @c -----------------------------------------------------------------------
+
+ @node Overview, Expression Example, Top, Top
+ @chapter Overview
+ @cindex Overview
+
+ @section Introduction
+
+ Traditional compiler construction tools such as lex and yacc focus on
+ the lexical analysis and parsing phases of compilation. But they
+ provide very little to support semantic analysis and code generation.
+
+ Yacc allows grammar rules to be tagged with semantic actions and values,
+ but it doesn't provide any routines that assist in the process of tree
+ building, semantic analysis, or code generation. Because those processes
+ are language-specific, yacc leaves the details to the programmer.
+
+ Support for semantic analysis was also a lot simpler in the languages
+ that were prevalent when lex and yacc were devised. C and Pascal
+ require declare before use, which allows the semantic information
+ about a statement to be determined within the parser at the point of
+ use. at footnote{K&R C did allow functions that weren't declared to be called,
+ but only if they returned an "int". This allowed the compiler to
+ guess the declaration if it wasn't available, and to proceed as
+ though all symbols were declared before use.} If extensive optimization
+ is not required, then code generation can also be performed within
+ the grammar, leading to a simple one-pass compiler structure.
+
+ Modern languages allow deferred declaration of methods, fields, and
+ types. For example, Java allows a method to refer to a field that
+ is declared further down the .java source file. A field can be
+ declared with a type whose class definition has not yet been parsed.
+
+ Hence, most of the semantic analysis that used to be performed inline
+ within a yacc grammar must now be performed after the entire program
+ has been parsed. Tree building and walking is now more important
+ than it was in older declare before use languages.
+
+ @section Tree walking: the need for something better
+
+ Building parse tree data structures and walking them is not terribly
+ difficult, but it is extremely time-consuming and error-prone. A
+ modern programming language may have hundreds of node types, divided
+ into categories for statements, expressions, types, declarations, etc.
+ When a new programming language is being devised, new node types may
+ be added quite frequently. This has ramifications in trying to manage
+ the code's complexity. at footnote{Implementing an existing programming
+ language has the same problems as a new language. Most programming
+ languages are too large to be implemented all at once, and so the problem
+ must be tackled in stages. These stages are very similar to those the
+ programmer goes through implementing a new language.}
+
+ For example, consider nodes that correspond to programming language
+ types in a C-like language. There will be node types for integer
+ types, floating-point types, pointers, structures, functions, etc.
+ There will be semantic analysis routines for testing types for
+ equality, comparing types for coercions and casts, evaluating the
+ size of a type for memory layout purposes, determining if the type
+ falls into a general category such as "integer" or "pointer", etc.
+
+ Let's say we wanted to add a new "128-bit integer" type to this
+ language. Adding a new node type is fairly straight-forward.
+ But we also need to track down every place in the code where the
+ compiler walks a type or deals with integers and add an appropriate
+ case for the new type. This is very error-prone. Such code is
+ likely to be split over many files, and good coding practices only
+ help to a certain extent.
+
+ This problem gets worse when new kinds of expressions and statements
+ are added to the language. The change not only affects semantic
+ analysis, but also optimization and code generation. Some compilers
+ use multiple passes over the tree to perform optimization, with
+ different algorithms used in each pass. Code generation may use a
+ number of different strategies, depending upon how an expression or
+ statement is used. If even one of these places is missed when the
+ new node type is added, then there is the potential for a very nasty
+ bug that may go unnoticed for months or years.
+
+ Object-oriented languages such as C++ can help a bit in constructing
+ robust tree structures. The base class can declare abstract methods
+ for any semantic analysis, optimization, or code generation routine
+ that needs to be implemented for all members of the node category.
+ But another code maintainence problem arises. What happens when
+ we want to add a new optimization pass in the future? We must go
+ into hundreds of classes and implement the methods.
+
+ To avoid changing hundreds of classes, texts on Design Patterns
+ suggest using a Visitor pattern. Then the new optimization pass
+ can be encapsulated in a visitor. This would work, except for
+ the following drawback of visitor patterns, as described in Gamma,
+ et al:
+
+ @quotation
+ @emph{The Visitor pattern makes it hard to add new subclasses of
+ Element. Each new ConcreteElement gives rise to a new abstract
+ operation on Visitor and a corresponding implementation in
+ every ConcreteVisitor class.}
+
+ @emph{... The Visitor class hierarchy can be difficult to maintain
+ when new ConcreteElement classes are added frequently. In such
+ cases, it's probably easier just to define operations on the
+ classes that make up the structure.}
+ @end quotation
+
+ That is, if we add a new node type in the future, we have a large
+ maintainence problem on our hands. The solution is to scatter the
+ implementation through-out every class, which is the situation we
+ were trying to avoid by using the Visitor pattern.
+
+ Because compiler construction deals with a large set of rapidly
+ changing node types and operations, neither of the usual approaches
+ work very well.
+
+ The ideal programming language for designing compilers needs to have
+ some way to detect when the programmer forgets to implement an operation
+ for a new node type, and to ensure that a new operation covers all
+ existing node types adequately. Existing OO languages do not perform
+ this kind of global error checking. What few checking procedures they
+ have change the maintainence problem into a different problem of
+ similar complexity.
+
+ @section Aspect-oriented programming
+
+ A new field in language design has emerged in recent years called
+ "Aspect-Oriented Programming" (AOP). A good review of the field
+ can be found in the October 2001 issue of the @emph{Communications of
+ the ACM}, and on the AspectJ Web site, @url{http://www.aspectj.org/}.
+
+ The following excerpt from the introduction to the AOP section in the
+ CACM issue describes the essential aspects of AOP, and the difference
+ between OOP and AOP:
+
+ @quotation
+ @emph{AOP is based on the idea that computer systems are better programmed
+ by separately specifying the various concerns (properties or areas
+ of interest) of a system and some description of their relationships,
+ and then relying on mechanisms in the underlying AOP environment to
+ weave or compose them together into a coherent program. ...
+ While the tendancy in OOP's is to find commonality among classes
+ and push it up the inheritance tree, AOP attempts to realize
+ scattered concerns as first-class elements, and eject them
+ horizontally from the object structure.}
+ @end quotation
+
+ Aspect-orientation gives us some hope of solving our compiler
+ complexity problems. We can view each operation on node types
+ (semantic analysis, optimization, code generation, etc) as an
+ "aspect" of the compiler's construction. The AOP language weaves
+ these aspects with the node types to create the final compiler.
+
+ @section The treecc approach
+
+ We don't really want to implement a new programming language
+ just for compiler construction. Especially since the new language's
+ implementation would have all of the problems described above and would
+ therefore also be difficult to debug and maintain.
+
+ The approach that we take with "treecc" is similar to that used by
+ "yacc". A simple rule-based language is devised that is used to describe
+ the intended behaviour declaratively. Embedded code is used to provide
+ the specific implementation details. A translator then converts the input
+ into source code that can be compiled in the usual fashion.
+
+ The translator is responsible for generating the tree building and
+ walking code, and for checking that all relevant operations have been
+ implemented on the node types. Functions are provided that make
+ it easier to build and walk the tree data structures from within
+ a "yacc" grammar and other parts of the compiler.
+
+ @c -----------------------------------------------------------------------
+
+ @node Expression Example, Invoking Treecc, Overview, Top
+ @chapter A simple example for expressions
+ @cindex Expression example
+
+ Consider the following yacc grammar for a simple expression language:
+
+ @example
+ %token INT FLOAT
+
+ %%
+
+ expr: INT
+ | FLOAT
+ | '(' expr ')'
+ | expr '+' expr
+ | expr '-' expr
+ | expr '*' expr
+ | expr '/' expr
+ | '-' expr
+ ;
+ @end example
+
+ (We will ignore the problems of precedence and associativity and
+ assume that the reader is familiar with how to resolve such issues
+ in yacc grammars).
+
+ There are 7 types of nodes for this grammar: @samp{intnum}, @samp{floatnum},
+ @samp{plus}, @samp{minus}, @samp{multiply}, @samp{divide}, and @samp{negate}.
+ They are defined in treecc as follows:
+
+ @example
+ %node expression %abstract %typedef
+
+ %node binary expression %abstract =
+ @{
+ expression *expr1;
+ expression *expr2;
+ @}
+
+ %node unary expression %abstract =
+ @{
+ expression *expr;
+ @}
+
+ %node intnum expression =
+ @{
+ int num;
+ @}
+
+ %node floatnum expression =
+ @{
+ float num;
+ @}
+
+ %node plus binary
+ %node minus binary
+ %node multiply binary
+ %node divide binary
+ %node negate unary
+ @end example
+
+ We have introduced three extra node types that refer
+ to any expression, binary expressions, and unary expressions. These
+ can be seen as superclasses in an OO-style framework. We have
+ declared these node types as @samp{abstract} because the yacc grammar
+ will not be permitted to create instances of these classes directly.
+
+ The @samp{binary}, @samp{unary}, @samp{intnum}, and @samp{floatnum}
+ node types have field definitions associated with them. These have
+ a similar syntax to C @code{struct} declarations.
+
+ The yacc grammar is augmented as follows to build the parse tree:
+
+ @example
+ %union @{
+ expression *node;
+ int inum;
+ float fnum;
+ @}
+
+ %token INT FLOAT
+
+ %type <node> expr
+ %type <inum> INT
+ %type <fnum> FLOAT
+
+ %%
+
+ expr: INT @{ $$ = intnum_create($1); @}
+ | FLOAT @{ $$ = floatnum_create($1); @}
+ | '(' expr ')' @{ $$ = $2; @}
+ | expr '+' expr @{ $$ = plus_create($1, $3); @}
+ | expr '-' expr @{ $$ = minus_create($1, $3); @}
+ | expr '*' expr @{ $$ = multiply_create($1, $3); @}
+ | expr '/' expr @{ $$ = divide_create($1, $3); @}
+ | '-' expr @{ $$ = negate_create($2); @}
+ ;
+ @end example
+
+ The treecc translator generates the @samp{*_create} functions so that
+ the rest of the compiler can build the necessary data structures
+ on demand. The parameters to the @samp{*_create} functions
+ are identical in type and order to the members of the structure for
+ that node type.
+
+ Because @samp{expression}, @samp{binary}, and @samp{unary} are abstract,
+ there will be no @samp{*_create} functions associated with them. This will
+ help the programmer catch certain kinds of errors.
+
+ The type that is returned from a @samp{*_create} function is the first
+ superclass of the node that has a @samp{%typedef} keyword associated with it;
+ @samp{expression *} in this case.
+
+ @section Storing extra information
+
+ Normally we will want to store extra information with a node beyond
+ that which is extracted by the yacc grammar. In our expression
+ example, we probably want to store type information in the nodes
+ so that we can determine if the whole expression is integer or
+ floating point during semantic analysis. We can add type information
+ to the @samp{expression} node type as follows:
+
+ @example
+ %node expression %abstract %typedef =
+ @{
+ %nocreate type_code type;
+ @}
+ @end example
+
+ The @samp{%nocreate} flag indicates that the field should not be passed
+ to the @samp{*_create} functions as a parameter. i.e. it provides semantic
+ information that isn't present in the grammar. When nodes are created,
+ any fields that are declared as @samp{%nocreate} will be undefined in value.
+ A default value can be specified as follows:
+
+ @example
+ %node expression %abstract %typedef =
+ @{
+ %nocreate type_code type = @{int_type@};
+ @}
+ @end example
+
+ Default values must be enclosed in @samp{@{} and @samp{@}} because they are
+ pieces of code in the underlying source language (C, C++, etc), instead
+ of tokens in the treecc syntax. Any legitimate expression in the
+ underlying source language may be used.
+
+ We also need to arrange for @samp{type_code} to be declared. One way to
+ do this is by adding a @samp{%decls} section to the front of the treecc
+ input file:
+
+ @example
+ %decls %@{
+
+ typedef enum
+ @{
+ int_type,
+ float_type
+
+ @} type_code;
+
+ %@}
+ @end example
+
+ We could have introduced the definition by placing a @samp{#include}
+ directive into the @samp{%decls} section instead, or by defining a
+ treecc enumerated type:
+
+ @example
+ %enum type_code =
+ @{
+ int_type,
+ float_type
+ @}
+ @end example
+
+ Now that we have these definitions, type-inferencing can be implemented
+ as follows:
+
+ @example
+ %operation void infer_type(expression *e)
+
+ infer_type(binary)
+ @{
+ infer_type(e->expr1);
+ infer_type(e->expr2);
+
+ if(e->expr1->type == float_type || e->expr2->type == float_type)
+ @{
+ e->type = float_type;
+ @}
+ else
+ @{
+ e->type = int_type;
+ @}
+ @}
+
+ infer_type(unary)
+ @{
+ infer_type(e->expr);
+ e->type = e->expr->type;
+ @}
+
+ infer_type(intnum)
+ @{
+ e->type = int_type;
+ @}
+ @end example
+
+ This example demonstrates using the abstract node types @samp{binary} and
+ @samp{unary} to define operations on all subclasses. The treecc translator
+ will generate code for a full C function called @samp{infer_type} that
+ incorporates all of the cases.
+
+ But hang on a second! What happened to @samp{floatnum}? Where did it
+ go? It turns out that treecc will catch this. It will report
+ an error to the effect that @samp{node type `floatnum' is not handled in
+ operation `infer_type'}. Here is its definition:
+
+ @example
+ infer_type(floatnum)
+ @{
+ e->type = float_type;
+ @}
+ @end example
+
+ As we can see, treecc has just caught a bug in the language
+ implementation and reported it to us as soon as we introduced it.
+
+ Let's now extend the language with a @samp{power} operator:
+
+ @example
+ yacc:
+
+ expr: expr '^' expr @{ $$ = create_power($1, $3); @}
+ ;
+
+ treecc:
+
+ %node power binary
+ @end example
+
+ That's all there is to it! When treecc re-translates the input
+ file, it will modify the definition of @samp{infer_type} to include the
+ extra case for @samp{power} nodes. Because @samp{power} is a subclass of
+ @samp{binary}, treecc already knows how to perform type inferencing for the
+ new node and it doesn't warn us about a missing declaration.
+
+ What if we wanted to restrict the second argument of @samp{power} to be
+ an integer value? We can add the following case to @samp{infer_type}:
+
+ @example
+ infer_type(power)
+ @{
+ infer_type(e->expr1);
+ infer_type(e->expr2);
+
+ if(e->expr2->type != int_type)
+ @{
+ error("second argument to `^' is not an integer");
+ @}
+
+ e->type = e->expr1->type;
+ @}
+ @end example
+
+ The translator now notices that there is a more specific implementation
+ of @samp{infer_type} for @samp{power}, and won't use the @samp{binary}
+ case for it.
+
+ The most important thing to realise here is that the translator always
+ checks that there are sufficient declarations for @samp{infer_type} to cover
+ all relevant node types. If it detects a lack, it will immediately
+ raise an error to the user. This allows tree coverage problems to
+ be found a lot sooner than with the traditional approach.
+
+ @xref{Full Expression Example}, for a complete listing of the above
+ example files.
+
+ @c -----------------------------------------------------------------------
+
+ @node Invoking Treecc, Syntax, Expression Example, Top
+ @chapter Invoking treecc from the command-line
+ @cindex Invoking treecc
+ @cindex Command-line options
+
+ The general form of treecc's command-line syntax is as follows:
+
+ @example
+ treecc [OPTIONS] INPUT ...
+ @end example
+
+ Treecc accepts the following command-line options:
+
+ @table @code
+ @item -o FILE
+ @itemx --output FILE
+ Set the name of the output file to @samp{FILE}. If this option is not
+ supplied, then the name of the first input file will be used, with its
+ extension changed to @samp{.c}. If the input is standard input,
+ the default output file is @samp{yy_tree.c}.
+
+ This option may be overridden using the @samp{%output} keyword in
+ the input files.
+
+ @item -h FILE
+ @itemx --header FILE
+ Set the name of the header output file to @samp{FILE}. This is only
+ used for the C and C++ output languages. If this option is not supplied,
+ then the name of the output file will be used, with its extension
+ changed to @samp{.h}. If the input is standard input, the default header
+ output file is @samp{yy_tree.h}.
+
+ This option may be overriden using the @samp{%header} keyword in the
+ input files. If this option is used with a language that does not require
+ headers, it will be ignored.
+
+ @item -d DIR
+ @itemx --output-dir DIR
+ Set the name of the Java output directory to @samp{DIR}. This is only
+ used for the Java language. If this option is not supplied, then the
+ directory corresponding to the first input file is used. If the input
+ is standard input, the default is the current directory.
+
+ This option may be overriden using the @samp{%outdir} keyword in the
+ input files. If this option is used with a language other than Java,
+ it will be ignored.
+
+ @item -e EXT
+ @itemx --extension EXT
+ Change the default output file extension to @samp{ext}, instead of
+ @samp{.c}. The value @samp{ext} can have a leading dot, but this is
+ not required.
+
+ @item -f
+ @itemx --force-create
+ Treecc normally attempts to optimise the creation of output files
+ so that they are only modified if a non-trivial change has
+ occurred in the input. This can reduce the number of source
+ code recompiles when treecc is used in combination with make.
+
+ This option forces the output files to be created, even if they
+ are the same as existing files with the same name.
+
+ The declaration @samp{%option force} can be used in the input files
+ to achieve the same effect as this option.
+
+ @item -O OPT
+ @itemx --option OPT
+ Set a treecc option value. This is a command-line version of
+ the @samp{%option} keyword in the input files.
+
+ @item -n
+ @itemx --no-output
+ Suppress the generation of output files. Treecc parses the
+ input files, checks for errors, and then stops.
+
+ @item --help
+ Print a usage message for the treecc program.
+
+ @item -v
+ @itemx --version
+ Print the version of the treecc program.
+
+ @item --
+ Marks the end of the command-line options, and the beginning of
+ the input filenames. You may need to use this if your filename
+ begins with @samp{-}. e.g. @samp{treecc -- -input.tc}. This is
+ not needed if the input is standard input: @samp{treecc -}
+ is perfectly valid.
+ @end table
+
+ @c -----------------------------------------------------------------------
+
+ @node Syntax, Nodes, Invoking Treecc, Top
+ @chapter Syntax of input files
+ @cindex Syntax
+
+ Treecc input files consist of zero or more declarations that define
+ nodes, operations, options, etc. The following sections describe each
+ of these elements.
+
+ @menu
+ * Nodes:: Node declarations
+ * Types:: Types used in fields and parameters
+ * Enumerations:: Enumerated type declarations
+ * Operations:: Operation declarations
+ * Options:: Options that modify treecc's behaviour
+ * Literal Code:: Literal code declarations
+ * Changing Files:: Changing input and output files
+ @end menu
+
+ @c -----------------------------------------------------------------------
+
+ @node Nodes, Types, Syntax, Syntax
+ @section Node declarations
+ @cindex Nodes
+ @cindex %node keyword
+ @cindex Fields
+
+ Node types are defined using the @samp{node} keyword in input files.
+ The general form of the declaration is:
+
+ @example
+ %node NAME [ PNAME ] [ FLAGS ] [ = FIELDS ]
+ @end example
+
+ @table @samp
+ @item NAME
+ An identifier that is used to refer to the node type elsewhere
+ in the treecc definition. It is also the name of the type that will be
+ visible to the programmer in literal code blocks.
+
+ @item PNAME
+ An identifier that refers to the parent node type that @samp{NAME} inherits
+ from. If @samp{PNAME} is not supplied, then @samp{NAME} is a top-level
+ declaration. It is legal to supply a @samp{PNAME} that has not yet
+ been defined in the input.
+
+ @item FLAGS
+ Any combination of @samp{%abstract} and @samp{%typedef}:
+
+ @table @samp
+ @item %abstract
+ @cindex %abstract keyword
+ The node type cannot be constructed by the programmer. In addition,
+ the programmer does not need to define operation cases for this node
+ type if all subtypes have cases associated with them.
+
+ @item %typedef
+ @cindex %typedef keyword
+ The node type is used as the common return type for node creation
+ functions. Top-level declarations must have a @samp{%typedef} keyword.
+ @end table
+ @end table
+
+ The @samp{FIELDS} part of a node declaration defines the fields that
+ make up the node type. Each field has the following general form:
+
+ @example
+ [ %nocreate ] TYPE FNAME [ = VALUE ] ';'
+ @end example
+
+ @table @samp
+ @item %nocreate
+ @cindex %nocreate keyword
+ The field is not used in the node's constructor. When the node is
+ constructed, the value of this field will be undefined unless
+ @samp{VALUE} is specified.
+
+ @item TYPE
+ The type that is associated with the field. Types can be declared
+ using a subset of the C declaration syntax, augmented with some C++
+ and Java features. @xref{Types}, for more information.
+
+ @item FNAME
+ The name to associate with the field. Treecc verifies that the field
+ does not currently exist in this node type, or in any of its ancestor
+ node types.
+
+ @item VALUE
+ The default value to assign to the field in the node's constructor.
+ This can only be used on fields that are declared with @samp{%nocreate}.
+ The value must be enclosed in braces. For example @samp{@{NULL@}} would
+ be used to initialize a field with @samp{NULL}.
+
+ The braces are required because the default value is expressed in
+ the underlying source language, and can use any of the usual constant
+ declaration features present in that language.
+ @end table
+
+ When the output language is C, treecc creates a struct-based type
+ called @samp{NAME} that contains the fields for @samp{NAME} and
+ all of its ancestor classes. The type also contains some house-keeping
+ fields that are used internally by the generated code. The following
+ is an example:
+
+ @example
+ typedef struct binary__ binary;
+ struct binary__ @{
+ const struct binary_vtable__ *vtable__;
+ int kind__;
+ char *filename__;
+ long linenum__;
+ type_code type;
+ expression * expr1;
+ expression * expr2;
+ @};
+ @end example
+
+ The programmer should avoid using any identifier that
+ ends with @samp{__}, because it may clash with house-keeping
+ identifiers that are generated by treecc.
+
+ When the output language is C++, Java, or C#, treecc creates a class
+ called @samp{NAME}, that inherits from the class @samp{PNAME}.
+ The field definitions for @samp{NAME} are converted into public members
+ in the output.
+
+ @c -----------------------------------------------------------------------
+
+ @node Types, Enumerations, Nodes, Syntax
+ @section Types used in fields and parameters
+ @cindex Types
+
+ Types that are used in field and parameter declarations have a
+ syntax which is subset of features found in C, C++, and Java:
+
+ @example
+ TypeAndName ::= Type [ IDENTIFIER ]
+
+ Type ::= TypeName
+ | Type '*'
+ | Type '&'
+ | Type '[' ']'
+
+ TypeName ::= IDENTIFIER @{ IDENTIFIER @}
+ @end example
+
+ Types are usually followed by an identifier that names the field or
+ parameter. The name is required for fields and is optional for parameters.
+ For example @samp{int} is usually equivalent to @samp{int x} in parameter
+ declarations.
+
+ The following are some examples of using types:
+
+ @example
+ int
+ int x
+ const char *str
+ expression *expr
+ Element[][] array
+ Item&
+ unsigned int y
+ const Element
+ @end example
+
+ The grammar used by treecc is slightly ambiguous. The last example above
+ declares a parameter called @samp{Element}, that has type @samp{const}.
+ The programmer probably intended to declare an anonymous parameter with type
+ @samp{const Element} instead.
+
+ This ambiguity is unavoidable given that treecc is not fully
+ aware of the underlying language's type system. When treecc
+ sees a type that ends in a sequence of identifiers, it will
+ always interpret the last identifier as the field or parameter
+ name. Thus, the programmer must write the following instead:
+
+ @example
+ const Element e
+ @end example
+
+ Treecc cannot declare types using the full power of C's type system.
+ The most common forms of declarations are supported, and the rest
+ can usually be obtained by defining a @samp{typedef} within a
+ literal code block. @xref{Literal Code}, for more information
+ on literal code blocks.
+
+ It is the responsibility of the programmer to use type constructs
+ that are supported by the underlying programming language. Types such
+ as @samp{const char *} will give an error when the output is compiled
+ with a Java compiler, for example.
+
+ @c -----------------------------------------------------------------------
+
+ @node Enumerations, Operations, Types, Syntax
+ @section Enumerated type declarations
+ @cindex Enumerations
+ @cindex enum declaration
+ @cindex %enum keyword
+
+ Enumerated types are a special kind of node type that can be used
+ by the programmer for simple values that don't require a full abstract
+ syntax tree node. The following is an example of defining a list
+ of the primitive machine types used in a Java virtual machine:
+
+ @example
+ %enum JavaType =
+ @{
+ JT_BYTE,
+ JT_SHORT,
+ JT_CHAR,
+ JT_INT,
+ JT_LONG,
+ JT_FLOAT,
+ JT_DOUBLE,
+ JT_OBJECT_REF
+ @}
+ @end example
+
+ Enumerations are useful when writing code generators and type
+ inferencing routines. The general form is:
+
+ @example
+ %enum NAME = @{ VALUES @}
+ @end example
+
+ @table @samp
+ @item NAME
+ An identifier to be used to name the enumerated type. The name must
+ not have been previously used as a node type, an enumerated type, or
+ an enumerated value.
+
+ @item VALUES
+ A comma-separated list of identifiers that name the values within
+ the enumeration. Each of the names must be unique, and must not have
+ been used previously as a node type, an enumerated type, or an
+ enumerated value.
+ @end table
+
+ Logically, each enumerated value is a special node type that inherits from
+ a parent node type corresponding to the enumerated type @samp{NAME}.
+
+ When the output language is C or C++, treecc generates an enumerated
+ typedef for @samp{NAME} that contains the enumerated values in the
+ same order as was used in the input file. The typedef name can be
+ used elsewhere in the code as the type of the enumeration.
+
+ When the output language is Java, treecc generates a class called
+ @samp{NAME} that contains the enumerated values as integer constants.
+ Elsewhere in the code, the type @samp{int} must be used to declare
+ variables of the enumerated type. Enumerated values are referred
+ to as @samp{NAME.VALUE}. If the enumerated type is used as a trigger
+ parameter, then @samp{NAME} must be used instead of @samp{int}:
+ treecc will convert the type when the Java code is output.
+
+ When the output language is C#, treecc generates an enumerated value
+ type called @samp{NAME} that contains the enumerated values as
+ members. The C# type @samp{NAME} can be used elsewhere in the code
+ as the type of the enumeration. Enumerated values are referred to
+ as @samp{NAME.VALUE}.
+
+ @c -----------------------------------------------------------------------
+
+ @node Operations, Options, Enumerations, Syntax
+ @section Operation declarations
+ @cindex Operations
+ @cindex operation declarations
+ @cindex operation cases
+ @cindex %operation keyword
+ @cindex trigger parameters
+
+ Operations are declared in two parts: the declaration, and the
+ cases. The declaration part defines the prototype for the
+ operation and the cases define how to handle specific kinds of
+ nodes for the operation.
+
+ Operations are defined over one or more trigger parameters. Each
+ trigger parameter specifies a node type or an enumerated type that
+ is selected upon to determine what course of action to take. The
+ following are some examples of operation declarations:
+
+ @example
+ %operation void infer_type(expression *e)
+ %operation type_code common_type([type_code t1], [type_code t2])
+ @end example
+
+ Trigger parameters are specified by enclosing them in square
+ brackets. If none of the parameters are enclosed in square
+ brackets, then treecc assumes that the first parameter is the
+ trigger.
+
+ The general form of an operation declaration is as follows:
+
+ @example
+ %operation @{ %virtual | %inline | %split @} RTYPE [CLASS::]NAME(PARAMS)
+ @end example
+
+ @table @samp
+ @item %virtual
+ @cindex %virtual keyword
+ Specifies that the operation is associated with a node type as
+ a virtual method. There must be only one trigger parameter,
+ and it must be the first parameter.
+
+ Non-virtual operations are written to the output source files
+ as global functions.
+
+ @item %inline
+ @cindex %inline keyword
+ Optimise the generation of the operation code so that all cases
+ are inline within the code for the function itself. This can
+ only be used with non-virtual operations, and may improve
+ code efficiency if there are lots of operation cases with a
+ small amount of code in each.
+
+ @item %split
+ @cindex %split keyword
+ Split the generation of the multi-trigger operation code across
+ multiple functions, to reduce the size of each individual function.
+ It is sometimes necessary to split large @code{%inline} operations
+ to avoid compiler limits on function size.
+
+ @item RTYPE
+ The type of the return value for the operation. This should be
+ @samp{void} if the operation does not have a return value.
+
+ @item CLASS
+ The name of the class to place the operation's definition within.
+ This can only be used with non-virtual operations, and is
+ intended for languages such as Java and C# that cannot declare
+ methods outside of classes. The class name will be ignored if
+ the output language is C.
+
+ If a class name is required, but the programmer did not supply it,
+ then @samp{NAME} will be used as the default. The exception to
+ this is the C# language: @samp{CLASS} must always be supplied and
+ it must be different from @samp{NAME}. This is due to a "feature"
+ in some C# compilers that forbid a method with the same name as
+ its enclosing class.
+
+ @item NAME
+ The name of the operation.
+
+ @item PARAMS
+ The parameters to the operation. Trigger parameters may be
+ enclosed in square brackets. Trigger parameters must be
+ either node types or enumerated types.
+ @end table
+
+ Once an operation has been declared, the programmer can specify
+ its cases anywhere in the input files. It is not necessary that
+ the cases appear after the operation, or that they be contiguous
+ within the input files. This permits the programmer to place
+ operation cases where they are logically required for maintainence
+ reasons.
+
+ There must be sufficient operation cases defined to cover every
+ possible combination of node types and enumerated values that
+ inherit from the specified trigger types. An operation case
+ has the following general form:
+
+ @example
+ NAME(TRIGGERS) [, NAME(TRIGGERS2) ...]
+ @{
+ CODE
+ @}
+ @end example
+
+ @table @samp
+ @item NAME
+ The name of the operation for which this case applies.
+
+ @item TRIGGERS
+ A comma-separated list of node types or enumerated values that
+ define the specific case that is handled by the following code.
+
+ @item CODE
+ Source code in the output source language that implements the
+ operation case.
+ @end table
+
+ Multiple trigger combinations can be associated with a single
+ block of code, by listing them all, separated by commas. For
+ example:
+
+ @example
+ common_type(int_type, int_type)
+ @{
+ return int_type;
+ @}
+
+ common_type(int_type, float_type),
+ common_type(float_type, int_type),
+ common_type(float_type, float_type)
+ @{
+ return float_type;
+ @}
+ @end example
+
+ @c -----------------------------------------------------------------------
+
+ @node Options, Literal Code, Operations, Syntax
+ @section Options that modify treecc's behaviour
+ @cindex Options
+ @cindex option declaration
+ @cindex %option keyword
+
+ "(*)" is used below to indicate an option that is enabled by default.
+
+ @table @samp
+ @item %option track_lines
+ @cindex track_lines option
+ Enable the generation of code that can track the current filename and
+ line number when nodes are created. @xref{Line Tracking}, for more
+ information. (*)
+
+ @item %option no_track_lines
+ @cindex no_track_lines option
+ Disable the generation of code that performs line number tracking.
+
+ @item %option singletons
+ @cindex singletons option
+ Optimise the creation of singleton node types. These are
+ node types without any fields. Treecc can optimise the code
+ so that only one instance of a singleton node type exists in
+ the system. This can speed up the creation of nodes for
+ constants within compilers. (*)
+
+ Singleton optimisations will have no effect if @samp{track_lines}
+ is enabled, because line tracking uses special hidden fields in
+ every node.
+
+ @item %option no_singletons
+ @cindex no_singletons option
+ Disable the optimisation of singleton node types.
+
+ @item %option reentrant
+ @cindex reentrant option
+ Enable the generation of reentrant code that does not rely
+ upon any global variables. Separate copies of the compiler
+ state can be used safely in separate threads. However, the
+ same copy of the compiler state cannot be used safely in two or
+ more threads.
+
+ @item %option no_reentrant
+ @cindex no_reentrant option
+ Disable the generation of reentrant code. The interface to
+ node management functions is simpler, but cannot be used
+ in a threaded environment. (*)
+
+ @item %option force
+ @cindex force option
+ Force output source files to be written, even if they are
+ unchanged. This option can also be set using the @samp{-f}
+ command-line option.
+
+ @item %option no_force
+ @cindex no_force option
+ Don't force output source files to be written if they are the
+ same as before. (*)
+
+ This option can help smooth integration of treecc with make.
+ Only those output files that have changed will be modified.
+ This reduces the number of files that the underlying source
+ language compiler must process after treecc is executed.
+
+ @item %option virtual_factory
+ @cindex virtual_factory option
+ Use virtual methods in the node type factories, so that the
+ programmer can subclass the factory and provide new
+ implementations of node creation functions. This option is
+ ignored for C, which does not use factories.
+
+ @item %option no_virtual_factory
+ @cindex no_virtual_factory option
+ Don't use virtual methods in the node type factories. (*)
+
+ @item %option abstract_factory
+ @cindex abstract_factory option
+ Use abstract virtual methods in the node type factories.
+ The programmer is responsible for subclassing the factory
+ to provide node creation functionality.
+
+ @item %option no_abstract_factory
+ @cindex no_abstract_factory option
+ Don't use abstract virtual methods in the node type factories. (*)
+
+ @item %option kind_in_node
+ @cindex kind_in_node option
+ Put the kind field in the node, for more efficient access at runtime. (*)
+
+ @item %option kind_in_vtable
+ @cindex kind_in_vtable option
+ Put the kind field in the vtable, and not the node. This saves some
+ memory, at the cost of slower access to the kind value at runtime.
+ This option only applies when the language is C. The kind field is
+ always placed in the node in other languages, because it isn't possible
+ to modify the vtable.
+
+ @item %option prefix = PREFIX
+ @cindex prefix option
+ Specify the prefix to be used in output files in place of "yy".
+
+ @item %option state_type = NAME
+ @cindex state_type option
+ Specify the name of the state type. The state type is generated
+ by treecc to perform centralised memory management and reentrancy
+ support. The default value is @samp{YYNODESTATE}. If the output language
+ uses factories, then this will also be the name of the factory
+ base class.
+
+ @item %option namespace = NAME
+ @cindex namespace option
+ Specify the namespace to write definitions to in the output
+ source files. This option is ignored when the output language
+ is C.
+
+ @item %option package = NAME
+ @cindex package option
+ Same as @samp{%option namespace = NAME}. Provided because @samp{package}
+ is more natural for Java programmers.
+
+ @item %option base = NUM
+ @cindex base option
+ Specify the numeric base to use for allocating numeric values to
+ node types. By default, node type allocation begins at 1.
+
+ @item %option lang = LANGUAGE
+ @cindex lang option
+ Specify the output language. Must be one of @code{"C"}, @code{"C++"},
+ @code{"Java"}, or @code{"C#"}. The default is @code{"C"}.
+
+ @item %option block_size = NUM
+ @cindex block_size option
+ Specify the size of the memory blocks to use in C and C++ node allocators.
+
+ @item %option strip_filenames
+ @cindex strip_filenames option
+ Strip filenames down to their base name in @code{#line} directives.
+ i.e. strip off the directory component. This can be helpful in
+ combination with the @code{%include %readonly} command when
+ treecc input files may processed from different directories,
+ causing common output files to change unexpectedly.
+
+ @item %option no_strip_filenames
+ @cindex no_strip_filenames option
+ Don't strip filenames in @code{#line} directives. (*)
+
+ @item %option internal_access
+ @cindex internal_access option
+ Use @code{internal} as the access mode for classes in C#, rather than
+ @code{public}.
+
+ @item %option public_access
+ @cindex public_access option
+ Use @code{public} as the access mode for classes in C#, rather than
+ @code{internal}. (*)
+
+ @item %option print_lines
+ @cindex print_lines option
+ Print @code{#line} markers in languages that use them. (*)
+
+ @item %option no_print_lines
+ @cindex no_print_lines option
+ Do not print @code{#line} markers, even in languages that normally
+ use them.
+
+ @item %option allocator
+ @cindex allocator option
+ Use treecc's standard node allocator for C and C++. This option has
+ no effect for other output languages. (*)
+
+ @item %option no_allocator
+ @cindex no_allocator option
+ Do not use treecc's standard node allocator for C and C++. This can be
+ useful when the programmer wants to redirect node allocation to their
+ own routines.
+
+ @item %option gc_allocator
+ @cindex gc_allocator option
+ Use libgc as a garbage-collecting node allocator for C and C++. This
+ option has no effect for other output languages.
+
+ @item %option no_gc_allocator
+ @cindex no_gc_allocator option
+ Do not use libgc as a garbage-collecting node allocator for C and C++. (*)
+
+ @item %option base_type
+ @cindex base_type option
+ Specify the base type for the root node of the treecc node heirarchy.
+ The default is no base type.
+
+ @end table
+
+ @c -----------------------------------------------------------------------
+
+ @node Literal Code, Changing Files, Options, Syntax
+ @section Literal code declarations
+ @cindex Literal code
+
+ Sometimes it is necessary to embed literal code within output @samp{.h}
+ and source files. Usually this is to @samp{#include} definitions
+ from other files, or to define functions that cannot be easily expressed
+ as operations.
+
+ A literal code block is specified by enclosing it in @samp{%@{} and
+ @samp{%@}}. The block can also be prefixed with the following flags:
+
+ @table @samp
+ @item %decls
+ @cindex %decls keyword
+ Write the literal code to the currently active declaration header file,
+ instead of the source file.
+
+ @item %both
+ @cindex %both keyword
+ Write the literal code to both the currently active declaration header file
+ and the currently active source file.
+
+ @item %end
+ @cindex %end keyword
+ Write the literal code to the end of the file, instead of the beginning.
+ @end table
+
+ Another form of literal code block is one which begins with @samp{%%} and
+ extends to the end of the current input file. This form implicitly has
+ the @samp{%end} flag.
+
+ @c -----------------------------------------------------------------------
+
+ @node Changing Files, Line Tracking, Literal Code, Syntax
+ @section Changing input and output files
+ @cindex Changing files
+
+ Most treecc compiler definitions will be too large to be manageable
+ in a single input file. They also will be too large to write to a
+ single output file, because that may overload the source language
+ compiler.
+
+ Multiple input files can be specified on the command-line, or
+ they can be explicitly included by other input files with
+ the following declarations:
+
+ @table @samp
+ @item %include [ %readonly ] FILENAME
+ @cindex include declaration
+ @cindex %include keyword
+ @cindex %readonly keyword
+ Include the contents of the specified file at the current point
+ within the current input file. @samp{FILENAME} is interpreted
+ relative to the name of the current input file.
+
+ If the @samp{%readonly} keyword is supplied, then any output
+ files that are generated by the included file must be read-only.
+ That is, no changes are expected by performing the inclusion.
+
+ The @samp{%readonly} keyword is useful for building compilers
+ in layers. The programmer may group a large number of useful
+ node types and operations together that are independent of the
+ particulars of a given language. The programmer then defines
+ language-specific compilers that "inherit" the common definitions.
+
+ Read-only inclusions ensure that any extensions that are added
+ by the language-specific parts do not "leak" into the common code.
+ @end table
+
+ Output files can be changed using the follow declarations:
+
+ @table @samp
+ @item %header FILENAME
+ @cindex header declaration
+ @cindex %header keyword
+ Change the currently active declaration header file to @samp{FILENAME},
+ which is interpreted relative to the current input file. This option
+ has no effect for languages without header files (Java and C#).
+
+ Any node types and operations that are defined after a @samp{%header}
+ declaration will be declared in @samp{FILENAME}.
+
+ @item %output FILENAME
+ @cindex output declaration
+ @cindex %output keyword
+ Change the currently active source file to @samp{FILENAME},
+ which is interpreted relative to the current input file. This option
+ has no effect for languages that require a single class per file (Java).
+
+ Any node types and operations that are defined after a @samp{%header}
+ declaration will have their implementations placed in @samp{FILENAME}.
+
+ @item %outdir DIRNAME
+ @cindex outdir declaration
+ @cindex %outdir keyword
+ Change the output source directory to @samp{DIRNAME}. This is only
+ used for Java, which requires that a single file be used for each class.
+ All classes are written to the specified directory. By default,
+ @samp{DIRNAME} is the current directory where treecc was invoked.
+ @end table
+
+ When treecc generates the output source code, it must insert several
+ common house-keeping functions and classes into the code. By default,
+ these are written to the first header and source files. This can
+ be changed with the @samp{%common} declaration:
+
+ @table @samp
+ @item %common
+ @cindex common declaration
+ @cindex %common keyword
+ Output the common house-keeping code to the currently active
+ declaration header file and the currently active source file.
+ This is typically used as follows:
+
+ @example
+ %header "common.h"
+ %output "common.c"
+ %common
+ @end example
+ @end table
+
+ @c -----------------------------------------------------------------------
+
+ @node Line Tracking, Output APIs, Changing Files, Top
+ @chapter Tracking line numbers in source files
+ @cindex Line tracking
+
+ When compilers emit error messages to the programmer, it is generally
+ a good idea to indicate which file and which line gave rise to the
+ error. Syntax errors can be emitted fairly easily because the parser
+ usually has access to the current line number. However, semantic
+ errors are harder to report because the parser may no longer be
+ active when the error is detected.
+
+ Treecc can generate code that automatically keeps track of what line
+ in the source file was active when a node is created. Every node
+ has two extra private fields that specify the name of the file and the
+ line number. Semantic analysis routines can query this information
+ when reporting errors.
+
+ Because treecc is not aware of how to obtain this information, the
+ programmer must supply some additional functions. @xref{Output APIs},
+ for more information.
+
+ @xref{Output APIs}, for more information.
+
+ @c -----------------------------------------------------------------------
+
+ @node Output APIs, C Language, Line Tracking, Top
+ @chapter API's available in the generated output
+ @cindex Output APIs
+
+ The source code that is generated by treecc exports a number of
+ application programmer interfaces (API's) to the programmer. These
+ can be used elsewhere in the compiler implementation to manipulate
+ abstract syntax trees. The following sections describe the API's
+ for each of the output languages.
+
+ @menu
+ * C Language:: C Language API's
+ * C++ Language:: C++ Language API's
+ * Java Language:: Java Language API's
+ * C# Language:: C# Language API's
+ * Ruby Language:: Ruby Language API's
+ @end menu
+
+ @c -----------------------------------------------------------------------
+
+ @node C Language, C++ Language, Output APIs, Output APIs
+ @section C Language APIs
+ @cindex C APIs
+
+ In the C output language, each node type is converted into a @samp{typedef}
+ that contains the node's fields, and the fields of its ancestor node
+ types. The following example demonstrates how treecc node declarations
+ are converted into C source code:
+
+ @example
+ %node expression %abstract %typedef =
+ @{
+ %nocreate type_code type;
+ @}
+ %node binary expression %abstract =
+ @{
+ expression *expr1;
+ expression *expr2;
+ @}
+ %node plus binary
+ @end example
+
+ becomes:
+
+ @example
+ typedef struct expression__ expression;
+ typedef struct binary__ binary;
+ typedef struct plus__ plus;
+
+ struct expression__ @{
+ const struct expression_vtable__ *vtable__;
+ int kind__;
+ char *filename__;
+ long linenum__;
+ type_code type;
+ @};
+ struct binary__ @{
+ const struct binary_vtable__ *vtable__;
+ int kind__;
+ char *filename__;
+ long linenum__;
+ type_code type;
+ expression * expr1;
+ expression * expr2;
+ @};
+ struct plus__ @{
+ const struct plus_vtable__ *vtable__;
+ int kind__;
+ char *filename__;
+ long linenum__;
+ type_code type;
+ expression * expr1;
+ expression * expr2;
+ @};
+ @end example
+
+ Programmers should avoid using any identifiers that end in
+ @samp{__}. Such identifiers are reserved for internal use by treecc
+ and its support routines.
+
+ For each non-abstract node type called @samp{NAME}, treecc generates a
+ function called @samp{NAME_create} that creates nodes of that type.
+ The general form of the function's prototype is as follows:
+
+ @example
+ TYPE *NAME_create([YYNODESTATE *state,] PARAMS)
+ @end example
+
+ @table @samp
+ @item TYPE
+ The return node type, which is the nearest ancestor that has the
+ @samp{%typedef} flag.
+
+ @item NAME
+ The name of the node type that is being created.
+
+ @item state
+ The system state, if reentrant code is being generated.
+
+ @item PARAMS
+ The create parameters, consisting of every field that does not
+ have the @samp{%nocreate} flag. The parameters appear in the
+ same order as the fields in the node types, from the top-most
+ ancestor down to the node type itself. For example:
+
+ @example
+ expression *plus_create(expression * expr1, expression * expr2);
+ @end example
+ @end table
+
+ Enumerated types are converted into a C @samp{typedef} with the
+ same name and values:
+
+ @example
+ %enum JavaType =
+ @{
+ JT_BYTE,
+ JT_SHORT,
+ JT_CHAR,
+ JT_INT,
+ JT_LONG,
+ JT_FLOAT,
+ JT_DOUBLE,
+ JT_OBJECT_REF
+ @}
+ @end example
+
+ becomes:
+
+ @example
+ typedef enum
+ @{
+ JT_BYTE,
+ JT_SHORT,
+ JT_CHAR,
+ JT_INT,
+ JT_LONG,
+ JT_FLOAT,
+ JT_DOUBLE,
+ JT_OBJECT_REF
+
+ @} JavaType;
+ @end example
+
+ Virtual operations are converted into C macros that invoke the
+ correct vtable entry on a node type:
+
+ @example
+ %operation %virtual void infer_type(expression *e)
+ @end example
+
+ becomes:
+
+ @example
+ #define infer_type(this__) \
+ ((*(((struct expression_vtable__ *) \
+ ((this__)->vtable__))->infer_type_v__)) \
+ ((expression *)(this__)))
+ @end example
+
+ Calls to @samp{infer_type} can then be made with @samp{infer_type(node)}.
+
+ Non-virtual operations are converted into C functions:
+
+ @example
+ %operation void infer_type(expression *e)
+ @end example
+
+ becomes:
+
+ @example
+ extern void infer_type(expression *e);
+ @end example
+
+ Because virtual and non-virtual operations use a similar call syntax,
+ it is very easy to convert a virtual operation into a non-virtual
+ operation when the output language is C. This isn't possible with
+ the other output languages.
+
+ Other house-keeping tasks are performed by the following functions
+ and macros. Some of these must be supplied by the programmer.
+ The @samp{state} parameter is required only if a reentrant compiler is
+ being built.
+
+ @table @code
+ @item int yykind(ANY *node)
+ @cindex yykind macro
+ Gets the numeric kind value associated with a particular node.
+ The kind value for node type @samp{NAME} is called @samp{NAME_kind}.
+
+ @item const char *yykindname(ANY *node)
+ @cindex yykindname macro
+ Gets the name of the node kind associated with a particular node.
+ This may be helpful for debugging and logging code.
+
+ @item int yyisa(ANY *node, type)
+ @cindex yyisa macro
+ Determines if @samp{node} is an instance of the node type @samp{type}.
+
+ @item char *yygetfilename(ANY *node)
+ @cindex yygetfilename macro
+ Gets the filename corresponding to where @samp{node} was created
+ during parsing. This macro is only generated if @samp{%option track_lines}
+ was specified.
+
+ @item long yygetlinenum(ANY *node)
+ @cindex yygetlinenum macro
+ Gets the line number corresponding to where @samp{node} was created
+ during parsing. This macro is only generated if @samp{%option track_lines}
+ was specified.
+
+ @item void yysetfilename(ANY *node, char *value)
+ @cindex yysetfilename macro
+ Sets the filename associated with @samp{node} to @samp{value}. The
+ string is not copied, so @samp{value} must persist for the lifetime
+ of the node. This macro will rarely be required, unless a node
+ corresponds to a different line than the current parse line. This
+ macro is only generated if @samp{%option track_lines} was specified.
+
+ @item void yysetlinenum(ANY *node, long value)
+ @cindex yysetlinenum macro
+ Sets the line number associated with @samp{node} to @samp{value}.
+ This macro will rarely be required, unless a node corresponds to a
+ different line than the current parse line. This macro is only
+ generated if @samp{%option track_lines} was specified.
+
+ @item char *yycurrfilename([YYNODESTATE *state])
+ @cindex yycurrfilename function
+ Get the name of the current input file from the parser. The pointer
+ that is returned from this function is stored as-is: the string is
+ not copied. Therefore, the value must persist for at least as long
+ as the node will persist. This function must be supplied by the programmer
+ if @samp{%option track_lines} was specified.
+
+ @item long yycurrlinenum([YYNODESTATE *state])
+ @cindex yycurrlinenum function
+ Get the number of the current input line from the parser. This
+ function must be supplied by the programmer if @samp{%option track_lines}
+ was specified.
+
+ @item void yynodeinit([YYNODESTATE *state])
+ @cindex yynodeinit function
+ Initializes the node memory manager. If the system is reentrant, then
+ the node memory manager is @samp{state}. Otherwise a global node
+ memory manager is used.
+
+ @item void *yynodealloc([YYNODESTATE *state,] unsigned int size)
+ @cindex yynodealloc function
+ Allocates a block of memory of @samp{size} bytes in size from the
+ node memory manager. This function is called automatically from
+ the node-specific @samp{*_create} functions. The programmer will
+ not normally need to call this function.
+
+ This function will return @code{NULL} if the system is out of
+ memory, or if @samp{size} is too large to be allocated within
+ the node memory manager. If the system is out of memory, then
+ @samp{yynodealloc} will call @samp{yynodefailed} prior to
+ returning @code{NULL}.
+
+ @item int yynodepush([YYNODESTATE *state])
+ @cindex yynodepush function
+ Pushes the current node memory manager position. The next time
+ @code{yynodepop} is called, the node memory manager will reset to
+ the pushed position. This function returns zero if the system
+ is out of memory.
+
+ @item void yynodepop([YYNODESTATE *state])
+ @cindex yynodepop function
+ Pops the current node memory manager position. This function has
+ no effect if @code{yynodepush} was not called previously.
+
+ The @code{yynodepush} and @code{yynodepop} functions can be used
+ to perform a simple kind of garbage collection on nodes. When
+ the parser enters a scope, it pushes the node memory manager
+ position. After all definitions in the scope have been dealt
+ with, the parser pops the node memory manager to reclaim all
+ of the memory used.
+
+ @item void yynodeclear([YYNODESTATE *state])
+ @cindex yynodeclear function
+ Clears the entire node memory manager and returns it to the
+ state it had after calling @code{yynodeinit}. This is typically
+ used upon program shutdown to free all remaining node memory.
+
+ @item void yynodefailed([YYNODESTATE *state])
+ @cindex yynodefailed function
+ Called when @code{yynodealloc} or @code{yynodepush} detects that
+ the system is out of memory. This function must be supplied by
+ the programmer. The programmer may choose to exit to program
+ when the system is out of memory; in which case @code{yynodealloc}
+ will never return @code{NULL}.
+ @end table
+
+ @c -----------------------------------------------------------------------
+
+ @node C++ Language, Java Language, C Language, Output APIs
+ @section C++ Language APIs
+ @cindex C++ APIs
+
+ In the C++ output language, each node type is converted into a @samp{class}
+ that contains the node's fields, virtual operations, and other house-keeping
+ definitions. The following example demonstrates how treecc node declarations
+ are converted into C++ source code:
+
+ @example
+ %node expression %abstract %typedef =
+ @{
+ %nocreate type_code type;
+ @}
+ %node binary expression %abstract =
+ @{
+ expression *expr1;
+ expression *expr2;
+ @}
+ %node plus binary
+ @end example
+
+ becomes:
+
+ @example
+ class expression
+ @{
+ protected:
+
+ int kind__;
+ char *filename__;
+ long linenum__;
+
+ public:
+
+ int getKind() const @{ return kind__; @}
+ const char *getFilename() const @{ return filename__; @}
+ int getLinenum() const @{ return linenum__; @}
+ void setFilename(char *filename) @{ filename__ = filename; @}
+ void setLinenum(long linenum) @{ linenum__ = linenum; @}
+
+ void *operator new(size_t);
+ void operator delete(void *, size_t);
+
+ protected:
+
+ expression();
+
+ public:
+
+ type_code type;
+
+ virtual int isA(int kind) const;
+ virtual const char *getKindName() const;
+
+ protected:
+
+ virtual ~expression();
+
+ @};
+
+ class binary : public expression
+ @{
+ protected:
+
+ binary(expression * expr1, expression * expr2);
+
+ public:
+
+ expression * expr1;
+ expression * expr2;
+
+ virtual int isA(int kind) const;
+ virtual const char *getKindName() const;
+
+ protected:
+
+ virtual ~binary();
+
+ @};
+
+ class plus : public binary
+ @{
+ public:
+
+ plus(expression * expr1, expression * expr2);
+
+ public:
+
+ virtual int isA(int kind) const;
+ virtual const char *getKindName() const;
+
+ protected:
+
+ virtual ~plus();
+
+ @};
+ @end example
+
+ The following standard methods are available on every node type:
+
+ @table @code
+ @item int getKind()
+ @cindex getKind method (C++)
+ Gets the numeric kind value associated with a particular node.
+ The kind value for node type @samp{NAME} is called @samp{NAME_kind}.
+
+ @item virtual const char *getKindName()
+ @cindex getKindName method (C++)
+ Gets the name of the node kind associated with a particular node.
+ This may be helpful for debugging and logging code.
+
+ @item virtual int isA(int kind)
+ @cindex isA method (C++)
+ Determines if the node is a member of the node type that corresponds
+ to the numeric kind value @samp{kind}.
+
+ @item const char *getFilename()
+ @cindex getFilename method (C++)
+ Gets the filename corresponding to where the node was created
+ during parsing. This method is only generated if @samp{%option track_lines}
+ was specified.
+
+ @item long getLinenum()
+ @cindex getLinenum method (C++)
+ Gets the line number corresponding to where the node was created
+ during parsing. This method is only generated if @samp{%option track_lines}
+ was specified.
+
+ @item void setFilename(char *value)
+ @cindex setFilename method (C++)
+ Sets the filename associated with the node to @samp{value}. The
+ string is not copied, so @samp{value} must persist for the lifetime
+ of the node. This method will rarely be required, unless a node
+ corresponds to a different line than the current parse line. This
+ method is only generated if @samp{%option track_lines} was specified.
+
+ @item void setLinenum(long value)
+ @cindex setLinenum method (C++)
+ Sets the line number associated with the node to @samp{value}.
+ This method will rarely be required, unless a node corresponds to a
+ different line than the current parse line. This method is only
+ generated if @samp{%option track_lines} was specified.
+ @end table
+
+ If the generated code is non-reentrant, then the constructor for the
+ class can be used to construct nodes of the specified node type. The
+ constructor parameters are the same as the fields within the node type's
+ definition, except for @samp{%nocreate} fields.
+
+ If the generated code is reentrant, then nodes cannot be constructed
+ using the C++ @samp{new} operator. The @samp{*Create} methods
+ on the @samp{YYNODESTATE} factory class must be used instead.
+
+ The @samp{YYNODESTATE} class contains a number of house-keeping methods
+ that are used to manage nodes:
+
+ @table @code
+ @item static YYNODESTATE *getState()
+ @cindex getState method (C++)
+ Gets the global @samp{YYNODESTATE} instance that is being used by
+ non-reentrant code. If an instance has not yet been created,
+ this method will create one.
+
+ When using non-reentrant code, the programmer will normally subclass
+ @samp{YYNODESTATE}, override some of the methods below, and then
+ construct an instance of the subclass. This constructed instance
+ will then be returned by future calls to @samp{getState}.
+
+ @item void *alloc(size_t size)
+ @cindex alloc method (C++)
+ Allocates a block of memory of @samp{size} bytes in size from the
+ node memory manager. This function is called automatically from
+ the node-specific constructors and @samp{*Create} methods. The programmer
+ will not normally need to call this function.
+
+ This function will return @code{NULL} if the system is out of
+ memory, or if @samp{size} is too large to be allocated within
+ the node memory manager. If the system is out of memory, then
+ @samp{alloc} will call @samp{failed} prior to returning @code{NULL}.
+
+ @item int push()
+ @cindex push method (C++)
+ Pushes the current node memory manager position. The next time
+ @code{pop} is called, the node memory manager will reset to
+ the pushed position. This function returns zero if the system
+ is out of memory.
+
+ @item void pop()
+ @cindex pop method (C++)
+ Pops the current node memory manager position. This function has
+ no effect if @code{push} was not called previously.
+
+ The @code{push} and @code{pop} methods can be used
+ to perform a simple kind of garbage collection on nodes. When
+ the parser enters a scope, it pushes the node memory manager
+ position. After all definitions in the scope have been dealt
+ with, the parser pops the node memory manager to reclaim all
+ of the memory used.
+
+ @item void clear()
+ @cindex clear method (C++)
+ Clears the entire node memory manager and returns it to the
+ state it had after construction.
+
+ @item virtual void failed()
+ @cindex failed method (C++)
+ Called when @code{alloc} or @code{push} detects that
+ the system is out of memory. This method is typically
+ overridden by the programmer in subclasses. The programmer may
+ choose to exit to program when the system is out of memory; in
+ which case @code{alloc} will never return @code{NULL}.
+
+ @item virtual char *currFilename()
+ @cindex currFilename method (C++)
+ Get the name of the current input file from the parser. The pointer
+ that is returned from this function is stored as-is: the string is
+ not copied. Therefore, the value must persist for at least as long
+ as the node will persist. This method is usually overrriden by
+ the programmer in subclasses if @samp{%option track_lines} was specified.
+
+ @item virtual long currLinenum()
+ @cindex currLinenum method (C++)
+ Get the number of the current input line from the parser. This
+ method is usually overridden by the programmer in subclasses
+ if @samp{%option track_lines} was specified.
+ @end table
+
+ The programmer will typically subclass @samp{YYNODESTATE} to provide
+ additional functionality, and then create an instance of this class
+ to act as the node memory manager and node creation factory.
+
+ @c -----------------------------------------------------------------------
+
+ @node Java Language, C# Language, C++ Language, Output APIs
+ @section Java Language APIs
+ @cindex Java APIs
+
+ In the Java output language, each node type is converted into a @samp{class}
+ that contains the node's fields, virtual operations, and other house-keeping
+ definitions. The following example demonstrates how treecc node declarations
+ are converted into Java source code:
+
+ @example
+ %node expression %abstract %typedef =
+ @{
+ %nocreate type_code type;
+ @}
+ %node binary expression %abstract =
+ @{
+ expression expr1;
+ expression expr2;
+ @}
+ %node plus binary
+ @end example
+
+ becomes:
+
+ @example
+ public class expression
+ @{
+ protected int kind__;
+ protected String filename__;
+ protected long linenum__;
+
+ public int getKind() @{ return kind__; @}
+ public String getFilename() @{ return filename__; @}
+ public long getLinenum() const @{ return linenum__; @}
+ public void setFilename(String filename) @{ filename__ = filename; @}
+ public void setLinenum(long linenum) @{ linenum__ = linenum; @}
+
+ public static final int KIND = 1;
+
+ public type_code type;
+
+ protected expression()
+ @{
+ this.kind__ = KIND;
+ this.filename__ = YYNODESTATE.getState().currFilename();
+ this.linenum__ = YYNODESTATE.getState().currLinenum();
+ @}
+
+ public int isA(int kind)
+ @{
+ if(kind == KIND)
+ return 1;
+ else
+ return 0;
+ @}
+
+ public String getKindName()
+ @{
+ return "expression";
+ @}
+ @}
+
+ public class binary extends expression
+ @{
+ public static final int KIND = 2;
+
+ public expression expr1;
+ public expression expr2;
+
+ protected binary(expression expr1, expression expr2)
+ @{
+ super();
+ this.kind__ = KIND;
+ this.expr1 = expr1;
+ this.expr2 = expr2;
+ @}
+
+ public int isA(int kind)
+ @{
+ if(kind == KIND)
+ return 1;
+ else
+ return super.isA(kind);
+ @}
+
+ public String getKindName()
+ @{
+ return "binary";
+ @}
+ @}
+
+ public class plus extends binary
+ @{
+ public static final int KIND = 3;
+
+ public plus(expression expr1, expression expr2)
+ @{
+ super(expr1, expr2);
+ this.kind__ = KIND;
+ @}
+
+ public int isA(int kind)
+ @{
+ if(kind == KIND)
+ return 1;
+ else
+ return super.isA(kind);
+ @}
+
+ public String getKindName()
+ @{
+ return "plus";
+ @}
+ @}
+ @end example
+
+ The following standard members are available on every node type:
+
+ @table @code
+ @item int KIND
+ @cindex KIND field (Java)
+ The kind value for the node type corresponding to this class.
+
+ @item int getKind()
+ @cindex getKind method (Java)
+ Gets the numeric kind value associated with a particular node.
+ The kind value for node type @samp{NAME} is called @samp{NAME.KIND}.
+
+ @item String getKindName()
+ @cindex getKindName method (Java)
+ Gets the name of the node kind associated with a particular node.
+ This may be helpful for debugging and logging code.
+
+ @item int isA(int kind)
+ @cindex isA method (Java)
+ Determines if the node is a member of the node type that corresponds
+ to the numeric kind value @samp{kind}.
+
+ @item String getFilename()
+ @cindex getFilename method (Java)
+ Gets the filename corresponding to where the node was created
+ during parsing. This method is only generated if @samp{%option track_lines}
+ was specified.
+
+ @item long getLinenum()
+ @cindex getLinenum method (Java)
+ Gets the line number corresponding to where the node was created
+ during parsing. This method is only generated if @samp{%option track_lines}
+ was specified.
+
+ @item void setFilename(String value)
+ @cindex setFilename method (Java)
+ Sets the filename associated with the node to @samp{value}.
+ This method will rarely be required, unless a node corresponds to
+ a different line than the current parse line. This method is only
+ generated if @samp{%option track_lines} was specified.
+
+ @item void setLinenum(long value)
+ @cindex setLinenum method (Java)
+ Sets the line number associated with the node to @samp{value}.
+ This method will rarely be required, unless a node corresponds to a
+ different line than the current parse line. This method is only
+ generated if @samp{%option track_lines} was specified.
+ @end table
+
+ If the generated code is non-reentrant, then the constructor for the
+ class can be used to construct nodes of the specified node type. The
+ constructor parameters are the same as the fields within the node type's
+ definition, except for @samp{%nocreate} fields.
+
+ If the generated code is reentrant, then nodes cannot be constructed
+ using the Java @samp{new} operator. The @samp{*Create} methods
+ on the @samp{YYNODESTATE} factory class must be used instead.
+
+ Enumerated types are converted into a Java @samp{class}:
+
+ @example
+ %enum JavaType =
+ @{
+ JT_BYTE,
+ JT_SHORT,
+ JT_CHAR,
+ JT_INT,
+ JT_LONG,
+ JT_FLOAT,
+ JT_DOUBLE,
+ JT_OBJECT_REF
+ @}
+ @end example
+
+ becomes:
+
+ @example
+ public class JavaType
+ @{
+ public static final int JT_BYTE = 0;
+ public static final int JT_SHORT = 1;
+ public static final int JT_CHAR = 2;
+ public static final int JT_INT = 3;
+ public static final int JT_LONG = 4;
+ public static final int JT_FLOAT = 5;
+ public static final int JT_DOUBLE = 6;
+ public static final int JT_OBJECT_REF = 7;
+ @}
+ @end example
+
+ References to enumerated types in fields and operation parameters
+ are replaced with the type @samp{int}.
+
+ Virtual operations are converted into public methods on the Java
+ node classes.
+
+ Non-virtual operations are converted into a static method within
+ a class named for the operation. For example,
+
+ @example
+ %operation void InferType::infer_type(expression e)
+ @end example
+
+ becomes:
+
+ @example
+ public class InferType
+ @{
+ public static void infer_type(expression e)
+ @{
+ ...
+ @}
+ @}
+ @end example
+
+ If the class name (@samp{InferType} in the above example) is omitted,
+ then the name of the operation is used as both the class name and the
+ the method name.
+
+ The @samp{YYNODESTATE} class contains a number of house-keeping methods
+ that are used to manage nodes:
+
+ @table @code
+ @item static YYNODESTATE getState()
+ @cindex getState method (Java)
+ Gets the global @samp{YYNODESTATE} instance that is being used by
+ non-reentrant code. If an instance has not yet been created,
+ this method will create one.
+
+ When using non-reentrant code, the programmer will normally subclass
+ @samp{YYNODESTATE}, override some of the methods below, and then
+ construct an instance of the subclass. This constructed instance
+ will then be returned by future calls to @samp{getState}.
+
+ This method will not be present if a reentrant system is being
+ generated.
+
+ @item String currFilename()
+ @cindex currFilename method (Java)
+ Get the name of the current input file from the parser. This method
+ is usually overrriden by the programmer in subclasses if
+ @samp{%option track_lines} was specified.
+
+ @item long currLinenum()
+ @cindex currLinenum method (Java)
+ Get the number of the current input line from the parser. This
+ method is usually overridden by the programmer in subclasses
+ if @samp{%option track_lines} was specified.
+ @end table
+
+ The programmer will typically subclass @samp{YYNODESTATE} to provide
+ additional functionality, and then create an instance of this class
+ to act as the global state and node creation factory.
+
+ @c -----------------------------------------------------------------------
+
+ @node C# Language, Ruby Language, Java Language, Output APIs
+ @section C# Language APIs
+ @cindex C# APIs
+
+ In the C# output language, each node type is converted into a @samp{class}
+ that contains the node's fields, virtual operations, and other house-keeping
+ definitions. The following example demonstrates how treecc node declarations
+ are converted into C# source code:
+
+ @example
+ %node expression %abstract %typedef =
+ @{
+ %nocreate type_code type;
+ @}
+ %node binary expression %abstract =
+ @{
+ expression expr1;
+ expression expr2;
+ @}
+ %node plus binary
+ @end example
+
+ becomes:
+
+ @example
+ public class expression
+ @{
+ protected int kind__;
+ protected String filename__;
+ protected long linenum__;
+
+ public int getKind() @{ return kind__; @}
+ public String getFilename() @{ return filename__; @}
+ public long getLinenum() const @{ return linenum__; @}
+ public void setFilename(String filename) @{ filename__ = filename; @}
+ public void setLinenum(long linenum) @{ linenum__ = linenum; @}
+
+ public const int KIND = 1;
+
+ public type_code type;
+
+ protected expression()
+ @{
+ this.kind__ = KIND;
+ this.filename__ = YYNODESTATE.getState().currFilename();
+ this.linenum__ = YYNODESTATE.getState().currLinenum();
+ @}
+
+ public virtual int isA(int kind)
+ @{
+ if(kind == KIND)
+ return 1;
+ else
+ return 0;
+ @}
+
+ public virtual String getKindName()
+ @{
+ return "expression";
+ @}
+ @}
+
+ public class binary : expression
+ @{
+ public const int KIND = 2;
+
+ public expression expr1;
+ public expression expr2;
+
+ protected binary(expression expr1, expression expr2)
+ : expression()
+ @{
+ this.kind__ = KIND;
+ this.expr1 = expr1;
+ this.expr2 = expr2;
+ @}
+
+ public override int isA(int kind)
+ @{
+ if(kind == KIND)
+ return 1;
+ else
+ return base.isA(kind);
+ @}
+
+ public override String getKindName()
+ @{
+ return "binary";
+ @}
+ @}
+
+ public class plus : binary
+ @{
+ public const int KIND = 5;
+
+ public plus(expression expr1, expression expr2)
+ : binary(expr1, expr2)
+ @{
+ this.kind__ = KIND;
+ @}
+
+ public override int isA(int kind)
+ @{
+ if(kind == KIND)
+ return 1;
+ else
+ return base.isA(kind);
+ @}
+
+ public override String getKindName()
+ @{
+ return "plus";
+ @}
+ @}
+ @end example
+
+ The following standard members are available on every node type:
+
+ @table @code
+ @item const int KIND
+ @cindex KIND field (C#)
+ The kind value for the node type corresponding to this class.
+
+ @item int getKind()
+ @cindex getKind method (C#)
+ Gets the numeric kind value associated with a particular node.
+ The kind value for node type @samp{NAME} is called @samp{NAME.KIND}.
+
+ @item virtual String getKindName()
+ @cindex getKindName method (C#)
+ Gets the name of the node kind associated with a particular node.
+ This may be helpful for debugging and logging code.
+
+ @item virtual int isA(int kind)
+ @cindex isA method (C#)
+ Determines if the node is a member of the node type that corresponds
+ to the numeric kind value @samp{kind}.
+
+ @item String getFilename()
+ @cindex getFilename method (C#)
+ Gets the filename corresponding to where the node was created
+ during parsing. This method is only generated if @samp{%option track_lines}
+ was specified.
+
+ @item long getLinenum()
+ @cindex getLinenum method (C#)
+ Gets the line number corresponding to where the node was created
+ during parsing. This method is only generated if @samp{%option track_lines}
+ was specified.
+
+ @item void setFilename(String value)
+ @cindex setFilename method (C#)
+ Sets the filename associated with the node to @samp{value}.
+ This method will rarely be required, unless a node corresponds to
+ a different line than the current parse line. This method is only
+ generated if @samp{%option track_lines} was specified.
+
+ @item void setLinenum(long value)
+ @cindex setLinenum method (C#)
+ Sets the line number associated with the node to @samp{value}.
+ This method will rarely be required, unless a node corresponds to a
+ different line than the current parse line. This method is only
+ generated if @samp{%option track_lines} was specified.
+ @end table
+
+ If the generated code is non-reentrant, then the constructor for the
+ class can be used to construct nodes of the specified node type. The
+ constructor parameters are the same as the fields within the node type's
+ definition, except for @samp{%nocreate} fields.
+
+ If the generated code is reentrant, then nodes cannot be constructed
+ using the C# @samp{new} operator. The @samp{*Create} methods
+ on the @samp{YYNODESTATE} factory class must be used instead.
+
+ Enumerated types are converted into a C# @samp{enum} definition:
+
+ @example
+ %enum JavaType =
+ @{
+ JT_BYTE,
+ JT_SHORT,
+ JT_CHAR,
+ JT_INT,
+ JT_LONG,
+ JT_FLOAT,
+ JT_DOUBLE,
+ JT_OBJECT_REF
+ @}
+ @end example
+
+ becomes:
+
+ @example
+ public enum JavaType
+ @{
+ JT_BYTE,
+ JT_SHORT,
+ JT_CHAR,
+ JT_INT,
+ JT_LONG,
+ JT_FLOAT,
+ JT_DOUBLE,
+ JT_OBJECT_REF,
+ @}
+ @end example
+
+ Virtual operations are converted into public virtual methods on the C#
+ node classes.
+
+ Non-virtual operations are converted into a static method within
+ a class named for the operation. For example,
+
+ @example
+ %operation void InferType::infer_type(expression e)
+ @end example
+
+ becomes:
+
+ @example
+ public class InferType
+ @{
+ public static void infer_type(expression e)
+ @{
+ ...
+ @}
+ @}
+ @end example
+
+ If the class name (@samp{InferType} in the above example) is omitted,
+ then the name of the operation is used as both the class name and the
+ the method name.
+
+ The @samp{YYNODESTATE} class contains a number of house-keeping methods
+ that are used to manage nodes:
+
+ @table @code
+ @item static YYNODESTATE getState()
+ @cindex getState method (C#)
+ Gets the global @samp{YYNODESTATE} instance that is being used by
+ non-reentrant code. If an instance has not yet been created,
+ this method will create one.
+
+ When using non-reentrant code, the programmer will normally subclass
+ @samp{YYNODESTATE}, override some of the methods below, and then
+ construct an instance of the subclass. This constructed instance
+ will then be returned by future calls to @samp{getState}.
+
+ This method will not be present if a reentrant system is being
+ generated.
+
+ @item virtual String currFilename()
+ @cindex currFilename method (C#)
+ Get the name of the current input file from the parser. This method
+ is usually overrriden by the programmer in subclasses if
+ @samp{%option track_lines} was specified.
+
+ @item virtual long currLinenum()
+ @cindex currLinenum method (C#)
+ Get the number of the current input line from the parser. This
+ method is usually overridden by the programmer in subclasses
+ if @samp{%option track_lines} was specified.
+ @end table
+
+ The programmer will typically subclass @samp{YYNODESTATE} to provide
+ additional functionality, and then create an instance of this class
+ to act as the global state and node creation factory.
+
+ @c -----------------------------------------------------------------------
+
+ @node Ruby Language, Full Expression Example, C# Language, Output APIs
+ @section Ruby Language APIs
+ @cindex Ruby APIs
+
+ In the Ruby output language, each node type is converted into a
+ @samp{class} that contains the node's fields, operations, and other
+ house-keeping definitions. The following example demonstrates how
+ treecc node declarations are converted into Ruby source code:
+
+ @example
+ %node expression %abstract %typedef =
+ @{
+ %nocreate type_code type;
+ @}
+ %node binary expression %abstract =
+ @{
+ expression expr1;
+ expression expr2;
+ @}
+ %node plus binary
+ @end example
+
+ becomes:
+
+ @example
+ class YYNODESTATE
+
+ @@@@state = nil
+
+ def YYNODESTATE.state
+ return @@@@state unless @@@@state.nil?
+ @@@@state = YYNODESTATE.new()
+ return @@@@state
+ end
+
+ def intialize
+ @@@@state = self
+ end
+
+ def currFilename
+ return nil
+ end
+
+ def currLinenum
+ return 0
+ end
+ end
+
+ class Expression
+ protected
+ attr_reader :kind
+ public
+
+ attr_accessor :Linenum, :Filename
+
+ attr_accessor :type
+
+ KIND = 1
+
+ def initialize()
+ @@kind = KIND
+ @@Filename = YYNODESTATE.state.currFilename()
+ @@Linenum = YYNODESTATE.state.currLinenum()
+ end
+
+ def isA(kind)
+ if(@@kind == KIND) then
+ return true
+ else
+ return 0
+ end
+ end
+
+ def KindName
+ return "Expression"
+ end
+
+ end
+
+ class Binary < Expression
+
+ attr_accessor :expr1
+ attr_accessor :expr2
+
+ KIND = 2
+
+ def initialize(expr1, expr2)
+ super(expr1, expr2)
+ @@kind = KIND
+ self.expr1 = expr1
+ self.expr2 = expr2
+ end
+
+ def isA(kind)
+ if(@@kind == Kind) then
+ return true
+ else
+ return super(kind)
+ end
+ end
+
+ def KindName
+ return "Binary"
+ end
+
+ end
+
+ class Plus < Binary
+
+ KIND = 3
+
+ def initialize(expr1, expr2)
+ super(expr1, expr2expr1, expr2)
+ @@kind = KIND
+ end
+
+ def isA(kind)
+ if(@@kind == KIND) then
+ return true
+ else
+ return super(kind)
+ end
+ end
+
+ def KindName
+ return "Plus"
+ end
+
+ end
+ @end example
+
+ The following standard members are available on every node type:
+
+ @table @code
+ @item KIND
+ @cindex KIND field (Ruby)
+ The kind value for the node type corresponding to this class.
+ The kind value for node type @samp{NAME} is called @samp{NAME::KIND}.
+
+ @item KindName
+ @cindex KindName field (Ruby)
+ The name of the node kind associated with a particular node. This may
+ be helpful for debugging and logging code.
+
+ @item isA(int kind)
+ @cindex isA method (Ruby)
+ Determines if the node is a member of the node type that corresponds
+ to the numeric kind value @samp{kind}.
+
+ @item Filename
+ @cindex Filename field (Ruby)
+ The filename corresponding to where the node was created during parsing.
+ This method is only generated if @samp{%option track_lines} was
+ specified.
+
+ @item Linenum()
+ @cindex Linenum field (Ruby)
+ The line number corresponding to where the node was created during
+ parsing. This method is only generated if @samp{%option track_lines}
+ was specified.
+
+ @end table
+
+ @c Don't know if this is true for ruby
+ @ignore
+ If the generated code is non-reentrant, then the constructor for the
+ class can be used to construct nodes of the specified node type. The
+ constructor parameters are the same as the fields within the node type's
+ definition, except for @samp{%nocreate} fields.
+
+ If the generated code is reentrant, then nodes cannot be constructed
+ using the C# @samp{new} operator. The @samp{*Create} methods
+ on the @samp{YYNODESTATE} factory class must be used instead.
+ @end ignore
+
+ Enumerated types are converted into a Ruby @samp{class} definition:
+
+ @example
+ %enum JavaType =
+ @{
+ JT_BYTE,
+ JT_SHORT,
+ JT_CHAR,
+ JT_INT,
+ JT_LONG,
+ JT_FLOAT,
+ JT_DOUBLE,
+ JT_OBJECT_REF
+ @}
+ @end example
+
+ becomes:
+
+ @example
+
+ class JavaType
+ JT_BYTE = 0
+ JT_SHORT = 1
+ JT_CHAR = 2
+ JT_INT = 3
+ JT_LONG = 4
+ JT_FLOAT = 5
+ JT_DOUBLE = 6
+ JT_OBJECT_REF = 7
+ end
+
+ @end example
+
+ @c
+ Virtual operations are converted into public methods on the Ruby
+ node classes.
+
+ Non-virtual operations are converted into a class method within
+ a class named for the operation. For example,
+
+ @example
+ %operation void InferType::infer_type(expression e)
+ @end example
+
+ becomes:
+
+ @example
+ class InferType
+ def InferType.infer_type(expression e)
+ ...
+ end
+ end
+ @end example
+
+ If the class name (@samp{InferType} in the above example) is omitted,
+ then the name of the operation is used as both the class name and the
+ the method name. You then get a method with a name starting with an
+ uppercase letter. However, Ruby methods start with lowercase methods.
+ So never forget the class name.
+
+ The @samp{YYNODESTATE} class contains a number of house-keeping methods
+ that are used to manage nodes:
+
+ @table @code
+ @item YYNODESTATE::state()
+ @cindex state field (Ruby)
+ Gets the global @samp{YYNODESTATE} instance that is being used by
+ non-reentrant code. If an instance has not yet been created,
+ this method will create one.
+
+ @c Don't know if the following is correct
+ @ignore
+
+ When using non-reentrant code, the programmer will normally subclass
+ @samp{YYNODESTATE}, override some of the methods below, and then
+ construct an instance of the subclass. This constructed instance
+ will then be returned by future calls to @samp{getState}.
+
+ This method will not be present if a reentrant system is being
+ generated.
+
+ @end ignore
+
+ @item currFilename
+ @cindex currFilename field (Ruby)
+ The name of the current input file from the parser. This fields
+ accessor method is usually overrriden by the programmer in subclasses if
+ @samp{%option track_lines} was specified.
+
+ @item currLinenum
+ @cindex currLinenum field (Ruby)
+ The number of the current input line from the parser. This fields
+ accessor method is usually overridden by the programmer in subclasses if
+ @samp{%option track_lines} was specified.
+ @end table
+
+ The programmer will typically subclass @samp{YYNODESTATE} to provide
+ additional functionality, and then create an instance of this class
+ to act as the global state and node creation factory.
+
+ @c -----------------------------------------------------------------------
+
+ @node Full Expression Example, EBNF Syntax, Ruby Language, Top
+ @appendix Full expression example code
+ @cindex Full expression example
+
+ The full treecc input file for the expression example is as follows:
+
+ @example
+ %enum type_code =
+ @{
+ int_type,
+ float_type
+ @}
+
+ %node expression %abstract %typedef =
+ @{
+ %nocreate type_code type = @{int_type@};
+ @}
+
+ %node binary expression %abstract =
+ @{
+ expression *expr1;
+ expression *expr2;
+ @}
+
+ %node unary expression %abstract =
+ @{
+ expression *expr;
+ @}
+
+ %node intnum expression =
+ @{
+ int num;
+ @}
+
+ %node floatnum expression =
+ @{
+ float num;
+ @}
+
+ %node plus binary
+ %node minus binary
+ %node multiply binary
+ %node divide binary
+ %node power binary
+ %node negate unary
+
+ %operation void infer_type(expression *e)
+
+ infer_type(binary)
+ @{
+ infer_type(e->expr1);
+ infer_type(e->expr2);
+
+ if(e->expr1->type == float_type || e->expr2->type == float_type)
+ @{
+ e->type = float_type;
+ @}
+ else
+ @{
+ e->type = int_type;
+ @}
+ @}
+
+ infer_type(unary)
+ @{
+ infer_type(e->expr);
+ e->type = e->expr->type;
+ @}
+
+ infer_type(intnum)
+ @{
+ e->type = int_type;
+ @}
+
+ infer_type(floatnum)
+ @{
+ e->type = float_type;
+ @}
+
+ infer_type(power)
+ @{
+ infer_type(e->expr1);
+ infer_type(e->expr2);
+
+ if(e->expr2->type != int_type)
+ @{
+ error("second argument to `^' is not an integer");
+ @}
+
+ e->type = e->expr1->type;
+ @}
+ @end example
+
+ The full yacc grammar is as follows:
+
+ @example
+ %union @{
+ expression *node;
+ int inum;
+ float fnum;
+ @}
+
+ %token INT FLOAT
+
+ %type <node> expr
+ %type <inum> INT
+ %type <fnum> FLOAT
+
+ %%
+
+ expr: INT @{ $$ = intnum_create($1); @}
+ | FLOAT @{ $$ = floatnum_create($1); @}
+ | '(' expr ')' @{ $$ = $2; @}
+ | expr '+' expr @{ $$ = plus_create($1, $3); @}
+ | expr '-' expr @{ $$ = minus_create($1, $3); @}
+ | expr '*' expr @{ $$ = multiply_create($1, $3); @}
+ | expr '/' expr @{ $$ = divide_create($1, $3); @}
+ | expr '^' expr @{ $$ = power_create($1, $3); @}
+ | '-' expr @{ $$ = negate_create($2); @}
+ ;
+ @end example
+
+ @c -----------------------------------------------------------------------
+
+ @node EBNF Syntax, Index, Full Expression Example, Top
+ @appendix EBNF syntax for treecc input files
+ @cindex EBNF syntax
+
+ The EBNF syntax for treecc input files uses the following
+ lexical tokens:
+
+ @example
+ IDENTIFIER ::= <A-Za-z_> @{ <A-Za-z0-9_> @}
+
+ STRING ::= '"' <anything that does not include '"'> '"'
+ | "'" <anything that does not include "'"> "'"
+
+ LITERAL_DEFNS ::= "%@{" <anything except "%@}"> "%@}"
+
+ LITERAL_END ::= "%%" <any character sequence until EOF>
+
+ LITERAL_CODE ::= '@{' <anything with matched '@{' and '@}'> '@}'
+ @end example
+
+ In addition, anything that begins with "%" in the following syntax
+ is a lexical keyword.
+
+ The EBNF syntax is as follows:
+
+ @example
+ File ::= @{ Declaration @}
+
+ Declaration ::= Node
+ | Operation
+ | OperationCase
+ | Option
+ | Enum
+ | Literal
+ | Header
+ | Output
+ | Common
+ | Include
+
+ Node ::= %node IDENTIFIER [ IDENTIFIER ] @{ NodeFlag @} [ '=' Fields ]
+
+ NodeFlag ::= %abstract | %typedef
+
+ Fields ::= '@{' @{ Field @} '@}'
+
+ Field ::= [ %nocreate ] TypeAndName [ '=' LITERAL_CODE ] ';'
+
+ TypeAndName ::= Type [ IDENTIFIER ]
+
+ Type ::= TypeName
+ | Type '*'
+ | Type '&'
+ | Type '[' ']'
+
+ TypeName ::= IDENTIFIER @{ IDENTIFIER @}
+
+ Operation ::= %operation @{ OperFlag @} Type
+ [ ClassName ] IDENTIFIER '(' [ Params ] ')'
+ [ '=' LITERAL_CODE ] [ ';' ]
+
+ OperFlag ::= %virtual | %inline | %split
+
+ ClassName ::= IDENTIFIER "::"
+
+ Params ::= Param @{ ',' Param @}
+
+ Param ::= TypeAndName | '[' TypeAndName ']'
+
+ OperationCase ::= OperationHead @{ ',' OperationHead @} LITERAL_CODE
+
+ OperationHead ::= IDENTIFIER '(' [ TypeList ] ')'
+
+ TypeList ::= IDENTIFIER @{ ',' IDENTIFIER @}
+
+ Option ::= %option IDENTIFIER [ '=' Value ]
+
+ Value ::= IDENTIFIER | STRING
+
+ Enum ::= %enum IDENTIFIER '=' '@{' EnumBody [ ',' ] '@}'
+
+ EnumBody ::= IDENTIFIER @{ ',' IDENTIFIER @}
+
+ Literal ::= @{ LiteralFlag @} (LITERAL_DEFNS | LITERAL_END)
+
+ LiteralFlag ::= %both | %decls | %end
+
+ Header ::= %header STRING
+
+ Output ::= %output STRING
+
+ Common ::= %common
+
+ Include ::= %include [ %readonly ] STRING
+
+ @end example
+
+ @c -----------------------------------------------------------------------
+
+ @page
+
+ @node Index, , EBNF Syntax, Top
+ @unnumbered Index
+
+ @printindex cp
+
+ @contents
+ @bye
More information about the llvm-commits
mailing list